diff options
author | Peter P. Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> | 2007-04-20 19:05:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:29:14 -0400 |
commit | 80feaacb8a6400a9540a961b6743c69a5896b937 (patch) | |
tree | a4f07e635de521f5e283e0f4081923a98c0256d5 | |
parent | 1370b5a59b941ac3873b5e8614d496e9f481d670 (diff) |
[AF_PACKET]: Add option to return orig_dev to userspace.
Add a packet socket option to allow the orig_dev index to be returned
to userspace when passing traffic through a decapsulated device, such
as the bonding driver.
This is very useful for layer 2 traffic being able to report which
physical device actually received the traffic, instead of having the
encapsulating device hide that information.
The new option is called PACKET_ORIGDEV.
Signed-off-by: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/if_packet.h | 1 | ||||
-rw-r--r-- | net/packet/af_packet.c | 32 |
2 files changed, 30 insertions, 3 deletions
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index f3de05c30678..ad09609227ff 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h | |||
@@ -42,6 +42,7 @@ struct sockaddr_ll | |||
42 | #define PACKET_STATISTICS 6 | 42 | #define PACKET_STATISTICS 6 |
43 | #define PACKET_COPY_THRESH 7 | 43 | #define PACKET_COPY_THRESH 7 |
44 | #define PACKET_AUXDATA 8 | 44 | #define PACKET_AUXDATA 8 |
45 | #define PACKET_ORIGDEV 9 | ||
45 | 46 | ||
46 | struct tpacket_stats | 47 | struct tpacket_stats |
47 | { | 48 | { |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 36388b2f32f9..02e401cd683f 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -201,7 +201,8 @@ struct packet_sock { | |||
201 | struct packet_type prot_hook; | 201 | struct packet_type prot_hook; |
202 | spinlock_t bind_lock; | 202 | spinlock_t bind_lock; |
203 | unsigned int running:1, /* prot_hook is attached*/ | 203 | unsigned int running:1, /* prot_hook is attached*/ |
204 | auxdata:1; | 204 | auxdata:1, |
205 | origdev:1; | ||
205 | int ifindex; /* bound device */ | 206 | int ifindex; /* bound device */ |
206 | __be16 num; | 207 | __be16 num; |
207 | #ifdef CONFIG_PACKET_MULTICAST | 208 | #ifdef CONFIG_PACKET_MULTICAST |
@@ -528,7 +529,10 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet | |||
528 | sll->sll_hatype = dev->type; | 529 | sll->sll_hatype = dev->type; |
529 | sll->sll_protocol = skb->protocol; | 530 | sll->sll_protocol = skb->protocol; |
530 | sll->sll_pkttype = skb->pkt_type; | 531 | sll->sll_pkttype = skb->pkt_type; |
531 | sll->sll_ifindex = dev->ifindex; | 532 | if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST) |
533 | sll->sll_ifindex = orig_dev->ifindex; | ||
534 | else | ||
535 | sll->sll_ifindex = dev->ifindex; | ||
532 | sll->sll_halen = 0; | 536 | sll->sll_halen = 0; |
533 | 537 | ||
534 | if (dev->hard_header_parse) | 538 | if (dev->hard_header_parse) |
@@ -673,7 +677,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe | |||
673 | sll->sll_hatype = dev->type; | 677 | sll->sll_hatype = dev->type; |
674 | sll->sll_protocol = skb->protocol; | 678 | sll->sll_protocol = skb->protocol; |
675 | sll->sll_pkttype = skb->pkt_type; | 679 | sll->sll_pkttype = skb->pkt_type; |
676 | sll->sll_ifindex = dev->ifindex; | 680 | if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST) |
681 | sll->sll_ifindex = orig_dev->ifindex; | ||
682 | else | ||
683 | sll->sll_ifindex = dev->ifindex; | ||
677 | 684 | ||
678 | h->tp_status = status; | 685 | h->tp_status = status; |
679 | smp_mb(); | 686 | smp_mb(); |
@@ -1413,6 +1420,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
1413 | po->auxdata = !!val; | 1420 | po->auxdata = !!val; |
1414 | return 0; | 1421 | return 0; |
1415 | } | 1422 | } |
1423 | case PACKET_ORIGDEV: | ||
1424 | { | ||
1425 | int val; | ||
1426 | |||
1427 | if (optlen < sizeof(val)) | ||
1428 | return -EINVAL; | ||
1429 | if (copy_from_user(&val, optval, sizeof(val))) | ||
1430 | return -EFAULT; | ||
1431 | |||
1432 | po->origdev = !!val; | ||
1433 | return 0; | ||
1434 | } | ||
1416 | default: | 1435 | default: |
1417 | return -ENOPROTOOPT; | 1436 | return -ENOPROTOOPT; |
1418 | } | 1437 | } |
@@ -1456,6 +1475,13 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
1456 | 1475 | ||
1457 | data = &val; | 1476 | data = &val; |
1458 | break; | 1477 | break; |
1478 | case PACKET_ORIGDEV: | ||
1479 | if (len > sizeof(int)) | ||
1480 | len = sizeof(int); | ||
1481 | val = po->origdev; | ||
1482 | |||
1483 | data = &val; | ||
1484 | break; | ||
1459 | default: | 1485 | default: |
1460 | return -ENOPROTOOPT; | 1486 | return -ENOPROTOOPT; |
1461 | } | 1487 | } |