static void packet_flush_mclist(struct sock *sk);
 
 struct packet_skb_cb {
-       unsigned int origlen;
        union {
                struct sockaddr_pkt pkt;
-               struct sockaddr_ll ll;
+               union {
+                       /* Trick: alias skb original length with
+                        * ll.sll_family and ll.protocol in order
+                        * to save room.
+                        */
+                       unsigned int origlen;
+                       struct sockaddr_ll ll;
+               };
        } sa;
 };
 
                     sizeof(skb->cb));
 
        sll = &PACKET_SKB_CB(skb)->sa.ll;
-       sll->sll_family = AF_PACKET;
        sll->sll_hatype = dev->type;
-       sll->sll_protocol = skb->protocol;
        sll->sll_pkttype = skb->pkt_type;
        if (unlikely(po->origdev))
                sll->sll_ifindex = orig_dev->ifindex;
 
        sll->sll_halen = dev_parse_header(skb, sll->sll_addr);
 
-       PACKET_SKB_CB(skb)->origlen = skb->len;
+       /* sll->sll_family and sll->sll_protocol are set in packet_recvmsg().
+        * Use their space for storing the original skb length.
+        */
+       PACKET_SKB_CB(skb)->sa.origlen = skb->len;
 
        if (pskb_trim(skb, snaplen))
                goto drop_n_acct;
        struct sk_buff *skb;
        int copied, err;
        int vnet_hdr_len = 0;
+       unsigned int origlen = 0;
 
        err = -EINVAL;
        if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT|MSG_ERRQUEUE))
        if (err)
                goto out_free;
 
+       if (sock->type != SOCK_PACKET) {
+               struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
+
+               /* Original length was stored in sockaddr_ll fields */
+               origlen = PACKET_SKB_CB(skb)->sa.origlen;
+               sll->sll_family = AF_PACKET;
+               sll->sll_protocol = skb->protocol;
+       }
+
        sock_recv_ts_and_drops(msg, sk, skb);
 
        if (msg->msg_name) {
                        msg->msg_namelen = sizeof(struct sockaddr_pkt);
                } else {
                        struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
+
                        msg->msg_namelen = sll->sll_halen +
                                offsetof(struct sockaddr_ll, sll_addr);
                }
                aux.tp_status = TP_STATUS_USER;
                if (skb->ip_summed == CHECKSUM_PARTIAL)
                        aux.tp_status |= TP_STATUS_CSUMNOTREADY;
-               aux.tp_len = PACKET_SKB_CB(skb)->origlen;
+               aux.tp_len = origlen;
                aux.tp_snaplen = skb->len;
                aux.tp_mac = 0;
                aux.tp_net = skb_network_offset(skb);