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 #include <net/if.h>
53 
54 /* Log configuration */
55 #include "sys/log.h"
56 #define LOG_MODULE "Tun6"
57 #define LOG_LEVEL LOG_LEVEL_WARN
58 
59 #ifdef linux
60 #include <linux/if.h>
61 #include <linux/if_tun.h>
62 #endif
63 
64 #include <err.h>
65 #include "net/netstack.h"
66 #include "net/packetbuf.h"
67 
68 static const char *config_ipaddr = "fd00::1/64";
69 /* Allocate some bytes in RAM and copy the string */
70 static char config_tundev[IFNAMSIZ + 1] = "tun0";
71 
72 
73 #ifndef __CYGWIN__
74 static int tunfd = -1;
75 
76 static int set_fd(fd_set *rset, fd_set *wset);
77 static void handle_fd(fd_set *rset, fd_set *wset);
78 static const struct select_callback tun_select_callback = {
79  set_fd,
80  handle_fd
81 };
82 #endif /* __CYGWIN__ */
83 
84 static int ssystem(const char *fmt, ...)
85  __attribute__((__format__ (__printf__, 1, 2)));
86 static int
87 ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
88 
89 int
90 static ssystem(const char *fmt, ...)
91 {
92  char cmd[128];
93  va_list ap;
94  va_start(ap, fmt);
95  vsnprintf(cmd, sizeof(cmd), fmt, ap);
96  va_end(ap);
97  LOG_INFO("%s\n", cmd);
98  fflush(stdout);
99  return system(cmd);
100 }
101 
102 /*---------------------------------------------------------------------------*/
103 static void
104 cleanup(void)
105 {
106  ssystem("ifconfig %s down", config_tundev);
107 #ifndef linux
108  ssystem("sysctl -w net.ipv6.conf.all.forwarding=1");
109 #endif
110  ssystem("netstat -nr"
111  " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'"
112  " | sh",
113  config_tundev);
114 }
115 
116 /*---------------------------------------------------------------------------*/
117 static void
118 sigcleanup(int signo)
119 {
120  fprintf(stderr, "signal %d\n", signo);
121  exit(0); /* exit(0) will call cleanup() */
122 }
123 
124 /*---------------------------------------------------------------------------*/
125 static void
126 ifconf(const char *tundev, const char *ipaddr)
127 {
128 #ifdef linux
129  ssystem("ifconfig %s inet `hostname` up", tundev);
130  ssystem("ifconfig %s add %s", tundev, ipaddr);
131 #elif defined(__APPLE__)
132  ssystem("ifconfig %s inet6 %s up", tundev, ipaddr);
133  ssystem("sysctl -w net.inet.ip.forwarding=1");
134 #else
135  ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr);
136  ssystem("sysctl -w net.inet.ip.forwarding=1");
137 #endif /* !linux */
138 
139  /* Print the configuration to the console. */
140  ssystem("ifconfig %s\n", tundev);
141 }
142 /*---------------------------------------------------------------------------*/
143 #ifdef linux
144 static int
145 tun_alloc(char *dev, uint16_t devsize)
146 {
147  struct ifreq ifr;
148  int fd, err;
149  LOG_INFO("Opening: %s\n", dev);
150  if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
151  /* Error message handled by caller */
152  return -1;
153  }
154 
155  memset(&ifr, 0, sizeof(ifr));
156 
157  /* Flags: IFF_TUN - TUN device (no Ethernet headers)
158  * IFF_NO_PI - Do not provide packet information
159  */
160  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
161  if(*dev != '\0') {
162  memcpy(ifr.ifr_name, dev, MIN(sizeof(ifr.ifr_name), devsize));
163  }
164  if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
165  /* Error message handled by caller */
166  close(fd);
167  return err;
168  }
169 
170  LOG_INFO("Using '%s' vs '%s'\n", dev, ifr.ifr_name);
171  strncpy(dev, ifr.ifr_name, MIN(devsize - 1, sizeof(ifr.ifr_name)));
172  dev[devsize - 1] = '\0';
173  LOG_INFO("Using %s\n", dev);
174  return fd;
175 }
176 #else
177 static int
178 devopen(const char *dev, int flags)
179 {
180  char t[32];
181  strcpy(t, "/dev/");
182  strncat(t, dev, sizeof(t) - 5);
183  return open(t, flags);
184 }
185 /*---------------------------------------------------------------------------*/
186 static int
187 tun_alloc(char *dev, uint16_t devsize)
188 {
189  LOG_INFO("Opening: %s\n", dev);
190  return devopen(dev, O_RDWR);
191 }
192 #endif
193 
194 #ifdef __CYGWIN__
195 /*wpcap process is used to connect to host interface */
196 static void
197 tun_init()
198 {
199  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
200 }
201 
202 #else
203 
204 
205 /*---------------------------------------------------------------------------*/
206 static void
207 tun_init()
208 {
209  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
210 
211  LOG_INFO("Initializing tun interface\n");
212 
213  tunfd = tun_alloc(config_tundev, sizeof(config_tundev));
214  if(tunfd == -1) {
215  LOG_WARN("Failed to open tun device (you may be lacking permission). Running without network.\n");
216  /* err(1, "failed to allocate tun device ``%s''", config_tundev); */
217  return;
218  }
219 
220  LOG_INFO("Tun open:%d\n", tunfd);
221 
222  select_set_callback(tunfd, &tun_select_callback);
223 
224  fprintf(stderr, "opened %s device ``/dev/%s''\n",
225  "tun", config_tundev);
226 
227  atexit(cleanup);
228  signal(SIGHUP, sigcleanup);
229  signal(SIGTERM, sigcleanup);
230  signal(SIGINT, sigcleanup);
231  ifconf(config_tundev, config_ipaddr);
232 }
233 
234 /*---------------------------------------------------------------------------*/
235 static int
236 tun_output(uint8_t *data, int len)
237 {
238  /* fprintf(stderr, "*** Writing to tun...%d\n", len); */
239  if(tunfd != -1 && write(tunfd, data, len) != len) {
240  err(1, "serial_to_tun: write");
241  return -1;
242  }
243  return 0;
244 }
245 /*---------------------------------------------------------------------------*/
246 static int
247 tun_input(unsigned char *data, int maxlen)
248 {
249  int size;
250 
251  if(tunfd == -1) {
252  /* tun is not open */
253  return 0;
254  }
255 
256  if((size = read(tunfd, data, maxlen)) == -1) {
257  err(1, "tun_input: read");
258  }
259  return size;
260 }
261 
262 /*---------------------------------------------------------------------------*/
263 static uint8_t
264 output(const linkaddr_t *localdest)
265 {
266  LOG_DBG("SUT: %u\n", uip_len);
267  if(uip_len > 0) {
268  return tun_output(uip_buf, uip_len);
269  }
270  return 0;
271 }
272 
273 /*---------------------------------------------------------------------------*/
274 /* tun and slip select callback */
275 /*---------------------------------------------------------------------------*/
276 static int
277 set_fd(fd_set *rset, fd_set *wset)
278 {
279  if(tunfd == -1) {
280  return 0;
281  }
282 
283  FD_SET(tunfd, rset);
284  return 1;
285 }
286 
287 /*---------------------------------------------------------------------------*/
288 
289 static void
290 handle_fd(fd_set *rset, fd_set *wset)
291 {
292  int size;
293 
294  if(tunfd == -1) {
295  /* tun is not open */
296  return;
297  }
298 
299  LOG_INFO("Tun6-handle FD\n");
300 
301  if(FD_ISSET(tunfd, rset)) {
302  size = tun_input(uip_buf, sizeof(uip_buf));
303  LOG_DBG("TUN data incoming read:%d\n", size);
304  uip_len = size;
305  tcpip_input();
306  }
307 }
308 #endif /* __CYGWIN_ */
309 
310 static void input(void)
311 {
312  /* should not happen */
313  LOG_DBG("Tun6 - input\n");
314 }
315 
316 
317 const struct network_driver tun6_net_driver ={
318  "tun6",
319  tun_init,
320  input,
321  output
322 };
323 
324 
325 /*---------------------------------------------------------------------------*/
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:1610
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:1847
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:445