6 * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
30 * $Id: ng_l2cap_cmds.h,v 1.4 2003/04/01 18:15:26 max Exp $
34 #ifndef _NETGRAPH_L2CAP_CMDS_H_
35 #define _NETGRAPH_L2CAP_CMDS_H_
37 /******************************************************************************
38 ******************************************************************************
39 ** L2CAP to L2CAP signaling command macros
40 ******************************************************************************
41 ******************************************************************************/
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.
50 /* L2CAP_CommandRej */
51 #define _ng_l2cap_cmd_rej(_m, _ident, _reason, _mtu, _scid, _dcid) \
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; \
59 MGETHDR((_m), M_NOWAIT, MT_DATA); \
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); \
68 c->param.reason = htole16((_reason)); \
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); \
79 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \
82 c->hdr.length = htole16(c->hdr.length); \
85 /* L2CAP_ConnectReq */
86 #define _ng_l2cap_con_req(_m, _ident, _psm, _scid) \
89 ng_l2cap_cmd_hdr_t hdr; \
90 ng_l2cap_con_req_cp param; \
91 } __attribute__ ((packed)) *c = NULL; \
93 MGETHDR((_m), M_NOWAIT, MT_DATA); \
97 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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)); \
104 c->param.psm = htole16((_psm)); \
105 c->param.scid = htole16((_scid)); \
108 /* L2CAP_ConnectRsp */
109 #define _ng_l2cap_con_rsp(_m, _ident, _dcid, _scid, _result, _status) \
112 ng_l2cap_cmd_hdr_t hdr; \
113 ng_l2cap_con_rsp_cp param; \
114 } __attribute__ ((packed)) *c = NULL; \
116 MGETHDR((_m), M_NOWAIT, MT_DATA); \
120 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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)); \
127 c->param.dcid = htole16((_dcid)); \
128 c->param.scid = htole16((_scid)); \
129 c->param.result = htole16((_result)); \
130 c->param.status = htole16((_status)); \
133 /* L2CAP_ConfigReq */
134 #define _ng_l2cap_cfg_req(_m, _ident, _dcid, _flags, _data) \
137 ng_l2cap_cmd_hdr_t hdr; \
138 ng_l2cap_cfg_req_cp param; \
139 } __attribute__ ((packed)) *c = NULL; \
141 MGETHDR((_m), M_NOWAIT, MT_DATA); \
142 if ((_m) == NULL) { \
143 NG_FREE_M((_data)); \
147 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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); \
154 c->param.dcid = htole16((_dcid)); \
155 c->param.flags = htole16((_flags)); \
156 if ((_data) != NULL) { \
157 int l = (_data)->m_pkthdr.len; \
159 m_cat((_m), (_data)); \
160 c->hdr.length += l; \
161 (_m)->m_pkthdr.len += l; \
164 c->hdr.length = htole16(c->hdr.length); \
167 /* L2CAP_ConfigRsp */
168 #define _ng_l2cap_cfg_rsp(_m, _ident, _scid, _flags, _result, _data) \
171 ng_l2cap_cmd_hdr_t hdr; \
172 ng_l2cap_cfg_rsp_cp param; \
173 } __attribute__ ((packed)) *c = NULL; \
175 MGETHDR((_m), M_NOWAIT, MT_DATA); \
176 if ((_m) == NULL) { \
177 NG_FREE_M((_data)); \
181 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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); \
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; \
194 m_cat((_m), (_data)); \
195 c->hdr.length += l; \
196 (_m)->m_pkthdr.len += l; \
199 c->hdr.length = htole16(c->hdr.length); \
202 #define _ng_l2cap_cmd_urs(_m, _ident, _result) \
205 ng_l2cap_cmd_hdr_t hdr; \
207 } __attribute__ ((packed)) *c = NULL; \
209 MGETHDR((_m), M_NOWAIT, MT_DATA); \
211 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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); \
218 c->result = htole16((_result)); \
221 /* Build configuration options */
222 #define _ng_l2cap_build_cfg_options(_m, _mtu, _flush_timo, _flow) \
224 u_int8_t *p = NULL; \
226 MGETHDR((_m), M_NOWAIT, MT_DATA); \
230 (_m)->m_pkthdr.len = (_m)->m_len = 0; \
231 p = mtod((_m), u_int8_t *); \
233 if ((_mtu) != NULL) { \
234 struct _cfg_opt_mtu { \
235 ng_l2cap_cfg_opt_t hdr; \
237 } __attribute__ ((packed)) *o = NULL; \
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)); \
244 (_m)->m_pkthdr.len += sizeof(*o); \
248 if ((_flush_timo) != NULL) { \
249 struct _cfg_opt_flush { \
250 ng_l2cap_cfg_opt_t hdr; \
252 } __attribute__ ((packed)) *o = NULL; \
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)); \
259 (_m)->m_pkthdr.len += sizeof(*o); \
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; \
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); \
289 (_m)->m_pkthdr.len += sizeof(*o); \
292 (_m)->m_len = (_m)->m_pkthdr.len; \
295 /* L2CAP_DisconnectReq */
296 #define _ng_l2cap_discon_req(_m, _ident, _dcid, _scid) \
298 struct _discon_req { \
299 ng_l2cap_cmd_hdr_t hdr; \
300 ng_l2cap_discon_req_cp param; \
301 } __attribute__ ((packed)) *c = NULL; \
303 MGETHDR((_m), M_NOWAIT, MT_DATA); \
307 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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)); \
314 c->param.dcid = htole16((_dcid)); \
315 c->param.scid = htole16((_scid)); \
318 /* L2CA_DisconnectRsp */
319 #define _ng_l2cap_discon_rsp(_m, _ident, _dcid, _scid) \
321 struct _discon_rsp { \
322 ng_l2cap_cmd_hdr_t hdr; \
323 ng_l2cap_discon_rsp_cp param; \
324 } __attribute__ ((packed)) *c = NULL; \
326 MGETHDR((_m), M_NOWAIT, MT_DATA); \
330 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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)); \
337 c->param.dcid = htole16((_dcid)); \
338 c->param.scid = htole16((_scid)); \
342 #define _ng_l2cap_echo_req(_m, _ident, _data, _size) \
344 ng_l2cap_cmd_hdr_t *c = NULL; \
346 MGETHDR((_m), M_NOWAIT, MT_DATA); \
350 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
352 c = mtod((_m), ng_l2cap_cmd_hdr_t *); \
353 c->code = NG_L2CAP_ECHO_REQ; \
354 c->ident = (_ident); \
357 if ((_data) != NULL) { \
358 m_copyback((_m), sizeof(*c), (_size), (_data)); \
359 c->length += (_size); \
362 c->length = htole16(c->length); \
366 #define _ng_l2cap_info_req(_m, _ident, _type) \
369 ng_l2cap_cmd_hdr_t hdr; \
370 ng_l2cap_info_req_cp param; \
371 } __attribute__ ((packed)) *c = NULL; \
373 MGETHDR((_m), M_NOWAIT, MT_DATA); \
377 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
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)); \
384 c->param.type = htole16((_type)); \
388 #define _ng_l2cap_info_rsp(_m, _ident, _type, _result, _mtu) \
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; \
396 MGETHDR((_m), M_NOWAIT, MT_DATA); \
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); \
405 c->param.type = htole16((_type)); \
406 c->param.result = htole16((_result)); \
408 if ((_result) == NG_L2CAP_SUCCESS) { \
410 case NG_L2CAP_CONNLESS_MTU: \
411 c->data.mtu.mtu = htole16((_mtu)); \
412 c->hdr.length += sizeof((c->data.mtu.mtu)); \
417 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \
420 c->hdr.length = htole16(c->hdr.length); \
423 void ng_l2cap_con_wakeup (ng_l2cap_con_p);
424 void ng_l2cap_con_fail (ng_l2cap_con_p, u_int16_t);
425 void ng_l2cap_process_command_timeout (node_p, hook_p, void *, int);
427 #endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */