diff options
| -rw-r--r-- | include/linux/netdevice.h | 2 | ||||
| -rw-r--r-- | net/core/dev.c | 16 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 9 |
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 | ||
| 1645 | static 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 | ||
| 1276 | bool 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 | |||
| 1276 | static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | 1284 | static 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 | } |
