Skip to content

Commit

Permalink
Merge branch 'netns-defrag'
Browse files Browse the repository at this point in the history
Eric W. Biederman says:

====================
net: Pass net into defragmentation

This is the next installment of my work to pass struct net through the
output path so the code does not need to guess how to figure out which
network namespace it is in, and ultimately routes can have output
devices in another network namespace.

In netfilter and af_packet we defragment packets in the output path,
and there is the usual amount of confusion about how to compute which
net we are processing the packets in.  This patchset clears that
confusion up by explicitly passing in struct net in ip_defrag,
ip_check_defrag, and nf_ct_frag6_gather.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 13, 2015
2 parents 161642e + b727759 commit b7a4609
Show file tree
Hide file tree
Showing 11 changed files with 27 additions and 26 deletions.
2 changes: 1 addition & 1 deletion drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)

port = macvlan_port_get_rcu(skb->dev);
if (is_multicast_ether_addr(eth->h_dest)) {
skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
skb = ip_check_defrag(dev_net(skb->dev), skb, IP_DEFRAG_MACVLAN);
if (!skb)
return RX_HANDLER_CONSUMED;
eth = eth_hdr(skb);
Expand Down
6 changes: 3 additions & 3 deletions include/net/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,11 +506,11 @@ static inline bool ip_defrag_user_in_between(u32 user,
return user >= lower_bond && user <= upper_bond;
}

int ip_defrag(struct sk_buff *skb, u32 user);
int ip_defrag(struct net *net, struct sk_buff *skb, u32 user);
#ifdef CONFIG_INET
struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user);
struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user);
#else
static inline struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
{
return skb;
}
Expand Down
2 changes: 1 addition & 1 deletion include/net/netfilter/ipv6/nf_defrag_ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ void nf_defrag_ipv6_enable(void);

int nf_ct_frag6_init(void);
void nf_ct_frag6_cleanup(void);
struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user);
void nf_ct_frag6_consume_orig(struct sk_buff *skb);

struct inet_frags_ctl;
Expand Down
7 changes: 3 additions & 4 deletions net/ipv4/ip_fragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,11 +654,10 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
}

/* Process an incoming IP datagram fragment. */
int ip_defrag(struct sk_buff *skb, u32 user)
int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
{
struct net_device *dev = skb->dev ? : skb_dst(skb)->dev;
int vif = l3mdev_master_ifindex_rcu(dev);
struct net *net = dev_net(dev);
struct ipq *qp;

IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
Expand All @@ -683,7 +682,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
}
EXPORT_SYMBOL(ip_defrag);

struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
{
struct iphdr iph;
int netoff;
Expand Down Expand Up @@ -712,7 +711,7 @@ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
if (pskb_trim_rcsum(skb, netoff + len))
return skb;
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
if (ip_defrag(skb, user))
if (ip_defrag(net, skb, user))
return NULL;
skb_clear_hash(skb);
}
Expand Down
10 changes: 6 additions & 4 deletions net/ipv4/ip_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ bool ip_call_ra_chain(struct sk_buff *skb)
u8 protocol = ip_hdr(skb)->protocol;
struct sock *last = NULL;
struct net_device *dev = skb->dev;
struct net *net = dev_net(dev);

for (ra = rcu_dereference(ip_ra_chain); ra; ra = rcu_dereference(ra->next)) {
struct sock *sk = ra->sk;
Expand All @@ -167,9 +168,9 @@ bool ip_call_ra_chain(struct sk_buff *skb)
if (sk && inet_sk(sk)->inet_num == protocol &&
(!sk->sk_bound_dev_if ||
sk->sk_bound_dev_if == dev->ifindex) &&
net_eq(sock_net(sk), dev_net(dev))) {
net_eq(sock_net(sk), net)) {
if (ip_is_fragment(ip_hdr(skb))) {
if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN))
if (ip_defrag(net, skb, IP_DEFRAG_CALL_RA_CHAIN))
return true;
}
if (last) {
Expand Down Expand Up @@ -246,14 +247,15 @@ int ip_local_deliver(struct sk_buff *skb)
/*
* Reassemble IP fragments.
*/
struct net *net = dev_net(skb->dev);

if (ip_is_fragment(ip_hdr(skb))) {
if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER))
return 0;
}

