• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2001-2002  Wayne Lee <waynelee@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 
41 #include "parser.h"
42 #include "rfcomm.h"
43 #include "sdp.h"
44 
45 static char *cr_str[] = {
46 	"RSP",
47 	"CMD"
48 };
49 
50 #define CR_STR(mcc_head) cr_str[mcc_head->type.cr]
51 #define GET_DLCI(addr) ((addr.server_chn << 1) | (addr.d & 1))
52 
print_rfcomm_hdr(long_frame_head * head,uint8_t * ptr,int len)53 static void print_rfcomm_hdr(long_frame_head* head, uint8_t *ptr, int len)
54 {
55 	address_field addr = head->addr;
56 	uint8_t ctr = head->control;
57 	uint16_t ilen = head->length.bits.len;
58 	uint8_t ctr_type,pf,dlci,fcs;
59 
60 	dlci     = GET_DLCI(addr);
61 	pf       = GET_PF(ctr);
62 	ctr_type = CLR_PF(ctr);
63 	fcs      = *(ptr + len - 1);
64 
65 	printf("cr %d dlci %d pf %d ilen %d fcs 0x%x ", addr.cr, dlci, pf, ilen, fcs);
66 }
67 
print_mcc(mcc_long_frame_head * mcc_head)68 static void print_mcc(mcc_long_frame_head* mcc_head)
69 {
70 	printf("mcc_len %d\n", mcc_head->length.bits.len);
71 }
72 
mcc_test(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)73 static inline void mcc_test(int level, uint8_t *ptr, int len,
74 				long_frame_head *head, mcc_long_frame_head *mcc_head)
75 {
76 	printf("TEST %s: ", CR_STR(mcc_head));
77 	print_rfcomm_hdr(head, ptr, len);
78 	print_mcc(mcc_head);
79 }
mcc_fcon(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)80 static inline void mcc_fcon(int level, uint8_t *ptr, int len,
81 				long_frame_head *head, mcc_long_frame_head *mcc_head)
82 {
83 	printf("FCON %s: ", CR_STR(mcc_head));
84 	print_rfcomm_hdr(head, ptr, len);
85 	print_mcc(mcc_head);
86 }
87 
mcc_fcoff(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)88 static inline void mcc_fcoff(int level, uint8_t *ptr, int len,
89 				long_frame_head *head, mcc_long_frame_head *mcc_head)
90 {
91 	printf("FCOFF %s: ", CR_STR(mcc_head));
92 	print_rfcomm_hdr(head, ptr, len);
93 	print_mcc(mcc_head);
94 }
95 
mcc_msc(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)96 static inline void mcc_msc(int level, uint8_t *ptr, int len,
97 				long_frame_head *head, mcc_long_frame_head *mcc_head)
98 {
99 	msc_msg *msc = (void*) (ptr - STRUCT_END(msc_msg, mcc_s_head));
100 
101 	printf("MSC %s: ", CR_STR(mcc_head));
102 	print_rfcomm_hdr(head, ptr, len);
103 	print_mcc(mcc_head);
104 	p_indent(level, 0);
105 	printf("dlci %d fc %d rtc %d rtr %d ic %d dv %d",
106 		GET_DLCI(msc->dlci), msc->v24_sigs.fc, msc->v24_sigs.rtc,
107 		msc->v24_sigs.rtr, msc->v24_sigs.ic, msc->v24_sigs.dv );
108 
109 	/* Assuming that break_signals field is _not declared_ in struct msc_msg... */
110 	if (len > STRUCT_OFFSET(msc_msg, fcs) - STRUCT_END(msc_msg, v24_sigs)) {
111 		break_signals *brk = (break_signals *)
112 			(ptr + STRUCT_END(msc_msg, v24_sigs));
113 		printf(" b1 %d b2 %d b3 %d len %d\n",
114 			brk->b1, brk->b2, brk->b3, brk->len);
115 	} else
116 		printf("\n");
117 }
118 
mcc_rpn(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)119 static inline void mcc_rpn(int level, uint8_t *ptr, int len,
120 				long_frame_head *head, mcc_long_frame_head *mcc_head)
121 {
122 	rpn_msg *rpn = (void *) (ptr - STRUCT_END(rpn_msg, mcc_s_head));
123 
124 	printf("RPN %s: ", CR_STR(mcc_head));
125 	print_rfcomm_hdr(head, ptr, len);
126 	print_mcc(mcc_head);
127 
128 	p_indent(level, 0);
129 	printf("dlci %d ", GET_DLCI(rpn->dlci));
130 
131 	/* Assuming that rpn_val is _declared_ as a member of rpn_msg... */
132 	if (len <= STRUCT_OFFSET(rpn_msg, rpn_val) - STRUCT_END(rpn_msg, mcc_s_head)) {
133 		printf("\n");
134 		return;
135 	}
136 
137 	printf("br %d db %d sb %d p %d pt %d xi %d xo %d\n",
138 		rpn->rpn_val.bit_rate, rpn->rpn_val.data_bits,
139 		rpn->rpn_val.stop_bit, rpn->rpn_val.parity,
140 		rpn->rpn_val.parity_type, rpn->rpn_val.xon_input,
141 		rpn->rpn_val.xon_output);
142 
143 	p_indent(level, 0);
144 	printf("rtri %d rtro %d rtci %d rtco %d xon %d xoff %d pm 0x%04x\n",
145 		rpn->rpn_val.rtr_input, rpn->rpn_val.rtr_output,
146 		rpn->rpn_val.rtc_input, rpn->rpn_val.rtc_output,
147 		rpn->rpn_val.xon, rpn->rpn_val.xoff, btohs(rpn->rpn_val.pm));
148 }
149 
mcc_rls(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)150 static inline void mcc_rls(int level, uint8_t *ptr, int len,
151 				long_frame_head *head, mcc_long_frame_head *mcc_head)
152 {
153 	rls_msg* rls = (void*) (ptr - STRUCT_END(rls_msg, mcc_s_head));
154 
155 	printf("RLS %s: ", CR_STR(mcc_head));
156 	print_rfcomm_hdr(head, ptr, len);
157 	print_mcc(mcc_head);
158 	printf("dlci %d error: %d", GET_DLCI(rls->dlci), rls->error);
159 }
160 
mcc_pn(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)161 static inline void mcc_pn(int level, uint8_t *ptr, int len,
162 				long_frame_head *head, mcc_long_frame_head *mcc_head)
163 {
164 	pn_msg *pn = (void*) (ptr - STRUCT_END(pn_msg, mcc_s_head));
165 
166 	printf("PN %s: ", CR_STR(mcc_head));
167 	print_rfcomm_hdr(head, ptr, len);
168 	print_mcc(mcc_head);
169 
170 	p_indent(level, 0);
171 	printf("dlci %d frame_type %d credit_flow %d pri %d ack_timer %d\n",
172 		pn->dlci, pn->frame_type, pn->credit_flow, pn->prior, pn->ack_timer);
173 	p_indent(level, 0);
174 	printf("frame_size %d max_retrans %d credits %d\n",
175 		btohs(pn->frame_size), pn->max_nbrof_retrans, pn->credits);
176 }
177 
mcc_nsc(int level,uint8_t * ptr,int len,long_frame_head * head,mcc_long_frame_head * mcc_head)178 static inline void mcc_nsc(int level, uint8_t *ptr, int len,
179 				long_frame_head *head, mcc_long_frame_head *mcc_head)
180 {
181 
182 	nsc_msg *nsc = (void*) (ptr - STRUCT_END(nsc_msg, mcc_s_head));
183 
184 	printf("NSC %s: ", CR_STR(mcc_head));
185 	print_rfcomm_hdr(head, ptr, len);
186 	print_mcc(mcc_head);
187 
188 	p_indent(level, 0);
189 	printf("cr %d, mcc_cmd_type %x\n",
190 		nsc->command_type.cr, nsc->command_type.type );
191 }
192 
mcc_frame(int level,struct frame * frm,long_frame_head * head)193 static inline void mcc_frame(int level, struct frame *frm, long_frame_head *head)
194 {
195 	mcc_short_frame_head *mcc_short_head_p = frm->ptr;
196 	mcc_long_frame_head mcc_head;
197 	uint8_t hdr_size;
198 
199 	if ( mcc_short_head_p->length.ea == EA ) {
200 		mcc_head.type = mcc_short_head_p->type;
201 		mcc_head.length.bits.len = mcc_short_head_p->length.len;
202 		hdr_size = sizeof(mcc_short_frame_head);
203 	} else {
204 		mcc_head = *(mcc_long_frame_head *)frm->ptr;
205 		mcc_head.length.val = btohs(mcc_head.length.val);
206 		hdr_size = sizeof(mcc_long_frame_head);
207 	}
208 
209 	frm->ptr += hdr_size;
210 	frm->len -= hdr_size;
211 
212 	p_indent(level, frm);
213 	printf("RFCOMM(s): ");
214 
215 	switch (mcc_head.type.type) {
216 	case TEST:
217 		mcc_test(level, frm->ptr, frm->len, head, &mcc_head);
218 		raw_dump(level, frm);
219 		break;
220 	case FCON:
221 		mcc_fcon(level, frm->ptr, frm->len, head, &mcc_head);
222 		break;
223 	case FCOFF:
224 		mcc_fcoff(level, frm->ptr, frm->len, head, &mcc_head);
225 		break;
226 	case MSC:
227 		mcc_msc(level, frm->ptr, frm->len, head, &mcc_head);
228 		break;
229 	case RPN:
230 		mcc_rpn(level, frm->ptr, frm->len, head, &mcc_head);
231 		break;
232 	case RLS:
233 		mcc_rls(level, frm->ptr, frm->len, head, &mcc_head);
234 		break;
235 	case PN:
236 		mcc_pn(level, frm->ptr, frm->len, head, &mcc_head);
237 		break;
238 	case NSC:
239 		mcc_nsc(level, frm->ptr, frm->len, head, &mcc_head);
240 		break;
241 	default:
242 		printf("MCC message type 0x%02x: ", mcc_head.type.type);
243 		print_rfcomm_hdr(head, frm->ptr, frm->len);
244 		printf("\n");
245 
246 		frm->len--;
247 		raw_dump(level, frm);
248 	}
249 }
250 
uih_frame(int level,struct frame * frm,long_frame_head * head)251 static inline void uih_frame(int level, struct frame *frm, long_frame_head *head)
252 {
253 	uint32_t proto;
254 
255 	if (!head->addr.server_chn) {
256 		mcc_frame(level, frm, head);
257 	} else {
258 		p_indent(level, frm);
259 		printf("RFCOMM(d): UIH: ");
260 		print_rfcomm_hdr(head, frm->ptr, frm->len);
261 		if (GET_PF(head->control)) {
262 			printf("credits %d\n", *(uint8_t *)(frm->ptr));
263 			frm->ptr++;
264 			frm->len--;
265 		} else
266 			printf("\n");
267 
268 		frm->len--;
269 		frm->dlci = GET_DLCI(head->addr);
270 		frm->channel = head->addr.server_chn;
271 
272 		proto = get_proto(frm->handle, RFCOMM_PSM, frm->channel);
273 
274 		if (frm->len > 0) {
275 			switch (proto) {
276 			case SDP_UUID_OBEX:
277 				if (!p_filter(FILT_OBEX))
278 					obex_dump(level + 1, frm);
279 				else
280 					raw_dump(level, frm);
281 				break;
282 
283 			case SDP_UUID_LAN_ACCESS_PPP:
284 			case SDP_UUID_DIALUP_NETWORKING:
285 				if (!p_filter(FILT_PPP))
286 					ppp_dump(level + 1, frm);
287 				else
288 					raw_dump(level, frm);
289 				break;
290 
291 			default:
292 				if (p_filter(FILT_RFCOMM))
293 					break;
294 
295 				raw_dump(level, frm);
296 				break;
297 			}
298 		}
299 	}
300 }
301 
rfcomm_dump(int level,struct frame * frm)302 void rfcomm_dump(int level, struct frame *frm)
303 {
304 	uint8_t hdr_size, ctr_type;
305 	short_frame_head *short_head_p = (void *) frm->ptr;
306 	long_frame_head head;
307 
308 	if (short_head_p->length.ea == EA) {
309 		head.addr = short_head_p->addr;
310 		head.control = short_head_p->control;
311 		head.length.bits.len = short_head_p->length.len;
312 		hdr_size = sizeof(short_frame_head);
313 	} else {
314 		head = *(long_frame_head *) frm->ptr;
315 		head.length.val = btohs(head.length.val);
316 		hdr_size = sizeof(long_frame_head);
317 	}
318 
319 	frm->ptr += hdr_size;
320 	frm->len -= hdr_size;
321 
322 	ctr_type = CLR_PF(head.control);
323 
324 	if (ctr_type == UIH) {
325 		uih_frame(level, frm, &head);
326 	} else {
327 		p_indent(level, frm);
328 		printf("RFCOMM(s): ");
329 
330 		switch (ctr_type) {
331 		case SABM:
332 			printf("SABM: ");
333 			break;
334 		case UA:
335 			printf("UA: ");
336 			break;
337 		case DM:
338 			printf("DM: ");
339 			break;
340 		case DISC:
341 			printf("DISC: ");
342 			del_frame(frm->handle, GET_DLCI(head.addr));
343 			break;
344 		default:
345 			printf("ERR: ");
346 		}
347 		print_rfcomm_hdr(&head, frm->ptr, frm->len);
348 		printf("\n");
349 	}
350 }
351