summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/decoder/gsmstack.c29
-rw-r--r--src/lib/decoder/gsmstack.h4
-rw-r--r--src/lib/decoder/gsmtap.h41
-rw-r--r--src/lib/decoder/out_pcap.c111
-rw-r--r--src/lib/decoder/out_pcap.h9
-rw-r--r--src/lib/decoder/tun.c125
-rw-r--r--src/lib/decoder/tun.h4
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 *);
personal git repositories of Harald Welte. Your mileage may vary