Skip to content

Jackdaw RNDIS RPL border router

Benoît Thébaudeau edited this page Sep 23, 2019 · 5 revisions

The RPL protocol has recently been added to contiki in the form of a contiki-conf.h option:

 #define UIP_CONF_IPV6_RPL 1

along with /examples/rpl-border-router which builds a border router that interfaces through a tunslip6 connection to linux. Apparently only one border router is allowed in the specification.

Some exploration has been done to make a RPL border router that interfaces through the Jackdaw's RNDIS network interface. The Remote Network Driver Interface Specification uses existing Windows (and Linux, but not Macintosh) network drivers and protocols, so the protocols used by tunslip6 can not be used.

The Jackdaw is normally a repeater with minimal ipv6 routines implemented via fakeuip.c, but RPL can be added by including the full uip6 stack (UIP_CONF_IPV6=1 instead of CONTIKI_NO_NET in the top-level makefile). This pushes the Jackdaw 8KB of RAM, but fortunately UIP_CONF_TCP and the associated buffers are not needed so there is still sufficient space for a full 1280 byte MTU along with perhaps ten entries in the router tables. The address prefix must be hard-coded since the tunslip6 method of transferring a prefix does not exist, then the Jackdaw will pass along the prefix to the RPL network and any packets sent through RNDIS will be passed to 6LowPAN if the neighbor is known. Similarly any response from 6LowPAN will be sent back through RNDIS (the rpl_fallback_interface) if the neighbor is not known (consequently the Jackdaw would bounce packets sent through RNDIS back through RNDIS if the neighbor is not known, and they would go back and forth until the hop count is exceeded. tunslip6 prevents this from happening, similar code has been added to the Jackdaw).

Another problem is that contiki currently has no provision for two interfaces which might have different link-layer headers; tunslip6 handles packet transfers through rebuffering but UIP_CONF_LLH_LEN is 14 for the ethernet headers but would be zero for 6LowPAN. Since the RPL code only gets 6LowPAN packets, a workaround is to patch all the packet length calculations in rpl-icmp6.c to undo the assumption of a larger uip_l2_l3_icmp_hdr_len. This change needs to be done in three places at present. If any are missed the corresponding RPL packet will not be fully decoded, causing for example a zero lifetime and immediate expiration for the route:

 --In rpl-icmp6.c, search for uip_l2_l3_icmp_hdr_len (three occurences) and modify as follows--
 //buffer_length = uip_len - uip_l2_l3_icmp_hdr_len;
  buffer_length = uip_len - uip_l2_l3_icmp_hdr_len+UIP_CONF_LLH_LEN

With all this done there is one final problem: By default RNDIS does the ipv6 address resolution protocol of neighbor solication/neighbor advertisement, and RPL doesn't support link-layer NS/NA broadcasts (even if it did you would not want the extra traffic). Without a NA response RNDIS will not send any IPV6 addressed packets.

Although the Jackdaw could trap the NS and construct a NA reply, it is simple to disable NS/NA on the Linux RNDIS interface:

 ifconfig usb0 -arp
 ip -6 address add bbbb::0/64 dev usb0

and Voila, it works! In Windows the NS/NA is apparently part of nud (neighbor unreachability detection) which can't be turned off, possibly as a result of some security update (spoofing a link-local return address could get through the firewall as a trusted interface). What should work is

 netsh interface ipv6 set nud=disabled interface=nn

but that gives a parameter error.

  netsh interface ipv6 set nud=disabled interface=nn store=persistent

gives no error but nud is still displayed as active, even after a reboot:

 netsh interface ipv6 show interface nn
 ...
 Neighbor Unreachability Detecion   : enabled

How to eliminate the blocking NS? One way is to add the neighbors manually, e.g. if the Jackdaw hard-coded prefix is bbbb::/64 and the Ravens are at bbbb::11:22ff:fe33:4455, 4456, 4457, ...

 netsh interface ipv6 add neighbor bbbb::11:22ff:fe33:4455 33-33-ff-33-44-55 interface=nn
 netsh interface ipv6 add neighbor bbbb::11:22ff:fe33:4456 33-33-ff-33-44-56 interface=nn
 netsh interface ipv6 add neighbor bbbb::11:22ff:fe33:4457 33-33-ff-33-44-57 interface=nn

then the link-local neighbors are added automatically, and

 netsh interface ipv6 show neighbor
 ...
 bbbb::11:22ff:fe33:4455                       33-33-ff-33-44-55  Permanent
 bbbb::11:22ff:fe33:4456                       33-33-ff-33-44-56  Permanent
 bbbb::11:22ff:fe33:4457                       33-33-ff-33-44-57  Permanent
 ff02::1:ff33:4455                             33-33-ff-33-44-55  Permanent
 ff02::1:ff33:4456                             33-33-ff-33-44-56  Permanent
 ff02::1:ff33:4457                             33-33-ff-33-44-57  Permanent

After this windows will send ipv6 packets directly to those three addresses, still sending NS to any others which the Jackdaw will drop [but]. What effect doing this would have on security?

On FreeBSD 8.2 guest on Windows 7 host (and thus on the Mac?), on the CDC-ECM the same effect can be achieved with:

 ndp -s bbbb::11:22ff:fe33:4455 33:33:ff:33:44:55
 ndp -s fe80::31:33:ff:ff:fe:33:44:55%ue0 33:33:ff:33:44:55

and so on for the other neighbors.

Before this a number of things need to be done.

Firmware: edit the contiki-conf.h for the avr-ravenusb platform and define:

 #define USB_CONF_MACINTOSH 1

This will enable CDC ECM in the firmware. Build the ravenusbstick firmware and upload it to the Jackdaw.

Enable IPv6 stuff on FreeBSD editing /etc/rc.conf adding this line:

 ipv6_enable="YES"

Then reboot the system (I've tried /etc/rc.d/network_ipv6 start without success).

Plug the Jackdaw. If you are running FreeBSD as Virtualbox guest you need to connect the device to the virtual machine. This is not enough (at least for me). You might need to chance the Jackdaw USB configuration selecting configuration #1. This can be done with:

 usbconfig -u 0 -a 2 set_config 1

The above command will cause FreeBSD to load/use the if_cdce module. The Ethernet interface created is named ue0.

If now ue0 is enabled with:

 ifconfig ue0 up

FreeBSD will automatically autoconfigure the link local IPv6 address on the interface.

If you also want to use the CDC ACM serial interface you need to manually load the umodem module:

 kldload umodem

The device /dev/cuaU0 will be created and can be opened with Minicom.

Clone this wiki locally