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