示例#1
0
int
ng_l2cap_l2ca_cfg_rsp_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result)
{
	ng_l2cap_p			 l2cap = ch->con->l2cap;
	struct ng_mesg			*msg = NULL;
	ng_l2cap_l2ca_cfg_rsp_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_ConfigRsp 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_ConfigRsp response message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG_RSP,
		sizeof(*op), M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		msg->header.token = token;
		msg->header.flags |= NGF_RESP;

		op = (ng_l2cap_l2ca_cfg_rsp_op *)(msg->data);
		op->result = result;

		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
	}

	return (error);
} /* ng_l2cap_l2ca_cfg_rsp_rsp */
示例#2
0
int
ng_l2cap_l2ca_cfg_ind(ng_l2cap_chan_p ch)
{
	ng_l2cap_p			 l2cap = ch->con->l2cap;
	struct ng_mesg			*msg = NULL;
	ng_l2cap_l2ca_cfg_ind_ip	*ip = 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_ConfigInd message. " \
"Hook is not connected or valid, psm=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ch->psm);

		return (ENOTCONN);
	}

	/* Create and send L2CA_ConnectInd message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG_IND,
			sizeof(*ip), M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		ip = (ng_l2cap_l2ca_cfg_ind_ip *)(msg->data);
		ip->lcid = ch->scid;
		ip->omtu = ch->omtu;
		bcopy(&ch->iflow, &ip->iflow, sizeof(ip->iflow));
		ip->flush_timo = ch->flush_timo;

		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
	}

	return (error);
} /* ng_l2cap_l2ca_cfg_ind */
示例#3
0
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 */
示例#4
0
int
ng_l2cap_l2ca_qos_ind(ng_l2cap_chan_p ch)
{
	ng_l2cap_p			 l2cap = ch->con->l2cap;
	struct ng_mesg			*msg = NULL;
	ng_l2cap_l2ca_qos_ind_ip	*ip = 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_QoSViolationInd message. " \
"Hook is not connected or valid, psm=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ch->psm);

		return (ENOTCONN);
	}

	/* Create and send L2CA_QoSViolationInd message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_QOS_IND,
		sizeof(*ip), M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		ip = (ng_l2cap_l2ca_qos_ind_ip *)(msg->data);
		bcopy(&ch->con->remote, &ip->bdaddr, sizeof(ip->bdaddr));
		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
	}

	return (error);
} /* ng_l2cap_l2ca_qos_ind */
示例#5
0
int
ng_l2cap_lp_qos_req(ng_l2cap_p l2cap, u_int16_t con_handle,
		ng_l2cap_flow_p flow)
{
	struct ng_mesg		*msg = NULL;
	ng_hci_lp_qos_req_ep	*ep = NULL;
	ng_l2cap_con_p		 con = NULL;
	int			 error = 0;

	/* Verify that we have this connection */
	con = ng_l2cap_con_by_handle(l2cap, con_handle);
	if (con == NULL) {
		NG_L2CAP_ERR(
"%s: %s - unexpected LP_QoSSetupReq event. " \
"Connection does not exist, con_handle=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), con_handle);

		return (ENOENT);
	}

	/* Verify connection state */
	if (con->state != NG_L2CAP_CON_OPEN) {
		NG_L2CAP_ERR(
"%s: %s - unexpected LP_QoSSetupReq event. " \
"Invalid connection state, state=%d, con_handle=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), con->state,
			con->con_handle);

		return (EINVAL);
	}

	/* 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 send LP_QoSSetupReq event */
	NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_QOS_REQ,
		sizeof(*ep), M_NOWAIT);
	if (msg == NULL)
		return (ENOMEM);

	ep = (ng_hci_lp_qos_req_ep *) (msg->data);
	ep->con_handle = con_handle;
	ep->flags = flow->flags;
	ep->service_type = flow->service_type;
	ep->token_rate = flow->token_rate;
	ep->peak_bandwidth = flow->peak_bandwidth;
	ep->latency = flow->latency;
	ep->delay_variation = flow->delay_variation;

	NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, 0);
	
	return (error);
} /* ng_l2cap_lp_con_req */
示例#6
0
int
ng_l2cap_l2ca_con_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result,
		u_int16_t status)
{
	ng_l2cap_p		 l2cap = ch->con->l2cap;
	struct ng_mesg		*msg = NULL;
	ng_l2cap_l2ca_con_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_Connect 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_Connect response message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CON,
		sizeof(*op), M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		msg->header.token = token;
		msg->header.flags |= NGF_RESP;

		op = (ng_l2cap_l2ca_con_op *)(msg->data);
		
		/*
		 * XXX Spec. says we should only populate LCID when result == 0
		 * What about PENDING? What the heck, for now always populate
		 * LCID :)
		 */
		if(ch->scid == NG_L2CAP_ATT_CID){
			op->idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
			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{
			op->idtype = (ch->con->linktype == NG_HCI_LINK_ACL)?
				NG_L2CAP_L2CA_IDTYPE_BREDR :
				NG_L2CAP_L2CA_IDTYPE_LE;
			op->lcid = ch->scid;				
		}
		op->encryption = ch->con->encryption;
		op->result = result;
		op->status = status;

		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
	}

	return (error);
} /* ng_l2cap_l2ca_con_rsp */
示例#7
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 */
示例#8
0
int
ng_l2cap_l2ca_write_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result,
		u_int16_t length)
{
	ng_l2cap_p		 l2cap = ch->con->l2cap;
	struct ng_mesg		*msg = NULL;
	ng_l2cap_l2ca_write_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_WriteRsp message. " \
"Hook is not connected or valid, psm=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ch->psm);

		return (ENOTCONN);
	}

	/* Create and send L2CA_WriteRsp message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_WRITE,
			sizeof(*op), M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		msg->header.token = token;
		msg->header.flags |= NGF_RESP;

		op = (ng_l2cap_l2ca_write_op *)(msg->data);
		op->result = result;
		op->length = length;
		if(ch->scid == NG_L2CAP_ATT_CID){
			op->idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
			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{
			op->idtype = (ch->con->linktype == NG_HCI_LINK_ACL)?
				NG_L2CAP_L2CA_IDTYPE_BREDR :
				NG_L2CAP_L2CA_IDTYPE_LE;
			op->lcid = ch->scid;				
			
		}
		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
	}

	return (error);
} /* ng_l2cap_l2ca_write_rsp */
示例#9
0
int
ng_l2cap_l2ca_ping_rsp(ng_l2cap_con_p con, u_int32_t token, u_int16_t result,
		struct mbuf *data)
{
	ng_l2cap_p		 l2cap = con->l2cap;
	struct ng_mesg		*msg = NULL;
	ng_l2cap_l2ca_ping_op	*op = NULL;
	int			 error = 0, size = 0;

