diff --git a/apps/webserver/httpd-cgi.c b/apps/webserver/httpd-cgi.c
index 722268ae3..e998812c2 100644
--- a/apps/webserver/httpd-cgi.c
+++ b/apps/webserver/httpd-cgi.c
@@ -158,7 +158,7 @@ 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(),
@@ -227,6 +227,113 @@ 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 +349,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 +369,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