diff --git a/examples/osd/native-border-router/Makefile b/examples/osd/native-border-router/Makefile new file mode 100644 index 000000000..d781ed35c --- /dev/null +++ b/examples/osd/native-border-router/Makefile @@ -0,0 +1,27 @@ +CONTIKI_PROJECT=border-router +all: $(CONTIKI_PROJECT) +APPS = slip-cmd + +CONTIKI=../../.. + +#linker optimizations +SMALL=1 + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" +PROJECT_SOURCEFILES += border-router-cmds.c tun-bridge.c border-router-rdc.c \ +slip-config.c slip-dev.c + +WITH_WEBSERVER=1 +ifeq ($(WITH_WEBSERVER),1) +CFLAGS += -DWEBSERVER=1 +PROJECT_SOURCEFILES += httpd-simple.c +else ifneq ($(WITH_WEBSERVER), 0) +APPS += $(WITH_WEBSERVER) +CFLAGS += -DWEBSERVER=2 +endif + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include + +connect-router: border-router.native + sudo ./border-router.native aaaa::1/64 diff --git a/examples/osd/native-border-router/border-router-cmds.c b/examples/osd/native-border-router/border-router-cmds.c new file mode 100644 index 000000000..68f7af48c --- /dev/null +++ b/examples/osd/native-border-router/border-router-cmds.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * Sets up some commands for the border router + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "contiki.h" +#include "cmd.h" +#include "border-router.h" +#include "border-router-cmds.h" +#include "dev/serial-line.h" +#include "net/rpl/rpl.h" +#include "net/ip/uiplib.h" +#include + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + + +uint8_t command_context; + +void packet_sent(uint8_t sessionid, uint8_t status, uint8_t tx); +void nbr_print_stat(void); + +/*---------------------------------------------------------------------------*/ +PROCESS(border_router_cmd_process, "Border router cmd process"); +/*---------------------------------------------------------------------------*/ +/* TODO: the below code needs some way of identifying from where the command */ +/* comes. In this case it can be from stdin or from SLIP. */ +/*---------------------------------------------------------------------------*/ +int +border_router_cmd_handler(const uint8_t *data, int len) +{ + /* handle global repair, etc here */ + if(data[0] == '!') { + PRINTF("Got configuration message of type %c\n", data[1]); + if(data[1] == 'G' && command_context == CMD_CONTEXT_STDIO) { + /* This is supposed to be from stdin */ + printf("Performing Global Repair...\n"); + rpl_repair_root(RPL_DEFAULT_INSTANCE); + return 1; + } else if(data[1] == 'M' && command_context == CMD_CONTEXT_RADIO) { + /* We need to know that this is from the slip-radio here. */ + PRINTF("Setting MAC address\n"); + border_router_set_mac(&data[2]); + return 1; + } else if(data[1] == 'C' && command_context == CMD_CONTEXT_RADIO) { + /* We need to know that this is from the slip-radio here. */ + printf("Channel is:%d\n", data[2]); + return 1; + } else if(data[1] == 'R' && command_context == CMD_CONTEXT_RADIO) { + /* We need to know that this is from the slip-radio here. */ + PRINTF("Packet data report for sid:%d st:%d tx:%d\n", + data[2], data[3], data[4]); + packet_sent(data[2], data[3], data[4]); + return 1; + } else if(data[1] == 'D' && command_context == CMD_CONTEXT_RADIO) { + /* We need to know that this is from the slip-radio here... */ + PRINTF("Sensor data received\n"); + border_router_set_sensors((const char *)&data[2], len - 2); + return 1; + } + } else if(data[0] == '?') { + PRINTF("Got request message of type %c\n", data[1]); + if(data[1] == 'M' && command_context == CMD_CONTEXT_STDIO) { + uint8_t buf[20]; + char* hexchar = "0123456789abcdef"; + int j; + /* this is just a test so far... just to see if it works */ + buf[0] = '!'; + buf[1] = 'M'; + for(j = 0; j < 8; j++) { + buf[2 + j * 2] = hexchar[uip_lladdr.addr[j] >> 4]; + buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15]; + } + cmd_send(buf, 18); + return 1; + } else if(data[1] == 'C' && command_context == CMD_CONTEXT_STDIO) { + /* send on! */ + write_to_slip(data, len); + return 1; + } else if(data[1] == 'S') { + border_router_print_stat(); + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +border_router_cmd_output(const uint8_t *data, int data_len) +{ + int i; + printf("CMD output: "); + for(i = 0; i < data_len; i++) { + printf("%c", data[i]); + } + printf("\n"); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(border_router_cmd_process, ev, data) +{ + PROCESS_BEGIN(); + PRINTF("Started br-cmd process\n"); + while(1) { + PROCESS_YIELD(); + if(ev == serial_line_event_message && data != NULL) { + PRINTF("Got serial data!!! %s of len: %d\n", + (char *)data, strlen((char *)data)); + command_context = CMD_CONTEXT_STDIO; + cmd_input(data, strlen((char *)data)); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/osd/native-border-router/border-router-cmds.h b/examples/osd/native-border-router/border-router-cmds.h new file mode 100644 index 000000000..6dcef36a0 --- /dev/null +++ b/examples/osd/native-border-router/border-router-cmds.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * Sets up some commands for the border router + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef BORDER_ROUTER_CMDS_H_ +#define BORDER_ROUTER_CMDS_H_ + +#define CMD_CONTEXT_RADIO 0 +#define CMD_CONTEXT_STDIO 1 + +extern uint8_t command_context; + +PROCESS_NAME(border_router_cmd_process); + +#endif /* BORDER_ROUTER_CMDS_H_ */ diff --git a/examples/osd/native-border-router/border-router-rdc.c b/examples/osd/native-border-router/border-router-rdc.c new file mode 100644 index 000000000..4aae30e5e --- /dev/null +++ b/examples/osd/native-border-router/border-router-rdc.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * A null RDC implementation that uses framer for headers and sends + * the packets over slip instead of radio. + * \author + * Adam Dunkels + * Joakim Eriksson + * Niclas Finne + */ + +#include "net/packetbuf.h" +#include "net/queuebuf.h" +#include "net/netstack.h" +#include "packetutils.h" +#include "border-router.h" +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define MAX_CALLBACKS 16 +static int callback_pos; + +/* a structure for calling back when packet data is coming back + from radio... */ +struct tx_callback { + mac_callback_t cback; + void *ptr; + struct packetbuf_attr attrs[PACKETBUF_NUM_ATTRS]; + struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS]; +}; + +static struct tx_callback callbacks[MAX_CALLBACKS]; +/*---------------------------------------------------------------------------*/ +void packet_sent(uint8_t sessionid, uint8_t status, uint8_t tx) +{ + if(sessionid < MAX_CALLBACKS) { + struct tx_callback *callback; + callback = &callbacks[sessionid]; + packetbuf_clear(); + packetbuf_attr_copyfrom(callback->attrs, callback->addrs); + mac_call_sent_callback(callback->cback, callback->ptr, status, tx); + } else { + PRINTF("*** ERROR: too high session id %d\n", sessionid); + } +} +/*---------------------------------------------------------------------------*/ +static int +setup_callback(mac_callback_t sent, void *ptr) +{ + struct tx_callback *callback; + int tmp = callback_pos; + callback = &callbacks[callback_pos]; + callback->cback = sent; + callback->ptr = ptr; + packetbuf_attr_copyto(callback->attrs, callback->addrs); + + callback_pos++; + if(callback_pos >= MAX_CALLBACKS) { + callback_pos = 0; + } + + return tmp; +} +/*---------------------------------------------------------------------------*/ +static void +send_packet(mac_callback_t sent, void *ptr) +{ + int size; + /* 3 bytes per packet attribute is required for serialization */ + uint8_t buf[PACKETBUF_NUM_ATTRS * 3 + PACKETBUF_SIZE + 3]; + uint8_t sid; + + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); + + /* ack or not ? */ + packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); + + if(NETSTACK_FRAMER.create() < 0) { + /* Failed to allocate space for headers */ + PRINTF("br-rdc: send failed, too large header\n"); + mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); + + } else { + /* here we send the data over SLIP to the radio-chip */ + size = 0; +#if SERIALIZE_ATTRIBUTES + size = packetutils_serialize_atts(&buf[3], sizeof(buf) - 3); +#endif + if(size < 0 || size + packetbuf_totlen() + 3 > sizeof(buf)) { + PRINTF("br-rdc: send failed, too large header\n"); + mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); + } else { + sid = setup_callback(sent, ptr); + + buf[0] = '!'; + buf[1] = 'S'; + buf[2] = sid; /* sequence or session number for this packet */ + + /* Copy packet data */ + memcpy(&buf[3 + size], packetbuf_hdrptr(), packetbuf_totlen()); + + write_to_slip(buf, packetbuf_totlen() + size + 3); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) +{ + if(buf_list != NULL) { + queuebuf_to_packetbuf(buf_list->buf); + send_packet(sent, ptr); + } +} +/*---------------------------------------------------------------------------*/ +static void +packet_input(void) +{ + if(NETSTACK_FRAMER.parse() < 0) { + PRINTF("br-rdc: failed to parse %u\n", packetbuf_datalen()); + } else { + NETSTACK_MAC.input(); + } +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +channel_check_interval(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + callback_pos = 0; +} +/*---------------------------------------------------------------------------*/ +const struct rdc_driver border_router_rdc_driver = { + "br-rdc", + init, + send_packet, + send_list, + packet_input, + on, + off, + channel_check_interval, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/osd/native-border-router/border-router.c b/examples/osd/native-border-router/border-router.c new file mode 100644 index 000000000..fe8d7fbf5 --- /dev/null +++ b/examples/osd/native-border-router/border-router.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/** + * \file + * border-router + * \author + * Niclas Finne + * Joakim Eriksson + * Nicolas Tsiftes + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/rpl/rpl.h" + +#include "net/netstack.h" +#include "dev/slip.h" +#include "cmd.h" +#include "border-router.h" +#include "border-router-cmds.h" + +#include +#include +#include +#include + +#define DEBUG DEBUG_FULL +#include "net/ip/uip-debug.h" + +#define MAX_SENSORS 4 + +extern long slip_sent; +extern long slip_received; + +static uip_ipaddr_t prefix; +static uint8_t prefix_set; +static uint8_t mac_set; + +static uint8_t sensor_count = 0; + +/* allocate MAX_SENSORS char[32]'s */ +static char sensors[MAX_SENSORS][32]; + +extern int contiki_argc; +extern char **contiki_argv; +extern const char *slip_config_ipaddr; + +CMD_HANDLERS(border_router_cmd_handler); + +PROCESS(border_router_process, "Border router process"); + +#if WEBSERVER==0 +/* No webserver */ +AUTOSTART_PROCESSES(&border_router_process,&border_router_cmd_process); +#elif WEBSERVER>1 +/* Use an external webserver application */ +#include "webserver-nogui.h" +AUTOSTART_PROCESSES(&border_router_process,&border_router_cmd_process, + &webserver_nogui_process); +#else +/* Use simple webserver with only one page */ +#include "httpd-simple.h" +PROCESS(webserver_nogui_process, "Web server"); +PROCESS_THREAD(webserver_nogui_process, ev, data) +{ + PROCESS_BEGIN(); + + httpd_init(); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + httpd_appcall(data); + } + + PROCESS_END(); +} +AUTOSTART_PROCESSES(&border_router_process,&border_router_cmd_process, + &webserver_nogui_process); + +static const char *TOP = "ContikiRPL\n"; +static const char *BOTTOM = "\n"; +static char buf[128]; +static int blen; +#define ADD(...) do { \ + blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__); \ + } while(0) +/*---------------------------------------------------------------------------*/ +static void +ipaddr_add(const uip_ipaddr_t *addr) +{ + uint16_t a; + int i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0 && sizeof(buf) - blen >= 2) { + buf[blen++] = ':'; + buf[blen++] = ':'; + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0 && blen < sizeof(buf)) { + buf[blen++] = ':'; + } + ADD("%x", a); + } + } +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(generate_routes(struct httpd_state *s)) +{ + static int i; + static uip_ds6_route_t *r; + static uip_ds6_nbr_t *nbr; + + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, TOP); + + blen = 0; + ADD("Neighbors
");
+  for(nbr = nbr_table_head(ds6_neighbors);
+      nbr != NULL;
+      nbr = nbr_table_next(ds6_neighbors, nbr)) {
+    ipaddr_add(&nbr->ipaddr);
+    ADD("\n");
+    if(blen > sizeof(buf) - 45) {
+      SEND_STRING(&s->sout, buf);
+      blen = 0;
+    }
+  }
+
+  ADD("
Routes
");
+  SEND_STRING(&s->sout, buf);
+  blen = 0;
+  for(r = uip_ds6_route_head();
+      r != NULL;
+      r = uip_ds6_route_next(r)) {
+    ipaddr_add(&r->ipaddr);
+    ADD("/%u (via ", r->length);
+    ipaddr_add(uip_ds6_route_nexthop(r));
+    if(r->state.lifetime < 600) {
+      ADD(") %lus\n", (unsigned long)r->state.lifetime);
+    } else {
+      ADD(")\n");
+    }
+    SEND_STRING(&s->sout, buf);
+    blen = 0;
+  }
+  ADD("
"); +//if(blen > 0) { + SEND_STRING(&s->sout, buf); +// blen = 0; +//} + + if(sensor_count > 0) { + ADD("Sensors
");
+    SEND_STRING(&s->sout, buf);
+    blen = 0;
+    for(i = 0; i < sensor_count; i++) {
+      ADD("%s\n", sensors[i]);
+      SEND_STRING(&s->sout, buf);
+      blen = 0;
+    }
+    ADD("
"); + SEND_STRING(&s->sout, buf); + } + + + SEND_STRING(&s->sout, BOTTOM); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +httpd_simple_script_t +httpd_simple_get_script(const char *name) +{ + return generate_routes; +} + +#endif /* WEBSERVER */ + +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTA("Server IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + PRINTA(" %p: =>", &uip_ds6_if.addr_list[i]); + uip_debug_ipaddr_print(&(uip_ds6_if.addr_list[i]).ipaddr); + PRINTA("\n"); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +request_mac(void) +{ + write_to_slip((uint8_t *)"?M", 2); +} +/*---------------------------------------------------------------------------*/ +void +border_router_set_mac(const uint8_t *data) +{ + memcpy(uip_lladdr.addr, data, sizeof(uip_lladdr.addr)); + linkaddr_set_node_addr((linkaddr_t *)uip_lladdr.addr); + + /* is this ok - should instead remove all addresses and + add them back again - a bit messy... ?*/ + uip_ds6_init(); + rpl_init(); + + mac_set = 1; +} +/*---------------------------------------------------------------------------*/ +void +border_router_print_stat() +{ + printf("bytes received over SLIP: %ld\n", slip_received); + printf("bytes sent over SLIP: %ld\n", slip_sent); +} + +/*---------------------------------------------------------------------------*/ +/* Format: ;;...;*/ +/* this function just cut at ; and store in the sensor array */ +void +border_router_set_sensors(const char *data, int len) +{ + int i; + int last_pos = 0; + int sc = 0; + for(i = 0;i < len; i++) { + if(data[i] == ';') { + sensors[sc][i - last_pos] = 0; + memcpy(sensors[sc++], &data[last_pos], i - last_pos); + last_pos = i + 1; /* skip the ';' */ + } + if(sc == MAX_SENSORS) { + sensor_count = sc; + return; + } + } + sensors[sc][len - last_pos] = 0; + memcpy(sensors[sc++], &data[last_pos], len - last_pos); + sensor_count = sc; +} +/*---------------------------------------------------------------------------*/ +static void +set_prefix_64(const uip_ipaddr_t *prefix_64) +{ + rpl_dag_t *dag; + uip_ipaddr_t ipaddr; + memcpy(&prefix, prefix_64, 16); + memcpy(&ipaddr, prefix_64, 16); + + prefix_set = 1; + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr); + if(dag != NULL) { + rpl_set_prefix(dag, &prefix, 64); + PRINTF("created a new RPL dag\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(border_router_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + prefix_set = 0; + + PROCESS_PAUSE(); + + PRINTF("RPL-Border router started\n"); + + slip_config_handle_arguments(contiki_argc, contiki_argv); + + /* tun init is also responsible for setting up the SLIP connection */ + tun_init(); + + while(!mac_set) { + etimer_set(&et, CLOCK_SECOND); + request_mac(); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + } + + if(slip_config_ipaddr != NULL) { + uip_ipaddr_t prefix; + + if(uiplib_ipaddrconv((const char *)slip_config_ipaddr, &prefix)) { + PRINTF("Setting prefix "); + PRINT6ADDR(&prefix); + PRINTF("\n"); + set_prefix_64(&prefix); + } else { + PRINTF("Parse error: %s\n", slip_config_ipaddr); + exit(0); + } + } + +#if DEBUG + print_local_addresses(); +#endif + + /* The border router runs with a 100% duty cycle in order to ensure high + packet reception rates. */ + NETSTACK_MAC.off(1); + + while(1) { + etimer_set(&et, CLOCK_SECOND * 2); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + /* do anything here??? */ + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/osd/native-border-router/border-router.h b/examples/osd/native-border-router/border-router.h new file mode 100644 index 000000000..68420320d --- /dev/null +++ b/examples/osd/native-border-router/border-router.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * Border router header file + * \author + * Joakim Eriksson + */ + +#ifndef BORDER_ROUTER_H_ +#define BORDER_ROUTER_H_ + +#include "contiki.h" +#include "net/ip/uip.h" +#include + +int border_router_cmd_handler(const uint8_t *data, int len); +int slip_config_handle_arguments(int argc, char **argv); +void write_to_slip(const uint8_t *buf, int len); + +void border_router_set_prefix_64(const uip_ipaddr_t *prefix_64); +void border_router_set_mac(const uint8_t *data); +void border_router_set_sensors(const char *data, int len); +void border_router_print_stat(void); + +void tun_init(void); + +int slip_init(void); +int slip_set_fd(int maxfd, fd_set *rset, fd_set *wset); +void slip_handle_fd(fd_set *rset, fd_set *wset); + +#endif /* BORDER_ROUTER_H_ */ diff --git a/examples/osd/native-border-router/httpd-simple.c b/examples/osd/native-border-router/httpd-simple.c new file mode 100644 index 000000000..115e54d45 --- /dev/null +++ b/examples/osd/native-border-router/httpd-simple.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * A simple web server forwarding page generation to a protothread + * \author + * Adam Dunkels + * Niclas Finne + * Joakim Eriksson + */ + +#include +#include + +#include "contiki-net.h" + +//#include "urlconv.h" + +#include "httpd-simple.h" +#define webserver_log_file(...) +#define webserver_log(...) + +#ifndef WEBSERVER_CONF_CFS_CONNS +#define CONNS UIP_CONNS +#else /* WEBSERVER_CONF_CFS_CONNS */ +#define CONNS WEBSERVER_CONF_CFS_CONNS +#endif /* WEBSERVER_CONF_CFS_CONNS */ + +#ifndef WEBSERVER_CONF_CFS_URLCONV +#define URLCONV 0 +#else /* WEBSERVER_CONF_CFS_URLCONV */ +#define URLCONV WEBSERVER_CONF_CFS_URLCONV +#endif /* WEBSERVER_CONF_CFS_URLCONV */ + +#define STATE_WAITING 0 +#define STATE_OUTPUT 1 + +MEMB(conns, struct httpd_state, CONNS); + +#define ISO_nl 0x0a +#define ISO_space 0x20 +#define ISO_period 0x2e +#define ISO_slash 0x2f + +/*---------------------------------------------------------------------------*/ +static const char *NOT_FOUND = "" +"
" +"

404 - file not found

" +"
" +"" +""; +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_string(struct httpd_state *s, const char *str)) +{ + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, str); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +const char http_content_type_html[] = "Content-type: text/html\r\n\r\n"; +static +PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr)) +{ + /* char *ptr; */ + + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, statushdr); + + /* ptr = strrchr(s->filename, ISO_period); */ + /* if(ptr == NULL) { */ + /* s->ptr = http_content_type_plain; */ + /* } else if(strcmp(http_html, ptr) == 0) { */ + /* s->ptr = http_content_type_html; */ + /* } else if(strcmp(http_css, ptr) == 0) { */ + /* s->ptr = http_content_type_css; */ + /* } else if(strcmp(http_png, ptr) == 0) { */ + /* s->ptr = http_content_type_png; */ + /* } else if(strcmp(http_gif, ptr) == 0) { */ + /* s->ptr = http_content_type_gif; */ + /* } else if(strcmp(http_jpg, ptr) == 0) { */ + /* s->ptr = http_content_type_jpg; */ + /* } else { */ + /* s->ptr = http_content_type_binary; */ + /* } */ + /* SEND_STRING(&s->sout, s->ptr); */ + SEND_STRING(&s->sout, http_content_type_html); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +const char http_header_200[] = "HTTP/1.0 200 OK\r\nServer: Contiki/2.4 http://www.sics.se/contiki/\r\nConnection: close\r\n"; +const char http_header_404[] = "HTTP/1.0 404 Not found\r\nServer: Contiki/2.4 http://www.sics.se/contiki/\r\nConnection: close\r\n"; +static +PT_THREAD(handle_output(struct httpd_state *s)) +{ + PT_BEGIN(&s->outputpt); + + s->script = NULL; + s->script = httpd_simple_get_script(&s->filename[1]); + if(s->script == NULL) { + strncpy(s->filename, "/notfound.html", sizeof(s->filename)); + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, http_header_404)); + PT_WAIT_THREAD(&s->outputpt, + send_string(s, NOT_FOUND)); + uip_close(); + webserver_log_file(&uip_conn->ripaddr, "404 - not found"); + PT_EXIT(&s->outputpt); + } else { + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, http_header_200)); + PT_WAIT_THREAD(&s->outputpt, s->script(s)); + } + s->script = NULL; + PSOCK_CLOSE(&s->sout); + PT_END(&s->outputpt); +} +/*---------------------------------------------------------------------------*/ +const char http_get[] = "GET "; +const char http_index_html[] = "/index.html"; +//const char http_referer[] = "Referer:" +static +PT_THREAD(handle_input(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sin); + + PSOCK_READTO(&s->sin, ISO_space); + + if(strncmp(s->inputbuf, http_get, 4) != 0) { + PSOCK_CLOSE_EXIT(&s->sin); + } + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + +#if URLCONV + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + urlconv_tofilename(s->filename, s->inputbuf, sizeof(s->filename)); +#else /* URLCONV */ + if(s->inputbuf[1] == ISO_space) { + strncpy(s->filename, http_index_html, sizeof(s->filename)); + } else { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + strncpy(s->filename, s->inputbuf, sizeof(s->filename)); + } +#endif /* URLCONV */ + + webserver_log_file(&uip_conn->ripaddr, s->filename); + + s->state = STATE_OUTPUT; + + while(1) { + PSOCK_READTO(&s->sin, ISO_nl); +#if 0 + if(strncmp(s->inputbuf, http_referer, 8) == 0) { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0; + webserver_log(s->inputbuf); + } +#endif + } + + PSOCK_END(&s->sin); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connection(struct httpd_state *s) +{ + handle_input(s); + if(s->state == STATE_OUTPUT) { + handle_output(s); + } +} + +/*---------------------------------------------------------------------------*/ +void +httpd_appcall(void *state) +{ + struct httpd_state *s = (struct httpd_state *)state; + + if(uip_closed() || uip_aborted() || uip_timedout()) { + if(s != NULL) { + s->script = NULL; + memb_free(&conns, s); + } + } else if(uip_connected()) { + s = (struct httpd_state *)memb_alloc(&conns); + if(s == NULL) { + uip_abort(); + webserver_log_file(&uip_conn->ripaddr, "reset (no memory block)"); + return; + } + tcp_markconn(uip_conn, s); + PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); + PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); + PT_INIT(&s->outputpt); + s->script = NULL; + s->state = STATE_WAITING; + timer_set(&s->timer, CLOCK_SECOND * 10); + handle_connection(s); + } else if(s != NULL) { + if(uip_poll()) { + if(timer_expired(&s->timer)) { + uip_abort(); + s->script = NULL; + memb_free(&conns, s); + webserver_log_file(&uip_conn->ripaddr, "reset (timeout)"); + } + } else { + timer_restart(&s->timer); + } + handle_connection(s); + } else { + uip_abort(); + } +} + +/*---------------------------------------------------------------------------*/ +void +httpd_init(void) +{ + + tcp_listen(UIP_HTONS(80)); + memb_init(&conns); +#if URLCONV + urlconv_init(); +#endif /* URLCONV */ +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/osd/native-border-router/httpd-simple.h b/examples/osd/native-border-router/httpd-simple.h new file mode 100644 index 000000000..a16dbd99e --- /dev/null +++ b/examples/osd/native-border-router/httpd-simple.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * A simple webserver + * \author + * Adam Dunkels + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef HTTPD_SIMPLE_H_ +#define HTTPD_SIMPLE_H_ + +#include "contiki-net.h" + +/* The current internal border router webserver ignores the requested file name */ +/* and needs no per-connection output buffer, so save some RAM */ +#ifndef WEBSERVER_CONF_CFS_PATHLEN +#define HTTPD_PATHLEN 2 +#else /* WEBSERVER_CONF_CFS_CONNS */ +#define HTTPD_PATHLEN WEBSERVER_CONF_CFS_PATHLEN +#endif /* WEBSERVER_CONF_CFS_CONNS */ + +struct httpd_state; +typedef char (* httpd_simple_script_t)(struct httpd_state *s); + +struct httpd_state { + struct timer timer; + struct psock sin, sout; + struct pt outputpt; + char inputbuf[HTTPD_PATHLEN + 24]; +/*char outputbuf[UIP_TCP_MSS]; */ + char filename[HTTPD_PATHLEN]; + httpd_simple_script_t script; + char state; +}; + +void httpd_init(void); +void httpd_appcall(void *state); + +httpd_simple_script_t httpd_simple_get_script(const char *name); + +#define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, strlen(str)) + +#endif /* HTTPD_SIMPLE_H_ */ diff --git a/examples/osd/native-border-router/project-conf.h b/examples/osd/native-border-router/project-conf.h new file mode 100644 index 000000000..4ef217fcb --- /dev/null +++ b/examples/osd/native-border-router/project-conf.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PROJECT_ROUTER_CONF_H_ +#define PROJECT_ROUTER_CONF_H_ + +#undef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE rpl_interface + +#undef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 4 + +#undef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1280 + +#undef UIP_CONF_RECEIVE_WINDOW +#define UIP_CONF_RECEIVE_WINDOW 60 + +#define SLIP_DEV_CONF_SEND_DELAY (CLOCK_SECOND / 32) + +#undef WEBSERVER_CONF_CFS_CONNS +#define WEBSERVER_CONF_CFS_CONNS 2 + +#define SERIALIZE_ATTRIBUTES 1 + +#define CMD_CONF_OUTPUT border_router_cmd_output + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC border_router_rdc_driver + +/* used by wpcap (see /cpu/native/net/wpcap-drv.c) */ +#define SELECT_CALLBACK 1 + +#endif /* PROJECT_ROUTER_CONF_H_ */ diff --git a/examples/osd/native-border-router/slip-config.c b/examples/osd/native-border-router/slip-config.c new file mode 100644 index 000000000..84d256127 --- /dev/null +++ b/examples/osd/native-border-router/slip-config.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * Slip configuration + * \author + * Niclas Finne + * Joakim Eriksson + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "contiki.h" + +int slip_config_verbose = 0; +const char *slip_config_ipaddr; +int slip_config_flowcontrol = 0; +int slip_config_timestamp = 0; +const char *slip_config_siodev = NULL; +const char *slip_config_host = NULL; +const char *slip_config_port = NULL; +char slip_config_tundev[32] = { "" }; +uint16_t slip_config_basedelay = 0; + +#ifndef BAUDRATE +#define BAUDRATE B115200 +#endif +speed_t slip_config_b_rate = BAUDRATE; + +/*---------------------------------------------------------------------------*/ +int +slip_config_handle_arguments(int argc, char **argv) +{ + const char *prog; + char c; + int baudrate = 115200; + + slip_config_verbose = 0; + + prog = argv[0]; + while((c = getopt(argc, argv, "B:H:D:Lhs:t:v::d::a:p:T")) != -1) { + switch(c) { + case 'B': + baudrate = atoi(optarg); + break; + + case 'H': + slip_config_flowcontrol = 1; + break; + + case 'L': + slip_config_timestamp = 1; + break; + + case 's': + if(strncmp("/dev/", optarg, 5) == 0) { + slip_config_siodev = optarg + 5; + } else { + slip_config_siodev = optarg; + } + break; + + case 't': + if(strncmp("/dev/", optarg, 5) == 0) { + strncpy(slip_config_tundev, optarg + 5, sizeof(slip_config_tundev)); + } else { + strncpy(slip_config_tundev, optarg, sizeof(slip_config_tundev)); + } + break; + + case 'a': + slip_config_host = optarg; + break; + + case 'p': + slip_config_port = optarg; + break; + + case 'd': + slip_config_basedelay = 10; + if(optarg) slip_config_basedelay = atoi(optarg); + break; + + case 'v': + slip_config_verbose = 2; + if(optarg) slip_config_verbose = atoi(optarg); + break; + + case '?': + case 'h': + default: +fprintf(stderr,"usage: %s [options] ipaddress\n", prog); +fprintf(stderr,"example: border-router.native -L -v2 -s ttyUSB1 aaaa::1/64\n"); +fprintf(stderr,"Options are:\n"); +#ifdef linux +fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200,921600 (default 115200)\n"); +#else +fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default 115200)\n"); +#endif +fprintf(stderr," -H Hardware CTS/RTS flow control (default disabled)\n"); +fprintf(stderr," -L Log output format (adds time stamps)\n"); +fprintf(stderr," -s siodev Serial device (default /dev/ttyUSB0)\n"); +fprintf(stderr," -a host Connect via TCP to server at \n"); +fprintf(stderr," -p port Connect via TCP to server at :\n"); +fprintf(stderr," -t tundev Name of interface (default tun0)\n"); +fprintf(stderr," -v[level] Verbosity level\n"); +fprintf(stderr," -v0 No messages\n"); +fprintf(stderr," -v1 Encapsulated SLIP debug messages (default)\n"); +fprintf(stderr," -v2 Printable strings after they are received\n"); +fprintf(stderr," -v3 Printable strings and SLIP packet notifications\n"); +fprintf(stderr," -v4 All printable characters as they are received\n"); +fprintf(stderr," -v5 All SLIP packets in hex\n"); +fprintf(stderr," -v Equivalent to -v3\n"); +fprintf(stderr," -d[basedelay] Minimum delay between outgoing SLIP packets.\n"); +fprintf(stderr," Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n"); +fprintf(stderr," -d is equivalent to -d10.\n"); +exit(1); + break; + } + } + argc -= optind - 1; + argv += optind - 1; + + if(argc != 2 && argc != 3) { + err(1, "usage: %s [-B baudrate] [-H] [-L] [-s siodev] [-t tundev] [-T] [-v verbosity] [-d delay] [-a serveraddress] [-p serverport] ipaddress", prog); + } + slip_config_ipaddr = argv[1]; + + switch(baudrate) { + case -2: + break; /* Use default. */ + case 9600: + slip_config_b_rate = B9600; + break; + case 19200: + slip_config_b_rate = B19200; + break; + case 38400: + slip_config_b_rate = B38400; + break; + case 57600: + slip_config_b_rate = B57600; + break; + case 115200: + slip_config_b_rate = B115200; + break; +#ifdef linux + case 921600: + slip_config_b_rate = B921600; + break; +#endif + default: + err(1, "unknown baudrate %d", baudrate); + break; + } + + if(*slip_config_tundev == '\0') { + /* Use default. */ + strcpy(slip_config_tundev, "tun0"); + } + return 1; +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/osd/native-border-router/slip-dev.c b/examples/osd/native-border-router/slip-dev.c new file mode 100644 index 000000000..8aabbe528 --- /dev/null +++ b/examples/osd/native-border-router/slip-dev.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2001, Adam Dunkels. + * Copyright (c) 2009, 2010 Joakim Eriksson, Niclas Finne, Dogan Yazar. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /* Below define allows importing saved output into Wireshark as "Raw IP" packet type */ +#define WIRESHARK_IMPORT_FORMAT 1 +#include "contiki.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "net/netstack.h" +#include "net/packetbuf.h" +#include "cmd.h" +#include "border-router-cmds.h" + +extern int slip_config_verbose; +extern int slip_config_flowcontrol; +extern const char *slip_config_siodev; +extern const char *slip_config_host; +extern const char *slip_config_port; +extern uint16_t slip_config_basedelay; +extern speed_t slip_config_b_rate; + +#ifdef SLIP_DEV_CONF_SEND_DELAY +#define SEND_DELAY SLIP_DEV_CONF_SEND_DELAY +#else +#define SEND_DELAY 0 +#endif + +int devopen(const char *dev, int flags); + +static FILE *inslip; + +/* for statistics */ +long slip_sent = 0; +long slip_received = 0; + +int slipfd = 0; + +//#define PROGRESS(s) fprintf(stderr, s) +#define PROGRESS(s) do { } while(0) + +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 + +/*---------------------------------------------------------------------------*/ +static void * +get_in_addr(struct sockaddr *sa) +{ + if(sa->sa_family == AF_INET) { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} +/*---------------------------------------------------------------------------*/ +static int +connect_to_server(const char *host, const char *port) +{ + /* Setup TCP connection */ + struct addrinfo hints, *servinfo, *p; + char s[INET6_ADDRSTRLEN]; + int rv, fd; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) { + err(1, "getaddrinfo: %s", gai_strerror(rv)); + return -1; + } + + /* loop through all the results and connect to the first we can */ + for(p = servinfo; p != NULL; p = p->ai_next) { + if((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + perror("client: socket"); + continue; + } + + if(connect(fd, p->ai_addr, p->ai_addrlen) == -1) { + close(fd); + perror("client: connect"); + continue; + } + break; + } + + if(p == NULL) { + err(1, "can't connect to ``%s:%s''", host, port); + return -1; + } + + fcntl(fd, F_SETFL, O_NONBLOCK); + + inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), + s, sizeof(s)); + + /* all done with this structure */ + freeaddrinfo(servinfo); + return fd; +} +/*---------------------------------------------------------------------------*/ +int +is_sensible_string(const unsigned char *s, int len) +{ + int i; + for(i = 1; i < len; i++) { + if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { + continue; + } else if(s[i] < ' ' || '~' < s[i]) { + return 0; + } + } + return 1; +} +/*---------------------------------------------------------------------------*/ +void +slip_packet_input(unsigned char *data, int len) +{ + packetbuf_copyfrom(data, len); + if(slip_config_verbose > 0) { + printf("Packet input over SLIP: %d\n", len); + } + NETSTACK_RDC.input(); +} +/*---------------------------------------------------------------------------*/ +/* + * Read from serial, when we have a packet call slip_packet_input. No output + * buffering, input buffered by stdio. + */ +void +serial_input(FILE *inslip) +{ + static unsigned char inbuf[2048]; + static int inbufptr = 0; + int ret,i; + unsigned char c; + +#ifdef linux + ret = fread(&c, 1, 1, inslip); + if(ret == -1 || ret == 0) err(1, "serial_input: read"); + goto after_fread; +#endif + + read_more: + if(inbufptr >= sizeof(inbuf)) { + fprintf(stderr, "*** dropping large %d byte packet\n", inbufptr); + inbufptr = 0; + } + ret = fread(&c, 1, 1, inslip); +#ifdef linux + after_fread: +#endif + if(ret == -1) { + err(1, "serial_input: read"); + } + if(ret == 0) { + clearerr(inslip); + return; + } + slip_received++; + switch(c) { + case SLIP_END: + if(inbufptr > 0) { + if(inbuf[0] == '!') { + command_context = CMD_CONTEXT_RADIO; + cmd_input(inbuf, inbufptr); + } else if(inbuf[0] == '?') { +#define DEBUG_LINE_MARKER '\r' + } else if(inbuf[0] == DEBUG_LINE_MARKER) { + fwrite(inbuf + 1, inbufptr - 1, 1, stdout); + } else if(is_sensible_string(inbuf, inbufptr)) { + if(slip_config_verbose == 1) { /* strings already echoed below for verbose>1 */ + fwrite(inbuf, inbufptr, 1, stdout); + } + } else { + if(slip_config_verbose > 2) { + printf("Packet from SLIP of length %d - write TUN\n", inbufptr); + if(slip_config_verbose > 4) { +#if WIRESHARK_IMPORT_FORMAT + printf("0000"); + for(i = 0; i < inbufptr; i++) printf(" %02x", inbuf[i]); +#else + printf(" "); + for(i = 0; i < inbufptr; i++) { + printf("%02x", inbuf[i]); + if((i & 3) == 3) printf(" "); + if((i & 15) == 15) printf("\n "); + } +#endif + printf("\n"); + } + } + slip_packet_input(inbuf, inbufptr); + } + inbufptr = 0; + } + break; + + case SLIP_ESC: + if(fread(&c, 1, 1, inslip) != 1) { + clearerr(inslip); + /* Put ESC back and give up! */ + ungetc(SLIP_ESC, inslip); + return; + } + + switch(c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + /* FALLTHROUGH */ + default: + inbuf[inbufptr++] = c; + + /* Echo lines as they are received for verbose=2,3,5+ */ + /* Echo all printable characters for verbose==4 */ + if(slip_config_verbose == 4) { + if(c == 0 || c == '\r' || c == '\n' || c == '\t' || (c >= ' ' && c <= '~')) { + fwrite(&c, 1, 1, stdout); + } + } else if(slip_config_verbose >= 2) { + if(c == '\n' && is_sensible_string(inbuf, inbufptr)) { + fwrite(inbuf, inbufptr, 1, stdout); + inbufptr = 0; + } + } + break; + } + + goto read_more; +} + +unsigned char slip_buf[2048]; +int slip_end, slip_begin, slip_packet_end, slip_packet_count; +static struct timer send_delay_timer; +/* delay between slip packets */ +static clock_time_t send_delay = SEND_DELAY; +/*---------------------------------------------------------------------------*/ +static void +slip_send(int fd, unsigned char c) +{ + if(slip_end >= sizeof(slip_buf)) { + err(1, "slip_send overflow"); + } + slip_buf[slip_end] = c; + slip_end++; + slip_sent++; + if(c == SLIP_END) { + /* Full packet received. */ + slip_packet_count++; + if(slip_packet_end == 0) { + slip_packet_end = slip_end; + } + } +} +/*---------------------------------------------------------------------------*/ +int +slip_empty() +{ + return slip_packet_end == 0; +} +/*---------------------------------------------------------------------------*/ +void +slip_flushbuf(int fd) +{ + int n; + + if(slip_empty()) { + return; + } + + n = write(fd, slip_buf + slip_begin, slip_packet_end - slip_begin); + + if(n == -1 && errno != EAGAIN) { + err(1, "slip_flushbuf write failed"); + } else if(n == -1) { + PROGRESS("Q"); /* Outqueue is full! */ + } else { + slip_begin += n; + if(slip_begin == slip_packet_end) { + slip_packet_count--; + if(slip_end > slip_packet_end) { + memcpy(slip_buf, slip_buf + slip_packet_end, + slip_end - slip_packet_end); + } + slip_end -= slip_packet_end; + slip_begin = slip_packet_end = 0; + if(slip_end > 0) { + /* Find end of next slip packet */ + for(n = 1; n < slip_end; n++) { + if(slip_buf[n] == SLIP_END) { + slip_packet_end = n + 1; + break; + } + } + /* a delay between slip packets to avoid losing data */ + if(send_delay > 0) { + timer_set(&send_delay_timer, send_delay); + } + } + } + } +} +/*---------------------------------------------------------------------------*/ +static void +write_to_serial(int outfd, const uint8_t *inbuf, int len) +{ + const uint8_t *p = inbuf; + int i; + + if(slip_config_verbose > 2) { +#ifdef __CYGWIN__ + printf("Packet from WPCAP of length %d - write SLIP\n", len); +#else + printf("Packet from TUN of length %d - write SLIP\n", len); +#endif + if(slip_config_verbose > 4) { +#if WIRESHARK_IMPORT_FORMAT + printf("0000"); + for(i = 0; i < len; i++) printf(" %02x", p[i]); +#else + printf(" "); + for(i = 0; i < len; i++) { + printf("%02x", p[i]); + if((i & 3) == 3) printf(" "); + if((i & 15) == 15) printf("\n "); + } +#endif + printf("\n"); + } + } + + /* It would be ``nice'' to send a SLIP_END here but it's not + * really necessary. + */ + /* slip_send(outfd, SLIP_END); */ + + for(i = 0; i < len; i++) { + switch(p[i]) { + case SLIP_END: + slip_send(outfd, SLIP_ESC); + slip_send(outfd, SLIP_ESC_END); + break; + case SLIP_ESC: + slip_send(outfd, SLIP_ESC); + slip_send(outfd, SLIP_ESC_ESC); + break; + default: + slip_send(outfd, p[i]); + break; + } + } + slip_send(outfd, SLIP_END); + PROGRESS("t"); +} +/*---------------------------------------------------------------------------*/ +/* writes an 802.15.4 packet to slip-radio */ +void +write_to_slip(const uint8_t *buf, int len) +{ + if(slipfd > 0) { + write_to_serial(slipfd, buf, len); + } +} +/*---------------------------------------------------------------------------*/ +static void +stty_telos(int fd) +{ + struct termios tty; + speed_t speed = slip_config_b_rate; + int i; + + if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); + + if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr"); + + cfmakeraw(&tty); + + /* Nonblocking read. */ + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 0; + if(slip_config_flowcontrol) { + tty.c_cflag |= CRTSCTS; + } else { + tty.c_cflag &= ~CRTSCTS; + } + tty.c_cflag &= ~HUPCL; + tty.c_cflag &= ~CLOCAL; + + cfsetispeed(&tty, speed); + cfsetospeed(&tty, speed); + + if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); + +#if 1 + /* Nonblocking read and write. */ + /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */ + + tty.c_cflag |= CLOCAL; + if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); + + i = TIOCM_DTR; + if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl"); +#endif + + usleep(10*1000); /* Wait for hardware 10ms. */ + + /* Flush input and output buffers. */ + if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); +} +/*---------------------------------------------------------------------------*/ +static int +set_fd(fd_set *rset, fd_set *wset) +{ + /* Anything to flush? */ + if(!slip_empty() && (send_delay == 0 || timer_expired(&send_delay_timer))) { + FD_SET(slipfd, wset); + } + + FD_SET(slipfd, rset); /* Read from slip ASAP! */ + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +handle_fd(fd_set *rset, fd_set *wset) +{ + if(FD_ISSET(slipfd, rset)) { + serial_input(inslip); + } + + if(FD_ISSET(slipfd, wset)) { + slip_flushbuf(slipfd); + } +} +/*---------------------------------------------------------------------------*/ +static const struct select_callback slip_callback = { set_fd, handle_fd }; +/*---------------------------------------------------------------------------*/ +void +slip_init(void) +{ + setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ + + if(slip_config_host != NULL) { + if(slip_config_port == NULL) { + slip_config_port = "60001"; + } + slipfd = connect_to_server(slip_config_host, slip_config_port); + if(slipfd == -1) { + err(1, "can't connect to ``%s:%s''", slip_config_host, slip_config_port); + } + + } else if(slip_config_siodev != NULL) { + if(strcmp(slip_config_siodev, "null") == 0) { + /* Disable slip */ + return; + } + slipfd = devopen(slip_config_siodev, O_RDWR | O_NONBLOCK); + if(slipfd == -1) { + err(1, "can't open siodev ``/dev/%s''", slip_config_siodev); + } + + } else { + static const char *siodevs[] = { + "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ + }; + int i; + for(i = 0; i < 3; i++) { + slip_config_siodev = siodevs[i]; + slipfd = devopen(slip_config_siodev, O_RDWR | O_NONBLOCK); + if(slipfd != -1) { + break; + } + } + if(slipfd == -1) { + err(1, "can't open siodev"); + } + } + + select_set_callback(slipfd, &slip_callback); + + if(slip_config_host != NULL) { + fprintf(stderr, "********SLIP opened to ``%s:%s''\n", slip_config_host, + slip_config_port); + } else { + fprintf(stderr, "********SLIP started on ``/dev/%s''\n", slip_config_siodev); + stty_telos(slipfd); + } + + timer_set(&send_delay_timer, 0); + slip_send(slipfd, SLIP_END); + inslip = fdopen(slipfd, "r"); + if(inslip == NULL) { + err(1, "main: fdopen"); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/osd/native-border-router/tun-bridge.c b/examples/osd/native-border-router/tun-bridge.c new file mode 100644 index 000000000..22cb4289b --- /dev/null +++ b/examples/osd/native-border-router/tun-bridge.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +#ifdef linux +#include +#include +#endif + +#include +#include "net/netstack.h" +#include "net/packetbuf.h" +#include "cmd.h" +#include "border-router.h" + +extern const char *slip_config_ipaddr; +extern char slip_config_tundev[32]; +extern uint16_t slip_config_basedelay; + +#ifndef __CYGWIN__ +static int tunfd; + +static int set_fd(fd_set *rset, fd_set *wset); +static void handle_fd(fd_set *rset, fd_set *wset); +static const struct select_callback tun_select_callback = { + set_fd, + handle_fd +}; +#endif /* __CYGWIN__ */ + +int ssystem(const char *fmt, ...) + __attribute__((__format__ (__printf__, 1, 2))); +int +ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2))); + +int +ssystem(const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + printf("%s\n", cmd); + fflush(stdout); + return system(cmd); +} + +/*---------------------------------------------------------------------------*/ +void +cleanup(void) +{ + ssystem("ifconfig %s down", slip_config_tundev); +#ifndef linux + ssystem("sysctl -w net.ipv6.conf.all.forwarding=1"); +#endif + ssystem("netstat -nr" + " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'" + " | sh", + slip_config_tundev); +} + +/*---------------------------------------------------------------------------*/ +void +sigcleanup(int signo) +{ + fprintf(stderr, "signal %d\n", signo); + exit(0); /* exit(0) will call cleanup() */ +} + +/*---------------------------------------------------------------------------*/ +void +ifconf(const char *tundev, const char *ipaddr) +{ +#ifdef linux + ssystem("ifconfig %s inet `hostname` up", tundev); + ssystem("ifconfig %s add %s", tundev, ipaddr); +#elif defined(__APPLE__) + ssystem("ifconfig %s inet6 %s up", tundev, ipaddr); + ssystem("sysctl -w net.inet.ip.forwarding=1"); +#else + ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr); + ssystem("sysctl -w net.inet.ip.forwarding=1"); +#endif /* !linux */ + + /* Print the configuration to the console. */ + ssystem("ifconfig %s\n", tundev); +} +/*---------------------------------------------------------------------------*/ +int +devopen(const char *dev, int flags) +{ + char t[32]; + strcpy(t, "/dev/"); + strncat(t, dev, sizeof(t) - 5); + return open(t, flags); +} +/*---------------------------------------------------------------------------*/ +#ifdef linux +int +tun_alloc(char *dev) +{ + struct ifreq ifr; + int fd, err; + + if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) { + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + + /* Flags: IFF_TUN - TUN device (no Ethernet headers) + * IFF_NO_PI - Do not provide packet information + */ + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + if(*dev != 0) + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { + close(fd); + return err; + } + strcpy(dev, ifr.ifr_name); + return fd; +} +#else +int +tun_alloc(char *dev) +{ + return devopen(dev, O_RDWR); +} +#endif + +#ifdef __CYGWIN__ +/*wpcap process is used to connect to host interface */ +void +tun_init() +{ + setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ + + slip_init(); +} + +#else + +static uint16_t delaymsec=0; +static uint32_t delaystartsec,delaystartmsec; + +/*---------------------------------------------------------------------------*/ +void +tun_init() +{ + setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ + + slip_init(); + + tunfd = tun_alloc(slip_config_tundev); + if(tunfd == -1) err(1, "main: open"); + + select_set_callback(tunfd, &tun_select_callback); + + fprintf(stderr, "opened %s device ``/dev/%s''\n", + "tun", slip_config_tundev); + + atexit(cleanup); + signal(SIGHUP, sigcleanup); + signal(SIGTERM, sigcleanup); + signal(SIGINT, sigcleanup); + ifconf(slip_config_tundev, slip_config_ipaddr); +} + +/*---------------------------------------------------------------------------*/ +void +tun_output(uint8_t *data, int len) +{ + /* fprintf(stderr, "*** Writing to tun...%d\n", len); */ + if(write(tunfd, data, len) != len) { + err(1, "serial_to_tun: write"); + } +} +/*---------------------------------------------------------------------------*/ +int +tun_input(unsigned char *data, int maxlen) +{ + int size; + if((size = read(tunfd, data, maxlen)) == -1) + err(1, "tun_input: read"); + return size; +} + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +static void +output(void) +{ + PRINTF("SUT: %u\n", uip_len); + if(uip_len > 0) { + tun_output(&uip_buf[UIP_LLH_LEN], uip_len); + } +} + + +const struct uip_fallback_interface rpl_interface = { + init, output +}; + +/*---------------------------------------------------------------------------*/ +/* tun and slip select callback */ +/*---------------------------------------------------------------------------*/ +static int +set_fd(fd_set *rset, fd_set *wset) +{ + FD_SET(tunfd, rset); + return 1; +} + +/*---------------------------------------------------------------------------*/ + +static void +handle_fd(fd_set *rset, fd_set *wset) +{ + /* Optional delay between outgoing packets */ + /* Base delay times number of 6lowpan fragments to be sent */ + /* delaymsec = 10; */ + if(delaymsec) { + struct timeval tv; + int dmsec; + gettimeofday(&tv, NULL); + dmsec=(tv.tv_sec-delaystartsec)*1000+tv.tv_usec/1000-delaystartmsec; + if(dmsec<0) delaymsec=0; + if(dmsec>delaymsec) delaymsec=0; + } + + if(delaymsec==0) { + int size; + + if(FD_ISSET(tunfd, rset)) { + size = tun_input(&uip_buf[UIP_LLH_LEN], sizeof(uip_buf)); + /* printf("TUN data incoming read:%d\n", size); */ + uip_len = size; + tcpip_input(); + + if(slip_config_basedelay) { + struct timeval tv; + gettimeofday(&tv, NULL) ; + delaymsec=slip_config_basedelay; + delaystartsec =tv.tv_sec; + delaystartmsec=tv.tv_usec/1000; + } + } + } +} +#endif /* __CYGWIN_ */ + +/*---------------------------------------------------------------------------*/