	/* Check if control hook is connected and valid */
	if (l2cap->ctl == NULL || NG_HOOK_NOT_VALID(l2cap->ctl)) {
		NG_L2CAP_WARN(
"%s: %s - unable to send L2CA_Ping response message. " \
"Hook is not connected or valid\n",
			__func__, NG_NODE_NAME(l2cap->node));
		error = ENOTCONN;
		goto out;
	}

	size = (data == NULL)? 0 : data->m_pkthdr.len;

	/* Create and send L2CA_Ping response message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_PING,
		sizeof(*op) + size, M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		msg->header.token = token;
		msg->header.flags |= NGF_RESP;

		op = (ng_l2cap_l2ca_ping_op *)(msg->data);
		op->result = result;
		bcopy(&con->remote, &op->bdaddr, sizeof(op->bdaddr));
		if (data != NULL && size > 0) {
			op->echo_size = size;
			m_copydata(data, 0, size, (caddr_t) op + sizeof(*op));
		}

		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->ctl, 0);
	}
out:
	NG_FREE_M(data);

	return (error);
} /* ng_l2cap_l2ca_ping_rsp */
void
ng_hci_node_is_up(node_p node, hook_p hook, void *arg1, int arg2)
{
	ng_hci_unit_p		 unit = NULL;
	struct ng_mesg		*msg = NULL;
	ng_hci_node_up_ep	*ep = NULL;
	int			 error;

	if (node == NULL || NG_NODE_NOT_VALID(node) ||
	    hook == NULL || NG_HOOK_NOT_VALID(hook))
		return;

	unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
	if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY)
		return;

	if (hook != unit->acl && hook != unit->sco)
		return;

