android: fix the path of the tunnel node in the /dev tree
[olsrd.git] / contrib / netsimpcap / src / network_tap.c
1
2 /*
3  * NetsimPcap - a userspace network bridge with simulated packet loss
4  *             Copyright 2008 H. Rogge (rogge@fgan.de)
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <pthread.h>
23 #include <stddef.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <signal.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <arpa/inet.h>
31 #include <linux/if_ether.h>
32 #include <linux/if_packet.h>
33 #include <linux/if_tun.h>
34 #include <net/if_arp.h>
35 #include <netinet/ip.h>
36 #include <netinet/udp.h>
37 #include <net/if.h>
38 #include <net/route.h>
39 #include <sys/ioctl.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42
43 #include "config.h"
44 #include "debug.h"
45 #include "network_tap.h"
46 #include "kernel_tunnel.h"
47
48 char macBroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
49
50 /*
51  * This function translates a mac address from string
52  * to binary format.
53  *
54  * @param pointer to source string
55  * @param pointer to target mac adresee
56  * @return 0 if successful, 1 for an error
57  */
58 int
59 readMac(char *value, MacAddress * target)
60 {
61   char buffer[13];
62   int index = 0;
63
64   memset(buffer, 0, sizeof(buffer));
65
66   char c;
67   while ((c = *value++)) {
68     switch (c) {
69     case '0':
70     case '1':
71     case '2':
72     case '3':
73     case '4':
74     case '5':
75     case '6':
76     case '7':
77     case '8':
78     case '9':
79     case 'a':
80     case 'A':
81     case 'b':
82     case 'B':
83     case 'c':
84     case 'C':
85     case 'd':
86     case 'D':
87     case 'e':
88     case 'E':
89     case 'f':
90     case 'F':
91       if (index > 11) {
92         return 1;
93       }
94       buffer[index++] = c;
95       break;
96     default:
97       break;
98     }
99   }
100
101   if (index < 12) {
102     return 1;
103   }
104
105   for (index = 5; index >= 0; index--) {
106     buffer[index * 2 + 2] = 0;
107
108     int value;
109     sscanf(&buffer[index], "%x", &value);
110     target->mac[index] = (char)value;
111   }
112   return 0;
113 }
114
115 /*
116  * closeTap
117  *
118  * This function close a tap device
119  *
120  * @param file destriptor of the tap device
121  */
122 void
123 closeTap(int fd)
124 {
125   close(fd);
126 }
127
128 /*
129  * createTap
130  *
131  * This function creates a tap device, sets a mac address
132  * and the broadcast address and activates the device
133  *
134  * @param pointer to device name
135  * @param pointer to mac address
136  * @return file descriptor of tap device, -1 if an error
137  * happened
138  */
139 int
140 createTap(char *name, MacAddress * mac)
141 {
142   static const char * deviceName = OS_TUNNEL_PATH;
143   int etfd;
144   struct ifreq ifreq;
145
146   int ioctlSkfd;
147   int ioctlres;
148
149   etfd = open(deviceName, O_RDWR);
150   if (etfd < 0) {
151     printf("Cannot open tap device!\n");
152     return -1;
153   }
154
155   memset(&ifreq, 0, sizeof(ifreq));
156   strncpy(ifreq.ifr_name, name, IFNAMSIZ - 1);
157   ifreq.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
158
159   /*
160    * Specify the IFF_TAP flag for Ethernet packets.
161    * Specify IFF_NO_PI for not receiving extra meta packet information.
162    */
163   ifreq.ifr_flags = IFF_TAP;
164   ifreq.ifr_flags |= IFF_NO_PI;
165
166   if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0) {
167     close(etfd);
168     printf("Cannot set tun device type!\n");
169     return -1;
170   }
171
172   memset(&ifreq, 0, sizeof(ifreq));
173   strncpy(ifreq.ifr_name, name, IFNAMSIZ - 1);
174   ifreq.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
175   ifreq.ifr_addr.sa_family = AF_INET;
176
177   ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
178   if (ioctlSkfd < 0) {
179     close(etfd);
180     printf("Cannot open configuration socket!\n");
181     return -1;
182   }
183
184   /* Set hardware address */
185   ifreq.ifr_addr.sa_family = ARPHRD_ETHER;
186   memcpy(ifreq.ifr_addr.sa_data, mac, 6);
187   ioctlres = ioctl(ioctlSkfd, SIOCSIFHWADDR, &ifreq);
188   if (ioctlres >= 0) {
189     /* Set hardware broadcast */
190     memcpy(ifreq.ifr_addr.sa_data, macBroadcast, 6);
191     ioctlres = ioctl(ioctlSkfd, SIOCSIFHWBROADCAST, &ifreq);
192     if (ioctlres >= 0) {
193       /* Bring EtherTunTap interface up (if not already) */
194       ifreq.ifr_addr.sa_family = AF_INET;
195       ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
196       if (ioctlres >= 0) {
197         ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
198         ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
199       }
200     }
201   }
202   if (ioctlres < 0) {
203     printf("Configuration of tun device failed! (%d %s)\n", errno, strerror(errno));
204     close(etfd);
205     close(ioctlSkfd);
206     return -1;
207   }
208
209   /* Set the multicast flag on the interface */
210   memset(&ifreq, 0, sizeof(ifreq));
211   strncpy(ifreq.ifr_name, name, IFNAMSIZ - 1);
212   ifreq.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
213
214   ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
215   if (ioctlres >= 0) {
216     ifreq.ifr_flags |= IFF_MULTICAST;
217     ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
218   }
219
220   close(ioctlSkfd);
221   return etfd;
222 }
223
224 /*
225  * Local Variables:
226  * c-basic-offset: 2
227  * indent-tabs-mode: nil
228  * End:
229  */