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[64] = "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)
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  strncpy(ifr.ifr_name, dev, IFNAMSIZ);
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, strlen(dev));
171  LOG_INFO("Using %s\n", dev);
172  return fd;
173 }
174 #else
175 static int
176 devopen(const char *dev, int flags)
177 {
178  char t[32];
179  strcpy(t, "/dev/");
180  strncat(t, dev, sizeof(t) - 5);
181  return open(t, flags);
182 }
183 /*---------------------------------------------------------------------------*/
184 static int
185 tun_alloc(char *dev)
186 {
187  LOG_INFO("Opening: %s\n", dev);
188  return devopen(dev, O_RDWR);
189 }
190 #endif
191 
192 #ifdef __CYGWIN__
193 /*wpcap process is used to connect to host interface */
194 static void
195 tun_init()
196 {
197  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
198 }
199 
200 #else
201 
202 
203 /*---------------------------------------------------------------------------*/
204 static void
205 tun_init()
206 {
207  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
208 
209  LOG_INFO("Initializing tun interface\n");
210 
211  tunfd = tun_alloc(config_tundev);
212  if(tunfd == -1) {
213  LOG_WARN("Failed to open tun device (you may be lacking permission). Running without network.\n");
214  /* err(1, "failed to allocate tun device ``%s''", config_tundev); */
215  return;
216  }
217 
218  LOG_INFO("Tun open:%d\n", tunfd);
219 
220  select_set_callback(tunfd, &tun_select_callback);
221 
222  fprintf(stderr, "opened %s device ``/dev/%s''\n",
223  "tun", config_tundev);
224 
225  atexit(cleanup);
226  signal(SIGHUP, sigcleanup);
227  signal(SIGTERM, sigcleanup);
228  signal(SIGINT, sigcleanup);
229  ifconf(config_tundev, config_ipaddr);
230 }
231 
232 /*---------------------------------------------------------------------------*/
233 static int
234 tun_output(uint8_t *data, int len)
235 {
236  /* fprintf(stderr, "*** Writing to tun...%d\n", len); */
237  if(tunfd != -1 && write(tunfd, data, len) != len) {
238  err(1, "serial_to_tun: write");
239  return -1;
240  }
241  return 0;
242 }
243 /*---------------------------------------------------------------------------*/
244 static int
245 tun_input(unsigned char *data, int maxlen)
246 {
247  int size;
248 
249  if(tunfd == -1) {
250  /* tun is not open */
251  return 0;
252  }
253 
254  if((size = read(tunfd, data, maxlen)) == -1) {
255  err(1, "tun_input: read");
256  }
257  return size;
258 }
259 
260 /*---------------------------------------------------------------------------*/
261 static uint8_t
262 output(const linkaddr_t *localdest)
263 {
264  LOG_DBG("SUT: %u\n", uip_len);
265  if(uip_len > 0) {
266  return tun_output(&uip_buf[UIP_LLH_LEN], uip_len);
267  }
268  return 0;
269 }
270 
271 /*---------------------------------------------------------------------------*/
272 /* tun and slip select callback */
273 /*---------------------------------------------------------------------------*/
274 static int
275 set_fd(fd_set *rset, fd_set *wset)
276 {
277  if(tunfd == -1) {
278  return 0;
279  }
280 
281  FD_SET(tunfd, rset);
282  return 1;
283 }
284 
285 /*---------------------------------------------------------------------------*/
286 
287 static void
288 handle_fd(fd_set *rset, fd_set *wset)
289 {
290  int size;
291 
292  if(tunfd == -1) {
293  /* tun is not open */
294  return;
295  }
296 
297  LOG_INFO("Tun6-handle FD\n");
298 
299  if(FD_ISSET(tunfd, rset)) {
300  size = tun_input(&uip_buf[UIP_LLH_LEN], sizeof(uip_buf));
301  LOG_DBG("TUN data incoming read:%d\n", size);
302  uip_len = size;
303  tcpip_input();
304  }
305 }
306 #endif /* __CYGWIN_ */
307 
308 static void input(void)
309 {
310  /* should not happen */
311  LOG_DBG("Tun6 - input\n");
312 }
313 
314 
315 const struct network_driver tun6_net_driver ={
316  "tun6",
317  tun_init,
318  input,
319  output
320 };
321 
322 
323 /*---------------------------------------------------------------------------*/
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:125
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:179
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:1549
Header file for IPv6-related data structures.
#define UIP_LLH_LEN
The link level header length.
Definition: uipopt.h:141
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:513
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:1777
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:449