	NG_MKMESSAGE(msg,NGM_HCI_COOKIE,NGM_HCI_NODE_UP,sizeof(*ep),M_NOWAIT);
	if (msg != NULL) {
		ep = (ng_hci_node_up_ep *)(msg->data);

		if (hook == unit->acl) {
			NG_HCI_BUFF_ACL_SIZE(unit->buffer, ep->pkt_size);
			NG_HCI_BUFF_ACL_TOTAL(unit->buffer, ep->num_pkts);
		} else {
			NG_HCI_BUFF_SCO_SIZE(unit->buffer, ep->pkt_size);
			NG_HCI_BUFF_SCO_TOTAL(unit->buffer, ep->num_pkts);
		} 

		bcopy(&unit->bdaddr, &ep->bdaddr, sizeof(ep->bdaddr));

		NG_SEND_MSG_HOOK(error, node, msg, hook, 0);
	} else
		error = ENOMEM;

	if (error != 0)
		NG_HCI_INFO(
"%s: %s - failed to send NODE_UP message to hook \"%s\", error=%d\n",
			__func__, NG_NODE_NAME(unit->node), 
			NG_HOOK_NAME(hook), error);
} /* ng_hci_node_is_up */
int
ng_hci_lp_con_ind(ng_hci_unit_con_p con, u_int8_t *uclass)
{
	ng_hci_unit_p		 unit = con->unit;
	struct ng_mesg		*msg = NULL;
	ng_hci_lp_con_ind_ep	*ep = NULL;
	hook_p			 hook = NULL;
	int			 error = 0;

	/*
	 * Connection_Request event is generated for specific link type.
	 * Use link_type to select upstream hook.
	 */

	if (con->link_type == NG_HCI_LINK_ACL)
		hook = unit->acl;
	else
		hook = unit->sco;

	if (hook != NULL && NG_HOOK_IS_VALID(hook)) {
		NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_IND, 
			sizeof(*ep), M_NOWAIT);
		if (msg == NULL)
			return (ENOMEM);

		ep = (ng_hci_lp_con_ind_ep *)(msg->data);
		ep->link_type = con->link_type;
		bcopy(uclass, ep->uclass, sizeof(ep->uclass));
		bcopy(&con->bdaddr, &ep->bdaddr, sizeof(ep->bdaddr));

		NG_SEND_MSG_HOOK(error, unit->node, msg, hook, 0);
	} else {
		NG_HCI_WARN(
"%s: %s - Upstream hook is not connected or not valid, hook=%p\n",
			__func__, NG_NODE_NAME(unit->node), hook);

		error = ENOTCONN;
	}

	return (error);
} /* ng_hci_lp_con_ind */
示例#12
0
int
ng_l2cap_l2ca_discon_ind(ng_l2cap_chan_p ch)
{
	ng_l2cap_p			 l2cap = ch->con->l2cap;
	struct ng_mesg			*msg = NULL;
	ng_l2cap_l2ca_discon_ind_ip	*ip = 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_DisconnectInd message. " \
"Hook is not connected or valid, psm=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ch->psm);

		return (ENOTCONN);
	}

	/* Create and send L2CA_DisconnectInd message */
	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_DISCON_IND,
		sizeof(*ip), M_NOWAIT);
	if (msg == NULL)
		error = ENOMEM;
	else {
		ip = (ng_l2cap_l2ca_discon_ind_ip *)(msg->data);
		ip->idtype = ch->idtype;
		if(ch->idtype == NG_L2CAP_L2CA_IDTYPE_ATT||
		   ch->idtype == NG_L2CAP_L2CA_IDTYPE_SMP)
			ip->lcid = ch->con->con_handle;
		else
			ip->lcid = ch->scid;
		
		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
	} 

	return (error);
} /* ng_l2cap_l2ca_discon_ind */
示例#13
0
static int
ng_vlan_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct ng_mesg *msg, *resp = NULL;
	struct ng_vlan_filter *vf;
	hook_p hook;
	struct ng_vlan_table *t;
	uintptr_t hook_data;
	int i, vlan_count;
	uint16_t vid;
	int error = 0;

	NGI_GET_MSG(item, msg);
	/* Deal with message according to cookie and command. */
	switch (msg->header.typecookie) {
	case NGM_VLAN_COOKIE:
		switch (msg->header.cmd) {
		case NGM_VLAN_ADD_FILTER:
			/* Check that message is long enough. */
			if (msg->header.arglen != sizeof(*vf)) {
				error = EINVAL;
				break;
			}
			vf = (struct ng_vlan_filter *)msg->data;
			/* Sanity check the VLAN ID value. */
#ifdef	NG_VLAN_USE_OLD_VLAN_NAME
			if (vf->vid == 0 && vf->vid != vf->vlan) {
				vf->vid = vf->vlan;
			} else if (vf->vid != 0 && vf->vlan != 0 &&
			    vf->vid != vf->vlan) {
				error = EINVAL;
				break;
			}
#endif
			if (vf->vid & ~EVL_VLID_MASK ||
			    vf->pcp & ~7 ||
			    vf->cfi & ~1) {
				error = EINVAL;
				break;
			}
			/* Check that a referenced hook exists. */
			hook = ng_findhook(node, vf->hook_name);
			if (hook == NULL) {
				error = ENOENT;
				break;
			}
			/* And is not one of the special hooks. */
			if (hook == priv->downstream_hook ||
			    hook == priv->nomatch_hook) {
				error = EINVAL;
				break;
			}
			/* And is not already in service. */
			if (IS_HOOK_VLAN_SET(NG_HOOK_PRIVATE(hook))) {
				error = EEXIST;
				break;
			}
			/* Check we don't already trap this VLAN. */
			if (priv->vlan_hook[vf->vid] != NULL) {
				error = EEXIST;
				break;
			}
			/* Link vlan and hook together. */
			NG_HOOK_SET_PRIVATE(hook,
			    (void *)(HOOK_VLAN_TAG_SET_MASK |
			    EVL_MAKETAG(vf->vid, vf->pcp, vf->cfi)));
			priv->vlan_hook[vf->vid] = hook;
			break;
		case NGM_VLAN_DEL_FILTER:
			/* Check that message is long enough. */
			if (msg->header.arglen != NG_HOOKSIZ) {
				error = EINVAL;
				break;
			}
			/* Check that hook exists and is active. */
			hook = ng_findhook(node, (char *)msg->data);
			if (hook == NULL) {
				error = ENOENT;
				break;
			}
			hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook);
			if (IS_HOOK_VLAN_SET(hook_data) == 0) {
				error = ENOENT;
				break;
			}

			KASSERT(priv->vlan_hook[EVL_VLANOFTAG(hook_data)] == hook,
			    ("%s: NGM_VLAN_DEL_FILTER: Invalid VID for Hook = %s\n",
			    __func__, (char *)msg->data));

			/* Purge a rule that refers to this hook. */
			priv->vlan_hook[EVL_VLANOFTAG(hook_data)] = NULL;
			NG_HOOK_SET_PRIVATE(hook, NULL);
			break;
		case NGM_VLAN_DEL_VID_FLT:
			/* Check that message is long enough. */
			if (msg->header.arglen != sizeof(uint16_t)) {
				error = EINVAL;
				break;
			}
			vid = (*((uint16_t *)msg->data));
			/* Sanity check the VLAN ID value. */
			if (vid & ~EVL_VLID_MASK) {
				error = EINVAL;
				break;
			}
			/* Check that hook exists and is active. */
			hook = priv->vlan_hook[vid];
			if (hook == NULL) {
				error = ENOENT;
				break;
			}
			hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook);
			if (IS_HOOK_VLAN_SET(hook_data) == 0) {
				error = ENOENT;
				break;
			}

			KASSERT(EVL_VLANOFTAG(hook_data) == vid,
			    ("%s: NGM_VLAN_DEL_VID_FLT:"
			    " Invalid VID Hook = %us, must be: %us\n",
			    __func__, (uint16_t )EVL_VLANOFTAG(hook_data),
			    vid));

			/* Purge a rule that refers to this hook. */
			priv->vlan_hook[vid] = NULL;
			NG_HOOK_SET_PRIVATE(hook, NULL);
			break;
		case NGM_VLAN_GET_TABLE:
			/* Calculate vlans. */
			vlan_count = 0;
			for (i = 0; i < (EVL_VLID_MASK + 1); i ++) {
				if (priv->vlan_hook[i] != NULL &&
				    NG_HOOK_IS_VALID(priv->vlan_hook[i]))
					vlan_count ++;
			}

			/* Allocate memory for responce. */
			NG_MKRESPONSE(resp, msg, sizeof(*t) +
			    vlan_count * sizeof(*t->filter), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}

			/* Pack data to responce. */
			t = (struct ng_vlan_table *)resp->data;
			t->n = 0;
			vf = &t->filter[0];
			for (i = 0; i < (EVL_VLID_MASK + 1); i ++) {
				hook = priv->vlan_hook[i];
				if (hook == NULL || NG_HOOK_NOT_VALID(hook))
					continue;
				hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook);
				if (IS_HOOK_VLAN_SET(hook_data) == 0)
					continue;

				KASSERT(EVL_VLANOFTAG(hook_data) == i,
				    ("%s: NGM_VLAN_GET_TABLE:"
				    " hook %s VID = %us, must be: %i\n",
				    __func__, NG_HOOK_NAME(hook),
				    (uint16_t)EVL_VLANOFTAG(hook_data), i));

