diff options
| -rw-r--r-- | include/linux/if_packet.h | 1 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 61 |
2 files changed, 61 insertions, 1 deletions
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index aa57a5f993fc..6ac23ef1801a 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h | |||
| @@ -47,6 +47,7 @@ struct sockaddr_ll { | |||
| 47 | #define PACKET_TX_RING 13 | 47 | #define PACKET_TX_RING 13 |
| 48 | #define PACKET_LOSS 14 | 48 | #define PACKET_LOSS 14 |
| 49 | #define PACKET_VNET_HDR 15 | 49 | #define PACKET_VNET_HDR 15 |
| 50 | #define PACKET_TX_TIMESTAMP 16 | ||
| 50 | 51 | ||
| 51 | struct tpacket_stats { | 52 | struct tpacket_stats { |
| 52 | unsigned int tp_packets; | 53 | unsigned int tp_packets; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index d7d0310dca9d..f162d59d8161 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -82,6 +82,7 @@ | |||
| 82 | #include <linux/mutex.h> | 82 | #include <linux/mutex.h> |
| 83 | #include <linux/if_vlan.h> | 83 | #include <linux/if_vlan.h> |
| 84 | #include <linux/virtio_net.h> | 84 | #include <linux/virtio_net.h> |
| 85 | #include <linux/errqueue.h> | ||
| 85 | 86 | ||
| 86 | #ifdef CONFIG_INET | 87 | #ifdef CONFIG_INET |
| 87 | #include <net/inet_common.h> | 88 | #include <net/inet_common.h> |
| @@ -315,6 +316,8 @@ static inline struct packet_sock *pkt_sk(struct sock *sk) | |||
| 315 | 316 | ||
| 316 | static void packet_sock_destruct(struct sock *sk) | 317 | static void packet_sock_destruct(struct sock *sk) |
| 317 | { | 318 | { |
| 319 | skb_queue_purge(&sk->sk_error_queue); | ||
| 320 | |||
| 318 | WARN_ON(atomic_read(&sk->sk_rmem_alloc)); | 321 | WARN_ON(atomic_read(&sk->sk_rmem_alloc)); |
| 319 | WARN_ON(atomic_read(&sk->sk_wmem_alloc)); | 322 | WARN_ON(atomic_read(&sk->sk_wmem_alloc)); |
| 320 | 323 | ||
| @@ -483,6 +486,9 @@ retry: | |||
| 483 | skb->dev = dev; | 486 | skb->dev = dev; |
| 484 | skb->priority = sk->sk_priority; | 487 | skb->priority = sk->sk_priority; |
| 485 | skb->mark = sk->sk_mark; | 488 | skb->mark = sk->sk_mark; |
| 489 | err = sock_tx_timestamp(msg, sk, skb_tx(skb)); | ||
| 490 | if (err < 0) | ||
| 491 | goto out_unlock; | ||
| 486 | 492 | ||
| 487 | dev_queue_xmit(skb); | 493 | dev_queue_xmit(skb); |
| 488 | rcu_read_unlock(); | 494 | rcu_read_unlock(); |
| @@ -1188,6 +1194,9 @@ static int packet_snd(struct socket *sock, | |||
| 1188 | err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); | 1194 | err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); |
| 1189 | if (err) | 1195 | if (err) |
| 1190 | goto out_free; | 1196 | goto out_free; |
| 1197 | err = sock_tx_timestamp(msg, sk, skb_tx(skb)); | ||
| 1198 | if (err < 0) | ||
| 1199 | goto out_free; | ||
| 1191 | 1200 | ||
| 1192 | skb->protocol = proto; | 1201 | skb->protocol = proto; |
| 1193 | skb->dev = dev; | 1202 | skb->dev = dev; |
| @@ -1487,6 +1496,51 @@ out: | |||
| 1487 | return err; | 1496 | return err; |
| 1488 | } | 1497 | } |
| 1489 | 1498 | ||
| 1499 | static int packet_recv_error(struct sock *sk, struct msghdr *msg, int len) | ||
| 1500 | { | ||
| 1501 | struct sock_exterr_skb *serr; | ||
| 1502 | struct sk_buff *skb, *skb2; | ||
| 1503 | int copied, err; | ||
| 1504 | |||
| 1505 | err = -EAGAIN; | ||
| 1506 | skb = skb_dequeue(&sk->sk_error_queue); | ||
| 1507 | if (skb == NULL) | ||
| 1508 | goto out; | ||
| 1509 | |||
| 1510 | copied = skb->len; | ||
| 1511 | if (copied > len) { | ||
| 1512 | msg->msg_flags |= MSG_TRUNC; | ||
| 1513 | copied = len; | ||
| 1514 | } | ||
| 1515 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
| 1516 | if (err) | ||
| 1517 | goto out_free_skb; | ||
| 1518 | |||
| 1519 | sock_recv_timestamp(msg, sk, skb); | ||
| 1520 | |||
| 1521 | serr = SKB_EXT_ERR(skb); | ||
| 1522 | put_cmsg(msg, SOL_PACKET, PACKET_TX_TIMESTAMP, | ||
| 1523 | sizeof(serr->ee), &serr->ee); | ||
| 1524 | |||
| 1525 | msg->msg_flags |= MSG_ERRQUEUE; | ||
| 1526 | err = copied; | ||
| 1527 | |||
| 1528 | /* Reset and regenerate socket error */ | ||
| 1529 | spin_lock_bh(&sk->sk_error_queue.lock); | ||
| 1530 | sk->sk_err = 0; | ||
| 1531 | if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) { | ||
| 1532 | sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno; | ||
| 1533 | spin_unlock_bh(&sk->sk_error_queue.lock); | ||
| 1534 | sk->sk_error_report(sk); | ||
| 1535 | } else | ||
| 1536 | spin_unlock_bh(&sk->sk_error_queue.lock); | ||
| 1537 | |||
| 1538 | out_free_skb: | ||
| 1539 | kfree_skb(skb); | ||
| 1540 | out: | ||
| 1541 | return err; | ||
| 1542 | } | ||
| 1543 | |||
| 1490 | /* | 1544 | /* |
| 1491 | * Pull a packet from our receive queue and hand it to the user. | 1545 | * Pull a packet from our receive queue and hand it to the user. |
| 1492 | * If necessary we block. | 1546 | * If necessary we block. |
| @@ -1502,7 +1556,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1502 | int vnet_hdr_len = 0; | 1556 | int vnet_hdr_len = 0; |
| 1503 | 1557 | ||
| 1504 | err = -EINVAL; | 1558 | err = -EINVAL; |
| 1505 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) | 1559 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT|MSG_ERRQUEUE)) |
| 1506 | goto out; | 1560 | goto out; |
| 1507 | 1561 | ||
| 1508 | #if 0 | 1562 | #if 0 |
| @@ -1511,6 +1565,11 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1511 | return -ENODEV; | 1565 | return -ENODEV; |
| 1512 | #endif | 1566 | #endif |
| 1513 | 1567 | ||
| 1568 | if (flags & MSG_ERRQUEUE) { | ||
| 1569 | err = packet_recv_error(sk, msg, len); | ||
| 1570 | goto out; | ||
| 1571 | } | ||
| 1572 | |||
| 1514 | /* | 1573 | /* |
| 1515 | * Call the generic datagram receiver. This handles all sorts | 1574 | * Call the generic datagram receiver. This handles all sorts |
| 1516 | * of horrible races and re-entrancy so we can forget about it | 1575 | * of horrible races and re-entrancy so we can forget about it |