return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,
dev_net(skb->dev), NULL, skb, skb->dev, NULL,
net, NULL, skb, skb->dev, NULL,
ip_local_deliver_finish);
}

Expand Down
7 changes: 4 additions & 3 deletions net/ipv4/netfilter/nf_defrag_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@
#endif
#include <net/netfilter/nf_conntrack_zones.h>

static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,
u_int32_t user)
{
int err;

skb_orphan(skb);

local_bh_disable();
err = ip_defrag(skb, user);
err = ip_defrag(net, skb, user);
local_bh_enable();

if (!err) {
Expand Down Expand Up @@ -85,7 +86,7 @@ static unsigned int ipv4_conntrack_defrag(void *priv,
enum ip_defrag_users user =
nf_ct_defrag_user(state->hook, skb);

if (nf_ct_ipv4_gather_frags(skb, user))
if (nf_ct_ipv4_gather_frags(state->net, skb, user))
return NF_STOLEN;
}
return NF_ACCEPT;
Expand Down
4 changes: 1 addition & 3 deletions net/ipv6/netfilter/nf_conntrack_reasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,12 +563,10 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
return 0;
}

struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
{
struct sk_buff *clone;
struct net_device *dev = skb->dev;
struct net *net = skb_dst(skb) ? dev_net(skb_dst(skb)->dev)
: dev_net(skb->dev);
struct frag_hdr *fhdr;
struct frag_queue *fq;
struct ipv6hdr *hdr;
Expand Down
3 changes: 2 additions & 1 deletion net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ static unsigned int ipv6_defrag(void *priv,
return NF_ACCEPT;
#endif

reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(state->hook, skb));
reasm = nf_ct_frag6_gather(state->net, skb,
nf_ct6_defrag_user(state->hook, skb));
/* queued */
if (reasm == NULL)
return NF_STOLEN;
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/ipvs/ip_vs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ static inline int ip_vs_gather_frags(struct netns_ipvs *ipvs,
int err;

local_bh_disable();
err = ip_defrag(skb, user);
err = ip_defrag(ipvs->net, skb, user);
local_bh_enable();
if (!err)
ip_send_check(ip_hdr(skb));
Expand Down
4 changes: 2 additions & 2 deletions net/openvswitch/conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
int err;

memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
err = ip_defrag(skb, user);
err = ip_defrag(net, skb, user);
if (err)
return err;

Expand All @@ -315,7 +315,7 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
struct sk_buff *reasm;

memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
reasm = nf_ct_frag6_gather(skb, user);
reasm = nf_ct_frag6_gather(net, skb, user);
if (!reasm)
return -EINPROGRESS;

Expand Down
6 changes: 3 additions & 3 deletions net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1439,17 +1439,17 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
{
struct packet_fanout *f = pt->af_packet_priv;
unsigned int num = READ_ONCE(f->num_members);
struct net *net = read_pnet(&f->net);
struct packet_sock *po;
unsigned int idx;

if (!net_eq(dev_net(dev), read_pnet(&f->net)) ||
!num) {
if (!net_eq(dev_net(dev), net) || !num) {
kfree_skb(skb);
return 0;
}

if (fanout_has_flag(f, PACKET_FANOUT_FLAG_DEFRAG)) {
skb = ip_check_defrag(skb, IP_DEFRAG_AF_PACKET);
skb = ip_check_defrag(net, skb, IP_DEFRAG_AF_PACKET);
if (!skb)
return 0;
}
Expand Down

0 comments on commit b7a4609

Please sign in to comment.