aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_packet.h1
-rw-r--r--net/packet/af_packet.c32
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
46struct tpacket_stats 47struct 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 }