static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; struct sock *sk = sock->sk; int err = 0; lock_sock(sk); BT_DBG("sk %p", sk); if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_l2)) { err = -EINVAL; goto done; } if (sk->type == SOCK_SEQPACKET && !la->l2_psm) { err = -EINVAL; goto done; } switch(sk->state) { case BT_CONNECT: case BT_CONNECT2: case BT_CONFIG: /* Already connecting */ goto wait; case BT_CONNECTED: /* Already connected */ goto done; case BT_OPEN: case BT_BOUND: /* Can connect */ break; default: err = -EBADFD; goto done; } /* Set destination address and psm */ bacpy(&bluez_pi(sk)->dst, &la->l2_bdaddr); l2cap_pi(sk)->psm = la->l2_psm; if ((err = l2cap_do_connect(sk))) goto done; wait: err = bluez_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); done: release_sock(sk); return err; }
static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sock *sk = sock->sk; struct sockaddr_l2 la; int len, err = 0; BT_DBG("sk %p type %d mode %d state %d", sk, sk->sk_type, l2cap_pi(sk)->mode, sk->sk_state); if (!addr || alen < sizeof(addr->sa_family) || addr->sa_family != AF_BLUETOOTH) return -EINVAL; memset(&la, 0, sizeof(la)); len = min_t(unsigned int, sizeof(la), alen); memcpy(&la, addr, len); if (la.l2_cid && la.l2_psm) return -EINVAL; lock_sock(sk); if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) && !(la.l2_psm || la.l2_cid || l2cap_pi(sk)->fixed_channel)) { err = -EINVAL; goto done; } switch (l2cap_pi(sk)->mode) { case L2CAP_MODE_BASIC: break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: if (!disable_ertm) break; /* fall through */ default: err = -ENOTSUPP; goto done; } switch (sk->sk_state) { case BT_CONNECT: case BT_CONNECT2: case BT_CONFIG: /* Already connecting */ goto wait; case BT_CONNECTED: /* Already connected */ err = -EISCONN; goto done; case BT_OPEN: case BT_BOUND: /* Can connect */ break; default: err = -EBADFD; goto done; } /* PSM must be odd and lsb of upper byte must be 0 */ if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && !l2cap_pi(sk)->fixed_channel && sk->sk_type != SOCK_RAW && !la.l2_cid) { BT_DBG("Bad PSM 0x%x", (int)__le16_to_cpu(la.l2_psm)); err = -EINVAL; goto done; } /* Set destination address and psm */ bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); l2cap_pi(sk)->psm = la.l2_psm; l2cap_pi(sk)->dcid = la.l2_cid; err = l2cap_do_connect(sk); if (err) goto done; wait: err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); done: if (err) BT_ERR("failed %d", err); release_sock(sk); return err; }