@@ -216,10 +216,16 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *,
216
216
static void packet_flush_mclist (struct sock * sk );
217
217
218
218
struct packet_skb_cb {
219
- unsigned int origlen ;
220
219
union {
221
220
struct sockaddr_pkt pkt ;
222
- struct sockaddr_ll ll ;
221
+ union {
222
+ /* Trick: alias skb original length with
223
+ * ll.sll_family and ll.protocol in order
224
+ * to save room.
225
+ */
226
+ unsigned int origlen ;
227
+ struct sockaddr_ll ll ;
228
+ };
223
229
} sa ;
224
230
};
225
231
@@ -1814,9 +1820,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
1814
1820
sizeof (skb -> cb ));
1815
1821
1816
1822
sll = & PACKET_SKB_CB (skb )-> sa .ll ;
1817
- sll -> sll_family = AF_PACKET ;
1818
1823
sll -> sll_hatype = dev -> type ;
1819
- sll -> sll_protocol = skb -> protocol ;
1820
1824
sll -> sll_pkttype = skb -> pkt_type ;
1821
1825
if (unlikely (po -> origdev ))
1822
1826
sll -> sll_ifindex = orig_dev -> ifindex ;
@@ -1825,7 +1829,10 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
1825
1829
1826
1830
sll -> sll_halen = dev_parse_header (skb , sll -> sll_addr );
1827
1831
1828
- PACKET_SKB_CB (skb )-> origlen = skb -> len ;
1832
+ /* sll->sll_family and sll->sll_protocol are set in packet_recvmsg().
1833
+ * Use their space for storing the original skb length.
1834
+ */
1835
+ PACKET_SKB_CB (skb )-> sa .origlen = skb -> len ;
1829
1836
1830
1837
if (pskb_trim (skb , snaplen ))
1831
1838
goto drop_n_acct ;
@@ -2883,6 +2890,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2883
2890
struct sk_buff * skb ;
2884
2891
int copied , err ;
2885
2892
int vnet_hdr_len = 0 ;
2893
+ unsigned int origlen = 0 ;
2886
2894
2887
2895
err = - EINVAL ;
2888
2896
if (flags & ~(MSG_PEEK |MSG_DONTWAIT |MSG_TRUNC |MSG_CMSG_COMPAT |MSG_ERRQUEUE ))
@@ -2982,6 +2990,15 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2982
2990
if (err )
2983
2991
goto out_free ;
2984
2992
2993
+ if (sock -> type != SOCK_PACKET ) {
2994
+ struct sockaddr_ll * sll = & PACKET_SKB_CB (skb )-> sa .ll ;
2995
+
2996
+ /* Original length was stored in sockaddr_ll fields */
2997
+ origlen = PACKET_SKB_CB (skb )-> sa .origlen ;
2998
+ sll -> sll_family = AF_PACKET ;
2999
+ sll -> sll_protocol = skb -> protocol ;
3000
+ }
3001
+
2985
3002
sock_recv_ts_and_drops (msg , sk , skb );
2986
3003
2987
3004
if (msg -> msg_name ) {
@@ -2993,6 +3010,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2993
3010
msg -> msg_namelen = sizeof (struct sockaddr_pkt );
2994
3011
} else {
2995
3012
struct sockaddr_ll * sll = & PACKET_SKB_CB (skb )-> sa .ll ;
3013
+
2996
3014
msg -> msg_namelen = sll -> sll_halen +
2997
3015
offsetof(struct sockaddr_ll , sll_addr );
2998
3016
}
@@ -3006,7 +3024,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
3006
3024
aux .tp_status = TP_STATUS_USER ;
3007
3025
if (skb -> ip_summed == CHECKSUM_PARTIAL )
3008
3026
aux .tp_status |= TP_STATUS_CSUMNOTREADY ;
3009
- aux .tp_len = PACKET_SKB_CB ( skb ) -> origlen ;
3027
+ aux .tp_len = origlen ;
3010
3028
aux .tp_snaplen = skb -> len ;
3011
3029
aux .tp_mac = 0 ;
3012
3030
aux .tp_net = skb_network_offset (skb );
0 commit comments