mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
![Flavio Leitner](/assets/img/avatar_default.png)
Netfilter assumes that if the socket is present in the skb, then it can be used because that reference is cleaned up while the skb is crossing netns. We want to change that to preserve the socket reference in a future patch, so this is a preparation updating netfilter to check if the socket netns matches before use it. Signed-off-by: Flavio Leitner <fbl@redhat.com> Acked-by: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
79 lines
2.1 KiB
C
79 lines
2.1 KiB
C
/*
|
|
* broadcast connection tracking helper
|
|
*
|
|
* (c) 2005 Patrick McHardy <kaber@trash.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/ip.h>
|
|
#include <net/route.h>
|
|
#include <linux/inetdevice.h>
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <net/netfilter/nf_conntrack.h>
|
|
#include <net/netfilter/nf_conntrack_helper.h>
|
|
#include <net/netfilter/nf_conntrack_expect.h>
|
|
|
|
int nf_conntrack_broadcast_help(struct sk_buff *skb,
|
|
struct nf_conn *ct,
|
|
enum ip_conntrack_info ctinfo,
|
|
unsigned int timeout)
|
|
{
|
|
struct nf_conntrack_expect *exp;
|
|
struct iphdr *iph = ip_hdr(skb);
|
|
struct rtable *rt = skb_rtable(skb);
|
|
struct in_device *in_dev;
|
|
struct nf_conn_help *help = nfct_help(ct);
|
|
__be32 mask = 0;
|
|
|
|
/* we're only interested in locally generated packets */
|
|
if (skb->sk == NULL || !net_eq(nf_ct_net(ct), sock_net(skb->sk)))
|
|
goto out;
|
|
if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
|
|
goto out;
|
|
if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
|
|
goto out;
|
|
|
|
in_dev = __in_dev_get_rcu(rt->dst.dev);
|
|
if (in_dev != NULL) {
|
|
for_primary_ifa(in_dev) {
|
|
if (ifa->ifa_broadcast == iph->daddr) {
|
|
mask = ifa->ifa_mask;
|
|
break;
|
|
}
|
|
} endfor_ifa(in_dev);
|
|
}
|
|
|
|
if (mask == 0)
|
|
goto out;
|
|
|
|
exp = nf_ct_expect_alloc(ct);
|
|
if (exp == NULL)
|
|
goto out;
|
|
|
|
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
|
|
exp->tuple.src.u.udp.port = help->helper->tuple.src.u.udp.port;
|
|
|
|
exp->mask.src.u3.ip = mask;
|
|
exp->mask.src.u.udp.port = htons(0xFFFF);
|
|
|
|
exp->expectfn = NULL;
|
|
exp->flags = NF_CT_EXPECT_PERMANENT;
|
|
exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
|
|
exp->helper = NULL;
|
|
|
|
nf_ct_expect_related(exp);
|
|
nf_ct_expect_put(exp);
|
|
|
|
nf_ct_refresh(ct, skb, timeout * HZ);
|
|
out:
|
|
return NF_ACCEPT;
|
|
}
|
|
EXPORT_SYMBOL_GPL(nf_conntrack_broadcast_help);
|
|
|
|
MODULE_LICENSE("GPL");
|