Example #1
0
int
ng_l2cap_lp_con_cfm(ng_l2cap_p l2cap, struct ng_mesg *msg)
{
	ng_hci_lp_con_cfm_ep	*ep = NULL;
	ng_l2cap_con_p		 con = NULL;
	int			 error = 0;

	/* Check message */
	if (msg->header.arglen != sizeof(*ep)) {
		NG_L2CAP_ALERT(
"%s: %s - invalid LP_ConnectCfm[Neg] message size\n",
			__func__, NG_NODE_NAME(l2cap->node));
		error = EMSGSIZE;
		goto out;
	}

	ep = (ng_hci_lp_con_cfm_ep *) (msg->data);

	/* Check if we have requested/accepted this connection */
	con = ng_l2cap_con_by_addr(l2cap, &ep->bdaddr);
	if (con == NULL) {
		NG_L2CAP_ERR(
"%s: %s - unexpected LP_ConnectCfm event. Connection does not exist\n",
			__func__, NG_NODE_NAME(l2cap->node));
		error = ENOENT;
		goto out;
	}

	/* Check connection state */
	if (con->state != NG_L2CAP_W4_LP_CON_CFM) {
		NG_L2CAP_ALERT(
"%s: %s - unexpected LP_ConnectCfm 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;
	}

	/*
	 * Looks like it is our confirmation. It is safe now to cancel 
	 * connection timer and notify upper layer. If timeout already
	 * happened then ignore connection confirmation and let timeout
	 * handle that.
 	 */

	if ((error = ng_l2cap_lp_untimeout(con)) != 0)
		goto out;

	if (ep->status == 0) {
		con->state = NG_L2CAP_CON_OPEN;
		con->con_handle = ep->con_handle;
		ng_l2cap_lp_deliver(con);
	} else /* Negative confirmation - remove connection descriptor */
		ng_l2cap_con_fail(con, ep->status);
out:
	return (error);
} /* ng_l2cap_lp_con_cfm */
Example #2
0
int
ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr)
{
	struct ng_mesg		*msg = NULL;
	ng_hci_lp_con_req_ep	*ep = NULL;
	ng_l2cap_con_p		 con = NULL;
	int			 error = 0;

	/* Verify that we DO NOT have connection to the remote unit */
	con = ng_l2cap_con_by_addr(l2cap, bdaddr);
	if (con != NULL) {
		NG_L2CAP_ALERT(
"%s: %s - unexpected LP_ConnectReq event. " \
"Connection already exists, state=%d, con_handle=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), con->state, 
			con->con_handle);

		return (EEXIST);
	}

	/* Check if lower layer protocol is still connected */
	if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) {
		NG_L2CAP_ERR(
"%s: %s - hook \"%s\" is not connected or valid\n",
			__func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI);

		return (ENOTCONN);
	}

	/* Create and intialize new connection descriptor */
	con = ng_l2cap_new_con(l2cap, bdaddr);
	if (con == NULL)
		return (ENOMEM);

	/* Create and send LP_ConnectReq event */
	NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_REQ,
		sizeof(*ep), M_NOWAIT);
	if (msg == NULL) {
		ng_l2cap_free_con(con);

		return (ENOMEM);
	}

	ep = (ng_hci_lp_con_req_ep *) (msg->data);
	bcopy(bdaddr, &ep->bdaddr, sizeof(ep->bdaddr));
	ep->link_type = NG_HCI_LINK_ACL;

	con->state = NG_L2CAP_W4_LP_CON_CFM;
	ng_l2cap_lp_timeout(con);

	NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, NULL);
	if (error != 0)
		ng_l2cap_free_con(con); /* will remove timeout */
	
	return (error);
} /* ng_l2cap_lp_con_req */
Example #3
0
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);
	if (con == NULL) {
		/* Submit LP_ConnectReq to the lower layer */
		error = ng_l2cap_lp_con_req(l2cap, &ip->bdaddr);
		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);
		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);
	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 */
	_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 */
