int ng_l2cap_l2ca_con_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg) { ng_l2cap_l2ca_con_rsp_ip *ip = NULL; ng_l2cap_con_p con = NULL; ng_l2cap_chan_p ch = NULL; ng_l2cap_cmd_p cmd = NULL; u_int16_t dcid; int error = 0; /* Check message */ if (msg->header.arglen != sizeof(*ip)) { NG_L2CAP_ALERT( "%s: %s - invalid L2CA_ConnectRsp request message size, size=%d\n", __func__, NG_NODE_NAME(l2cap->node), msg->header.arglen); error = EMSGSIZE; goto out; } ip = (ng_l2cap_l2ca_con_rsp_ip *)(msg->data); /* Check if we have this channel */ ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid); if (ch == NULL) { NG_L2CAP_ALERT( "%s: %s - unexpected L2CA_ConnectRsp request message. " \ "Channel does not exist, lcid=%d\n", __func__, NG_NODE_NAME(l2cap->node), ip->lcid); error = ENOENT; goto out; } /* Check channel state */ if (ch->state != NG_L2CAP_W4_L2CA_CON_RSP) { NG_L2CAP_ERR( "%s: %s - unexpected L2CA_ConnectRsp request message. " \ "Invalid channel state, state=%d, lcid=%d\n", __func__, NG_NODE_NAME(l2cap->node), ch->state, ip->lcid); error = EINVAL; goto out; } dcid = ch->dcid; con = ch->con; /* * Now we are pretty much sure it is our response. So create and send * L2CAP_ConnectRsp message to our peer. */ if (ch->ident != ip->ident) NG_L2CAP_WARN( "%s: %s - channel ident and response ident do not match, scid=%d, ident=%d. " \ "Will use response ident=%d\n", __func__, NG_NODE_NAME(l2cap->node), ch->scid, ch->ident, ip->ident); /* Check result */ switch (ip->result) { case NG_L2CAP_SUCCESS: ch->state = NG_L2CAP_CONFIG; ch->cfg_state = 0; break; case NG_L2CAP_PENDING: break; default: ng_l2cap_free_chan(ch); ch = NULL; break; } /* Create L2CAP command */ cmd = ng_l2cap_new_cmd(con, ch, ip->ident, NG_L2CAP_CON_RSP, msg->header.token); if (cmd == NULL) { if (ch != NULL) ng_l2cap_free_chan(ch); error = ENOMEM; goto out; } _ng_l2cap_con_rsp(cmd->aux, cmd->ident, ip->lcid, dcid, ip->result, ip->status); if (cmd->aux == NULL) { if (ch != NULL) ng_l2cap_free_chan(ch); ng_l2cap_free_cmd(cmd); error = ENOBUFS; goto out; } /* Link command to the queue */ ng_l2cap_link_cmd(con, cmd); ng_l2cap_lp_deliver(con); out: return (error); } /* ng_l2cap_l2ca_con_rsp_req */
int ng_l2cap_l2ca_con_req(ng_l2cap_p l2cap, struct ng_mesg *msg) { ng_l2cap_l2ca_con_ip *ip = NULL; ng_l2cap_con_p con = NULL; ng_l2cap_chan_p ch = NULL; ng_l2cap_cmd_p cmd = NULL; int error = 0; /* Check message */ if (msg->header.arglen != sizeof(*ip)) { NG_L2CAP_ALERT( "%s: %s - invalid L2CA_Connect request message size, size=%d\n", __func__, NG_NODE_NAME(l2cap->node), msg->header.arglen); error = EMSGSIZE; goto out; } ip = (ng_l2cap_l2ca_con_ip *)(msg->data); /* Check if we have connection to the remote unit */ con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr, ip->linktype); if (con == NULL) { /* Submit LP_ConnectReq to the lower layer */ error = ng_l2cap_lp_con_req(l2cap, &ip->bdaddr,ip->linktype); if (error != 0) { NG_L2CAP_ERR( "%s: %s - unable to send LP_ConnectReq message, error=%d\n", __func__, NG_NODE_NAME(l2cap->node), error); goto out; } /* This should not fail */ con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr, ip->linktype); KASSERT((con != NULL), ("%s: %s - could not find connection!\n", __func__, NG_NODE_NAME(l2cap->node))); } /* * Create new empty channel descriptor. In case of any failure do * not touch connection descriptor. */ ch = ng_l2cap_new_chan(l2cap, con, ip->psm, ip->idtype); if (ch == NULL) { error = ENOMEM; goto out; } /* Now create L2CAP_ConnectReq command */ cmd = ng_l2cap_new_cmd(ch->con, ch, ng_l2cap_get_ident(con), NG_L2CAP_CON_REQ, msg->header.token); if (cmd == NULL) { ng_l2cap_free_chan(ch); error = ENOMEM; goto out; } if (cmd->ident == NG_L2CAP_NULL_IDENT) { ng_l2cap_free_cmd(cmd); ng_l2cap_free_chan(ch); error = EIO; goto out; } /* Create L2CAP command packet */ if(ip->idtype == NG_L2CAP_L2CA_IDTYPE_ATT){ _ng_l2cap_con_rsp(cmd->aux, cmd->ident, NG_L2CAP_ATT_CID, NG_L2CAP_ATT_CID, 0, 0); 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{ _ng_l2cap_con_req(cmd->aux, cmd->ident, ch->psm, ch->scid); } if (cmd->aux == NULL) { ng_l2cap_free_cmd(cmd); ng_l2cap_free_chan(ch); error = ENOBUFS; goto out; } ch->state = NG_L2CAP_W4_L2CAP_CON_RSP; /* Link command to the queue */ ng_l2cap_link_cmd(ch->con, cmd); ng_l2cap_lp_deliver(ch->con); out: return (error); } /* ng_l2cap_l2ca_con_req */