1/*
2 * ng_l2cap_cmds.h
3 */
4
5/*-
6 * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $Id: ng_l2cap_cmds.h,v 1.4 2003/04/01 18:15:26 max Exp $
31 * $FreeBSD$
32 */
33
34#ifndef _NETGRAPH_L2CAP_CMDS_H_
35#define _NETGRAPH_L2CAP_CMDS_H_
36
37/******************************************************************************
38 ******************************************************************************
39 **                L2CAP to L2CAP signaling command macros
40 ******************************************************************************
41 ******************************************************************************/
42
43/*
44 * Note: All L2CAP implementations are required to support minimal signaling
45 *       MTU of 48 bytes. In order to simplify things we will send one command
46 *       per one L2CAP packet. Given evrything above we can assume that one
47 *       signaling packet will fit into single mbuf.
48 */
49
50/* L2CAP_CommandRej */
51#define	_ng_l2cap_cmd_rej(_m, _ident, _reason, _mtu, _scid, _dcid)	\
52do {									\
53	struct _cmd_rej {						\
54		ng_l2cap_cmd_hdr_t	 hdr;				\
55		ng_l2cap_cmd_rej_cp	 param;				\
56		ng_l2cap_cmd_rej_data_t	 data;				\
57	} __attribute__ ((packed))	*c = NULL;			\
58									\
59	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
60	if ((_m) == NULL) 						\
61		break;							\
62									\
63	c = mtod((_m), struct _cmd_rej *);				\
64	c->hdr.code = NG_L2CAP_CMD_REJ;					\
65	c->hdr.ident = (_ident);					\
66	c->hdr.length = sizeof(c->param);				\
67									\
68	c->param.reason = htole16((_reason));				\
69									\
70	if ((_reason) == NG_L2CAP_REJ_MTU_EXCEEDED) {			\
71		c->data.mtu.mtu = htole16((_mtu));			\
72		c->hdr.length += sizeof(c->data.mtu);			\
73	} else if ((_reason) == NG_L2CAP_REJ_INVALID_CID) {		\
74		c->data.cid.scid = htole16((_scid));			\
75		c->data.cid.dcid = htole16((_dcid));			\
76		c->hdr.length += sizeof(c->data.cid);			\
77	}								\
78									\
79	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + 		\
80					c->hdr.length;			\
81									\
82	c->hdr.length = htole16(c->hdr.length);				\
83} while (0)
84
85/* L2CAP_ConnectReq */
86#define	_ng_l2cap_con_req(_m, _ident, _psm, _scid)			\
87do {									\
88	struct _con_req {						\
89		ng_l2cap_cmd_hdr_t	 hdr;				\
90		ng_l2cap_con_req_cp	 param;				\
91	} __attribute__ ((packed)) 	*c = NULL;			\
92									\
93	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
94	if ((_m) == NULL) 						\
95		break;							\
96									\
97	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
98									\
99	c = mtod((_m), struct _con_req *);				\
100	c->hdr.code = NG_L2CAP_CON_REQ;					\
101	c->hdr.ident = (_ident);					\
102	c->hdr.length = htole16(sizeof(c->param));			\
103									\
104	c->param.psm = htole16((_psm));					\
105	c->param.scid = htole16((_scid));				\
106} while (0)
107
108/* L2CAP_ConnectRsp */
109#define _ng_l2cap_con_rsp(_m, _ident, _dcid, _scid, _result, _status)	\
110do {									\
111	struct _con_rsp {						\
112		ng_l2cap_cmd_hdr_t	 hdr;				\
113		ng_l2cap_con_rsp_cp	 param;				\
114	} __attribute__ ((packed))	*c = NULL;			\
115									\
116	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
117	if ((_m) == NULL) 						\
118		break;							\
119									\
120	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
121									\
122	c = mtod((_m), struct _con_rsp *);				\
123	c->hdr.code = NG_L2CAP_CON_RSP;					\
124	c->hdr.ident = (_ident);					\
125	c->hdr.length = htole16(sizeof(c->param));			\
126									\
127	c->param.dcid = htole16((_dcid));				\
128	c->param.scid = htole16((_scid));				\
129	c->param.result = htole16((_result));				\
130	c->param.status = htole16((_status));				\
131} while (0)
132
133/* L2CAP_ConfigReq */
134#define	_ng_l2cap_cfg_req(_m, _ident, _dcid, _flags, _data)		\
135do {									\
136	struct _cfg_req {						\
137		ng_l2cap_cmd_hdr_t	 hdr;				\
138		ng_l2cap_cfg_req_cp	 param;				\
139	} __attribute__ ((packed))	*c = NULL;			\
140									\
141	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
142	if ((_m) == NULL) { 						\
143		NG_FREE_M((_data));					\
144		break;							\
145	}								\
146									\
147	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
148									\
149	c = mtod((_m), struct _cfg_req *);				\
150	c->hdr.code = NG_L2CAP_CFG_REQ;					\
151	c->hdr.ident = (_ident);					\
152	c->hdr.length = sizeof(c->param);				\
153									\
154	c->param.dcid = htole16((_dcid));				\
155	c->param.flags = htole16((_flags));				\
156	if ((_data) != NULL) {						\
157		int	l = (_data)->m_pkthdr.len;			\
158									\
159		m_cat((_m), (_data));					\
160		c->hdr.length += l;					\
161		(_m)->m_pkthdr.len += l;				\
162	}								\
163									\
164	c->hdr.length = htole16(c->hdr.length);				\
165} while (0)
166
167/* L2CAP_ConfigRsp */
168#define _ng_l2cap_cfg_rsp(_m, _ident, _scid, _flags, _result, _data)	\
169do {									\
170	struct _cfg_rsp {						\
171		ng_l2cap_cmd_hdr_t	 hdr;				\
172		ng_l2cap_cfg_rsp_cp	 param;				\
173	} __attribute__ ((packed))	*c = NULL;			\
174									\
175	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
176	if ((_m) == NULL) { 						\
177		NG_FREE_M((_data));					\
178		break;							\
179	}								\
180									\
181	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
182									\
183	c = mtod((_m), struct _cfg_rsp *);				\
184	c->hdr.code = NG_L2CAP_CFG_RSP;					\
185	c->hdr.ident = (_ident);					\
186	c->hdr.length = sizeof(c->param);				\
187									\
188	c->param.scid = htole16((_scid));				\
189	c->param.flags = htole16((_flags));				\
190	c->param.result = htole16((_result));				\
191	if ((_data) != NULL) {						\
192		int	l = (_data)->m_pkthdr.len;			\
193									\
194		m_cat((_m), (_data));					\
195		c->hdr.length += l;					\
196		(_m)->m_pkthdr.len += l;				\
197	}								\
198									\
199	c->hdr.length = htole16(c->hdr.length);				\
200} while (0)
201
202#define _ng_l2cap_cmd_urs(_m, _ident, _result)	\
203do {									\
204	struct  _cmd_urs{						\
205		ng_l2cap_cmd_hdr_t	 hdr;				\
206		uint16_t	 result;				\
207	} __attribute__ ((packed))	*c = NULL;			\
208									\
209	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
210									\
211	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
212									\
213	c = mtod((_m), struct _cmd_urs *);				\
214	c->hdr.code = NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE;		\
215	c->hdr.ident = (_ident);					\
216	c->hdr.length = sizeof(c->result);				\
217									\
218	c->result = htole16((_result));				\
219} while (0)
220
221/* Build configuration options */
222#define _ng_l2cap_build_cfg_options(_m, _mtu, _flush_timo, _flow)	\
223do {									\
224	u_int8_t	*p = NULL;					\
225									\
226	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
227	if ((_m) == NULL)						\
228		break;							\
229									\
230	(_m)->m_pkthdr.len = (_m)->m_len = 0;				\
231	p = mtod((_m), u_int8_t *);					\
232									\
233	if ((_mtu) != NULL) {						\
234		struct _cfg_opt_mtu {					\
235			ng_l2cap_cfg_opt_t	 hdr;			\
236			u_int16_t		 val;			\
237		} __attribute__ ((packed))	*o = NULL;		\
238									\
239		o = (struct _cfg_opt_mtu *) p;				\
240		o->hdr.type = NG_L2CAP_OPT_MTU;				\
241		o->hdr.length = sizeof(o->val);				\
242		o->val = htole16(*(u_int16_t *)(_mtu));			\
243									\
244		(_m)->m_pkthdr.len += sizeof(*o);			\
245		p += sizeof(*o);					\
246	}								\
247									\
248	if ((_flush_timo) != NULL) {					\
249		struct _cfg_opt_flush {					\
250			ng_l2cap_cfg_opt_t	 hdr;			\
251			u_int16_t		 val;			\
252		} __attribute__ ((packed))	*o = NULL;		\
253									\
254		o = (struct _cfg_opt_flush *) p;			\
255		o->hdr.type = NG_L2CAP_OPT_FLUSH_TIMO;			\
256		o->hdr.length = sizeof(o->val);				\
257		o->val = htole16(*(u_int16_t *)(_flush_timo));		\
258									\
259		(_m)->m_pkthdr.len += sizeof(*o);			\
260		p += sizeof(*o);					\
261	}								\
262									\
263	if ((_flow) != NULL) {						\
264		struct _cfg_opt_flow {					\
265			ng_l2cap_cfg_opt_t	 hdr;			\
266			ng_l2cap_flow_t		 val;			\
267		} __attribute__ ((packed))	*o = NULL;		\
268									\
269		o = (struct _cfg_opt_flow *) p;				\
270		o->hdr.type = NG_L2CAP_OPT_QOS;				\
271		o->hdr.length = sizeof(o->val);				\
272		o->val.flags = ((ng_l2cap_flow_p)(_flow))->flags;	\
273		o->val.service_type = ((ng_l2cap_flow_p)		\
274				(_flow))->service_type;			\
275		o->val.token_rate =					\
276			htole32(((ng_l2cap_flow_p)(_flow))->token_rate);\
277		o->val.token_bucket_size =				\
278			htole32(((ng_l2cap_flow_p)			\
279				(_flow))->token_bucket_size);		\
280		o->val.peak_bandwidth = 				\
281			htole32(((ng_l2cap_flow_p)			\
282				(_flow))->peak_bandwidth);		\
283		o->val.latency = htole32(((ng_l2cap_flow_p)		\
284				(_flow))->latency);			\
285		o->val.delay_variation = 				\
286			htole32(((ng_l2cap_flow_p)			\
287				(_flow))->delay_variation);		\
288									\
289		(_m)->m_pkthdr.len += sizeof(*o);			\
290	}								\
291									\
292	(_m)->m_len = (_m)->m_pkthdr.len;				\
293} while (0)
294
295/* L2CAP_DisconnectReq */
296#define	_ng_l2cap_discon_req(_m, _ident, _dcid, _scid)			\
297do {									\
298	struct _discon_req {						\
299		ng_l2cap_cmd_hdr_t	 hdr;				\
300		ng_l2cap_discon_req_cp	 param;				\
301	} __attribute__ ((packed))	*c = NULL;			\
302									\
303	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
304	if ((_m) == NULL)						\
305		break;							\
306									\
307	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
308									\
309	c = mtod((_m), struct _discon_req *);				\
310	c->hdr.code = NG_L2CAP_DISCON_REQ;				\
311	c->hdr.ident = (_ident);					\
312	c->hdr.length = htole16(sizeof(c->param));			\
313									\
314	c->param.dcid = htole16((_dcid));				\
315	c->param.scid = htole16((_scid));				\
316} while (0)
317
318/* L2CA_DisconnectRsp */
319#define	_ng_l2cap_discon_rsp(_m, _ident, _dcid, _scid)			\
320do {									\
321	struct _discon_rsp {						\
322		ng_l2cap_cmd_hdr_t	 hdr;				\
323		ng_l2cap_discon_rsp_cp	 param;				\
324	} __attribute__ ((packed))	*c = NULL;			\
325									\
326	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
327	if ((_m) == NULL)						\
328		break;							\
329									\
330	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
331									\
332	c = mtod((_m), struct _discon_rsp *);				\
333	c->hdr.code = NG_L2CAP_DISCON_RSP;				\
334	c->hdr.ident = (_ident);					\
335	c->hdr.length = htole16(sizeof(c->param));			\
336									\
337	c->param.dcid = htole16((_dcid));				\
338	c->param.scid = htole16((_scid));				\
339} while (0)
340
341/* L2CAP_EchoReq */
342#define	_ng_l2cap_echo_req(_m, _ident, _data, _size)			\
343do {									\
344	ng_l2cap_cmd_hdr_t	*c = NULL;				\
345									\
346	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
347	if ((_m) == NULL) 						\
348		break;							\
349									\
350	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
351									\
352	c = mtod((_m), ng_l2cap_cmd_hdr_t *);				\
353	c->code = NG_L2CAP_ECHO_REQ;					\
354	c->ident = (_ident);						\
355	c->length = 0;							\
356									\
357	if ((_data) != NULL) {						\
358		m_copyback((_m), sizeof(*c), (_size), (_data));		\
359		c->length += (_size);					\
360	}								\
361									\
362	c->length = htole16(c->length);					\
363} while (0)
364
365/* L2CAP_InfoReq */
366#define	_ng_l2cap_info_req(_m, _ident, _type)				\
367do {									\
368	struct _info_req {						\
369		ng_l2cap_cmd_hdr_t	 hdr;				\
370		ng_l2cap_info_req_cp	 param;				\
371	} __attribute__ ((packed))	*c = NULL;			\
372									\
373	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
374	if ((_m) == NULL)						\
375		break;							\
376									\
377	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
378									\
379	c = mtod((_m), struct _info_req *);				\
380	c->hdr.code = NG_L2CAP_INFO_REQ;				\
381	c->hdr.ident = (_ident);					\
382	c->hdr.length = htole16(sizeof(c->param));			\
383									\
384	c->param.type = htole16((_type));				\
385} while (0)
386
387/* L2CAP_InfoRsp */
388#define	_ng_l2cap_info_rsp(_m, _ident, _type, _result, _mtu)		\
389do {									\
390	struct _info_rsp {						\
391		ng_l2cap_cmd_hdr_t	 hdr;				\
392		ng_l2cap_info_rsp_cp	 param;				\
393		ng_l2cap_info_rsp_data_t data;				\
394	} __attribute__ ((packed))	*c = NULL;			\
395									\
396	MGETHDR((_m), M_NOWAIT, MT_DATA);				\
397	if ((_m) == NULL) 						\
398		break;							\
399									\
400	c = mtod((_m), struct _info_rsp *);				\
401	c->hdr.code = NG_L2CAP_INFO_RSP;				\
402	c->hdr.ident = (_ident);					\
403	c->hdr.length = sizeof(c->param);				\
404									\
405	c->param.type = htole16((_type));				\
406	c->param.result = htole16((_result));				\
407									\
408	if ((_result) == NG_L2CAP_SUCCESS) {				\
409		switch ((_type)) {					\
410		case NG_L2CAP_CONNLESS_MTU:				\
411			c->data.mtu.mtu = htole16((_mtu));		\
412			c->hdr.length += sizeof((c->data.mtu.mtu));	\
413			break;						\
414		}							\
415	}								\
416									\
417	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) +		\
418					c->hdr.length;			\
419									\
420	c->hdr.length = htole16(c->hdr.length);		 		\
421} while (0)
422
423void ng_l2cap_con_wakeup              (ng_l2cap_con_p);
424void ng_l2cap_con_fail                (ng_l2cap_con_p, u_int16_t);
425void ng_l2cap_process_command_timeout (node_p, hook_p, void *, int);
426
427#endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */
428
429