Contiki-NG
Loading...
Searching...
No Matches
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
68static const char *config_ipaddr = "fd00::1/64";
69/* Allocate some bytes in RAM and copy the string */
70static char config_tundev[IFNAMSIZ + 1] = "tun0";
71
72
73static int tunfd = -1;
74
75static int set_fd(fd_set *rset, fd_set *wset);
76static void handle_fd(fd_set *rset, fd_set *wset);
77static const struct select_callback tun_select_callback = {
78 set_fd,
79 handle_fd
80};
81
82static int ssystem(const char *fmt, ...)
83 __attribute__((__format__ (__printf__, 1, 2)));
84
85int
86static ssystem(const char *fmt, ...)
87{
88 char cmd[128];
89 va_list ap;
90 va_start(ap, fmt);
91 vsnprintf(cmd, sizeof(cmd), fmt, ap);
92 va_end(ap);
93 LOG_INFO("%s\n", cmd);
94 fflush(stdout);
95 return system(cmd);
96}
97
98/*---------------------------------------------------------------------------*/
99static void
100cleanup(void)
101{
102#define TMPBUFSIZE 128
103 /* Called from signal handler, avoid unsafe functions. */
104 char buf[TMPBUFSIZE];
105 strcpy(buf, "ifconfig ");
106 /* Will not overflow, but null-terminate to avoid spurious warnings. */
107 buf[TMPBUFSIZE - 1] = '\0';
108 strncat(buf, config_tundev, TMPBUFSIZE - strlen(buf) - 1);
109 strncat(buf, " down", TMPBUFSIZE - strlen(buf) - 1);
110 system(buf);
111#ifndef linux
112 system("sysctl -w net.ipv6.conf.all.forwarding=1");
113#endif
114 strcpy(buf, "netstat -nr"
115 " | awk '{ if ($2 == \"");
116 buf[TMPBUFSIZE - 1] = '\0';
117 strncat(buf, config_tundev, TMPBUFSIZE - strlen(buf) - 1);
118 strncat(buf, "\") print \"route delete -net \"$1; }'"
119 " | sh", TMPBUFSIZE - strlen(buf) - 1);
120 system(buf);
121}
122
123/*---------------------------------------------------------------------------*/
124static void CC_NORETURN
125sigcleanup(int signo)
126{
127 const char *prefix = "signal ";
128 const char *sig =
129 signo == SIGHUP ? "HUP\n" : signo == SIGTERM ? "TERM\n" : "INT\n";
130 write(fileno(stderr), prefix, strlen(prefix));
131 write(fileno(stderr), sig, strlen(sig));
132 cleanup();
133 _exit(0);
134}
135
136/*---------------------------------------------------------------------------*/
137static void
138ifconf(const char *tundev, const char *ipaddr)
139{
140#ifdef linux
141 ssystem("ifconfig %s inet `hostname` up", tundev);
142 ssystem("ifconfig %s add %s", tundev, ipaddr);
143#elif defined(__APPLE__)
144 ssystem("ifconfig %s inet6 %s up", tundev, ipaddr);
145 ssystem("sysctl -w net.inet.ip.forwarding=1");
146#else
147 ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr);
148 ssystem("sysctl -w net.inet.ip.forwarding=1");
149#endif /* !linux */
150
151 /* Print the configuration to the console. */
152 ssystem("ifconfig %s\n", tundev);
153}
154/*---------------------------------------------------------------------------*/
155#ifdef linux
156static int
157tun_alloc(char *dev, uint16_t devsize)
158{
159 struct ifreq ifr;
160 int fd, err;
161 LOG_INFO("Opening: %s\n", dev);
162 if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
163 /* Error message handled by caller */
164 return -1;
165 }
166
167 memset(&ifr, 0, sizeof(ifr));
168
169 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
170 * IFF_NO_PI - Do not provide packet information
171 */
172 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
173 if(*dev != '\0') {
174 memcpy(ifr.ifr_name, dev, MIN(sizeof(ifr.ifr_name), devsize));
175 }
176 if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
177 /* Error message handled by caller */
178 close(fd);
179 return err;
180 }
181
182 LOG_INFO("Using '%s' vs '%s'\n", dev, ifr.ifr_name);
183 strncpy(dev, ifr.ifr_name, MIN(devsize - 1, sizeof(ifr.ifr_name)));
184 dev[devsize - 1] = '\0';
185 LOG_INFO("Using %s\n", dev);
186 return fd;
187}
188#else
189static int
190devopen(const char *dev, int flags)
191{
192 char t[32];
193 strcpy(t, "/dev/");
194 strncat(t, dev, sizeof(t) - 5);
195 return open(t, flags);
196}
197/*---------------------------------------------------------------------------*/
198static int
199tun_alloc(char *dev, uint16_t devsize)
200{
201 LOG_INFO("Opening: %s\n", dev);
202 return devopen(dev, O_RDWR);
203}
204#endif
205/*---------------------------------------------------------------------------*/
206static void
207tun_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/*---------------------------------------------------------------------------*/
235static int
236tun_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 }
242 return 0;
243}
244/*---------------------------------------------------------------------------*/
245static int
246tun_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/*---------------------------------------------------------------------------*/
262static uint8_t
263output(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/*---------------------------------------------------------------------------*/
275static int
276set_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
288static void
289handle_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
308static void input(void)
309{
310 /* should not happen */
311 LOG_DBG("Tun6 - input\n");
312}
313
314
315const struct network_driver tun6_net_driver ={
316 "tun6",
317 tun_init,
318 input,
319 output
320};
321
322
323/*---------------------------------------------------------------------------*/
#define CC_NORETURN
Configure if the C compiler supports functions that are not meant to return e.g.
Definition cc.h:99
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition tcpip.c:433
#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.
The structure of a network driver in Contiki.
Definition netstack.h:115
void(* input)(void)
Callback for getting notified of incoming packet in packetbuf.
Definition netstack.h:122
uint8_t(* output)(const linkaddr_t *localdest)
Output funtion, sends from uipbuf.
Definition netstack.h:125
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.