From 6c274198ad9ed182545125fb6bfde2a99114cc0a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 27 Nov 2008 08:35:42 +0530 Subject: Add PCAP (LINKTYPE GSM incl. gsmtap hdr) support --- gsm-tvoid/src/lib/Makefile.am | 7 ++- gsm-tvoid/src/lib/gsmstack.c | 19 +++++++- gsm-tvoid/src/lib/gsmstack.h | 2 + gsm-tvoid/src/lib/gsmtap.h | 26 +++++++++++ gsm-tvoid/src/lib/out_pcap.c | 105 ++++++++++++++++++++++++++++++++++++++++++ gsm-tvoid/src/lib/out_pcap.h | 7 +++ 6 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 gsm-tvoid/src/lib/gsmtap.h create mode 100644 gsm-tvoid/src/lib/out_pcap.c create mode 100644 gsm-tvoid/src/lib/out_pcap.h diff --git a/gsm-tvoid/src/lib/Makefile.am b/gsm-tvoid/src/lib/Makefile.am index d8d504f..4f2ba65 100644 --- a/gsm-tvoid/src/lib/Makefile.am +++ b/gsm-tvoid/src/lib/Makefile.am @@ -51,7 +51,8 @@ _gsm_la_SOURCES = \ mm_f.cc \ gsm_burst_cf.cc \ gsm_burst_sink_c.cc \ - tun.c + tun.c \ + out_pcap.c # magic flags @@ -82,7 +83,9 @@ grinclude_HEADERS = \ gsm_burst_cf.h \ gsm_burst_sink_c.h \ gsm_constants.h \ - tun.h + tun.h \ + out_pcap.h \ + gsmtap.h # These swig headers get installed in ${prefix}/include/gnuradio/swig diff --git a/gsm-tvoid/src/lib/gsmstack.c b/gsm-tvoid/src/lib/gsmstack.c index ecea4f9..e09420c 100644 --- a/gsm-tvoid/src/lib/gsmstack.c +++ b/gsm-tvoid/src/lib/gsmstack.c @@ -5,6 +5,7 @@ #include "system.h" #include #include +#include #include #include "gsmstack.h" #include "gsm_constants.h" @@ -12,6 +13,8 @@ #include "sch.h" #include "cch.h" +#include "out_pcap.h" + static void out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len); #if 0 @@ -46,9 +49,14 @@ GS_new(GS_CTX *ctx) interleave_init(&ctx->interleave_ctx, 456, 114); ctx->fn = -1; ctx->bsic = -1; + ctx->tun_fd = mktun("gsm", ctx->ether_addr); if (ctx->tun_fd < 0) - return -1; + fprintf(stderr, "cannot open 'gsm' tun device, did you create it?\n"); + + ctx->pcap_fd = open_pcap_file("tvoid.pcap"); + if (ctx->pcap_fd < 0) + fprintf(stderr, "cannot open PCAP file: %s\n", strerror(errno)); return 0; } @@ -65,8 +73,14 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src) unsigned char *data; int len; - if (ts != 0) + if (ts != 0) { + /* non-0 timeslots should end up in PCAP */ + data = decode_cch(ctx, ctx->burst, &len); + if (data == NULL) + return -1; + write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, 0, data, len); return; + } if (type == SCH) { @@ -111,6 +125,7 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src) out_gsmdecode(0, 0, ts, ctx->fn - 4, data, len); write_interface(ctx->tun_fd, data+1, len-1, ctx->ether_addr); + write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, fn, data, len); #if 0 if (ctx->fn % 51 != 0) && ( (((ctx->fn % 51 + 5) % 10 == 0) || (((ctx->fn % 51) + 1) % 10 ==0) ) ) ready = 1; diff --git a/gsm-tvoid/src/lib/gsmstack.h b/gsm-tvoid/src/lib/gsmstack.h index 8230442..b4a5c96 100644 --- a/gsm-tvoid/src/lib/gsmstack.h +++ b/gsm-tvoid/src/lib/gsmstack.h @@ -23,6 +23,8 @@ typedef struct int tun_fd; unsigned char ether_addr[ETH_ALEN]; + + int pcap_fd; } GS_CTX; int GS_new(GS_CTX *ctx); diff --git a/gsm-tvoid/src/lib/gsmtap.h b/gsm-tvoid/src/lib/gsmtap.h new file mode 100644 index 0000000..6676d9a --- /dev/null +++ b/gsm-tvoid/src/lib/gsmtap.h @@ -0,0 +1,26 @@ +#ifndef _GSMTAP_H +#define _GSMTAP_H + +/* gsmtap header, pseudo-header in front of the actua GSM payload*/ + +#include + +#define GSMTAP_VERSION 0x02 + +#define GSMTAP_TYPE_UM 0x01 +#define GSMTAP_TYPE_ABIS 0x02 + +struct gsmtap_hdr { + u_int8_t version; /* version, set to 0x01 currently */ + u_int8_t hdr_len; /* length in number of 32bit words */ + u_int8_t type; /* see GSMTAP_TYPE_* */ + u_int8_t timeslot; /* timeslot (0..7 on Um) */ + + u_int16_t arfcn; /* ARFCN (frequency) */ + u_int8_t noise_db; + u_int8_t signal_db; + + u_int32_t frame_number; + +} __attribute__((packed)); +#endif /* _GSMTAP_H */ diff --git a/gsm-tvoid/src/lib/out_pcap.c b/gsm-tvoid/src/lib/out_pcap.c new file mode 100644 index 0000000..95f24f5 --- /dev/null +++ b/gsm-tvoid/src/lib/out_pcap.c @@ -0,0 +1,105 @@ +/* PCAP support for gsm-tvoid + * (C) 2008 by Harald Welte + */ + +#include +#include +#include +#include +#include +#include + +#include "out_pcap.h" +#include "gsmtap.h" + +#ifndef LINKTYPE_GSMTAP +#define LINKTYPE_GSMTAP 2342 +#endif + +#define TCPDUMP_MAGIC 0xa1b2c3d4 + +struct pcap_timeval { + int32_t tv_sec; + int32_t tv_usec; +}; + +struct pcap_sf_pkthdr { + struct pcap_timeval ts; /* time stamp */ + u_int32_t caplen; /* lenght of portion present */ + u_int32_t len; /* length of this packet */ +}; + +static int write_pcap_file_header(int fd) +{ + struct pcap_file_header pfh; + + pfh.magic = TCPDUMP_MAGIC; + pfh.version_major = PCAP_VERSION_MAJOR; + pfh.version_minor = PCAP_VERSION_MINOR; + pfh.thiszone = timezone; + pfh.sigfigs = 0; + pfh.snaplen = 1024; /* FIXME */ + pfh.linktype = LINKTYPE_GSMTAP; + + if (write(fd, &pfh, sizeof(pfh)) < sizeof(pfh)) + return -1; + + return 0; +} + +/* open pcap file and write header */ +int open_pcap_file(char *fname) +{ + int fd; + int rc; + + fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0660); + if (fd < 0) + return fd; + + rc = write_pcap_file_header(fd); + if (rc < 0) { + close(fd); + fd = -EIO; + } + + return fd; +} + +int write_pcap_packet(int fd, int arfcn, int ts, int fn, + char *data, unsigned int len) +{ + unsigned char buf[8192]; + struct pcap_sf_pkthdr *ph; + struct gsmtap_hdr *gh; + struct timeval tv; + int rc; + + printf("writing pcap packet fd=%d len=%d\n", fd, len); + + ph = (struct pcap_sf_pkthdr *) &buf[0]; + gh = (struct gsmtap_hdr *) &buf[sizeof(struct pcap_sf_pkthdr)]; + + gettimeofday(&tv, NULL); + + ph->ts.tv_sec = tv.tv_sec; + ph->ts.tv_usec = tv.tv_usec; + ph->caplen = ph->len = len + sizeof(struct gsmtap_hdr); + + gh->version = GSMTAP_VERSION; + gh->hdr_len = sizeof(struct gsmtap_hdr)>>2; + gh->type = GSMTAP_TYPE_UM; + gh->timeslot = ts; + gh->arfcn = htons(arfcn); + /* we don't support signal/noise yet */ + gh->noise_db = gh->signal_db = 0; + gh->frame_number = htonl(fn); + + memcpy(buf + sizeof(*ph) + sizeof(*gh), data, len); + + rc = write(fd, buf, sizeof(*ph) + sizeof(*gh) + len); + + fsync(fd); + + return rc; +} diff --git a/gsm-tvoid/src/lib/out_pcap.h b/gsm-tvoid/src/lib/out_pcap.h new file mode 100644 index 0000000..e8d4b3c --- /dev/null +++ b/gsm-tvoid/src/lib/out_pcap.h @@ -0,0 +1,7 @@ +#ifndef _PCAP_IF_H +#define _PCAP_IF_H + +extern int open_pcap_file(char *fname); +int write_pcap_packet(int fd, int arfcn, int ts, int fn, char *data, unsigned int len); + +#endif -- cgit v1.2.3