From c48b7ab78dd8b1a90945a443953092b14a73958a Mon Sep 17 00:00:00 2001 From: David Kopf Date: Tue, 28 Jun 2011 08:19:48 -0400 Subject: [PATCH] Add RPL nodes and border router to minimal-net platform (cygwin only) --- apps/webserver/httpd-cgi.c | 128 ++++++- apps/webserver/httpd-fs/header.html | 1 + apps/webserver/httpd-fs/index.html | 1 + apps/webserver/httpd-fs/status.shtml | 11 + core/net/rpl/rpl-icmp6.c | 10 + cpu/native/net/wpcap-drv.c | 33 ++ cpu/native/net/wpcap.c | 523 +++++++++++++++++++++++---- cpu/native/net/wpcap.h | 2 + platform/minimal-net/contiki-conf.h | 83 ++++- platform/minimal-net/contiki-main.c | 129 ++++++- 10 files changed, 843 insertions(+), 78 deletions(-) create mode 100644 apps/webserver/httpd-fs/status.shtml diff --git a/apps/webserver/httpd-cgi.c b/apps/webserver/httpd-cgi.c index 722268ae3..d53da8b15 100644 --- a/apps/webserver/httpd-cgi.c +++ b/apps/webserver/httpd-cgi.c @@ -158,7 +158,8 @@ make_tcp_stats(void *arg) struct httpd_state *s = (struct httpd_state *)arg; conn = &uip_conns[s->u.count]; - #if UIP_CONF_IPV6 +#if UIP_CONF_IPV6 +{ char buf[48]; httpd_sprint_ip6(conn->ripaddr, buf); return snprintf((char *)uip_appdata, uip_mss(), @@ -171,6 +172,7 @@ make_tcp_stats(void *arg) conn->timer, (uip_outstanding(conn))? '*':' ', (uip_stopped(conn))? '!':' '); +} #else return snprintf((char *)uip_appdata, uip_mss(), "%d%u.%u.%u.%u:%u%s%u%u%c %c\r\n", @@ -227,6 +229,114 @@ PT_THREAD(processes(struct httpd_state *s, char *ptr)) } PSOCK_END(&s->sout); } +#if UIP_CONF_IPV6 +/*---------------------------------------------------------------------------*/ +#define HTTPD_STRING_ATTR +#define httpd_snprintf snprintf +#define httpd_cgi_sprint_ip6 httpd_sprint_ip6 + +static const char httpd_cgi_addrh[] HTTPD_STRING_ATTR = ""; +static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "[Room for %u more]"; +static const char httpd_cgi_addrb[] HTTPD_STRING_ATTR = "
"; +static const char httpd_cgi_addrn[] HTTPD_STRING_ATTR = "(none)
"; +extern uip_ds6_nbr_t uip_ds6_nbr_cache[]; +extern uip_ds6_route_t uip_ds6_routing_table[]; +extern uip_ds6_netif_t uip_ds6_if; + +static unsigned short +make_addresses(void *p) +{ +uint8_t i,j=0; +uint16_t numprinted; + numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); + for (i=0; isout); + + PSOCK_GENERATOR_SEND(&s->sout, make_addresses, s->u.ptr); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static unsigned short +make_neighbors(void *p) +{ +uint8_t i,j=0; +uint16_t numprinted; + numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); + for (i=0; isout); + + PSOCK_GENERATOR_SEND(&s->sout, make_neighbors, s->u.ptr); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static unsigned short +make_routes(void *p) +{ +static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via "; +static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %us
"; +static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")
"; +uint8_t i,j=0; +uint16_t numprinted; + numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); + for (i=0; isout); + + PSOCK_GENERATOR_SEND(&s->sout, make_routes, s->u.ptr); + + PSOCK_END(&s->sout); +} +#endif /* UIP_CONF_IPV6 */ /*---------------------------------------------------------------------------*/ void httpd_cgi_add(struct httpd_cgi_call *c) @@ -242,10 +352,19 @@ httpd_cgi_add(struct httpd_cgi_call *c) } } /*---------------------------------------------------------------------------*/ - +#if UIP_CONF_IPV6 +static const char adrs_name[] HTTPD_STRING_ATTR = "addresses"; +static const char nbrs_name[] HTTPD_STRING_ATTR = "neighbors"; +static const char rtes_name[] HTTPD_STRING_ATTR = "routes"; +#endif HTTPD_CGI_CALL(file, file_name, file_stats); HTTPD_CGI_CALL(tcp, tcp_name, tcp_stats); HTTPD_CGI_CALL(proc, proc_name, processes); +#if UIP_CONF_IPV6 +HTTPD_CGI_CALL(adrs, adrs_name, addresses); +HTTPD_CGI_CALL(nbrs, nbrs_name, neighbors); +HTTPD_CGI_CALL(rtes, rtes_name, routes); +#endif void httpd_cgi_init(void) @@ -253,5 +372,10 @@ httpd_cgi_init(void) httpd_cgi_add(&file); httpd_cgi_add(&tcp); httpd_cgi_add(&proc); +#if UIP_CONF_IPV6 + httpd_cgi_add(&adrs); + httpd_cgi_add(&nbrs); + httpd_cgi_add(&rtes); +#endif } /*---------------------------------------------------------------------------*/ diff --git a/apps/webserver/httpd-fs/header.html b/apps/webserver/httpd-fs/header.html index 65d967cb8..3b444b1fc 100644 --- a/apps/webserver/httpd-fs/header.html +++ b/apps/webserver/httpd-fs/header.html @@ -13,6 +13,7 @@

