fix remote-snapshot with external nodes
[sliver-openvswitch.git] / planetlab / exp-tool / tunproxy.c
1 /*\r
2  * tunproxy.c --- small demo program for tunneling over UDP with tun/tap\r
3  *\r
4  * Copyright (C) 2003  Philippe Biondi <phil@secdev.org>\r
5  * Copyright (C) 2013  Felician Nemeth <nemethf@tmit.bme.hu>\r
6  *\r
7  * This program is free software; you can redistribute it and/or modify it\r
8  * under the terms of the GNU Lesser General Public License as published by\r
9  * the Free Software Foundation.\r
10  *\r
11  * This program is distributed in the hope that it will be useful, but\r
12  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
14  * Lesser General Public License for more details.\r
15  *\r
16  * http://www.secdev.org/projects/tuntap_udp/files/tunproxy.c\r
17  */\r
18 \r
19 #include <stdlib.h>\r
20 #include <stdio.h>\r
21 #include <string.h>\r
22 #include <unistd.h>\r
23 #include <sys/stat.h>\r
24 #include <fcntl.h>\r
25 #include <sys/types.h>\r
26 #include <sys/socket.h>\r
27 #include <netinet/in.h>\r
28 #include <arpa/inet.h>\r
29 #include <string.h>\r
30 #include <net/if.h>\r
31 #include <linux/if_tun.h>\r
32 #include <getopt.h>\r
33 #include <sys/ioctl.h>\r
34 #include <errno.h>\r
35 \r
36 #define PERROR(x) do { perror(x); exit(1); } while (0)\r
37 #define ERROR(x, args ...) do { fprintf(stderr,"ERROR:" x, ## args); exit(1); } while (0)\r
38 \r
39 extern void exit(int);\r
40 \r
41 void usage()\r
42 {\r
43         fprintf(stderr, "Usage: tunproxy -t target_ip:port [-p local_port] [-e]\n");\r
44         exit(0);\r
45 }\r
46 \r
47 int main(int argc, char *argv[])\r
48 {\r
49         struct sockaddr_in sin, sout, remote;\r
50         struct ifreq ifr;\r
51         int fd, s, remote_len, remote_port, local_port, l;\r
52         unsigned int soutlen;\r
53         char c, *p, *remote_ip = 0;\r
54         char buf[2000];\r
55         fd_set fdset;\r
56 \r
57         int TUNMODE = IFF_TUN, DEBUG = 0;\r
58 \r
59         while ((c = getopt(argc, argv, "t:p:ehd")) != -1) {\r
60                 switch (c) {\r
61                 case 'h':\r
62                         usage();\r
63                 case 'd':\r
64                         DEBUG++;\r
65                         break;\r
66                 case 'p':\r
67                         local_port = atoi(optarg);\r
68                         break;\r
69                 case 't':\r
70                         p = memchr(optarg,':',16);\r
71                         if (!p) ERROR("invalid argument : [%s]\n",optarg);\r
72                         *p = 0;\r
73                         remote_ip = optarg;\r
74                         remote_port = atoi(p+1);\r
75                         break;\r
76                 case 'e':\r
77                         TUNMODE = IFF_TAP;\r
78                         break;\r
79                 default:\r
80                         usage();\r
81                 }\r
82         }\r
83         if (remote_ip == 0) usage();\r
84 \r
85         if ( (fd = open("/dev/net/tun",O_RDWR)) < 0) PERROR("open");\r
86 \r
87         memset(&ifr, 0, sizeof(ifr));\r
88         ifr.ifr_flags = TUNMODE | IFF_NO_PI;\r
89         strncpy(ifr.ifr_name, "toto%d", IFNAMSIZ);\r
90         if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) PERROR("ioctl");\r
91 \r
92         printf("Allocated interface %s. Configure and use it\n", ifr.ifr_name);\r
93         \r
94         s = socket(PF_INET, SOCK_DGRAM, 0);\r
95         sin.sin_family = AF_INET;\r
96         sin.sin_addr.s_addr = htonl(INADDR_ANY);\r
97         sin.sin_port = htons(local_port);\r
98 \r
99         if ( bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0)\r
100           PERROR("bind");\r
101 \r
102         remote_len = sizeof(remote);\r
103         memset(&remote, 0, remote_len);\r
104         remote.sin_family = AF_INET;\r
105         remote.sin_port = htons(remote_port);\r
106         remote.sin_addr.s_addr=inet_addr(remote_ip);\r
107 \r
108         while (1) {\r
109                 FD_ZERO(&fdset);\r
110                 FD_SET(fd, &fdset);\r
111                 FD_SET(s, &fdset);\r
112                 if (select(fd+s+1, &fdset,NULL,NULL,NULL) < 0) PERROR("select");\r
113                 if (FD_ISSET(fd, &fdset)) {\r
114                         if (DEBUG)\r
115                           if (write(1,">", 1) < 0) PERROR("write");\r
116                         l = read(fd, buf, sizeof(buf));\r
117                         if (l < 0) \r
118                           PERROR("read");\r
119                         if (sendto(s, buf, l, 0, (struct sockaddr *)&remote, remote_len) < 0)\r
120                           PERROR("sendto");\r
121                 }\r
122                 if (FD_ISSET(s, &fdset)) {\r
123                         if (DEBUG) \r
124                           if (write(1,"<", 1) < 0) PERROR("write");\r
125                         soutlen = sizeof(sout);\r
126                         l = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&sout, &soutlen);\r
127                         if (l == -1) {\r
128                           if (write(1,"(", 1) < 0) PERROR("write");\r
129                           fprintf(stderr, "[%s,%d]", strerror(errno), l);\r
130                           continue;\r
131                         }\r
132                         if ((sout.sin_addr.s_addr != remote.sin_addr.s_addr) ||\r
133                             (sout.sin_port != remote.sin_port)) {\r
134                           printf("Got packet from  %s:%u instead of %s:%u\n", \r
135                                  inet_ntoa(sout.sin_addr), ntohs(sout.sin_port),\r
136                                  inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));\r
137                         }\r
138                         if (write(fd, buf, l) < 0) PERROR("write");\r
139                 }\r
140         }\r
141 }\r