linux/net/netfilter/nf_conntrack_broadcast.c
<<
>>
Prefs
   1/*
   2 *      broadcast connection tracking helper
   3 *
   4 *      (c) 2005 Patrick McHardy <kaber@trash.net>
   5 *
   6 *      This program is free software; you can redistribute it and/or
   7 *      modify it under the terms of the GNU General Public License
   8 *      as published by the Free Software Foundation; either version
   9 *      2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/ip.h>
  14#include <net/route.h>
  15#include <linux/inetdevice.h>
  16#include <linux/skbuff.h>
  17
  18#include <net/netfilter/nf_conntrack.h>
  19#include <net/netfilter/nf_conntrack_helper.h>
  20#include <net/netfilter/nf_conntrack_expect.h>
  21
  22int nf_conntrack_broadcast_help(struct sk_buff *skb,
  23                                unsigned int protoff,
  24                                struct nf_conn *ct,
  25                                enum ip_conntrack_info ctinfo,
  26                                unsigned int timeout)
  27{
  28        struct nf_conntrack_expect *exp;
  29        struct iphdr *iph = ip_hdr(skb);
  30        struct rtable *rt = skb_rtable(skb);
  31        struct in_device *in_dev;
  32        struct nf_conn_help *help = nfct_help(ct);
  33        __be32 mask = 0;
  34
  35        /* we're only interested in locally generated packets */
  36        if (skb->sk == NULL)
  37                goto out;
  38        if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
  39                goto out;
  40        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
  41                goto out;
  42
  43        rcu_read_lock();
  44        in_dev = __in_dev_get_rcu(rt->dst.dev);
  45        if (in_dev != NULL) {
  46                for_primary_ifa(in_dev) {
  47                        if (ifa->ifa_broadcast == iph->daddr) {
  48                                mask = ifa->ifa_mask;
  49                                break;
  50                        }
  51                } endfor_ifa(in_dev);
  52        }
  53        rcu_read_unlock();
  54
  55        if (mask == 0)
  56                goto out;
  57
  58        exp = nf_ct_expect_alloc(ct);
  59        if (exp == NULL)
  60                goto out;
  61
  62        exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
  63        exp->tuple.src.u.udp.port = help->helper->tuple.src.u.udp.port;
  64
  65        exp->mask.src.u3.ip       = mask;
  66        exp->mask.src.u.udp.port  = htons(0xFFFF);
  67
  68        exp->expectfn             = NULL;
  69        exp->flags                = NF_CT_EXPECT_PERMANENT;
  70        exp->class                = NF_CT_EXPECT_CLASS_DEFAULT;
  71        exp->helper               = NULL;
  72
  73        nf_ct_expect_related(exp);
  74        nf_ct_expect_put(exp);
  75
  76        nf_ct_refresh(ct, skb, timeout * HZ);
  77out:
  78        return NF_ACCEPT;
  79}
  80EXPORT_SYMBOL_GPL(nf_conntrack_broadcast_help);
  81
  82MODULE_LICENSE("GPL");
  83