summaryrefslogtreecommitdiff
path: root/src/lib/decoder/out_pcap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/decoder/out_pcap.c')
-rw-r--r--src/lib/decoder/out_pcap.c111
1 files changed, 111 insertions, 0 deletions
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;
+}
personal git repositories of Harald Welte. Your mileage may vary