Home | History | Annotate | Download | only in parser
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2002-2007  Marcel Holtmann <marcel (at) holtmann.org>
      6  *
      7  *
      8  *  This program is free software; you can redistribute it and/or modify
      9  *  it under the terms of the GNU General Public License as published by
     10  *  the Free Software Foundation; either version 2 of the License, or
     11  *  (at your option) any later version.
     12  *
     13  *  This program is distributed in the hope that it will be useful,
     14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *  GNU General Public License for more details.
     17  *
     18  *  You should have received a copy of the GNU General Public License
     19  *  along with this program; if not, write to the Free Software
     20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include <config.h>
     26 #endif
     27 
     28 #include <stdio.h>
     29 #include <errno.h>
     30 #include <unistd.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 
     34 #include <sys/types.h>
     35 #include <netinet/in.h>
     36 
     37 #include "parser.h"
     38 
     39 #define TABLE_SIZE 10
     40 
     41 static struct {
     42 	uint16_t handle;
     43 	uint16_t cid;
     44 	struct frame msg[16];
     45 } table[TABLE_SIZE];
     46 
     47 static void add_segment(uint8_t bid, struct frame *frm, int len)
     48 {
     49 	uint16_t handle = frm->handle, cid = frm->cid;
     50 	struct frame *msg;
     51 	void *data;
     52 	int i, pos = -1;
     53 
     54 	if (bid > 15)
     55 		return;
     56 
     57 	for (i = 0; i < TABLE_SIZE; i++) {
     58 		if (table[i].handle == handle && table[i].cid == cid) {
     59 			pos = i;
     60 			break;
     61 		}
     62 
     63 		if (pos < 0 && !table[i].handle && !table[i].cid)
     64 			pos = i;
     65 	}
     66 
     67 	if (pos < 0)
     68 		return;
     69 
     70 	table[pos].handle = handle;
     71 	table[pos].cid    = cid;
     72 	msg = &table[pos].msg[bid];
     73 
     74 	data = malloc(msg->data_len + len);
     75 	if (!data)
     76 		return;
     77 
     78 	if (msg->data_len > 0)
     79 		memcpy(data, msg->data, msg->data_len);
     80 
     81 	memcpy(data + msg->data_len, frm->ptr, len);
     82 	free(msg->data);
     83 	msg->data = data;
     84 	msg->data_len += len;
     85 	msg->ptr = msg->data;
     86 	msg->len = msg->data_len;
     87 	msg->in  = frm->in;
     88 	msg->ts  = frm->ts;
     89 	msg->handle = handle;
     90 	msg->cid    = cid;
     91 }
     92 
     93 static void free_segment(uint8_t bid, struct frame *frm)
     94 {
     95 	uint16_t handle = frm->handle, cid = frm->cid;
     96 	struct frame *msg;
     97 	int i, len = 0, pos = -1;
     98 
     99 	if (bid > 15)
    100 		return;
    101 
    102 	for (i = 0; i < TABLE_SIZE; i++)
    103 		if (table[i].handle == handle && table[i].cid == cid) {
    104 			pos = i;
    105 			break;
    106 		}
    107 
    108 	if (pos < 0)
    109 		return;
    110 
    111 	msg = &table[pos].msg[bid];
    112 
    113 	if (msg->data)
    114 		free(msg->data);
    115 
    116 	msg->data = NULL;
    117 	msg->data_len = 0;
    118 
    119 	for (i = 0; i < 16; i++)
    120 		len += table[pos].msg[i].data_len;
    121 
    122 	if (!len) {
    123 		table[pos].handle = 0;
    124 		table[pos].cid = 0;
    125 	}
    126 }
    127 
    128 static struct frame *get_segment(uint8_t bid, struct frame *frm)
    129 {
    130 	uint16_t handle = frm->handle, cid = frm->cid;
    131 	int i;
    132 
    133 	if (bid > 15)
    134 		return NULL;
    135 
    136 	for (i = 0; i < TABLE_SIZE; i++)
    137 		if (table[i].handle == handle && table[i].cid == cid)
    138 			return &table[i].msg[bid];
    139 
    140 	return NULL;
    141 }
    142 
    143 static char *bst2str(uint8_t bst)
    144 {
    145 	switch (bst) {
    146 	case 0x00:
    147 		return "complete CAPI Message";
    148 	case 0x01:
    149 		return "segmented CAPI Message";
    150 	case 0x02:
    151 		return "error";
    152 	case 0x03:
    153 		return "reserved";
    154 	default:
    155 		return "unknown";
    156 	}
    157 }
    158 
    159 void cmtp_dump(int level, struct frame *frm)
    160 {
    161 	struct frame *msg;
    162 	uint8_t hdr, bid;
    163 	uint16_t len;
    164 
    165 	while (frm->len > 0) {
    166 
    167 		hdr = get_u8(frm);
    168 		bid = (hdr & 0x3c) >> 2;
    169 
    170 		switch ((hdr & 0xc0) >> 6) {
    171 		case 0x01:
    172 			len = get_u8(frm);
    173 			break;
    174 		case 0x02:
    175 			len = htons(get_u16(frm));
    176 			break;
    177 		default:
    178 			len = 0;
    179 			break;
    180 		}
    181 
    182 		p_indent(level, frm);
    183 
    184 		printf("CMTP: %s: id %d len %d\n", bst2str(hdr & 0x03), bid, len);
    185 
    186 		switch (hdr & 0x03) {
    187 		case 0x00:
    188 			add_segment(bid, frm, len);
    189 			msg = get_segment(bid, frm);
    190 			if (!msg)
    191 				break;
    192 
    193 			if (!p_filter(FILT_CAPI))
    194 				capi_dump(level + 1, msg);
    195 			else
    196 				raw_dump(level, msg);
    197 
    198 			free_segment(bid, frm);
    199 			break;
    200 		case 0x01:
    201 			add_segment(bid, frm, len);
    202 			break;
    203 		default:
    204 			free_segment(bid, frm);
    205 			break;
    206 		}
    207 
    208 		frm->ptr += len;
    209 		frm->len -= len;
    210 	}
    211 }
    212