static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) { struct sco_conn *conn = sco_pi(sk)->conn; struct sk_buff *skb; int err, count; /* Check outgoing MTU */ if (len > conn->mtu) return -EINVAL; BT_DBG("sk %p len %d", sk, len); count = MIN(conn->mtu, len); if (!(skb = bluez_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) return err; if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { err = -EFAULT; goto fail; } if ((err = hci_send_sco(conn->hcon, skb)) < 0) goto fail; return count; fail: kfree_skb(skb); return err; }
static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { struct sock *sk = sock->sk; struct hci_dev *hdev = hci_pi(sk)->hdev; struct sk_buff *skb; int err; DBG("sock %p sk %p", sock, sk); if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) return -EINVAL; if (!hdev) return -EBADFD; if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) return err; if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { kfree_skb(skb); return -EFAULT; } skb->dev = (void *) hdev; skb->pkt_type = *((unsigned char *) skb->data); skb_pull(skb, 1); /* Send frame to HCI core */ hci_send_raw(skb); return len; }
static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { struct sock *sk = sock->sk; struct hci_dev *hdev; struct sk_buff *skb; int err; BT_DBG("sock %p sk %p", sock, sk); if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) return -EINVAL; if (len < 4) return -EINVAL; lock_sock(sk); if (!(hdev = hci_pi(sk)->hdev)) { err = -EBADFD; goto done; } if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) goto done; if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { err = -EFAULT; goto drop; } skb->pkt_type = *((unsigned char *) skb->data); skb_pull(skb, 1); skb->dev = (void *) hdev; if (skb->pkt_type == HCI_COMMAND_PKT) { u16 opcode = __le16_to_cpu(get_unaligned((u16 *)skb->data)); u16 ogf = cmd_opcode_ogf(opcode); u16 ocf = cmd_opcode_ocf(opcode); if (((ogf > HCI_SFLT_MAX_OGF) || !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) && !capable(CAP_NET_RAW)) { err = -EPERM; goto drop; } if (test_bit(HCI_RAW, &hdev->flags) || (ogf == OGF_VENDOR_CMD)) { skb_queue_tail(&hdev->raw_q, skb); hci_sched_tx(hdev); } else { skb_queue_tail(&hdev->cmd_q, skb); hci_sched_cmd(hdev); } } else { if (!capable(CAP_NET_RAW)) { err = -EPERM; goto drop; } skb_queue_tail(&hdev->raw_q, skb); hci_sched_tx(hdev); } err = len; done: release_sock(sk); return err; drop: kfree_skb(skb); goto done; }
static int l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sk_buff *skb, **frag; int err, hlen, count, sent=0; l2cap_hdr *lh; BT_DBG("sk %p len %d", sk, len); /* First fragment (with L2CAP header) */ if (sk->type == SOCK_DGRAM) hlen = L2CAP_HDR_SIZE + 2; else hlen = L2CAP_HDR_SIZE; count = MIN(conn->mtu - hlen, len); skb = bluez_skb_send_alloc(sk, hlen + count, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) return err; /* Create L2CAP header */ lh = (l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid); lh->len = __cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); if (sk->type == SOCK_DGRAM) put_unaligned(l2cap_pi(sk)->psm, (__u16 *) skb_put(skb, 2)); if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { err = -EFAULT; goto fail; } sent += count; len -= count; /* Continuation fragments (no L2CAP header) */ frag = &skb_shinfo(skb)->frag_list; while (len) { count = MIN(conn->mtu, len); *frag = bluez_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err); if (!*frag) goto fail; if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) { err = -EFAULT; goto fail; } sent += count; len -= count; frag = &(*frag)->next; } if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0) goto fail; return sent; fail: kfree_skb(skb); return err; }
static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { struct sock *sk = sock->sk; struct hci_dev *hdev; struct sk_buff *skb; int err; BT_DBG("sock %p sk %p", sock, sk); if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) return -EINVAL; if (len < 4) return -EINVAL; lock_sock(sk); if (!(hdev = hci_pi(sk)->hdev)) { err = -EBADFD; goto done; } if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) goto done; if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { err = -EFAULT; goto drop; } skb->pkt_type = *((unsigned char *) skb->data); skb_pull(skb, 1); if (!capable(CAP_NET_RAW)) { err = -EPERM; if (skb->pkt_type == HCI_COMMAND_PKT) { __u16 opcode = __le16_to_cpu(*(__u16 *)skb->data); __u16 ogf = cmd_opcode_ogf(opcode) - 1; __u16 ocf = cmd_opcode_ocf(opcode) & HCI_FLT_OCF_BITS; if (ogf > HCI_SFLT_MAX_OGF || !hci_test_bit(ocf, &hci_sec_filter.ocf_mask[ogf])) goto drop; } else goto drop; } /* Send frame to HCI core */ skb->dev = (void *) hdev; hci_send_raw(skb); err = len; done: release_sock(sk); return err; drop: kfree_skb(skb); goto done; }