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) \ 52 do { \ 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) \ 87 do { \ 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) \ 110 do { \ 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) \ 135 do { \ 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) \ 169 do { \ 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) \ 203 do { \ 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) \ 223 do { \ 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) \ 297 do { \ 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) \ 320 do { \ 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) \ 343 do { \ 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) \ 367 do { \ 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) \ 389 do { \ 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 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); 426 427 #endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */ 428 429