Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      broadcast connection tracking helper
0004  *
0005  *      (c) 2005 Patrick McHardy <kaber@trash.net>
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/ip.h>
0010 #include <net/route.h>
0011 #include <linux/inetdevice.h>
0012 #include <linux/skbuff.h>
0013 
0014 #include <net/netfilter/nf_conntrack.h>
0015 #include <net/netfilter/nf_conntrack_helper.h>
0016 #include <net/netfilter/nf_conntrack_expect.h>
0017 
0018 int nf_conntrack_broadcast_help(struct sk_buff *skb,
0019                 struct nf_conn *ct,
0020                 enum ip_conntrack_info ctinfo,
0021                 unsigned int timeout)
0022 {
0023     const struct nf_conntrack_helper *helper;
0024     struct nf_conntrack_expect *exp;
0025     struct iphdr *iph = ip_hdr(skb);
0026     struct rtable *rt = skb_rtable(skb);
0027     struct in_device *in_dev;
0028     struct nf_conn_help *help = nfct_help(ct);
0029     __be32 mask = 0;
0030 
0031     /* we're only interested in locally generated packets */
0032     if (skb->sk == NULL || !net_eq(nf_ct_net(ct), sock_net(skb->sk)))
0033         goto out;
0034     if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
0035         goto out;
0036     if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
0037         goto out;
0038 
0039     in_dev = __in_dev_get_rcu(rt->dst.dev);
0040     if (in_dev != NULL) {
0041         const struct in_ifaddr *ifa;
0042 
0043         in_dev_for_each_ifa_rcu(ifa, in_dev) {
0044             if (ifa->ifa_flags & IFA_F_SECONDARY)
0045                 continue;
0046 
0047             if (ifa->ifa_broadcast == iph->daddr) {
0048                 mask = ifa->ifa_mask;
0049                 break;
0050             }
0051         }
0052     }
0053 
0054     if (mask == 0)
0055         goto out;
0056 
0057     exp = nf_ct_expect_alloc(ct);
0058     if (exp == NULL)
0059         goto out;
0060 
0061     exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
0062 
0063     helper = rcu_dereference(help->helper);
0064     if (helper)
0065         exp->tuple.src.u.udp.port = helper->tuple.src.u.udp.port;
0066 
0067     exp->mask.src.u3.ip       = mask;
0068     exp->mask.src.u.udp.port  = htons(0xFFFF);
0069 
0070     exp->expectfn             = NULL;
0071     exp->flags                = NF_CT_EXPECT_PERMANENT;
0072     exp->class        = NF_CT_EXPECT_CLASS_DEFAULT;
0073     exp->helper               = NULL;
0074 
0075     nf_ct_expect_related(exp, 0);
0076     nf_ct_expect_put(exp);
0077 
0078     nf_ct_refresh(ct, skb, timeout * HZ);
0079 out:
0080     return NF_ACCEPT;
0081 }
0082 EXPORT_SYMBOL_GPL(nf_conntrack_broadcast_help);
0083 
0084 MODULE_LICENSE("GPL");