1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2000-2002 Maxim Krasnyansky <maxk (at) qualcomm.com> 6 * Copyright (C) 2003-2007 Marcel Holtmann <marcel (at) holtmann.org> 7 * 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include <config.h> 27 #endif 28 29 #include <stdio.h> 30 #include <errno.h> 31 #include <unistd.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <netinet/in.h> 38 39 #include <bluetooth/bluetooth.h> 40 #include <bluetooth/hci.h> 41 #include <bluetooth/l2cap.h> 42 43 #include "parser.h" 44 #include "sdp.h" 45 46 typedef struct { 47 uint16_t handle; 48 struct frame frm; 49 } handle_info; 50 #define HANDLE_TABLE_SIZE 10 51 52 static handle_info handle_table[HANDLE_TABLE_SIZE]; 53 54 typedef struct { 55 uint16_t handle; 56 uint16_t cid; 57 uint16_t psm; 58 uint16_t num; 59 uint8_t mode; 60 } cid_info; 61 #define CID_TABLE_SIZE 20 62 63 static cid_info cid_table[2][CID_TABLE_SIZE]; 64 65 #define SCID cid_table[0] 66 #define DCID cid_table[1] 67 68 static struct frame *add_handle(uint16_t handle) 69 { 70 register handle_info *t = handle_table; 71 register int i; 72 73 for (i = 0; i < HANDLE_TABLE_SIZE; i++) 74 if (!t[i].handle) { 75 t[i].handle = handle; 76 return &t[i].frm; 77 } 78 return NULL; 79 } 80 81 static struct frame *get_frame(uint16_t handle) 82 { 83 register handle_info *t = handle_table; 84 register int i; 85 86 for (i = 0; i < HANDLE_TABLE_SIZE; i++) 87 if (t[i].handle == handle) 88 return &t[i].frm; 89 90 return add_handle(handle); 91 } 92 93 static void add_cid(int in, uint16_t handle, uint16_t cid, uint16_t psm) 94 { 95 register cid_info *table = cid_table[in]; 96 register int i, pos = -1; 97 uint16_t num = 1; 98 99 for (i = 0; i < CID_TABLE_SIZE; i++) { 100 if ((pos < 0 && !table[i].cid) || table[i].cid == cid) 101 pos = i; 102 if (table[i].psm == psm) 103 num++; 104 } 105 106 if (pos >= 0) { 107 table[pos].handle = handle; 108 table[pos].cid = cid; 109 table[pos].psm = psm; 110 table[pos].num = num; 111 table[pos].mode = 0; 112 } 113 } 114 115 static void del_cid(int in, uint16_t dcid, uint16_t scid) 116 { 117 register int t, i; 118 uint16_t cid[2]; 119 120 if (!in) { 121 cid[0] = dcid; 122 cid[1] = scid; 123 } else { 124 cid[0] = scid; 125 cid[1] = dcid; 126 } 127 128 for (t = 0; t < 2; t++) { 129 for (i = 0; i < CID_TABLE_SIZE; i++) 130 if (cid_table[t][i].cid == cid[t]) { 131 cid_table[t][i].handle = 0; 132 cid_table[t][i].cid = 0; 133 cid_table[t][i].psm = 0; 134 cid_table[t][i].num = 0; 135 cid_table[t][i].mode = 0; 136 break; 137 } 138 } 139 } 140 141 static void del_handle(uint16_t handle) 142 { 143 register int t, i; 144 145 for (t = 0; t < 2; t++) { 146 for (i = 0; i < CID_TABLE_SIZE; i++) 147 if (cid_table[t][i].handle == handle) { 148 cid_table[t][i].handle = 0; 149 cid_table[t][i].cid = 0; 150 cid_table[t][i].psm = 0; 151 cid_table[t][i].num = 0; 152 cid_table[t][i].mode = 0; 153 break; 154 } 155 } 156 } 157 static uint16_t get_psm(int in, uint16_t cid) 158 { 159 register cid_info *table = cid_table[in]; 160 register int i; 161 162 for (i = 0; i < CID_TABLE_SIZE; i++) 163 if (table[i].cid == cid) 164 return table[i].psm; 165 return parser.defpsm; 166 } 167 168 static uint16_t get_num(int in, uint16_t cid) 169 { 170 register cid_info *table = cid_table[in]; 171 register int i; 172 173 for (i = 0; i < CID_TABLE_SIZE; i++) 174 if (table[i].cid == cid) 175 return table[i].num; 176 return 0; 177 } 178 179 static void set_mode(int in, uint16_t cid, uint8_t mode) 180 { 181 register cid_info *table = cid_table[in]; 182 register int i; 183 184 for (i = 0; i < CID_TABLE_SIZE; i++) 185 if (table[i].cid == cid) 186 table[i].mode = mode; 187 } 188 189 static uint8_t get_mode(int in, uint16_t cid) 190 { 191 register cid_info *table = cid_table[in]; 192 register int i; 193 194 for (i = 0; i < CID_TABLE_SIZE; i++) 195 if (table[i].cid == cid) 196 return table[i].mode; 197 return 0; 198 } 199 200 static uint32_t get_val(uint8_t *ptr, uint8_t len) 201 { 202 switch (len) { 203 case 1: 204 return *ptr; 205 case 2: 206 return btohs(bt_get_unaligned((uint16_t *) ptr)); 207 case 4: 208 return btohl(bt_get_unaligned((uint32_t *) ptr)); 209 } 210 return 0; 211 } 212 213 static char *reason2str(uint16_t reason) 214 { 215 switch (reason) { 216 case 0x0000: 217 return "Command not understood"; 218 case 0x0001: 219 return "Signalling MTU exceeded"; 220 case 0x0002: 221 return "Invalid CID in request"; 222 default: 223 return "Reserved"; 224 } 225 } 226 227 static char *connresult2str(uint16_t result) 228 { 229 switch (result) { 230 case 0x0000: 231 return "Connection successful"; 232 case 0x0001: 233 return "Connection pending"; 234 case 0x0002: 235 return "Connection refused - PSM not supported"; 236 case 0x0003: 237 return "Connection refused - security block"; 238 case 0x0004: 239 return "Connection refused - no resources available"; 240 default: 241 return "Reserved"; 242 } 243 } 244 245 static char *status2str(uint16_t status) 246 { 247 switch (status) { 248 case 0x0000: 249 return "No futher information available"; 250 case 0x0001: 251 return "Authentication pending"; 252 case 0x0002: 253 return "Authorization pending"; 254 default: 255 return "Reserved"; 256 } 257 } 258 259 static char *confresult2str(uint16_t result) 260 { 261 switch (result) { 262 case 0x0000: 263 return "Success"; 264 case 0x0001: 265 return "Failure - unacceptable parameters"; 266 case 0x0002: 267 return "Failure - rejected (no reason provided)"; 268 case 0x0003: 269 return "Failure - unknown options"; 270 default: 271 return "Reserved"; 272 } 273 } 274 static char *inforesult2str(uint16_t result) 275 { 276 switch (result) { 277 case 0x0000: 278 return "Success"; 279 case 0x0001: 280 return "Not supported"; 281 default: 282 return "Reserved"; 283 } 284 } 285 286 static char *type2str(uint8_t type) 287 { 288 switch (type) { 289 case 0x00: 290 return "No traffic"; 291 case 0x01: 292 return "Best effort"; 293 case 0x02: 294 return "Guaranteed"; 295 default: 296 return "Reserved"; 297 } 298 } 299 300 static char *mode2str(uint8_t mode) 301 { 302 switch (mode) { 303 case 0x00: 304 return "Basic"; 305 case 0x01: 306 return "Retransmission"; 307 case 0x02: 308 return "Flow control"; 309 default: 310 return "Reserved"; 311 } 312 } 313 314 static char *sar2str(uint8_t sar) 315 { 316 switch (sar) { 317 case 0x00: 318 return "Unsegmented"; 319 case 0x01: 320 return "Start"; 321 case 0x02: 322 return "End"; 323 case 0x03: 324 return "Continuation"; 325 default: 326 return "Bad SAR"; 327 328 } 329 } 330 331 static char *supervisory2str(uint8_t supervisory) 332 { 333 switch (supervisory) { 334 case 0x00: 335 return "Receiver Ready (RR)"; 336 case 0x01: 337 return "Reject (REJ)"; 338 case 0x02: 339 case 0x03: 340 return "Reserved Supervisory"; 341 default: 342 return "Bad Supervisory"; 343 } 344 } 345 346 static inline void command_rej(int level, struct frame *frm) 347 { 348 l2cap_cmd_rej *h = frm->ptr; 349 uint16_t reason = btohs(h->reason); 350 uint32_t cid; 351 352 printf("Command rej: reason %d", reason); 353 354 switch (reason) { 355 case 0x0001: 356 printf(" mtu %d\n", get_val(frm->ptr + L2CAP_CMD_REJ_SIZE, 2)); 357 break; 358 case 0x0002: 359 cid = get_val(frm->ptr + L2CAP_CMD_REJ_SIZE, 4); 360 printf(" dcid 0x%4.4x scid 0x%4.4x\n", cid & 0xffff, cid >> 16); 361 break; 362 default: 363 printf("\n"); 364 break; 365 } 366 367 p_indent(level + 1, frm); 368 printf("%s\n", reason2str(reason)); 369 } 370 371 static inline void conn_req(int level, struct frame *frm) 372 { 373 l2cap_conn_req *h = frm->ptr; 374 uint16_t psm = btohs(h->psm); 375 uint16_t scid = btohs(h->scid); 376 377 add_cid(frm->in, frm->handle, scid, psm); 378 379 if (p_filter(FILT_L2CAP)) 380 return; 381 382 printf("Connect req: psm %d scid 0x%4.4x\n", psm, scid); 383 } 384 385 static inline void conn_rsp(int level, struct frame *frm) 386 { 387 l2cap_conn_rsp *h = frm->ptr; 388 uint16_t scid = btohs(h->scid); 389 uint16_t dcid = btohs(h->dcid); 390 uint16_t result = btohs(h->result); 391 uint16_t status = btohs(h->status); 392 uint16_t psm; 393 394 switch (h->result) { 395 case L2CAP_CR_SUCCESS: 396 if ((psm = get_psm(!frm->in, scid))) 397 add_cid(frm->in, frm->handle, dcid, psm); 398 break; 399 400 case L2CAP_CR_PEND: 401 break; 402 403 default: 404 del_cid(frm->in, dcid, scid); 405 break; 406 } 407 408 if (p_filter(FILT_L2CAP)) 409 return; 410 411 printf("Connect rsp: dcid 0x%4.4x scid 0x%4.4x result %d status %d\n", 412 dcid, scid, result, status); 413 414 p_indent(level + 1, frm); 415 printf("%s", connresult2str(result)); 416 417 if (result == 0x0001) 418 printf(" - %s\n", status2str(status)); 419 else 420 printf("\n"); 421 } 422 423 static void conf_rfc(void *ptr, int len, int in, uint16_t cid) 424 { 425 uint8_t mode; 426 427 mode = *((uint8_t *) ptr); 428 set_mode(in, cid, mode); 429 430 printf("RFC 0x%02x (%s", mode, mode2str(mode)); 431 if (mode == 0x01 || mode == 0x02) { 432 uint8_t txwin, maxtrans; 433 uint16_t rto, mto, mps; 434 txwin = *((uint8_t *) (ptr + 1)); 435 maxtrans = *((uint8_t *) (ptr + 2)); 436 rto = btohs(bt_get_unaligned((uint16_t *) (ptr + 3))); 437 mto = btohs(bt_get_unaligned((uint16_t *) (ptr + 5))); 438 mps = btohs(bt_get_unaligned((uint16_t *) (ptr + 7))); 439 printf(", TxWin %d, MaxTx %d, RTo %d, MTo %d, MPS %d", 440 txwin, maxtrans, rto, mto, mps); 441 } 442 printf(")"); 443 } 444 445 static void conf_opt(int level, void *ptr, int len, int in, uint16_t cid) 446 { 447 p_indent(level, 0); 448 while (len > 0) { 449 l2cap_conf_opt *h = ptr; 450 451 ptr += L2CAP_CONF_OPT_SIZE + h->len; 452 len -= L2CAP_CONF_OPT_SIZE + h->len; 453 454 if (h->type & 0x80) 455 printf("["); 456 457 switch (h->type & 0x7f) { 458 case L2CAP_CONF_MTU: 459 set_mode(in, cid, 0x00); 460 printf("MTU"); 461 if (h->len > 0) 462 printf(" %d", get_val(h->val, h->len)); 463 break; 464 465 case L2CAP_CONF_FLUSH_TO: 466 printf("FlushTO"); 467 if (h->len > 0) 468 printf(" %d", get_val(h->val, h->len)); 469 break; 470 471 case L2CAP_CONF_QOS: 472 printf("QoS"); 473 if (h->len > 0) 474 printf(" 0x%02x (%s)", *(h->val + 1), type2str(*(h->val + 1))); 475 break; 476 477 case L2CAP_CONF_RFC: 478 conf_rfc(h->val, h->len, in, cid); 479 break; 480 481 default: 482 printf("Unknown (type %2.2x, len %d)", h->type & 0x7f, h->len); 483 break; 484 } 485 486 if (h->type & 0x80) 487 printf("] "); 488 else 489 printf(" "); 490 } 491 printf("\n"); 492 } 493 494 static void conf_list(int level, uint8_t *list, int len) 495 { 496 int i; 497 498 p_indent(level, 0); 499 for (i = 0; i < len; i++) { 500 switch (list[i] & 0x7f) { 501 case L2CAP_CONF_MTU: 502 printf("MTU "); 503 break; 504 case L2CAP_CONF_FLUSH_TO: 505 printf("FlushTo "); 506 break; 507 case L2CAP_CONF_QOS: 508 printf("QoS "); 509 break; 510 case L2CAP_CONF_RFC: 511 printf("RFC "); 512 break; 513 default: 514 printf("%2.2x ", list[i] & 0x7f); 515 break; 516 } 517 } 518 printf("\n"); 519 } 520 521 static inline void conf_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 522 { 523 l2cap_conf_req *h = frm->ptr; 524 uint16_t dcid = btohs(h->dcid); 525 int clen = btohs(cmd->len) - L2CAP_CONF_REQ_SIZE; 526 527 if (p_filter(FILT_L2CAP)) 528 return; 529 530 printf("Config req: dcid 0x%4.4x flags 0x%2.2x clen %d\n", 531 dcid, btohs(h->flags), clen); 532 533 if (clen > 0) 534 conf_opt(level + 1, h->data, clen, frm->in, dcid); 535 } 536 537 static inline void conf_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 538 { 539 l2cap_conf_rsp *h = frm->ptr; 540 uint16_t scid = btohs(h->scid); 541 uint16_t result = btohs(h->result); 542 int clen = btohs(cmd->len) - L2CAP_CONF_RSP_SIZE; 543 544 if (p_filter(FILT_L2CAP)) 545 return; 546 547 printf("Config rsp: scid 0x%4.4x flags 0x%2.2x result %d clen %d\n", 548 scid, btohs(h->flags), result, clen); 549 550 if (clen > 0) { 551 if (result) { 552 p_indent(level + 1, frm); 553 printf("%s\n", confresult2str(result)); 554 } 555 if (result == 0x0003) 556 conf_list(level + 1, h->data, clen); 557 else 558 conf_opt(level + 1, h->data, clen, frm->in, scid); 559 } else { 560 p_indent(level + 1, frm); 561 printf("%s\n", confresult2str(result)); 562 } 563 } 564 565 static inline void disconn_req(int level, struct frame *frm) 566 { 567 l2cap_disconn_req *h = frm->ptr; 568 569 if (p_filter(FILT_L2CAP)) 570 return; 571 572 printf("Disconn req: dcid 0x%4.4x scid 0x%4.4x\n", 573 btohs(h->dcid), btohs(h->scid)); 574 } 575 576 static inline void disconn_rsp(int level, struct frame *frm) 577 { 578 l2cap_disconn_rsp *h = frm->ptr; 579 uint16_t dcid = btohs(h->dcid); 580 uint16_t scid = btohs(h->scid); 581 582 del_cid(frm->in, dcid, scid); 583 584 if (p_filter(FILT_L2CAP)) 585 return; 586 587 printf("Disconn rsp: dcid 0x%4.4x scid 0x%4.4x\n", 588 btohs(h->dcid), btohs(h->scid)); 589 } 590 591 static inline void echo_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 592 { 593 if (p_filter(FILT_L2CAP)) 594 return; 595 596 printf("Echo req: dlen %d\n", btohs(cmd->len)); 597 raw_dump(level, frm); 598 } 599 600 static inline void echo_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 601 { 602 if (p_filter(FILT_L2CAP)) 603 return; 604 605 printf("Echo rsp: dlen %d\n", btohs(cmd->len)); 606 raw_dump(level, frm); 607 } 608 609 static void info_opt(int level, int type, void *ptr, int len) 610 { 611 uint32_t mask; 612 613 p_indent(level, 0); 614 615 switch (type) { 616 case 0x0001: 617 printf("Connectionless MTU %d\n", get_val(ptr, len)); 618 break; 619 case 0x0002: 620 mask = get_val(ptr, len); 621 printf("Extended feature mask 0x%4.4x\n", mask); 622 if (parser.flags & DUMP_VERBOSE) { 623 if (mask & 0x01) { 624 p_indent(level + 1, 0); 625 printf("Flow control mode\n"); 626 } 627 if (mask & 0x02) { 628 p_indent(level + 1, 0); 629 printf("Retransmission mode\n"); 630 } 631 if (mask & 0x04) { 632 p_indent(level + 1, 0); 633 printf("Bi-directional QoS\n"); 634 } 635 } 636 break; 637 default: 638 printf("Unknown (len %d)\n", len); 639 break; 640 } 641 } 642 643 static inline void info_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 644 { 645 l2cap_info_req *h = frm->ptr; 646 647 if (p_filter(FILT_L2CAP)) 648 return; 649 650 printf("Info req: type %d\n", btohs(h->type)); 651 } 652 653 static inline void info_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 654 { 655 l2cap_info_rsp *h = frm->ptr; 656 uint16_t type = btohs(h->type); 657 uint16_t result = btohs(h->result); 658 int ilen = btohs(cmd->len) - L2CAP_INFO_RSP_SIZE; 659 660 if (p_filter(FILT_L2CAP)) 661 return; 662 663 printf("Info rsp: type %d result %d\n", type, result); 664 665 if (ilen > 0) { 666 info_opt(level + 1, type, h->data, ilen); 667 } else { 668 p_indent(level + 1, frm); 669 printf("%s\n", inforesult2str(result)); 670 } 671 } 672 673 static void l2cap_parse(int level, struct frame *frm) 674 { 675 l2cap_hdr *hdr = (void *)frm->ptr; 676 uint16_t dlen = btohs(hdr->len); 677 uint16_t cid = btohs(hdr->cid); 678 uint16_t psm; 679 680 frm->ptr += L2CAP_HDR_SIZE; 681 frm->len -= L2CAP_HDR_SIZE; 682 683 if (cid == 0x1) { 684 /* Signaling channel */ 685 686 while (frm->len >= L2CAP_CMD_HDR_SIZE) { 687 l2cap_cmd_hdr *hdr = frm->ptr; 688 689 frm->ptr += L2CAP_CMD_HDR_SIZE; 690 frm->len -= L2CAP_CMD_HDR_SIZE; 691 692 if (!p_filter(FILT_L2CAP)) { 693 p_indent(level, frm); 694 printf("L2CAP(s): "); 695 } 696 697 switch (hdr->code) { 698 case L2CAP_COMMAND_REJ: 699 command_rej(level, frm); 700 break; 701 702 case L2CAP_CONN_REQ: 703 conn_req(level, frm); 704 break; 705 706 case L2CAP_CONN_RSP: 707 conn_rsp(level, frm); 708 break; 709 710 case L2CAP_CONF_REQ: 711 conf_req(level, hdr, frm); 712 break; 713 714 case L2CAP_CONF_RSP: 715 conf_rsp(level, hdr, frm); 716 break; 717 718 case L2CAP_DISCONN_REQ: 719 disconn_req(level, frm); 720 break; 721 722 case L2CAP_DISCONN_RSP: 723 disconn_rsp(level, frm); 724 break; 725 726 case L2CAP_ECHO_REQ: 727 echo_req(level, hdr, frm); 728 break; 729 730 case L2CAP_ECHO_RSP: 731 echo_rsp(level, hdr, frm); 732 break; 733 734 case L2CAP_INFO_REQ: 735 info_req(level, hdr, frm); 736 break; 737 738 case L2CAP_INFO_RSP: 739 info_rsp(level, hdr, frm); 740 break; 741 742 default: 743 if (p_filter(FILT_L2CAP)) 744 break; 745 printf("code 0x%2.2x ident %d len %d\n", 746 hdr->code, hdr->ident, btohs(hdr->len)); 747 raw_dump(level, frm); 748 } 749 750 if (frm->len > btohs(hdr->len)) { 751 frm->len -= btohs(hdr->len); 752 frm->ptr += btohs(hdr->len); 753 } else 754 frm->len = 0; 755 } 756 } else if (cid == 0x2) { 757 /* Connectionless channel */ 758 759 if (p_filter(FILT_L2CAP)) 760 return; 761 762 psm = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); 763 frm->ptr += 2; 764 frm->len -= 2; 765 766 p_indent(level, frm); 767 printf("L2CAP(c): len %d psm %d\n", dlen, psm); 768 raw_dump(level, frm); 769 } else { 770 /* Connection oriented channel */ 771 772 uint8_t mode = get_mode(!frm->in, cid); 773 uint16_t psm = get_psm(!frm->in, cid); 774 uint16_t ctrl = 0, fcs = 0; 775 uint32_t proto; 776 777 frm->cid = cid; 778 frm->num = get_num(!frm->in, cid); 779 780 if (mode > 0) { 781 ctrl = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); 782 frm->ptr += 2; 783 frm->len -= 4; 784 fcs = btohs(bt_get_unaligned((uint16_t *) (frm->ptr + frm->len))); 785 } 786 787 if (!p_filter(FILT_L2CAP)) { 788 p_indent(level, frm); 789 printf("L2CAP(d): cid 0x%4.4x len %d", cid, dlen); 790 if (mode > 0) 791 printf(" ctrl 0x%4.4x fcs 0x%4.4x", ctrl, fcs); 792 printf(" [psm %d]\n", psm); 793 level++; 794 if (mode > 0) { 795 p_indent(level, frm); 796 printf("%s:", ctrl & 0x01 ? "S-frame" : "I-frame"); 797 if (ctrl & 0x01) { 798 printf(" %s", supervisory2str((ctrl & 0x0c) >> 2)); 799 } else { 800 uint8_t sar = (ctrl & 0xc000) >> 14; 801 printf(" %s", sar2str(sar)); 802 if (sar == 1) { 803 uint16_t len; 804 len = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); 805 frm->ptr += 2; 806 frm->len -= 2; 807 printf(" (len %d)", len); 808 } 809 printf(" TxSeq %d", (ctrl & 0x7e) >> 1); 810 } 811 printf(" ReqSeq %d", (ctrl & 0x3f00) >> 8); 812 if (ctrl & 0x80) 813 printf(" Retransmission Disable"); 814 printf("\n"); 815 } 816 } 817 818 switch (psm) { 819 case 0x01: 820 if (!p_filter(FILT_SDP)) 821 sdp_dump(level + 1, frm); 822 else 823 raw_dump(level + 1, frm); 824 break; 825 826 case 0x03: 827 if (!p_filter(FILT_RFCOMM)) 828 rfcomm_dump(level, frm); 829 else 830 raw_dump(level + 1, frm); 831 break; 832 833 case 0x0f: 834 if (!p_filter(FILT_BNEP)) 835 bnep_dump(level, frm); 836 else 837 raw_dump(level + 1, frm); 838 break; 839 840 case 0x11: 841 case 0x13: 842 if (!p_filter(FILT_HIDP)) 843 hidp_dump(level, frm); 844 else 845 raw_dump(level + 1, frm); 846 break; 847 848 case 0x17: 849 if (!p_filter(FILT_AVCTP)) 850 avctp_dump(level, frm); 851 else 852 raw_dump(level + 1, frm); 853 break; 854 855 case 0x19: 856 if (!p_filter(FILT_AVDTP)) 857 avdtp_dump(level, frm); 858 else 859 raw_dump(level + 1, frm); 860 break; 861 862 default: 863 proto = get_proto(frm->handle, psm, 0); 864 865 switch (proto) { 866 case SDP_UUID_CMTP: 867 if (!p_filter(FILT_CMTP)) 868 cmtp_dump(level, frm); 869 else 870 raw_dump(level + 1, frm); 871 break; 872 873 case SDP_UUID_HARDCOPY_CONTROL_CHANNEL: 874 if (!p_filter(FILT_HCRP)) 875 hcrp_dump(level, frm); 876 else 877 raw_dump(level + 1, frm); 878 break; 879 880 default: 881 if (p_filter(FILT_L2CAP)) 882 break; 883 884 raw_dump(level, frm); 885 break; 886 } 887 break; 888 } 889 } 890 } 891 892 void l2cap_dump(int level, struct frame *frm) 893 { 894 struct frame *fr; 895 l2cap_hdr *hdr; 896 uint16_t dlen; 897 898 if (frm->flags & ACL_START) { 899 hdr = frm->ptr; 900 dlen = btohs(hdr->len); 901 902 if (frm->len == (dlen + L2CAP_HDR_SIZE)) { 903 /* Complete frame */ 904 l2cap_parse(level, frm); 905 return; 906 } 907 908 if (!(fr = get_frame(frm->handle))) { 909 fprintf(stderr, "Not enough connection handles\n"); 910 raw_dump(level, frm); 911 return; 912 } 913 914 if (fr->data) 915 free(fr->data); 916 917 if (!(fr->data = malloc(dlen + L2CAP_HDR_SIZE))) { 918 perror("Can't allocate L2CAP reassembly buffer"); 919 return; 920 } 921 memcpy(fr->data, frm->ptr, frm->len); 922 fr->data_len = dlen + L2CAP_HDR_SIZE; 923 fr->len = frm->len; 924 fr->ptr = fr->data; 925 fr->dev_id = frm->dev_id; 926 fr->in = frm->in; 927 fr->ts = frm->ts; 928 fr->handle = frm->handle; 929 fr->cid = frm->cid; 930 fr->num = frm->num; 931 fr->dlci = frm->dlci; 932 fr->channel = frm->channel; 933 fr->pppdump_fd = frm->pppdump_fd; 934 fr->audio_fd = frm->audio_fd; 935 } else { 936 if (!(fr = get_frame(frm->handle))) { 937 fprintf(stderr, "Not enough connection handles\n"); 938 raw_dump(level, frm); 939 return; 940 } 941 942 if (!fr->data) { 943 /* Unexpected fragment */ 944 raw_dump(level, frm); 945 return; 946 } 947 948 if (frm->len > (fr->data_len - fr->len)) { 949 /* Bad fragment */ 950 raw_dump(level, frm); 951 free(fr->data); fr->data = NULL; 952 return; 953 } 954 955 memcpy(fr->data + fr->len, frm->ptr, frm->len); 956 fr->len += frm->len; 957 958 if (fr->len == fr->data_len) { 959 /* Complete frame */ 960 l2cap_parse(level, fr); 961 962 free(fr->data); fr->data = NULL; 963 return; 964 } 965 } 966 } 967 968 void l2cap_clear(uint16_t handle) 969 { 970 del_handle(handle); 971 } 972