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
70extern const char *slip_config_ipaddr;
71extern char slip_config_tundev[32];
72extern uint16_t slip_config_basedelay;
73
74#ifndef __CYGWIN__
75static int tunfd;
76
77static int set_fd(fd_set *rset, fd_set *wset);
78static void handle_fd(fd_set *rset, fd_set *wset);
79static const struct select_callback tun_select_callback = {
80 set_fd,
81 handle_fd
82};
83#endif /* __CYGWIN__ */
84
85int ssystem(const char *fmt, ...)
86 __attribute__((__format__ (__printf__, 1, 2)));
87int
88ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
89
90int
91ssystem(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/*---------------------------------------------------------------------------*/
103void
104cleanup(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/*---------------------------------------------------------------------------*/
116void
117sigcleanup(int signo)
118{
119 fprintf(stderr, "signal %d\n", signo);
120 exit(0); /* exit(0) will call cleanup() */
121}
122/*---------------------------------------------------------------------------*/
123void
124ifconf(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/*---------------------------------------------------------------------------*/
141int
142devopen(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
151int
152tun_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 - 1);
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
179int
180tun_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 */
188void
189tun_init()
190{
191 setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
192
193 slip_init();
194}
195#else
196
197static uint16_t delaymsec = 0;
198static uint32_t delaystartsec, delaystartmsec;
199
200/*---------------------------------------------------------------------------*/
201void
202tun_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/*---------------------------------------------------------------------------*/
228static int
229tun_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/*---------------------------------------------------------------------------*/
239int
240tun_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/*---------------------------------------------------------------------------*/
249static void
250init(void)
251{
252}
253/*---------------------------------------------------------------------------*/
254static int
255output(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}
263const struct uip_fallback_interface rpl_interface = {
264 init, output
265};
266
267/*---------------------------------------------------------------------------*/
268/* tun and slip select callback */
269/*---------------------------------------------------------------------------*/
270static int
271set_fd(fd_set *rset, fd_set *wset)
272{
273 FD_SET(tunfd, rset);
274 return 1;
275}
276/*---------------------------------------------------------------------------*/
277
278static void
279handle_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/*---------------------------------------------------------------------------*/
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:1606
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:445
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:465
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
Header file for the logging system.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for IPv6-related data structures.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
Header file for the uIP TCP/IP stack.