vpn: tcp-natting in one direction
authorPhilipp Tölke <toelke@in.tum.de>
Mon, 28 Jun 2010 12:37:43 +0000 (12:37 +0000)
committerPhilipp Tölke <toelke@in.tum.de>
Mon, 28 Jun 2010 12:37:43 +0000 (12:37 +0000)
untested and most likly unworking code

src/vpn/Makefile
src/vpn/packet.c
src/vpn/packet.h
src/vpn/tcp.c [new file with mode: 0644]
src/vpn/tcp.h [new file with mode: 0644]
src/vpn/test.c

index 783c66d923b20c33463f9ca2c4fcf0ab53e2c24b..d2d4342bbee8e8d7f2be1e4b54b8d844a75854a5 100644 (file)
@@ -3,11 +3,19 @@ CXXFLAGS = ${CFLAGS}
 
 LDFLAGS =
 
-all:default
+.PHONY: .dependencies
 
-default: test
+all: default
 
-test: test.o tun.o packet.o debug.o pretty-print.o
+default: .dependencies test
+
+test: test.o tun.o packet.o debug.o pretty-print.o tcp.o
+
+.dependencies:
+       echo > .dependencies
+       gcc -M *.c >> .dependencies
+
+-include .dependencies
 
 clean:
        rm -f *.o
index 37ce448635eb46737e1a6fff7ee6b9f727634d40..2d52dbc81f1df0e16a1c1c8e46ab6ae8e3c937e1 100644 (file)
@@ -9,12 +9,12 @@
 #include "debug.h"
 #include "packet.h"
 
