* See the GNU General Public License for more details.
  */
 struct llc_sap;
-struct sk_buff;
 struct net_device;
+struct sk_buff;
+struct sock;
 
 extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
-extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim);
+extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
+                              unsigned char prim);
 extern struct sk_buff *llc_alloc_frame(struct net_device *dev);
 
 extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
 
        /* put original socket back into a clean listen state. */
        sk->sk_state = TCP_LISTEN;
        sk->sk_ack_backlog--;
-       skb->sk = NULL;
        dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
                llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
 frees:
        lock_sock(sk);
        if (!skb)
                goto release;
-       skb->sk       = sk;
        skb->dev      = llc->dev;
        skb->protocol = llc_proto_type(addr->sllc_arphrd);
        skb_reserve(skb, hdrlen); 
 
        if (skb) {
                struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
-               skb->sk  = sk;
+               skb_set_owner_r(skb, sk);
                ev->type = type;
                llc_process_tmr_ev(sk, skb);
        }
 
 
        switch (ev->ind_prim) {
        case LLC_DATA_PRIM:
-               llc_save_primitive(skb, LLC_DATA_PRIM);
-               if (sock_queue_rcv_skb(sk, skb)) {
+               llc_save_primitive(sk, skb, LLC_DATA_PRIM);
+               if (unlikely(sock_queue_rcv_skb(sk, skb))) {
                        /*
                         * shouldn't happen
                         */
        case LLC_CONN_PRIM: {
                struct sock *parent = skb->sk;
 
+               skb_orphan(skb);
+               /*
+                * Set the skb->sk to the new struct sock, so that at accept
+                * type the upper layer can get the newly created struct sock.
+                */
                skb->sk = sk;
                skb_queue_tail(&parent->sk_receive_queue, skb);
                sk->sk_state_change(parent);
                memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));
                llc_sap_add_socket(sap, sk);
                sock_hold(sk);
+               skb_set_owner_r(skb, parent);
                sock_put(parent);
-               skb->sk = parent;
-       } else
-               skb->sk = sk;
+       }
        bh_lock_sock(sk);
        if (!sock_owned_by_user(sk))
                llc_conn_rcv(sk, skb);
 
        return skb;
 }
 
-void llc_save_primitive(struct sk_buff* skb, u8 prim)
+void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
 {
        struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
 
        /* save primitive for use by the user. */
-       addr->sllc_family = skb->sk->sk_family;
+       addr->sllc_family = sk->sk_family;
        addr->sllc_arphrd = skb->dev->type;
        addr->sllc_test   = prim == LLC_TEST_PRIM;
        addr->sllc_xid    = prim == LLC_XID_PRIM;
                if (skb->sk->sk_state == TCP_LISTEN)
                        kfree_skb(skb);
                else {
-                       llc_save_primitive(skb, ev->prim);
+                       llc_save_primitive(skb->sk, skb, ev->prim);
 
                        /* queue skb to the user. */
                        if (sock_queue_rcv_skb(skb->sk, skb))
 
        sk = llc_lookup_dgram(sap, &laddr);
        if (sk) {
-               skb->sk = sk;
+               skb_set_owner_r(skb, sk);
                llc_sap_rcv(sap, skb);
                sock_put(sk);
        } else