1 /* $NetBSD: bnep.c,v 1.11 2011/08/27 22:30:44 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 Iain Hibbert 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 ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __RCSID("$NetBSD: bnep.c,v 1.11 2011/08/27 22:30:44 joerg Exp $"); 30 31 #include <bluetooth.h> 32 #include <sdp.h> 33 #include <stdarg.h> 34 #include <string.h> 35 36 #include "btpand.h" 37 #include "bnep.h" 38 39 static bool bnep_recv_extension(packet_t *); 40 static size_t bnep_recv_control(channel_t *, uint8_t *, size_t, bool); 41 static size_t bnep_recv_control_command_not_understood(channel_t *, uint8_t *, size_t); 42 static size_t bnep_recv_setup_connection_req(channel_t *, uint8_t *, size_t); 43 static size_t bnep_recv_setup_connection_rsp(channel_t *, uint8_t *, size_t); 44 static size_t bnep_recv_filter_net_type_set(channel_t *, uint8_t *, size_t); 45 static size_t bnep_recv_filter_net_type_rsp(channel_t *, uint8_t *, size_t); 46 static size_t bnep_recv_filter_multi_addr_set(channel_t *, uint8_t *, size_t); 47 static size_t bnep_recv_filter_multi_addr_rsp(channel_t *, uint8_t *, size_t); 48 49 static bool bnep_pfilter(channel_t *, packet_t *); 50 static bool bnep_mfilter(channel_t *, packet_t *); 51 52 static const uint8_t NAP_UUID[] = { 53 0x00, 0x00, 0x11, 0x16, 54 0x00, 0x00, 55 0x10, 0x00, 56 0x80, 0x00, 57 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb 58 }; 59 60 static const uint8_t GN_UUID[] = { 61 0x00, 0x00, 0x11, 0x17, 62 0x00, 0x00, 63 0x10, 0x00, 64 0x80, 0x00, 65 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb, 66 }; 67 68 static const uint8_t PANU_UUID[] = { 69 0x00, 0x00, 0x11, 0x15, 70 0x00, 0x00, 71 0x10, 0x00, 72 0x80, 0x00, 73 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb 74 }; 75 76 /* 77 * receive BNEP packet 78 * return true if packet is to be forwarded 79 */ 80 bool 81 bnep_recv(packet_t *pkt) 82 { 83 size_t len; 84 uint8_t type; 85 86 if (pkt->len < 1) 87 return false; 88 89 type = pkt->ptr[0]; 90 packet_adj(pkt, 1); 91 92 switch (BNEP_TYPE(type)) { 93 case BNEP_GENERAL_ETHERNET: 94 if (pkt->len < (ETHER_ADDR_LEN * 2) + ETHER_TYPE_LEN) { 95 log_debug("dropped short packet (type 0x%2.2x)", type); 96 return false; 97 } 98 99 pkt->dst = pkt->ptr; 100 packet_adj(pkt, ETHER_ADDR_LEN); 101 pkt->src = pkt->ptr; 102 packet_adj(pkt, ETHER_ADDR_LEN); 103 pkt->type = pkt->ptr; 104 packet_adj(pkt, ETHER_TYPE_LEN); 105 break; 106 107 case BNEP_CONTROL: 108 len = bnep_recv_control(pkt->chan, pkt->ptr, pkt->len, false); 109 if (len == 0) 110 return false; 111 112 packet_adj(pkt, len); 113 break; 114 115 case BNEP_COMPRESSED_ETHERNET: 116 if (pkt->len < ETHER_TYPE_LEN) { 117 log_debug("dropped short packet (type 0x%2.2x)", type); 118 return false; 119 } 120 121 pkt->dst = pkt->chan->laddr; 122 pkt->src = pkt->chan->raddr; 123 pkt->type = pkt->ptr; 124 packet_adj(pkt, ETHER_TYPE_LEN); 125 break; 126 127 case BNEP_COMPRESSED_ETHERNET_SRC_ONLY: 128 if (pkt->len < ETHER_ADDR_LEN + ETHER_TYPE_LEN) { 129 log_debug("dropped short packet (type 0x%2.2x)", type); 130 return false; 131 } 132 133 pkt->dst = pkt->chan->laddr; 134 pkt->src = pkt->ptr; 135 packet_adj(pkt, ETHER_ADDR_LEN); 136 pkt->type = pkt->ptr; 137 packet_adj(pkt, ETHER_TYPE_LEN); 138 break; 139 140 case BNEP_COMPRESSED_ETHERNET_DST_ONLY: 141 if (pkt->len < ETHER_ADDR_LEN + ETHER_TYPE_LEN) { 142 log_debug("dropped short packet (type 0x%2.2x)", type); 143 return false; 144 } 145 146 pkt->dst = pkt->ptr; 147 packet_adj(pkt, ETHER_ADDR_LEN); 148 pkt->src = pkt->chan->raddr; 149 pkt->type = pkt->ptr; 150 packet_adj(pkt, ETHER_TYPE_LEN); 151 break; 152 153 default: 154 /* 155 * Any packet containing a reserved BNEP 156 * header packet type SHALL be dropped. 157 */ 158 159 log_debug("dropped packet with reserved type 0x%2.2x", type); 160 return false; 161 } 162 163 if (BNEP_TYPE_EXT(type) 164 && !bnep_recv_extension(pkt)) 165 return false; /* invalid extensions */ 166 167 if (BNEP_TYPE(type) == BNEP_CONTROL 168 || pkt->chan->state != CHANNEL_OPEN) 169 return false; /* no forwarding */ 170 171 if (pkt->len > ETHER_MAX_LEN) 172 log_debug("received long packet " 173 "(type=0x%2.2x, proto=0x%4.4x, len=%zu)", 174 type, be16dec(pkt->type), pkt->len); 175 176 return true; 177 } 178 179 static bool 180 bnep_recv_extension(packet_t *pkt) 181 { 182 exthdr_t *eh; 183 size_t len, size; 184 uint8_t type; 185 186 do { 187 if (pkt->len < 2) 188 return false; 189 190 type = pkt->ptr[0]; 191 size = pkt->ptr[1]; 192 193 if (pkt->len < size + 2) 194 return false; 195 196 switch (type) { 197 case BNEP_EXTENSION_CONTROL: 198 len = bnep_recv_control(pkt->chan, pkt->ptr + 2, size, true); 199 if (len != size) 200 log_err("ignored spurious data in exthdr"); 201 202 break; 203 204 default: 205 /* Unknown extension headers in data packets */ 206 /* SHALL be forwarded irrespective of any */ 207 /* network protocol or multicast filter settings */ 208 /* and any local filtering policy. */ 209 210 eh = malloc(sizeof(exthdr_t)); 211 if (eh == NULL) { 212 log_err("exthdr malloc() failed: %m"); 213 break; 214 } 215 216 eh->ptr = pkt->ptr; 217 eh->len = size; 218 STAILQ_INSERT_TAIL(&pkt->extlist, eh, next); 219 break; 220 } 221 222 packet_adj(pkt, size + 2); 223 } while (BNEP_TYPE_EXT(type)); 224 225 return true; 226 } 227 228 static size_t 229 bnep_recv_control(channel_t *chan, uint8_t *ptr, size_t size, bool isext) 230 { 231 uint8_t type; 232 size_t len; 233 234 if (size-- < 1) 235 return 0; 236 237 type = *ptr++; 238 239 switch (type) { 240 case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD: 241 len = bnep_recv_control_command_not_understood(chan, ptr, size); 242 break; 243 244 case BNEP_SETUP_CONNECTION_REQUEST: 245 if (isext) 246 return 0; /* not allowed in extension headers */ 247 248 len = bnep_recv_setup_connection_req(chan, ptr, size); 249 break; 250 251 case BNEP_SETUP_CONNECTION_RESPONSE: 252 if (isext) 253 return 0; /* not allowed in extension headers */ 254 255 len = bnep_recv_setup_connection_rsp(chan, ptr, size); 256 break; 257 258 case BNEP_FILTER_NET_TYPE_SET: 259 len = bnep_recv_filter_net_type_set(chan, ptr, size); 260 break; 261 262 case BNEP_FILTER_NET_TYPE_RESPONSE: 263 len = bnep_recv_filter_net_type_rsp(chan, ptr, size); 264 break; 265 266 case BNEP_FILTER_MULTI_ADDR_SET: 267 len = bnep_recv_filter_multi_addr_set(chan, ptr, size); 268 break; 269 270 case BNEP_FILTER_MULTI_ADDR_RESPONSE: 271 len = bnep_recv_filter_multi_addr_rsp(chan, ptr, size); 272 break; 273 274 default: 275 len = 0; 276 break; 277 } 278 279 if (len == 0) 280 bnep_send_control(chan, BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD, type); 281 282 return len; 283 } 284 285 static size_t 286 bnep_recv_control_command_not_understood(channel_t *chan, uint8_t *ptr, size_t size) 287 { 288 uint8_t type; 289 290 if (size < 1) 291 return 0; 292 293 type = *ptr++; 294 log_err("received Control Command Not Understood (0x%2.2x)", type); 295 296 /* we didn't send any reserved commands, just shut them down */ 297 chan->down(chan); 298 299 return 1; 300 } 301 302 static size_t 303 bnep_recv_setup_connection_req(channel_t *chan, uint8_t *ptr, size_t size) 304 { 305 size_t len; 306 uint8_t off; 307 int src, dst, rsp; 308 309 if (size < 1) 310 return 0; 311 312 len = *ptr++; 313 if (size < (len * 2 + 1)) 314 return 0; 315 316 if (chan->state != CHANNEL_WAIT_CONNECT_REQ 317 && chan->state != CHANNEL_OPEN) { 318 log_debug("ignored"); 319 return (len * 2 + 1); 320 } 321 322 if (len == 2) 323 off = 2; 324 else if (len == 4) 325 off = 0; 326 else if (len == 16) 327 off = 0; 328 else { 329 rsp = BNEP_SETUP_INVALID_UUID_SIZE; 330 goto done; 331 } 332 333 if (memcmp(ptr, NAP_UUID + off, len) == 0) 334 dst = SDP_SERVICE_CLASS_NAP; 335 else if (memcmp(ptr, GN_UUID + off, len) == 0) 336 dst = SDP_SERVICE_CLASS_GN; 337 else if (memcmp(ptr, PANU_UUID + off, len) == 0) 338 dst = SDP_SERVICE_CLASS_PANU; 339 else 340 dst = 0; 341 342 if (dst != service_class) { 343 rsp = BNEP_SETUP_INVALID_DST_UUID; 344 goto done; 345 } 346 347 ptr += len; 348 349 if (memcmp(ptr, NAP_UUID + off, len) == 0) 350 src = SDP_SERVICE_CLASS_NAP; 351 else if (memcmp(ptr, GN_UUID + off, len) == 0) 352 src = SDP_SERVICE_CLASS_GN; 353 else if (memcmp(ptr, PANU_UUID + off, len) == 0) 354 src = SDP_SERVICE_CLASS_PANU; 355 else 356 src = 0; 357 358 if ((dst != SDP_SERVICE_CLASS_PANU && src != SDP_SERVICE_CLASS_PANU) 359 || src == 0) { 360 rsp = BNEP_SETUP_INVALID_SRC_UUID; 361 goto done; 362 } 363 364 rsp = BNEP_SETUP_SUCCESS; 365 chan->state = CHANNEL_OPEN; 366 channel_timeout(chan, 0); 367 368 done: 369 log_debug("addr %s response 0x%2.2x", 370 ether_ntoa((struct ether_addr *)chan->raddr), rsp); 371 372 bnep_send_control(chan, BNEP_SETUP_CONNECTION_RESPONSE, rsp); 373 if (rsp == BNEP_SETUP_SUCCESS) { 374 bnep_send_control(chan, BNEP_FILTER_NET_TYPE_SET); 375 bnep_send_control(chan, BNEP_FILTER_MULTI_ADDR_SET); 376 } 377 return (len * 2 + 1); 378 } 379 380 static size_t 381 bnep_recv_setup_connection_rsp(channel_t *chan, uint8_t *ptr, size_t size) 382 { 383 int rsp; 384 385 if (size < 2) 386 return 0; 387 388 rsp = be16dec(ptr); 389 390 if (chan->state != CHANNEL_WAIT_CONNECT_RSP) { 391 log_debug("ignored"); 392 return 2; 393 } 394 395 log_debug("addr %s response 0x%2.2x", 396 ether_ntoa((struct ether_addr *)chan->raddr), rsp); 397 398 if (rsp == BNEP_SETUP_SUCCESS) { 399 chan->state = CHANNEL_OPEN; 400 channel_timeout(chan, 0); 401 bnep_send_control(chan, BNEP_FILTER_NET_TYPE_SET); 402 bnep_send_control(chan, BNEP_FILTER_MULTI_ADDR_SET); 403 } else { 404 chan->down(chan); 405 } 406 407 return 2; 408 } 409 410 static size_t 411 bnep_recv_filter_net_type_set(channel_t *chan, uint8_t *ptr, size_t size) 412 { 413 pfilter_t *pf; 414 int i, nf, rsp; 415 size_t len; 416 417 if (size < 2) 418 return 0; 419 420 len = be16dec(ptr); 421 ptr += 2; 422 423 if (size < (len + 2)) 424 return 0; 425 426 if (chan->state != CHANNEL_OPEN) { 427 log_debug("ignored"); 428 return (len + 2); 429 } 430 431 nf = len / 4; 432 if (nf > BNEP_MAX_NET_TYPE_FILTERS) { 433 rsp = BNEP_FILTER_TOO_MANY_FILTERS; 434 goto done; 435 } 436 pf = malloc(nf * sizeof(pfilter_t)); 437 if (pf == NULL) { 438 rsp = BNEP_FILTER_TOO_MANY_FILTERS; 439 goto done; 440 } 441 442 log_debug("nf = %d", nf); 443 444 for (i = 0; i < nf; i++) { 445 pf[i].start = be16dec(ptr); 446 ptr += 2; 447 pf[i].end = be16dec(ptr); 448 ptr += 2; 449 450 if (pf[i].start > pf[i].end) { 451 free(pf); 452 rsp = BNEP_FILTER_INVALID_RANGE; 453 goto done; 454 } 455 456 log_debug("pf[%d] = %#4.4x, %#4.4x", i, pf[i].start, pf[i].end); 457 } 458 459 if (chan->pfilter) 460 free(chan->pfilter); 461 462 chan->pfilter = pf; 463 chan->npfilter = nf; 464 465 rsp = BNEP_FILTER_SUCCESS; 466 467 done: 468 log_debug("addr %s response 0x%2.2x", 469 ether_ntoa((struct ether_addr *)chan->raddr), rsp); 470 471 bnep_send_control(chan, BNEP_FILTER_NET_TYPE_RESPONSE, rsp); 472 return (len + 2); 473 } 474 475 static size_t 476 bnep_recv_filter_net_type_rsp(channel_t *chan, uint8_t *ptr, size_t size) 477 { 478 int rsp; 479 480 if (size < 2) 481 return 0; 482 483 if (chan->state != CHANNEL_OPEN) { 484 log_debug("ignored"); 485 return 2; 486 } 487 488 rsp = be16dec(ptr); 489 if (rsp != BNEP_FILTER_SUCCESS) 490 log_err("filter_net_type: addr %s response 0x%2.2x", 491 ether_ntoa((struct ether_addr *)chan->raddr), rsp); 492 493 return 2; 494 } 495 496 static size_t 497 bnep_recv_filter_multi_addr_set(channel_t *chan, uint8_t *ptr, size_t size) 498 { 499 mfilter_t *mf; 500 int i, nf, rsp; 501 size_t len; 502 503 if (size < 2) 504 return 0; 505 506 len = be16dec(ptr); 507 ptr += 2; 508 509 if (size < (len + 2)) 510 return 0; 511 512 if (chan->state != CHANNEL_OPEN) { 513 log_debug("ignored"); 514 return (len + 2); 515 } 516 517 nf = len / (ETHER_ADDR_LEN * 2); 518 if (nf > BNEP_MAX_MULTI_ADDR_FILTERS) { 519 rsp = BNEP_FILTER_TOO_MANY_FILTERS; 520 goto done; 521 } 522 mf = malloc(nf * sizeof(mfilter_t)); 523 if (mf == NULL) { 524 rsp = BNEP_FILTER_TOO_MANY_FILTERS; 525 goto done; 526 } 527 528 log_debug("nf = %d", nf); 529 530 for (i = 0; i < nf; i++) { 531 memcpy(mf[i].start, ptr, ETHER_ADDR_LEN); 532 ptr += ETHER_ADDR_LEN; 533 534 memcpy(mf[i].end, ptr, ETHER_ADDR_LEN); 535 ptr += ETHER_ADDR_LEN; 536 537 if (memcmp(mf[i].start, mf[i].end, ETHER_ADDR_LEN) > 0) { 538 free(mf); 539 rsp = BNEP_FILTER_INVALID_RANGE; 540 goto done; 541 } 542 543 log_debug("pf[%d] = " 544 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " 545 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", i, 546 mf[i].start[0], mf[i].start[1], mf[i].start[2], 547 mf[i].start[3], mf[i].start[4], mf[i].start[5], 548 mf[i].end[0], mf[i].end[1], mf[i].end[2], 549 mf[i].end[3], mf[i].end[4], mf[i].end[5]); 550 } 551 552 if (chan->mfilter) 553 free(chan->mfilter); 554 555 chan->mfilter = mf; 556 chan->nmfilter = nf; 557 558 rsp = BNEP_FILTER_SUCCESS; 559 560 done: 561 log_debug("addr %s response 0x%2.2x", 562 ether_ntoa((struct ether_addr *)chan->raddr), rsp); 563 564 bnep_send_control(chan, BNEP_FILTER_MULTI_ADDR_RESPONSE, rsp); 565 return (len + 2); 566 } 567 568 static size_t 569 bnep_recv_filter_multi_addr_rsp(channel_t *chan, uint8_t *ptr, size_t size) 570 { 571 int rsp; 572 573 if (size < 2) 574 return false; 575 576 if (chan->state != CHANNEL_OPEN) { 577 log_debug("ignored"); 578 return 2; 579 } 580 581 rsp = be16dec(ptr); 582 if (rsp != BNEP_FILTER_SUCCESS) 583 log_err("filter_multi_addr: addr %s response 0x%2.2x", 584 ether_ntoa((struct ether_addr *)chan->raddr), rsp); 585 586 return 2; 587 } 588 589 void 590 bnep_send_control(channel_t *chan, uint8_t type, ...) 591 { 592 packet_t *pkt; 593 uint8_t *p; 594 va_list ap; 595 596 assert(chan->state != CHANNEL_CLOSED); 597 598 pkt = packet_alloc(chan); 599 if (pkt == NULL) 600 return; 601 602 p = pkt->ptr; 603 va_start(ap, type); 604 605 *p++ = BNEP_CONTROL; 606 *p++ = type; 607 608 switch(type) { 609 case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD: 610 *p++ = va_arg(ap, int); 611 break; 612 613 case BNEP_SETUP_CONNECTION_REQUEST: 614 *p++ = va_arg(ap, int); 615 be16enc(p, va_arg(ap, int)); 616 p += 2; 617 be16enc(p, va_arg(ap, int)); 618 p += 2; 619 break; 620 621 case BNEP_SETUP_CONNECTION_RESPONSE: 622 case BNEP_FILTER_NET_TYPE_RESPONSE: 623 case BNEP_FILTER_MULTI_ADDR_RESPONSE: 624 be16enc(p, va_arg(ap, int)); 625 p += 2; 626 break; 627 628 case BNEP_FILTER_NET_TYPE_SET: 629 case BNEP_FILTER_MULTI_ADDR_SET: 630 be16enc(p, 0); /* just clear filters for now */ 631 p += 2; 632 break; 633 634 default: 635 log_err("Can't send control type 0x%2.2x", type); 636 break; 637 } 638 639 va_end(ap); 640 pkt->len = p - pkt->ptr; 641 642 channel_put(chan, pkt); 643 packet_free(pkt); 644 } 645 646 /* 647 * BNEP send packet routine 648 * return true if packet can be removed from queue 649 */ 650 bool 651 bnep_send(channel_t *chan, packet_t *pkt) 652 { 653 struct iovec iov[2]; 654 uint8_t *p, *type, *proto; 655 exthdr_t *eh; 656 bool src, dst; 657 size_t nw; 658 659 if (pkt->type == NULL) { 660 iov[0].iov_base = pkt->ptr; 661 iov[0].iov_len = pkt->len; 662 iov[1].iov_base = NULL; 663 iov[1].iov_len = 0; 664 } else { 665 p = chan->sendbuf; 666 667 dst = (memcmp(pkt->dst, chan->raddr, ETHER_ADDR_LEN) != 0); 668 src = (memcmp(pkt->src, chan->laddr, ETHER_ADDR_LEN) != 0); 669 670 type = p; 671 p += 1; 672 673 if (dst && src) 674 *type = BNEP_GENERAL_ETHERNET; 675 else if (dst && !src) 676 *type = BNEP_COMPRESSED_ETHERNET_DST_ONLY; 677 else if (!dst && src) 678 *type = BNEP_COMPRESSED_ETHERNET_SRC_ONLY; 679 else /* (!dst && !src) */ 680 *type = BNEP_COMPRESSED_ETHERNET; 681 682 if (dst) { 683 memcpy(p, pkt->dst, ETHER_ADDR_LEN); 684 p += ETHER_ADDR_LEN; 685 } 686 687 if (src) { 688 memcpy(p, pkt->src, ETHER_ADDR_LEN); 689 p += ETHER_ADDR_LEN; 690 } 691 692 proto = p; 693 memcpy(p, pkt->type, ETHER_TYPE_LEN); 694 p += ETHER_TYPE_LEN; 695 696 STAILQ_FOREACH(eh, &pkt->extlist, next) { 697 if (p + eh->len > chan->sendbuf + chan->mtu) 698 break; 699 700 *type |= BNEP_EXT; 701 type = p; 702 703 memcpy(p, eh->ptr, eh->len); 704 p += eh->len; 705 } 706 707 *type &= ~BNEP_EXT; 708 709 iov[0].iov_base = chan->sendbuf; 710 iov[0].iov_len = (p - chan->sendbuf); 711 712 if ((chan->npfilter == 0 || bnep_pfilter(chan, pkt)) 713 && (chan->nmfilter == 0 || bnep_mfilter(chan, pkt))) { 714 iov[1].iov_base = pkt->ptr; 715 iov[1].iov_len = pkt->len; 716 } else if (be16dec(proto) == ETHERTYPE_VLAN 717 && pkt->len >= ETHER_VLAN_ENCAP_LEN) { 718 iov[1].iov_base = pkt->ptr; 719 iov[1].iov_len = ETHER_VLAN_ENCAP_LEN; 720 } else { 721 iov[1].iov_base = NULL; 722 iov[1].iov_len = 0; 723 memset(proto, 0, ETHER_TYPE_LEN); 724 } 725 } 726 727 if (iov[0].iov_len + iov[1].iov_len > chan->mtu) { 728 log_err("packet exceeded MTU (dropped)"); 729 return false; 730 } 731 732 nw = writev(chan->fd, iov, __arraycount(iov)); 733 return (nw > 0); 734 } 735 736 static bool 737 bnep_pfilter(channel_t *chan, packet_t *pkt) 738 { 739 int proto, i; 740 741 proto = be16dec(pkt->type); 742 if (proto == ETHERTYPE_VLAN) { /* IEEE 802.1Q tag header */ 743 if (pkt->len < 4) 744 return false; 745 746 proto = be16dec(pkt->ptr + 2); 747 } 748 749 for (i = 0; i < chan->npfilter; i++) { 750 if (chan->pfilter[i].start <= proto 751 && chan->pfilter[i].end >=proto) 752 return true; 753 } 754 755 return false; 756 } 757 758 static bool 759 bnep_mfilter(channel_t *chan, packet_t *pkt) 760 { 761 int i; 762 763 if (!ETHER_IS_MULTICAST(pkt->dst)) 764 return true; 765 766 for (i = 0; i < chan->nmfilter; i++) { 767 if (memcmp(pkt->dst, chan->mfilter[i].start, ETHER_ADDR_LEN) >= 0 768 && memcmp(pkt->dst, chan->mfilter[i].end, ETHER_ADDR_LEN) <= 0) 769 return true; 770 } 771 772 return false; 773 } 774