Addresses

+%! addresses +

Neighbors

+%! neighbors +

Routes

+%! routes +

Sensors

+%! sensors + +%! file-stats . diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 2b76f919f..bd39a5405 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -198,6 +198,10 @@ dio_input(void) buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; +#if RPL_CONF_ADJUST_LLH_LEN + buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header +#endif + /* Process the DIO base option. */ i = 0; buffer = UIP_ICMP_PAYLOAD; @@ -490,6 +494,9 @@ dao_input(void) buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; +#if RPL_CONF_ADJUST_LLH_LEN + buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header +#endif pos = 0; instance_id = buffer[pos++]; @@ -687,6 +694,9 @@ dao_ack_input(void) buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; +#if RPL_CONF_ADJUST_LLH_LEN + buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header +#endif instance_id = buffer[0]; sequence = buffer[2]; diff --git a/cpu/native/net/wpcap-drv.c b/cpu/native/net/wpcap-drv.c index 3c6e5e4e5..a41c914c3 100644 --- a/cpu/native/net/wpcap-drv.c +++ b/cpu/native/net/wpcap-drv.c @@ -83,6 +83,39 @@ pollhandler(void) uip_len = 0; } } + +#ifdef UIP_FALLBACK_INTERFACE + + process_poll(&wpcap_process); + uip_len = wfall_poll(); + + if(uip_len > 0) { +#if UIP_CONF_IPV6 + if(BUF->type == uip_htons(UIP_ETHTYPE_IPV6)) { + tcpip_input(); + } else + goto bail; +#endif /* UIP_CONF_IPV6 */ + if(BUF->type == uip_htons(UIP_ETHTYPE_IP)) { + uip_len -= sizeof(struct uip_eth_hdr); + tcpip_input(); +#if !UIP_CONF_IPV6 + } else if(BUF->type == uip_htons(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(); //math + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if(uip_len > 0) { + wfall_send(); + } +#endif /* !UIP_CONF_IPV6 */ + } else { +bail: + uip_len = 0; + } + } +#endif + } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(wpcap_process, ev, data) diff --git a/cpu/native/net/wpcap.c b/cpu/native/net/wpcap.c index b0d6af43b..efc3968b6 100644 --- a/cpu/native/net/wpcap.c +++ b/cpu/native/net/wpcap.c @@ -30,7 +30,6 @@ * * Author: Oliver Schmidt * - * $Id: wpcap.c,v 1.20 2010/10/19 20:30:47 oliverschmidt Exp $ */ #define WIN32_LEAN_AND_MEAN @@ -41,6 +40,7 @@ #include #include + #ifdef __CYGWIN__ #include #else /* __CYGWIN__ */ @@ -59,6 +59,63 @@ #include "net/wpcap.h" +#if UIP_CONF_IPV6 +#include +struct in6_addr addr6; +char addr6str[64]; +/*---------------------------------------------------------------------------*/ +uint8_t +issame_ip6addr(struct in6_addr addr1, struct in6_addr addr2) +{ + return ((addr1.s6_addr32[0]==addr2.s6_addr32[0]) && + (addr1.s6_addr32[1]==addr2.s6_addr32[1]) && + (addr1.s6_addr32[2]==addr2.s6_addr32[2]) && + (addr1.s6_addr32[3]==addr2.s6_addr32[3]) ); +} +/*---------------------------------------------------------------------------*/ +uint8_t +iszero_ip6addr(struct in6_addr addr) +{ + return ((addr.s6_addr32[0]==0) && + (addr.s6_addr32[1]==0) && + (addr.s6_addr32[2]==0) && + (addr.s6_addr32[3]==0) ); +} +/*---------------------------------------------------------------------------*/ +uint8_t +sprint_ip6addr(struct in6_addr addr, char * result) +{ + unsigned char i = 0; + unsigned char zerocnt = 0; + unsigned char numprinted = 0; + char * starting = result; + + *result++='['; + while (numprinted < 8) { + if ((addr.s6_addr16[i] == 0) && (zerocnt == 0)) { + while(addr.s6_addr16[zerocnt + i] == 0) zerocnt++; + if (zerocnt == 1) { + *result++ = '0'; + numprinted++; + break; + } + i += zerocnt; + numprinted += zerocnt; + } else { + result += sprintf(result, "%x", (unsigned int) uip_ntohs(addr.s6_addr16[i])); + i++; + numprinted++; + } + if (numprinted != 8) *result++ = ':'; + } + *result++=']'; + *result=0; + return (result - starting); +} + +#endif /* UIP_CONF_IPV6 */ + + #ifdef __CYGWIN__ __attribute__((dllimport)) extern char **__argv[]; #endif /* __CYGWIN__ */ @@ -101,6 +158,45 @@ static struct pcap *(* pcap_open_live)(char *, int, int, int, char *); static int (* pcap_next_ex)(struct pcap *, struct pcap_pkthdr **, unsigned char **); static int (* pcap_sendpacket)(struct pcap *, unsigned char *, int); +#ifdef UIP_FALLBACK_INTERFACE +static struct pcap *pfall; +struct in_addr addrfall; +#if UIP_CONF_IPV6 +struct in_addr6 addrfall6; +#endif + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +/* Nothing to do here */ +} +/*---------------------------------------------------------------------------*/ +u8_t wfall_send(uip_lladdr_t *lladdr); +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +static void +output(void) +{ +#if 0 + if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { + /* Do not bounce packets back to fallback if the packet was received from it */ + PRINTF("fallback: Destination off-link but no route src="); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(" dst="); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("\n"); + } else { +#endif + PRINTF("FUT: %u\n", uip_len); + wfall_send(0); +} + +const struct uip_fallback_interface rpl_interface = { + init, output +}; + +#endif + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) #define IPBUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) @@ -113,49 +209,6 @@ error_exit(char *message) } /*---------------------------------------------------------------------------*/ static void -init_pcap(struct in_addr addr) -{ - struct pcap_if *interfaces; - struct pcap_addr *paddr; - char error[256]; - - if(pcap_findalldevs(&interfaces, error) == -1) { - error_exit(error); - } - - while(interfaces != NULL) { - log_message("init_pcap: found interface: ", interfaces->description); - - if(interfaces->addresses != NULL) { - for(paddr = interfaces->addresses; - paddr != NULL; - paddr = paddr->next) { - if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET) { - - struct in_addr interface_addr; - interface_addr = ((struct sockaddr_in *)paddr->addr)->sin_addr; - log_message("init_pcap: with address: ", inet_ntoa(interface_addr)); - - if(interface_addr.s_addr == addr.s_addr) { - pcap = pcap_open_live(interfaces->name, UIP_BUFSIZE, 0, -1, error); - if(pcap == NULL) { - error_exit(error); - } -// pcap_setdirection(PCAP_D_IN); //Not implemented in windows yet? - return; - } - } - } - } - interfaces = interfaces->next; - } - - if(interfaces == NULL) { - error_exit("no interface found with specified ip address\n"); - } -} -/*---------------------------------------------------------------------------*/ -static void set_ethaddr(struct in_addr addr) { PIP_ADAPTER_ADDRESSES adapters; @@ -214,25 +267,301 @@ set_ethaddr(struct in_addr addr) error_exit("no adapter found with ip addr specified on cmdline\n"); } } + +#if UIP_CONF_IPV6 +/*---------------------------------------------------------------------------*/ +static void +set_ethaddr6(struct in_addr6 addr) +{ + PIP_ADAPTER_ADDRESSES adapters; + ULONG size = 0; + + if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER, + NULL, NULL, &size) != ERROR_BUFFER_OVERFLOW) { + error_exit("error on access to adapter list size\n"); + } + adapters = alloca(size); + if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER, + NULL, adapters, &size) != ERROR_SUCCESS) { + error_exit("error on access to adapter list\n"); + } + + while(adapters != NULL) { + + char buffer[256]; + WideCharToMultiByte(CP_ACP, 0, adapters->Description, -1, + buffer, sizeof(buffer), NULL, NULL); + log_message("set_ethaddr: found adapter: ", buffer); + + if(adapters->FirstUnicastAddress != NULL && + adapters->FirstUnicastAddress->Address.lpSockaddr != NULL && + adapters->FirstUnicastAddress->Address.lpSockaddr->sa_family == AF_INET6) { + + struct in_addr6 adapter_addr; + adapter_addr = ((struct sockaddr_in6 *)adapters->FirstUnicastAddress->Address.lpSockaddr)->sin6_addr; + sprint_ip6addr(adapter_addr, addr6str); + log_message("set_ethaddr: with ipv6 address: : ", addr6str); + if(issame_ip6addr(adapter_addr,addr6)) { + if(adapters->PhysicalAddressLength != 6) { + error_exit("ip addr specified on cmdline does not belong to an ethernet card\n"); + } + wsprintf(buffer, "%02X-%02X-%02X-%02X-%02X-%02X", + adapters->PhysicalAddress[0], adapters->PhysicalAddress[1], + adapters->PhysicalAddress[2], adapters->PhysicalAddress[3], + adapters->PhysicalAddress[4], adapters->PhysicalAddress[5]); + log_message("set_ethaddr: ethernetaddr: ", buffer); +#if UIP_CONF_IPV6 +// int i;for (i=0;i<6;i++) uip_ethaddr.addr[i] = adapters->PhysicalAddress[i]; //does this need doing? +#else + uip_setethaddr((*(struct uip_eth_addr *)adapters->PhysicalAddress)); +#endif + break; + } + } + adapters = adapters->Next; + } + + if(adapters == NULL) { + error_exit("no adapter found with ip addr specified on cmdline\n"); + } +} +#endif +/*---------------------------------------------------------------------------*/ +static void +init_pcap(struct in_addr addr) +{ + struct pcap_if *interfaces; + struct pcap_addr *paddr; + char error[256]; + + if(pcap_findalldevs(&interfaces, error) == -1) { + error_exit(error); + } + + while(interfaces != NULL) { + log_message("init_pcap: found interface: ", interfaces->description); + + if(interfaces->addresses != NULL) { + for(paddr = interfaces->addresses; + paddr != NULL; + paddr = paddr->next) { + if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET) { + struct in_addr interface_addr; + interface_addr = ((struct sockaddr_in *)paddr->addr)->sin_addr; + log_message("init_pcap: with address: ", inet_ntoa(interface_addr)); + + if(interface_addr.s_addr == addr.s_addr) { + pcap = pcap_open_live(interfaces->name, UIP_BUFSIZE, 0, -1, error); + if(pcap == NULL) { + error_exit(error); + } +#ifdef UIP_FALLBACK_INTERFACE + log_message("init_pcap: Opened as primary interface",""); +#endif +// pcap_setdirection(PCAP_D_IN); //Not implemented in windows yet? + set_ethaddr(addr); + +#ifdef UIP_FALLBACK_INTERFACE + } + if (pfall && pcap) return; + if(interface_addr.s_addr == addrfall.s_addr) { + pfall = pcap_open_live(interfaces->name, UIP_BUFSIZE, 0, -1, error); + if(pfall == NULL) { + error_exit(error); + } + log_message("init_pcap: Opened as fallback interface",""); + if (pcap) return; + } +#else + return; + } +#endif + +#if UIP_CONF_IPV6 + + } else if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET6) { + struct in6_addr interface_addr; + interface_addr = ((struct sockaddr_in6 *)paddr->addr)->sin6_addr; + + sprint_ip6addr(interface_addr, addr6str); + log_message("init_pcap: with ipv6 address: ", addr6str); + + if (issame_ip6addr(interface_addr, addr6)) { + pcap = pcap_open_live(interfaces->name, UIP_BUFSIZE, 0, -1, error); + if(pcap == NULL) { + error_exit(error); + } +#ifdef UIP_FALLBACK_INTERFACE + log_message("init_pcap: Opened as primary interface",""); +#endif + set_ethaddr6(addr6); +// pcap_setdirection(PCAP_D_IN); //Not implemented in windows yet? +#ifdef UIP_FALLBACK_INTERFACE + } + if (pfall && pcap) return; //exit when we have both interfaces + + if (issame_ip6addr(interface_addr, addrfall6)) { + pfall = pcap_open_live(interfaces->name, UIP_BUFSIZE, 0, -1, error); + if(pfall == NULL) { + error_exit(error); + } + log_message("init_pcap: Opened as fallback interface",""); + if (pcap) return; + } +#else + return; + } +#endif +#endif /* UIP_CONF_IPV6 */ + } + } + } + interfaces = interfaces->next; + + } + + if(interfaces == NULL) { + error_exit("no interface found with specified ip address\n"); + } +} /*---------------------------------------------------------------------------*/ void wpcap_init(void) { struct in_addr addr; + addr.s_addr = INADDR_NONE; //255.255.255.255 +#ifdef UIP_FALLBACK_INTERFACE + addrfall.s_addr = INADDR_NONE; +#endif + /* Pick up possible ip addresses from command line */ #ifdef __CYGWIN__ - addr.s_addr = inet_addr((*__argv)[1]); -#else /* __CYGWIN__ */ - addr.s_addr = inet_addr(__argv[1]); -#endif /* __CYGWIN__ */ - if(addr.s_addr == INADDR_NONE) { -// error_exit("usage: \n"); - addr.s_addr = inet_addr("10.10.10.10"); - log_message("usage: \n-->I'll try guessing ", inet_ntoa(addr)); - } else { - log_message("wpcap_init:cmdline address: ", inet_ntoa(addr)); + if ((*__argv)[1]) { + addr.s_addr = inet_addr((*__argv)[1]); +#if UIP_CONF_IPV6 + uiplib_ipaddrconv((*__argv)[1],(uip_ipaddr_t*) &addr6.s6_addr); +#endif +#ifdef UIP_FALLBACK_INTERFACE + if ((*__argv)[2]) { + addrfall.s_addr = inet_addr((*__argv)[2]); +#if UIP_CONF_IPV6 + uiplib_ipaddrconv((*__argv)[2],(uip_ipaddr_t*) &addrfall6.s6_addr); +#endif + } +#endif } +#else /* __CYGWIN__ */ +/* VC++ build on win32 platform. Currently the platform has no ipv6 support */ + addr.s_addr = inet_addr(__argv[1]); +#if UIP_CONF_IPV6 + if((__argv)[1]) + uiplib_ipaddrconv((__argv)[1],(uip_ipaddr_t*) &addr6.s6_addr); +#endif +#ifdef UIP_FALLBACK_INTERFACE + addrfall.s_addr = inet_addr(__argv[2]); +#if UIP_CONF_IPV6 + if((__argv)[2]) + uiplib_ipaddrconv((__argv)[2],(uip_ipaddr_t*) &addrfall6.s6_addr); +#endif +#endif +#endif /* __CYGWIN__ */ + +#if DEBUG + log_message("wpcap_init:Passed ipv4 ", inet_ntoa(addr)); + sprint_ip6addr(addr6, addr6str); + log_message("wpcap_init:Passed ipv6 ", addr6str); +#ifdef UIP_FALLBACK_INTERFACE + log_message("wpcap_init:Passed fallback ipv4 ", inet_ntoa(addrfall)); + sprint_ip6addr(addrfall6, addr6str); + log_message("wpcap_init:Passed fallback ipv6 ", addr6str); +#endif +#endif + + /* Use build defaults if not enough addresses passed */ +#if UIP_CONF_IPV6 + +#ifdef UIP_FALLBACK_INTERFACE + if(addrfall.s_addr == INADDR_NONE) { + if(iszero_ip6addr(addrfall6)) { +#ifdef WPCAP_WPCAP_FALLBACK_ADDRESS + addrfall.s_addr = inet_addr(WPCAP_FALLBACK_ADDRESS); +// if(addrfall.s_addr == INADDR_NONE) { //use ipv6 if contiki-conf.h override + uiplib_ipaddrconv(WPCAP_FALLBACK_ADDRESS,(uip_ipaddr_t*) &addrfall6.s6_addr); +// } +#else +// addrfall.s_addr = inet_addr("10.2.10.10"); + uiplib_ipaddrconv("bbbb::1",(uip_ipaddr_t*) &addrfall6.s6_addr); +#endif + } + } +#endif + + if(addr.s_addr == INADDR_NONE) { + if(iszero_ip6addr(addr6)) { +#ifdef WPCAP_INTERFACE_ADDRESS + addr.s_addr = inet_addr(WPCAP_INTERFACE_ADDRESS); +// if(addr.s_addr == INADDR_NONE) { + uiplib_ipaddrconv(WPCAP_INTERFACE_ADDRESS,(uip_ipaddr_t*) &addr6.s6_addr); +// } +#else + addr.s_addr = inet_addr("10.10.10.10"); //prefer ipv4 default for legacy compatibility +// uiplib_ipaddrconv("aaaa::1",(uip_ipaddr_t*) &addr6.s6_addr); +#endif + +#ifdef UIP_FALLBACK_INTERFACE + log_message("usage: \n",""); + if(addr.s_addr != INADDR_NONE) { + log_message("-->I'll try interface address ", inet_ntoa(addr)); + } else { + sprint_ip6addr(addr6, addr6str); + log_message("-->I'll try interface address ", addr6str); + } + if(addrfall.s_addr != INADDR_NONE) { + log_message("--> and fallback address ", inet_ntoa(addrfall)); + } else { + sprint_ip6addr(addrfall6, addr6str); + log_message("--> and fallback address ", addr6str); + } +#else + if(addr.s_addr != INADDR_NONE) { + log_message("usage: \n-->I'll try guessing ", inet_ntoa(addr)); + } else { + sprint_ip6addr(addr6, addr6str); + log_message("usage: \n-->I'll try guessing ", addr6str); + } +#endif + } + } +#else /* ip4 build */ + if(addr.s_addr == INADDR_NONE) { +#ifdef WPCAP_INTERFACE_ADDRESS + addr.s_addr = inet_addr(WPCAP_INTERFACE_ADDRESS); +#else + addr.s_addr = inet_addr("10.10.10.10"); +#endif + log_message("usage: \n-->I'll try guessing ", inet_ntoa(addr)); + } +#endif /* UIP_CONF_IPV6 */ + +#if DEBUG + log_message("wpcap_init:Using ipv4 ", inet_ntoa(addr)); + sprint_ip6addr(addr6, addr6str); + log_message("wpcap_init:Using ipv6 ", addr6str); +#ifdef UIP_FALLBACK_INTERFACE + log_message("wpcap_init:Using fallback ipv4 ", inet_ntoa(addrfall)); + sprint_ip6addr(addrfall6, addr6str); + log_message("wpcap_init:Using fallback ipv6 ", addr6str); +#endif +#endif + + // log_message("wpcap_init:cmdline address: ", inet_ntoa(addr)); + + wpcap = LoadLibrary("wpcap.dll"); pcap_findalldevs = (int (*)(struct pcap_if **, char *)) GetProcAddress(wpcap, "pcap_findalldevs"); @@ -248,8 +577,7 @@ wpcap_init(void) error_exit("error on access to winpcap library\n"); } - init_pcap(addr); - set_ethaddr(addr); + init_pcap(addr); } @@ -268,6 +596,44 @@ wpcap_poll(void) } #if UIP_CONF_IPV6 +/* Since pcap_setdirection(PCAP_D_IN) is not implemented in winpcap all outgoing packets + * will be echoed back. The stack will ignore any packets not addressed to it, but initial + * ipv6 neighbor solicitations are addressed to everyone and the echoed NS sent on startup + * would be processed as a conflicting NS race which would cause a stack shutdown. + * So discard all packets with our source address (packet starts destaddr, srcaddr, ...) + * + */ + int i; + for (i=0;icaplen > UIP_BUFSIZE) { + return 0; + } +// PRINTF("SIN: %lu\n", packet_header->caplen); + CopyMemory(uip_buf, packet, packet_header->caplen); + return (u16_t)packet_header->caplen; + +} + +#ifdef UIP_FALLBACK_INTERFACE +u16_t +wfall_poll(void) +{ + struct pcap_pkthdr *packet_header; + unsigned char *packet; + + switch(pcap_next_ex(pfall, &packet_header, &packet)) { + case -1: + error_exit("error on fallback poll\n"); + case 0: + return 0; + } +#if UIP_CONF_IPV6 /* Since pcap_setdirection(PCAP_D_IN) is not implemented in winpcap all outgoing packets * will be echoed back. The stack will ignore any packets not addressed to it, but initial * ipv6 neighbor solicitations are addressed to everyone and the echoed NS sent on startup @@ -286,16 +652,46 @@ wpcap_poll(void) if(packet_header->caplen > UIP_BUFSIZE) { return 0; } - + PRINTF("FIN: %lu\n", packet_header->caplen); CopyMemory(uip_buf, packet, packet_header->caplen); return (u16_t)packet_header->caplen; } +#endif + /*---------------------------------------------------------------------------*/ #if UIP_CONF_IPV6 u8_t wpcap_send(uip_lladdr_t *lladdr) +{ + // if(lladdr == NULL) { //when fallback used this gets ptr to lladdr of all zeroes on forwarded packets + if(1) { +/* the dest must be multicast*/ + (&BUF->dest)->addr[0] = 0x33; + (&BUF->dest)->addr[1] = 0x33; + (&BUF->dest)->addr[2] = IPBUF->destipaddr.u8[12]; + (&BUF->dest)->addr[3] = IPBUF->destipaddr.u8[13]; + (&BUF->dest)->addr[4] = IPBUF->destipaddr.u8[14]; + (&BUF->dest)->addr[5] = IPBUF->destipaddr.u8[15]; + } else { + memcpy(&BUF->dest, lladdr, UIP_LLADDR_LEN); + } + memcpy(&BUF->src, &uip_lladdr, UIP_LLADDR_LEN); + PRINTF("SUT: %u\n", uip_len); + PRINTF("Src= %02x %02x %02x %02x %02x %02x",(&BUF->src)->addr[0],(&BUF->src)->addr[1],(&BUF->src)->addr[2],(&BUF->src)->addr[3],(&BUF->src)->addr[4],(&BUF->src)->addr[5]); + PRINTF(" Dst= %02x %02x %02x %02x %02x %02x",(&BUF->dest)->addr[0],(&BUF->dest)->addr[1],(&BUF->dest)->addr[2],(&BUF->dest)->addr[3],(&BUF->dest)->addr[4],(&BUF->dest)->addr[5]); + PRINTF(" Type=%04x\n",BUF->type); + BUF->type = UIP_HTONS(UIP_ETHTYPE_IPV6); + uip_len += sizeof(struct uip_eth_hdr); + if(pcap_sendpacket(pcap, uip_buf, uip_len) == -1) { + error_exit("error on send\n"); + } +return 0; +} +#ifdef UIP_FALLBACK_INTERFACE +u8_t +wfall_send(uip_lladdr_t *lladdr) { if(lladdr == NULL) { /* the dest must be multicast*/ @@ -309,17 +705,18 @@ wpcap_send(uip_lladdr_t *lladdr) memcpy(&BUF->dest, lladdr, UIP_LLADDR_LEN); } memcpy(&BUF->src, &uip_lladdr, UIP_LLADDR_LEN); - - PRINTF("Src= %02x %02x %02x %02x %02x %02x",(&BUF->src)->addr[0],(&BUF->src)->addr[1],(&BUF->src)->addr[2],(&BUF->src)->addr[3],(&BUF->src)->addr[4],(&BUF->src)->addr[5]); - PRINTF(" Dst= %02x %02x %02x %02x %02x %02x",(&BUF->dest)->addr[0],(&BUF->dest)->addr[1],(&BUF->dest)->addr[2],(&BUF->dest)->addr[3],(&BUF->dest)->addr[4],(&BUF->dest)->addr[5]); - PRINTF(" Type=%04x\n",BUF->type); + PRINTF("FUT: %u\n", uip_len); + PRINTF("Srcf= %02x %02x %02x %02x %02x %02x",(&BUF->src)->addr[0],(&BUF->src)->addr[1],(&BUF->src)->addr[2],(&BUF->src)->addr[3],(&BUF->src)->addr[4],(&BUF->src)->addr[5]); + PRINTF(" Dstf= %02x %02x %02x %02x %02x %02x",(&BUF->dest)->addr[0],(&BUF->dest)->addr[1],(&BUF->dest)->addr[2],(&BUF->dest)->addr[3],(&BUF->dest)->addr[4],(&BUF->dest)->addr[5]); + PRINTF(" Typef=%04x\n",BUF->type); BUF->type = UIP_HTONS(UIP_ETHTYPE_IPV6); uip_len += sizeof(struct uip_eth_hdr); - if(pcap_sendpacket(pcap, uip_buf, uip_len) == -1) { - error_exit("error on send\n"); + if(pcap_sendpacket(pfall, uip_buf, uip_len) == -1) { + error_exit("error on fallback send\n"); } return 0; } +#endif #else /* UIP_CONF_IPV6 */ void wpcap_send(void) diff --git a/cpu/native/net/wpcap.h b/cpu/native/net/wpcap.h index 69b96a369..2f4a0cc52 100644 --- a/cpu/native/net/wpcap.h +++ b/cpu/native/net/wpcap.h @@ -38,8 +38,10 @@ void wpcap_init(void); u16_t wpcap_poll(void); +u16_t wfall_poll(void); #if UIP_CONF_IPV6 u8_t wpcap_send(uip_lladdr_t *lladdr); +u8_t wfall_send(uip_lladdr_t *lladdr); #else void wpcap_send(void); #endif diff --git a/platform/minimal-net/contiki-conf.h b/platform/minimal-net/contiki-conf.h index 617fc9e87..2f61858d5 100644 --- a/platform/minimal-net/contiki-conf.h +++ b/platform/minimal-net/contiki-conf.h @@ -51,6 +51,74 @@ typedef uint32_t u32_t; typedef int32_t s32_t; typedef unsigned short uip_stats_t; +#if UIP_CONF_IPV6 +/* The Windows build uses wpcap to connect to a host interface. It finds the interface by scanning for + * an address, which can be specified here and overridden with the command line. + * An ip4 or ip6 address can be used; this allows turning off the ip4 protocol on the interface. + * The existing turorials use an ipv4 address, so we leave that as the default. + * Non-windows builds don't use this define. + */ +//#define WPCAP_INTERFACE_ADDRESS "fdfd::1" //10.10.10.10 is the default (even for ipv6) + +/* Minimal-net gets a 6 byte ethernet MAC assigned in uip.c, currently {0x00,0x06,0x98,0x00,0x02,0x32} + * This gets converted to a link layer address of [fe80::206:98ff:fe00:232] + * You could change the uip.c address when running multiple instances, however HARD_CODED_ADDRESS + * can also specify a different MAC address if any of the last three bytes are non-zero. It can also + * specify a prefix if any of the first four longs are nonzero. RPL builds use this to pass a prefix + * to the border router and also to ensure it has a different link-layer address from the RPL end node. + * HARD_CODED_ADDRESS can also be changed in /platform/minimal-net/contiki-main.c so as not to force complete + * rebuilds when making multiple instances of a minimal-net client. +*/ +//#define HARD_CODED_ADDRESS "::10" //assign link-layer address fe80::ff:fe00:10, wait for RA or RPL prefix +//#define HARD_CODED_ADDRESS "fdfd::" //assign prefix; address becomes fdfd::206:98ff:fe00:232 +//#define HARD_CODED_ADDRESS "fdfd::10" //assign prefix and ipv6 address fdfd::ff:fe00:10 + +/* RPL currently works only on Windows. *nix would require converting the tun interface to two pcap tees. */ +#define UIP_CONF_IPV6_RPL 0 +#define RPL_BORDER_ROUTER 0 +#endif + +#if UIP_CONF_IPV6_RPL +/* RPL motes use the uip.c link layer address or optionally the harded coded address (but without the prefix!) + * Different instances can be made by changing the link layer portion of HARD_CODED_ADDRESS in contiki-main.c + * Rename them to e.g. webserver6.10, webserver6.11, ... + * They should all attach to a minimal-net rpl border that uses the same primary interface. + */ +#define RPL_CONF_ADJUST_LLH_LEN 1 +#define HARD_CODED_ADDRESS "bbbb::10" //the prefix is ignored for a rpl end node + +#if RPL_BORDER_ROUTER +/* RPL border router accepts packets from the host through the fallback and directs them to + * the primary interface. Thus the fallback and rpl dag prefix must be the same. The prefix of + * the primary interface does not matter! + * Rename this build to e.g. webrouter. Then on Windows create two loopback interfaces, bbbb:: and fdfd:: + * Attach the RPL end nodes to fdfd:: and the webrouter to fdfd:: with bbbb:: as the fallback. + * Direct browser to bbbb::ff:fe00:1/status.html, bbbb::ff:fe00:10/status.html, bbbb::ff:fe00:20/status.html. + * The traffic will go through the bbbb:: interface to the router, then out the fdfd:: interface to the end + * nodes. The end nodes must be explicitly added as neighbors to avoid a blocking NS + * netsh interface ipv6 add neighbor bbbb::ff:fe00:10 33-33-ff-33-44-10 interface=16 (# of the bbbb interface) + * netsh interface ipv6 add neighbor bbbb::ff:fe00:20 33-33-ff-33-44-20 interface=16 (# of the bbbb interface) + * + * Instead of using the fdfd:: loopback it is also possible to attach the border router to another interface, + * e.g. the jackdaw RNDIS <-> repeater. Then RPL will configure on the radio network and the RF motes will + * be reached through bbbb::. + * Possibly minimal-net RPL motes could also be added to this interface? + * + */ +#define UIP_CONF_ROUTER 1 +//#define RPL_CONF_STATS 0 +//#define UIP_CONF_BUFFER_SIZE 1300 +#undef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE rpl_interface +//#define WPCAP_FALLBACK_ADDRESS "bbbb::1" //bbbb::1 is the default fallback prefix +#undef HARD_CODED_ADDRESS +#define HARD_CODED_ADDRESS "bbbb::1" //bbbb::ff:fe00:1 is the RPL border router default +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 +#endif + +#endif #define UIP_CONF_MAX_LISTENPORTS 40 #define UIP_CONF_MAX_CONNECTIONS 40 @@ -70,10 +138,17 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_IPV6_QUEUE_PKT 1 #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 1 -#define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_NEIGHBORS 4 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 +//#define UIP_CONF_NETIF_MAX_ADDRESSES 5 +//#define UIP_CONF_ND6_MAX_PREFIXES 3 +//#define UIP_CONF_ND6_MAX_NEIGHBORS 40 +//#define UIP_CONF_ND6_MAX_DEFROUTERS 2 +#define UIP_CONF_DS6_NBR_NBU 100 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 5 +#define UIP_CONF_DS6_ROUTE_NBU 100 +#define UIP_CONF_DS6_ADDR_NBU 10 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 #endif /* UIP_CONF_IPV6 */ typedef unsigned long clock_time_t; diff --git a/platform/minimal-net/contiki-main.c b/platform/minimal-net/contiki-main.c index 652c31270..ba10af75d 100644 --- a/platform/minimal-net/contiki-main.c +++ b/platform/minimal-net/contiki-main.c @@ -57,6 +57,72 @@ PROCINIT(&etimer_process, &tcpip_process, &wpcap_process, &serial_line_process); PROCINIT(&etimer_process, &tapdev_process, &tcpip_process, &serial_line_process); #endif /* __CYGWIN__ */ +#if RPL_BORDER_ROUTER +#include "net/rpl/rpl.h" + +uint16_t dag_id[] = {0x1111, 0x1100, 0, 0, 0, 0, 0, 0x0011}; + +PROCESS(border_router_process, "RPL Border Router"); +PROCESS_THREAD(border_router_process, ev, data) +{ + + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + +{ rpl_dag_t *dag; + char buf[sizeof(dag_id)]; + memcpy(buf,dag_id,sizeof(dag_id)); + dag = rpl_set_root((uip_ip6addr_t *)buf); + +/* Assign separate addresses to the uip stack and the host network interface, but with the same prefix */ +/* E.g. bbbb::ff:fe00:200 to the stack and bbbb::1 to the host *fallback* network interface */ +/* Otherwise the host will trap packets intended for the stack, just as the stack will trap packets intended for the host */ +/* $ifconfig usb0 -arp on Ubuntu to skip the neighbor solicitations. Add explicit neighbors on other OSs */ + if(dag != NULL) { + printf("Created a new RPL dag\n"); + +#if UIP_CONF_ROUTER_RECEIVE_RA +//Contiki stack will shut down until assigned an address from the interface RA +//Currently this requires changes in the core rpl-icmp6.c to pass the link-local RA broadcast + +#else +void sprint_ip6(uip_ip6addr_t addr); + int i; + uip_ip6addr_t ipaddr; +#ifdef HARD_CODED_ADDRESS + uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); +#else + uip_ip6addr(&ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1); +#endif + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + rpl_set_prefix(dag, &ipaddr, 64); + + for (i=0;i