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