• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2000-2002  Maxim Krasnyansky <maxk@qualcomm.com>
6  *  Copyright (C) 2003-2007  Marcel Holtmann <marcel@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 
add_handle(uint16_t handle)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 
get_frame(uint16_t handle)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 
add_cid(int in,uint16_t handle,uint16_t cid,uint16_t psm)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 
del_cid(int in,uint16_t dcid,uint16_t scid)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 
del_handle(uint16_t handle)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 }
get_psm(int in,uint16_t cid)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 
get_num(int in,uint16_t cid)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 
set_mode(int in,uint16_t cid,uint8_t mode)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 
get_mode(int in,uint16_t cid)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 
get_val(uint8_t * ptr,uint8_t len)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 
reason2str(uint16_t reason)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 
connresult2str(uint16_t result)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 
status2str(uint16_t status)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 
confresult2str(uint16_t result)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 }
inforesult2str(uint16_t result)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 
type2str(uint8_t type)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 
mode2str(uint8_t mode)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 
sar2str(uint8_t sar)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 
supervisory2str(uint8_t supervisory)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 
command_rej(int level,struct frame * frm)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 
conn_req(int level,struct frame * frm)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 
conn_rsp(int level,struct frame * frm)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 
conf_rfc(void * ptr,int len,int in,uint16_t cid)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 
conf_opt(int level,void * ptr,int len,int in,uint16_t cid)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 
conf_list(int level,uint8_t * list,int len)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 
conf_req(int level,l2cap_cmd_hdr * cmd,struct frame * frm)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 
conf_rsp(int level,l2cap_cmd_hdr * cmd,struct frame * frm)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 
disconn_req(int level,struct frame * frm)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 
disconn_rsp(int level,struct frame * frm)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 
echo_req(int level,l2cap_cmd_hdr * cmd,struct frame * frm)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 
echo_rsp(int level,l2cap_cmd_hdr * cmd,struct frame * frm)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 
info_opt(int level,int type,void * ptr,int len)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 
info_req(int level,l2cap_cmd_hdr * cmd,struct frame * frm)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 
info_rsp(int level,l2cap_cmd_hdr * cmd,struct frame * frm)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 
l2cap_parse(int level,struct frame * frm)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 
l2cap_dump(int level,struct frame * frm)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 
l2cap_clear(uint16_t handle)968 void l2cap_clear(uint16_t handle)
969 {
970 	del_handle(handle);
971 }
972