xref: /freebsd/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c (revision 053359b7f43aa87c06bef8be6d4fbea48bae4ca9)
1878ed226SJulian Elischer /*
2878ed226SJulian Elischer  * ng_l2cap_cmds.c
3c398230bSWarner Losh  */
4c398230bSWarner Losh 
5c398230bSWarner Losh /*-
6878ed226SJulian Elischer  * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
7878ed226SJulian Elischer  * All rights reserved.
8878ed226SJulian Elischer  *
9878ed226SJulian Elischer  * Redistribution and use in source and binary forms, with or without
10878ed226SJulian Elischer  * modification, are permitted provided that the following conditions
11878ed226SJulian Elischer  * are met:
12878ed226SJulian Elischer  * 1. Redistributions of source code must retain the above copyright
13878ed226SJulian Elischer  *    notice, this list of conditions and the following disclaimer.
14878ed226SJulian Elischer  * 2. Redistributions in binary form must reproduce the above copyright
15878ed226SJulian Elischer  *    notice, this list of conditions and the following disclaimer in the
16878ed226SJulian Elischer  *    documentation and/or other materials provided with the distribution.
17878ed226SJulian Elischer  *
18878ed226SJulian Elischer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19878ed226SJulian Elischer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20878ed226SJulian Elischer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21878ed226SJulian Elischer  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22878ed226SJulian Elischer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23878ed226SJulian Elischer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24878ed226SJulian Elischer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25878ed226SJulian Elischer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26878ed226SJulian Elischer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27878ed226SJulian Elischer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28878ed226SJulian Elischer  * SUCH DAMAGE.
29878ed226SJulian Elischer  *
300986ab12SMaksim Yevmenkin  * $Id: ng_l2cap_cmds.c,v 1.2 2003/09/08 19:11:45 max Exp $
31878ed226SJulian Elischer  * $FreeBSD$
32878ed226SJulian Elischer  */
33878ed226SJulian Elischer 
34878ed226SJulian Elischer #include <sys/param.h>
35878ed226SJulian Elischer #include <sys/systm.h>
36878ed226SJulian Elischer #include <sys/kernel.h>
37878ed226SJulian Elischer #include <sys/endian.h>
38878ed226SJulian Elischer #include <sys/malloc.h>
39878ed226SJulian Elischer #include <sys/mbuf.h>
40878ed226SJulian Elischer #include <sys/queue.h>
41878ed226SJulian Elischer #include <netgraph/ng_message.h>
42878ed226SJulian Elischer #include <netgraph/netgraph.h>
43b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/include/ng_bluetooth.h>
44b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/include/ng_hci.h>
45b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/include/ng_l2cap.h>
46b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/l2cap/ng_l2cap_var.h>
47b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/l2cap/ng_l2cap_cmds.h>
48b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/l2cap/ng_l2cap_evnt.h>
49b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/l2cap/ng_l2cap_llpi.h>
50b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/l2cap/ng_l2cap_ulpi.h>
51b84b10f9SMaksim Yevmenkin #include <netgraph/bluetooth/l2cap/ng_l2cap_misc.h>
52878ed226SJulian Elischer 
53878ed226SJulian Elischer /******************************************************************************
54878ed226SJulian Elischer  ******************************************************************************
55878ed226SJulian Elischer  **                    L2CAP commands processing module
56878ed226SJulian Elischer  ******************************************************************************
57878ed226SJulian Elischer  ******************************************************************************/
58878ed226SJulian Elischer 
59878ed226SJulian Elischer /*
60878ed226SJulian Elischer  * Process L2CAP command queue on connection
61878ed226SJulian Elischer  */
62878ed226SJulian Elischer 
63878ed226SJulian Elischer void
64878ed226SJulian Elischer ng_l2cap_con_wakeup(ng_l2cap_con_p con)
65878ed226SJulian Elischer {
66878ed226SJulian Elischer 	ng_l2cap_cmd_p	 cmd = NULL;
67878ed226SJulian Elischer 	struct mbuf	*m = NULL;
68878ed226SJulian Elischer 	int		 error = 0;
69878ed226SJulian Elischer 
70878ed226SJulian Elischer 	/* Find first non-pending command in the queue */
71878ed226SJulian Elischer 	TAILQ_FOREACH(cmd, &con->cmd_list, next) {
72878ed226SJulian Elischer 		KASSERT((cmd->con == con),
73878ed226SJulian Elischer ("%s: %s - invalid connection pointer!\n",
74878ed226SJulian Elischer 			__func__, NG_NODE_NAME(con->l2cap->node)));
75878ed226SJulian Elischer 
76878ed226SJulian Elischer 		if (!(cmd->flags & NG_L2CAP_CMD_PENDING))
77878ed226SJulian Elischer 			break;
78878ed226SJulian Elischer 	}
79878ed226SJulian Elischer 
80878ed226SJulian Elischer 	if (cmd == NULL)
81878ed226SJulian Elischer 		return;
82878ed226SJulian Elischer 
83878ed226SJulian Elischer 	/* Detach command packet */
84878ed226SJulian Elischer 	m = cmd->aux;
85878ed226SJulian Elischer 	cmd->aux = NULL;
86878ed226SJulian Elischer 
87878ed226SJulian Elischer 	/* Process command */
88878ed226SJulian Elischer 	switch (cmd->code) {
89878ed226SJulian Elischer 	case NG_L2CAP_DISCON_RSP:
90878ed226SJulian Elischer 	case NG_L2CAP_ECHO_RSP:
91878ed226SJulian Elischer 	case NG_L2CAP_INFO_RSP:
924301b251SMaksim Yevmenkin 		/*
934301b251SMaksim Yevmenkin 		 * Do not check return ng_l2cap_lp_send() value, because
944301b251SMaksim Yevmenkin 		 * in these cases we do not really have a graceful way out.
954301b251SMaksim Yevmenkin 		 * ECHO and INFO responses are internal to the stack and not
964301b251SMaksim Yevmenkin 		 * visible to user. REJect is just being nice to remote end
974301b251SMaksim Yevmenkin 		 * (otherwise remote end will timeout anyway). DISCON is
984301b251SMaksim Yevmenkin 		 * probably most interesting here, however, if it fails
994301b251SMaksim Yevmenkin 		 * there is nothing we can do anyway.
1004301b251SMaksim Yevmenkin 		 */
1014301b251SMaksim Yevmenkin 
1024301b251SMaksim Yevmenkin 		(void) ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
103878ed226SJulian Elischer 		ng_l2cap_unlink_cmd(cmd);
104878ed226SJulian Elischer 		ng_l2cap_free_cmd(cmd);
105878ed226SJulian Elischer 		break;
106fbc48c2bSTakanori Watanabe 	case NG_L2CAP_CMD_REJ:
107fbc48c2bSTakanori Watanabe 		(void) ng_l2cap_lp_send(con,
108fbc48c2bSTakanori Watanabe 					(con->linktype == NG_HCI_LINK_ACL)?
109fbc48c2bSTakanori Watanabe 					NG_L2CAP_SIGNAL_CID:
110fbc48c2bSTakanori Watanabe 					NG_L2CAP_LESIGNAL_CID
111fbc48c2bSTakanori Watanabe 					, m);
112fbc48c2bSTakanori Watanabe 		ng_l2cap_unlink_cmd(cmd);
113fbc48c2bSTakanori Watanabe 		ng_l2cap_free_cmd(cmd);
114fbc48c2bSTakanori Watanabe 		break;
115878ed226SJulian Elischer 
116878ed226SJulian Elischer 	case NG_L2CAP_CON_REQ:
117878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
118878ed226SJulian Elischer 		if (error != 0) {
119878ed226SJulian Elischer 			ng_l2cap_l2ca_con_rsp(cmd->ch, cmd->token,
120878ed226SJulian Elischer 				NG_L2CAP_NO_RESOURCES, 0);
121878ed226SJulian Elischer 			ng_l2cap_free_chan(cmd->ch); /* will free commands */
122878ed226SJulian Elischer 		} else
123878ed226SJulian Elischer 			ng_l2cap_command_timeout(cmd,
124878ed226SJulian Elischer 				bluetooth_l2cap_rtx_timeout());
125878ed226SJulian Elischer 		break;
126878ed226SJulian Elischer 	case NG_L2CAP_CON_RSP:
127878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
128878ed226SJulian Elischer 		ng_l2cap_unlink_cmd(cmd);
129878ed226SJulian Elischer 		if (cmd->ch != NULL) {
130878ed226SJulian Elischer 			ng_l2cap_l2ca_con_rsp_rsp(cmd->ch, cmd->token,
131878ed226SJulian Elischer 				(error == 0)? NG_L2CAP_SUCCESS :
132878ed226SJulian Elischer 					NG_L2CAP_NO_RESOURCES);
133878ed226SJulian Elischer 			if (error != 0)
134878ed226SJulian Elischer 				ng_l2cap_free_chan(cmd->ch);
135878ed226SJulian Elischer 		}
136878ed226SJulian Elischer 		ng_l2cap_free_cmd(cmd);
137878ed226SJulian Elischer 		break;
138878ed226SJulian Elischer 
139878ed226SJulian Elischer 	case NG_L2CAP_CFG_REQ:
140878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
141878ed226SJulian Elischer 		if (error != 0) {
142878ed226SJulian Elischer 			ng_l2cap_l2ca_cfg_rsp(cmd->ch, cmd->token,
143878ed226SJulian Elischer 				NG_L2CAP_NO_RESOURCES);
144878ed226SJulian Elischer 			ng_l2cap_unlink_cmd(cmd);
145878ed226SJulian Elischer 			ng_l2cap_free_cmd(cmd);
146878ed226SJulian Elischer 		} else
147878ed226SJulian Elischer 			ng_l2cap_command_timeout(cmd,
148878ed226SJulian Elischer 				bluetooth_l2cap_rtx_timeout());
149878ed226SJulian Elischer 		break;
150878ed226SJulian Elischer 
151878ed226SJulian Elischer 	case NG_L2CAP_CFG_RSP:
152878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
153878ed226SJulian Elischer 		ng_l2cap_unlink_cmd(cmd);
154878ed226SJulian Elischer 		if (cmd->ch != NULL)
155878ed226SJulian Elischer 			ng_l2cap_l2ca_cfg_rsp_rsp(cmd->ch, cmd->token,
156878ed226SJulian Elischer 				(error == 0)? NG_L2CAP_SUCCESS :
157878ed226SJulian Elischer 					NG_L2CAP_NO_RESOURCES);
158878ed226SJulian Elischer 		ng_l2cap_free_cmd(cmd);
159878ed226SJulian Elischer 		break;
160878ed226SJulian Elischer 
161878ed226SJulian Elischer 	case NG_L2CAP_DISCON_REQ:
162878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
163878ed226SJulian Elischer 		ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token,
164878ed226SJulian Elischer 			(error == 0)? NG_L2CAP_SUCCESS : NG_L2CAP_NO_RESOURCES);
165878ed226SJulian Elischer 		if (error != 0)
166878ed226SJulian Elischer 			ng_l2cap_free_chan(cmd->ch); /* XXX free channel */
167878ed226SJulian Elischer 		else
168878ed226SJulian Elischer 			ng_l2cap_command_timeout(cmd,
169878ed226SJulian Elischer 				bluetooth_l2cap_rtx_timeout());
170878ed226SJulian Elischer 		break;
171878ed226SJulian Elischer 
172878ed226SJulian Elischer 	case NG_L2CAP_ECHO_REQ:
173878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
174878ed226SJulian Elischer 		if (error != 0) {
175878ed226SJulian Elischer 			ng_l2cap_l2ca_ping_rsp(con, cmd->token,
176878ed226SJulian Elischer 					NG_L2CAP_NO_RESOURCES, NULL);
177878ed226SJulian Elischer 			ng_l2cap_unlink_cmd(cmd);
178878ed226SJulian Elischer 			ng_l2cap_free_cmd(cmd);
179878ed226SJulian Elischer 		} else
180878ed226SJulian Elischer 			ng_l2cap_command_timeout(cmd,
181878ed226SJulian Elischer 				bluetooth_l2cap_rtx_timeout());
182878ed226SJulian Elischer 		break;
183878ed226SJulian Elischer 
184878ed226SJulian Elischer 	case NG_L2CAP_INFO_REQ:
185878ed226SJulian Elischer 		error = ng_l2cap_lp_send(con, NG_L2CAP_SIGNAL_CID, m);
186878ed226SJulian Elischer 		if (error != 0) {
187878ed226SJulian Elischer 			ng_l2cap_l2ca_get_info_rsp(con, cmd->token,
188878ed226SJulian Elischer 				NG_L2CAP_NO_RESOURCES, NULL);
189878ed226SJulian Elischer 			ng_l2cap_unlink_cmd(cmd);
190878ed226SJulian Elischer 			ng_l2cap_free_cmd(cmd);
191878ed226SJulian Elischer 		} else
192878ed226SJulian Elischer 			ng_l2cap_command_timeout(cmd,
193878ed226SJulian Elischer 				bluetooth_l2cap_rtx_timeout());
194878ed226SJulian Elischer 		break;
195878ed226SJulian Elischer 
196878ed226SJulian Elischer 	case NGM_L2CAP_L2CA_WRITE: {
197878ed226SJulian Elischer 		int	length = m->m_pkthdr.len;
198878ed226SJulian Elischer 
199878ed226SJulian Elischer 		if (cmd->ch->dcid == NG_L2CAP_CLT_CID) {
200878ed226SJulian Elischer 			m = ng_l2cap_prepend(m, sizeof(ng_l2cap_clt_hdr_t));
201878ed226SJulian Elischer 			if (m == NULL)
202878ed226SJulian Elischer 				error = ENOBUFS;
203878ed226SJulian Elischer 			else
204878ed226SJulian Elischer                 		mtod(m, ng_l2cap_clt_hdr_t *)->psm =
205878ed226SJulian Elischer 							htole16(cmd->ch->psm);
206878ed226SJulian Elischer 		}
207878ed226SJulian Elischer 
208878ed226SJulian Elischer 		if (error == 0)
209878ed226SJulian Elischer 			error = ng_l2cap_lp_send(con, cmd->ch->dcid, m);
210878ed226SJulian Elischer 
211878ed226SJulian Elischer 		ng_l2cap_l2ca_write_rsp(cmd->ch, cmd->token,
212878ed226SJulian Elischer 			(error == 0)? NG_L2CAP_SUCCESS : NG_L2CAP_NO_RESOURCES,
213878ed226SJulian Elischer 			length);
214878ed226SJulian Elischer 
215878ed226SJulian Elischer 		ng_l2cap_unlink_cmd(cmd);
216878ed226SJulian Elischer 		ng_l2cap_free_cmd(cmd);
217878ed226SJulian Elischer 		} break;
218fbc48c2bSTakanori Watanabe 	case NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE:
219fbc48c2bSTakanori Watanabe 		error = ng_l2cap_lp_send(con, NG_L2CAP_LESIGNAL_CID, m);
220fbc48c2bSTakanori Watanabe 		ng_l2cap_unlink_cmd(cmd);
221fbc48c2bSTakanori Watanabe 		ng_l2cap_free_cmd(cmd);
222fbc48c2bSTakanori Watanabe 		break;
223fbc48c2bSTakanori Watanabe 	case NG_L2CAP_CMD_PARAM_UPDATE_REQUEST:
224fbc48c2bSTakanori Watanabe 		  /*TBD.*/
225878ed226SJulian Elischer 	/* XXX FIXME add other commands */
226878ed226SJulian Elischer 	default:
2270986ab12SMaksim Yevmenkin 		panic(
2280986ab12SMaksim Yevmenkin "%s: %s - unknown command code=%d\n",
2290986ab12SMaksim Yevmenkin 			__func__, NG_NODE_NAME(con->l2cap->node), cmd->code);
230878ed226SJulian Elischer 		break;
231878ed226SJulian Elischer 	}
232878ed226SJulian Elischer } /* ng_l2cap_con_wakeup */
233878ed226SJulian Elischer 
234878ed226SJulian Elischer /*
235878ed226SJulian Elischer  * We have failed to open ACL connection to the remote unit. Could be negative
236878ed226SJulian Elischer  * confirmation or timeout. So fail any "delayed" commands, notify upper layer,
237878ed226SJulian Elischer  * remove all channels and remove connection descriptor.
238878ed226SJulian Elischer  */
239878ed226SJulian Elischer 
240878ed226SJulian Elischer void
241878ed226SJulian Elischer ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result)
242878ed226SJulian Elischer {
243878ed226SJulian Elischer 	ng_l2cap_p	l2cap = con->l2cap;
244878ed226SJulian Elischer 	ng_l2cap_cmd_p	cmd = NULL;
245878ed226SJulian Elischer 	ng_l2cap_chan_p	ch = NULL;
246878ed226SJulian Elischer 
247878ed226SJulian Elischer 	NG_L2CAP_INFO(
248878ed226SJulian Elischer "%s: %s - ACL connection failed, result=%d\n",
249878ed226SJulian Elischer 		__func__, NG_NODE_NAME(l2cap->node), result);
250878ed226SJulian Elischer 
25182e1beccSMaksim Yevmenkin 	/* Connection is dying */
25282e1beccSMaksim Yevmenkin 	con->flags |= NG_L2CAP_CON_DYING;
25382e1beccSMaksim Yevmenkin 
254878ed226SJulian Elischer 	/* Clean command queue */
255878ed226SJulian Elischer 	while (!TAILQ_EMPTY(&con->cmd_list)) {
256878ed226SJulian Elischer 		cmd = TAILQ_FIRST(&con->cmd_list);
257878ed226SJulian Elischer 
258878ed226SJulian Elischer 		ng_l2cap_unlink_cmd(cmd);
259878ed226SJulian Elischer 		if(cmd->flags & NG_L2CAP_CMD_PENDING)
260878ed226SJulian Elischer 			ng_l2cap_command_untimeout(cmd);
261878ed226SJulian Elischer 
262878ed226SJulian Elischer 		KASSERT((cmd->con == con),
263878ed226SJulian Elischer ("%s: %s - invalid connection pointer!\n",
2640986ab12SMaksim Yevmenkin 			__func__, NG_NODE_NAME(l2cap->node)));
265878ed226SJulian Elischer 
266878ed226SJulian Elischer 		switch (cmd->code) {
267878ed226SJulian Elischer 		case NG_L2CAP_CMD_REJ:
268878ed226SJulian Elischer 		case NG_L2CAP_DISCON_RSP:
269878ed226SJulian Elischer 		case NG_L2CAP_ECHO_RSP:
270878ed226SJulian Elischer 		case NG_L2CAP_INFO_RSP:
271fbc48c2bSTakanori Watanabe 		case NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE:
272878ed226SJulian Elischer 			break;
273878ed226SJulian Elischer 
274878ed226SJulian Elischer 		case NG_L2CAP_CON_REQ:
275878ed226SJulian Elischer 			ng_l2cap_l2ca_con_rsp(cmd->ch, cmd->token, result, 0);
276878ed226SJulian Elischer 			break;
277878ed226SJulian Elischer 
278878ed226SJulian Elischer 		case NG_L2CAP_CON_RSP:
279878ed226SJulian Elischer 			if (cmd->ch != NULL)
280878ed226SJulian Elischer 				ng_l2cap_l2ca_con_rsp_rsp(cmd->ch, cmd->token,
281878ed226SJulian Elischer 					result);
282878ed226SJulian Elischer 			break;
283878ed226SJulian Elischer 
284878ed226SJulian Elischer 		case NG_L2CAP_CFG_REQ:
285878ed226SJulian Elischer 		case NG_L2CAP_CFG_RSP:
286878ed226SJulian Elischer 		case NGM_L2CAP_L2CA_WRITE:
287878ed226SJulian Elischer 			ng_l2cap_l2ca_discon_ind(cmd->ch);
288878ed226SJulian Elischer 			break;
289878ed226SJulian Elischer 
290878ed226SJulian Elischer 		case NG_L2CAP_DISCON_REQ:
291878ed226SJulian Elischer 			ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token,
292878ed226SJulian Elischer 				NG_L2CAP_SUCCESS);
293878ed226SJulian Elischer 			break;
294878ed226SJulian Elischer 
295878ed226SJulian Elischer 		case NG_L2CAP_ECHO_REQ:
296878ed226SJulian Elischer 			ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
297878ed226SJulian Elischer 				result, NULL);
298878ed226SJulian Elischer 			break;
299878ed226SJulian Elischer 
300878ed226SJulian Elischer 		case NG_L2CAP_INFO_REQ:
301878ed226SJulian Elischer 			ng_l2cap_l2ca_get_info_rsp(cmd->con, cmd->token,
302878ed226SJulian Elischer 				result, NULL);
303878ed226SJulian Elischer 			break;
304878ed226SJulian Elischer 
305878ed226SJulian Elischer 		/* XXX FIXME add other commands */
306878ed226SJulian Elischer 
307878ed226SJulian Elischer 		default:
3080986ab12SMaksim Yevmenkin 			panic(
3090986ab12SMaksim Yevmenkin "%s: %s - unexpected command code=%d\n",
3100986ab12SMaksim Yevmenkin 				__func__, NG_NODE_NAME(l2cap->node), cmd->code);
311878ed226SJulian Elischer 			break;
312878ed226SJulian Elischer 		}
313878ed226SJulian Elischer 
314878ed226SJulian Elischer 		if (cmd->ch != NULL)
315878ed226SJulian Elischer 			ng_l2cap_free_chan(cmd->ch);
316878ed226SJulian Elischer 
317878ed226SJulian Elischer 		ng_l2cap_free_cmd(cmd);
318878ed226SJulian Elischer 	}
319878ed226SJulian Elischer 
320878ed226SJulian Elischer 	/*
321878ed226SJulian Elischer 	 * There still might be channels (in OPEN state?) that
3227a2b450fSEitan Adler 	 * did not submit any commands, so disconnect them
323878ed226SJulian Elischer 	 */
324878ed226SJulian Elischer 
325878ed226SJulian Elischer 	LIST_FOREACH(ch, &l2cap->chan_list, next)
326878ed226SJulian Elischer 		if (ch->con == con)
327878ed226SJulian Elischer 			ng_l2cap_l2ca_discon_ind(ch);
328878ed226SJulian Elischer 
329878ed226SJulian Elischer 	/* Free connection descriptor */
330878ed226SJulian Elischer 	ng_l2cap_free_con(con);
331878ed226SJulian Elischer } /* ng_l2cap_con_fail */
332878ed226SJulian Elischer 
333878ed226SJulian Elischer /*
334878ed226SJulian Elischer  * Process L2CAP command timeout. In general - notify upper layer and destroy
335*053359b7SPedro F. Giffuni  * channel. Do not pay much attention to return code, just do our best.
336878ed226SJulian Elischer  */
337878ed226SJulian Elischer 
338878ed226SJulian Elischer void
339878ed226SJulian Elischer ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
340878ed226SJulian Elischer {
3410986ab12SMaksim Yevmenkin 	ng_l2cap_p	l2cap = NULL;
3420986ab12SMaksim Yevmenkin 	ng_l2cap_con_p	con = NULL;
3430986ab12SMaksim Yevmenkin 	ng_l2cap_cmd_p	cmd = NULL;
3440986ab12SMaksim Yevmenkin 	u_int16_t	con_handle = (arg2 & 0x0ffff);
3450986ab12SMaksim Yevmenkin 	u_int8_t	ident = ((arg2 >> 16) & 0xff);
346878ed226SJulian Elischer 
3470986ab12SMaksim Yevmenkin 	if (NG_NODE_NOT_VALID(node)) {
3480986ab12SMaksim Yevmenkin 		printf("%s: Netgraph node is not valid\n", __func__);
3490986ab12SMaksim Yevmenkin 		return;
3500986ab12SMaksim Yevmenkin 	}
3510986ab12SMaksim Yevmenkin 
3520986ab12SMaksim Yevmenkin 	l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node);
3530986ab12SMaksim Yevmenkin 
3540986ab12SMaksim Yevmenkin 	con = ng_l2cap_con_by_handle(l2cap, con_handle);
3550986ab12SMaksim Yevmenkin 	if (con == NULL) {
3560986ab12SMaksim Yevmenkin 		NG_L2CAP_ALERT(
3570986ab12SMaksim Yevmenkin "%s: %s - could not find connection, con_handle=%d\n",
3580986ab12SMaksim Yevmenkin 			__func__, NG_NODE_NAME(node), con_handle);
3590986ab12SMaksim Yevmenkin 		return;
3600986ab12SMaksim Yevmenkin 	}
3610986ab12SMaksim Yevmenkin 
3620986ab12SMaksim Yevmenkin 	cmd = ng_l2cap_cmd_by_ident(con, ident);
3630986ab12SMaksim Yevmenkin 	if (cmd == NULL) {
3640986ab12SMaksim Yevmenkin 		NG_L2CAP_ALERT(
3650986ab12SMaksim Yevmenkin "%s: %s - could not find command, con_handle=%d, ident=%d\n",
3660986ab12SMaksim Yevmenkin 			__func__, NG_NODE_NAME(node), con_handle, ident);
3670986ab12SMaksim Yevmenkin 		return;
3680986ab12SMaksim Yevmenkin 	}
369878ed226SJulian Elischer 
370878ed226SJulian Elischer 	cmd->flags &= ~NG_L2CAP_CMD_PENDING;
371878ed226SJulian Elischer 	ng_l2cap_unlink_cmd(cmd);
372878ed226SJulian Elischer 
373878ed226SJulian Elischer 	switch (cmd->code) {
374878ed226SJulian Elischer  	case NG_L2CAP_CON_REQ:
375878ed226SJulian Elischer 		ng_l2cap_l2ca_con_rsp(cmd->ch, cmd->token, NG_L2CAP_TIMEOUT, 0);
376878ed226SJulian Elischer 		ng_l2cap_free_chan(cmd->ch);
377878ed226SJulian Elischer 		break;
378878ed226SJulian Elischer 
379878ed226SJulian Elischer 	case NG_L2CAP_CFG_REQ:
380878ed226SJulian Elischer 		ng_l2cap_l2ca_cfg_rsp(cmd->ch, cmd->token, NG_L2CAP_TIMEOUT);
381878ed226SJulian Elischer 		break;
382878ed226SJulian Elischer 
383878ed226SJulian Elischer  	case NG_L2CAP_DISCON_REQ:
384878ed226SJulian Elischer 		ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token, NG_L2CAP_TIMEOUT);
385878ed226SJulian Elischer 		ng_l2cap_free_chan(cmd->ch); /* XXX free channel */
386878ed226SJulian Elischer 		break;
387878ed226SJulian Elischer 
388878ed226SJulian Elischer 	case NG_L2CAP_ECHO_REQ:
389878ed226SJulian Elischer 		/* Echo request timed out. Let the upper layer know */
390878ed226SJulian Elischer 		ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
391878ed226SJulian Elischer 			NG_L2CAP_TIMEOUT, NULL);
392878ed226SJulian Elischer 		break;
393878ed226SJulian Elischer 
394878ed226SJulian Elischer 	case NG_L2CAP_INFO_REQ:
395878ed226SJulian Elischer 		/* Info request timed out. Let the upper layer know */
396878ed226SJulian Elischer 		ng_l2cap_l2ca_get_info_rsp(cmd->con, cmd->token,
397878ed226SJulian Elischer 			NG_L2CAP_TIMEOUT, NULL);
398878ed226SJulian Elischer 		break;
399878ed226SJulian Elischer 
400878ed226SJulian Elischer 	/* XXX FIXME add other commands */
401878ed226SJulian Elischer 
402878ed226SJulian Elischer 	default:
4030986ab12SMaksim Yevmenkin 		panic(
4040986ab12SMaksim Yevmenkin "%s: %s - unexpected command code=%d\n",
4050986ab12SMaksim Yevmenkin 			__func__, NG_NODE_NAME(l2cap->node), cmd->code);
406878ed226SJulian Elischer 		break;
407878ed226SJulian Elischer 	}
408878ed226SJulian Elischer 
409878ed226SJulian Elischer 	ng_l2cap_free_cmd(cmd);
410878ed226SJulian Elischer } /* ng_l2cap_process_command_timeout */
411878ed226SJulian Elischer 
412