Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
Show First 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_addr(bdaddr_p, int); | static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_addr(bdaddr_p, int); | ||||
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_token(u_int32_t); | static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_token(u_int32_t); | ||||
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_cid (bdaddr_p, int,int); | static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_cid (bdaddr_p, int,int); | ||||
static int ng_btsocket_l2cap_result2errno(int); | static int ng_btsocket_l2cap_result2errno(int); | ||||
static int ng_btsock_l2cap_addrtype_to_linktype(int addrtype); | static int ng_btsock_l2cap_addrtype_to_linktype(int addrtype); | ||||
static int ng_btsock_l2cap_pcb_to_idtype(struct ng_btsocket_l2cap_pcb *); | |||||
#define ng_btsocket_l2cap_wakeup_input_task() \ | #define ng_btsocket_l2cap_wakeup_input_task() \ | ||||
taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_queue_task) | taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_queue_task) | ||||
#define ng_btsocket_l2cap_wakeup_route_task() \ | #define ng_btsocket_l2cap_wakeup_route_task() \ | ||||
taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_rt_task) | taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_rt_task) | ||||
int ng_btsock_l2cap_pcb_to_idtype(struct ng_btsocket_l2cap_pcb *pcb) | |||||
{ | |||||
if(pcb->dsttype == BDADDR_BREDR){ | |||||
return NG_L2CAP_L2CA_IDTYPE_BREDR; | |||||
}else if(pcb->psm == 0){ | |||||
return NG_L2CAP_L2CA_IDTYPE_ATT; | |||||
}else{ | |||||
return NG_L2CAP_L2CA_IDTYPE_LE; | |||||
} | |||||
} | |||||
int ng_btsock_l2cap_addrtype_to_linktype(int addrtype) | int ng_btsock_l2cap_addrtype_to_linktype(int addrtype) | ||||
{ | { | ||||
switch(addrtype){ | switch(addrtype){ | ||||
case BDADDR_LE_PUBLIC: | case BDADDR_LE_PUBLIC: | ||||
return NG_HCI_LINK_LE_PUBLIC; | return NG_HCI_LINK_LE_PUBLIC; | ||||
case BDADDR_LE_RANDOM: | case BDADDR_LE_RANDOM: | ||||
return NG_HCI_LINK_LE_RANDOM; | return NG_HCI_LINK_LE_RANDOM; | ||||
▲ Show 20 Lines • Show All 226 Lines • ▼ Show 20 Lines | if (op->result == NG_L2CAP_PENDING) { | ||||
ng_btsocket_l2cap_timeout(pcb); | ng_btsocket_l2cap_timeout(pcb); | ||||
mtx_unlock(&pcb->pcb_mtx); | mtx_unlock(&pcb->pcb_mtx); | ||||
mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | ||||
return (0); | return (0); | ||||
} | } | ||||
if (op->result == NG_L2CAP_SUCCESS){ | if (op->result == NG_L2CAP_SUCCESS){ | ||||
if(ng_btsock_l2cap_pcb_to_idtype(pcb) == | if((pcb->idtype == NG_L2CAP_L2CA_IDTYPE_ATT)|| | ||||
NG_L2CAP_L2CA_IDTYPE_ATT){ | (pcb->idtype == NG_L2CAP_L2CA_IDTYPE_SMP)){ | ||||
pcb->encryption = op->encryption; pcb->cid = op->lcid; | |||||
if(pcb->need_encrypt && !(pcb->encryption)){ | |||||
pcb->state = NG_BTSOCKET_L2CAP_W4_ENC_CHANGE; | |||||
}else{ | |||||
pcb->state = NG_BTSOCKET_L2CAP_OPEN; | pcb->state = NG_BTSOCKET_L2CAP_OPEN; | ||||
soisconnected(pcb->so); | soisconnected(pcb->so); | ||||
pcb->cid = op->lcid; | } | ||||
}else{ | }else{ | ||||
/* | /* | ||||
* Channel is now open, so update local channel ID and | * Channel is now open, so update local channel ID and | ||||
* start configuration process. Source and destination | * start configuration process. Source and destination | ||||
* addresses as well as route must be already set. | * addresses as well as route must be already set. | ||||
*/ | */ | ||||
pcb->cid = op->lcid; | pcb->cid = op->lcid; | ||||
pcb->encryption = op->encryption; | |||||
error = ng_btsocket_l2cap_send_l2ca_cfg_req(pcb); | error = ng_btsocket_l2cap_send_l2ca_cfg_req(pcb); | ||||
if (error != 0) { | if (error != 0) { | ||||
/* Send disconnect request with "zero" token */ | /* Send disconnect request with "zero" token */ | ||||
ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb); | ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb); | ||||
/* ... and close the socket */ | /* ... and close the socket */ | ||||
pcb->state = NG_BTSOCKET_L2CAP_CLOSED; | pcb->state = NG_BTSOCKET_L2CAP_CLOSED; | ||||
soisdisconnected(pcb->so); | soisdisconnected(pcb->so); | ||||
Show All 10 Lines | if (op->result == NG_L2CAP_SUCCESS){ | ||||
* code to "errno" code and disconnect the socket. Channel | * code to "errno" code and disconnect the socket. Channel | ||||
* already has been closed. | * already has been closed. | ||||
*/ | */ | ||||
pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result); | pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result); | ||||
pcb->state = NG_BTSOCKET_L2CAP_CLOSED; | pcb->state = NG_BTSOCKET_L2CAP_CLOSED; | ||||
soisdisconnected(pcb->so); | soisdisconnected(pcb->so); | ||||
} | } | ||||
mtx_unlock(&pcb->pcb_mtx); | mtx_unlock(&pcb->pcb_mtx); | ||||
mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | ||||
return (error); | return (error); | ||||
} /* ng_btsocket_l2cap_process_l2ca_con_req_rsp */ | } /* ng_btsocket_l2cap_process_l2ca_con_req_rsp */ | ||||
/* | /* | ||||
* Process L2CA_ConnectRsp response | * Process L2CA_ConnectRsp response | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | respond: | ||||
if (pcb != NULL) | if (pcb != NULL) | ||||
mtx_unlock(&pcb->pcb_mtx); | mtx_unlock(&pcb->pcb_mtx); | ||||
mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | ||||
return (error); | return (error); | ||||
} /* ng_btsocket_l2cap_process_l2ca_con_ind */ | } /* ng_btsocket_l2cap_process_l2ca_con_ind */ | ||||
/*Encryption Change*/ | |||||
static int ng_btsocket_l2cap_process_l2ca_enc_change(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt) | |||||
{ | |||||
ng_l2cap_l2ca_enc_chg_op *op = NULL; | |||||
ng_btsocket_l2cap_pcb_t *pcb = NULL; | |||||
if (msg->header.arglen != sizeof(*op)) | |||||
return (EMSGSIZE); | |||||
op = (ng_l2cap_l2ca_enc_chg_op *)(msg->data); | |||||
pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, op->lcid, | |||||
op->idtype); | |||||
mtx_lock(&pcb->pcb_mtx); | |||||
pcb->encryption = op->result; | |||||
if(pcb->need_encrypt){ | |||||
if(pcb->state != NG_BTSOCKET_L2CAP_W4_ENC_CHANGE){ | |||||
NG_BTSOCKET_L2CAP_WARN("%s: Invalid pcb status %d", | |||||
__func__, pcb->state); | |||||
}else if(pcb->encryption){ | |||||
pcb->state = NG_BTSOCKET_L2CAP_OPEN; | |||||
soisconnected(pcb->so); | |||||
}else{ | |||||
pcb->so->so_error = EPERM; | |||||
pcb->state = NG_BTSOCKET_L2CAP_CLOSED; | |||||
soisdisconnected(pcb->so); | |||||
} | |||||
} | |||||
mtx_unlock(&pcb->pcb_mtx); | |||||
return 0; | |||||
} | |||||
/* | /* | ||||
* Process L2CA_Config response | * Process L2CA_Config response | ||||
*/ | */ | ||||
static int | static int | ||||
ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg, | ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg, | ||||
ng_btsocket_l2cap_rtentry_p rt) | ng_btsocket_l2cap_rtentry_p rt) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 496 Lines • ▼ Show 20 Lines | if (msg == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
msg->header.token = pcb->token; | msg->header.token = pcb->token; | ||||
ip = (ng_l2cap_l2ca_con_ip *)(msg->data); | ip = (ng_l2cap_l2ca_con_ip *)(msg->data); | ||||
bcopy(&pcb->dst, &ip->bdaddr, sizeof(ip->bdaddr)); | bcopy(&pcb->dst, &ip->bdaddr, sizeof(ip->bdaddr)); | ||||
ip->psm = pcb->psm; | ip->psm = pcb->psm; | ||||
ip->linktype = ng_btsock_l2cap_addrtype_to_linktype(pcb->dsttype); | ip->linktype = ng_btsock_l2cap_addrtype_to_linktype(pcb->dsttype); | ||||
ip->idtype = ng_btsock_l2cap_pcb_to_idtype(pcb); | ip->idtype = pcb->idtype; | ||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0); | NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0); | ||||
return (error); | return (error); | ||||
} /* ng_btsocket_l2cap_send_l2ca_con_req */ | } /* ng_btsocket_l2cap_send_l2ca_con_req */ | ||||
/* | /* | ||||
* Send L2CA_Connect response | * Send L2CA_Connect response | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_DISCON, | ||||
sizeof(*ip), M_NOWAIT); | sizeof(*ip), M_NOWAIT); | ||||
if (msg == NULL) | if (msg == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
msg->header.token = token; | msg->header.token = token; | ||||
ip = (ng_l2cap_l2ca_discon_ip *)(msg->data); | ip = (ng_l2cap_l2ca_discon_ip *)(msg->data); | ||||
ip->lcid = pcb->cid; | ip->lcid = pcb->cid; | ||||
ip->idtype = ng_btsock_l2cap_pcb_to_idtype(pcb); | ip->idtype = pcb->idtype; | ||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0); | NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0); | ||||
return (error); | return (error); | ||||
} /* ng_btsocket_l2cap_send_l2ca_discon_req */ | } /* ng_btsocket_l2cap_send_l2ca_discon_req */ | ||||
/***************************************************************************** | /***************************************************************************** | ||||
***************************************************************************** | ***************************************************************************** | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
"%s: Received L2CAP data packet: src bdaddr=%x:%x:%x:%x:%x:%x, " \ | "%s: Received L2CAP data packet: src bdaddr=%x:%x:%x:%x:%x:%x, " \ | ||||
"dcid=%d, length=%d\n", | "dcid=%d, length=%d\n", | ||||
__func__, | __func__, | ||||
rt->src.b[5], rt->src.b[4], rt->src.b[3], | rt->src.b[5], rt->src.b[4], rt->src.b[3], | ||||
rt->src.b[2], rt->src.b[1], rt->src.b[0], | rt->src.b[2], rt->src.b[1], rt->src.b[0], | ||||
hdr->dcid, hdr->length); | hdr->dcid, hdr->length); | ||||
if ((hdr->dcid >= NG_L2CAP_FIRST_CID) || | if ((hdr->dcid >= NG_L2CAP_FIRST_CID) || | ||||
(idtype == NG_L2CAP_L2CA_IDTYPE_ATT)){ | (idtype == NG_L2CAP_L2CA_IDTYPE_ATT)|| | ||||
(idtype == NG_L2CAP_L2CA_IDTYPE_SMP) | |||||
){ | |||||
mtx_lock(&ng_btsocket_l2cap_sockets_mtx); | mtx_lock(&ng_btsocket_l2cap_sockets_mtx); | ||||
/* Normal packet: find connected socket */ | /* Normal packet: find connected socket */ | ||||
pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, hdr->dcid,idtype); | pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, hdr->dcid,idtype); | ||||
if (pcb == NULL) { | if (pcb == NULL) { | ||||
mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | mtx_unlock(&ng_btsocket_l2cap_sockets_mtx); | ||||
goto drop; | goto drop; | ||||
▲ Show 20 Lines • Show All 249 Lines • ▼ Show 20 Lines | "%s: Could not find out source bdaddr for L2CA message\n", __func__); | ||||
case NGM_L2CAP_L2CA_DISCON_IND: /* L2CA_Disconnect indicator */ | case NGM_L2CAP_L2CA_DISCON_IND: /* L2CA_Disconnect indicator */ | ||||
ng_btsocket_l2cap_process_l2ca_discon_ind(msg, rt); | ng_btsocket_l2cap_process_l2ca_discon_ind(msg, rt); | ||||
break; | break; | ||||
case NGM_L2CAP_L2CA_WRITE: /* L2CA_Write response */ | case NGM_L2CAP_L2CA_WRITE: /* L2CA_Write response */ | ||||
ng_btsocket_l2cap_process_l2ca_write_rsp(msg, rt); | ng_btsocket_l2cap_process_l2ca_write_rsp(msg, rt); | ||||
break; | break; | ||||
case NGM_L2CAP_L2CA_ENC_CHANGE: | |||||
ng_btsocket_l2cap_process_l2ca_enc_change(msg, rt); | |||||
emax: can you please remove this printf() or change it to one of the log macros? | |||||
break; | |||||
/* XXX FIXME add other L2CA messages */ | /* XXX FIXME add other L2CA messages */ | ||||
default: | default: | ||||
NG_BTSOCKET_L2CAP_WARN( | NG_BTSOCKET_L2CAP_WARN( | ||||
"%s: Unknown L2CA message, cmd=%d\n", __func__, msg->header.cmd); | "%s: Unknown L2CA message, cmd=%d\n", __func__, msg->header.cmd); | ||||
break; | break; | ||||
} | } | ||||
drop: | drop: | ||||
Show All 40 Lines | case NGQF_MESG: { | ||||
case NGM_L2CAP_L2CA_CON_RSP: | case NGM_L2CAP_L2CA_CON_RSP: | ||||
case NGM_L2CAP_L2CA_CON_IND: | case NGM_L2CAP_L2CA_CON_IND: | ||||
case NGM_L2CAP_L2CA_CFG: | case NGM_L2CAP_L2CA_CFG: | ||||
case NGM_L2CAP_L2CA_CFG_RSP: | case NGM_L2CAP_L2CA_CFG_RSP: | ||||
case NGM_L2CAP_L2CA_CFG_IND: | case NGM_L2CAP_L2CA_CFG_IND: | ||||
case NGM_L2CAP_L2CA_DISCON: | case NGM_L2CAP_L2CA_DISCON: | ||||
case NGM_L2CAP_L2CA_DISCON_IND: | case NGM_L2CAP_L2CA_DISCON_IND: | ||||
case NGM_L2CAP_L2CA_WRITE: | case NGM_L2CAP_L2CA_WRITE: | ||||
case NGM_L2CAP_L2CA_ENC_CHANGE: | |||||
/* XXX FIXME add other L2CA messages */ | /* XXX FIXME add other L2CA messages */ | ||||
ng_btsocket_l2cap_l2ca_msg_input(msg, hook); | ng_btsocket_l2cap_l2ca_msg_input(msg, hook); | ||||
break; | break; | ||||
default: | default: | ||||
ng_btsocket_l2cap_default_msg_input(msg, hook); | ng_btsocket_l2cap_default_msg_input(msg, hook); | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 355 Lines • ▼ Show 20 Lines | ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
ng_btsocket_l2cap_pcb_t *pcb = so2l2cap_pcb(so); | ng_btsocket_l2cap_pcb_t *pcb = so2l2cap_pcb(so); | ||||
struct sockaddr_l2cap_compat *sal = (struct sockaddr_l2cap_compat *) nam; | struct sockaddr_l2cap_compat *sal = (struct sockaddr_l2cap_compat *) nam; | ||||
struct sockaddr_l2cap *sa = (struct sockaddr_l2cap *)nam; | struct sockaddr_l2cap *sa = (struct sockaddr_l2cap *)nam; | ||||
struct sockaddr_l2cap ba; | struct sockaddr_l2cap ba; | ||||
ng_btsocket_l2cap_rtentry_t *rt = NULL; | ng_btsocket_l2cap_rtentry_t *rt = NULL; | ||||
int have_src, error = 0; | int have_src, error = 0; | ||||
int idtype = NG_L2CAP_L2CA_IDTYPE_BREDR; | |||||
/* Check socket */ | /* Check socket */ | ||||
if (pcb == NULL) | if (pcb == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (ng_btsocket_l2cap_node == NULL) | if (ng_btsocket_l2cap_node == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (pcb->state == NG_BTSOCKET_L2CAP_CONNECTING) | if (pcb->state == NG_BTSOCKET_L2CAP_CONNECTING) | ||||
return (EINPROGRESS); | return (EINPROGRESS); | ||||
Show All 12 Lines | if (sa->l2cap_len != sizeof(*sa)) | ||||
return (EINVAL); | return (EINVAL); | ||||
if ((sa->l2cap_psm && sa->l2cap_cid)) | if ((sa->l2cap_psm && sa->l2cap_cid)) | ||||
return EINVAL; | return EINVAL; | ||||
if (bcmp(&sa->l2cap_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) | if (bcmp(&sa->l2cap_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) | ||||
return (EDESTADDRREQ); | return (EDESTADDRREQ); | ||||
if((sa->l2cap_bdaddr_type == BDADDR_BREDR)&& | if((sa->l2cap_bdaddr_type == BDADDR_BREDR)&& | ||||
(sa->l2cap_psm == 0)) | (sa->l2cap_psm == 0)) | ||||
return EDESTADDRREQ; | return EDESTADDRREQ; | ||||
if((sa->l2cap_bdaddr_type != BDADDR_BREDR)&& | if(sa->l2cap_bdaddr_type != BDADDR_BREDR){ | ||||
(sa->l2cap_cid != NG_L2CAP_ATT_CID)){ | if(sa->l2cap_cid == NG_L2CAP_ATT_CID){ | ||||
idtype = NG_L2CAP_L2CA_IDTYPE_ATT; | |||||
}else if (sa->l2cap_cid == NG_L2CAP_SMP_CID){ | |||||
idtype =NG_L2CAP_L2CA_IDTYPE_SMP; | |||||
}else{ | |||||
//if cid == 0 idtype = NG_L2CAP_L2CA_IDTYPE_LE; | |||||
// Not supported yet | |||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
} | |||||
if (pcb->psm != 0 && pcb->psm != le16toh(sa->l2cap_psm)) | if (pcb->psm != 0 && pcb->psm != le16toh(sa->l2cap_psm)) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* | /* | ||||
* Routing. Socket should be bound to some source address. The source | * Routing. Socket should be bound to some source address. The source | ||||
* address can be ANY. Destination address must be set and it must not | * address can be ANY. Destination address must be set and it must not | ||||
* be ANY. If source address is ANY then find first rtentry that has | * be ANY. If source address is ANY then find first rtentry that has | ||||
* src != dst. | * src != dst. | ||||
*/ | */ | ||||
mtx_lock(&ng_btsocket_l2cap_rt_mtx); | mtx_lock(&ng_btsocket_l2cap_rt_mtx); | ||||
mtx_lock(&ng_btsocket_l2cap_sockets_mtx); | mtx_lock(&ng_btsocket_l2cap_sockets_mtx); | ||||
mtx_lock(&pcb->pcb_mtx); | mtx_lock(&pcb->pcb_mtx); | ||||
/* Send destination address and PSM */ | /* Send destination address and PSM */ | ||||
bcopy(&sa->l2cap_bdaddr, &pcb->dst, sizeof(pcb->dst)); | bcopy(&sa->l2cap_bdaddr, &pcb->dst, sizeof(pcb->dst)); | ||||
pcb->psm = le16toh(sa->l2cap_psm); | pcb->psm = le16toh(sa->l2cap_psm); | ||||
pcb->dsttype = sa->l2cap_bdaddr_type; | pcb->dsttype = sa->l2cap_bdaddr_type; | ||||
pcb->cid = sa->l2cap_cid; | pcb->cid = 0; | ||||
pcb->idtype = idtype; | |||||
pcb->rt = NULL; | pcb->rt = NULL; | ||||
have_src = bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src)); | have_src = bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src)); | ||||
LIST_FOREACH(rt, &ng_btsocket_l2cap_rt, next) { | LIST_FOREACH(rt, &ng_btsocket_l2cap_rt, next) { | ||||
if (rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook)) | if (rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook)) | ||||
continue; | continue; | ||||
/* Match src and dst */ | /* Match src and dst */ | ||||
if (have_src) { | if (have_src) { | ||||
if (bcmp(&pcb->src, &rt->src, sizeof(rt->src)) == 0) | if (bcmp(&pcb->src, &rt->src, sizeof(rt->src)) == 0) | ||||
break; | break; | ||||
} else { | } else { | ||||
if (bcmp(&pcb->dst, &rt->src, sizeof(rt->src)) != 0) | if (bcmp(&pcb->dst, &rt->src, sizeof(rt->src)) != 0) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (rt != NULL) { | if (rt != NULL) { | ||||
pcb->rt = rt; | pcb->rt = rt; | ||||
if (!have_src){ | if (!have_src){ | ||||
bcopy(&rt->src, &pcb->src, sizeof(pcb->src)); | bcopy(&rt->src, &pcb->src, sizeof(pcb->src)); | ||||
pcb->srctype = | pcb->srctype = | ||||
(sa->l2cap_bdaddr_type == BDADDR_BREDR)? | (sa->l2cap_bdaddr_type == BDADDR_BREDR)? | ||||
BDADDR_BREDR : BDADDR_LE_RANDOM; | BDADDR_BREDR : BDADDR_LE_PUBLIC; | ||||
} | } | ||||
} else | } else | ||||
error = EHOSTUNREACH; | error = EHOSTUNREACH; | ||||
/* | /* | ||||
* Send L2CA_Connect request | * Send L2CA_Connect request | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | case SO_L2CAP_OFLOW: /* get outgoing flow spec. */ | ||||
error = sooptcopyout(sopt, &pcb->oflow, | error = sooptcopyout(sopt, &pcb->oflow, | ||||
sizeof(pcb->oflow)); | sizeof(pcb->oflow)); | ||||
break; | break; | ||||
case SO_L2CAP_FLUSH: /* get flush timeout */ | case SO_L2CAP_FLUSH: /* get flush timeout */ | ||||
error = sooptcopyout(sopt, &pcb->flush_timo, | error = sooptcopyout(sopt, &pcb->flush_timo, | ||||
sizeof(pcb->flush_timo)); | sizeof(pcb->flush_timo)); | ||||
break; | break; | ||||
case SO_L2CAP_ENCRYPTED: /* get encrypt required */ | |||||
error = sooptcopyout(sopt, &pcb->need_encrypt, | |||||
sizeof(pcb->need_encrypt)); | |||||
Not Done Inline Actionsi think this is cut and paste typo. it should read sizeof(pcb->need_encrypt), imo emax: i think this is cut and paste typo. it should read sizeof(pcb->need_encrypt), imo | |||||
break; | |||||
default: | default: | ||||
error = ENOPROTOOPT; | error = ENOPROTOOPT; | ||||
break; | break; | ||||
} | } | ||||
break; | break; | ||||
case SOPT_SET: | case SOPT_SET: | ||||
/* | /* | ||||
Show All 23 Lines | case SO_L2CAP_OFLOW: /* set outgoing flow spec. */ | ||||
break; | break; | ||||
case SO_L2CAP_FLUSH: /* set flush timeout */ | case SO_L2CAP_FLUSH: /* set flush timeout */ | ||||
error = sooptcopyin(sopt, &v, sizeof(v), | error = sooptcopyin(sopt, &v, sizeof(v), | ||||
sizeof(v.flush_timo)); | sizeof(v.flush_timo)); | ||||
if (error == 0) | if (error == 0) | ||||
pcb->flush_timo = v.flush_timo; | pcb->flush_timo = v.flush_timo; | ||||
break; | break; | ||||
case SO_L2CAP_ENCRYPTED: /*set connect encryption opt*/ | |||||
if((pcb->state != NG_BTSOCKET_L2CAP_OPEN) && | |||||
(pcb->state != NG_BTSOCKET_L2CAP_W4_ENC_CHANGE)){ | |||||
error = sooptcopyin(sopt, &v, sizeof(v), | |||||
sizeof(v.encryption)); | |||||
if(error == 0) | |||||
Not Done Inline Actionsdo you think this should check socket state? basically, if connection is already established, i think, it should refuse to change encryption. otherwise it might give an impression that encryption can be turned on/off while connection is established. emax: do you think this should check socket state? basically, if connection is already established, i… | |||||
pcb->need_encrypt = (v.encryption)?1:0; | |||||
}else{ | |||||
error = EINVAL; | |||||
} | |||||
break; | |||||
default: | default: | ||||
error = ENOPROTOOPT; | error = ENOPROTOOPT; | ||||
break; | break; | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | if (pcb == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (ng_btsocket_l2cap_node == NULL) | if (ng_btsocket_l2cap_node == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
bcopy(&pcb->dst, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr)); | bcopy(&pcb->dst, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr)); | ||||
sa.l2cap_psm = htole16(pcb->psm); | sa.l2cap_psm = htole16(pcb->psm); | ||||
sa.l2cap_len = sizeof(sa); | sa.l2cap_len = sizeof(sa); | ||||
sa.l2cap_family = AF_BLUETOOTH; | sa.l2cap_family = AF_BLUETOOTH; | ||||
switch(pcb->idtype){ | |||||
case NG_L2CAP_L2CA_IDTYPE_ATT: | |||||
sa.l2cap_cid = NG_L2CAP_ATT_CID; | |||||
break; | |||||
case NG_L2CAP_L2CA_IDTYPE_SMP: | |||||
sa.l2cap_cid = NG_L2CAP_SMP_CID; | |||||
break; | |||||
default: | |||||
sa.l2cap_cid = 0; | sa.l2cap_cid = 0; | ||||
break; | |||||
} | |||||
sa.l2cap_bdaddr_type = pcb->dsttype; | sa.l2cap_bdaddr_type = pcb->dsttype; | ||||
*nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); | *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); | ||||
return ((*nam == NULL)? ENOMEM : 0); | return ((*nam == NULL)? ENOMEM : 0); | ||||
} /* ng_btsocket_l2cap_peeraddr */ | } /* ng_btsocket_l2cap_peeraddr */ | ||||
/* | /* | ||||
* Send data to socket | * Send data to socket | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | "%s: Failed to create L2CA packet header\n", __func__); | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
hdr = mtod(m, ng_l2cap_l2ca_hdr_t *); | hdr = mtod(m, ng_l2cap_l2ca_hdr_t *); | ||||
hdr->token = pcb->token; | hdr->token = pcb->token; | ||||
hdr->length = m->m_pkthdr.len - sizeof(*hdr); | hdr->length = m->m_pkthdr.len - sizeof(*hdr); | ||||
hdr->lcid = pcb->cid; | hdr->lcid = pcb->cid; | ||||
hdr->idtype = ng_btsock_l2cap_pcb_to_idtype(pcb); | hdr->idtype = pcb->idtype; | ||||
NG_BTSOCKET_L2CAP_INFO( | NG_BTSOCKET_L2CAP_INFO( | ||||
"%s: Sending packet: len=%d, length=%d, lcid=%d, token=%d, state=%d\n", | "%s: Sending packet: len=%d, length=%d, lcid=%d, token=%d, state=%d\n", | ||||
__func__, m->m_pkthdr.len, hdr->length, hdr->lcid, | __func__, m->m_pkthdr.len, hdr->length, hdr->lcid, | ||||
hdr->token, pcb->state); | hdr->token, pcb->state); | ||||
/* | /* | ||||
* If we got here than we have successfuly creates new L2CAP | * If we got here than we have successfuly creates new L2CAP | ||||
* data packet and now we can send it to the L2CAP layer | * data packet and now we can send it to the L2CAP layer | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
ng_btsocket_l2cap_pcb_p p = NULL; | ng_btsocket_l2cap_pcb_p p = NULL; | ||||
mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED); | mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED); | ||||
LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next){ | LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next){ | ||||
if (p->cid == cid && | if (p->cid == cid && | ||||
bcmp(src, &p->src, sizeof(p->src)) == 0&& | bcmp(src, &p->src, sizeof(p->src)) == 0&& | ||||
ng_btsock_l2cap_pcb_to_idtype(p) == idtype) | p->idtype == idtype) | ||||
break; | break; | ||||
} | } | ||||
return (p); | return (p); | ||||
} /* ng_btsocket_l2cap_pcb_by_cid */ | } /* ng_btsocket_l2cap_pcb_by_cid */ | ||||
/* | /* | ||||
* Set timeout on socket | * Set timeout on socket | ||||
▲ Show 20 Lines • Show All 171 Lines • Show Last 20 Lines |
can you please remove this printf() or change it to one of the log macros?