Add the option to write the communication on the D Channel to a pcap file

When using ISDN as network type and using a fake LAPD encapsulation
wireshark should be able to recognize some bits if dump.

Append a dummy LAPD header. It is not clear to me if the Control field
of the LAPD frame is part of the msg or if we need to add it as well.

TODO:
    - Do the same for the B Channel
    - Write out time
    - Check if more of the LAPD frame needs to be prepended. The
      information from the mISDNhead comes into mind. Maybe it makes
      sense to start a custom wireshark mISDN dissector.
This commit is contained in:
Holger Freyther 2009-01-02 00:40:15 +00:00
parent 355701bcc0
commit 9a3ee0ff1b
3 changed files with 111 additions and 1 deletions

View File

@ -22,5 +22,6 @@
int mi_setup(struct gsm_bts *bts, int cardnr,
void (cb)(int event, struct gsm_bts *bts));
void mi_set_pcap_fd(int fd);
#endif

View File

@ -27,6 +27,8 @@
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
#define _GNU_SOURCE
#include <getopt.h>
@ -689,6 +691,20 @@ static int bootstrap_network(void)
return 0;
}
static void create_pcap_file(char *file)
{
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open(file, O_WRONLY|O_TRUNC|O_CREAT, mode);
if (fd < 0) {
perror("Failed to open file for pcap");
return;
}
mi_set_pcap_fd(fd);
}
static void print_usage()
{
printf("Usage: bsc_hack\n");
@ -704,6 +720,7 @@ static void print_help()
printf(" -l --database db-name The database to use\n");
printf(" -a --authorize-everyone Allow everyone into the network.\n");
printf(" -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
printf(" -p --pcap file The filename of the pcap file\n");
printf(" -h --help this text\n");
}
@ -720,10 +737,11 @@ static void handle_options(int argc, char** argv)
{"database", 1, 0, 'l'},
{"authorize-everyone", 0, 0, 'a'},
{"reject-cause", 1, 0, 'r'},
{"pcap", 1, 0, 'p'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hc:n:d:sar:",
c = getopt_long(argc, argv, "hc:n:d:sar:p:",
long_options, &option_index);
if (c == -1)
break;
@ -754,6 +772,9 @@ static void handle_options(int argc, char** argv)
case 'r':
gsm0408_set_reject_cause(atoi(optarg));
break;
case 'p':
create_pcap_file(optarg);
break;
default:
/* ignore */
break;

View File

@ -1,6 +1,7 @@
/* OpenBSC Abis interface to mISDNuser */
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
*
* All Rights Reserved
*
@ -45,6 +46,88 @@
#define NUM_E1_TS 32
/*
* pcap writing of the misdn load
* pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat
*/
#define WTAP_ENCAP_ISDN 17
#define PCAP_INPUT 0
#define PCAP_OUTPUT 1
struct pcap_hdr {
u_int32_t magic_number;
u_int16_t version_major;
u_int16_t version_minor;
int32_t thiszone;
u_int32_t sigfigs;
u_int32_t snaplen;
u_int32_t network;
} __attribute__((packed));
struct pcaprec_hdr {
u_int32_t ts_sec;
u_int32_t ts_usec;
u_int32_t incl_len;
u_int32_t orig_len;
} __attribute__((packed));
struct fake_lapd_frame {
u_int8_t ea1 : 1;
u_int8_t cr : 1;
u_int8_t sapi : 6;
u_int8_t ea2 : 1;
u_int8_t tei : 7;
u_int8_t control_foo; /* fake UM's ... */
} __attribute__((packed));
static int pcap_fd = -1;
void mi_set_pcap_fd(int fd)
{
int ret;
struct pcap_hdr header = {
.magic_number = 0xa1b2c3d4,
.version_major = 2,
.version_minor = 4,
.thiszone = 0,
.sigfigs = 0,
.snaplen = 65535,
.network = WTAP_ENCAP_ISDN,
};
pcap_fd = fd;
ret = write(pcap_fd, &header, sizeof(header));
}
static void write_pcap_packet(int direction, struct sockaddr_mISDN* addr,
struct msgb *msg) {
if (pcap_fd < 0)
return;
int ret;
struct fake_lapd_frame header = {
.ea1 = 0,
.cr = PCAP_OUTPUT ? 1 : 0,
.sapi = addr->sapi & 0x3F,
.ea2 = 1,
.tei = addr->tei & 0x7F,
.control_foo = 0x13 /* UI with P set */,
};
struct pcaprec_hdr payload_header = {
.ts_sec = 0,
.ts_usec = 0,
.incl_len = msg->len + sizeof(header) - MISDN_HEADER_LEN,
.orig_len = msg->len + sizeof(header) - MISDN_HEADER_LEN,
};
ret = write(pcap_fd, &header, sizeof(header));
ret = write(pcap_fd, &payload_header, sizeof(payload_header));
ret = write(pcap_fd, msg->data + MISDN_HEADER_LEN,
msg->len - MISDN_HEADER_LEN);
}
/* data structure for one E1 interface with A-bis */
struct mi_e1_handle {
struct gsm_bts *bts;
@ -122,6 +205,8 @@ static int handle_ts1_read(struct bsc_fd *bfd)
DEBUGP(DMI, "<= len = %d, prim(0x%x) id(0x%x)\n",
ret, hh->prim, hh->id);
write_pcap_packet(PCAP_INPUT, &l2addr, msg);
switch (hh->prim) {
case DL_INFORMATION_IND:
DEBUGP(DMI, "got DL_INFORMATION_IND\n");
@ -218,6 +303,8 @@ static int handle_ts1_write(struct bsc_fd *bfd)
fprintf(stdout, "OML TX: ");
hexdump(l2_data, msg->len - MISDN_HEADER_LEN);
}
write_pcap_packet(PCAP_OUTPUT, &e1h->omladdr, msg);
ret = sendto(bfd->fd, msg->data, msg->len, 0,
(struct sockaddr *)&e1h->omladdr,
sizeof(e1h->omladdr));
@ -243,6 +330,7 @@ static int handle_ts1_write(struct bsc_fd *bfd)
hexdump(l2_data, msg->len - MISDN_HEADER_LEN);
}
write_pcap_packet(PCAP_OUTPUT, &e1h->l2addr, msg);
ret = sendto(bfd->fd, msg->data, msg->len, 0,
(struct sockaddr *)&e1h->l2addr,
sizeof(e1h->l2addr));