-long payload(struct ip6_pkt* pkt) {{{
-       return (pkt->hdr.paylgth[0] << 8) + pkt->hdr.paylgth[1];
+long payload(struct ip6_hdr* hdr) {{{
+       return (hdr->paylgth[0] << 8) + hdr->paylgth[1];
 }}}
 
 void send_pkt(int fd, struct ip6_pkt* pkt) {{{
-       int sz = payload(pkt);
+       int sz = payload(&(pkt->hdr));
        int w = 0;
        char* buf = (char*)malloc(sz+40);
 
@@ -120,8 +120,8 @@ struct ip6_pkt* parse_ip6(struct pkt_tun* pkt) {{{
                pkt6->hdr.dadr[w] = pkt->data[24+w];
        }
 
-       pkt6->data = (unsigned char*)malloc(payload(pkt6));
-       memcpy(pkt6->data, pkt->data+40, payload(pkt6));
+       pkt6->data = (unsigned char*)malloc(payload(&(pkt6->hdr)));
+       memcpy(pkt6->data, pkt->data+40, payload(&(pkt6->hdr)));
 
        return pkt6;
 }}}
@@ -150,8 +150,8 @@ struct ip6_tcp* parse_ip6_tcp(struct ip6_pkt* pkt) {{{
        res->data.opt = (unsigned char*) malloc((res->data.off - 5)*4);
        memcpy(res->data.opt, pkt->data+20, (res->data.off - 5)*4);
 
-       res->data.data = (unsigned char*) malloc(payload(pkt) - 4*(res->data.off));
-       memcpy(res->data.data, pkt->data+4*(res->data.off), payload(pkt) - 4*(res->data.off));
+       res->data.data = (unsigned char*) malloc(payload(&(pkt->hdr)) - 4*(res->data.off));
+       memcpy(res->data.data, pkt->data+4*(res->data.off), payload(&(pkt->hdr)) - 4*(res->data.off));
 
        return res;
 }}}
index 50469093653582046aa908fce675b044cb5a7a1b..4044eecb01bee71adf3c4e6848264cbcc977c311 100644 (file)
@@ -45,6 +45,6 @@ extern struct ip6_pkt* parse_ip6(struct pkt_tun* pkt);
 
 struct ip6_tcp* parse_ip6_tcp(struct ip6_pkt*);
 
-extern long payload(struct ip6_pkt* pkt);
+extern long payload(struct ip6_hdr* pkt);
 
 #endif
diff --git a/src/vpn/tcp.c b/src/vpn/tcp.c
new file mode 100644 (file)
index 0000000..cd40f28
--- /dev/null
@@ -0,0 +1,146 @@
+#include "debug.h"
+#include "packet.h"
+#include "tcp.h"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct le {
+       int spt, dpt;
+
+       unsigned char sadr[16];
+       unsigned char dadr[16];
+
+       int socket;
+
+       struct le* next;
+};
+
+static struct le* le_head = 0;
+
+static int look_for_child(struct ip6_tcp* pkt) {
+       struct le* cur;
+
+       for(cur = le_head; cur != 0; cur = cur->next) {
+               if (cur->spt == pkt->data.spt &&/*{{{*/
+                               cur->dpt == pkt->data.spt &&
+                               cur->sadr[0] == pkt->hdr.sadr[0] &&
+                               cur->sadr[1] == pkt->hdr.sadr[1] &&
+                               cur->sadr[2] == pkt->hdr.sadr[2] &&
+                               cur->sadr[3] == pkt->hdr.sadr[3] &&
+                               cur->sadr[4] == pkt->hdr.sadr[4] &&
+                               cur->sadr[5] == pkt->hdr.sadr[5] &&
+                               cur->sadr[6] == pkt->hdr.sadr[6] &&
+                               cur->sadr[7] == pkt->hdr.sadr[7] &&
+                               cur->sadr[8] == pkt->hdr.sadr[8] &&
+                               cur->sadr[9] == pkt->hdr.sadr[9] &&
+                               cur->sadr[10] == pkt->hdr.sadr[10] &&
+                               cur->sadr[11] == pkt->hdr.sadr[11] &&
+                               cur->sadr[12] == pkt->hdr.sadr[12] &&
+                               cur->sadr[13] == pkt->hdr.sadr[13] &&
+                               cur->sadr[14] == pkt->hdr.sadr[14] &&
+                               cur->sadr[15] == pkt->hdr.sadr[15] &&
+
+                               cur->dadr[0] == pkt->hdr.dadr[0] &&
+                               cur->dadr[1] == pkt->hdr.dadr[1] &&
+                               cur->dadr[2] == pkt->hdr.dadr[2] &&
+                               cur->dadr[3] == pkt->hdr.dadr[3] &&
+                               cur->dadr[4] == pkt->hdr.dadr[4] &&
+                               cur->dadr[5] == pkt->hdr.dadr[5] &&
+                               cur->dadr[6] == pkt->hdr.dadr[6] &&
+                               cur->dadr[7] == pkt->hdr.dadr[7] &&
+                               cur->dadr[8] == pkt->hdr.dadr[8] &&
+                               cur->dadr[9] == pkt->hdr.dadr[9] &&
+                               cur->dadr[10] == pkt->hdr.dadr[10] &&
+                               cur->dadr[11] == pkt->hdr.dadr[11] &&
+                               cur->dadr[12] == pkt->hdr.dadr[12] &&
+                               cur->dadr[13] == pkt->hdr.dadr[13] &&
+                               cur->dadr[14] == pkt->hdr.dadr[14] &&
+                               cur->dadr[15] == pkt->hdr.dadr[15])/*}}}*/
+                       return cur->socket;
+       }
+       return -1;
+}
+
+static struct le* new_le() {{{
+       struct le* res = (struct le*) malloc(sizeof(struct le));
+
+       struct le** cur;
+
+       for(cur = &le_head; *cur != 0; cur = &((*cur)->next)) {}
+
+       *cur = res;
+
+       return res;
+}}}
+
+static int nat(struct ip6_tcp* pkt) {{{
+       unsigned char adr1[] = { 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
+       unsigned char adr2[] = { 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
+
+       if (strncmp((char*)adr1, (char*)pkt->hdr.dadr, 16)) {
+               int sock = socket(AF_INET, SOCK_STREAM, 0);
+               struct sockaddr_in info;
+               memset(&info, 0, sizeof(info));
+
+               info.sin_family = AF_INET;
+               info.sin_port = pkt->data.dpt;
+               inet_pton(AF_INET, "94.142.241.111", &info.sin_addr.s_addr);
+
+               connect(sock, (const struct sockaddr*)&info, sizeof(info));
+               return sock;
+       } else if (strncmp((char*)adr2, (char*)pkt->hdr.dadr, 16)) {
+               int sock = socket(AF_INET6, SOCK_STREAM, 0);
+
+               struct sockaddr_in6 info;
+               memset(&info, 0, sizeof(info));
+
+               info.sin6_family = AF_INET6;
+               info.sin6_port = pkt->data.dpt;
+
+               inet_pton(AF_INET6, "2a02:898:17:8000::42", info.sin6_addr.s6_addr);
+
+               connect(sock, (const struct sockaddr*)&info, sizeof(info));
+
+               return sock;
+       }
+       return -1;
+}}}
+
+void handle_tcp(struct ip6_tcp* pkt) {
+       signal(SIGCHLD, SIG_IGN);
+
+       int fd = look_for_child(pkt);
+
+       if (fd == -1) {
+               struct le* le = new_le();
+               le->spt = pkt->data.spt;
+               le->dpt = pkt->data.dpt;
+
+               memcpy(le->sadr, pkt->hdr.sadr, 16);
+               memcpy(le->dadr, pkt->hdr.dadr, 16);
+
+               le->socket = nat(pkt);
+               fd = le->socket;
+       }
+
+       int size = payload((&pkt->hdr)) - pkt->data.off;
+
+       int w = 0;
+       while (size > 0) {
+               w = write(fd, pkt->data.data, size - w);
+               if (w < 0) {
+                       debug(1, 0, "writing: %s\n", strerror(errno));
+               } else {
+                       size -= w;
+               }
+       }
+}
diff --git a/src/vpn/tcp.h b/src/vpn/tcp.h
new file mode 100644 (file)
index 0000000..c933b1b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _GNTUN_TCP_H_
+#define _GNTUN_TCP_H_
+
+#include "packet.h"
+
+extern void handle_tcp(struct ip6_tcp*);
+
+#endif
index acdf4249a42344be158726f4c2840e570ea11f2d..3672b9df2cb870e67876aeb9ce9747626681715b 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/socket.h>
+#include <string.h>
 
 #include <linux/if.h>
 
@@ -8,6 +9,7 @@
 #include "tun.h"
 #include "debug.h"
 #include "pretty-print.h"
+#include "tcp.h"
 
 int main(int c, char** v) {
        char dev[IFNAMSIZ];
@@ -32,6 +34,7 @@ int main(int c, char** v) {
                                                pkt_printf(pkt6);
                                                struct ip6_tcp* pkt6_tcp = parse_ip6_tcp(pkt6);
                                                pkt_printf_ip6tcp(pkt6_tcp);
+                                               handle_tcp(pkt6_tcp);
                                                break;
                                }
                                break;