diff options
-rw-r--r-- | gsm-tvoid/src/lib/Makefile.am | 6 | ||||
-rw-r--r-- | gsm-tvoid/src/lib/gsmstack.c | 4 | ||||
-rw-r--r-- | gsm-tvoid/src/lib/gsmstack.h | 4 | ||||
-rw-r--r-- | gsm-tvoid/src/lib/tun.c | 125 | ||||
-rw-r--r-- | gsm-tvoid/src/lib/tun.h | 4 |
5 files changed, 141 insertions, 2 deletions
diff --git a/gsm-tvoid/src/lib/Makefile.am b/gsm-tvoid/src/lib/Makefile.am index fa876b2..d8d504f 100644 --- a/gsm-tvoid/src/lib/Makefile.am +++ b/gsm-tvoid/src/lib/Makefile.am @@ -50,7 +50,8 @@ _gsm_la_SOURCES = \ mm_c.cc \ mm_f.cc \ gsm_burst_cf.cc \ - gsm_burst_sink_c.cc + gsm_burst_sink_c.cc \ + tun.c # magic flags @@ -80,7 +81,8 @@ grinclude_HEADERS = \ mm_f.h \ gsm_burst_cf.h \ gsm_burst_sink_c.h \ - gsm_constants.h + gsm_constants.h \ + tun.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 22fa170..ecea4f9 100644 --- a/gsm-tvoid/src/lib/gsmstack.c +++ b/gsm-tvoid/src/lib/gsmstack.c @@ -46,6 +46,9 @@ 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; return 0; } @@ -107,6 +110,7 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src) //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); #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 d79a40f..8230442 100644 --- a/gsm-tvoid/src/lib/gsmstack.h +++ b/gsm-tvoid/src/lib/gsmstack.h @@ -6,6 +6,7 @@ extern "C" { #endif +#include <linux/if_ether.h> #include "interleave.h" typedef struct @@ -19,6 +20,9 @@ typedef struct /* FIXME: later do this per each ts per each arfcn */ unsigned char burst[4 * 58 * 2]; int burst_count; + + int tun_fd; + unsigned char ether_addr[ETH_ALEN]; } GS_CTX; int GS_new(GS_CTX *ctx); diff --git a/gsm-tvoid/src/lib/tun.c b/gsm-tvoid/src/lib/tun.c new file mode 100644 index 0000000..2abda90 --- /dev/null +++ b/gsm-tvoid/src/lib/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/gsm-tvoid/src/lib/tun.h b/gsm-tvoid/src/lib/tun.h new file mode 100644 index 0000000..a7868c4 --- /dev/null +++ b/gsm-tvoid/src/lib/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 *); |