#ifdef	NG_VLAN_USE_OLD_VLAN_NAME
				vf->vlan = i;
#endif
				vf->vid = i;
				vf->pcp = EVL_PRIOFTAG(hook_data);
				vf->cfi = EVL_CFIOFTAG(hook_data);
				strncpy(vf->hook_name,
				    NG_HOOK_NAME(hook), NG_HOOKSIZ);
				vf ++;
				t->n ++;
			}
			break;
		case NGM_VLAN_GET_DECAP:
			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}
			(*((uint32_t *)resp->data)) = priv->decap_enable;
			break;
		case NGM_VLAN_SET_DECAP:
			if (msg->header.arglen != sizeof(uint32_t)) {
				error = EINVAL;
				break;
			}
			priv->decap_enable = (*((uint32_t *)msg->data));
			break;
		case NGM_VLAN_GET_ENCAP:
			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}
			(*((uint32_t *)resp->data)) = priv->encap_enable;
			break;
		case NGM_VLAN_SET_ENCAP:
			if (msg->header.arglen != sizeof(uint32_t)) {
				error = EINVAL;
				break;
			}
			priv->encap_enable = (*((uint32_t *)msg->data));
			break;
		case NGM_VLAN_GET_ENCAP_PROTO:
			NG_MKRESPONSE(resp, msg, sizeof(uint16_t), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}
			(*((uint16_t *)resp->data)) = ntohs(priv->encap_proto);
			break;
		case NGM_VLAN_SET_ENCAP_PROTO:
			if (msg->header.arglen != sizeof(uint16_t)) {
				error = EINVAL;
				break;
			}
			priv->encap_proto = htons((*((uint16_t *)msg->data)));
			break;
		default: /* Unknown command. */
			error = EINVAL;
			break;
		}
		break;
	case NGM_FLOW_COOKIE:
	    {
		struct ng_mesg *copy;

		/*
		 * Flow control messages should come only
		 * from downstream.
		 */

		if (lasthook == NULL)
			break;
		if (lasthook != priv->downstream_hook)
			break;
		/* Broadcast the event to all uplinks. */
		for (i = 0; i < (EVL_VLID_MASK + 1); i ++) {
			if (priv->vlan_hook[i] == NULL)
				continue;

			NG_COPYMESSAGE(copy, msg, M_NOWAIT);
			if (copy == NULL)
				continue;
			NG_SEND_MSG_HOOK(error, node, copy,
			    priv->vlan_hook[i], 0);
		}
		break;
	    }
	default: /* Unknown type cookie. */
		error = EINVAL;
		break;
	}
	NG_RESPOND_MSG(error, node, item, resp);
	NG_FREE_MSG(msg);
	return (error);
}
示例#14
0
int
ng_l2cap_l2ca_enable_clt(ng_l2cap_p l2cap, struct ng_mesg *msg)
{
	ng_l2cap_l2ca_enable_clt_ip	*ip = NULL;
	int				 error = 0;
#if 0
 *	ng_l2cap_l2ca_enable_clt_op	*op = NULL;
 *	u_int16_t			 result; 
 * 	u_int32_t			 token;
#endif

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

		return (EMSGSIZE);
	}

	/* Process request */
	ip = (ng_l2cap_l2ca_enable_clt_ip *) (msg->data);
