aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--net/core/dev.c16
-rw-r--r--net/packet/af_packet.c9
3 files changed, 25 insertions, 2 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3560d688161e..59dc05f38247 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1522,6 +1522,8 @@ struct packet_type {
1522 struct sk_buff **(*gro_receive)(struct sk_buff **head, 1522 struct sk_buff **(*gro_receive)(struct sk_buff **head,
1523 struct sk_buff *skb); 1523 struct sk_buff *skb);
1524 int (*gro_complete)(struct sk_buff *skb); 1524 int (*gro_complete)(struct sk_buff *skb);
1525 bool (*id_match)(struct packet_type *ptype,
1526 struct sock *sk);
1525 void *af_packet_priv; 1527 void *af_packet_priv;
1526 struct list_head list; 1528 struct list_head list;
1527}; 1529};
diff --git a/net/core/dev.c b/net/core/dev.c
index a39354ee1432..debd9372472f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1642,6 +1642,19 @@ static inline int deliver_skb(struct sk_buff *skb,
1642 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 1642 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
1643} 1643}
1644 1644
1645static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
1646{
1647 if (ptype->af_packet_priv == NULL)
1648 return false;
1649
1650 if (ptype->id_match)
1651 return ptype->id_match(ptype, skb->sk);
1652 else if ((struct sock *)ptype->af_packet_priv == skb->sk)
1653 return true;
1654
1655 return false;
1656}
1657
1645/* 1658/*
1646 * Support routine. Sends outgoing frames to any network 1659 * Support routine. Sends outgoing frames to any network
1647 * taps currently in use. 1660 * taps currently in use.
@@ -1659,8 +1672,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
1659 * they originated from - MvS (miquels@drinkel.ow.org) 1672 * they originated from - MvS (miquels@drinkel.ow.org)
1660 */ 1673 */
1661 if ((ptype->dev == dev || !ptype->dev) && 1674 if ((ptype->dev == dev || !ptype->dev) &&
1662 (ptype->af_packet_priv == NULL || 1675 (!skb_loop_sk(ptype, skb))) {
1663 (struct sock *)ptype->af_packet_priv != skb->sk)) {
1664 if (pt_prev) { 1676 if (pt_prev) {
1665 deliver_skb(skb2, pt_prev, skb->dev); 1677 deliver_skb(skb2, pt_prev, skb->dev);
1666 pt_prev = ptype; 1678 pt_prev = ptype;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8ac890a1a4c0..aee7196aac36 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1273,6 +1273,14 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
1273 spin_unlock(&f->lock); 1273 spin_unlock(&f->lock);
1274} 1274}
1275 1275
1276bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
1277{
1278 if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout)
1279 return true;
1280
1281 return false;
1282}
1283
1276static int fanout_add(struct sock *sk, u16 id, u16 type_flags) 1284static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1277{ 1285{
1278 struct packet_sock *po = pkt_sk(sk); 1286 struct packet_sock *po = pkt_sk(sk);
@@ -1325,6 +1333,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1325 match->prot_hook.dev = po->prot_hook.dev; 1333 match->prot_hook.dev = po->prot_hook.dev;
1326 match->prot_hook.func = packet_rcv_fanout; 1334 match->prot_hook.func = packet_rcv_fanout;
1327 match->prot_hook.af_packet_priv = match; 1335 match->prot_hook.af_packet_priv = match;
1336 match->prot_hook.id_match = match_fanout_group;
1328 dev_add_pack(&match->prot_hook); 1337 dev_add_pack(&match->prot_hook);
1329 list_add(&match->list, &fanout_list); 1338 list_add(&match->list, &fanout_list);
1330 } 1339 }