Contiki-NG
tun6-net.c
1 /*
2  * Copyright (c) 2011, 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  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /**
31  * \author
32  * Niclas Finne <nfi@sics.se>
33  * Joakim Eriksson <joakime@sics.se>
34  */
35 
36 #include "net/ipv6/uip.h"
37 #include "net/ipv6/uip-ds6.h"
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <sys/time.h>
43 #include <sys/types.h>
44 
45 #include <unistd.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <signal.h>
49 #include <termios.h>
50 #include <sys/ioctl.h>
51 #include <sys/socket.h>
52 
53 /* Log configuration */
54 #include "sys/log.h"
55 #define LOG_MODULE "Tun6"
56 #define LOG_LEVEL LOG_LEVEL_WARN
57 
58 #ifdef linux
59 #include <linux/if.h>
60 #include <linux/if_tun.h>
61 #endif
62 
63 #include <err.h>
64 #include "net/netstack.h"
65 #include "net/packetbuf.h"
66 
67 static const char *config_ipaddr = "fd00::1/64";
68 /* Allocate some bytes in RAM and copy the string */
69 static char config_tundev[IFNAMSIZ + 1] = "tun0";
70 
71 
72 #ifndef __CYGWIN__
73 static int tunfd = -1;
74 
75 static int set_fd(fd_set *rset, fd_set *wset);
76 static void handle_fd(fd_set *rset, fd_set *wset);
77 static const struct select_callback tun_select_callback = {
78  set_fd,
79  handle_fd
80 };
81 #endif /* __CYGWIN__ */
82 
83 static int ssystem(const char *fmt, ...)
84  __attribute__((__format__ (__printf__, 1, 2)));
85 static int
86 ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
87 
88 int
89 static ssystem(const char *fmt, ...)
90 {
91  char cmd[128];
92  va_list ap;
93  va_start(ap, fmt);
94  vsnprintf(cmd, sizeof(cmd), fmt, ap);
95  va_end(ap);
96  LOG_INFO("%s\n", cmd);
97  fflush(stdout);
98  return system(cmd);
99 }
100 
101 /*---------------------------------------------------------------------------*/
102 static void
103 cleanup(void)
104 {
105  ssystem("ifconfig %s down", config_tundev);
106 #ifndef linux
107  ssystem("sysctl -w net.ipv6.conf.all.forwarding=1");
108 #endif
109  ssystem("netstat -nr"
110  " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'"
111  " | sh",
112  config_tundev);
113 }
114 
115 /*---------------------------------------------------------------------------*/
116 static void
117 sigcleanup(int signo)
118 {
119  fprintf(stderr, "signal %d\n", signo);
120  exit(0); /* exit(0) will call cleanup() */
121 }
122 
123 /*---------------------------------------------------------------------------*/
124 static void
125 ifconf(const char *tundev, const char *ipaddr)
126 {
127 #ifdef linux
128  ssystem("ifconfig %s inet `hostname` up", tundev);
129  ssystem("ifconfig %s add %s", tundev, ipaddr);
130 #elif defined(__APPLE__)
131  ssystem("ifconfig %s inet6 %s up", tundev, ipaddr);
132  ssystem("sysctl -w net.inet.ip.forwarding=1");
133 #else
134  ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr);
135  ssystem("sysctl -w net.inet.ip.forwarding=1");
136 #endif /* !linux */
137 
138  /* Print the configuration to the console. */
139  ssystem("ifconfig %s\n", tundev);
140 }
141 /*---------------------------------------------------------------------------*/
142 #ifdef linux
143 static int
144 tun_alloc(char *dev, uint16_t devsize)
145 {
146  struct ifreq ifr;
147  int fd, err;
148  LOG_INFO("Opening: %s\n", dev);
149  if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
150  /* Error message handled by caller */
151  return -1;
152  }
153 
154  memset(&ifr, 0, sizeof(ifr));
155 
156  /* Flags: IFF_TUN - TUN device (no Ethernet headers)
157  * IFF_NO_PI - Do not provide packet information
158  */
159  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
160  if(*dev != '\0') {
161  memcpy(ifr.ifr_name, dev, MIN(sizeof(ifr.ifr_name), devsize));
162  }
163  if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
164  /* Error message handled by caller */
165  close(fd);
166  return err;
167  }
168 
169  LOG_INFO("Using '%s' vs '%s'\n", dev, ifr.ifr_name);
170  strncpy(dev, ifr.ifr_name, MIN(devsize - 1, sizeof(ifr.ifr_name)));
171  dev[devsize - 1] = '\0';
172  LOG_INFO("Using %s\n", dev);
173  return fd;
174 }
175 #else
176 static int
177 devopen(const char *dev, int flags)
178 {
179  char t[32];
180  strcpy(t, "/dev/");
181  strncat(t, dev, sizeof(t) - 5);
182  return open(t, flags);
183 }
184 /*---------------------------------------------------------------------------*/
185 static int
186 tun_alloc(char *dev, uint16_t devsize)
187 {
188  LOG_INFO("Opening: %s\n", dev);
189  return devopen(dev, O_RDWR);
190 }
191 #endif
192 
193 #ifdef __CYGWIN__
194 /*wpcap process is used to connect to host interface */
195 static void
196 tun_init()
197 {
198  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
199 }
200 
201 #else
202 
203 
204 /*---------------------------------------------------------------------------*/
205 static void
206 tun_init()
207 {
208  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
209 
210  LOG_INFO("Initializing tun interface\n");
211 
212  tunfd = tun_alloc(config_tundev, sizeof(config_tundev));
213  if(tunfd == -1) {
214  LOG_WARN("Failed to open tun device (you may be lacking permission). Running without network.\n");
215  /* err(1, "failed to allocate tun device ``%s''", config_tundev); */
216  return;
217  }
218 
219  LOG_INFO("Tun open:%d\n", tunfd);
220 
221  select_set_callback(tunfd, &tun_select_callback);
222 
223  fprintf(stderr, "opened %s device ``/dev/%s''\n",
224  "tun", config_tundev);
225 
226  atexit(cleanup);
227  signal(SIGHUP, sigcleanup);
228  signal(SIGTERM, sigcleanup);
229  signal(SIGINT, sigcleanup);
230  ifconf(config_tundev, config_ipaddr);
231 }
232 
233 /*---------------------------------------------------------------------------*/
234 static int
235 tun_output(uint8_t *data, int len)
236 {
237  /* fprintf(stderr, "*** Writing to tun...%d\n", len); */
238  if(tunfd != -1 && write(tunfd, data, len) != len) {
239  err(1, "serial_to_tun: write");
240  return -1;
241  }
242  return 0;
243 }
244 /*---------------------------------------------------------------------------*/
245 static int
246 tun_input(unsigned char *data, int maxlen)
247 {
248  int size;
249 
250  if(tunfd == -1) {
251  /* tun is not open */
252  return 0;
253  }
254 
255  if((size = read(tunfd, data, maxlen)) == -1) {
256  err(1, "tun_input: read");
257  }
258  return size;
259 }
260 
261 /*---------------------------------------------------------------------------*/
262 static uint8_t
263 output(const linkaddr_t *localdest)
264 {
265  LOG_DBG("SUT: %u\n", uip_len);
266  if(uip_len > 0) {
267  return tun_output(uip_buf, uip_len);
268  }
269  return 0;
270 }
271 
272 /*---------------------------------------------------------------------------*/
273 /* tun and slip select callback */
274 /*---------------------------------------------------------------------------*/
275 static int
276 set_fd(fd_set *rset, fd_set *wset)
277 {
278  if(tunfd == -1) {
279  return 0;
280  }
281 
282  FD_SET(tunfd, rset);
283  return 1;
284 }
285 
286 /*---------------------------------------------------------------------------*/
287 
288 static void
289 handle_fd(fd_set *rset, fd_set *wset)
290 {
291  int size;
292 
293  if(tunfd == -1) {
294  /* tun is not open */
295  return;
296  }
297 
298  LOG_INFO("Tun6-handle FD\n");
299 
300  if(FD_ISSET(tunfd, rset)) {
301  size = tun_input(uip_buf, sizeof(uip_buf));
302  LOG_DBG("TUN data incoming read:%d\n", size);
303  uip_len = size;
304  tcpip_input();
305  }
306 }
307 #endif /* __CYGWIN_ */
308 
309 static void input(void)
310 {
311  /* should not happen */
312  LOG_DBG("Tun6 - input\n");
313 }
314 
315 
316 const struct network_driver tun6_net_driver ={
317  "tun6",
318  tun_init,
319  input,
320  output
321 };
322 
323 
324 /*---------------------------------------------------------------------------*/
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Definition: sicslowpan.c:1576
Header file for IPv6-related data structures.
The structure of a network driver in Contiki.
Definition: netstack.h:117
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:510
Header file for the uIP TCP/IP stack.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1813
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:445