Home | History | Annotate | Download | only in parser
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2001-2002  Wayne Lee <waynelee (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 
     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 
     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 
     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 
     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 }
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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