Home | History | Annotate | Download | only in parser
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-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 #include <sys/types.h>
     34 
     35 #include "parser.h"
     36 
     37 #define PPP_U8(frm)  (get_u8(frm))
     38 #define PPP_U16(frm) (btohs(htons(get_u16(frm))))
     39 #define PPP_U32(frm) (btohl(htonl(get_u32(frm))))
     40 
     41 static int ppp_traffic = 0;
     42 
     43 static unsigned char ppp_magic1[] = { 0x7e, 0xff, 0x03, 0xc0, 0x21 };
     44 static unsigned char ppp_magic2[] = { 0x7e, 0xff, 0x7d, 0x23, 0xc0, 0x21 };
     45 static unsigned char ppp_magic3[] = { 0x7e, 0x7d, 0xdf, 0x7d, 0x23, 0xc0, 0x21 };
     46 
     47 static inline int check_for_ppp_traffic(unsigned char *data, int size)
     48 {
     49 	int i;
     50 
     51 	for (i = 0; i < size - sizeof(ppp_magic1); i++)
     52 		if (!memcmp(data + i, ppp_magic1, sizeof(ppp_magic1))) {
     53 			ppp_traffic = 1;
     54 			return i;
     55 		}
     56 
     57 	for (i = 0; i < size - sizeof(ppp_magic2); i++)
     58 		if (!memcmp(data + i, ppp_magic2, sizeof(ppp_magic2))) {
     59 			ppp_traffic = 1;
     60 			return i;
     61 		}
     62 
     63 	for (i = 0; i < size - sizeof(ppp_magic3); i++)
     64 		if (!memcmp(data + i, ppp_magic3, sizeof(ppp_magic3))) {
     65 			ppp_traffic = 1;
     66 			return i;
     67 		}
     68 
     69 	return -1;
     70 }
     71 
     72 static inline char *dir2str(uint8_t in)
     73 {
     74 	return in ? "DCE" : "DTE";
     75 }
     76 
     77 static inline char *proto2str(uint16_t proto)
     78 {
     79 	switch (proto) {
     80 	case 0x0001:
     81 		return "Padding Protocol";
     82 	case 0x0021:
     83 		return "IP";
     84 	case 0x8021:
     85 		return "IP Control Protocol";
     86 	case 0x80fd:
     87 		return "Compression Control Protocol";
     88 	case 0xc021:
     89 		return "Link Control Protocol";
     90 	case 0xc023:
     91 		return "Password Authentication Protocol";
     92 	case 0xc025:
     93 		return "Link Quality Report";
     94 	case 0xc223:
     95 		return "Challenge Handshake Authentication Protocol";
     96 	default:
     97 		return "Unknown Protocol";
     98 	}
     99 }
    100 
    101 static void hdlc_dump(int level, struct frame *frm)
    102 {
    103 	uint8_t addr = get_u8(frm);
    104 	uint8_t ctrl = get_u8(frm);
    105 	uint16_t fcs, proto;
    106 
    107 	fcs = bt_get_unaligned((uint16_t *) (frm->ptr + frm->len - 2));
    108 	frm->len -= 2;
    109 
    110 	p_indent(level, frm);
    111 
    112 	if (addr != 0xff || ctrl != 0x03) {
    113 		frm->ptr -= 2;
    114 		frm->len += 2;
    115 		printf("HDLC: %s: len %d fcs 0x%04x\n",
    116 				dir2str(frm->in), frm->len, fcs);
    117 	} else
    118 		printf("HDLC: %s: addr 0x%02x ctrl 0x%02x len %d fcs 0x%04x\n",
    119 				dir2str(frm->in), addr, ctrl, frm->len, fcs);
    120 
    121 	if (*((uint8_t *) frm->ptr) & 0x80)
    122 		proto = get_u16(frm);
    123 	else
    124 		proto = get_u8(frm);
    125 
    126 	p_indent(level + 1, frm);
    127 	printf("PPP: %s (0x%04x): len %d\n", proto2str(proto), proto, frm->len);
    128 
    129 	raw_dump(level + 1, frm);
    130 }
    131 
    132 static inline void unslip_frame(int level, struct frame *frm, int len)
    133 {
    134 	struct frame msg;
    135 	unsigned char *data, *ptr;
    136 	int i, p = 0;
    137 
    138 	data = malloc(len * 2);
    139 	if (!data)
    140 		return;
    141 
    142 	ptr = frm->ptr;
    143 
    144 	for (i = 0; i < len; i++) {
    145 		if (ptr[i] == 0x7d) {
    146 			data[p++] = ptr[i + 1] ^ 0x20;
    147 			i++;
    148 		} else
    149 			data[p++] = ptr[i];
    150 	}
    151 
    152 	memset(&msg, 0, sizeof(msg));
    153 	msg.data     = data;
    154 	msg.data_len = len * 2;
    155 	msg.ptr      = msg.data;
    156 	msg.len      = p;
    157 	msg.in       = frm->in;
    158 	msg.ts       = frm->ts;
    159 	msg.handle   = frm->handle;
    160 	msg.cid      = frm->cid;
    161 
    162 	hdlc_dump(level, &msg);
    163 
    164 	free(data);
    165 }
    166 
    167 void ppp_dump(int level, struct frame *frm)
    168 {
    169 	void *ptr, *end;
    170 	int err, len, pos = 0;
    171 
    172 	if (frm->pppdump_fd > fileno(stderr)) {
    173 		unsigned char id;
    174 		uint16_t len = htons(frm->len);
    175 		uint32_t ts = htonl(frm->ts.tv_sec & 0xffffffff);
    176 
    177 		id = 0x07;
    178 		err = write(frm->pppdump_fd, &id, 1);
    179 		err = write(frm->pppdump_fd, &ts, 4);
    180 
    181 		id = frm->in ? 0x02 : 0x01;
    182 		err = write(frm->pppdump_fd, &id, 1);
    183 		err = write(frm->pppdump_fd, &len, 2);
    184 		err = write(frm->pppdump_fd, frm->ptr, frm->len);
    185 	}
    186 
    187 	if (!ppp_traffic) {
    188 		pos = check_for_ppp_traffic(frm->ptr, frm->len);
    189 		if (pos < 0) {
    190 			raw_dump(level, frm);
    191 			return;
    192 		}
    193 
    194 		if (pos > 0) {
    195 			raw_ndump(level, frm, pos);
    196 			frm->ptr += pos;
    197 			frm->len -= pos;
    198 		}
    199 	}
    200 
    201 	frm = add_frame(frm);
    202 
    203 	while (frm->len > 0) {
    204 		ptr = memchr(frm->ptr, 0x7e, frm->len);
    205 		if (!ptr)
    206 			break;
    207 
    208 		if (frm->ptr != ptr) {
    209 			frm->len -= (ptr - frm->ptr);
    210 			frm->ptr = ptr;
    211 		}
    212 
    213 		end = memchr(frm->ptr + 1, 0x7e, frm->len - 1);
    214 		if (!end)
    215 			break;
    216 
    217 		len = end - ptr - 1;
    218 
    219 		frm->ptr++;
    220 		frm->len--;
    221 
    222 		if (len > 0) {
    223 			unslip_frame(level, frm, len);
    224 
    225 			frm->ptr += len;
    226 			frm->len -= len;
    227 		}
    228 	}
    229 }
    230