Bluetooth LE Security Management channel support.
Add a socket option to block until underlying HCI connection encrypted. Differential Revision: https://reviews.freebsd.org/D3981
This commit is contained in:
parent
3c82a7278a
commit
5e743ed2df
@ -929,7 +929,7 @@ encryption_change(ng_hci_unit_p unit, struct mbuf *event)
|
|||||||
"%s: %s - invalid connection handle=%d\n",
|
"%s: %s - invalid connection handle=%d\n",
|
||||||
__func__, NG_NODE_NAME(unit->node), h);
|
__func__, NG_NODE_NAME(unit->node), h);
|
||||||
error = ENOENT;
|
error = ENOENT;
|
||||||
} else if (con->link_type != NG_HCI_LINK_ACL) {
|
} else if (con->link_type == NG_HCI_LINK_SCO) {
|
||||||
NG_HCI_ALERT(
|
NG_HCI_ALERT(
|
||||||
"%s: %s - invalid link type=%d\n",
|
"%s: %s - invalid link type=%d\n",
|
||||||
__func__, NG_NODE_NAME(unit->node),
|
__func__, NG_NODE_NAME(unit->node),
|
||||||
@ -940,6 +940,7 @@ encryption_change(ng_hci_unit_p unit, struct mbuf *event)
|
|||||||
con->encryption_mode = NG_HCI_ENCRYPTION_MODE_P2P;
|
con->encryption_mode = NG_HCI_ENCRYPTION_MODE_P2P;
|
||||||
else
|
else
|
||||||
con->encryption_mode = NG_HCI_ENCRYPTION_MODE_NONE;
|
con->encryption_mode = NG_HCI_ENCRYPTION_MODE_NONE;
|
||||||
|
ng_hci_lp_enc_change(con, ep->encryption_enable);
|
||||||
} else
|
} else
|
||||||
NG_HCI_ERR(
|
NG_HCI_ERR(
|
||||||
"%s: %s - failed to change encryption mode, status=%d\n",
|
"%s: %s - failed to change encryption mode, status=%d\n",
|
||||||
|
@ -814,6 +814,37 @@ ng_hci_lp_con_cfm(ng_hci_unit_con_p con, int status)
|
|||||||
return (0);
|
return (0);
|
||||||
} /* ng_hci_lp_con_cfm */
|
} /* ng_hci_lp_con_cfm */
|
||||||
|
|
||||||
|
int
|
||||||
|
ng_hci_lp_enc_change(ng_hci_unit_con_p con, int status)
|
||||||
|
{
|
||||||
|
ng_hci_unit_p unit = con->unit;
|
||||||
|
struct ng_mesg *msg = NULL;
|
||||||
|
ng_hci_lp_enc_change_ep *ep = NULL;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
|
||||||
|
if (con->link_type != NG_HCI_LINK_SCO) {
|
||||||
|
if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
|
||||||
|
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_ENC_CHG,
|
||||||
|
sizeof(*ep), M_NOWAIT);
|
||||||
|
if (msg != NULL) {
|
||||||
|
ep = (ng_hci_lp_enc_change_ep *) msg->data;
|
||||||
|
ep->status = status;
|
||||||
|
ep->link_type = con->link_type;
|
||||||
|
ep->con_handle = con->con_handle;
|
||||||
|
|
||||||
|
NG_SEND_MSG_HOOK(error, unit->node, msg,
|
||||||
|
unit->acl, 0);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
NG_HCI_INFO(
|
||||||
|
"%s: %s - ACL hook not valid, hook=%p\n",
|
||||||
|
__func__, NG_NODE_NAME(unit->node), unit->acl);
|
||||||
|
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
} /* ng_hci_lp_con_cfm */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send LP_ConnectInd event to the upper layer protocol
|
* Send LP_ConnectInd event to the upper layer protocol
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +47,7 @@ int ng_hci_lp_discon_ind (ng_hci_unit_con_p, int);
|
|||||||
int ng_hci_lp_qos_req (ng_hci_unit_p, item_p, hook_p);
|
int ng_hci_lp_qos_req (ng_hci_unit_p, item_p, hook_p);
|
||||||
int ng_hci_lp_qos_cfm (ng_hci_unit_con_p, int);
|
int ng_hci_lp_qos_cfm (ng_hci_unit_con_p, int);
|
||||||
int ng_hci_lp_qos_ind (ng_hci_unit_con_p);
|
int ng_hci_lp_qos_ind (ng_hci_unit_con_p);
|
||||||
|
int ng_hci_lp_enc_change (ng_hci_unit_con_p, int);
|
||||||
|
|
||||||
void ng_hci_process_con_timeout (node_p, hook_p, void *, int);
|
void ng_hci_process_con_timeout (node_p, hook_p, void *, int);
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ struct sockaddr_l2cap {
|
|||||||
#define SO_L2CAP_IFLOW 3 /* get incoming flow spec. */
|
#define SO_L2CAP_IFLOW 3 /* get incoming flow spec. */
|
||||||
#define SO_L2CAP_OFLOW 4 /* get/set outgoing flow spec. */
|
#define SO_L2CAP_OFLOW 4 /* get/set outgoing flow spec. */
|
||||||
#define SO_L2CAP_FLUSH 5 /* get/set flush timeout */
|
#define SO_L2CAP_FLUSH 5 /* get/set flush timeout */
|
||||||
|
#define SO_L2CAP_ENCRYPTED 6 /* get/set whether wait for encryptin on connect */
|
||||||
/*
|
/*
|
||||||
* Raw L2CAP sockets ioctl's
|
* Raw L2CAP sockets ioctl's
|
||||||
*/
|
*/
|
||||||
|
@ -136,7 +136,7 @@ struct ng_btsocket_l2cap_pcb {
|
|||||||
|
|
||||||
u_int16_t psm; /* PSM */
|
u_int16_t psm; /* PSM */
|
||||||
u_int16_t cid; /* Local channel ID */
|
u_int16_t cid; /* Local channel ID */
|
||||||
|
uint8_t idtype;
|
||||||
u_int16_t flags; /* socket flags */
|
u_int16_t flags; /* socket flags */
|
||||||
#define NG_BTSOCKET_L2CAP_CLIENT (1 << 0) /* socket is client */
|
#define NG_BTSOCKET_L2CAP_CLIENT (1 << 0) /* socket is client */
|
||||||
#define NG_BTSOCKET_L2CAP_TIMO (1 << 1) /* timeout pending */
|
#define NG_BTSOCKET_L2CAP_TIMO (1 << 1) /* timeout pending */
|
||||||
@ -147,6 +147,7 @@ struct ng_btsocket_l2cap_pcb {
|
|||||||
#define NG_BTSOCKET_L2CAP_CONFIGURING 2 /* wait for config */
|
#define NG_BTSOCKET_L2CAP_CONFIGURING 2 /* wait for config */
|
||||||
#define NG_BTSOCKET_L2CAP_OPEN 3 /* socket open */
|
#define NG_BTSOCKET_L2CAP_OPEN 3 /* socket open */
|
||||||
#define NG_BTSOCKET_L2CAP_DISCONNECTING 4 /* wait for disconnect */
|
#define NG_BTSOCKET_L2CAP_DISCONNECTING 4 /* wait for disconnect */
|
||||||
|
#define NG_BTSOCKET_L2CAP_W4_ENC_CHANGE 5
|
||||||
|
|
||||||
u_int8_t cfg_state; /* config state */
|
u_int8_t cfg_state; /* config state */
|
||||||
#define NG_BTSOCKET_L2CAP_CFG_IN (1 << 0) /* incoming path done */
|
#define NG_BTSOCKET_L2CAP_CFG_IN (1 << 0) /* incoming path done */
|
||||||
@ -156,7 +157,7 @@ struct ng_btsocket_l2cap_pcb {
|
|||||||
|
|
||||||
#define NG_BTSOCKET_L2CAP_CFG_IN_SENT (1 << 2) /* L2CAP ConfigReq sent */
|
#define NG_BTSOCKET_L2CAP_CFG_IN_SENT (1 << 2) /* L2CAP ConfigReq sent */
|
||||||
#define NG_BTSOCKET_L2CAP_CFG_OUT_SENT (1 << 3) /* ---/--- */
|
#define NG_BTSOCKET_L2CAP_CFG_OUT_SENT (1 << 3) /* ---/--- */
|
||||||
|
uint8_t encryption;
|
||||||
u_int16_t imtu; /* Incoming MTU */
|
u_int16_t imtu; /* Incoming MTU */
|
||||||
ng_l2cap_flow_t iflow; /* Input flow spec */
|
ng_l2cap_flow_t iflow; /* Input flow spec */
|
||||||
|
|
||||||
@ -172,7 +173,8 @@ struct ng_btsocket_l2cap_pcb {
|
|||||||
ng_btsocket_l2cap_rtentry_p rt; /* routing info */
|
ng_btsocket_l2cap_rtentry_p rt; /* routing info */
|
||||||
|
|
||||||
struct mtx pcb_mtx; /* pcb mutex */
|
struct mtx pcb_mtx; /* pcb mutex */
|
||||||
|
uint16_t need_encrypt; /*encryption needed*/
|
||||||
|
|
||||||
LIST_ENTRY(ng_btsocket_l2cap_pcb) next; /* link to next PCB */
|
LIST_ENTRY(ng_btsocket_l2cap_pcb) next; /* link to next PCB */
|
||||||
};
|
};
|
||||||
typedef struct ng_btsocket_l2cap_pcb ng_btsocket_l2cap_pcb_t;
|
typedef struct ng_btsocket_l2cap_pcb ng_btsocket_l2cap_pcb_t;
|
||||||
|
@ -469,7 +469,13 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
u_int16_t con_handle; /* connection handle */
|
u_int16_t con_handle; /* connection handle */
|
||||||
} ng_hci_lp_qos_ind_ep;
|
} ng_hci_lp_qos_ind_ep;
|
||||||
|
/*Encryption Change event*/
|
||||||
|
#define NGM_HCI_LP_ENC_CHG 10 /* HCI->Upper*/
|
||||||
|
typedef struct {
|
||||||
|
uint16_t con_handle;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t link_type;
|
||||||
|
}ng_hci_lp_enc_change_ep;
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
** HCI node command/event parameters
|
** HCI node command/event parameters
|
||||||
|
@ -256,6 +256,7 @@ typedef union {
|
|||||||
u_int16_t mtu; /* NG_L2CAP_OPT_MTU */
|
u_int16_t mtu; /* NG_L2CAP_OPT_MTU */
|
||||||
u_int16_t flush_timo; /* NG_L2CAP_OPT_FLUSH_TIMO */
|
u_int16_t flush_timo; /* NG_L2CAP_OPT_FLUSH_TIMO */
|
||||||
ng_l2cap_flow_t flow; /* NG_L2CAP_OPT_QOS */
|
ng_l2cap_flow_t flow; /* NG_L2CAP_OPT_QOS */
|
||||||
|
uint16_t encryption;
|
||||||
} ng_l2cap_cfg_opt_val_t;
|
} ng_l2cap_cfg_opt_val_t;
|
||||||
typedef ng_l2cap_cfg_opt_val_t * ng_l2cap_cfg_opt_val_p;
|
typedef ng_l2cap_cfg_opt_val_t * ng_l2cap_cfg_opt_val_p;
|
||||||
|
|
||||||
@ -357,6 +358,7 @@ typedef struct {
|
|||||||
#define NG_L2CAP_L2CA_IDTYPE_BREDR 0
|
#define NG_L2CAP_L2CA_IDTYPE_BREDR 0
|
||||||
#define NG_L2CAP_L2CA_IDTYPE_ATT 1
|
#define NG_L2CAP_L2CA_IDTYPE_ATT 1
|
||||||
#define NG_L2CAP_L2CA_IDTYPE_LE 2
|
#define NG_L2CAP_L2CA_IDTYPE_LE 2
|
||||||
|
#define NG_L2CAP_L2CA_IDTYPE_SMP 3
|
||||||
/* L2CA_Connect */
|
/* L2CA_Connect */
|
||||||
#define NGM_L2CAP_L2CA_CON 0x80
|
#define NGM_L2CAP_L2CA_CON 0x80
|
||||||
/* Upper -> L2CAP */
|
/* Upper -> L2CAP */
|
||||||
@ -373,6 +375,7 @@ typedef struct {
|
|||||||
uint16_t idtype; /*ID type*/
|
uint16_t idtype; /*ID type*/
|
||||||
u_int16_t result; /* 0x00 - success */
|
u_int16_t result; /* 0x00 - success */
|
||||||
u_int16_t status; /* if result != 0x00 */
|
u_int16_t status; /* if result != 0x00 */
|
||||||
|
uint8_t encryption;
|
||||||
} ng_l2cap_l2ca_con_op;
|
} ng_l2cap_l2ca_con_op;
|
||||||
|
|
||||||
/* L2CA_ConnectInd */
|
/* L2CA_ConnectInd */
|
||||||
@ -598,6 +601,12 @@ typedef struct {
|
|||||||
* u_int16_t result; /* 0x00 - success */
|
* u_int16_t result; /* 0x00 - success */
|
||||||
* } ng_l2cap_l2ca_enable_clt_op;
|
* } ng_l2cap_l2ca_enable_clt_op;
|
||||||
#endif
|
#endif
|
||||||
|
#define NGM_L2CAP_L2CA_ENC_CHANGE 0x92
|
||||||
|
typedef struct {
|
||||||
|
uint16_t lcid;
|
||||||
|
uint16_t result;
|
||||||
|
uint8_t idtype;
|
||||||
|
} ng_l2cap_l2ca_enc_chg_op;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
|
@ -475,6 +475,8 @@ ng_l2cap_process_con_req(ng_l2cap_con_p con, u_int8_t ident)
|
|||||||
con->rx_pkt = NULL;
|
con->rx_pkt = NULL;
|
||||||
if(dcid == NG_L2CAP_ATT_CID)
|
if(dcid == NG_L2CAP_ATT_CID)
|
||||||
idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
|
idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
|
||||||
|
else if(dcid == NG_L2CAP_SMP_CID)
|
||||||
|
idtype = NG_L2CAP_L2CA_IDTYPE_SMP;
|
||||||
else if( con->linktype != NG_HCI_LINK_ACL)
|
else if( con->linktype != NG_HCI_LINK_ACL)
|
||||||
idtype = NG_L2CAP_L2CA_IDTYPE_LE;
|
idtype = NG_L2CAP_L2CA_IDTYPE_LE;
|
||||||
else
|
else
|
||||||
@ -602,7 +604,9 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
cmd->ch->dcid = dcid;
|
cmd->ch->dcid = dcid;
|
||||||
cmd->ch->state = (cmd->ch->scid == NG_L2CAP_ATT_CID)?
|
cmd->ch->state = ((cmd->ch->scid == NG_L2CAP_ATT_CID)||
|
||||||
|
(cmd->ch->scid == NG_L2CAP_SMP_CID))
|
||||||
|
?
|
||||||
NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
|
NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
|
||||||
} else
|
} else
|
||||||
/* There was an error, so close the channel */
|
/* There was an error, so close the channel */
|
||||||
|
@ -481,6 +481,58 @@ ng_l2cap_lp_qos_ind(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
return (error);
|
return (error);
|
||||||
} /* ng_l2cap_qos_ind */
|
} /* ng_l2cap_qos_ind */
|
||||||
|
|
||||||
|
int
|
||||||
|
ng_l2cap_lp_enc_change(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
||||||
|
{
|
||||||
|
ng_hci_lp_enc_change_ep *ep = NULL;
|
||||||
|
ng_l2cap_con_p con = NULL;
|
||||||
|
int error = 0;
|
||||||
|
ng_l2cap_chan_p ch = NULL;
|
||||||
|
/* Check message */
|
||||||
|
if (msg->header.arglen != sizeof(*ep)) {
|
||||||
|
NG_L2CAP_ALERT(
|
||||||
|
"%s: %s - invalid LP_ENCChange message size\n",
|
||||||
|
__func__, NG_NODE_NAME(l2cap->node));
|
||||||
|
error = EMSGSIZE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ep = (ng_hci_lp_enc_change_ep *) (msg->data);
|
||||||
|
|
||||||
|
/* Check if we have this connection */
|
||||||
|
con = ng_l2cap_con_by_handle(l2cap, ep->con_handle);
|
||||||
|
if (con == NULL) {
|
||||||
|
NG_L2CAP_ERR(
|
||||||
|
"%s: %s - unexpected LP_Enc Change Event. " \
|
||||||
|
"Connection does not exist, con_handle=%d\n",
|
||||||
|
__func__, NG_NODE_NAME(l2cap->node), ep->con_handle);
|
||||||
|
error = ENOENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify connection state */
|
||||||
|
if (con->state != NG_L2CAP_CON_OPEN) {
|
||||||
|
NG_L2CAP_ERR(
|
||||||
|
"%s: %s - unexpected ENC_CHANGE event. " \
|
||||||
|
"Invalid connection state, state=%d, con_handle=%d\n",
|
||||||
|
__func__, NG_NODE_NAME(l2cap->node), con->state,
|
||||||
|
con->con_handle);
|
||||||
|
error = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
con->encryption = ep->status;
|
||||||
|
|
||||||
|
LIST_FOREACH(ch, &l2cap->chan_list, next){
|
||||||
|
if((ch->con->con_handle == ep->con_handle) &&
|
||||||
|
(ch->con->linktype == ep->link_type))
|
||||||
|
ng_l2cap_l2ca_encryption_change(ch, ep->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return (error);
|
||||||
|
} /* ng_l2cap_enc_change */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare L2CAP packet. Prepend packet with L2CAP packet header and then
|
* Prepare L2CAP packet. Prepend packet with L2CAP packet header and then
|
||||||
* segment it according to HCI MTU.
|
* segment it according to HCI MTU.
|
||||||
|
@ -41,6 +41,7 @@ int ng_l2cap_lp_discon_ind (ng_l2cap_p, struct ng_mesg *);
|
|||||||
int ng_l2cap_lp_qos_req (ng_l2cap_p, u_int16_t, ng_l2cap_flow_p);
|
int ng_l2cap_lp_qos_req (ng_l2cap_p, u_int16_t, ng_l2cap_flow_p);
|
||||||
int ng_l2cap_lp_qos_cfm (ng_l2cap_p, struct ng_mesg *);
|
int ng_l2cap_lp_qos_cfm (ng_l2cap_p, struct ng_mesg *);
|
||||||
int ng_l2cap_lp_qos_ind (ng_l2cap_p, struct ng_mesg *);
|
int ng_l2cap_lp_qos_ind (ng_l2cap_p, struct ng_mesg *);
|
||||||
|
int ng_l2cap_lp_enc_change (ng_l2cap_p, struct ng_mesg *);
|
||||||
int ng_l2cap_lp_send (ng_l2cap_con_p, u_int16_t,struct mbuf *);
|
int ng_l2cap_lp_send (ng_l2cap_con_p, u_int16_t,struct mbuf *);
|
||||||
int ng_l2cap_lp_receive (ng_l2cap_p, struct mbuf *);
|
int ng_l2cap_lp_receive (ng_l2cap_p, struct mbuf *);
|
||||||
void ng_l2cap_lp_deliver (ng_l2cap_con_p);
|
void ng_l2cap_lp_deliver (ng_l2cap_con_p);
|
||||||
|
@ -350,7 +350,9 @@ ng_l2cap_lower_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
|||||||
case NGM_HCI_LP_QOS_IND:
|
case NGM_HCI_LP_QOS_IND:
|
||||||
error = ng_l2cap_lp_qos_ind(l2cap, msg);
|
error = ng_l2cap_lp_qos_ind(l2cap, msg);
|
||||||
break;
|
break;
|
||||||
|
case NGM_HCI_LP_ENC_CHG:
|
||||||
|
error = ng_l2cap_lp_enc_change(l2cap, msg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
break;
|
break;
|
||||||
|
@ -114,7 +114,7 @@ ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr, int type)
|
|||||||
|
|
||||||
con->l2cap = l2cap;
|
con->l2cap = l2cap;
|
||||||
con->state = NG_L2CAP_CON_CLOSED;
|
con->state = NG_L2CAP_CON_CLOSED;
|
||||||
|
con->encryption = 0;
|
||||||
/*
|
/*
|
||||||
* XXX
|
* XXX
|
||||||
*
|
*
|
||||||
@ -340,6 +340,8 @@ ng_l2cap_new_chan(ng_l2cap_p l2cap, ng_l2cap_con_p con, u_int16_t psm, int idtyp
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
if(idtype == NG_L2CAP_L2CA_IDTYPE_ATT){
|
if(idtype == NG_L2CAP_L2CA_IDTYPE_ATT){
|
||||||
ch->scid = ch->dcid = NG_L2CAP_ATT_CID;
|
ch->scid = ch->dcid = NG_L2CAP_ATT_CID;
|
||||||
|
}else if(idtype == NG_L2CAP_L2CA_IDTYPE_SMP){
|
||||||
|
ch->scid = ch->dcid = NG_L2CAP_SMP_CID;
|
||||||
}else{
|
}else{
|
||||||
ch->scid = ng_l2cap_get_cid(l2cap,
|
ch->scid = ng_l2cap_get_cid(l2cap,
|
||||||
(con->linktype!= NG_HCI_LINK_ACL));
|
(con->linktype!= NG_HCI_LINK_ACL));
|
||||||
@ -379,7 +381,8 @@ ng_l2cap_chan_by_scid(ng_l2cap_p l2cap, u_int16_t scid, int idtype)
|
|||||||
{
|
{
|
||||||
ng_l2cap_chan_p ch = NULL;
|
ng_l2cap_chan_p ch = NULL;
|
||||||
|
|
||||||
if(idtype == NG_L2CAP_L2CA_IDTYPE_ATT){
|
if((idtype == NG_L2CAP_L2CA_IDTYPE_ATT)||
|
||||||
|
(idtype == NG_L2CAP_L2CA_IDTYPE_SMP)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +393,6 @@ ng_l2cap_chan_by_scid(ng_l2cap_p l2cap, u_int16_t scid, int idtype)
|
|||||||
if((idtype != NG_L2CAP_L2CA_IDTYPE_LE)&&
|
if((idtype != NG_L2CAP_L2CA_IDTYPE_LE)&&
|
||||||
(ch->con->linktype != NG_HCI_LINK_ACL ))
|
(ch->con->linktype != NG_HCI_LINK_ACL ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ch->scid == scid)
|
if (ch->scid == scid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,10 @@ ng_l2cap_l2ca_con_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
_ng_l2cap_con_rsp(cmd->aux, cmd->ident, NG_L2CAP_ATT_CID,
|
_ng_l2cap_con_rsp(cmd->aux, cmd->ident, NG_L2CAP_ATT_CID,
|
||||||
NG_L2CAP_ATT_CID, 0, 0);
|
NG_L2CAP_ATT_CID, 0, 0);
|
||||||
cmd->aux->m_flags |= M_PROTO2;
|
cmd->aux->m_flags |= M_PROTO2;
|
||||||
|
}else if(ip->idtype == NG_L2CAP_L2CA_IDTYPE_SMP){
|
||||||
|
_ng_l2cap_con_rsp(cmd->aux, cmd->ident, NG_L2CAP_SMP_CID,
|
||||||
|
NG_L2CAP_SMP_CID, 0, 0);
|
||||||
|
cmd->aux->m_flags |= M_PROTO2;
|
||||||
}else{
|
}else{
|
||||||
_ng_l2cap_con_req(cmd->aux, cmd->ident, ch->psm, ch->scid);
|
_ng_l2cap_con_req(cmd->aux, cmd->ident, ch->psm, ch->scid);
|
||||||
}
|
}
|
||||||
@ -191,13 +195,16 @@ ng_l2cap_l2ca_con_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result,
|
|||||||
if(ch->scid == NG_L2CAP_ATT_CID){
|
if(ch->scid == NG_L2CAP_ATT_CID){
|
||||||
op->idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
|
op->idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
|
||||||
op->lcid = ch->con->con_handle;
|
op->lcid = ch->con->con_handle;
|
||||||
|
}else if(ch->scid == NG_L2CAP_SMP_CID){
|
||||||
|
op->idtype = NG_L2CAP_L2CA_IDTYPE_SMP;
|
||||||
|
op->lcid = ch->con->con_handle;
|
||||||
}else{
|
}else{
|
||||||
op->idtype = (ch->con->linktype == NG_HCI_LINK_ACL)?
|
op->idtype = (ch->con->linktype == NG_HCI_LINK_ACL)?
|
||||||
NG_L2CAP_L2CA_IDTYPE_BREDR :
|
NG_L2CAP_L2CA_IDTYPE_BREDR :
|
||||||
NG_L2CAP_L2CA_IDTYPE_LE;
|
NG_L2CAP_L2CA_IDTYPE_LE;
|
||||||
op->lcid = ch->scid;
|
op->lcid = ch->scid;
|
||||||
}
|
}
|
||||||
|
op->encryption = ch->con->encryption;
|
||||||
op->result = result;
|
op->result = result;
|
||||||
op->status = status;
|
op->status = status;
|
||||||
|
|
||||||
@ -234,7 +241,8 @@ ng_l2cap_l2ca_con_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
ip = (ng_l2cap_l2ca_con_rsp_ip *)(msg->data);
|
ip = (ng_l2cap_l2ca_con_rsp_ip *)(msg->data);
|
||||||
|
|
||||||
/* Check if we have this channel */
|
/* Check if we have this channel */
|
||||||
if(ip->lcid != NG_L2CAP_ATT_CID){
|
if((ip->lcid != NG_L2CAP_ATT_CID)&&
|
||||||
|
(ip->lcid != NG_L2CAP_SMP_CID)){
|
||||||
ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid
|
ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid
|
||||||
,(ip->linktype == NG_HCI_LINK_ACL)?
|
,(ip->linktype == NG_HCI_LINK_ACL)?
|
||||||
NG_L2CAP_L2CA_IDTYPE_BREDR:
|
NG_L2CAP_L2CA_IDTYPE_BREDR:
|
||||||
@ -281,7 +289,8 @@ ng_l2cap_l2ca_con_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
/* Check result */
|
/* Check result */
|
||||||
switch (ip->result) {
|
switch (ip->result) {
|
||||||
case NG_L2CAP_SUCCESS:
|
case NG_L2CAP_SUCCESS:
|
||||||
ch->state = (ch->scid == NG_L2CAP_ATT_CID)?
|
ch->state = ((ch->scid == NG_L2CAP_ATT_CID)||
|
||||||
|
(ch->scid == NG_L2CAP_SMP_CID))?
|
||||||
NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
|
NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
|
||||||
ch->cfg_state = 0;
|
ch->cfg_state = 0;
|
||||||
break;
|
break;
|
||||||
@ -324,6 +333,53 @@ ng_l2cap_l2ca_con_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
return (error);
|
return (error);
|
||||||
} /* ng_l2cap_l2ca_con_rsp_req */
|
} /* ng_l2cap_l2ca_con_rsp_req */
|
||||||
|
|
||||||
|
int ng_l2cap_l2ca_encryption_change(ng_l2cap_chan_p ch, uint16_t result)
|
||||||
|
{
|
||||||
|
ng_l2cap_p l2cap = ch->con->l2cap;
|
||||||
|
struct ng_mesg *msg = NULL;
|
||||||
|
ng_l2cap_l2ca_enc_chg_op *op = NULL;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
/* Check if upstream hook is connected and valid */
|
||||||
|
if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
|
||||||
|
NG_L2CAP_ERR(
|
||||||
|
"%s: %s - unable to send L2CA_ConnectRsp response message. " \
|
||||||
|
"Hook is not connected or valid, psm=%d\n",
|
||||||
|
__func__, NG_NODE_NAME(l2cap->node), ch->psm);
|
||||||
|
|
||||||
|
return (ENOTCONN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create and send L2CA_ConnectRsp response message */
|
||||||
|
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_ENC_CHANGE,
|
||||||
|
sizeof(*op), M_NOWAIT);
|
||||||
|
if (msg == NULL)
|
||||||
|
error = ENOMEM;
|
||||||
|
else {
|
||||||
|
msg->header.token = 0;
|
||||||
|
msg->header.flags |= NGF_RESP;
|
||||||
|
|
||||||
|
op = (ng_l2cap_l2ca_enc_chg_op *)(msg->data);
|
||||||
|
op->result = result;
|
||||||
|
if(ch->scid ==NG_L2CAP_ATT_CID||
|
||||||
|
ch->scid ==NG_L2CAP_SMP_CID){
|
||||||
|
op->lcid = ch->con->con_handle;
|
||||||
|
op->idtype = (ch->scid==NG_L2CAP_ATT_CID)?
|
||||||
|
NG_L2CAP_L2CA_IDTYPE_ATT:
|
||||||
|
NG_L2CAP_L2CA_IDTYPE_SMP;
|
||||||
|
}else{
|
||||||
|
op->idtype =(ch->con->linktype ==NG_HCI_LINK_ACL)?
|
||||||
|
NG_L2CAP_L2CA_IDTYPE_BREDR:
|
||||||
|
NG_L2CAP_L2CA_IDTYPE_LE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Send L2CAP_ConnectRsp response to the upper layer
|
* Send L2CAP_ConnectRsp response to the upper layer
|
||||||
*/
|
*/
|
||||||
@ -399,6 +455,7 @@ ng_l2cap_l2ca_con_ind(ng_l2cap_chan_p ch)
|
|||||||
ip->psm = ch->psm;
|
ip->psm = ch->psm;
|
||||||
ip->ident = ch->ident;
|
ip->ident = ch->ident;
|
||||||
ip->linktype = ch->con->linktype;
|
ip->linktype = ch->con->linktype;
|
||||||
|
|
||||||
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
|
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,7 +558,8 @@ ng_l2cap_l2ca_cfg_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
|
|
||||||
/* Adjust channel state for re-configuration */
|
/* Adjust channel state for re-configuration */
|
||||||
if (ch->state == NG_L2CAP_OPEN) {
|
if (ch->state == NG_L2CAP_OPEN) {
|
||||||
ch->state = (ch->scid == NG_L2CAP_ATT_CID)?
|
ch->state = ((ch->scid == NG_L2CAP_ATT_CID)||
|
||||||
|
(ch->scid == NG_L2CAP_SMP_CID))?
|
||||||
NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
|
NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
|
||||||
ch->cfg_state = 0;
|
ch->cfg_state = 0;
|
||||||
}
|
}
|
||||||
@ -812,7 +870,10 @@ ng_l2cap_l2ca_write_req(ng_l2cap_p l2cap, struct mbuf *m)
|
|||||||
if (l2ca_hdr->idtype == NG_L2CAP_L2CA_IDTYPE_ATT){
|
if (l2ca_hdr->idtype == NG_L2CAP_L2CA_IDTYPE_ATT){
|
||||||
ch = ng_l2cap_chan_by_conhandle(l2cap, NG_L2CAP_ATT_CID,
|
ch = ng_l2cap_chan_by_conhandle(l2cap, NG_L2CAP_ATT_CID,
|
||||||
l2ca_hdr->lcid);
|
l2ca_hdr->lcid);
|
||||||
} else{
|
} else if (l2ca_hdr->idtype == NG_L2CAP_L2CA_IDTYPE_SMP){
|
||||||
|
ch = ng_l2cap_chan_by_conhandle(l2cap, NG_L2CAP_SMP_CID,
|
||||||
|
l2ca_hdr->lcid);
|
||||||
|
}else{
|
||||||
if (l2ca_hdr->lcid < NG_L2CAP_FIRST_CID) {
|
if (l2ca_hdr->lcid < NG_L2CAP_FIRST_CID) {
|
||||||
NG_L2CAP_ERR(
|
NG_L2CAP_ERR(
|
||||||
"%s: %s - invalid L2CA Data packet. Inavlid channel ID, cid=%d\n",
|
"%s: %s - invalid L2CA Data packet. Inavlid channel ID, cid=%d\n",
|
||||||
@ -901,6 +962,9 @@ ng_l2cap_l2ca_write_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result,
|
|||||||
if(ch->scid == NG_L2CAP_ATT_CID){
|
if(ch->scid == NG_L2CAP_ATT_CID){
|
||||||
op->idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
|
op->idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
|
||||||
op->lcid = ch->con->con_handle;
|
op->lcid = ch->con->con_handle;
|
||||||
|
}else if(ch->scid == NG_L2CAP_SMP_CID){
|
||||||
|
op->idtype = NG_L2CAP_L2CA_IDTYPE_SMP;
|
||||||
|
op->lcid = ch->con->con_handle;
|
||||||
}else{
|
}else{
|
||||||
op->idtype = (ch->con->linktype == NG_HCI_LINK_ACL)?
|
op->idtype = (ch->con->linktype == NG_HCI_LINK_ACL)?
|
||||||
NG_L2CAP_L2CA_IDTYPE_BREDR :
|
NG_L2CAP_L2CA_IDTYPE_BREDR :
|
||||||
@ -928,7 +992,8 @@ ng_l2cap_l2ca_receive(ng_l2cap_con_p con)
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
int idtype;
|
int idtype;
|
||||||
uint16_t *idp;
|
uint16_t *idp;
|
||||||
|
int silent = 0;
|
||||||
|
|
||||||
NG_L2CAP_M_PULLUP(con->rx_pkt, sizeof(*hdr));
|
NG_L2CAP_M_PULLUP(con->rx_pkt, sizeof(*hdr));
|
||||||
if (con->rx_pkt == NULL)
|
if (con->rx_pkt == NULL)
|
||||||
return (ENOBUFS);
|
return (ENOBUFS);
|
||||||
@ -945,6 +1010,17 @@ ng_l2cap_l2ca_receive(ng_l2cap_con_p con)
|
|||||||
* Here,ATT channel is distinguished by
|
* Here,ATT channel is distinguished by
|
||||||
* connection handle
|
* connection handle
|
||||||
*/
|
*/
|
||||||
|
hdr->dcid = con->con_handle;
|
||||||
|
silent = 1;
|
||||||
|
}else if(hdr->dcid == NG_L2CAP_SMP_CID){
|
||||||
|
idtype = NG_L2CAP_L2CA_IDTYPE_SMP;
|
||||||
|
ch = ng_l2cap_chan_by_conhandle(l2cap, NG_L2CAP_SMP_CID,
|
||||||
|
con->con_handle);
|
||||||
|
/*
|
||||||
|
* Here,SMP channel is distinguished by
|
||||||
|
* connection handle
|
||||||
|
*/
|
||||||
|
silent = 1;
|
||||||
hdr->dcid = con->con_handle;
|
hdr->dcid = con->con_handle;
|
||||||
}else{
|
}else{
|
||||||
idtype = (con->linktype==NG_HCI_LINK_ACL)?
|
idtype = (con->linktype==NG_HCI_LINK_ACL)?
|
||||||
@ -953,7 +1029,8 @@ ng_l2cap_l2ca_receive(ng_l2cap_con_p con)
|
|||||||
ch = ng_l2cap_chan_by_scid(l2cap, hdr->dcid, idtype);
|
ch = ng_l2cap_chan_by_scid(l2cap, hdr->dcid, idtype);
|
||||||
}
|
}
|
||||||
if (ch == NULL) {
|
if (ch == NULL) {
|
||||||
NG_L2CAP_ERR(
|
if(!silent)
|
||||||
|
NG_L2CAP_ERR(
|
||||||
"%s: %s - unexpected L2CAP data packet. Channel does not exist, cid=%d, idtype=%d\n",
|
"%s: %s - unexpected L2CAP data packet. Channel does not exist, cid=%d, idtype=%d\n",
|
||||||
__func__, NG_NODE_NAME(l2cap->node), hdr->dcid, idtype);
|
__func__, NG_NODE_NAME(l2cap->node), hdr->dcid, idtype);
|
||||||
error = ENOENT;
|
error = ENOENT;
|
||||||
@ -1165,6 +1242,21 @@ ng_l2cap_l2ca_discon_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
|||||||
}else{
|
}else{
|
||||||
NG_L2CAP_ERR(
|
NG_L2CAP_ERR(
|
||||||
"%s: %s - unexpected L2CA_Disconnect request message. " \
|
"%s: %s - unexpected L2CA_Disconnect request message. " \
|
||||||
|
"Channel does not exist, conhandle=%d\n",
|
||||||
|
__func__, NG_NODE_NAME(l2cap->node), ip->lcid);
|
||||||
|
error = EINVAL;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}else if(ip->idtype == NG_L2CAP_L2CA_IDTYPE_SMP){
|
||||||
|
/* Don't send Disconnect request on L2CAP Layer*/
|
||||||
|
ch = ng_l2cap_chan_by_conhandle(l2cap, NG_L2CAP_SMP_CID,
|
||||||
|
ip->lcid);
|
||||||
|
|
||||||
|
if(ch != NULL){
|
||||||
|
ng_l2cap_free_chan(ch);
|
||||||
|
}else{
|
||||||
|
NG_L2CAP_ERR(
|
||||||
|
"%s: %s - unexpected L2CA_Disconnect request message. " \
|
||||||
"Channel does not exist, conhandle=%d\n",
|
"Channel does not exist, conhandle=%d\n",
|
||||||
__func__, NG_NODE_NAME(l2cap->node), ip->lcid);
|
__func__, NG_NODE_NAME(l2cap->node), ip->lcid);
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
|
@ -74,6 +74,6 @@ int ng_l2cap_l2ca_get_info_rsp (ng_l2cap_con_p, u_int32_t, u_int16_t,
|
|||||||
struct mbuf *);
|
struct mbuf *);
|
||||||
|
|
||||||
int ng_l2cap_l2ca_enable_clt (ng_l2cap_p, struct ng_mesg *);
|
int ng_l2cap_l2ca_enable_clt (ng_l2cap_p, struct ng_mesg *);
|
||||||
|
int ng_l2cap_l2ca_encryption_change(ng_l2cap_chan_p , uint16_t );
|
||||||
#endif /* ndef _NETGRAPH_L2CAP_ULPI_H_ */
|
#endif /* ndef _NETGRAPH_L2CAP_ULPI_H_ */
|
||||||
|
|
||||||
|
@ -119,7 +119,8 @@ typedef struct ng_l2cap_con {
|
|||||||
|
|
||||||
u_int8_t ident; /* last allocated ident */
|
u_int8_t ident; /* last allocated ident */
|
||||||
uint8_t linktype;
|
uint8_t linktype;
|
||||||
|
uint8_t encryption;
|
||||||
|
|
||||||
TAILQ_HEAD(, ng_l2cap_cmd) cmd_list; /* pending L2CAP cmds */
|
TAILQ_HEAD(, ng_l2cap_cmd) cmd_list; /* pending L2CAP cmds */
|
||||||
|
|
||||||
struct mbuf *tx_pkt; /* xmitted L2CAP packet */
|
struct mbuf *tx_pkt; /* xmitted L2CAP packet */
|
||||||
|
@ -213,7 +213,7 @@ static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_cid (bdaddr_p, int,i
|
|||||||
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)
|
||||||
|
|
||||||
@ -221,16 +221,6 @@ static int ng_btsock_l2cap_pcb_to_idtype(struct ng_btsocket_l2cap_pcb *);
|
|||||||
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)
|
||||||
{
|
{
|
||||||
@ -473,11 +463,15 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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->state = NG_BTSOCKET_L2CAP_OPEN;
|
pcb->encryption = op->encryption; pcb->cid = op->lcid;
|
||||||
soisconnected(pcb->so);
|
if(pcb->need_encrypt && !(pcb->encryption)){
|
||||||
pcb->cid = op->lcid;
|
pcb->state = NG_BTSOCKET_L2CAP_W4_ENC_CHANGE;
|
||||||
|
}else{
|
||||||
|
pcb->state = NG_BTSOCKET_L2CAP_OPEN;
|
||||||
|
soisconnected(pcb->so);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
/*
|
/*
|
||||||
* Channel is now open, so update local channel ID and
|
* Channel is now open, so update local channel ID and
|
||||||
@ -486,7 +480,7 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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 */
|
||||||
@ -513,7 +507,6 @@ ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
|
|||||||
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);
|
||||||
|
|
||||||
@ -702,7 +695,40 @@ ng_btsocket_l2cap_process_l2ca_con_ind(struct ng_mesg *msg,
|
|||||||
|
|
||||||
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
|
||||||
*/
|
*/
|
||||||
@ -1215,7 +1241,7 @@ ng_btsocket_l2cap_send_l2ca_con_req(ng_btsocket_l2cap_pcb_p pcb)
|
|||||||
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);
|
||||||
@ -1354,7 +1380,7 @@ ng_btsocket_l2cap_send_l2ca_discon_req(u_int32_t 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);
|
||||||
|
|
||||||
@ -1441,7 +1467,9 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
|
|||||||
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);
|
||||||
|
|
||||||
@ -1707,7 +1735,10 @@ ng_btsocket_l2cap_l2ca_msg_input(struct ng_mesg *msg, hook_p hook)
|
|||||||
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);
|
||||||
|
|
||||||
|
break;
|
||||||
/* XXX FIXME add other L2CA messages */
|
/* XXX FIXME add other L2CA messages */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1764,6 +1795,7 @@ ng_btsocket_l2cap_input(void *context, int pending)
|
|||||||
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;
|
||||||
@ -2135,7 +2167,7 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *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);
|
||||||
@ -2164,9 +2196,16 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
|
|||||||
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){
|
||||||
return EINVAL;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pcb->psm != 0 && pcb->psm != le16toh(sa->l2cap_psm))
|
if (pcb->psm != 0 && pcb->psm != le16toh(sa->l2cap_psm))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
@ -2185,8 +2224,8 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
|
|||||||
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));
|
||||||
|
|
||||||
@ -2211,7 +2250,7 @@ ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam,
|
|||||||
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;
|
||||||
@ -2297,6 +2336,11 @@ ng_btsocket_l2cap_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
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));
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error = ENOPROTOOPT;
|
error = ENOPROTOOPT;
|
||||||
@ -2337,7 +2381,17 @@ ng_btsocket_l2cap_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
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)
|
||||||
|
pcb->need_encrypt = (v.encryption)?1:0;
|
||||||
|
}else{
|
||||||
|
error = EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error = ENOPROTOOPT;
|
error = ENOPROTOOPT;
|
||||||
break;
|
break;
|
||||||
@ -2489,7 +2543,17 @@ ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam)
|
|||||||
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;
|
||||||
sa.l2cap_cid = 0;
|
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;
|
||||||
|
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);
|
||||||
|
|
||||||
@ -2608,7 +2672,7 @@ ng_btsocket_l2cap_send2(ng_btsocket_l2cap_pcb_p pcb)
|
|||||||
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,
|
||||||
@ -2721,7 +2785,7 @@ ng_btsocket_l2cap_pcb_by_cid(bdaddr_p src, int cid, int idtype)
|
|||||||
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user