#if 0
 *	result = NG_L2CAP_SUCCESS;
#endif

	switch (ip->psm) 
	{
	case 0:
		/* Special case: disable/enable all PSM */
		if (ip->enable)
			l2cap->flags &= ~(NG_L2CAP_CLT_SDP_DISABLED    |
					  NG_L2CAP_CLT_RFCOMM_DISABLED |
					  NG_L2CAP_CLT_TCP_DISABLED);
		else
			l2cap->flags |= (NG_L2CAP_CLT_SDP_DISABLED    |
					 NG_L2CAP_CLT_RFCOMM_DISABLED |
					 NG_L2CAP_CLT_TCP_DISABLED);
		break;

	case NG_L2CAP_PSM_SDP:
		if (ip->enable)
			l2cap->flags &= ~NG_L2CAP_CLT_SDP_DISABLED;
		else
			l2cap->flags |= NG_L2CAP_CLT_SDP_DISABLED;
		break;

	case NG_L2CAP_PSM_RFCOMM:
		if (ip->enable)
			l2cap->flags &= ~NG_L2CAP_CLT_RFCOMM_DISABLED;
		else
			l2cap->flags |= NG_L2CAP_CLT_RFCOMM_DISABLED;
		break;

	case NG_L2CAP_PSM_TCP:
		if (ip->enable)
			l2cap->flags &= ~NG_L2CAP_CLT_TCP_DISABLED;
		else
			l2cap->flags |= NG_L2CAP_CLT_TCP_DISABLED;
		break;
	
	default:
		NG_L2CAP_ERR(
"%s: %s - unsupported PSM=%d\n", __func__, NG_NODE_NAME(l2cap->node), ip->psm);
#if 0
 *		result = NG_L2CAP_PSM_NOT_SUPPORTED;
#endif
		error = ENOTSUP;
		break;
	}

