void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) { struct sockaddr_llc *addr; /* save primitive for use by the user. */ addr = llc_ui_skb_cb(skb); memset(addr, 0, sizeof(*addr)); 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; addr->sllc_ua = prim == LLC_DATAUNIT_PRIM; llc_pdu_decode_sa(skb, addr->sllc_mac); llc_pdu_decode_ssap(skb, &addr->sllc_sap); }
/** * llc_ui_recvmsg - copy received data to the socket user. * @sock: Socket to copy data from. * @msg: Various user space related information. * @size: Size of user buffer. * @flags: User specified flags. * * Copy received data to the socket user. * Returns non-negative upon success, negative otherwise. */ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; struct sk_buff *skb; size_t copied = 0; int rc = -ENOMEM, timeout; int noblock = flags & MSG_DONTWAIT; dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); lock_sock(sk); timeout = sock_rcvtimeo(sk, noblock); rc = llc_ui_wait_for_data(sk, timeout); if (rc) { dprintk("%s: llc_ui_wait_for_data failed recv " "in %02X from %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); goto out; } skb = skb_dequeue(&sk->sk_receive_queue); if (!skb) /* shutdown */ goto out; copied = skb->len; if (copied > size) copied = size; rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); if (rc) goto dgram_free; if (skb->len > copied) { skb_pull(skb, copied); skb_queue_head(&sk->sk_receive_queue, skb); } if (uaddr) memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr)); msg->msg_namelen = sizeof(*uaddr); if (!skb->list) { dgram_free: kfree_skb(skb); } out: release_sock(sk); return rc ? : copied; }