1 /* 2 * ng_l2cap_cmds.h 3 */ 4 5 /*- 6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 * $FreeBSD$ 34 */ 35 36 #ifndef _NETGRAPH_L2CAP_CMDS_H_ 37 #define _NETGRAPH_L2CAP_CMDS_H_ 38 39 /****************************************************************************** 40 ****************************************************************************** 41 ** L2CAP to L2CAP signaling command macros 42 ****************************************************************************** 43 ******************************************************************************/ 44 45 /* 46 * Note: All L2CAP implementations are required to support minimal signaling 47 * MTU of 48 bytes. In order to simplify things we will send one command 48 * per one L2CAP packet. Given evrything above we can assume that one 49 * signaling packet will fit into single mbuf. 50 */ 51 52 /* L2CAP_CommandRej */ 53 #define _ng_l2cap_cmd_rej(_m, _ident, _reason, _mtu, _scid, _dcid) \ 54 do { \ 55 struct _cmd_rej { \ 56 ng_l2cap_cmd_hdr_t hdr; \ 57 ng_l2cap_cmd_rej_cp param; \ 58 ng_l2cap_cmd_rej_data_t data; \ 59 } __attribute__ ((packed)) *c = NULL; \ 60 \ 61 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 62 if ((_m) == NULL) \ 63 break; \ 64 \ 65 c = mtod((_m), struct _cmd_rej *); \ 66 c->hdr.code = NG_L2CAP_CMD_REJ; \ 67 c->hdr.ident = (_ident); \ 68 c->hdr.length = sizeof(c->param); \ 69 \ 70 c->param.reason = htole16((_reason)); \ 71 \ 72 if ((_reason) == NG_L2CAP_REJ_MTU_EXCEEDED) { \ 73 c->data.mtu.mtu = htole16((_mtu)); \ 74 c->hdr.length += sizeof(c->data.mtu); \ 75 } else if ((_reason) == NG_L2CAP_REJ_INVALID_CID) { \ 76 c->data.cid.scid = htole16((_scid)); \ 77 c->data.cid.dcid = htole16((_dcid)); \ 78 c->hdr.length += sizeof(c->data.cid); \ 79 } \ 80 \ 81 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \ 82 c->hdr.length; \ 83 \ 84 c->hdr.length = htole16(c->hdr.length); \ 85 } while (0) 86 87 /* L2CAP_ConnectReq */ 88 #define _ng_l2cap_con_req(_m, _ident, _psm, _scid) \ 89 do { \ 90 struct _con_req { \ 91 ng_l2cap_cmd_hdr_t hdr; \ 92 ng_l2cap_con_req_cp param; \ 93 } __attribute__ ((packed)) *c = NULL; \ 94 \ 95 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 96 if ((_m) == NULL) \ 97 break; \ 98 \ 99 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 100 \ 101 c = mtod((_m), struct _con_req *); \ 102 c->hdr.code = NG_L2CAP_CON_REQ; \ 103 c->hdr.ident = (_ident); \ 104 c->hdr.length = htole16(sizeof(c->param)); \ 105 \ 106 c->param.psm = htole16((_psm)); \ 107 c->param.scid = htole16((_scid)); \ 108 } while (0) 109 110 /* L2CAP_ConnectRsp */ 111 #define _ng_l2cap_con_rsp(_m, _ident, _dcid, _scid, _result, _status) \ 112 do { \ 113 struct _con_rsp { \ 114 ng_l2cap_cmd_hdr_t hdr; \ 115 ng_l2cap_con_rsp_cp param; \ 116 } __attribute__ ((packed)) *c = NULL; \ 117 \ 118 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 119 if ((_m) == NULL) \ 120 break; \ 121 \ 122 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 123 \ 124 c = mtod((_m), struct _con_rsp *); \ 125 c->hdr.code = NG_L2CAP_CON_RSP; \ 126 c->hdr.ident = (_ident); \ 127 c->hdr.length = htole16(sizeof(c->param)); \ 128 \ 129 c->param.dcid = htole16((_dcid)); \ 130 c->param.scid = htole16((_scid)); \ 131 c->param.result = htole16((_result)); \ 132 c->param.status = htole16((_status)); \ 133 } while (0) 134 135 /* L2CAP_ConfigReq */ 136 #define _ng_l2cap_cfg_req(_m, _ident, _dcid, _flags, _data) \ 137 do { \ 138 struct _cfg_req { \ 139 ng_l2cap_cmd_hdr_t hdr; \ 140 ng_l2cap_cfg_req_cp param; \ 141 } __attribute__ ((packed)) *c = NULL; \ 142 \ 143 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 144 if ((_m) == NULL) { \ 145 NG_FREE_M((_data)); \ 146 break; \ 147 } \ 148 \ 149 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 150 \ 151 c = mtod((_m), struct _cfg_req *); \ 152 c->hdr.code = NG_L2CAP_CFG_REQ; \ 153 c->hdr.ident = (_ident); \ 154 c->hdr.length = sizeof(c->param); \ 155 \ 156 c->param.dcid = htole16((_dcid)); \ 157 c->param.flags = htole16((_flags)); \ 158 if ((_data) != NULL) { \ 159 int l = (_data)->m_pkthdr.len; \ 160 \ 161 m_cat((_m), (_data)); \ 162 c->hdr.length += l; \ 163 (_m)->m_pkthdr.len += l; \ 164 } \ 165 \ 166 c->hdr.length = htole16(c->hdr.length); \ 167 } while (0) 168 169 /* L2CAP_ConfigRsp */ 170 #define _ng_l2cap_cfg_rsp(_m, _ident, _scid, _flags, _result, _data) \ 171 do { \ 172 struct _cfg_rsp { \ 173 ng_l2cap_cmd_hdr_t hdr; \ 174 ng_l2cap_cfg_rsp_cp param; \ 175 } __attribute__ ((packed)) *c = NULL; \ 176 \ 177 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 178 if ((_m) == NULL) { \ 179 NG_FREE_M((_data)); \ 180 break; \ 181 } \ 182 \ 183 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 184 \ 185 c = mtod((_m), struct _cfg_rsp *); \ 186 c->hdr.code = NG_L2CAP_CFG_RSP; \ 187 c->hdr.ident = (_ident); \ 188 c->hdr.length = sizeof(c->param); \ 189 \ 190 c->param.scid = htole16((_scid)); \ 191 c->param.flags = htole16((_flags)); \ 192 c->param.result = htole16((_result)); \ 193 if ((_data) != NULL) { \ 194 int l = (_data)->m_pkthdr.len; \ 195 \ 196 m_cat((_m), (_data)); \ 197 c->hdr.length += l; \ 198 (_m)->m_pkthdr.len += l; \ 199 } \ 200 \ 201 c->hdr.length = htole16(c->hdr.length); \ 202 } while (0) 203 204 #define _ng_l2cap_cmd_urs(_m, _ident, _result) \ 205 do { \ 206 struct _cmd_urs{ \ 207 ng_l2cap_cmd_hdr_t hdr; \ 208 uint16_t result; \ 209 } __attribute__ ((packed)) *c = NULL; \ 210 \ 211 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 212 \ 213 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 214 \ 215 c = mtod((_m), struct _cmd_urs *); \ 216 c->hdr.code = NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE; \ 217 c->hdr.ident = (_ident); \ 218 c->hdr.length = sizeof(c->result); \ 219 \ 220 c->result = htole16((_result)); \ 221 } while (0) 222 223 /* Build configuration options */ 224 #define _ng_l2cap_build_cfg_options(_m, _mtu, _flush_timo, _flow) \ 225 do { \ 226 u_int8_t *p = NULL; \ 227 \ 228 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 229 if ((_m) == NULL) \ 230 break; \ 231 \ 232 (_m)->m_pkthdr.len = (_m)->m_len = 0; \ 233 p = mtod((_m), u_int8_t *); \ 234 \ 235 if ((_mtu) != NULL) { \ 236 struct _cfg_opt_mtu { \ 237 ng_l2cap_cfg_opt_t hdr; \ 238 u_int16_t val; \ 239 } __attribute__ ((packed)) *o = NULL; \ 240 \ 241 o = (struct _cfg_opt_mtu *) p; \ 242 o->hdr.type = NG_L2CAP_OPT_MTU; \ 243 o->hdr.length = sizeof(o->val); \ 244 o->val = htole16(*(u_int16_t *)(_mtu)); \ 245 \ 246 (_m)->m_pkthdr.len += sizeof(*o); \ 247 p += sizeof(*o); \ 248 } \ 249 \ 250 if ((_flush_timo) != NULL) { \ 251 struct _cfg_opt_flush { \ 252 ng_l2cap_cfg_opt_t hdr; \ 253 u_int16_t val; \ 254 } __attribute__ ((packed)) *o = NULL; \ 255 \ 256 o = (struct _cfg_opt_flush *) p; \ 257 o->hdr.type = NG_L2CAP_OPT_FLUSH_TIMO; \ 258 o->hdr.length = sizeof(o->val); \ 259 o->val = htole16(*(u_int16_t *)(_flush_timo)); \ 260 \ 261 (_m)->m_pkthdr.len += sizeof(*o); \ 262 p += sizeof(*o); \ 263 } \ 264 \ 265 if ((_flow) != NULL) { \ 266 struct _cfg_opt_flow { \ 267 ng_l2cap_cfg_opt_t hdr; \ 268 ng_l2cap_flow_t val; \ 269 } __attribute__ ((packed)) *o = NULL; \ 270 \ 271 o = (struct _cfg_opt_flow *) p; \ 272 o->hdr.type = NG_L2CAP_OPT_QOS; \ 273 o->hdr.length = sizeof(o->val); \ 274 o->val.flags = ((ng_l2cap_flow_p)(_flow))->flags; \ 275 o->val.service_type = ((ng_l2cap_flow_p) \ 276 (_flow))->service_type; \ 277 o->val.token_rate = \ 278 htole32(((ng_l2cap_flow_p)(_flow))->token_rate);\ 279 o->val.token_bucket_size = \ 280 htole32(((ng_l2cap_flow_p) \ 281 (_flow))->token_bucket_size); \ 282 o->val.peak_bandwidth = \ 283 htole32(((ng_l2cap_flow_p) \ 284 (_flow))->peak_bandwidth); \ 285 o->val.latency = htole32(((ng_l2cap_flow_p) \ 286 (_flow))->latency); \ 287 o->val.delay_variation = \ 288 htole32(((ng_l2cap_flow_p) \ 289 (_flow))->delay_variation); \ 290 \ 291 (_m)->m_pkthdr.len += sizeof(*o); \ 292 } \ 293 \ 294 (_m)->m_len = (_m)->m_pkthdr.len; \ 295 } while (0) 296 297 /* L2CAP_DisconnectReq */ 298 #define _ng_l2cap_discon_req(_m, _ident, _dcid, _scid) \ 299 do { \ 300 struct _discon_req { \ 301 ng_l2cap_cmd_hdr_t hdr; \ 302 ng_l2cap_discon_req_cp param; \ 303 } __attribute__ ((packed)) *c = NULL; \ 304 \ 305 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 306 if ((_m) == NULL) \ 307 break; \ 308 \ 309 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 310 \ 311 c = mtod((_m), struct _discon_req *); \ 312 c->hdr.code = NG_L2CAP_DISCON_REQ; \ 313 c->hdr.ident = (_ident); \ 314 c->hdr.length = htole16(sizeof(c->param)); \ 315 \ 316 c->param.dcid = htole16((_dcid)); \ 317 c->param.scid = htole16((_scid)); \ 318 } while (0) 319 320 /* L2CA_DisconnectRsp */ 321 #define _ng_l2cap_discon_rsp(_m, _ident, _dcid, _scid) \ 322 do { \ 323 struct _discon_rsp { \ 324 ng_l2cap_cmd_hdr_t hdr; \ 325 ng_l2cap_discon_rsp_cp param; \ 326 } __attribute__ ((packed)) *c = NULL; \ 327 \ 328 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 329 if ((_m) == NULL) \ 330 break; \ 331 \ 332 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 333 \ 334 c = mtod((_m), struct _discon_rsp *); \ 335 c->hdr.code = NG_L2CAP_DISCON_RSP; \ 336 c->hdr.ident = (_ident); \ 337 c->hdr.length = htole16(sizeof(c->param)); \ 338 \ 339 c->param.dcid = htole16((_dcid)); \ 340 c->param.scid = htole16((_scid)); \ 341 } while (0) 342 343 /* L2CAP_EchoReq */ 344 #define _ng_l2cap_echo_req(_m, _ident, _data, _size) \ 345 do { \ 346 ng_l2cap_cmd_hdr_t *c = NULL; \ 347 \ 348 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 349 if ((_m) == NULL) \ 350 break; \ 351 \ 352 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 353 \ 354 c = mtod((_m), ng_l2cap_cmd_hdr_t *); \ 355 c->code = NG_L2CAP_ECHO_REQ; \ 356 c->ident = (_ident); \ 357 c->length = 0; \ 358 \ 359 if ((_data) != NULL) { \ 360 m_copyback((_m), sizeof(*c), (_size), (_data)); \ 361 c->length += (_size); \ 362 } \ 363 \ 364 c->length = htole16(c->length); \ 365 } while (0) 366 367 /* L2CAP_InfoReq */ 368 #define _ng_l2cap_info_req(_m, _ident, _type) \ 369 do { \ 370 struct _info_req { \ 371 ng_l2cap_cmd_hdr_t hdr; \ 372 ng_l2cap_info_req_cp param; \ 373 } __attribute__ ((packed)) *c = NULL; \ 374 \ 375 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 376 if ((_m) == NULL) \ 377 break; \ 378 \ 379 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ 380 \ 381 c = mtod((_m), struct _info_req *); \ 382 c->hdr.code = NG_L2CAP_INFO_REQ; \ 383 c->hdr.ident = (_ident); \ 384 c->hdr.length = htole16(sizeof(c->param)); \ 385 \ 386 c->param.type = htole16((_type)); \ 387 } while (0) 388 389 /* L2CAP_InfoRsp */ 390 #define _ng_l2cap_info_rsp(_m, _ident, _type, _result, _mtu) \ 391 do { \ 392 struct _info_rsp { \ 393 ng_l2cap_cmd_hdr_t hdr; \ 394 ng_l2cap_info_rsp_cp param; \ 395 ng_l2cap_info_rsp_data_t data; \ 396 } __attribute__ ((packed)) *c = NULL; \ 397 \ 398 MGETHDR((_m), M_NOWAIT, MT_DATA); \ 399 if ((_m) == NULL) \ 400 break; \ 401 \ 402 c = mtod((_m), struct _info_rsp *); \ 403 c->hdr.code = NG_L2CAP_INFO_RSP; \ 404 c->hdr.ident = (_ident); \ 405 c->hdr.length = sizeof(c->param); \ 406 \ 407 c->param.type = htole16((_type)); \ 408 c->param.result = htole16((_result)); \ 409 \ 410 if ((_result) == NG_L2CAP_SUCCESS) { \ 411 switch ((_type)) { \ 412 case NG_L2CAP_CONNLESS_MTU: \ 413 c->data.mtu.mtu = htole16((_mtu)); \ 414 c->hdr.length += sizeof((c->data.mtu.mtu)); \ 415 break; \ 416 } \ 417 } \ 418 \ 419 (_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \ 420 c->hdr.length; \ 421 \ 422 c->hdr.length = htole16(c->hdr.length); \ 423 } while (0) 424 425 void ng_l2cap_con_wakeup (ng_l2cap_con_p); 426 void ng_l2cap_con_fail (ng_l2cap_con_p, u_int16_t); 427 void ng_l2cap_process_command_timeout (node_p, hook_p, void *, int); 428 429 #endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */ 430 431