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-2011 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 case 0x03: 310 return "Enhanced Retransmission"; 311 case 0x04: 312 return "Streaming"; 313 default: 314 return "Reserved"; 315 } 316 } 317 318 static char *fcs2str(uint8_t fcs) 319 { 320 switch (fcs) { 321 case 0x00: 322 return "No FCS"; 323 case 0x01: 324 return "CRC16 Check"; 325 default: 326 return "Reserved"; 327 } 328 } 329 330 static char *sar2str(uint8_t sar) 331 { 332 switch (sar) { 333 case 0x00: 334 return "Unsegmented"; 335 case 0x01: 336 return "Start"; 337 case 0x02: 338 return "End"; 339 case 0x03: 340 return "Continuation"; 341 default: 342 return "Bad SAR"; 343 344 } 345 } 346 347 static char *supervisory2str(uint8_t supervisory) 348 { 349 switch (supervisory) { 350 case 0x00: 351 return "Receiver Ready (RR)"; 352 case 0x01: 353 return "Reject (REJ)"; 354 case 0x02: 355 return "Receiver Not Ready (RNR)"; 356 case 0x03: 357 return "Select Reject (SREJ)"; 358 default: 359 return "Bad Supervisory"; 360 } 361 } 362 363 static inline void command_rej(int level, struct frame *frm) 364 { 365 l2cap_cmd_rej *h = frm->ptr; 366 uint16_t reason = btohs(h->reason); 367 uint32_t cid; 368 369 printf("Command rej: reason %d", reason); 370 371 switch (reason) { 372 case 0x0001: 373 printf(" mtu %d\n", get_val(frm->ptr + L2CAP_CMD_REJ_SIZE, 2)); 374 break; 375 case 0x0002: 376 cid = get_val(frm->ptr + L2CAP_CMD_REJ_SIZE, 4); 377 printf(" dcid 0x%4.4x scid 0x%4.4x\n", cid & 0xffff, cid >> 16); 378 break; 379 default: 380 printf("\n"); 381 break; 382 } 383 384 p_indent(level + 1, frm); 385 printf("%s\n", reason2str(reason)); 386 } 387 388 static inline void conn_req(int level, struct frame *frm) 389 { 390 l2cap_conn_req *h = frm->ptr; 391 uint16_t psm = btohs(h->psm); 392 uint16_t scid = btohs(h->scid); 393 394 add_cid(frm->in, frm->handle, scid, psm); 395 396 if (p_filter(FILT_L2CAP)) 397 return; 398 399 printf("Connect req: psm %d scid 0x%4.4x\n", psm, scid); 400 } 401 402 static inline void conn_rsp(int level, struct frame *frm) 403 { 404 l2cap_conn_rsp *h = frm->ptr; 405 uint16_t scid = btohs(h->scid); 406 uint16_t dcid = btohs(h->dcid); 407 uint16_t result = btohs(h->result); 408 uint16_t status = btohs(h->status); 409 uint16_t psm; 410 411 switch (h->result) { 412 case L2CAP_CR_SUCCESS: 413 if ((psm = get_psm(!frm->in, scid))) 414 add_cid(frm->in, frm->handle, dcid, psm); 415 break; 416 417 case L2CAP_CR_PEND: 418 break; 419 420 default: 421 del_cid(frm->in, dcid, scid); 422 break; 423 } 424 425 if (p_filter(FILT_L2CAP)) 426 return; 427 428 printf("Connect rsp: dcid 0x%4.4x scid 0x%4.4x result %d status %d\n", 429 dcid, scid, result, status); 430 431 p_indent(level + 1, frm); 432 printf("%s", connresult2str(result)); 433 434 if (result == 0x0001) 435 printf(" - %s\n", status2str(status)); 436 else 437 printf("\n"); 438 } 439 440 static void conf_rfc(void *ptr, int len, int in, uint16_t cid) 441 { 442 uint8_t mode; 443 444 mode = *((uint8_t *) ptr); 445 set_mode(in, cid, mode); 446 447 printf("RFC 0x%02x (%s", mode, mode2str(mode)); 448 if (mode >= 0x01 && mode <= 0x04) { 449 uint8_t txwin, maxtrans; 450 uint16_t rto, mto, mps; 451 txwin = *((uint8_t *) (ptr + 1)); 452 maxtrans = *((uint8_t *) (ptr + 2)); 453 rto = btohs(bt_get_unaligned((uint16_t *) (ptr + 3))); 454 mto = btohs(bt_get_unaligned((uint16_t *) (ptr + 5))); 455 mps = btohs(bt_get_unaligned((uint16_t *) (ptr + 7))); 456 printf(", TxWin %d, MaxTx %d, RTo %d, MTo %d, MPS %d", 457 txwin, maxtrans, rto, mto, mps); 458 } 459 printf(")"); 460 } 461 462 static void conf_fcs(void *ptr, int len) 463 { 464 uint8_t fcs; 465 466 fcs = *((uint8_t *) ptr); 467 printf("FCS Option"); 468 if (len > 0) 469 printf(" 0x%2.2x (%s)", fcs, fcs2str(fcs)); 470 } 471 472 static void conf_opt(int level, void *ptr, int len, int in, uint16_t cid) 473 { 474 p_indent(level, 0); 475 while (len > 0) { 476 l2cap_conf_opt *h = ptr; 477 478 ptr += L2CAP_CONF_OPT_SIZE + h->len; 479 len -= L2CAP_CONF_OPT_SIZE + h->len; 480 481 if (h->type & 0x80) 482 printf("["); 483 484 switch (h->type & 0x7f) { 485 case L2CAP_CONF_MTU: 486 set_mode(in, cid, 0x00); 487 printf("MTU"); 488 if (h->len > 0) 489 printf(" %d", get_val(h->val, h->len)); 490 break; 491 492 case L2CAP_CONF_FLUSH_TO: 493 printf("FlushTO"); 494 if (h->len > 0) 495 printf(" %d", get_val(h->val, h->len)); 496 break; 497 498 case L2CAP_CONF_QOS: 499 printf("QoS"); 500 if (h->len > 0) 501 printf(" 0x%02x (%s)", *(h->val + 1), type2str(*(h->val + 1))); 502 break; 503 504 case L2CAP_CONF_RFC: 505 conf_rfc(h->val, h->len, in, cid); 506 break; 507 508 case L2CAP_CONF_FCS: 509 conf_fcs(h->val, h->len); 510 break; 511 512 default: 513 printf("Unknown (type %2.2x, len %d)", h->type & 0x7f, h->len); 514 break; 515 } 516 517 if (h->type & 0x80) 518 printf("] "); 519 else 520 printf(" "); 521 } 522 printf("\n"); 523 } 524 525 static void conf_list(int level, uint8_t *list, int len) 526 { 527 int i; 528 529 p_indent(level, 0); 530 for (i = 0; i < len; i++) { 531 switch (list[i] & 0x7f) { 532 case L2CAP_CONF_MTU: 533 printf("MTU "); 534 break; 535 case L2CAP_CONF_FLUSH_TO: 536 printf("FlushTo "); 537 break; 538 case L2CAP_CONF_QOS: 539 printf("QoS "); 540 break; 541 case L2CAP_CONF_RFC: 542 printf("RFC "); 543 break; 544 case L2CAP_CONF_FCS: 545 printf("FCS "); 546 break; 547 default: 548 printf("%2.2x ", list[i] & 0x7f); 549 break; 550 } 551 } 552 printf("\n"); 553 } 554 555 static inline void conf_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 556 { 557 l2cap_conf_req *h = frm->ptr; 558 uint16_t dcid = btohs(h->dcid); 559 int clen = btohs(cmd->len) - L2CAP_CONF_REQ_SIZE; 560 561 if (p_filter(FILT_L2CAP)) 562 return; 563 564 printf("Config req: dcid 0x%4.4x flags 0x%2.2x clen %d\n", 565 dcid, btohs(h->flags), clen); 566 567 if (clen > 0) 568 conf_opt(level + 1, h->data, clen, frm->in, dcid); 569 } 570 571 static inline void conf_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 572 { 573 l2cap_conf_rsp *h = frm->ptr; 574 uint16_t scid = btohs(h->scid); 575 uint16_t result = btohs(h->result); 576 int clen = btohs(cmd->len) - L2CAP_CONF_RSP_SIZE; 577 578 if (p_filter(FILT_L2CAP)) 579 return; 580 581 printf("Config rsp: scid 0x%4.4x flags 0x%2.2x result %d clen %d\n", 582 scid, btohs(h->flags), result, clen); 583 584 if (clen > 0) { 585 if (result) { 586 p_indent(level + 1, frm); 587 printf("%s\n", confresult2str(result)); 588 } 589 if (result == 0x0003) 590 conf_list(level + 1, h->data, clen); 591 else 592 conf_opt(level + 1, h->data, clen, frm->in, scid); 593 } else { 594 p_indent(level + 1, frm); 595 printf("%s\n", confresult2str(result)); 596 } 597 } 598 599 static inline void disconn_req(int level, struct frame *frm) 600 { 601 l2cap_disconn_req *h = frm->ptr; 602 603 if (p_filter(FILT_L2CAP)) 604 return; 605 606 printf("Disconn req: dcid 0x%4.4x scid 0x%4.4x\n", 607 btohs(h->dcid), btohs(h->scid)); 608 } 609 610 static inline void disconn_rsp(int level, struct frame *frm) 611 { 612 l2cap_disconn_rsp *h = frm->ptr; 613 uint16_t dcid = btohs(h->dcid); 614 uint16_t scid = btohs(h->scid); 615 616 del_cid(frm->in, dcid, scid); 617 618 if (p_filter(FILT_L2CAP)) 619 return; 620 621 printf("Disconn rsp: dcid 0x%4.4x scid 0x%4.4x\n", 622 btohs(h->dcid), btohs(h->scid)); 623 } 624 625 static inline void echo_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 626 { 627 if (p_filter(FILT_L2CAP)) 628 return; 629 630 printf("Echo req: dlen %d\n", btohs(cmd->len)); 631 raw_dump(level, frm); 632 } 633 634 static inline void echo_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 635 { 636 if (p_filter(FILT_L2CAP)) 637 return; 638 639 printf("Echo rsp: dlen %d\n", btohs(cmd->len)); 640 raw_dump(level, frm); 641 } 642 643 static void info_opt(int level, int type, void *ptr, int len) 644 { 645 uint32_t mask; 646 647 p_indent(level, 0); 648 649 switch (type) { 650 case 0x0001: 651 printf("Connectionless MTU %d\n", get_val(ptr, len)); 652 break; 653 case 0x0002: 654 mask = get_val(ptr, len); 655 printf("Extended feature mask 0x%4.4x\n", mask); 656 if (parser.flags & DUMP_VERBOSE) { 657 if (mask & 0x01) { 658 p_indent(level + 1, 0); 659 printf("Flow control mode\n"); 660 } 661 if (mask & 0x02) { 662 p_indent(level + 1, 0); 663 printf("Retransmission mode\n"); 664 } 665 if (mask & 0x04) { 666 p_indent(level + 1, 0); 667 printf("Bi-directional QoS\n"); 668 } 669 } 670 break; 671 case 0x0003: 672 printf("Fixed channel list\n"); 673 break; 674 default: 675 printf("Unknown (len %d)\n", len); 676 break; 677 } 678 } 679 680 static inline void info_req(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 681 { 682 l2cap_info_req *h = frm->ptr; 683 684 if (p_filter(FILT_L2CAP)) 685 return; 686 687 printf("Info req: type %d\n", btohs(h->type)); 688 } 689 690 static inline void info_rsp(int level, l2cap_cmd_hdr *cmd, struct frame *frm) 691 { 692 l2cap_info_rsp *h = frm->ptr; 693 uint16_t type = btohs(h->type); 694 uint16_t result = btohs(h->result); 695 int ilen = btohs(cmd->len) - L2CAP_INFO_RSP_SIZE; 696 697 if (p_filter(FILT_L2CAP)) 698 return; 699 700 printf("Info rsp: type %d result %d\n", type, result); 701 702 if (ilen > 0) { 703 info_opt(level + 1, type, h->data, ilen); 704 } else { 705 p_indent(level + 1, frm); 706 printf("%s\n", inforesult2str(result)); 707 } 708 } 709 710 static void l2cap_parse(int level, struct frame *frm) 711 { 712 l2cap_hdr *hdr = (void *)frm->ptr; 713 uint16_t dlen = btohs(hdr->len); 714 uint16_t cid = btohs(hdr->cid); 715 uint16_t psm; 716 717 frm->ptr += L2CAP_HDR_SIZE; 718 frm->len -= L2CAP_HDR_SIZE; 719 720 if (cid == 0x1) { 721 /* Signaling channel */ 722 723 while (frm->len >= L2CAP_CMD_HDR_SIZE) { 724 l2cap_cmd_hdr *hdr = frm->ptr; 725 726 frm->ptr += L2CAP_CMD_HDR_SIZE; 727 frm->len -= L2CAP_CMD_HDR_SIZE; 728 729 if (!p_filter(FILT_L2CAP)) { 730 p_indent(level, frm); 731 printf("L2CAP(s): "); 732 } 733 734 switch (hdr->code) { 735 case L2CAP_COMMAND_REJ: 736 command_rej(level, frm); 737 break; 738 739 case L2CAP_CONN_REQ: 740 conn_req(level, frm); 741 break; 742 743 case L2CAP_CONN_RSP: 744 conn_rsp(level, frm); 745 break; 746 747 case L2CAP_CONF_REQ: 748 conf_req(level, hdr, frm); 749 break; 750 751 case L2CAP_CONF_RSP: 752 conf_rsp(level, hdr, frm); 753 break; 754 755 case L2CAP_DISCONN_REQ: 756 disconn_req(level, frm); 757 break; 758 759 case L2CAP_DISCONN_RSP: 760 disconn_rsp(level, frm); 761 break; 762 763 case L2CAP_ECHO_REQ: 764 echo_req(level, hdr, frm); 765 break; 766 767 case L2CAP_ECHO_RSP: 768 echo_rsp(level, hdr, frm); 769 break; 770 771 case L2CAP_INFO_REQ: 772 info_req(level, hdr, frm); 773 break; 774 775 case L2CAP_INFO_RSP: 776 info_rsp(level, hdr, frm); 777 break; 778 779 default: 780 if (p_filter(FILT_L2CAP)) 781 break; 782 printf("code 0x%2.2x ident %d len %d\n", 783 hdr->code, hdr->ident, btohs(hdr->len)); 784 raw_dump(level, frm); 785 } 786 787 if (frm->len > btohs(hdr->len)) { 788 frm->len -= btohs(hdr->len); 789 frm->ptr += btohs(hdr->len); 790 } else 791 frm->len = 0; 792 } 793 } else if (cid == 0x2) { 794 /* Connectionless channel */ 795 796 if (p_filter(FILT_L2CAP)) 797 return; 798 799 psm = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); 800 frm->ptr += 2; 801 frm->len -= 2; 802 803 p_indent(level, frm); 804 printf("L2CAP(c): len %d psm %d\n", dlen, psm); 805 raw_dump(level, frm); 806 } else { 807 /* Connection oriented channel */ 808 809 uint8_t mode = get_mode(!frm->in, cid); 810 uint16_t psm = get_psm(!frm->in, cid); 811 uint16_t ctrl = 0, fcs = 0; 812 uint32_t proto; 813 814 frm->cid = cid; 815 frm->num = get_num(!frm->in, cid); 816 817 if (mode > 0) { 818 ctrl = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); 819 frm->ptr += 2; 820 frm->len -= 4; 821 fcs = btohs(bt_get_unaligned((uint16_t *) (frm->ptr + frm->len))); 822 } 823 824 if (!p_filter(FILT_L2CAP)) { 825 p_indent(level, frm); 826 printf("L2CAP(d): cid 0x%4.4x len %d", cid, dlen); 827 if (mode > 0) 828 printf(" ctrl 0x%4.4x fcs 0x%4.4x", ctrl, fcs); 829 printf(" [psm %d]\n", psm); 830 level++; 831 if (mode > 0) { 832 p_indent(level, frm); 833 printf("%s:", ctrl & 0x01 ? "S-frame" : "I-frame"); 834 if (ctrl & 0x01) { 835 printf(" %s", supervisory2str((ctrl & 0x0c) >> 2)); 836 } else { 837 uint8_t sar = (ctrl & 0xc000) >> 14; 838 printf(" %s", sar2str(sar)); 839 if (sar == 1) { 840 uint16_t len; 841 len = btohs(bt_get_unaligned((uint16_t *) frm->ptr)); 842 frm->ptr += 2; 843 frm->len -= 2; 844 printf(" (len %d)", len); 845 } 846 printf(" TxSeq %d", (ctrl & 0x7e) >> 1); 847 } 848 printf(" ReqSeq %d", (ctrl & 0x3f00) >> 8); 849 if (ctrl & 0x80) 850 printf(" F-bit"); 851 if (ctrl & 0x10) 852 printf(" P-bit"); 853 printf("\n"); 854 } 855 } 856 857 switch (psm) { 858 case 0x01: 859 if (!p_filter(FILT_SDP)) 860 sdp_dump(level + 1, frm); 861 else 862 raw_dump(level + 1, frm); 863 break; 864 865 case 0x03: 866 if (!p_filter(FILT_RFCOMM)) 867 rfcomm_dump(level, frm); 868 else 869 raw_dump(level + 1, frm); 870 break; 871 872 case 0x0f: 873 if (!p_filter(FILT_BNEP)) 874 bnep_dump(level, frm); 875 else 876 raw_dump(level + 1, frm); 877 break; 878 879 case 0x11: 880 case 0x13: 881 if (!p_filter(FILT_HIDP)) 882 hidp_dump(level, frm); 883 else 884 raw_dump(level + 1, frm); 885 break; 886 887 case 0x17: 888 if (!p_filter(FILT_AVCTP)) 889 avctp_dump(level, frm); 890 else 891 raw_dump(level + 1, frm); 892 break; 893 894 case 0x19: 895 if (!p_filter(FILT_AVDTP)) 896 avdtp_dump(level, frm); 897 else 898 raw_dump(level + 1, frm); 899 break; 900 901 case 0x1f: 902 if (!p_filter(FILT_ATT)) 903 att_dump(level, frm); 904 else 905 raw_dump(level + 1, frm); 906 break; 907 908 default: 909 proto = get_proto(frm->handle, psm, 0); 910 911 switch (proto) { 912 case SDP_UUID_CMTP: 913 if (!p_filter(FILT_CMTP)) 914 cmtp_dump(level, frm); 915 else 916 raw_dump(level + 1, frm); 917 break; 918 919 case SDP_UUID_HARDCOPY_CONTROL_CHANNEL: 920 if (!p_filter(FILT_HCRP)) 921 hcrp_dump(level, frm); 922 else 923 raw_dump(level + 1, frm); 924 break; 925 926 default: 927 if (p_filter(FILT_L2CAP)) 928 break; 929 930 raw_dump(level, frm); 931 break; 932 } 933 break; 934 } 935 } 936 } 937 938 void l2cap_dump(int level, struct frame *frm) 939 { 940 struct frame *fr; 941 l2cap_hdr *hdr; 942 uint16_t dlen; 943 944 if ((frm->flags & ACL_START) || frm->flags == ACL_START_NO_FLUSH) { 945 hdr = frm->ptr; 946 dlen = btohs(hdr->len); 947 948 if ((int) frm->len == (dlen + L2CAP_HDR_SIZE)) { 949 /* Complete frame */ 950 l2cap_parse(level, frm); 951 return; 952 } 953 954 if (!(fr = get_frame(frm->handle))) { 955 fprintf(stderr, "Not enough connection handles\n"); 956 raw_dump(level, frm); 957 return; 958 } 959 960 if (fr->data) 961 free(fr->data); 962 963 if (!(fr->data = malloc(dlen + L2CAP_HDR_SIZE))) { 964 perror("Can't allocate L2CAP reassembly buffer"); 965 return; 966 } 967 memcpy(fr->data, frm->ptr, frm->len); 968 fr->data_len = dlen + L2CAP_HDR_SIZE; 969 fr->len = frm->len; 970 fr->ptr = fr->data; 971 fr->dev_id = frm->dev_id; 972 fr->in = frm->in; 973 fr->ts = frm->ts; 974 fr->handle = frm->handle; 975 fr->cid = frm->cid; 976 fr->num = frm->num; 977 fr->dlci = frm->dlci; 978 fr->channel = frm->channel; 979 fr->pppdump_fd = frm->pppdump_fd; 980 fr->audio_fd = frm->audio_fd; 981 } else { 982 if (!(fr = get_frame(frm->handle))) { 983 fprintf(stderr, "Not enough connection handles\n"); 984 raw_dump(level, frm); 985 return; 986 } 987 988 if (!fr->data) { 989 /* Unexpected fragment */ 990 raw_dump(level, frm); 991 return; 992 } 993 994 if (frm->len > (fr->data_len - fr->len)) { 995 /* Bad fragment */ 996 raw_dump(level, frm); 997 free(fr->data); fr->data = NULL; 998 return; 999 } 1000 1001 memcpy(fr->data + fr->len, frm->ptr, frm->len); 1002 fr->len += frm->len; 1003 1004 if (fr->len == fr->data_len) { 1005 /* Complete frame */ 1006 l2cap_parse(level, fr); 1007 1008 free(fr->data); fr->data = NULL; 1009 return; 1010 } 1011 } 1012 } 1013 1014 void l2cap_clear(uint16_t handle) 1015 { 1016 del_handle(handle); 1017 } 1018