#if 0
 *	/* Create and send response message */
 * 	token = msg->header.token;
 * 	NG_FREE_MSG(msg);
 * 	NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_ENABLE_CLT,
 * 		sizeof(*op), M_NOWAIT);
 * 	if (msg == NULL)
 * 		error = ENOMEM;
 * 	else {
 * 		msg->header.token = token;
 * 		msg->header.flags |= NGF_RESP;
 * 
 * 		op = (ng_l2cap_l2ca_enable_clt_op *)(msg->data);
 * 		op->result = result;
 * 	}
 * 
 * 	/* Send response to control hook */
 * 	if (l2cap->ctl != NULL && NG_HOOK_IS_VALID(l2cap->ctl))
 * 		NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->ctl, 0);
#endif

	return (error);
} /* ng_l2cap_l2ca_enable_clt */
int
ng_hci_lp_con_cfm(ng_hci_unit_con_p con, int status)
{
	ng_hci_unit_p		 unit = con->unit;
	struct ng_mesg		*msg = NULL;
	ng_hci_lp_con_cfm_ep	*ep = NULL;
	int			 error;

	/*
	 * Check who wants to be notified. For ACL links both ACL and SCO
	 * upstream hooks will be notified (if required). For SCO links
	 * only SCO upstream hook will receive notification
	 */

	if (con->link_type == NG_HCI_LINK_ACL && 
	    con->flags & NG_HCI_CON_NOTIFY_ACL) {
		if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
			NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_CFM, 
				sizeof(*ep), M_NOWAIT);
			if (msg != NULL) {
				ep = (ng_hci_lp_con_cfm_ep *) msg->data;
				ep->status = status;
				ep->link_type = con->link_type;
				ep->con_handle = con->con_handle;
				bcopy(&con->bdaddr, &ep->bdaddr, 
					sizeof(ep->bdaddr));

				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);

		con->flags &= ~NG_HCI_CON_NOTIFY_ACL;
	}

	if (con->flags & NG_HCI_CON_NOTIFY_SCO) {
		if (unit->sco != NULL && NG_HOOK_IS_VALID(unit->sco)) {
			NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_CFM, 
				sizeof(*ep), M_NOWAIT);
			if (msg != NULL) {
				ep = (ng_hci_lp_con_cfm_ep *) msg->data;
				ep->status = status;
				ep->link_type = con->link_type;
				ep->con_handle = con->con_handle;
				bcopy(&con->bdaddr, &ep->bdaddr, 
					sizeof(ep->bdaddr));

				NG_SEND_MSG_HOOK(error, unit->node, msg,
					unit->sco, 0);
			}
		} else
			NG_HCI_INFO(
"%s: %s - SCO hook not valid, hook=%p\n",
				__func__, NG_NODE_NAME(unit->node), unit->acl);

		con->flags &= ~NG_HCI_CON_NOTIFY_SCO;
	}

	return (0);
} /* ng_hci_lp_con_cfm */
示例#16
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 */