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 NETSTACK_CONF_WITH_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  if(system(buf) == -1) {
335  perror("tapdev: system: ifconfig");
336  return;
337  }
338  printf("%s\n", buf);
339 
340  /* */
341  lasttime = 0;
342 
343  /* gdk_input_add(fd, GDK_INPUT_READ,
344  read_callback, NULL);*/
345 
346  atexit(&tapdev_exit);
347 }
348 /*---------------------------------------------------------------------------*/
349 static void
350 do_send(void)
351 {
352  int ret;
353 
354  if(fd <= 0) {
355  return;
356  }
357 
358 
359  PRINTF("tapdev_send: sending %d bytes\n", uip_len);
360  /* check_checksum(uip_buf, size);*/
361 #if DROP
362  drop++;
363  if(drop % 8 == 7) {
364  PRINTF("Dropped an output packet!\n");
365  return;
366  }
367 #endif /* DROP */
368 
369  ret = write(fd, uip_buf, uip_len);
370 
371  if(ret == -1) {
372  perror("tap_dev: tapdev_send: writev");
373  exit(1);
374  }
375 }
376 /*---------------------------------------------------------------------------*/
377 uint8_t
378 tapdev_send(const uip_lladdr_t *lladdr)
379 {
380  /*
381  * If L3 dest is multicast, build L2 multicast address
382  * as per RFC 2464 section 7
383  * else fill with th eaddrsess in argument
384  */
385  if(lladdr == NULL) {
386  /* the dest must be multicast */
387  (&BUF->dest)->addr[0] = 0x33;
388  (&BUF->dest)->addr[1] = 0x33;
389  (&BUF->dest)->addr[2] = IPBUF->destipaddr.u8[12];
390  (&BUF->dest)->addr[3] = IPBUF->destipaddr.u8[13];
391  (&BUF->dest)->addr[4] = IPBUF->destipaddr.u8[14];
392  (&BUF->dest)->addr[5] = IPBUF->destipaddr.u8[15];
393  } else {
394  memcpy(&BUF->dest, lladdr, UIP_LLADDR_LEN);
395  }
396  memcpy(&BUF->src, &uip_lladdr, UIP_LLADDR_LEN);
397  BUF->type = UIP_HTONS(UIP_ETHTYPE_IPV6); //math tmp
398 
399  uip_len += sizeof(struct uip_eth_hdr);
400  do_send();
401  return 0;
402 }
403 
404 /*---------------------------------------------------------------------------*/
405 void
406 tapdev_do_send(void)
407 {
408  do_send();
409 }
410 /*---------------------------------------------------------------------------*/
411 // math added function
412 void
413 tapdev_exit(void)
414 {
415  PRINTF("tapdev: Closing...\n");
416 
417 #ifdef __APPLE__
418  tapdev_cleanup_darwin_routes();
419 #endif
420 
421  close(fd);
422 }
423 /*---------------------------------------------------------------------------*/
424 
425 #endif /* NETSTACK_CONF_WITH_IPV6 */
uip_len
The length of the packet in the uip_buf buffer.
Definition: tcp_loader.c:75
Configuration options for uIP.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1239
#define UIP_LLADDR_LEN
Link layer address length.
Definition: uip.h:151
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:523
The Ethernet header.
Definition: uip_arp.h:60
#define NULL
The null pointer.
802.3 address
Definition: uip.h:129
Header file for the uIP TCP/IP stack.
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip.c:118
#define UIP_BUFSIZE
The size of the uIP packet buffer.
Definition: uipopt.h:173