Beispiel #1
0
static struct pdu_wbuf*
build_pdu_wbuf_msg_with_fd(struct pdu_wbuf* wbuf, int fd)
{
  struct iovec* iov;
  union {
    struct cmsghdr chdr;
    unsigned char data[CMSG_SPACE(sizeof(fd))];
  } cmsg;
  struct cmsghdr* chdr;

  assert(wbuf);

  iov = pdu_wbuf_tail(wbuf);
  iov->iov_base = wbuf->buf.raw;
  iov->iov_len = wbuf->off;

  memset(&wbuf->msg, 0, sizeof(wbuf->msg));
  wbuf->msg.msg_iov = iov;
  wbuf->msg.msg_iovlen = 1;
  wbuf->msg.msg_control = iov + 1;
  wbuf->msg.msg_controllen = sizeof(cmsg);

  chdr = CMSG_FIRSTHDR(&wbuf->msg);
  chdr->cmsg_len = sizeof(fd);
  chdr->cmsg_level = SOL_SOCKET;
  chdr->cmsg_type = SCM_RIGHTS;
  *((int*)CMSG_DATA(chdr)) = fd;

  return wbuf;
}
Beispiel #2
0
static struct pdu_wbuf*
build_pdu_wbuf_msg(struct pdu_wbuf* wbuf)
{
  struct iovec* iov;

  assert(wbuf);

  iov = pdu_wbuf_tail(wbuf);
  iov->iov_base = wbuf->buf.raw;
  iov->iov_len = wbuf->off;

  memset(&wbuf->msg, 0, sizeof(wbuf->msg));
  wbuf->msg.msg_iov = iov;
  wbuf->msg.msg_iovlen = 1;

  return wbuf;
}
static bt_status_t
opcode_connect(const struct pdu* cmd)
{
  long off;
  bt_bdaddr_t bd_addr;
  uint8_t type;
  uint8_t uuid[16];
  uint16_t channel;
  uint8_t flags;
  struct pdu_wbuf* wbuf;
  struct ancillary_data* data;
  bt_status_t status;

  off = read_bt_bdaddr_t(cmd, 0, &bd_addr);
  if (off < 0)
    return BT_STATUS_PARM_INVALID;
  if (read_pdu_at(cmd, off, "CmsC", &type, uuid, sizeof(uuid),
                                    &channel, &flags) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0,
                         ALIGNMENT_PADDING + sizeof(*data),
                         build_ancillary_data);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  data = ceil_align(pdu_wbuf_tail(wbuf), ALIGNMENT_PADDING);

  status = bt_sock_connect(&bd_addr, type, uuid, channel,
                           &data->sock_fd, flags);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_sock_listen;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_sock_listen:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static bt_status_t
opcode_listen(const struct pdu* cmd)
{
  uint8_t type;
  int8_t service_name[256];
  uint8_t uuid[16];
  uint16_t channel;
  uint8_t flags;
  struct pdu_wbuf* wbuf;
  struct ancillary_data* data;
  bt_status_t status;

  if (read_pdu_at(cmd, 0, "CmmSC", &type,
                                   service_name, (size_t)sizeof(service_name),
                                   uuid, (size_t)sizeof(uuid),
                                   &channel, &flags) < 0)
    return BT_STATUS_PARM_INVALID;

  wbuf = create_pdu_wbuf(0,
                         ALIGNMENT_PADDING + sizeof(*data),
                         build_ancillary_data);
  if (!wbuf)
    return BT_STATUS_NOMEM;

  data = ceil_align(pdu_wbuf_tail(wbuf), ALIGNMENT_PADDING);

  status = bt_sock_listen(type, (char*)service_name, uuid, channel,
                          &data->sock_fd, flags);
  if (status != BT_STATUS_SUCCESS)
    goto err_bt_sock_listen;

  init_pdu(&wbuf->buf.pdu, cmd->service, cmd->opcode);
  send_pdu(wbuf);

  return BT_STATUS_SUCCESS;
err_bt_sock_listen:
  cleanup_pdu_wbuf(wbuf);
  return status;
}
static int
build_ancillary_data(struct pdu_wbuf* wbuf, struct msghdr* msg)
{
  struct ancillary_data* data;
  struct cmsghdr* chdr;

  assert(msg);

  data = ceil_align(pdu_wbuf_tail(wbuf), ALIGNMENT_PADDING);

  msg->msg_control = data->cmsgbuf;
  msg->msg_controllen = sizeof(data->cmsgbuf);

  chdr = CMSG_FIRSTHDR(msg);
  chdr->cmsg_len = CMSG_LEN(sizeof(data->sock_fd));
  chdr->cmsg_level = SOL_SOCKET;
  chdr->cmsg_type = SCM_RIGHTS;
  memcpy(CMSG_DATA(chdr), &data->sock_fd, sizeof(data->sock_fd));

  msg->msg_controllen = chdr->cmsg_len;

  return 0;
}