Contiki 3.x
tapdev6.c
1 /*
2  * Copyright (c) 2001, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of the Institute nor the names of its contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * Author: Adam Dunkels <adam@sics.se>
33  *
34  */
35 
36 #include "net/ip/uip.h"
37 #include "net/ip/uipopt.h"
38 
39 #if UIP_CONF_IPV6
40 
41 #include <fcntl.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <sys/ioctl.h>
47 #include <sys/socket.h>
48 #include <sys/types.h>
49 #include <sys/time.h>
50 #include <sys/uio.h>
51 #include <sys/socket.h>
52 
53 
54 #ifdef linux
55 #include <sys/ioctl.h>
56 #include <linux/if.h>
57 #include <linux/if_tun.h>
58 #define DEVTAP "/dev/net/tun"
59 #else /* linux */
60 #define DEVTAP "/dev/tap0"
61 #endif /* linux */
62 
63 #ifdef __APPLE__
64 #include <net/if.h>
65 #include <netinet/in.h>
66 #include <netinet6/in6_var.h>
67 #include <netinet6/nd6.h> // ND6_INFINITE_LIFETIME
68 #include <fcntl.h>
69 #include <sys/stat.h>
70 #include <sys/errno.h>
71 #include <net/if_dl.h> // struct sockaddr_dl
72 #include <net/route.h> // AF_ROUTE things
73 #endif
74 
75 #include "tapdev6.h"
76 #include "contiki-net.h"
77 
78 #define DROP 0
79 
80 #if DROP
81 static int drop = 0;
82 #endif
83 
84 static int fd = -1;
85 
86 static unsigned long lasttime;
87 
88 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
89 #define IPBUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
90 
91 #define DEBUG 0
92 #if DEBUG
93 #define PRINTF(...) printf(__VA_ARGS__)
94 #define PRINT6ADDR(addr) PRINTF("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
95 #else
96 #define PRINTF(...)
97 #define PRINT6ADDR(addr)
98 #endif
99 
100 static void do_send(void);
101 uint8_t tapdev_send(const uip_lladdr_t *lladdr);
102 
103 /*---------------------------------------------------------------------------*/
104 int
105 tapdev_fd(void)
106 {
107  return fd;
108 }
109 
110 
111 uint16_t
112 tapdev_poll(void)
113 {
114  fd_set fdset;
115  struct timeval tv;
116  int ret;
117 
118  tv.tv_sec = 0;
119  tv.tv_usec = 0;
120 
121  FD_ZERO(&fdset);
122  if(fd > 0) {
123  FD_SET(fd, &fdset);
124  }
125 
126  ret = select(fd + 1, &fdset, NULL, NULL, &tv);
127 
128  if(ret == 0) {
129  return 0;
130  }
131  ret = read(fd, uip_buf, UIP_BUFSIZE);
132 
133  PRINTF("tapdev6: read %d bytes (max %d)\n", ret, UIP_BUFSIZE);
134 
135  if(ret == -1) {
136  perror("tapdev_poll: read");
137  }
138  return ret;
139 }
140 /*---------------------------------------------------------------------------*/
141 #if defined(__APPLE__)
142 static int reqfd = -1, sfd = -1, interface_index;
143 
144 static void
145 tapdev_init_darwin_routes(void)
146 {
147  struct stat st;
148 
149  if(-1 == fstat(fd, &st)) {
150  perror("tapdev: fstat failed.");
151  exit(EXIT_FAILURE);
152  }
153 
154  /************* Add address *************/
155 
156  struct in6_aliasreq addreq6 = { };
157  reqfd = socket(AF_INET6, SOCK_DGRAM, 0);
158 
159  if(-1 == fcntl(reqfd, F_SETFD, FD_CLOEXEC)) {
160  perror("tapdev: fcntl failed.");
161  exit(EXIT_FAILURE);
162  }
163 
164  devname_r(st.st_rdev, S_IFCHR, addreq6.ifra_name,
165  sizeof(addreq6.ifra_name));
166 
167  addreq6.ifra_addr.sin6_family = AF_INET6;
168  addreq6.ifra_addr.sin6_len = sizeof(addreq6.ifra_addr);
169  addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA);
170  addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[7] = UIP_HTONS(0x0001);
171 
172  addreq6.ifra_prefixmask.sin6_family = AF_INET6;
173  addreq6.ifra_prefixmask.sin6_len = sizeof(addreq6.ifra_prefixmask);
174  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[0] =
175  UIP_HTONS(0xFFFF);
176  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[1] =
177  UIP_HTONS(0xFFFF);
178  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[2] =
179  UIP_HTONS(0xFFFF);
180  addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[3] =
181  UIP_HTONS(0xFFFF);
182 
183  addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
184  addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
185  addreq6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
186  addreq6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;
187 
188  if(-1 == ioctl(reqfd, SIOCAIFADDR_IN6, &addreq6)) {
189  perror("tapdev: Uable to add address, call to ioctl failed.");
190  exit(EXIT_FAILURE);
191  }
192 
193  /************* Add route *************/
194 
195  int s = socket(AF_ROUTE, SOCK_RAW, AF_INET6);
196 
197  if(s == -1) {
198  perror("tapdev: Unable to add route, call to socket() failed.");
199 
200  // Failing to add the route is not fatal, so just return.
201  return;
202  }
203 
204  sfd = s;
205  interface_index = if_nametoindex(devname(st.st_rdev, S_IFCHR));
206 
207  PRINTF("tapdev: if_nametoindex(devname(st.st_rdev, S_IFCHR)) = %d\n",
208  interface_index);
209  PRINTF("tapdev: devname(st.st_rdev, S_IFCHR) = %s\n",
210  devname(st.st_rdev, S_IFCHR));
211 
212  struct {
213  struct rt_msghdr hdr;
214  struct sockaddr_in6 dst;
215  struct sockaddr_dl gw;
216  struct sockaddr_in6 mask;
217  } msg = {};
218 
219  msg.hdr.rtm_msglen = sizeof(msg);
220  msg.hdr.rtm_version = RTM_VERSION;
221  msg.hdr.rtm_type = RTM_ADD;
222  msg.hdr.rtm_index = interface_index;
223  msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
224  msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
225  msg.hdr.rtm_pid = getpid();
226  msg.hdr.rtm_seq = 0;
227 
228  msg.dst.sin6_family = AF_INET6;
229  msg.dst.sin6_len = sizeof(msg.dst);
230  msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA);
231 
232  msg.gw.sdl_family = AF_LINK;
233  msg.gw.sdl_len = sizeof(msg.gw);
234  msg.gw.sdl_index = interface_index;
235 
236  msg.mask.sin6_family = AF_INET6;
237  msg.mask.sin6_len = sizeof(msg.mask);
238  msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF);
239  msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF);
240  msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF);
241  msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF);
242 
243  if(-1 == write(s, &msg, sizeof(msg))) {
244  perror("tapdev: Unable to add route, call to write() failed.");
245 
246  // Failing to add the route is not fatal, so just return.
247  return;
248  }
249 }
250 /*---------------------------------------------------------------------------*/
251 static void
252 tapdev_cleanup_darwin_routes(void)
253 {
254  struct {
255  struct rt_msghdr hdr;
256  struct sockaddr_in6 dst;
257  struct sockaddr_dl gw;
258  struct sockaddr_in6 mask;
259  } msg = {};
260 
261  msg.hdr.rtm_msglen = sizeof(msg);
262  msg.hdr.rtm_version = RTM_VERSION;
263  msg.hdr.rtm_type = RTM_DELETE;
264  msg.hdr.rtm_index = interface_index;
265  msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
266  msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
267  msg.hdr.rtm_pid = getpid();
268  msg.hdr.rtm_seq = 0;
269 
270  msg.dst.sin6_family = AF_INET6;
271  msg.dst.sin6_len = sizeof(msg.dst);
272  msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA);
273 
274  msg.gw.sdl_family = AF_LINK;
275  msg.gw.sdl_len = sizeof(msg.gw);
276  msg.gw.sdl_index = interface_index;
277 
278  msg.mask.sin6_family = AF_INET6;
279  msg.mask.sin6_len = sizeof(msg.mask);
280  msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF);
281  msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF);
282  msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF);
283  msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF);
284  if(-1 == write(sfd, &msg, sizeof(msg))) {
285  perror("tapdev: Unable to delete route");
286  exit(EXIT_FAILURE);
287  }
288 
289  close(reqfd);
290  close(sfd);
291 }
292 #endif // defined(__APPLE__)
293 /*---------------------------------------------------------------------------*/
294 void
295 tapdev_init(void)
296 {
297  char buf[1024];
298 
299  fd = open(DEVTAP, O_RDWR);
300  if(fd == -1) {
301  perror("tapdev: tapdev_init: open");
302  return;
303  }
304 
305 #ifdef linux
306  {
307  struct ifreq ifr;
308  memset(&ifr, 0, sizeof(ifr));
309  ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
310  if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
311  perror(buf);
312  exit(1);
313  }
314  }
315 #endif /* Linux */
316 
317 #ifdef __APPLE__
318  tapdev_init_darwin_routes();
319 #endif
320 
321  /* Linux (ubuntu)
322  snprintf(buf, sizeof(buf), "ip link set tap0 up");
323  system(buf);
324  PRINTF("%s\n", buf);
325  snprintf(buf, sizeof(buf), "ip -6 address add fc00::231/7 dev tap0");
326  system(buf);
327  PRINTF("%s\n", buf);
328  snprintf(buf, sizeof(buf), "ip -6 route add fc00::0/7 dev tap0");
329  system(buf);
330  PRINTF("%s\n", buf);
331  */
332  /* freebsd */
333  snprintf(buf, sizeof(buf), "ifconfig tap0 up");
334  system(buf);
335  printf("%s\n", buf);
336 
337  /* */
338  lasttime = 0;
339 
340  /* gdk_input_add(fd, GDK_INPUT_READ,
341  read_callback, NULL);*/
342 
343  atexit(&tapdev_exit);
344 }
345 /*---------------------------------------------------------------------------*/
346 static void
347 do_send(void)
348 {
349  int ret;
350 
351  if(fd <= 0) {
352  return;
353  }
354 
355 
356  PRINTF("tapdev_send: sending %d bytes\n", uip_len);
357  /* check_checksum(uip_buf, size);*/
358 #if DROP
359  drop++;
360  if(drop % 8 == 7) {
361  PRINTF("Dropped an output packet!\n");
362  return;
363  }
364 #endif /* DROP */
365 
366  ret = write(fd, uip_buf, uip_len);
367 
368  if(ret == -1) {
369  perror("tap_dev: tapdev_send: writev");
370  exit(1);
371  }
372 }
373 /*---------------------------------------------------------------------------*/
374 uint8_t
375 tapdev_send(const uip_lladdr_t *lladdr)
376 {
377  /*
378  * If L3 dest is multicast, build L2 multicast address
379  * as per RFC 2464 section 7
380  * else fill with th eaddrsess in argument
381  */
382  if(lladdr == NULL) {
383  /* the dest must be multicast */
384  (&BUF->dest)->addr[0] = 0x33;
385  (&BUF->dest)->addr[1] = 0x33;
386  (&BUF->dest)->addr[2] = IPBUF->destipaddr.u8[12];
387  (&BUF->dest)->addr[3] = IPBUF->destipaddr.u8[13];
388  (&BUF->dest)->addr[4] = IPBUF->destipaddr.u8[14];
389  (&BUF->dest)->addr[5] = IPBUF->destipaddr.u8[15];
390  } else {
391  memcpy(&BUF->dest, lladdr, UIP_LLADDR_LEN);
392  }
393  memcpy(&BUF->src, &uip_lladdr, UIP_LLADDR_LEN);
394  BUF->type = UIP_HTONS(UIP_ETHTYPE_IPV6); //math tmp
395 
396  uip_len += sizeof(struct uip_eth_hdr);
397  do_send();
398  return 0;
399 }
400 
401 /*---------------------------------------------------------------------------*/
402 void
403 tapdev_do_send(void)
404 {
405  do_send();
406 }
407 /*---------------------------------------------------------------------------*/
408 // math added function
409 void
410 tapdev_exit(void)
411 {
412  PRINTF("tapdev: Closing...\n");
413 
414 #ifdef __APPLE__
415  tapdev_cleanup_darwin_routes();
416 #endif
417 
418  close(fd);
419 }
420 /*---------------------------------------------------------------------------*/
421 
422 #endif /* UIP_CONF_IPV6 */
uip_len
The length of the packet in the uip_buf buffer.
Definition: tcp_loader.c:75
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:115
Header file for the uIP TCP/IP stack.
#define NULL
The null pointer.
#define UIP_BUFSIZE
The size of the uIP packet buffer.
Definition: uipopt.h:173
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1238
The Ethernet header.
Definition: uip_arp.h:60
Configuration options for uIP.
802.3 address
Definition: uip.h:135