Contiki-NG
tun-bridge.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 /*---------------------------------------------------------------------------*/
54 /* Log configuration */
55 #include "sys/log.h"
56 #define LOG_MODULE "BR"
57 #define LOG_LEVEL LOG_LEVEL_NONE
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 #include "cmd.h"
68 #include "border-router.h"
69 
70 extern const char *slip_config_ipaddr;
71 extern char slip_config_tundev[32];
72 extern uint16_t slip_config_basedelay;
73 
74 #ifndef __CYGWIN__
75 static int tunfd;
76 
77 static int set_fd(fd_set *rset, fd_set *wset);
78 static void handle_fd(fd_set *rset, fd_set *wset);
79 static const struct select_callback tun_select_callback = {
80  set_fd,
81  handle_fd
82 };
83 #endif /* __CYGWIN__ */
84 
85 int ssystem(const char *fmt, ...)
86  __attribute__((__format__ (__printf__, 1, 2)));
87 int
88 ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
89 
90 int
91 ssystem(const char *fmt, ...)
92 {
93  char cmd[128];
94  va_list ap;
95  va_start(ap, fmt);
96  vsnprintf(cmd, sizeof(cmd), fmt, ap);
97  va_end(ap);
98  printf("%s\n", cmd);
99  fflush(stdout);
100  return system(cmd);
101 }
102 /*---------------------------------------------------------------------------*/
103 void
104 cleanup(void)
105 {
106  ssystem("ifconfig %s down", slip_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  slip_config_tundev);
114 }
115 /*---------------------------------------------------------------------------*/
116 void
117 sigcleanup(int signo)
118 {
119  fprintf(stderr, "signal %d\n", signo);
120  exit(0); /* exit(0) will call cleanup() */
121 }
122 /*---------------------------------------------------------------------------*/
123 void
124 ifconf(const char *tundev, const char *ipaddr)
125 {
126 #ifdef linux
127  ssystem("ifconfig %s inet `hostname` up", tundev);
128  ssystem("ifconfig %s add %s", tundev, ipaddr);
129 #elif defined(__APPLE__)
130  ssystem("ifconfig %s inet6 %s up", tundev, ipaddr);
131  ssystem("sysctl -w net.inet.ip.forwarding=1");
132 #else
133  ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr);
134  ssystem("sysctl -w net.inet.ip.forwarding=1");
135 #endif /* !linux */
136 
137  /* Print the configuration to the console. */
138  ssystem("ifconfig %s\n", tundev);
139 }
140 /*---------------------------------------------------------------------------*/
141 int
142 devopen(const char *dev, int flags)
143 {
144  char t[32];
145  strcpy(t, "/dev/");
146  strncat(t, dev, sizeof(t) - 5);
147  return open(t, flags);
148 }
149 /*---------------------------------------------------------------------------*/
150 #ifdef linux
151 int
152 tun_alloc(char *dev)
153 {
154  struct ifreq ifr;
155  int fd, err;
156 
157  if((fd = open("/dev/net/tun", O_RDWR)) < 0) {
158  return -1;
159  }
160 
161  memset(&ifr, 0, sizeof(ifr));
162 
163  /* Flags: IFF_TUN - TUN device (no Ethernet headers)
164  * IFF_NO_PI - Do not provide packet information
165  */
166  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
167  if(*dev != 0) {
168  strncpy(ifr.ifr_name, dev, IFNAMSIZ);
169  }
170 
171  if((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) {
172  close(fd);
173  return err;
174  }
175  strcpy(dev, ifr.ifr_name);
176  return fd;
177 }
178 #else
179 int
180 tun_alloc(char *dev)
181 {
182  return devopen(dev, O_RDWR);
183 }
184 #endif
185 
186 #ifdef __CYGWIN__
187 /*wpcap process is used to connect to host interface */
188 void
189 tun_init()
190 {
191  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
192 
193  slip_init();
194 }
195 #else
196 
197 static uint16_t delaymsec = 0;
198 static uint32_t delaystartsec, delaystartmsec;
199 
200 /*---------------------------------------------------------------------------*/
201 void
202 tun_init()
203 {
204  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
205 
206  slip_init();
207 
208  LOG_INFO("Opening tun interface:%s\n", slip_config_tundev);
209 
210  tunfd = tun_alloc(slip_config_tundev);
211 
212  if(tunfd == -1) {
213  err(1, "tun_init: open");
214  }
215 
216  select_set_callback(tunfd, &tun_select_callback);
217 
218  fprintf(stderr, "opened %s device ``/dev/%s''\n",
219  "tun", slip_config_tundev);
220 
221  atexit(cleanup);
222  signal(SIGHUP, sigcleanup);
223  signal(SIGTERM, sigcleanup);
224  signal(SIGINT, sigcleanup);
225  ifconf(slip_config_tundev, slip_config_ipaddr);
226 }
227 /*---------------------------------------------------------------------------*/
228 static int
229 tun_output(uint8_t *data, int len)
230 {
231  /* fprintf(stderr, "*** Writing to tun...%d\n", len); */
232  if(write(tunfd, data, len) != len) {
233  err(1, "serial_to_tun: write");
234  return -1;
235  }
236  return 0;
237 }
238 /*---------------------------------------------------------------------------*/
239 int
240 tun_input(unsigned char *data, int maxlen)
241 {
242  int size;
243  if((size = read(tunfd, data, maxlen)) == -1) {
244  err(1, "tun_input: read");
245  }
246  return size;
247 }
248 /*---------------------------------------------------------------------------*/
249 static void
250 init(void)
251 {
252 }
253 /*---------------------------------------------------------------------------*/
254 static int
255 output(void)
256 {
257  LOG_DBG("SUT: %u\n", uip_len);
258  if(uip_len > 0) {
259  return tun_output(uip_buf, uip_len);
260  }
261  return 0;
262 }
263 const struct uip_fallback_interface rpl_interface = {
264  init, output
265 };
266 
267 /*---------------------------------------------------------------------------*/
268 /* tun and slip select callback */
269 /*---------------------------------------------------------------------------*/
270 static int
271 set_fd(fd_set *rset, fd_set *wset)
272 {
273  FD_SET(tunfd, rset);
274  return 1;
275 }
276 /*---------------------------------------------------------------------------*/
277 
278 static void
279 handle_fd(fd_set *rset, fd_set *wset)
280 {
281  /* Optional delay between outgoing packets */
282  /* Base delay times number of 6lowpan fragments to be sent */
283  /* delaymsec = 10; */
284  if(delaymsec) {
285  struct timeval tv;
286  int dmsec;
287  gettimeofday(&tv, NULL);
288  dmsec = (tv.tv_sec - delaystartsec) * 1000 + tv.tv_usec / 1000 - delaystartmsec;
289  if(dmsec < 0) {
290  delaymsec = 0;
291  }
292  if(dmsec > delaymsec) {
293  delaymsec = 0;
294  }
295  }
296 
297  if(delaymsec == 0) {
298  int size;
299 
300  if(FD_ISSET(tunfd, rset)) {
301  size = tun_input(uip_buf, sizeof(uip_buf));
302  /* printf("TUN data incoming read:%d\n", size); */
303  uip_len = size;
304  tcpip_input();
305 
306  if(slip_config_basedelay) {
307  struct timeval tv;
308  gettimeofday(&tv, NULL);
309  delaymsec = slip_config_basedelay;
310  delaystartsec = tv.tv_sec;
311  delaystartmsec = tv.tv_usec / 1000;
312  }
313  }
314  }
315 }
316 #endif /* __CYGWIN_ */
317 
318 /*---------------------------------------------------------------------------*/
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
Border router header file
Simple command handler
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:1565
Header file for IPv6-related data structures.
#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
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:445