aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/openbsc/misdn.h1
-rw-r--r--src/bsc_hack.c23
-rw-r--r--src/misdn.c88
3 files changed, 111 insertions, 1 deletions
diff --git a/include/openbsc/misdn.h b/include/openbsc/misdn.h
index f3f198022..09dc5ba3f 100644
--- a/include/openbsc/misdn.h
+++ b/include/openbsc/misdn.h
@@ -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
diff --git a/src/bsc_hack.c b/src/bsc_hack.c
index 9fa0157de..c59024a90 100644
--- a/src/bsc_hack.c
+++ b/src/bsc_hack.c
@@ -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;
diff --git a/src/misdn.c b/src/misdn.c
index ab378da34..0d54c7928 100644
--- a/src/misdn.c
+++ b/src/misdn.c
@@ -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));