2 * tunproxy.c --- small demo program for tunneling over UDP with tun/tap
\r
4 * Copyright (C) 2003 Philippe Biondi <phil@secdev.org>
\r
5 * Copyright (C) 2013 Felician Nemeth <nemethf@tmit.bme.hu>
\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
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
16 * http://www.secdev.org/projects/tuntap_udp/files/tunproxy.c
\r
19 #ifdef HAVE_CONFIG_H
\r
26 #include <sys/stat.h>
\r
28 #include <sys/types.h>
\r
29 #include <sys/socket.h>
\r
30 #include <netinet/in.h>
\r
31 #include <arpa/inet.h>
\r
34 #include <linux/if_tun.h>
\r
36 #include <sys/ioctl.h>
\r
39 #define PERROR(x) do { perror(x); exit(1); } while (0)
\r
40 #define ERROR(x, args ...) do { fprintf(stderr,"ERROR:" x, ## args); exit(1); } while (0)
\r
42 extern void exit(int);
\r
46 fprintf(stderr, "Usage: tunproxy -t target_ip:port [-p local_port] [-e]\n");
\r
50 int main(int argc, char *argv[])
\r
52 struct sockaddr_in sin, sout, remote;
\r
54 int fd, s, remote_len, remote_port, local_port, l;
\r
55 unsigned int soutlen;
\r
56 char c, *p, *remote_ip = 0;
\r
60 int TUNMODE = IFF_TUN, DEBUG = 0;
\r
62 while ((c = getopt(argc, argv, "t:p:ehd")) != -1) {
\r
70 local_port = atoi(optarg);
\r
73 p = memchr(optarg,':',16);
\r
74 if (!p) ERROR("invalid argument : [%s]\n",optarg);
\r
77 remote_port = atoi(p+1);
\r
86 if (remote_ip == 0) usage();
\r
88 if ( (fd = open("/dev/net/tun",O_RDWR)) < 0) PERROR("open");
\r
90 memset(&ifr, 0, sizeof(ifr));
\r
91 ifr.ifr_flags = TUNMODE | IFF_NO_PI;
\r
92 strncpy(ifr.ifr_name, "toto%d", IFNAMSIZ);
\r
93 if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) PERROR("ioctl");
\r
95 printf("Allocated interface %s. Configure and use it\n", ifr.ifr_name);
\r
97 s = socket(PF_INET, SOCK_DGRAM, 0);
\r
98 sin.sin_family = AF_INET;
\r
99 sin.sin_addr.s_addr = htonl(INADDR_ANY);
\r
100 sin.sin_port = htons(local_port);
\r
102 if ( bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0)
\r
105 remote_len = sizeof(remote);
\r
106 memset(&remote, 0, remote_len);
\r
107 remote.sin_family = AF_INET;
\r
108 remote.sin_port = htons(remote_port);
\r
109 remote.sin_addr.s_addr=inet_addr(remote_ip);
\r
113 FD_SET(fd, &fdset);
\r
115 if (select(fd+s+1, &fdset,NULL,NULL,NULL) < 0) PERROR("select");
\r
116 if (FD_ISSET(fd, &fdset)) {
\r
118 if (write(1,">", 1) < 0) PERROR("write");
\r
119 l = read(fd, buf, sizeof(buf));
\r
122 if (sendto(s, buf, l, 0, (struct sockaddr *)&remote, remote_len) < 0)
\r
125 if (FD_ISSET(s, &fdset)) {
\r
127 if (write(1,"<", 1) < 0) PERROR("write");
\r
128 soutlen = sizeof(sout);
\r
129 l = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&sout, &soutlen);
\r
131 if (write(1,"(", 1) < 0) PERROR("write");
\r
132 fprintf(stderr, "[%s,%d]", strerror(errno), l);
\r
135 if ((sout.sin_addr.s_addr != remote.sin_addr.s_addr) ||
\r
136 (sout.sin_port != remote.sin_port)) {
\r
137 printf("Got packet from %s:%u instead of %s:%u\n",
\r
138 inet_ntoa(sout.sin_addr), ntohs(sout.sin_port),
\r
139 inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
\r
141 if (write(fd, buf, l) < 0) PERROR("write");
\r