diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/decoder/gsmstack.c | 29 | ||||
-rw-r--r-- | src/lib/decoder/gsmstack.h | 4 | ||||
-rw-r--r-- | src/lib/decoder/gsmtap.h | 41 | ||||
-rw-r--r-- | src/lib/decoder/out_pcap.c | 111 | ||||
-rw-r--r-- | src/lib/decoder/out_pcap.h | 9 | ||||
-rw-r--r-- | src/lib/decoder/tun.c | 125 | ||||
-rw-r--r-- | src/lib/decoder/tun.h | 4 |
7 files changed, 306 insertions, 17 deletions
diff --git a/src/lib/decoder/gsmstack.c b/src/lib/decoder/gsmstack.c index ceda6c5..a1f32d8 100644 --- a/src/lib/decoder/gsmstack.c +++ b/src/lib/decoder/gsmstack.c @@ -84,17 +84,17 @@ GS_new(GS_CTX *ctx) ctx->fn = -1; ctx->bsic = -1; -// ctx->tun_fd = mktun("gsm", ctx->ether_addr); -// if (ctx->tun_fd < 0) -// fprintf(stderr, "cannot open 'gsm' tun device, did you create it?\n"); + ctx->tun_fd = mktun("gsm", ctx->ether_addr); + if (ctx->tun_fd < 0) + 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)); + ctx->pcap_fd = open_pcap_file("tvoid.pcap"); + if (ctx->pcap_fd < 0) + fprintf(stderr, "cannot open PCAP file: %s\n", strerror(errno)); -// ctx->burst_pcap_fd = open_pcap_file("tvoid-burst.pcap"); -// if (ctx->burst_pcap_fd < 0) -// fprintf(stderr, "cannot open burst PCAP file: %s\n", strerror(errno)); + ctx->burst_pcap_fd = open_pcap_file("tvoid-burst.pcap"); + if (ctx->burst_pcap_fd < 0) + fprintf(stderr, "cannot open burst PCAP file: %s\n", strerror(errno)); return 0; } @@ -118,8 +118,8 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src, int fn) /* write burst to burst PCAP file */ burst_octify(octified, src, USEFUL_BITS); -// write_pcap_packet(ctx->burst_pcap_fd, 0 /* arfcn */, ts, ctx->fn, -// 1, type, octified, BURST_BYTES); + write_pcap_packet(ctx->burst_pcap_fd, 0 /* arfcn */, ts, ctx->fn, + 1, type, octified, BURST_BYTES); #if 0 if (ts != 0) { @@ -177,9 +177,9 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src, int fn) //DEBUGF("OK TS %d, len %d\n", ts, len); 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, ctx->fn, -// 0, NORMAL, data, len); + write_interface(ctx->tun_fd, data+1, len-1, ctx->ether_addr); + write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, + 0, NORMAL, data, len); #if 0 if (ctx->fn % 51 != 0) && ( (((ctx->fn % 51 + 5) % 10 == 0) || (((ctx->fn % 51) + 1) % 10 ==0) ) ) ready = 1; @@ -204,4 +204,3 @@ out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len) printf("\n"); fflush(stdout); } - diff --git a/src/lib/decoder/gsmstack.h b/src/lib/decoder/gsmstack.h index 7295b08..9355785 100644 --- a/src/lib/decoder/gsmstack.h +++ b/src/lib/decoder/gsmstack.h @@ -29,8 +29,8 @@ typedef struct int tun_fd; unsigned char ether_addr[ETH_ALEN]; -// int pcap_fd; -// int burst_pcap_fd; + int pcap_fd; + int burst_pcap_fd; } GS_CTX; int GS_new(GS_CTX *ctx); diff --git a/src/lib/decoder/gsmtap.h b/src/lib/decoder/gsmtap.h new file mode 100644 index 0000000..1022194 --- /dev/null +++ b/src/lib/decoder/gsmtap.h @@ -0,0 +1,41 @@ +#ifndef _GSMTAP_H +#define _GSMTAP_H + +/* gsmtap header, pseudo-header in front of the actua GSM payload*/ + +#include <sys/types.h> + +#define GSMTAP_VERSION 0x01 + +#define GSMTAP_TYPE_UM 0x01 +#define GSMTAP_TYPE_ABIS 0x02 +#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ + +#define GSMTAP_BURST_UNKNOWN 0x00 +#define GSMTAP_BURST_FCCH 0x01 +#define GSMTAP_BURST_PARTIAL_SCH 0x02 +#define GSMTAP_BURST_SCH 0x03 +#define GSMTAP_BURST_CTS_SCH 0x04 +#define GSMTAP_BURST_COMPACT_SCH 0x05 +#define GSMTAP_BURST_NORMAL 0x06 +#define GSMTAP_BURST_DUMMY 0x07 +#define GSMTAP_BURST_ACCESS 0x08 + +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; /* noise figure in dB */ + u_int8_t signal_db; /* signal level in dB */ + + u_int32_t frame_number; /* GSM Frame Number (FN) */ + + u_int8_t burst_type; /* Type of burst, see above */ + u_int8_t antenna_nr; /* Antenna Number */ + u_int16_t res; /* reserved for future use (RFU) */ + +} __attribute__((packed)); +#endif /* _GSMTAP_H */ diff --git a/src/lib/decoder/out_pcap.c b/src/lib/decoder/out_pcap.c new file mode 100644 index 0000000..4da5fd6 --- /dev/null +++ b/src/lib/decoder/out_pcap.c @@ -0,0 +1,111 @@ +/* PCAP support for gsm-tvoid + * (C) 2008 by Harald Welte <laforge@gnumonks.org> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <pcap.h> +#include <errno.h> +#include <time.h> + +#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, + int burst, int burst_type, + const unsigned char *data, unsigned int len) +{ + unsigned char buf[8192]; + struct pcap_sf_pkthdr *ph; + struct gsmtap_hdr *gh; + struct timeval tv; + int rc; + + if (fd < 0) + return -EINVAL; + + 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; + if (burst) + gh->type = GSMTAP_TYPE_UM_BURST; + else + 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); + gh->burst_type = burst_type & 0xff; + + memcpy(buf + sizeof(*ph) + sizeof(*gh), data, len); + + rc = write(fd, buf, sizeof(*ph) + sizeof(*gh) + len); + + //fsync(fd); + + return rc; +} diff --git a/src/lib/decoder/out_pcap.h b/src/lib/decoder/out_pcap.h new file mode 100644 index 0000000..5ae5e3c --- /dev/null +++ b/src/lib/decoder/out_pcap.h @@ -0,0 +1,9 @@ +#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, + int burst, int burst_type, + const unsigned char *data, unsigned int len); +#endif diff --git a/src/lib/decoder/tun.c b/src/lib/decoder/tun.c new file mode 100644 index 0000000..2abda90 --- /dev/null +++ b/src/lib/decoder/tun.c @@ -0,0 +1,125 @@ +// $Id: tun.cc,v 1.2 2007-07-07 16:31:42 jl Exp $ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <libgen.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <linux/if_tun.h> +#include <linux/if.h> +#include <linux/if_ether.h> +#include <arpa/inet.h> + +int mktun(const char *chan_name, unsigned char *ether_addr) { + + struct ifreq ifr; + // struct ifreq ifw; + char if_name[IFNAMSIZ]; + int fd, one = 1; + // int sd; + + // construct TUN interface + if((fd = open("/dev/net/tun", O_RDWR)) == -1) { + perror("open"); + return -1; + } + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", chan_name); + if(ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) { + perror("TUNSETIFF"); + close(fd); + return -1; + } + + // save actual name + memcpy(if_name, ifr.ifr_name, IFNAMSIZ); + + // get ether addr + memset(&ifr, 0, sizeof(ifr)); + memcpy(ifr.ifr_name, if_name, IFNAMSIZ); + if(ioctl(fd, SIOCGIFHWADDR, (void *)&ifr) == -1) { + perror("SIOCGIFHWADDR"); + close(fd); + return -1; + } + memcpy(ether_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + + // set persistent + if(ioctl(fd, TUNSETPERSIST, (void *)&one) == -1) { + perror("TUNSETPERSIST"); + close(fd); + return -1; + } + + // set interface up + /* XXX must be root + if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + perror("socket"); + close(fd); + return -1; + } + + // get current flags + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1); + if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) { + perror("SIOCGIFFLAGS"); + close(sd); + close(fd); + return -1; + } + + // set up + memset(&ifw, 0, sizeof(ifw)); + strncpy(ifw.ifr_name, if_name, IFNAMSIZ - 1); + ifw.ifr_flags = ifr.ifr_flags | IFF_UP | IFF_RUNNING; + if(ioctl(sd, SIOCSIFFLAGS, &ifw) == -1) { + perror("SIOCSIFFLAGS"); + close(sd); + close(fd); + return -1; + } + close(sd); + */ + + return fd; +} + + +static inline int min(int a, int b) { + + return (a < b)? a : b; +} + + +static const unsigned int DEFAULT_MTU = 1500; +static const unsigned short ether_type = 0xfed5; // current dtap ethertype + +int write_interface(int fd, unsigned char *data, unsigned int data_len, + unsigned char *ether_addr) { + + unsigned char frame[DEFAULT_MTU]; // XXX buffer overflow? + struct ethhdr eh; + + if(fd < 0) + return data_len; + + memcpy(eh.h_dest, ether_addr, ETH_ALEN); + memcpy(eh.h_source, ether_addr, ETH_ALEN); + eh.h_proto = htons(ether_type); + + memcpy(frame, &eh, sizeof(eh)); + memcpy(frame + sizeof(eh), data, + min(data_len, sizeof(frame) - sizeof(eh))); + + if(write(fd, frame, sizeof(eh) + data_len) == -1) { + perror("write"); + return -1; + } + + return data_len; +} diff --git a/src/lib/decoder/tun.h b/src/lib/decoder/tun.h new file mode 100644 index 0000000..a7868c4 --- /dev/null +++ b/src/lib/decoder/tun.h @@ -0,0 +1,4 @@ +// $Id: tun.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $ + +int mktun(const char *, unsigned char *); +int write_interface(int, unsigned char *, unsigned int, unsigned char *); |