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