Example #4
0
int
ng_l2cap_l2ca_get_info_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
{
	ng_l2cap_l2ca_get_info_ip	*ip = NULL;
	ng_l2cap_con_p			 con = NULL;
	ng_l2cap_cmd_p			 cmd = NULL;
	int				 error = 0;

	/* Verify message */
	if (msg->header.arglen != sizeof(*ip)) {
		NG_L2CAP_ALERT(
"%s: %s - invalid L2CA_GetInfo request message size, size=%d\n",
			__func__, NG_NODE_NAME(l2cap->node),
			msg->header.arglen);
		error = EMSGSIZE;
		goto out;
	}

	ip = (ng_l2cap_l2ca_get_info_ip *)(msg->data);

	/* Check if we have connection to the unit */
	con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
	if (con == NULL) {
		/* Submit LP_ConnectReq to the lower layer */
		error = ng_l2cap_lp_con_req(l2cap, &ip->bdaddr);
		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);
		KASSERT((con != NULL),
("%s: %s - could not find connection!\n", __func__, NG_NODE_NAME(l2cap->node)));
	}

	/* Create L2CAP command descriptor */
	cmd = ng_l2cap_new_cmd(con, NULL, ng_l2cap_get_ident(con),
			NG_L2CAP_INFO_REQ, msg->header.token);
	if (cmd == NULL) {
		error = ENOMEM;
		goto out;
	}

	if (cmd->ident == NG_L2CAP_NULL_IDENT) {
		ng_l2cap_free_cmd(cmd);
		error = EIO;
		goto out;
	}

	/* Create L2CAP command packet */
	_ng_l2cap_info_req(cmd->aux, cmd->ident, ip->info_type);
	if (cmd->aux == NULL) {
		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_get_info_req */
Example #5
0
int
ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, struct ng_mesg *msg)
{
	ng_hci_lp_con_ind_ep	*ep = NULL;
	ng_hci_lp_con_rsp_ep	*rp = NULL;
	struct ng_mesg		*rsp = NULL;
	ng_l2cap_con_p		 con = NULL;
	int			 error = 0;

	/* Check message */
	if (msg->header.arglen != sizeof(*ep)) {
		NG_L2CAP_ALERT(
"%s: %s - invalid LP_ConnectInd message size\n",
			__func__, NG_NODE_NAME(l2cap->node));

		return (EMSGSIZE);
	}

 	ep = (ng_hci_lp_con_ind_ep *) (msg->data);

	/* Make sure we have only one connection to the remote unit */
	con = ng_l2cap_con_by_addr(l2cap, &ep->bdaddr);
	if (con != NULL) {
		NG_L2CAP_ALERT(
"%s: %s - unexpected LP_ConnectInd event. " \
"Connection already exists, state=%d, con_handle=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), con->state, 
			con->con_handle);

		return (EEXIST);
	}

	/* Check if lower layer protocol is still connected */
	if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) {
		NG_L2CAP_ERR(
"%s: %s - hook \"%s\" is not connected or valid",
			__func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI);

		return (ENOTCONN);
	}

	/* Create and intialize new connection descriptor */
	con = ng_l2cap_new_con(l2cap, &ep->bdaddr);
	if (con == NULL)
		return (ENOMEM);

	/* Create and send LP_ConnectRsp event */
	NG_MKMESSAGE(rsp, NGM_HCI_COOKIE, NGM_HCI_LP_CON_RSP,
		sizeof(*rp), M_NOWAIT);
	if (rsp == NULL) {
		ng_l2cap_free_con(con);

		return (ENOMEM);
	}

	rp = (ng_hci_lp_con_rsp_ep *)(rsp->data);
	rp->status = 0x00; /* accept connection */
	rp->link_type = NG_HCI_LINK_ACL;
	bcopy(&ep->bdaddr, &rp->bdaddr, sizeof(rp->bdaddr));

	con->state = NG_L2CAP_W4_LP_CON_CFM;
	ng_l2cap_lp_timeout(con);

	NG_SEND_MSG_HOOK(error, l2cap->node, rsp, l2cap->hci, 0);
	if (error != 0) {
		if (ng_l2cap_lp_untimeout(con) == 0)
			ng_l2cap_free_con(con);

		/*
		 * Do not free connection if ng_l2cap_lp_untimeout() failed
		 * let timeout handler deal with it. Always return error to
		 * the caller.
		 */
	}

	return (error);
} /* ng_l2cap_lp_con_ind */