/* * Copyright (C) 2016 Google Inc. * Author: Kevin Cernekee * * 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 #include 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); }