blob: 7605589e606f059d868bc44dc74e1374a2811068 [file] [log] [blame]
/*
* Copyright (C) 2016 Google Inc.
* Author: Kevin Cernekee <cernekee@chromium.org>
*
* This helper pokes a hole in the firewall for unicast mDNS replies
* (RFC6762 section 5.1). It is needed because the destination address of
* the outgoing mDNS query (224.0.0.251) will not match the source address
* of the incoming response (192.168.x.x or similar). The helper is not used
* for standard multicast queries/responses in which the sport and dport are
* both 5353, because those can be handled by a standard filter/INPUT rule.
*
* Usage:
*
* nfct add helper mdns inet udp
* iptables -t raw -A OUTPUT -p udp -d 224.0.0.251 '!' --sport 5353 \
* --dport 5353 -j CT --helper mdns
* iptables -t filter -A INPUT -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT
* iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED \
* -j ACCEPT
*
* Requires Linux 3.12 or higher. NAT is unsupported.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "conntrackd.h"
#include "helper.h"
#include "myct.h"
#include "log.h"
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <linux/netfilter.h>
static int mdns_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
struct myct *myct, uint32_t ctinfo)
{
struct nf_expect *exp;
int dir = CTINFO2DIR(ctinfo);
union nfct_attr_grp_addr saddr;
uint16_t sport, dport;
exp = nfexp_new();
if (exp == NULL) {
pr_debug("conntrack_mdns: failed to allocate expectation\n");
return NF_ACCEPT;
}
cthelper_get_addr_src(myct->ct, dir, &saddr);
cthelper_get_port_src(myct->ct, dir, &sport);
cthelper_get_port_src(myct->ct, !dir, &dport);
if (cthelper_expect_init(exp,
myct->ct,
0 /* class */,
NULL /* saddr */,
&saddr /* daddr */,
IPPROTO_UDP,
&dport /* sport */,
&sport /* dport */,
NF_CT_EXPECT_PERMANENT)) {
pr_debug("conntrack_mdns: failed to init expectation\n");
nfexp_destroy(exp);
return NF_ACCEPT;
}
myct->exp = exp;
return NF_ACCEPT;
}
static struct ctd_helper mdns_helper = {
.name = "mdns",
.l4proto = IPPROTO_UDP,
.priv_data_len = 0,
.cb = mdns_helper_cb,
.policy = {
[0] = {
.name = "mdns",
.expect_max = 8,
.expect_timeout = 30,
},
},
};
static void __attribute__ ((constructor)) mdns_init(void)
{
helper_register(&mdns_helper);
}