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
23 #include <sys/stat.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
31 #include <linux/if_tun.h>
\r
33 #include <sys/ioctl.h>
\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
39 extern void exit(int);
\r
43 fprintf(stderr, "Usage: tunproxy -t target_ip:port [-p local_port] [-e]\n");
\r
47 int main(int argc, char *argv[])
\r
49 struct sockaddr_in sin, sout, remote;
\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
57 int TUNMODE = IFF_TUN, DEBUG = 0;
\r
59 while ((c = getopt(argc, argv, "t:p:ehd")) != -1) {
\r
67 local_port = atoi(optarg);
\r
70 p = memchr(optarg,':',16);
\r
71 if (!p) ERROR("invalid argument : [%s]\n",optarg);
\r
74 remote_port = atoi(p+1);
\r
83 if (remote_ip == 0) usage();
\r
85 if ( (fd = open("/dev/net/tun",O_RDWR)) < 0) PERROR("open");
\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
92 printf("Allocated interface %s. Configure and use it\n", ifr.ifr_name);
\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
99 if ( bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0)
\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
110 FD_SET(fd, &fdset);
\r
112 if (select(fd+s+1, &fdset,NULL,NULL,NULL) < 0) PERROR("select");
\r
113 if (FD_ISSET(fd, &fdset)) {
\r
115 if (write(1,">", 1) < 0) PERROR("write");
\r
116 l = read(fd, buf, sizeof(buf));
\r
119 if (sendto(s, buf, l, 0, (struct sockaddr *)&remote, remote_len) < 0)
\r
122 if (FD_ISSET(s, &fdset)) {
\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
128 if (write(1,"(", 1) < 0) PERROR("write");
\r
129 fprintf(stderr, "[%s,%d]", strerror(errno), l);
\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
138 if (write(fd, buf, l) < 0) PERROR("write");
\r