From d89339d61dd091ac2682815b2278f3eb33c96b33 Mon Sep 17 00:00:00 2001 From: sdhsdh Date: Tue, 20 Jan 2009 00:28:14 +0000 Subject: [PATCH] - initial commit of blip (berkeley low-power ip) stack --- support/sdk/c/blip/Makefile | 12 + support/sdk/c/blip/driver/Makefile | 41 + support/sdk/c/blip/driver/config.c | 79 + support/sdk/c/blip/driver/config.h | 16 + support/sdk/c/blip/driver/hashtable.c | 274 ++ support/sdk/c/blip/driver/hashtable.h | 199 ++ support/sdk/c/blip/driver/hashtable_private.h | 106 + support/sdk/c/blip/driver/logging.c | 96 + support/sdk/c/blip/driver/logging.h | 64 + support/sdk/c/blip/driver/nwstate.c | 503 +++ support/sdk/c/blip/driver/nwstate.h | 112 + support/sdk/c/blip/driver/radvd-1.0/CHANGES | 346 ++ support/sdk/c/blip/driver/radvd-1.0/COPYRIGHT | 37 + .../sdk/c/blip/driver/radvd-1.0/INTRO.html | 142 + support/sdk/c/blip/driver/radvd-1.0/Makefile | 572 ++++ .../sdk/c/blip/driver/radvd-1.0/Makefile.am | 63 + .../sdk/c/blip/driver/radvd-1.0/Makefile.in | 572 ++++ support/sdk/c/blip/driver/radvd-1.0/README | 61 + support/sdk/c/blip/driver/radvd-1.0/TODO | 59 + support/sdk/c/blip/driver/radvd-1.0/VERSION | 6 + .../sdk/c/blip/driver/radvd-1.0/aclocal.m4 | 136 + .../sdk/c/blip/driver/radvd-1.0/config.cache | 48 + .../sdk/c/blip/driver/radvd-1.0/config.guess | 1319 ++++++++ support/sdk/c/blip/driver/radvd-1.0/config.h | 57 + .../sdk/c/blip/driver/radvd-1.0/config.h.in | 56 + .../sdk/c/blip/driver/radvd-1.0/config.log | 107 + .../sdk/c/blip/driver/radvd-1.0/config.status | 353 ++ .../sdk/c/blip/driver/radvd-1.0/config.sub | 1440 ++++++++ support/sdk/c/blip/driver/radvd-1.0/configure | 2911 +++++++++++++++++ .../sdk/c/blip/driver/radvd-1.0/configure.in | 157 + .../c/blip/driver/radvd-1.0/copyright.blurb | 14 + .../sdk/c/blip/driver/radvd-1.0/defaults.h | 226 ++ support/sdk/c/blip/driver/radvd-1.0/depcomp | 479 +++ .../c/blip/driver/radvd-1.0/device-bsd44.c | 251 ++ .../c/blip/driver/radvd-1.0/device-common.c | 101 + .../c/blip/driver/radvd-1.0/device-linux.c | 298 ++ support/sdk/c/blip/driver/radvd-1.0/gram.c | 2390 ++++++++++++++ support/sdk/c/blip/driver/radvd-1.0/gram.h | 160 + support/sdk/c/blip/driver/radvd-1.0/gram.y | 621 ++++ .../sdk/c/blip/driver/radvd-1.0/includes.h | 98 + .../sdk/c/blip/driver/radvd-1.0/install-sh | 251 ++ .../sdk/c/blip/driver/radvd-1.0/interface.c | 248 ++ support/sdk/c/blip/driver/radvd-1.0/log.c | 182 ++ support/sdk/c/blip/driver/radvd-1.0/missing | 336 ++ .../sdk/c/blip/driver/radvd-1.0/mkinstalldirs | 40 + .../sdk/c/blip/driver/radvd-1.0/pathnames.h | 48 + support/sdk/c/blip/driver/radvd-1.0/process.c | 454 +++ .../sdk/c/blip/driver/radvd-1.0/radvd.8.man | 173 + support/sdk/c/blip/driver/radvd-1.0/radvd.c | 638 ++++ .../c/blip/driver/radvd-1.0/radvd.conf.5.man | 591 ++++ .../blip/driver/radvd-1.0/radvd.conf.example | 116 + support/sdk/c/blip/driver/radvd-1.0/radvd.h | 225 ++ .../c/blip/driver/radvd-1.0/radvdump.8.man | 87 + .../sdk/c/blip/driver/radvd-1.0/radvdump.c | 477 +++ support/sdk/c/blip/driver/radvd-1.0/recv.c | 119 + support/sdk/c/blip/driver/radvd-1.0/scanner.c | 2398 ++++++++++++++ support/sdk/c/blip/driver/radvd-1.0/scanner.l | 153 + support/sdk/c/blip/driver/radvd-1.0/send.c | 331 ++ support/sdk/c/blip/driver/radvd-1.0/socket.c | 107 + support/sdk/c/blip/driver/radvd-1.0/stamp-h | 1 + .../sdk/c/blip/driver/radvd-1.0/stamp-h.in | 0 support/sdk/c/blip/driver/radvd-1.0/timer.c | 204 ++ support/sdk/c/blip/driver/radvd-1.0/util.c | 65 + support/sdk/c/blip/driver/radvd-wrapper.c | 162 + support/sdk/c/blip/driver/routing.c | 272 ++ support/sdk/c/blip/driver/routing.h | 71 + support/sdk/c/blip/driver/serial_tun.c | 1108 +++++++ support/sdk/c/blip/driver/tun_dev.c | 211 ++ support/sdk/c/blip/driver/tun_dev.h | 64 + support/sdk/c/blip/driver/tunnel.c | 70 + support/sdk/c/blip/include/6lowpan.h | 240 ++ support/sdk/c/blip/include/IEEE154.h | 49 + support/sdk/c/blip/include/devconf.h | 100 + support/sdk/c/blip/include/in_cksum.h | 45 + support/sdk/c/blip/include/ip.h | 269 ++ support/sdk/c/blip/include/ip_malloc.h | 28 + support/sdk/c/blip/include/lib6lowpan.h | 239 ++ support/sdk/c/blip/lib6lowpan/Makefile | 45 + support/sdk/c/blip/lib6lowpan/in_cksum.c | 222 ++ support/sdk/c/blip/lib6lowpan/ip_malloc.c | 97 + support/sdk/c/blip/lib6lowpan/lib6lowpan.c | 346 ++ .../sdk/c/blip/lib6lowpan/lib6lowpanFrag.c | 205 ++ support/sdk/c/blip/lib6lowpan/lib6lowpanIP.c | 628 ++++ support/sdk/c/blip/lib6lowpan/printpacket.c | 101 + support/sdk/c/blip/libtcp/Makefile | 18 + support/sdk/c/blip/libtcp/circ.c | 219 ++ support/sdk/c/blip/libtcp/circ.h | 26 + support/sdk/c/blip/libtcp/tcplib.c | 562 ++++ support/sdk/c/blip/libtcp/tcplib.h | 162 + support/sdk/c/blip/libtcp/test_circ.c | 78 + support/sdk/c/blip/libtcp/test_server.c | 175 + support/sdk/c/blip/serial_tun.conf | 22 + support/sdk/c/sf/serialsource.c | 2 +- tos/lib/net/blip/ICMP.h | 91 + tos/lib/net/blip/ICMPResponderC.nc | 57 + tos/lib/net/blip/ICMPResponderP.nc | 417 +++ tos/lib/net/blip/IPAddressC.nc | 37 + tos/lib/net/blip/IPAddressP.nc | 84 + tos/lib/net/blip/IPDispatch.h | 272 ++ tos/lib/net/blip/IPDispatchC.nc | 123 + tos/lib/net/blip/IPDispatchP.nc | 1013 ++++++ tos/lib/net/blip/IPRoutingP.nc | 915 ++++++ tos/lib/net/blip/PrintfUART.h | 368 +++ tos/lib/net/blip/TcpC.nc | 17 + tos/lib/net/blip/TcpP.nc | 177 + tos/lib/net/blip/TcpSocketC.nc | 11 + tos/lib/net/blip/UdpC.nc | 12 + tos/lib/net/blip/UdpP.nc | 154 + tos/lib/net/blip/UdpSocketC.nc | 9 + tos/lib/net/blip/interfaces/ICMP.nc | 37 + tos/lib/net/blip/interfaces/ICMPPing.nc | 12 + tos/lib/net/blip/interfaces/IP.nc | 23 + tos/lib/net/blip/interfaces/IPAddress.nc | 35 + tos/lib/net/blip/interfaces/IPRouting.nc | 94 + tos/lib/net/blip/interfaces/Statistics.nc | 36 + tos/lib/net/blip/interfaces/Tcp.nc | 46 + tos/lib/net/blip/interfaces/UDP.nc | 27 + tos/lib/net/blip/nwprog/BootImage.nc | 8 + tos/lib/net/blip/nwprog/Deluge.h | 104 + tos/lib/net/blip/nwprog/DelugePatch.nc | 14 + tos/lib/net/blip/nwprog/DelugePatchC.nc | 60 + tos/lib/net/blip/nwprog/DelugePatchClientC.nc | 40 + tos/lib/net/blip/nwprog/DelugePatchP.nc | 244 ++ tos/lib/net/blip/nwprog/DelugeReadIdent.nc | 20 + tos/lib/net/blip/nwprog/DelugeReadIdentC.nc | 51 + .../net/blip/nwprog/DelugeReadIdentClientC.nc | 40 + tos/lib/net/blip/nwprog/DelugeReadIdentP.nc | 147 + tos/lib/net/blip/nwprog/DelugeVerify.nc | 14 + tos/lib/net/blip/nwprog/DelugeVerifyC.nc | 60 + .../net/blip/nwprog/DelugeVerifyClientC.nc | 40 + tos/lib/net/blip/nwprog/DelugeVerifyP.nc | 161 + tos/lib/net/blip/nwprog/NWProgC.nc | 40 + tos/lib/net/blip/nwprog/NWProgP.nc | 215 ++ tos/lib/net/blip/serial/SerialDevConf.h | 29 + tos/lib/net/blip/serial/SerialDevConfC.nc | 69 + .../blip/serial/SerialPacketInfoDevConfP.nc | 57 + tos/lib/net/blip/shell/FlashShellC.nc | 14 + tos/lib/net/blip/shell/FlashShellP.nc | 46 + .../net/blip/shell/RegisterShellCommand.nc | 4 + tos/lib/net/blip/shell/Shell.h | 8 + tos/lib/net/blip/shell/ShellCommand.nc | 25 + tos/lib/net/blip/shell/ShellCommandC.nc | 14 + tos/lib/net/blip/shell/ShellCommandP.nc | 8 + tos/lib/net/blip/shell/UDPShellC.nc | 47 + tos/lib/net/blip/shell/UDPShellP.nc | 289 ++ tos/lib/net/blip/table.c | 31 + tos/lib/net/blip/table.h | 16 + 147 files changed, 33643 insertions(+), 1 deletion(-) create mode 100644 support/sdk/c/blip/Makefile create mode 100644 support/sdk/c/blip/driver/Makefile create mode 100644 support/sdk/c/blip/driver/config.c create mode 100644 support/sdk/c/blip/driver/config.h create mode 100644 support/sdk/c/blip/driver/hashtable.c create mode 100644 support/sdk/c/blip/driver/hashtable.h create mode 100644 support/sdk/c/blip/driver/hashtable_private.h create mode 100644 support/sdk/c/blip/driver/logging.c create mode 100644 support/sdk/c/blip/driver/logging.h create mode 100644 support/sdk/c/blip/driver/nwstate.c create mode 100644 support/sdk/c/blip/driver/nwstate.h create mode 100644 support/sdk/c/blip/driver/radvd-1.0/CHANGES create mode 100644 support/sdk/c/blip/driver/radvd-1.0/COPYRIGHT create mode 100644 support/sdk/c/blip/driver/radvd-1.0/INTRO.html create mode 100644 support/sdk/c/blip/driver/radvd-1.0/Makefile create mode 100644 support/sdk/c/blip/driver/radvd-1.0/Makefile.am create mode 100644 support/sdk/c/blip/driver/radvd-1.0/Makefile.in create mode 100644 support/sdk/c/blip/driver/radvd-1.0/README create mode 100644 support/sdk/c/blip/driver/radvd-1.0/TODO create mode 100644 support/sdk/c/blip/driver/radvd-1.0/VERSION create mode 100644 support/sdk/c/blip/driver/radvd-1.0/aclocal.m4 create mode 100644 support/sdk/c/blip/driver/radvd-1.0/config.cache create mode 100755 support/sdk/c/blip/driver/radvd-1.0/config.guess create mode 100644 support/sdk/c/blip/driver/radvd-1.0/config.h create mode 100644 support/sdk/c/blip/driver/radvd-1.0/config.h.in create mode 100644 support/sdk/c/blip/driver/radvd-1.0/config.log create mode 100755 support/sdk/c/blip/driver/radvd-1.0/config.status create mode 100755 support/sdk/c/blip/driver/radvd-1.0/config.sub create mode 100755 support/sdk/c/blip/driver/radvd-1.0/configure create mode 100644 support/sdk/c/blip/driver/radvd-1.0/configure.in create mode 100644 support/sdk/c/blip/driver/radvd-1.0/copyright.blurb create mode 100644 support/sdk/c/blip/driver/radvd-1.0/defaults.h create mode 100755 support/sdk/c/blip/driver/radvd-1.0/depcomp create mode 100644 support/sdk/c/blip/driver/radvd-1.0/device-bsd44.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/device-common.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/device-linux.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/gram.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/gram.h create mode 100644 support/sdk/c/blip/driver/radvd-1.0/gram.y create mode 100644 support/sdk/c/blip/driver/radvd-1.0/includes.h create mode 100755 support/sdk/c/blip/driver/radvd-1.0/install-sh create mode 100644 support/sdk/c/blip/driver/radvd-1.0/interface.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/log.c create mode 100755 support/sdk/c/blip/driver/radvd-1.0/missing create mode 100755 support/sdk/c/blip/driver/radvd-1.0/mkinstalldirs create mode 100644 support/sdk/c/blip/driver/radvd-1.0/pathnames.h create mode 100644 support/sdk/c/blip/driver/radvd-1.0/process.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvd.8.man create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvd.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvd.conf.5.man create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvd.conf.example create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvd.h create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvdump.8.man create mode 100644 support/sdk/c/blip/driver/radvd-1.0/radvdump.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/recv.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/scanner.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/scanner.l create mode 100644 support/sdk/c/blip/driver/radvd-1.0/send.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/socket.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/stamp-h create mode 100644 support/sdk/c/blip/driver/radvd-1.0/stamp-h.in create mode 100644 support/sdk/c/blip/driver/radvd-1.0/timer.c create mode 100644 support/sdk/c/blip/driver/radvd-1.0/util.c create mode 100644 support/sdk/c/blip/driver/radvd-wrapper.c create mode 100644 support/sdk/c/blip/driver/routing.c create mode 100644 support/sdk/c/blip/driver/routing.h create mode 100644 support/sdk/c/blip/driver/serial_tun.c create mode 100644 support/sdk/c/blip/driver/tun_dev.c create mode 100644 support/sdk/c/blip/driver/tun_dev.h create mode 100644 support/sdk/c/blip/driver/tunnel.c create mode 100644 support/sdk/c/blip/include/6lowpan.h create mode 100644 support/sdk/c/blip/include/IEEE154.h create mode 100644 support/sdk/c/blip/include/devconf.h create mode 100644 support/sdk/c/blip/include/in_cksum.h create mode 100644 support/sdk/c/blip/include/ip.h create mode 100644 support/sdk/c/blip/include/ip_malloc.h create mode 100644 support/sdk/c/blip/include/lib6lowpan.h create mode 100644 support/sdk/c/blip/lib6lowpan/Makefile create mode 100644 support/sdk/c/blip/lib6lowpan/in_cksum.c create mode 100644 support/sdk/c/blip/lib6lowpan/ip_malloc.c create mode 100644 support/sdk/c/blip/lib6lowpan/lib6lowpan.c create mode 100644 support/sdk/c/blip/lib6lowpan/lib6lowpanFrag.c create mode 100644 support/sdk/c/blip/lib6lowpan/lib6lowpanIP.c create mode 100644 support/sdk/c/blip/lib6lowpan/printpacket.c create mode 100644 support/sdk/c/blip/libtcp/Makefile create mode 100644 support/sdk/c/blip/libtcp/circ.c create mode 100644 support/sdk/c/blip/libtcp/circ.h create mode 100644 support/sdk/c/blip/libtcp/tcplib.c create mode 100644 support/sdk/c/blip/libtcp/tcplib.h create mode 100644 support/sdk/c/blip/libtcp/test_circ.c create mode 100644 support/sdk/c/blip/libtcp/test_server.c create mode 100644 support/sdk/c/blip/serial_tun.conf create mode 100644 tos/lib/net/blip/ICMP.h create mode 100644 tos/lib/net/blip/ICMPResponderC.nc create mode 100644 tos/lib/net/blip/ICMPResponderP.nc create mode 100644 tos/lib/net/blip/IPAddressC.nc create mode 100644 tos/lib/net/blip/IPAddressP.nc create mode 100644 tos/lib/net/blip/IPDispatch.h create mode 100644 tos/lib/net/blip/IPDispatchC.nc create mode 100644 tos/lib/net/blip/IPDispatchP.nc create mode 100644 tos/lib/net/blip/IPRoutingP.nc create mode 100644 tos/lib/net/blip/PrintfUART.h create mode 100644 tos/lib/net/blip/TcpC.nc create mode 100644 tos/lib/net/blip/TcpP.nc create mode 100644 tos/lib/net/blip/TcpSocketC.nc create mode 100644 tos/lib/net/blip/UdpC.nc create mode 100644 tos/lib/net/blip/UdpP.nc create mode 100644 tos/lib/net/blip/UdpSocketC.nc create mode 100644 tos/lib/net/blip/interfaces/ICMP.nc create mode 100644 tos/lib/net/blip/interfaces/ICMPPing.nc create mode 100644 tos/lib/net/blip/interfaces/IP.nc create mode 100644 tos/lib/net/blip/interfaces/IPAddress.nc create mode 100644 tos/lib/net/blip/interfaces/IPRouting.nc create mode 100644 tos/lib/net/blip/interfaces/Statistics.nc create mode 100644 tos/lib/net/blip/interfaces/Tcp.nc create mode 100644 tos/lib/net/blip/interfaces/UDP.nc create mode 100644 tos/lib/net/blip/nwprog/BootImage.nc create mode 100644 tos/lib/net/blip/nwprog/Deluge.h create mode 100644 tos/lib/net/blip/nwprog/DelugePatch.nc create mode 100644 tos/lib/net/blip/nwprog/DelugePatchC.nc create mode 100644 tos/lib/net/blip/nwprog/DelugePatchClientC.nc create mode 100644 tos/lib/net/blip/nwprog/DelugePatchP.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeReadIdent.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeReadIdentC.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeReadIdentClientC.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeReadIdentP.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeVerify.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeVerifyC.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeVerifyClientC.nc create mode 100644 tos/lib/net/blip/nwprog/DelugeVerifyP.nc create mode 100644 tos/lib/net/blip/nwprog/NWProgC.nc create mode 100644 tos/lib/net/blip/nwprog/NWProgP.nc create mode 100644 tos/lib/net/blip/serial/SerialDevConf.h create mode 100644 tos/lib/net/blip/serial/SerialDevConfC.nc create mode 100644 tos/lib/net/blip/serial/SerialPacketInfoDevConfP.nc create mode 100644 tos/lib/net/blip/shell/FlashShellC.nc create mode 100644 tos/lib/net/blip/shell/FlashShellP.nc create mode 100644 tos/lib/net/blip/shell/RegisterShellCommand.nc create mode 100644 tos/lib/net/blip/shell/Shell.h create mode 100644 tos/lib/net/blip/shell/ShellCommand.nc create mode 100644 tos/lib/net/blip/shell/ShellCommandC.nc create mode 100644 tos/lib/net/blip/shell/ShellCommandP.nc create mode 100644 tos/lib/net/blip/shell/UDPShellC.nc create mode 100644 tos/lib/net/blip/shell/UDPShellP.nc create mode 100644 tos/lib/net/blip/table.c create mode 100644 tos/lib/net/blip/table.h diff --git a/support/sdk/c/blip/Makefile b/support/sdk/c/blip/Makefile new file mode 100644 index 00000000..38caf567 --- /dev/null +++ b/support/sdk/c/blip/Makefile @@ -0,0 +1,12 @@ + +all: + cd lib6lowpan && make + cp lib6lowpan/lib6lowpan.a . + + cd driver && make + cp driver/ip-driver . + +clean: + cd lib6lowpan && make clean + cd driver && make clean + rm lib6lowpan.a ip-driver diff --git a/support/sdk/c/blip/driver/Makefile b/support/sdk/c/blip/driver/Makefile new file mode 100644 index 00000000..8c4de957 --- /dev/null +++ b/support/sdk/c/blip/driver/Makefile @@ -0,0 +1,41 @@ + +SOURCES=serial_tun.c tun_dev.c hashtable.c routing.c nwstate.c \ + logging.c config.c radvd-wrapper.c + +COMMON_SRC = radvd/log.c radvd/socket.c radvd/recv.c radvd/util.c radvd/radvd.h \ + radvd/defaults.h radvd/pathnames.h \ + radvd/includes.h +radvd_SOURCES = $(COMMON_SRC) radvd/timer.c radvd/send.c radvd/process.c radvd/interface.c \ + radvd/device.c radvd/device-common.c radvd/gram.h + +LIBS=../lib6lowpan.a ${TOSROOT}/support/sdk/c/sf/libmote.a +TARGET=ip-driver +INCLUDE=../include/ + +ifndef GCC +GCC=gcc +endif + +TFLAGS=-Wall -g -DPC +TFLAGS+=-I${TOSROOT}/support/sdk/c/sf -I$(INCLUDE) -Iradvd/ + + +ifneq ($(filter sim-null,$(MAKECMDGOALS)),) + TFLAGS+=-DSIM +endif + +# CFLAGS+=-DFULL_PATH_INSTALL +all: $(TARGET) + +sim: lib + make $(TARGET) sim-null + +sim-null: + echo Built $(TARGET) for TOSSIM + +$(TARGET): $(SOURCES) $(LIBS) + $(GCC) $(TFLAGS) $(CFLAGS) -o $(TARGET) $(SOURCES) $(radvd_SOURCES) $(LIBS) -lm + +clean: + rm $(TARGET) + diff --git a/support/sdk/c/blip/driver/config.c b/support/sdk/c/blip/driver/config.c new file mode 100644 index 00000000..4cbb4f8f --- /dev/null +++ b/support/sdk/c/blip/driver/config.c @@ -0,0 +1,79 @@ + +#include +#include +#include +#include +#include +#include + +#include "ip.h" +#include "config.h" +#include "logging.h" + +#define BUF_LEN 200 + +void rm_comment (char *buf) { + while (*buf != '#' && *buf != '\0') + buf++; + *buf = '\0'; +} + +void upd_start(char **buf) { + while ((**buf == ' ' || **buf == '\t' || **buf == '\n') && **buf != '\0') + *buf = (*buf) + 1; +} + +int config_parse(const char *file, struct config *c) { + char *buf, real_buf[BUF_LEN], arg[BUF_LEN]; + FILE *fp = fopen(file, "r"); + int gotargs = 0; + if (fp == NULL) return 1; + + while (fgets(real_buf, BUF_LEN, fp) != NULL) { + buf = real_buf; + rm_comment(buf); + upd_start(&buf); + if (sscanf(buf, "addr %s\n", arg) > 0) { + inet_pton6(arg, &c->router_addr); + gotargs ++; + } else if (sscanf(buf, "proxy %s\n", c->proxy_dev) > 0) { + gotargs ++; + } else if (sscanf(buf, "channel %i\n", &c->channel) > 0) { + if (c->channel < 11 || c->channel > 26) { + fatal("Invalid channel specified in '%s'\n", file); + exit(1); + } + gotargs ++; + } else if (sscanf(buf, "log %s\n", arg) > 0) { + int i; + for (i = 0; i < 5; i++) { + if (strncmp(log_names[i], arg, strlen(log_names[i])) == 0) { + info("Read log level: %s\n", arg); + log_setlevel(i); + break; + } + } + } else if (*buf != '\0') { + // anything else indicates that there's invalid input. + return 1; + } + } + fclose(fp); + + if (gotargs != 3) return 1; + + info("Read config from '%s'\n", file); + info("\tProxying neighbor advertisements to %s\n", c->proxy_dev); + info("\tUsing channel %i\n", c->channel); + return 0; +} + +int config_print(struct config *c) { + char buf[64]; + printf ("configuration:\n"); + inet_ntop(AF_INET6, &c->router_addr, buf, 64); + printf (" router address: %s\n", buf); + printf(" proxy dev: %s\n", c->proxy_dev); + printf(" channel: %i\n", c->channel); + return 0; +} diff --git a/support/sdk/c/blip/driver/config.h b/support/sdk/c/blip/driver/config.h new file mode 100644 index 00000000..0a79dd36 --- /dev/null +++ b/support/sdk/c/blip/driver/config.h @@ -0,0 +1,16 @@ +#ifndef _CONFIG_H +#define _CONFIG_H + +#include + +struct config { + struct in6_addr router_addr; + char proxy_dev[IFNAMSIZ]; + int channel; +}; + + +int config_parse(const char *file, struct config *c); +int config_print(struct config *c); + +#endif diff --git a/support/sdk/c/blip/driver/hashtable.c b/support/sdk/c/blip/driver/hashtable.c new file mode 100644 index 00000000..763357ed --- /dev/null +++ b/support/sdk/c/blip/driver/hashtable.c @@ -0,0 +1,274 @@ +/* Copyright (C) 2004 Christopher Clark */ + +#include "hashtable.h" +#include "hashtable_private.h" +#include +#include +#include +#include + +/* +Credit for primes table: Aaron Krowne + http://br.endernet.org/~akrowne/ + http://planetmath.org/encyclopedia/GoodHashTablePrimes.html +*/ +static const unsigned int primes[] = { +53, 97, 193, 389, +769, 1543, 3079, 6151, +12289, 24593, 49157, 98317, +196613, 393241, 786433, 1572869, +3145739, 6291469, 12582917, 25165843, +50331653, 100663319, 201326611, 402653189, +805306457, 1610612741 +}; +const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]); +const float max_load_factor = 0.65; + +/*****************************************************************************/ +struct hashtable * +create_hashtable(unsigned int minsize, + unsigned int (*hashf) (void*), + int (*eqf) (void*,void*)) +{ + struct hashtable *h; + unsigned int pindex, size = primes[0]; + /* Check requested hashtable isn't too large */ + if (minsize > (1u << 30)) return NULL; + /* Enforce size as prime */ + for (pindex=0; pindex < prime_table_length; pindex++) { + if (primes[pindex] > minsize) { size = primes[pindex]; break; } + } + h = (struct hashtable *)malloc(sizeof(struct hashtable)); + if (NULL == h) return NULL; /*oom*/ + h->table = (struct entry **)malloc(sizeof(struct entry*) * size); + if (NULL == h->table) { free(h); return NULL; } /*oom*/ + memset(h->table, 0, size * sizeof(struct entry *)); + h->tablelength = size; + h->primeindex = pindex; + h->entrycount = 0; + h->hashfn = hashf; + h->eqfn = eqf; + h->loadlimit = (unsigned int) ceil(size * max_load_factor); + return h; +} + +/*****************************************************************************/ +unsigned int +hash(struct hashtable *h, void *k) +{ + /* Aim to protect against poor hash functions by adding logic here + * - logic taken from java 1.4 hashtable source */ + unsigned int i = h->hashfn(k); + i += ~(i << 9); + i ^= ((i >> 14) | (i << 18)); /* >>> */ + i += (i << 4); + i ^= ((i >> 10) | (i << 22)); /* >>> */ + return i; +} + +/*****************************************************************************/ +static int +hashtable_expand(struct hashtable *h) +{ + /* Double the size of the table to accomodate more entries */ + struct entry **newtable; + struct entry *e; + struct entry **pE; + unsigned int newsize, i, index; + /* Check we're not hitting max capacity */ + if (h->primeindex == (prime_table_length - 1)) return 0; + newsize = primes[++(h->primeindex)]; + + newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize); + if (NULL != newtable) + { + memset(newtable, 0, newsize * sizeof(struct entry *)); + /* This algorithm is not 'stable'. ie. it reverses the list + * when it transfers entries between the tables */ + for (i = 0; i < h->tablelength; i++) { + while (NULL != (e = h->table[i])) { + h->table[i] = e->next; + index = indexFor(newsize,e->h); + e->next = newtable[index]; + newtable[index] = e; + } + } + free(h->table); + h->table = newtable; + } + /* Plan B: realloc instead */ + else + { + newtable = (struct entry **) + realloc(h->table, newsize * sizeof(struct entry *)); + if (NULL == newtable) { (h->primeindex)--; return 0; } + h->table = newtable; + memset(newtable[h->tablelength], 0, newsize - h->tablelength); + for (i = 0; i < h->tablelength; i++) { + for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { + index = indexFor(newsize,e->h); + if (index == i) + { + pE = &(e->next); + } + else + { + *pE = e->next; + e->next = newtable[index]; + newtable[index] = e; + } + } + } + } + h->tablelength = newsize; + h->loadlimit = (unsigned int) ceil(newsize * max_load_factor); + return -1; +} + +/*****************************************************************************/ +unsigned int +hashtable_count(struct hashtable *h) +{ + return h->entrycount; +} + +/*****************************************************************************/ +int +hashtable_insert(struct hashtable *h, void *k, void *v) +{ + /* This method allows duplicate keys - but they shouldn't be used */ + unsigned int index; + struct entry *e; + if (++(h->entrycount) > h->loadlimit) + { + /* Ignore the return value. If expand fails, we should + * still try cramming just this value into the existing table + * -- we may not have memory for a larger table, but one more + * element may be ok. Next time we insert, we'll try expanding again.*/ + hashtable_expand(h); + } + e = (struct entry *)malloc(sizeof(struct entry)); + if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ + e->h = hash(h,k); + index = indexFor(h->tablelength,e->h); + e->k = k; + e->v = v; + e->next = h->table[index]; + h->table[index] = e; + return -1; +} + +/*****************************************************************************/ +void * /* returns value associated with key */ +hashtable_search(struct hashtable *h, void *k) +{ + struct entry *e; + unsigned int hashvalue, index; + hashvalue = hash(h,k); + index = indexFor(h->tablelength,hashvalue); + e = h->table[index]; + while (NULL != e) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; + e = e->next; + } + return NULL; +} + +/*****************************************************************************/ +void * /* returns value associated with key */ +hashtable_remove(struct hashtable *h, void *k) +{ + /* TODO: consider compacting the table when the load factor drops enough, + * or provide a 'compact' method. */ + + struct entry *e; + struct entry **pE; + void *v; + unsigned int hashvalue, index; + + hashvalue = hash(h,k); + index = indexFor(h->tablelength,hash(h,k)); + pE = &(h->table[index]); + e = *pE; + while (NULL != e) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) + { + *pE = e->next; + h->entrycount--; + v = e->v; + freekey(e->k); + free(e); + return v; + } + pE = &(e->next); + e = e->next; + } + return NULL; +} + +/*****************************************************************************/ +/* destroy */ +void +hashtable_destroy(struct hashtable *h, int free_values) +{ + unsigned int i; + struct entry *e, *f; + struct entry **table = h->table; + if (free_values) + { + for (i = 0; i < h->tablelength; i++) + { + e = table[i]; + while (NULL != e) + { f = e; e = e->next; freekey(f->k); free(f->v); free(f); } + } + } + else + { + for (i = 0; i < h->tablelength; i++) + { + e = table[i]; + while (NULL != e) + { f = e; e = e->next; freekey(f->k); free(f); } + } + } + free(h->table); + free(h); +} + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER + * 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. +*/ diff --git a/support/sdk/c/blip/driver/hashtable.h b/support/sdk/c/blip/driver/hashtable.h new file mode 100644 index 00000000..b90781ab --- /dev/null +++ b/support/sdk/c/blip/driver/hashtable.h @@ -0,0 +1,199 @@ +/* Copyright (C) 2002 Christopher Clark */ + +#ifndef __HASHTABLE_CWC22_H__ +#define __HASHTABLE_CWC22_H__ + +struct hashtable; + +/* Example of use: + * + * struct hashtable *h; + * struct some_key *k; + * struct some_value *v; + * + * static unsigned int hash_from_key_fn( void *k ); + * static int keys_equal_fn ( void *key1, void *key2 ); + * + * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); + * k = (struct some_key *) malloc(sizeof(struct some_key)); + * v = (struct some_value *) malloc(sizeof(struct some_value)); + * + * (initialise k and v to suitable values) + * + * if (! hashtable_insert(h,k,v) ) + * { exit(-1); } + * + * if (NULL == (found = hashtable_search(h,k) )) + * { printf("not found!"); } + * + * if (NULL == (found = hashtable_remove(h,k) )) + * { printf("Not found\n"); } + * + */ + +/* Macros may be used to define type-safe(r) hashtable access functions, with + * methods specialized to take known key and value types as parameters. + * + * Example: + * + * Insert this at the start of your file: + * + * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); + * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); + * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); + * + * This defines the functions 'insert_some', 'search_some' and 'remove_some'. + * These operate just like hashtable_insert etc., with the same parameters, + * but their function signatures have 'struct some_key *' rather than + * 'void *', and hence can generate compile time errors if your program is + * supplying incorrect data as a key (and similarly for value). + * + * Note that the hash and key equality functions passed to create_hashtable + * still take 'void *' parameters instead of 'some key *'. This shouldn't be + * a difficult issue as they're only defined and passed once, and the other + * functions will ensure that only valid keys are supplied to them. + * + * The cost for this checking is increased code size and runtime overhead + * - if performance is important, it may be worth switching back to the + * unsafe methods once your program has been debugged with the safe methods. + * This just requires switching to some simple alternative defines - eg: + * #define insert_some hashtable_insert + * + */ + +/***************************************************************************** + * create_hashtable + + * @name create_hashtable + * @param minsize minimum initial size of hashtable + * @param hashfunction function for hashing keys + * @param key_eq_fn function for determining key equality + * @return newly created hashtable or NULL on failure + */ + +struct hashtable * +create_hashtable(unsigned int minsize, + unsigned int (*hashfunction) (void*), + int (*key_eq_fn) (void*,void*)); + +/***************************************************************************** + * hashtable_insert + + * @name hashtable_insert + * @param h the hashtable to insert into + * @param k the key - hashtable claims ownership and will free on removal + * @param v the value - does not claim ownership + * @return non-zero for successful insertion + * + * This function will cause the table to expand if the insertion would take + * the ratio of entries to table size over the maximum load factor. + * + * This function does not check for repeated insertions with a duplicate key. + * The value returned when using a duplicate key is undefined -- when + * the hashtable changes size, the order of retrieval of duplicate key + * entries is reversed. + * If in doubt, remove before insert. + */ + +int +hashtable_insert(struct hashtable *h, void *k, void *v); + +#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ +int fnname (struct hashtable *h, keytype *k, valuetype *v) \ +{ \ + return hashtable_insert(h,k,v); \ +} + +/***************************************************************************** + * hashtable_search + + * @name hashtable_search + * @param h the hashtable to search + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void * +hashtable_search(struct hashtable *h, void *k); + +#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ +valuetype * fnname (struct hashtable *h, keytype *k) \ +{ \ + return (valuetype *) (hashtable_search(h,k)); \ +} + +/***************************************************************************** + * hashtable_remove + + * @name hashtable_remove + * @param h the hashtable to remove the item from + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void * /* returns value */ +hashtable_remove(struct hashtable *h, void *k); + +#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ +valuetype * fnname (struct hashtable *h, keytype *k) \ +{ \ + return (valuetype *) (hashtable_remove(h,k)); \ +} + + +/***************************************************************************** + * hashtable_count + + * @name hashtable_count + * @param h the hashtable + * @return the number of items stored in the hashtable + */ +unsigned int +hashtable_count(struct hashtable *h); + + +/***************************************************************************** + * hashtable_destroy + + * @name hashtable_destroy + * @param h the hashtable + * @param free_values whether to call 'free' on the remaining values + */ + +void +hashtable_destroy(struct hashtable *h, int free_values); + +#endif /* __HASHTABLE_CWC22_H__ */ + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER + * 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. +*/ diff --git a/support/sdk/c/blip/driver/hashtable_private.h b/support/sdk/c/blip/driver/hashtable_private.h new file mode 100644 index 00000000..f6227014 --- /dev/null +++ b/support/sdk/c/blip/driver/hashtable_private.h @@ -0,0 +1,106 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* Copyright (C) 2002, 2004 Christopher Clark */ + +#ifndef __HASHTABLE_PRIVATE_CWC22_H__ +#define __HASHTABLE_PRIVATE_CWC22_H__ + +#include "hashtable.h" + +/*****************************************************************************/ +struct entry +{ + void *k, *v; + unsigned int h; + struct entry *next; +}; + +struct hashtable { + unsigned int tablelength; + struct entry **table; + unsigned int entrycount; + unsigned int loadlimit; + unsigned int primeindex; + unsigned int (*hashfn) (void *k); + int (*eqfn) (void *k1, void *k2); +}; + +/*****************************************************************************/ +unsigned int +hash(struct hashtable *h, void *k); + +/*****************************************************************************/ +/* indexFor */ +static inline unsigned int +indexFor(unsigned int tablelength, unsigned int hashvalue) { + return (hashvalue % tablelength); +}; + +/* Only works if tablelength == 2^N */ +/*static inline unsigned int +indexFor(unsigned int tablelength, unsigned int hashvalue) +{ + return (hashvalue & (tablelength - 1u)); +} +*/ + +/*****************************************************************************/ +#define freekey(X) free(X) +/*define freekey(X) ; */ + + +/*****************************************************************************/ + +#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER + * 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. +*/ diff --git a/support/sdk/c/blip/driver/logging.c b/support/sdk/c/blip/driver/logging.c new file mode 100644 index 00000000..4df083db --- /dev/null +++ b/support/sdk/c/blip/driver/logging.c @@ -0,0 +1,96 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#include +#include +#include +#include +#include "logging.h" + + +loglevel_t log_level; +FILE *log_dest; + + +char *log_names[5] = {"DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL"}; + +static void timestamp(){ + struct timeval tv; + struct timezone tz; + struct tm *ltime; + gettimeofday(&tv, &tz); + ltime = localtime(&tv.tv_sec); + fprintf(log_dest, "%02d:%02d:%02d.%03d: ", + ltime->tm_hour, ltime->tm_min, ltime->tm_sec, (int)tv.tv_usec); +} + +loglevel_t log_setlevel(loglevel_t l) { + loglevel_t old_lvl = log_level; + log_level = l; + return old_lvl; +} + +loglevel_t log_getlevel() { + return log_level; +} + +void log_init() { + log_level = LOGLVL_INFO; + log_dest = stderr; +} + +void log_log (loglevel_t level, const char *fmt, ...) { + if (log_level > level) return; + va_list ap; + va_start(ap, fmt); + timestamp(); + fprintf(log_dest, "%s: ", log_names[level]); + vfprintf(log_dest, fmt, ap); + va_end(ap); +} + +void log_clear (loglevel_t level, const char *fmt, ...) { + if (log_level > level) return; + va_list ap; + va_start(ap, fmt); + vfprintf(log_dest, fmt, ap); + va_end(ap); +} + +/* print char* in hex format */ +void log_dump_serial_packet(unsigned char *packet, const int len) { + int i; + if (log_level > LOGLVL_DEBUG) return; + + printf("len: %d\n", len); + if (!packet) + return; + for (i = 0; i < len; i++) { + printf("%02x ", packet[i]); + //printf("%02x(%c) ", packet[i], packet[i]); + //printf("%c", packet[i]); + } + putchar('\n'); +} diff --git a/support/sdk/c/blip/driver/logging.h b/support/sdk/c/blip/driver/logging.h new file mode 100644 index 00000000..c0f98376 --- /dev/null +++ b/support/sdk/c/blip/driver/logging.h @@ -0,0 +1,64 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef LOGGING_H_ +#define LOGGING_H_ + +#include + +// SDH : log levels defined here +// also edit the log names in logging.h +typedef enum { + LOGLVL_DEBUG = 0, + LOGLVL_INFO = 1, + LOGLVL_WARN = 2, + LOGLVL_ERROR = 3, + LOGLVL_FATAL = 4, +} loglevel_t; + +extern char *log_names[5]; +extern loglevel_t log_level; +extern FILE *log_dest; + +void log_init(); + +loglevel_t log_setlevel(loglevel_t l); +loglevel_t log_getlevel(); + +void log_log (loglevel_t level, const char *fmt, ...); +void log_clear (loglevel_t level, const char *fmt, ...); + +#define debug(fmt, args...) \ + log_log(LOGLVL_DEBUG, fmt, ## args) +#define info(fmt, args...) \ + log_log(LOGLVL_INFO, fmt, ## args) +#define warn(fmt, args...) \ + log_log(LOGLVL_WARN, fmt, ## args) +#define error(fmt, args...) \ + log_log(LOGLVL_ERROR, fmt, ## args) +#define fatal(fmt, args...) \ + log_log(LOGLVL_FATAL, fmt, ## args) + +#define log_fprintf(X, FMT, ...) ; + +void log_dump_serial_packet(unsigned char *packet, const int len); + +#endif diff --git a/support/sdk/c/blip/driver/nwstate.c b/support/sdk/c/blip/driver/nwstate.c new file mode 100644 index 00000000..96575401 --- /dev/null +++ b/support/sdk/c/blip/driver/nwstate.c @@ -0,0 +1,503 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include +#include +#include +#include +#include "nwstate.h" +#include "hashtable.h" +#include "logging.h" +#include "lib6lowpan.h" +#include "routing.h" + +struct hashtable *links; +struct hashtable *routers; + +router_t *router_list = NULL; +int routes_out_of_date = 1; + +extern struct in6_addr __my_address; + + +void compute_routes(node_id_t v1); +// +// general boilerplate +// + +static unsigned int hash_link(void *k) { + link_key_t *l = (link_key_t *)k; + if (l->r1 > l->r2) + return (l->r1 | (l->r2 << 16)); + else + return (l->r2 | (l->r1 << 16)); +} +static int link_equal(void *k1, void *k2) { + link_key_t *l1 = (link_key_t *)k1; + link_key_t *l2 = (link_key_t *)k2; + return ((l1->r1 == l2->r1 && l1->r2 == l2->r2) || + (l1->r1 == l2->r2 && l1->r2 == l2->r1)); +} + +static unsigned int hash_router(void *k) { + return *((router_key_t *)k); +} + +static int router_equal(void *k1, void *k2) { + return ((router_t *)k1)->id == ((router_t *)k2)->id; +} + +int do_print = 0; +int do_routes = 0; +int printCount = 0; + +int nw_print_dotfile(char *filename) { + router_t *r; + link_t *e; + FILE *fp = fopen (filename, "w"); + if (fp == NULL) return -1; + info("writing topology to '%s'\n", filename); + printCount ++; + fprintf(fp, "digraph Network {\n"); + + for (r = router_list; r != NULL; r = r->next) { + for (e = r->links; e != NULL; e = e->next1) { + if (e->pc < printCount) { + fprintf(fp, " \"0x%x\" -> \"0x%x\" [label=\"%f\"]\n", e->n1->id, e->n2->id, e->qual); + e->pc = printCount; + } + } + for (e = r->links; e != NULL; e = e->next2) { + if (e->pc < printCount) { + fprintf(fp, " \"0x%x\" -> \"0x%x\" [label=\"%f\"]\n", e->n1->id, e->n2->id, e->qual); + e->pc = printCount; + } + } + } + + fprintf(fp, "}\n"); + fclose(fp); + return 0; +} + + +void nw_print_routes() { + router_t *r,*s; + for (r = router_list; r != NULL; r = r->next) { + log_clear(LOGLVL_INFO, " 0x%x: ", r->id); + for (s = r->sp.prev; s != NULL; s = s->sp.prev) { + log_clear(LOGLVL_INFO, "0x%x ", s->id); + } + log_clear(LOGLVL_INFO, "\n"); + } +} + +void nw_test_routes() { + node_id_t dest = ntohs(__my_address.s6_addr16[7]); + debug("nwstate: computing new routes (root: 0x%x)\n", ntohs(__my_address.s6_addr16[7])); + compute_routes(dest); +} + +void nw_print_links() { + router_t *r; + link_t *l; + for (r = router_list; r != NULL; r = r->next) { + log_clear(LOGLVL_INFO, " 0x%x: dist: %.1f\n", r->id, r->sp.dist); + for (l = r->links; l != NULL; l = (r == l->n1) ? l->next1 : l->next2) { + if (r == l->n1) { + log_clear(LOGLVL_INFO, " --> 0x%x [%.1f]\n", l->n2->id, l->qual); + } + } + log_clear(LOGLVL_INFO, "\n"); + } +} + +// +// helpers +// + +router_t *get_insert_router(node_id_t rid) { + router_key_t *key; + router_t *ret = hashtable_search(routers, &rid); + if (ret == NULL) { + key = (router_key_t *)malloc(sizeof(router_key_t)); + ret = (router_t *)malloc(sizeof(router_t)); + + ret->id = rid; + ret->links = NULL; + ret->next = router_list; + + ret->reports = 0; + + ret->sp.dist = FLT_MAX; + ret->sp.prev = NULL; + + router_list = ret; + + *key = rid; + hashtable_insert(routers, key, ret); + routing_add_table_entry(rid); + } + return ret; +} + + +// +// network state API impl. +// + +int nw_init() { + links = create_hashtable(16, hash_link, link_equal); + routers = create_hashtable(16, hash_router, router_equal); + return 0; +} + +/* + * Adds an observation of the link (v1, v2) to the database. This + * implicitly adds the reverse edge for now, as well. + */ +int nw_add_incr_edge(node_id_t v1, struct topology_entry *te) { + link_key_t key; + link_t *link_str; + node_id_t v2 = ntoh16(te->hwaddr); + key.r1 = v1; + key.r2 = v2; + + link_str = hashtable_search(links, &key); + if (link_str == NULL) { + link_key_t *new_key = (link_key_t *)malloc(sizeof(link_key_t)); + router_t *r1 = get_insert_router(v1); + router_t *r2 = get_insert_router(v2); + link_str = (link_t *)malloc(sizeof(link_t)); + + new_key->r1 = v1; + new_key->r2 = v2; + + // point the links at their routers + link_str->n1 = r1; + link_str->n2 = r2; + // add this link to the head of the linked list of edges each router maintains + link_str->next1 = r1->links; + link_str->next2 = r2->links; + + link_str->n1_reportcount = 0; + link_str->n2_reportcount = 0; + + r1->links = link_str; + r2->links = link_str; + + link_str->pc = 0; + + + hashtable_insert(links, new_key, link_str); + + } + + link_str->marked = 1; + link_str->qual = ((float)(te->etx)) / 10.0; + link_str->conf = te->conf; + debug("nw_add_incr_edge [%i -> %i]: qual: %f conf: %i\n", + v1, v2, link_str->qual, link_str->conf); + (v1 == link_str->n1->id) ? link_str->n1_reportcount++ : + link_str->n2_reportcount++; + + return 0; +} + +/* + * Returns a route from v1 to v2 as a linked list. + * + * quadratic-time dijkstra implementation: no priority queue + */ +/* + * relaxes the neighbors of cur + */ +float getMetric(link_t *l) { + return l->qual; + //return ((float)l->qual / 3000.0) + 1.0; + //return (10. / (float)l->nobs); +} +void update_neighbors(router_t *cur) { + link_t *l; + router_t *otherguy; + // clunky iterator + for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) { + otherguy = (cur == l->n1) ? l->n2 : l->n1; + + if (cur->sp.dist + getMetric(l) < otherguy->sp.dist) { + otherguy->sp.dist = cur->sp.dist + getMetric(l); + otherguy->sp.prev = cur; + } + } +} + +router_t *extract_min(router_t **list) { + router_t *r, *prev = NULL, *min = NULL, *prev_min = NULL; + float min_dist = FLT_MAX; + for (r = *list; r != NULL; r = r->sp.setptr) { + if (r->sp.dist < min_dist) { + min_dist = r->sp.dist; + min = r; + prev_min = prev; + } + prev = r; + } + + if (min == NULL) { + // it might be the case that not everyone is reachable. In that + // case, we'll just leave them unconnected. + *list = NULL; + } else if (prev_min == NULL) { + // the first element was the best, set list is pointed at the second element + *list = (*list)->sp.setptr; + } else { + // otherwise just remove the min element from the list + prev_min->sp.setptr = min->sp.setptr; + } + + return min; +} + +void age_routers() { + router_t *r; + int max_reports = 0; + for (r = router_list; r != NULL; r = r->next) { + if (r->reports > max_reports) { + max_reports = r->reports; + } + // debug("nwstate: node: %i reports: %i\n", r->id, r->reports); + } + if (max_reports == 4) { + debug("age_routers: max: %i\n", max_reports); + for (r = router_list; r != NULL; r = r->next) { + if (r->reports > 0) { + r->reports = 0; + } else { + // debug("nwstate: removing router 0x%x due to age %i\n", r->id, r->reports); + // nw_inval_node(r->id); + r->reports = 0; + } + } + } +} + +/* + * compute all destinations shortest path to node v1 + */ +void compute_routes(node_id_t v1) { + router_t *r, *cur = NULL, *not_visited = NULL; + routes_out_of_date = 0; + + for (r = router_list; r != NULL; r = r->next) { + r->sp.dist = FLT_MAX; + r->sp.prev = NULL; + if (r->id == v1) { + cur = r; + } else { + r->sp.setptr = not_visited; + not_visited = r; + } + } + if (cur == NULL) return; + cur->sp.dist = 0; + + while (not_visited != NULL) { + update_neighbors(cur); + cur = extract_min (¬_visited); + } + // all the prev and distance pointers are now valid. +} + +path_t *nw_get_route(node_id_t v1, node_id_t v2) { + router_t *r, *from, *to; + path_t *ret = NULL, *new; + + from = hashtable_search(routers, &v1); + to = hashtable_search(routers, &v2); + + if (from == NULL || to == NULL) return NULL; + + if (to->sp.prev == NULL || from->sp.prev != NULL || routes_out_of_date) { + // the current set of shortest paths do not end at node v2, if we + // haven't computed any paths yet, we will do that when the next + // test fails. + debug("nw_get_route: computing new routes\n"); + compute_routes(v1); + } + // now the routes should be valid; + for (r = to; r != NULL; r = r->sp.prev) { + // this both constructs the return value and reverses the path, + // since the prev pointers will give you the reverse path. + + // in the future routes will probably be cached. + + if (r != from) { + new = (path_t *)malloc(sizeof(path_t)); + new->node = r->id; + new->next = ret; + new->length = (ret == NULL) ? 1 : ret->length + 1; + ret = new; + } + } + return ret; +} + +void nw_free_path(path_t *r) { + path_t *next; + while (r != NULL) { + next = r->next; + free(r); + r = next; + } +} + +// remove link from the linked list of links owned by router. +void remove_link(router_t *r, link_t *link) { + link_t *l; + link_t **prev = &r->links; + for (l = r->links; l != NULL; l = (r== l->n1) ? l->next1 : l->next2) { + if (l == link) { + *prev = (r == l->n1) ? l->next1 : l->next2; + return; + } + prev = (r == l->n1) ? &l->next1 : &l->next2; + } + warn("link_remove: link not removed (inconsistent state)?\n"); +} + +void nw_inval_node(node_id_t v) { + router_t *cur; + link_t *l, *next; + router_t *otherguy; + link_key_t key; + routes_out_of_date = 1; + + cur = hashtable_search(routers, &v); + if (cur == NULL) return; + + // remove the links from the linked lists of the other guys, + // and delete them from the hashtable + for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) { + otherguy = (cur == l->n1) ? l->n2 : l->n1; + key.r1 = v; + key.r2 = otherguy->id; + remove_link(otherguy, l); + hashtable_remove(links, &key); + } + + // free the link structures + l = cur->links; + while (l != NULL) { + next = (cur == l->n1) ? l->next1 : l->next2; + free(l); + l = next; + } + cur->links = NULL; + + // force a route recomputation when this node is used. + cur->sp.dist = FLT_MAX; + cur->sp.prev = NULL; +} + +/* + * called before adding the topology from a node + * unsets the marked bit * in the link structures to show that they + * have not been reported + */ +void nw_unmark_links(node_id_t v) { + router_t *cur; + link_t *l; + routes_out_of_date = 1; + + cur = hashtable_search(routers, &v); + if (cur == NULL) return; + + for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) { + l->marked = 0; + } + +} + +void nw_report_node(node_id_t v) { + router_t *cur; + + cur = hashtable_search(routers, &v); + if (cur == NULL) return; + + cur->reports++; +} + +/* + * called after processing a topology report + * + * removes links which were not contained by this topology report, and + * which were not reported by the router on the other end. + * + */ +void nw_clear_unmarked(node_id_t v) { + router_t *cur; + link_key_t key; + link_t *l, *next; + key.r1 = v; + + cur = hashtable_search(routers, &v); + if (cur == NULL) return; + + for (l = cur->links; l != NULL; l = (cur == l->n1) ? l->next1 : l->next2) { + if (l->marked == 0) { + // it's not marked, so it wasn't contained in the topology report + if (((cur == l->n1) ? l->n2_reportcount : l->n1_reportcount) == 0) { + // it has never been reported by the router on the other end, so we + // remove the link from the topology data + router_t *otherguy = (cur == l->n1) ? l->n2 : l->n1; + key.r2 = otherguy->id; + remove_link(otherguy, l); + hashtable_remove(links, &key); + //info("removing unmarked link, 0x%x -> 0x%x\n", cur->id, otherguy->id); + // remove it from our own linked list + } else { + // it has been reported by the other size, so we just set its + // observation count to zero. + if (cur == l->n1) l->n1_reportcount = 0 ; + else l->n2_reportcount = 0; + l->marked = 1; + // router_t *otherguy = (cur == l->n1) ? l->n2 : l->n1; + //debug("unseting obs count on 0x%x -> 0x%x\n", cur->id, otherguy->id); + } + } + } + + // free the links no longer in use + l = cur->links; + while (l != NULL) { + next = (cur == l->n1) ? l->next1 : l->next2; + // if its still umarked, we mean to remove it from the graph + if (l->marked == 0) { + remove_link(cur, l); + free(l); + } + l = next; + } + + + age_routers(); +} diff --git a/support/sdk/c/blip/driver/nwstate.h b/support/sdk/c/blip/driver/nwstate.h new file mode 100644 index 00000000..7374047d --- /dev/null +++ b/support/sdk/c/blip/driver/nwstate.h @@ -0,0 +1,112 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef NWSTATE_H +#define NWSTATE_H + +#include <6lowpan.h> +/* + * Defines a programatic representation of the link state of the network. + * Also tracks observable statistics about the links present. + * + */ + +typedef uint16_t node_id_t; + +struct route_path { + uint16_t len; + hw_addr_t path[0]; +}; + +typedef struct { + node_id_t r1; + node_id_t r2; +} link_key_t; + +struct router; +struct link; + +typedef struct link { + struct router *n1; + struct router *n2; + + struct link *next1; + struct link *next2; + + int n1_reportcount; + int n2_reportcount; + + int marked; + + float qual; + int conf; + int pc; +} link_t; + +typedef node_id_t router_key_t; + +typedef enum bool { + FALSE, + TRUE, +} bool_t; + +typedef struct router { + node_id_t id; + link_t *links; + struct router *next; + int reports; + + // fields for shortest path + // computation + struct { + // the current estimate of the + // distance to the source + float dist; + // the current prev pointer + struct router *prev; + // used for maintaining a list of + // vertices we have not yet visited + struct router *setptr; + } sp; +} router_t; + +typedef struct path { + node_id_t node; + int length; + struct path *next; +} path_t; + +int nw_init(); +int nw_add_incr_edge(node_id_t v1, struct topology_entry *v2); +void nw_report_node(node_id_t v); +path_t *nw_get_route(node_id_t v1, node_id_t v2); +void nw_free_path(path_t *path); +void nw_inval_node(node_id_t v); + +void nw_unmark_links(node_id_t v); +void nw_clear_unmarked(node_id_t v); + +int nw_print_dotfile(char *filename); +void nw_print_routes(); +void nw_print_links(); +void nw_test_routes(); + +#endif diff --git a/support/sdk/c/blip/driver/radvd-1.0/CHANGES b/support/sdk/c/blip/driver/radvd-1.0/CHANGES new file mode 100644 index 00000000..2165e2e7 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/CHANGES @@ -0,0 +1,346 @@ +$Id$ + +11/01/2006 Release 1.0. + +10/09/2006 Perform a static/dynamic code audit; plug some minor + bugs (see CVS changelogs for more information) and + perform minor clean-up. + +08/07/2006 Implement MAX_INITIAL_RTR_ADVERT_INTERVAL handling, + patch from Yoshifuji Hideaki / USAGI. + +05/23/2006 Unblock SIGALRM signals at startup. Some scripts/programs + seem to run radvd from ALRM-blocked context which breaks + the timers. + +05/23/2006 Redefined IgnoreIfMissing: by default, radvd will now + try to reinitialize failed interfaces automatically. + IgnoreIfMissing is still needed if radvd is started when the + interface isn't up, and it also quenches some messages + relating to missing interfaces. + +03/29/2006 Implement RDNSS draft, using non-allocated + IANA ND type value 25, by Lauréline Provost, + Mickaël Guérin, Adrien Clerc, Gaetan Eleouet, + Bahattin Demirplak, Lionel Guilmin (at the + ENSEEIHT, Toulouse) + +03/06/2006 Fix the default STDERR+syslog logging methods, so + we don't try to unnecessarily log to STDERR after + forking. + +01/18/2006 radvd-0.9.1 did not initialize AdvDefaultLifetime (etc.) + appropriately, unbreak the "clean-up". + +01/13/2006 Release 0.9.1. + +12/30/2005 Great cleanup of signed/unsigned values, add + -Wall and a number of other warnings to CFLAGS + by default. Do not allow signed values for + HomeAgentPreference anymore. + +12/30/2005 Fix a couple of IPv6 Ready Logo Phase-2 IPv6 Core + Protocols Self Test issues, patches from Yoshifuji + Hideaki / USAGI. + +11/13/2005 Create a short FAQ in README file. + +10/28/2005 Get interface MTU automatically, so that you can + use jumboframes and advertise MTU >1500. + +10/19/2005 Release 0.9. + +10/18/2005 Transfer sole maintainership of radvd to Pekka Savola. + +10/18/2005 Make the radvd.conf syntax dump default + in radvdump and remove the previous default to + reduce code duplication. + +09/28/2005 Add NEMO Basic support (RFC3961) and fix default + HomeAgentLifetime, from Ville Nuorvala. + +08/18/2005 Implement more robust timer handler, especially + because some Linux kernels don't seem to behave + all that well; see http://lkml.org/lkml/2005/4/29/163. + Based on extensive testing & reports by + Tomasz Grobelny. NB: the bug report was caused by + a bad timer patch in PLD's kernel package, and this + should not occur often with standard kernels. + +07/24/2005 Implement a new logging method "stderr_syslog" which is + now also the default. Everything is logged on syslog, + while the most important messages (i.e., start-up failures) + are also logged on stderr. + +07/08/2005 Release 0.8. + +07/05/2005 Change the more-specific route ND option code + from de-facto '9' to the official '24'. Change + back in defaults.h if you need old behaviour. + +07/05/2005 Fix wrongly calculated prefix with Base6to4Interface + on ppc and maybe other big endian arches, from + Debian #301543 by Sam Hathaway. + +07/05/2005 Fix Linux-2.6.12-bk4+ error with HUP signal, + from YOSHIFUJI Hideaki / USAGI. + +03/29/2005 Merge a part of MIPv6/non-MIPv6 code, make printing + error messages nicer. + +03/22/2005 Be a bit more informative about config file parsing + errors. + +02/21/2005 Release 0.7.3. + +02/19/2005 Fix crash when reloading config with AdvSendAdvert off. + +02/15/2005 Merge a few fixes and improvements from USAGI: + - support microsecond scheduling and fix RA intervals + - send zero router lifetime when forwarding is disabled + - use a more flexible inter-RA delay + +01/07/2005 Accomodate interface indexes > 9999, from Hagen Fritsch. + +12/15/2004 Advertise zero Router Lifetime when shutting down; + implements a SHOULD in RFC2461 section 6.2.5. + +10/16/2004 Update Mobile IPv6 to match RFC 3775, from Greg Daley. + +08/20/2004 Minor documentation cleanups. + +03/09/2004 Implement "IgnoreIfMissing" interface flag, which can be + used on interfaces which aren't enabled when radvd starts + but will later become available (e.g., Bluetooth) -- + and then you wish to send HUP to radvd to activate the + configs. + +02/21/2004 Further cleanups, to fix autoconf/autoheader problems + with newer toolchain; mostly by Marko Myllynen. + +02/20/2004 Clean up a bit: remove old junk from configure.in, + rename "log()" to "flog()" to satisfy newer GCCs, + allow underscores in the interface names (the last two + fixes already committed earlier). + +01/19/2004 Make radvd check for forwarding status using procfs on + Linux; needed with 2.6 kernels. Loosely based on + a patch by USAGI. + +11/21/2003 Add support for Router Preferences and More Specific + Routes from Markku Savela . + NOTE! The specification is not final yet, there will be + changes! (Man page, documentation and radvdump support + by Pekka Savola.) + +09/11/2003 When starting up, check if the MAC address is all zero + (could happen e.g. with bridge interfaces with no attached + physical interfaces), and warn if so. For more information, + http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=103469 + +06/10/2003 When chrooting, check the possible return code + from chdir("/"). + +03/08/2003 Add patch from MAEDA Naoaki + to discard RS's from the unspecied source address with + link-layer address option, as required by RFC2461. + +10/28/2002 Release 0.7.2: + - add support for VLANs (from USAGI) + - make it compile better on newer NetBSD's (NetBSD) + - fix a syntax error in radvd.conf(5) sample documentation + - use IPV6_RECV{HOPLIMIT,PKTINFO} not + IPV6_{HOPLIMIT,PKTINFO} if supported + - (in Red Hat spec file) don't create radvd gid explicitly + - a lot of coding style cleanups + +01/16/2002 Release 0.7.1. + +01/12/2002 Update config.{guess,sub} from ftp.gnu.org; update INTRO. + Marko Myllynen and Debian bug #115992. + +01/02/2002 Ensure NULL-termination with strncpy. + +12/31/2001 Radvdump fixes: eliminate a warning of Prefix Information + sections with '-d -f'; add a note that + {Min,Max}RtrAdvInterval cannot be obtained with '-f'; + implement '-e' to be used with '-f' which omits all + advertised default settings. Mostly by Marko Myllynen. + +12/28/2001 Small cleanups. AdvSendAdvert is implicitly off by + default. Check configuration file permissions; must + not be writable by others, and if non-root, + not by self/own group. By Marko Myllynen. + +12/21/2001 Check via sysctl that IPv6 forwarding is enabled; + exit unless debugging is enabled. Triggered by + Marko Myllynen. + +11/22/2001 MinRtrAdvInterval for MIPv6 is 0.05 seconds, not 0.5. + (Note: untested). + +11/20/2001 Rework BSD device memory management a bit, minor cleanups. + Version bumped to 0.7.0. + +11/14/2001 Maintainership of radvd transferred from Lars Fenneberg + to Pekka Savola and Nathan Lutchansky. Lars' CVS + repository adopted, and changes merged from the -pX + branch. + +08/29/2001 Minor change for NetBSD 1.5.1 compatibility. + (Nathan Lutchansky) + +07/20/2001 Support for non-multicast links, like ISATAP. + (Nathan Lutchansky) + +07/03/2001 Minimum MTU has been changed to 1280 in the latest RFC's. + (Pekka Savola) + +06/30/2001 Check for possible buffer overflows; replace strcpy with + strncpy. No fatals found. Remove redunant radvd -t check. + (Pekka Savola) + +06/24/2001 Fix 1-byte overflow in /proc/net/igmp6 handling, + clean out possible memory garbage when sending RA's + (patch from ). + +06/19/2001 When dropping root, also set up supplementary groups + properly. On Linux, when sending RA's, check that the + interface has joined all-routers multicast group. Add a few + RFC2461 MUST sanity checks when receiving datagrams. Clean + out non-EUI64 addressing scheme and other minor bits. + (Pekka Savola) + +04/28/2001 Misc cleanup and bugfixes, automake support. + +03/28/2001 Grammar cleanup. Integrated 6to4 support through + "Base6to4Interface" option in prefix configuration. Signal + handling fixed by blocking on select() rather than recvmsg() + so SIGTERM/HUP take effect immediately now. (Nathan Lutchansky) + +03/27/2001 Security fixes: close stdin/out and chdir("/") via + daemon() to prevent possible exploits, and a flag to allow + radvd to set[ug]id to an unprivileged user (from Pekka Savola). + +02/01/2001 scope_id is not supported in glibc2.1. So it is now + compiled conditionally. + +01/31/2001 Add CC variable to Makefile. Fix bug with IPV6_ADD_MEMBERSHIP + handling. Set scope_id when sending packets. + +12/02/2000 man pages update, rewritten pid file handling, rewritten + signal handling (SIGHUP and SIGTERM), gcc warnings cleanup, + new radvdump option -f: print received RAs in config file + format (by Marko) + +11/19/2000 integrated the last two change entries into the main source + (patches by Marko Myllynen), fixed bug in log.c, fixed file + description leak in readin_config, rewrote code in timer.c, + updated man pages again (from Marko Myllynen, too), PID + file support (patch from Marko Myllynen, based on a patch + from Tommi.Komulainen@iki.fi) + +15/08/2000 RFC 2461 updates, Mobile IPv6 extensions added + +14/07/2000 added RA interval option and modified some default values + for timers + +06/15/99 changed to run with glibc 2.1 on RedHat 6.0. + +03/03/98 radvd now joins ipv6-allrouters on Linux. Fix contributed + by A.N.Kuznetsov . + +10/23/97 radvd will now accept any prefix length in its config + file but will warn about unusual ones + +10/19/97 removed backwards compatibility code in recv.c. + IPV6_HOPLIMIT support is now assumed to exist. + +10/19/97 fixed alignment problems in recv.c and send.c. + +10/16/97 the Makefile install target now uses mkinstalldirs. + +10/16/97 changed all u_int*_t to uint*_t for better POSIX + compliance and portability. Needs 2.1.57-CVS or glibc. + BSD seems to need patches. + +10/16/97 more intelligent configure; tries to figure out + where the IPv6 libraries and inclues are (if not in + the standard places). Searches in /usr/inet6 and /usr/ipv6. + +10/15/97 integrated small patches for glibc and BSD from Craig and + Philip + +09/14/97 EUI-64 "support" + +09/01/97 centralized all includes into includes.h for easier + maintainance + +08/25/97 changed all occurences of IPV6_TXINFO/IPV6_RXINFO + to IPV6_PKTINFO + +08/25/97 removed some compatibility stuff for older Linux kernels + +03/17/97 changed linux/if_arp.h to net/if_arp.h in device-linux.c + and configure.in (for glibc compatibility) + +03/17/97 integrated patch from Philip Blundell + into configure.in to check for inet_* in libc first and + then for libinet6 (for glibc compatibility). + +03/16/97 corrected small error in radvd.conf(5) man page and other + small changes + +03/16/97 removed linklocal.c source file from the distribution + because it wasn't used anymore + +03/16/97 added html version of the INTRO, removed ascii version. + +02/12/97 missing directories are now created on make install + +01/19/97 now also the rest of a line followed by a '#' is treated + as a comment in the config file + +01/16/97 added IPPROTO_IPV6/IPV6_HOPLIMIT support, so now incoming + RS' and RAs are checked if there hoplimit is 255 (on Linux + this only works with kernel version 2.1.21 and above) + +01/15/97 lots of portability cleanups; radvd is now using autoconf + for automatic configuration; removed support for the + in. prefix + +01/05/97 integrated BSD 4.4 patches from Craig + +12/21/96 release of version 0.3 + +12/15/96 the AdvSendAdvert flag works now + +12/14/96 added radvdump, dumps all received RAs in a human + readable form + +12/13/96 rewrote radvd to use new advanced API headers + +12/08/96 added radvd.conf(5) man page + +12/03/96 changed RAW_CHECKSUM to IPV6_CHECKSUM for kernels + 2.1.14 and above + +11/24/96 added checking of received RAs according to RFC 1970 + +11/20/96 rewrote the default handling, now it should conform + to RFC 1970 + +11/17/96 release of version 0.2 + +11/17/96 added -h (--help) and -f (--facility) option + +11/17/96 added setsockopt(..., SOL_IPV6, IPV6_MULTICAST_HOPS), so + that radvd works for kernel versions >2.1.7 (without this + you get "NDISC: fake router advertisment received" on your + hosts) + +11/17/96 added a man page for radvd(8) + +11/17/96 some minor filename changes + +11/13/96 first release of this version of in.radvd (0.1) diff --git a/support/sdk/c/blip/driver/radvd-1.0/COPYRIGHT b/support/sdk/c/blip/driver/radvd-1.0/COPYRIGHT new file mode 100644 index 00000000..1f464b06 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/COPYRIGHT @@ -0,0 +1,37 @@ + The author(s) grant permission for redistribution and use in source and +binary forms, with or without modification, of the software and documentation +provided that the following conditions are met: + +0. If you receive a version of the software that is specifically labelled + as not being for redistribution (check the version message and/or README), + you are not permitted to redistribute that version of the software in any + way or form. +1. All terms of all other applicable copyrights and licenses must be + followed. +2. Redistributions of source code must retain the authors' copyright + notice(s), this list of conditions, and the following disclaimer. +3. Redistributions in binary form must reproduce the authors' copyright + notice(s), this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgement with the name(s) of the + authors as specified in the copyright notice(s) substituted where + indicated: + + This product includes software developed by the authors which are + mentioned at the start of the source files and other contributors. + +5. Neither the name(s) of the author(s) 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 ITS AUTHORS 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 AUTHORS 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. diff --git a/support/sdk/c/blip/driver/radvd-1.0/INTRO.html b/support/sdk/c/blip/driver/radvd-1.0/INTRO.html new file mode 100644 index 00000000..29ea681b --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/INTRO.html @@ -0,0 +1,142 @@ + + + + + +RADVD Introduction + + + +

RADVD Introduction

+ +

+by Lars Fenneberg et al. Updated +2002-01-12. +

+ +

+IPv6 has a lot more +support for autoconfiguration than +IPv4. But for this +autoconfiguration to work on the hosts of a network, the routers +of the local network have to run a program which answers the +autoconfiguration requests of the hosts. +

+ +

+On Linux this program is called +radvd, which stands for +Router ADVertisement Daemon. This daemon listens to Router Solicitations +(RS) and answers with Router Advertisement (RA). Furthermore unsolicited +RAs are also send from time to time. +RFC 2461 defines most +functions of radvd. +

+ +

+Router Advertisements contain information, which is used by hosts to +configure their interfaces. This information includes address prefixes, +the MTU of the link and information about default routers. +

+ +

+Of course the routers can't autoconfigure themselves, so the information +on the routers has to be provided by the administrator of the system. +This is done by manually configuring the interfaces and routes and by +configuring the router advertisement daemon. +

+ +

+A small and simple configuration file for radvd might look like this: +

+ +

+

+
+interface eth0
+{
+        AdvSendAdvert on;
+        prefix 2001:db8:0:1::/64
+        {
+                AdvOnLink on;
+                AdvAutonomous on;
+        };
+};
+
+
+ +

+It says that radvd should advertise (AdvSendAdvert on) the prefix +2001:db8:0:1:: which has a lenght of 64 on the interface eth0. +Also the prefix is marked as autonomous (AdvAutonomous on) and as on-link +(AdvOnLink on). The both currently default to enabled but are included +here for introductory purposes; it isn't necessary to define them. +All the other options are left on their default values. +

+ +

+Autonomous means that the prefix can be used for automatic address +configuration and on-link means that the hosts can assume that all the hosts +which use this prefix are reachable via the interface on which the host +received this RA. +

+ +

+The prefix must be 64 bits long (apart from very few exceptions), as dictated by +RFC 2464 and other +standards for different link-layer technologies. For more +details, see RFC 2462 +(IPv6 Stateless Address Autoconfiguration) and +RFC 2464 +(Transmission of IPv6 Packets over Ethernet Networks). For more information +on configuring radvd please look at the manual pages which are included in +the radvd distribution. +

+ +

+So, when an interface on a hosts is UPed and a RA is received, the host +can configure an address on the interface by using the prefix and +appending the EUI-64 identifier derived from the hardware address +(also called link-layer token). The EUI-64 identifier is simply appended +after the prefix. For example: +

+ +

+

+
+   Announced prefix:    2001:db8:0:1::
+
+   MAC address:         00:07:E9:7B:02:59
+
+   EUI-64 identifier:   0207:e9ff:fe7b:259
+
+   Configured address:  2001:db8:0:1:207:e9ff:fe7b:259
+
+
+ +

+The host can also choose a default router by examining the RA. +the rest works automatically. +

+ +

+So now we've configured radvd, but we still need to configure the interfaces +and set the routes (on the router). There's a lot of good material on +setting up IPv6, and the reader is encouraged to have a look +at it; for example: +

+ +

+

+ +
+ +

+Copyright © 1997 Lars Fenneberg +

+ + + diff --git a/support/sdk/c/blip/driver/radvd-1.0/Makefile b/support/sdk/c/blip/driver/radvd-1.0/Makefile new file mode 100644 index 00000000..647d35ba --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/Makefile @@ -0,0 +1,572 @@ +# Generated automatically from Makefile.in by configure. +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# +# $Id$ +# +# Authors: +# Lars Fenneberg +# +# This software is Copyright 1996,1997 by the above mentioned author(s), +# All Rights Reserved. +# +# The license which is distributed with this software in the file COPYRIGHT +# applies to this software. If your distribution is missing this file, you +# may request it from . +# + + +SHELL = /bin/sh + +srcdir = . +top_srcdir = . +prefix = /usr/local +exec_prefix = ${prefix} + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +libexecdir = ${exec_prefix}/libexec +datadir = ${prefix}/share +sysconfdir = ${prefix}/etc +sharedstatedir = ${prefix}/com +localstatedir = ${prefix}/var +libdir = ${exec_prefix}/lib +infodir = ${prefix}/info +mandir = ${prefix}/man +includedir = ${prefix}/include +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/radvd +pkglibdir = $(libdir)/radvd +pkgincludedir = $(includedir)/radvd + +top_builddir = . + +ACLOCAL = aclocal +AUTOCONF = autoconf +AUTOMAKE = automake +AUTOHEADER = autoheader + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} +transform = s,x,x, + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = x86_64-unknown-linux-gnu +build_triplet = x86_64-unknown-linux-gnu +host_alias = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_alias = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +CC = gcc +GZIP = /bin/gzip +LEX = flex +LN = /bin/ln +LOG_FACILITY = LOG_DAEMON +MAKEINFO = makeinfo +PACKAGE = radvd +PATH_RADVD_CONF = ${prefix}/etc/radvd.conf +PATH_RADVD_LOG = /var/log/radvd.log +PATH_RADVD_PID = /var/run/radvd.pid +RM = /bin/rm +SED = /bin/sed +TAR = /bin/tar +VERSION = 1.0 +YACC = bison -y + +AUTOMAKE_OPTIONS = 1.2 foreign + +DEFS = -DPATH_RADVD_CONF=\"$(PATH_RADVD_CONF)\" \ + -DPATH_RADVD_LOG=\"$(PATH_RADVD_LOG)\" -DLOG_FACILITY=$(LOG_FACILITY) \ + -DPATH_RADVD_PID=\"$(PATH_RADVD_PID)\" \ + -DVERSION=\"$(VERSION)\" -DINET6=1 + +INCLUDES = -I$(srcdir) -I. + +######################################################################## + +COMMON_SRC = log.c socket.c recv.c util.c radvd.h defaults.h pathnames.h \ + includes.h + + +sbin_PROGRAMS = radvd radvdump + +radvd_SOURCES = $(COMMON_SRC) radvd.c timer.c send.c process.c interface.c \ + device.c device-common.c gram.y gram.h scanner.l + +radvd_LDADD = -lfl +EXTRA_radvd_SOURCES = device-linux.c device-bsd44.c +YFLAGS = -d +CFLAGS = -g -O2 -Wall -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations + + +radvdump_SOURCES = $(COMMON_SRC) radvdump.c + +man_MANS = radvd.8 radvdump.8 radvd.conf.5 +EXTRA_DIST = radvd.8.man radvdump.8.man radvd.conf.5.man VERSION CHANGES \ + COPYRIGHT INTRO.html copyright.blurb radvd.conf.example + +BUILT_SOURCES = device.c + +CLEANFILES = radvd.8 radvdump.8 radvd.conf.5 +DISTCLEANFILES = device.c + +SUFFIXES = .man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(sbin_PROGRAMS) + +CPPFLAGS = +LDFLAGS = +LIBS = -lc +radvd_OBJECTS = log.o socket.o recv.o util.o radvd.o timer.o send.o \ +process.o interface.o device.o device-common.o gram.o scanner.o +radvd_DEPENDENCIES = +radvd_LDFLAGS = +radvdump_OBJECTS = log.o socket.o recv.o util.o radvdump.o +radvdump_LDADD = $(LDADD) +radvdump_DEPENDENCIES = +radvdump_LDFLAGS = +LEX_OUTPUT_ROOT = lex.yy +LEXLIB = -lfl +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = README ./stamp-h.in Makefile.am Makefile.in TODO \ +aclocal.m4 config.guess config.h.in config.sub configure configure.in \ +gram.c install-sh missing mkinstalldirs scanner.c + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +DEP_FILES = .deps/device-bsd44.P .deps/device-common.P \ +.deps/device-linux.P .deps/device.P .deps/gram.P .deps/interface.P \ +.deps/log.P .deps/process.P .deps/radvd.P .deps/radvdump.P .deps/recv.P \ +.deps/scanner.P .deps/send.P .deps/socket.P .deps/timer.P .deps/util.P +SOURCES = $(radvd_SOURCES) $(EXTRA_radvd_SOURCES) $(radvdump_SOURCES) +OBJECTS = $(radvd_OBJECTS) $(radvdump_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .l .man .o .s .y +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: $(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +mostlyclean-sbinPROGRAMS: + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) + +distclean-sbinPROGRAMS: + +maintainer-clean-sbinPROGRAMS: + +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(sbin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +radvd: $(radvd_OBJECTS) $(radvd_DEPENDENCIES) + @rm -f radvd + $(LINK) $(radvd_LDFLAGS) $(radvd_OBJECTS) $(radvd_LDADD) $(LIBS) + +radvdump: $(radvdump_OBJECTS) $(radvdump_DEPENDENCIES) + @rm -f radvdump + $(LINK) $(radvdump_LDFLAGS) $(radvdump_OBJECTS) $(radvdump_LDADD) $(LIBS) +.l.c: + $(LEX) $(AM_LFLAGS) $(LFLAGS) $< && mv $(LEX_OUTPUT_ROOT).c $@ +.y.c: + $(YACC) $(AM_YFLAGS) $(YFLAGS) $< && mv y.tab.c $*.c + if test -f y.tab.h; then \ + if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \ + else :; fi +gram.h: gram.c + + +install-man5: + $(mkinstalldirs) $(DESTDIR)$(man5dir) + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \ + done + +uninstall-man5: + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \ + rm -f $(DESTDIR)$(man5dir)/$$inst; \ + done + +install-man8: + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done + +uninstall-man8: + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man5 install-man8 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man5 uninstall-man8 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-sbinPROGRAMS +install-exec: install-exec-am + +install-data-am: install-man +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-sbinPROGRAMS uninstall-man +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(MANS) config.h +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man5 \ + $(DESTDIR)$(mandir)/man8 + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + -test -z "scannerlgramhgramc$(BUILT_SOURCES)" || rm -f scannerl gramh gramc $(BUILT_SOURCES) +mostlyclean-am: mostlyclean-hdr mostlyclean-sbinPROGRAMS \ + mostlyclean-compile mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-hdr clean-sbinPROGRAMS clean-compile clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-hdr distclean-sbinPROGRAMS distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-sbinPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS clean-sbinPROGRAMS \ +maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \ +install-sbinPROGRAMS mostlyclean-compile distclean-compile \ +clean-compile maintainer-clean-compile install-man5 uninstall-man5 \ +install-man8 uninstall-man8 install-man uninstall-man tags \ +mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir mostlyclean-depend distclean-depend clean-depend \ +maintainer-clean-depend info-am info dvi-am dvi check check-am \ +installcheck-am installcheck all-recursive-am install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +.man: + $(SED) -e 's,@''VERSION''@,$(VERSION),g' \ + -e 's,@''sbindir''@,$(sbindir),g' \ + -e 's,@''PATH_RADVD_CONF''@,$(PATH_RADVD_CONF),g' \ + -e 's,@''PATH_RADVD_PID''@,$(PATH_RADVD_PID),g' \ + -e 's,@''PATH_RADVD_LOG''@,$(PATH_RADVD_LOG),g' \ + -e 's,@''LOG_FACILITY''@,$(LOG_FACILITY),g' \ + $< > $@ + +dist-hook: + rm -f $(distdir)/device.c + mkdir $(distdir)/redhat + cp -p $(srcdir)/redhat/radvd.init $(srcdir)/redhat/radvd.spec \ + $(srcdir)/redhat/radvd.sysconfig $(distdir)/redhat + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/support/sdk/c/blip/driver/radvd-1.0/Makefile.am b/support/sdk/c/blip/driver/radvd-1.0/Makefile.am new file mode 100644 index 00000000..506e32fe --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/Makefile.am @@ -0,0 +1,63 @@ +# +# $Id$ +# +# Authors: +# Lars Fenneberg +# +# This software is Copyright 1996,1997 by the above mentioned author(s), +# All Rights Reserved. +# +# The license which is distributed with this software in the file COPYRIGHT +# applies to this software. If your distribution is missing this file, you +# may request it from . +# + +AUTOMAKE_OPTIONS = 1.2 foreign + +DEFS= -DPATH_RADVD_CONF=\"$(PATH_RADVD_CONF)\" \ + -DPATH_RADVD_LOG=\"$(PATH_RADVD_LOG)\" -DLOG_FACILITY=$(LOG_FACILITY) \ + -DPATH_RADVD_PID=\"$(PATH_RADVD_PID)\" \ + -DVERSION=\"$(VERSION)\" -DINET6=1 +INCLUDES=-I$(srcdir) -I. + +######################################################################## + +COMMON_SRC = log.c socket.c recv.c util.c radvd.h defaults.h pathnames.h \ + includes.h + +sbin_PROGRAMS = radvd radvdump + +radvd_SOURCES = $(COMMON_SRC) radvd.c timer.c send.c process.c interface.c \ + device.c device-common.c gram.y gram.h scanner.l +radvd_LDADD = -lfl +EXTRA_radvd_SOURCES = device-linux.c device-bsd44.c +YFLAGS = -d +CFLAGS = @CFLAGS@ -Wall -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations + +radvdump_SOURCES = $(COMMON_SRC) radvdump.c + +man_MANS = radvd.8 radvdump.8 radvd.conf.5 +EXTRA_DIST = radvd.8.man radvdump.8.man radvd.conf.5.man VERSION CHANGES \ + COPYRIGHT INTRO.html copyright.blurb radvd.conf.example +BUILT_SOURCES = device.c + +CLEANFILES = radvd.8 radvdump.8 radvd.conf.5 +DISTCLEANFILES = device.c + +SUFFIXES = .man + +.man: + $(SED) -e 's,@''VERSION''@,$(VERSION),g' \ + -e 's,@''sbindir''@,$(sbindir),g' \ + -e 's,@''PATH_RADVD_CONF''@,$(PATH_RADVD_CONF),g' \ + -e 's,@''PATH_RADVD_PID''@,$(PATH_RADVD_PID),g' \ + -e 's,@''PATH_RADVD_LOG''@,$(PATH_RADVD_LOG),g' \ + -e 's,@''LOG_FACILITY''@,$(LOG_FACILITY),g' \ + $< > $@ + +dist-hook: + rm -f $(distdir)/device.c + mkdir $(distdir)/redhat + cp -p $(srcdir)/redhat/radvd.init $(srcdir)/redhat/radvd.spec \ + $(srcdir)/redhat/radvd.sysconfig $(distdir)/redhat diff --git a/support/sdk/c/blip/driver/radvd-1.0/Makefile.in b/support/sdk/c/blip/driver/radvd-1.0/Makefile.in new file mode 100644 index 00000000..cb9df342 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/Makefile.in @@ -0,0 +1,572 @@ +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# +# $Id$ +# +# Authors: +# Lars Fenneberg +# +# This software is Copyright 1996,1997 by the above mentioned author(s), +# All Rights Reserved. +# +# The license which is distributed with this software in the file COPYRIGHT +# applies to this software. If your distribution is missing this file, you +# may request it from . +# + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ +CC = @CC@ +GZIP = @GZIP@ +LEX = @LEX@ +LN = @LN@ +LOG_FACILITY = @LOG_FACILITY@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +PATH_RADVD_CONF = @PATH_RADVD_CONF@ +PATH_RADVD_LOG = @PATH_RADVD_LOG@ +PATH_RADVD_PID = @PATH_RADVD_PID@ +RM = @RM@ +SED = @SED@ +TAR = @TAR@ +VERSION = @VERSION@ +YACC = @YACC@ + +AUTOMAKE_OPTIONS = 1.2 foreign + +DEFS = -DPATH_RADVD_CONF=\"$(PATH_RADVD_CONF)\" \ + -DPATH_RADVD_LOG=\"$(PATH_RADVD_LOG)\" -DLOG_FACILITY=$(LOG_FACILITY) \ + -DPATH_RADVD_PID=\"$(PATH_RADVD_PID)\" \ + -DVERSION=\"$(VERSION)\" -DINET6=1 + +INCLUDES = -I$(srcdir) -I. + +######################################################################## + +COMMON_SRC = log.c socket.c recv.c util.c radvd.h defaults.h pathnames.h \ + includes.h + + +sbin_PROGRAMS = radvd radvdump + +radvd_SOURCES = $(COMMON_SRC) radvd.c timer.c send.c process.c interface.c \ + device.c device-common.c gram.y gram.h scanner.l + +radvd_LDADD = -lfl +EXTRA_radvd_SOURCES = device-linux.c device-bsd44.c +YFLAGS = -d +CFLAGS = @CFLAGS@ -Wall -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations + + +radvdump_SOURCES = $(COMMON_SRC) radvdump.c + +man_MANS = radvd.8 radvdump.8 radvd.conf.5 +EXTRA_DIST = radvd.8.man radvdump.8.man radvd.conf.5.man VERSION CHANGES \ + COPYRIGHT INTRO.html copyright.blurb radvd.conf.example + +BUILT_SOURCES = device.c + +CLEANFILES = radvd.8 radvdump.8 radvd.conf.5 +DISTCLEANFILES = device.c + +SUFFIXES = .man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(sbin_PROGRAMS) + +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +radvd_OBJECTS = log.o socket.o recv.o util.o radvd.o timer.o send.o \ +process.o interface.o device.o device-common.o gram.o scanner.o +radvd_DEPENDENCIES = +radvd_LDFLAGS = +radvdump_OBJECTS = log.o socket.o recv.o util.o radvdump.o +radvdump_LDADD = $(LDADD) +radvdump_DEPENDENCIES = +radvdump_LDFLAGS = +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LEXLIB = @LEXLIB@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = README ./stamp-h.in Makefile.am Makefile.in TODO \ +aclocal.m4 config.guess config.h.in config.sub configure configure.in \ +gram.c install-sh missing mkinstalldirs scanner.c + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +DEP_FILES = .deps/device-bsd44.P .deps/device-common.P \ +.deps/device-linux.P .deps/device.P .deps/gram.P .deps/interface.P \ +.deps/log.P .deps/process.P .deps/radvd.P .deps/radvdump.P .deps/recv.P \ +.deps/scanner.P .deps/send.P .deps/socket.P .deps/timer.P .deps/util.P +SOURCES = $(radvd_SOURCES) $(EXTRA_radvd_SOURCES) $(radvdump_SOURCES) +OBJECTS = $(radvd_OBJECTS) $(radvdump_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .l .man .o .s .y +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: $(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +mostlyclean-sbinPROGRAMS: + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) + +distclean-sbinPROGRAMS: + +maintainer-clean-sbinPROGRAMS: + +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(sbin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +radvd: $(radvd_OBJECTS) $(radvd_DEPENDENCIES) + @rm -f radvd + $(LINK) $(radvd_LDFLAGS) $(radvd_OBJECTS) $(radvd_LDADD) $(LIBS) + +radvdump: $(radvdump_OBJECTS) $(radvdump_DEPENDENCIES) + @rm -f radvdump + $(LINK) $(radvdump_LDFLAGS) $(radvdump_OBJECTS) $(radvdump_LDADD) $(LIBS) +.l.c: + $(LEX) $(AM_LFLAGS) $(LFLAGS) $< && mv $(LEX_OUTPUT_ROOT).c $@ +.y.c: + $(YACC) $(AM_YFLAGS) $(YFLAGS) $< && mv y.tab.c $*.c + if test -f y.tab.h; then \ + if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \ + else :; fi +gram.h: gram.c + + +install-man5: + $(mkinstalldirs) $(DESTDIR)$(man5dir) + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \ + done + +uninstall-man5: + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \ + rm -f $(DESTDIR)$(man5dir)/$$inst; \ + done + +install-man8: + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done + +uninstall-man8: + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man5 install-man8 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man5 uninstall-man8 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-sbinPROGRAMS +install-exec: install-exec-am + +install-data-am: install-man +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-sbinPROGRAMS uninstall-man +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(MANS) config.h +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man5 \ + $(DESTDIR)$(mandir)/man8 + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + -test -z "scannerlgramhgramc$(BUILT_SOURCES)" || rm -f scannerl gramh gramc $(BUILT_SOURCES) +mostlyclean-am: mostlyclean-hdr mostlyclean-sbinPROGRAMS \ + mostlyclean-compile mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-hdr clean-sbinPROGRAMS clean-compile clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-hdr distclean-sbinPROGRAMS distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-sbinPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS clean-sbinPROGRAMS \ +maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \ +install-sbinPROGRAMS mostlyclean-compile distclean-compile \ +clean-compile maintainer-clean-compile install-man5 uninstall-man5 \ +install-man8 uninstall-man8 install-man uninstall-man tags \ +mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir mostlyclean-depend distclean-depend clean-depend \ +maintainer-clean-depend info-am info dvi-am dvi check check-am \ +installcheck-am installcheck all-recursive-am install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +.man: + $(SED) -e 's,@''VERSION''@,$(VERSION),g' \ + -e 's,@''sbindir''@,$(sbindir),g' \ + -e 's,@''PATH_RADVD_CONF''@,$(PATH_RADVD_CONF),g' \ + -e 's,@''PATH_RADVD_PID''@,$(PATH_RADVD_PID),g' \ + -e 's,@''PATH_RADVD_LOG''@,$(PATH_RADVD_LOG),g' \ + -e 's,@''LOG_FACILITY''@,$(LOG_FACILITY),g' \ + $< > $@ + +dist-hook: + rm -f $(distdir)/device.c + mkdir $(distdir)/redhat + cp -p $(srcdir)/redhat/radvd.init $(srcdir)/redhat/radvd.spec \ + $(srcdir)/redhat/radvd.sysconfig $(distdir)/redhat + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/support/sdk/c/blip/driver/radvd-1.0/README b/support/sdk/c/blip/driver/radvd-1.0/README new file mode 100644 index 00000000..98a722e6 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/README @@ -0,0 +1,61 @@ +$Id$ + +Installation: +============= + +Run configure, e.g. + +./configure --prefix=/usr/local --sysconfdir=/etc --mandir=/usr/share/man + +See configure --help for additional command line arguments. + +Run 'make' and 'make install'. On BSD, you may need to use 'gmake'. + +Configuration: +============== + +See INTRO.html, radvd.conf(8) and radvd.conf.example. + +Frequently Asked Questions: +=========================== + +Setting up radvd is very simple, so the most frequently asked +questions have been about what radvd _doesn't_ do... + + 1. How do I set up the router running radvd to automatically + configure an address from the prefix advertised in Route + Advertisements from upstream? + + -- You don't. By the specification, routers ignore RAs. + You'll probably need to use manual configuration. But you + can't use the same prefix on two links in any case unless you + use something like proxy-ND (draft-ietf-ipv6-ndproxy-04.txt). + You may need to re-think your topology; prefix delegation + (e.g., manually or with RFC3633) may help. + + 2. How do I set up the router running radvd to automatically + configure the interfaces to use an EUI64-based address? + + -- You don't. The design philosophy of radvd is that it's + not the _router's_ configuration tool, but a route advertising + daemon. You'll need to set up all the addresses, routes, etc. + yourself. These tasks are something that system initscripts + could possibly do instead. + + 3. I have a dynamic /48 prefix. How do I set up radvd to: + a) set up interface addresses and routes on downstream + interfaces, and + b) advertise /64 prefixes from the /48 on downstream interfaces? + + -- For a), this isn't supported. For b), radvd includes special + support for 6to4 upstream interface but assumes that the interface + addresses/routes are set up manually. This should probably + be done in the initscripts or manually. (Though if someone were + to send a patch for b), it might be incorporated.) + + 4. How do I set up radvd to do either unicast or multicast routing? + + -- You don't. Radvd is not a routing or forwarding daemon. + You need to set any appropriate routing/forwarding first, + and then radvd to only advertise the prefixes to hosts as + appropriate. diff --git a/support/sdk/c/blip/driver/radvd-1.0/TODO b/support/sdk/c/blip/driver/radvd-1.0/TODO new file mode 100644 index 00000000..d1444a75 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/TODO @@ -0,0 +1,59 @@ +$Id$ + + NOTE WELL + ========= + + *NONE* of the items are being actively worked on. + So, if you're interested in one of these features, + it means you'll have to submit a patch... :-) + + +read list of interfaces with SIOCGIFCONF (AF_INET6 support in the kernel would +be nice) or from /proc + +Quoting Peter Bieringer (peter@bieringer.de): +> Das war's schon. Ach ja, wenn Du mal eine neue Version machst, kannst Du +> noch einen Schalter einbauen, damit radvd trotz debug-level >0 auf Wunsch +> als daemon in den Hintergrund starten kann? +[ Peter wants that a debugging level greater than 0 doesn't stop radvd +from forking.] + +support for few protocol constants defined in RFC 2461 Sec 10 is missing. + +consider whether UnicastOnly flag should be detected by radvdump. + +read the man pages one more time and make sure their are understandable +and English is correct + +The following parts of RFC2461(bis) are not implemented: + - section 6.2.1: Adv{Valid,Preferred}Lifetime that decrements in real time, + that is, one that will result in a Lifetime of zero at the specified time in + the future. (MUST) + - section 6.2.5: when AdvSendAdvertisements changes to FALSE, we don't send + a final RA with zero Router Lifetime (we just send it when shutting down). + (SHOULD) + - section 6.2.8: if the link-local address of the router changes, it should + multicast a few RAs from the old address with zero router lifetime, and a + few from the new address. (SHOULD). + +Consider whether to support RFC 4286 (Multicast Router Discovery). + +Consider whether to support multiple IPv4 addresses with Base6to4Interface +(currently the code just uses the first one). + +Consider whether to support a generalization of Base6to4Interface for +arbitrary IPv6 prefixes, to be used for automatic generation of downstream +prefixes. Also consider whether this would need to support multiple IPv6 +prefixes on the upstream interfaces. See question 3 in README for more on +this. + +Use getifaddrs() instead of ioctl SIOCGIFADDR and other friends. The +problem with this is that e.g. RHL73's glibc didn't support getifaddrs(), +and before glibc 2.3.3 getifaddrs() didn't use netlink so it didn't work +well with IPv6. So, some kind of compat library would be needed if this +would be used... + +Consider whether radvd should work around missing/broken interfaces by +default, especially if a previously working interface gets disabled. + +Implement Secure Neighbor Discovery (RFC 3971). diff --git a/support/sdk/c/blip/driver/radvd-1.0/VERSION b/support/sdk/c/blip/driver/radvd-1.0/VERSION new file mode 100644 index 00000000..9fb98e81 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/VERSION @@ -0,0 +1,6 @@ +# +# $Id$ +# +# this file is automatically processed by configure +# +1.0 diff --git a/support/sdk/c/blip/driver/radvd-1.0/aclocal.m4 b/support/sdk/c/blip/driver/radvd-1.0/aclocal.m4 new file mode 100644 index 00000000..f12013ec --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/aclocal.m4 @@ -0,0 +1,136 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4-p5 + +dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN([AM_MISSING_PROG], +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + + +dnl AM_PROG_LEX +dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT +AC_DEFUN([AM_PROG_LEX], +[missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1) +AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex") +AC_PROG_LEX +AC_DECL_YYTEXT]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN([AM_CONFIG_HEADER], +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.cache b/support/sdk/c/blip/driver/radvd-1.0/config.cache new file mode 100644 index 00000000..c9dfd232 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.cache @@ -0,0 +1,48 @@ +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +ac_cv_c_const=${ac_cv_c_const=yes} +ac_cv_func_getopt_long=${ac_cv_func_getopt_long=yes} +ac_cv_header_getopt_h=${ac_cv_header_getopt_h=yes} +ac_cv_header_inttypes_h=${ac_cv_header_inttypes_h=yes} +ac_cv_header_machine_limits_h=${ac_cv_header_machine_limits_h=no} +ac_cv_header_machine_param_h=${ac_cv_header_machine_param_h=no} +ac_cv_header_net_if_arp_h=${ac_cv_header_net_if_arp_h=yes} +ac_cv_header_net_if_dl_h=${ac_cv_header_net_if_dl_h=no} +ac_cv_header_net_if_types_h=${ac_cv_header_net_if_types_h=no} +ac_cv_header_netinet_ip6_h=${ac_cv_header_netinet_ip6_h=yes} +ac_cv_header_stdc=${ac_cv_header_stdc=yes} +ac_cv_header_sys_param_h=${ac_cv_header_sys_param_h=yes} +ac_cv_header_sys_sockio_h=${ac_cv_header_sys_sockio_h=no} +ac_cv_header_sys_time_h=${ac_cv_header_sys_time_h=yes} +ac_cv_header_time=${ac_cv_header_time=yes} +ac_cv_lib_c_inet_ntop=${ac_cv_lib_c_inet_ntop=yes} +ac_cv_lib_fl_yywrap=${ac_cv_lib_fl_yywrap=yes} +ac_cv_path_GZIP=${ac_cv_path_GZIP=/bin/gzip} +ac_cv_path_LN=${ac_cv_path_LN=/bin/ln} +ac_cv_path_RM=${ac_cv_path_RM=/bin/rm} +ac_cv_path_SED=${ac_cv_path_SED=/bin/sed} +ac_cv_path_TAR=${ac_cv_path_TAR=/bin/tar} +ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'} +ac_cv_prog_CC=${ac_cv_prog_CC=gcc} +ac_cv_prog_CPP=${ac_cv_prog_CPP='gcc -E'} +ac_cv_prog_LEX=${ac_cv_prog_LEX=flex} +ac_cv_prog_YACC=${ac_cv_prog_YACC='bison -y'} +ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no} +ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes} +ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes} +ac_cv_prog_gcc=${ac_cv_prog_gcc=yes} +ac_cv_prog_lex_root=${ac_cv_prog_lex_root=lex.yy} +ac_cv_prog_lex_yytext_pointer=${ac_cv_prog_lex_yytext_pointer=yes} +ac_cv_prog_make_make_set=${ac_cv_prog_make_make_set=yes} diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.guess b/support/sdk/c/blip/driver/radvd-1.0/config.guess new file mode 100755 index 00000000..aa6ea3f6 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.guess @@ -0,0 +1,1319 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-01-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + UNAME_MACHINE_ARCH=`(uname -p) 2>/dev/null` || \ + UNAME_MACHINE_ARCH=unknown + case "${UNAME_MACHINE_ARCH}" in + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_supported_targets=`cd /; ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + LIBC=gnuaout + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.h b/support/sdk/c/blip/driver/radvd-1.0/config.h new file mode 100644 index 00000000..b1c13a59 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.h @@ -0,0 +1,57 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#define YYTEXT_POINTER 1 + +/* Define if you have the getopt_long function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define if you have the header file. */ +#define HAVE_GETOPT_H 1 + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_LIMITS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_PARAM_H */ + +/* Define if you have the header file. */ +#define HAVE_NET_IF_ARP_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NET_IF_DL_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NET_IF_TYPES_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the c library (-lc). */ +#define HAVE_LIBC 1 + +/* whether struct sockaddr_in6 has sin6_scope_id */ +#define HAVE_SIN6_SCOPE_ID 1 + +/* whether struct in6_addr has u6_addrXX and defines s6_addrXX */ +#define HAVE_IN6_ADDR_S6_ADDR 1 + diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.h.in b/support/sdk/c/blip/driver/radvd-1.0/config.h.in new file mode 100644 index 00000000..87932a47 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.h.in @@ -0,0 +1,56 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#undef YYTEXT_POINTER + +/* Define if you have the getopt_long function. */ +#undef HAVE_GETOPT_LONG + +/* Define if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_MACHINE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_MACHINE_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_NET_IF_ARP_H + +/* Define if you have the header file. */ +#undef HAVE_NET_IF_DL_H + +/* Define if you have the header file. */ +#undef HAVE_NET_IF_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the c library (-lc). */ +#undef HAVE_LIBC + +/* whether struct sockaddr_in6 has sin6_scope_id */ +#undef HAVE_SIN6_SCOPE_ID + +/* whether struct in6_addr has u6_addrXX and defines s6_addrXX */ +#undef HAVE_IN6_ADDR_S6_ADDR + diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.log b/support/sdk/c/blip/driver/radvd-1.0/config.log new file mode 100644 index 00000000..b2a9a4da --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.log @@ -0,0 +1,107 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +configure:609: checking host system type +configure:630: checking target system type +configure:648: checking build system type +configure:683: checking for a BSD compatible install +configure:736: checking whether build environment is sane +configure:793: checking whether make sets ${MAKE} +configure:832: checking for working aclocal +configure:845: checking for working autoconf +configure:858: checking for working automake +configure:871: checking for working autoheader +configure:884: checking for working makeinfo +configure:919: checking for gcc +configure:1032: checking whether the C compiler (gcc ) works +configure:1048: gcc -o conftest conftest.c 1>&5 +configure:1074: checking whether the C compiler (gcc ) is a cross-compiler +configure:1079: checking whether we are using GNU C +configure:1088: gcc -E conftest.c +configure:1107: checking whether gcc accepts -g +configure:1151: checking for a BSD compatible install +configure:1206: checking for rm +configure:1245: checking for sed +configure:1284: checking for ln +configure:1321: checking for bison +configure:1352: checking how to run the C preprocessor +configure:1373: gcc -E conftest.c >/dev/null 2>conftest.out +configure:1437: checking for flex +configure:1470: checking for flex +configure:1504: checking for yywrap in -lfl +configure:1523: gcc -o conftest -g -O2 conftest.c -lfl 1>&5 +configure:1546: checking lex output file root +configure:1567: checking whether yytext is a pointer +configure:1586: gcc -o conftest -g -O2 conftest.c -lfl 1>&5 +configure:1610: checking for tar +configure:1645: checking for gzip +configure:1679: checking where to put logfile +configure:1691: checking where to put pidfile +configure:1703: checking where to find configfile +configure:1715: checking which syslog facility to use +configure:1728: checking for inet_ntop in -lc +configure:1747: gcc -o conftest -g -O2 conftest.c -lc 1>&5 +configure:1822: checking for ANSI C header files +configure:1835: gcc -E conftest.c >/dev/null 2>conftest.out +configure:1902: gcc -o conftest -g -O2 conftest.c -lc 1>&5 +configure: In function 'main': +configure:1897: warning: incompatible implicit declaration of built-in function 'exit' +configure:1929: checking for sys/time.h +configure:1939: gcc -E conftest.c >/dev/null 2>conftest.out +configure:1966: checking whether time.h and sys/time.h may both be included +configure:1980: gcc -c -g -O2 conftest.c 1>&5 +configure:2003: checking for netinet/ip6.h +configure:2013: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2082: checking for sys/sockio.h +configure:2092: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2088:24: error: sys/sockio.h: No such file or directory +configure: failed program was: +#line 2087 "configure" +#include "confdefs.h" +#include +configure:2082: checking for getopt.h +configure:2092: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2082: checking for inttypes.h +configure:2092: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2122: checking for net/if_dl.h +configure:2132: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2128:23: error: net/if_dl.h: No such file or directory +configure: failed program was: +#line 2127 "configure" +#include "confdefs.h" +#include +configure:2122: checking for net/if_types.h +configure:2132: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2128:26: error: net/if_types.h: No such file or directory +configure: failed program was: +#line 2127 "configure" +#include "confdefs.h" +#include +configure:2122: checking for net/if_arp.h +configure:2132: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2162: checking for sys/param.h +configure:2172: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2202: checking for machine/param.h +configure:2212: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2208:27: error: machine/param.h: No such file or directory +configure: failed program was: +#line 2207 "configure" +#include "confdefs.h" +#include +configure:2242: checking for machine/limits.h +configure:2252: gcc -E conftest.c >/dev/null 2>conftest.out +configure:2248:28: error: machine/limits.h: No such file or directory +configure: failed program was: +#line 2247 "configure" +#include "confdefs.h" +#include +configure:2280: checking for working const +configure:2334: gcc -c -g -O2 conftest.c 1>&5 +configure:2356: checking whether struct sockaddr_in6 has sin6_scope_id +configure:2367: gcc -c -g -O2 conftest.c 1>&5 +configure:2382: checking whether struct in6_addr has u6_addrXX and defines s6_addrXX +configure:2392: gcc -c -g -O2 conftest.c 1>&5 +configure: In function 'main': +configure:2388: warning: initialization makes integer from pointer without a cast +configure:2409: checking for getopt_long +configure:2437: gcc -o conftest -g -O2 conftest.c -lc 1>&5 diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.status b/support/sdk/c/blip/driver/radvd-1.0/config.status new file mode 100755 index 00000000..4eaf46da --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.status @@ -0,0 +1,353 @@ +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host jackalope.cs.berkeley.edu: +# +# ./configure +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: ./config.status [--recheck] [--version] [--help]" +for ac_option +do + case "$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running ${CONFIG_SHELL-/bin/sh} ./configure --no-create --no-recursion" + exec ${CONFIG_SHELL-/bin/sh} ./configure --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "./config.status generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "$ac_cs_usage"; exit 0 ;; + *) echo "$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=. +ac_given_INSTALL="/usr/bin/install -c" + +trap 'rm -fr Makefile config.h conftest*; exit 1' 1 2 15 + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\&%]/\\&/g; + s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF +/^[ ]*VPATH[ ]*=[^:]*$/d + +s%@SHELL@%/bin/sh%g +s%@CFLAGS@%-g -O2%g +s%@CPPFLAGS@%%g +s%@CXXFLAGS@%%g +s%@FFLAGS@%%g +s%@DEFS@%-DHAVE_CONFIG_H%g +s%@LDFLAGS@%%g +s%@LIBS@%-lc %g +s%@exec_prefix@%${prefix}%g +s%@prefix@%/usr/local%g +s%@program_transform_name@%s,x,x,%g +s%@bindir@%${exec_prefix}/bin%g +s%@sbindir@%${exec_prefix}/sbin%g +s%@libexecdir@%${exec_prefix}/libexec%g +s%@datadir@%${prefix}/share%g +s%@sysconfdir@%${prefix}/etc%g +s%@sharedstatedir@%${prefix}/com%g +s%@localstatedir@%${prefix}/var%g +s%@libdir@%${exec_prefix}/lib%g +s%@includedir@%${prefix}/include%g +s%@oldincludedir@%/usr/include%g +s%@infodir@%${prefix}/info%g +s%@mandir@%${prefix}/man%g +s%@host@%x86_64-unknown-linux-gnu%g +s%@host_alias@%x86_64-unknown-linux-gnu%g +s%@host_cpu@%x86_64%g +s%@host_vendor@%unknown%g +s%@host_os@%linux-gnu%g +s%@target@%x86_64-unknown-linux-gnu%g +s%@target_alias@%x86_64-unknown-linux-gnu%g +s%@target_cpu@%x86_64%g +s%@target_vendor@%unknown%g +s%@target_os@%linux-gnu%g +s%@build@%x86_64-unknown-linux-gnu%g +s%@build_alias@%x86_64-unknown-linux-gnu%g +s%@build_cpu@%x86_64%g +s%@build_vendor@%unknown%g +s%@build_os@%linux-gnu%g +s%@INSTALL_PROGRAM@%${INSTALL}%g +s%@INSTALL_SCRIPT@%${INSTALL_PROGRAM}%g +s%@INSTALL_DATA@%${INSTALL} -m 644%g +s%@PACKAGE@%radvd%g +s%@VERSION@%1.0%g +s%@ACLOCAL@%aclocal%g +s%@AUTOCONF@%autoconf%g +s%@AUTOMAKE@%automake%g +s%@AUTOHEADER@%autoheader%g +s%@MAKEINFO@%makeinfo%g +s%@SET_MAKE@%%g +s%@CC@%gcc%g +s%@RM@%/bin/rm%g +s%@SED@%/bin/sed%g +s%@LN@%/bin/ln%g +s%@YACC@%bison -y%g +s%@LEX@%flex%g +s%@LEXLIB@%-lfl%g +s%@CPP@%gcc -E%g +s%@LEX_OUTPUT_ROOT@%lex.yy%g +s%@TAR@%/bin/tar%g +s%@GZIP@%/bin/gzip%g +s%@PATH_RADVD_CONF@%${prefix}/etc/radvd.conf%g +s%@PATH_RADVD_PID@%/var/run/radvd.pid%g +s%@PATH_RADVD_LOG@%/var/log/radvd.log%g +s%@LOG_FACILITY@%LOG_DAEMON%g + +CEOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi + +CONFIG_FILES=${CONFIG_FILES-"Makefile"} +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then + CONFIG_HEADERS="config.h" +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + + cat > conftest.frag < conftest.out + rm -f conftest.in + mv conftest.out conftest.in + + cat > conftest.frag < conftest.out + rm -f conftest.in + mv conftest.out conftest.in + + cat > conftest.frag < conftest.out + rm -f conftest.in + mv conftest.out conftest.in + + cat > conftest.frag < conftest.out + rm -f conftest.in + mv conftest.out conftest.in + + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +ac_sources="device-linux.c" +ac_dests="device.c" +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done + + +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 diff --git a/support/sdk/c/blip/driver/radvd-1.0/config.sub b/support/sdk/c/blip/driver/radvd-1.0/config.sub new file mode 100755 index 00000000..16573348 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/config.sub @@ -0,0 +1,1440 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-01-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[34] | sh[34]eb | shbe | shle \ + | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cray2-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \ + | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [cjt]90) + basic_machine=${basic_machine}-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* | -morphos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/support/sdk/c/blip/driver/radvd-1.0/configure b/support/sdk/c/blip/driver/radvd-1.0/configure new file mode 100755 index 00000000..531cbcfa --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/configure @@ -0,0 +1,2911 @@ +#! /bin/sh + +# From configure.in ($Id$) + + + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + + + + +# +# Check to make sure that the build environment is sane. +# + + + + + + + + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-logfile Path to the radvd logfile [/var/log/radvd.log]" +ac_help="$ac_help + --with-pidfile Path to the radvd pidfile [/var/run/radvd.pid]" +ac_help="$ac_help + --with-configfile Path to the radvd config file [SYSCONF/radvd.conf]" +ac_help="$ac_help + --with-facility Syslog facility to use when using syslog logging" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=radvd.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:609: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:630: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:648: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +VERSION=`cat ${srcdir}/VERSION | grep -v '^#' | tr -d '\012'` +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:683: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:736: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:793: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=radvd + +VERSION=$VERSION + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 +echo "configure:832: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:845: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:858: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:871: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:884: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +echo $ac_n "building for architecture""... $ac_c" 1>&6 +case "$target" in + *linux*) + echo "$ac_t""linux" 1>&6 + arch=linux + ;; + *bsd*) + echo "$ac_t""bsd44" 1>&6 + arch=bsd44 + ;; + *) + echo "$ac_t""unknown" 1>&6 + { echo "configure: error: currently only Linux and BSD 4.4 with NRL's IPv6 code are +supported. If you have such a system and it is not guessed correctly +you must specifiy it with --target on the configure command line" 1>&2; exit 1; } + ;; +esac + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:919: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:949: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1000: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1032: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1043 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1048: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1074: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1079: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1107: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1151: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1206: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$RM" in + /*) + ac_cv_path_RM="$RM" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_RM="$RM" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_RM="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_RM" && ac_cv_path_RM="NOTFOUND" + ;; +esac +fi +RM="$ac_cv_path_RM" +if test -n "$RM"; then + echo "$ac_t""$RM" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test "x$RM" = xNOTFOUND; then + { echo "configure: error: can't find rm in your path - check PATH" 1>&2; exit 1; } +fi +# Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1245: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_SED'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SED" in + /*) + ac_cv_path_SED="$SED" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_SED="$SED" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SED="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_SED" && ac_cv_path_SED="NOTFOUND" + ;; +esac +fi +SED="$ac_cv_path_SED" +if test -n "$SED"; then + echo "$ac_t""$SED" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test "x$SED" = xNOTFOUND; then + { echo "configure: error: can't find sed in your path - check PATH" 1>&2; exit 1; } +fi +# Extract the first word of "ln", so it can be a program name with args. +set dummy ln; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1284: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_LN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$LN" in + /*) + ac_cv_path_LN="$LN" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_LN="$LN" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_LN="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +LN="$ac_cv_path_LN" +if test -n "$LN"; then + echo "$ac_t""$LN" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +for ac_prog in 'bison -y' byacc +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1321: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_YACC="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +YACC="$ac_cv_prog_YACC" +if test -n "$YACC"; then + echo "$ac_t""$YACC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1352: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1373: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1390: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1407: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +missing_dir=`cd $ac_aux_dir && pwd` +for ac_prog in flex lex +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1437: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_LEX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +LEX="$ac_cv_prog_LEX" +if test -n "$LEX"; then + echo "$ac_t""$LEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$LEX" && break +done +test -n "$LEX" || LEX=""$missing_dir/missing flex"" + +# Extract the first word of "flex", so it can be a program name with args. +set dummy flex; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1470: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_LEX="flex" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex" +fi +fi +LEX="$ac_cv_prog_LEX" +if test -n "$LEX"; then + echo "$ac_t""$LEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$LEXLIB" +then + case "$LEX" in + flex*) ac_lib=fl ;; + *) ac_lib=l ;; + esac + echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6 +echo "configure:1504: checking for yywrap in -l$ac_lib" >&5 +ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-l$ac_lib $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LEXLIB="-l$ac_lib" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking lex output file root""... $ac_c" 1>&6 +echo "configure:1546: checking lex output file root" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # The minimal lex program is just a single line: %%. But some broken lexes +# (Solaris, I think it was) want two %% lines, so accommodate them. +echo '%% +%%' | $LEX +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; } +fi +fi + +echo "$ac_t""$ac_cv_prog_lex_root" 1>&6 +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6 +echo "configure:1567: checking whether yytext is a pointer" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c +ac_save_LIBS="$LIBS" +LIBS="$LIBS $LEXLIB" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_prog_lex_yytext_pointer=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +LIBS="$ac_save_LIBS" +rm -f "${LEX_OUTPUT_ROOT}.c" + +fi + +echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6 +if test $ac_cv_prog_lex_yytext_pointer = yes; then + cat >> confdefs.h <<\EOF +#define YYTEXT_POINTER 1 +EOF + +fi + +# Extract the first word of "tar", so it can be a program name with args. +set dummy tar; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1610: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_TAR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$TAR" in + /*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_TAR="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +TAR="$ac_cv_path_TAR" +if test -n "$TAR"; then + echo "$ac_t""$TAR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "gzip", so it can be a program name with args. +set dummy gzip; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1645: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GZIP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GZIP" in + /*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GZIP="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +GZIP="$ac_cv_path_GZIP" +if test -n "$GZIP"; then + echo "$ac_t""$GZIP" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +echo $ac_n "checking where to put logfile""... $ac_c" 1>&6 +echo "configure:1679: checking where to put logfile" >&5 +# Check whether --with-logfile or --without-logfile was given. +if test "${with_logfile+set}" = set; then + withval="$with_logfile" + PATH_RADVD_LOG=$withval +else + PATH_RADVD_LOG=/var/log/radvd.log +fi + +echo "$ac_t""$PATH_RADVD_LOG" 1>&6 + +echo $ac_n "checking where to put pidfile""... $ac_c" 1>&6 +echo "configure:1691: checking where to put pidfile" >&5 +# Check whether --with-pidfile or --without-pidfile was given. +if test "${with_pidfile+set}" = set; then + withval="$with_pidfile" + PATH_RADVD_PID=$withval +else + PATH_RADVD_PID=/var/run/radvd.pid +fi + +echo "$ac_t""$PATH_RADVD_PID" 1>&6 + +echo $ac_n "checking where to find configfile""... $ac_c" 1>&6 +echo "configure:1703: checking where to find configfile" >&5 +# Check whether --with-configfile or --without-configfile was given. +if test "${with_configfile+set}" = set; then + withval="$with_configfile" + PATH_RADVD_CONF=$withval +else + PATH_RADVD_CONF=${sysconfdir}/radvd.conf +fi + +echo "$ac_t""$PATH_RADVD_CONF" 1>&6 + +echo $ac_n "checking which syslog facility to use""... $ac_c" 1>&6 +echo "configure:1715: checking which syslog facility to use" >&5 +# Check whether --with-facility or --without-facility was given. +if test "${with_facility+set}" = set; then + withval="$with_facility" + LOG_FACILITY=$withval +else + LOG_FACILITY=LOG_DAEMON +fi + +echo "$ac_t""$LOG_FACILITY" 1>&6 + + +echo $ac_n "checking for inet_ntop in -lc""... $ac_c" 1>&6 +echo "configure:1728: checking for inet_ntop in -lc" >&5 +ac_lib_var=`echo c'_'inet_ntop | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo c | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +echo $ac_n "checking for inet_ntop in -linet6""... $ac_c" 1>&6 +echo "configure:1773: checking for inet_ntop in -linet6" >&5 +ac_lib_var=`echo inet6'_'inet_ntop | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-linet6 $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -linet6" + +else + echo "$ac_t""no" 1>&6 +{ echo "configure: error: can't continue without libinet6.a library - check your LDFLAGS" 1>&2; exit 1; } + +fi + + +fi + +# prevent caching +unset ac_cv_lib_inet6_inet_ntop + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1822: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1835: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in sys/time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1929: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1939: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:1966: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:1980: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + + +ac_safe=`echo "netinet/ip6.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for netinet/ip6.h""... $ac_c" 1>&6 +echo "configure:2003: checking for netinet/ip6.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2013: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + hdrfound=yes +else + echo "$ac_t""no" 1>&6 +hdrfound=no +fi + +if test "$hdrfound" = no +then + # deprecated + ac_safe=`echo "netinet/ipv6.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for netinet/ipv6.h""... $ac_c" 1>&6 +echo "configure:2040: checking for netinet/ipv6.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2050: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + hdrfound=yes +else + echo "$ac_t""no" 1>&6 +fi + +fi +if test "$hdrfound" = no +then + echo "$ac_t""no" 1>&6 +fi +unset hdrfound + +for ac_hdr in sys/sockio.h getopt.h inttypes.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2082: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in net/if_dl.h net/if_types.h net/if_arp.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2122: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2132: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2162: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2172: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in machine/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2202: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2212: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in machine/limits.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2242: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2252: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:2280: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:2334: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + + +echo $ac_n "checking whether struct sockaddr_in6 has sin6_scope_id""... $ac_c" 1>&6 +echo "configure:2356: checking whether struct sockaddr_in6 has sin6_scope_id" >&5 +cat > conftest.$ac_ext < +#include +int main() { +static struct sockaddr_in6 ac_sin6; int ac_size = +sizeof (ac_sin6.sin6_scope_id); +; return 0; } +EOF +if { (eval echo configure:2367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF +#define HAVE_SIN6_SCOPE_ID 1 +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +echo $ac_n "checking whether struct in6_addr has u6_addrXX and defines s6_addrXX""... $ac_c" 1>&6 +echo "configure:2382: checking whether struct in6_addr has u6_addrXX and defines s6_addrXX" >&5 +cat > conftest.$ac_ext < +int main() { +static struct in6_addr in6_u; +int u = in6_u.s6_addr16; +; return 0; } +EOF +if { (eval echo configure:2392: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF +#define HAVE_IN6_ADDR_S6_ADDR 1 +EOF + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +for ac_func in getopt_long +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2409: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2437: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + + + + + + + + + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@RM@%$RM%g +s%@SED@%$SED%g +s%@LN@%$LN%g +s%@YACC@%$YACC%g +s%@LEX@%$LEX%g +s%@LEXLIB@%$LEXLIB%g +s%@CPP@%$CPP%g +s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g +s%@TAR@%$TAR%g +s%@GZIP@%$GZIP%g +s%@PATH_RADVD_CONF@%$PATH_RADVD_CONF%g +s%@PATH_RADVD_PID@%$PATH_RADVD_PID%g +s%@PATH_RADVD_LOG@%$PATH_RADVD_LOG%g +s%@LOG_FACILITY@%$LOG_FACILITY%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/support/sdk/c/blip/driver/radvd-1.0/configure.in b/support/sdk/c/blip/driver/radvd-1.0/configure.in new file mode 100644 index 00000000..39ea262a --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/configure.in @@ -0,0 +1,157 @@ +dnl +dnl $Id$ +dnl +dnl Authors: +dnl Lars Fenneberg +dnl +dnl This software is Copyright 1996-2000 by the above mentioned author(s), +dnl All Rights Reserved. +dnl +dnl The license which is distributed with this software in the file COPYRIGHT +dnl applies to this software. If your distribution is missing this file, you +dnl may request it from . +dnl +dnl + +AC_REVISION ($Id$) +AC_INIT(radvd.c) + +AC_CANONICAL_SYSTEM +VERSION=`cat ${srcdir}/VERSION | grep -v '^#' | tr -d '\012'` +AM_INIT_AUTOMAKE(radvd,$VERSION,true) + +echo $ac_n "building for architecture""... $ac_c" 1>&6 +case "$target" in + *linux*) + AC_MSG_RESULT(linux) + arch=linux + ;; + *bsd*) + AC_MSG_RESULT(bsd44) + arch=bsd44 + ;; + *) + AC_MSG_RESULT(unknown) + AC_MSG_ERROR( +[currently only Linux and BSD 4.4 with NRL's IPv6 code are +supported. If you have such a system and it is not guessed correctly +you must specifiy it with --target on the configure command line]) + ;; +esac + +dnl Determine CC and preset CFLAGS +AC_PROG_CC + +dnl Needed for normal compile +AC_PROG_INSTALL +AC_PATH_PROG(RM, rm, NOTFOUND) +if test "x$RM" = xNOTFOUND; then + AC_MSG_ERROR(can't find rm in your path - check PATH) +fi +AC_PATH_PROG(SED, sed, NOTFOUND) +if test "x$SED" = xNOTFOUND; then + AC_MSG_ERROR(can't find sed in your path - check PATH) +fi +dnl Not needed +AC_PATH_PROG(LN, ln) +AC_PROG_YACC +AM_PROG_LEX +AC_PATH_PROG(TAR, tar) +AC_PATH_PROG(GZIP, gzip) + +dnl Check where to put the logfile +AC_MSG_CHECKING(where to put logfile) +AC_ARG_WITH(logfile, +[ --with-logfile Path to the radvd logfile [/var/log/radvd.log]], + PATH_RADVD_LOG=$withval, + PATH_RADVD_LOG=/var/log/radvd.log) +AC_MSG_RESULT($PATH_RADVD_LOG) + +dnl Check where to put the pidfile +AC_MSG_CHECKING(where to put pidfile) +AC_ARG_WITH(pidfile, +[ --with-pidfile Path to the radvd pidfile [/var/run/radvd.pid]], + PATH_RADVD_PID=$withval, + PATH_RADVD_PID=/var/run/radvd.pid) +AC_MSG_RESULT($PATH_RADVD_PID) + +dnl Check where to put the configfile +AC_MSG_CHECKING(where to find configfile) +AC_ARG_WITH(configfile, +[ --with-configfile Path to the radvd config file [SYSCONF/radvd.conf]], + PATH_RADVD_CONF=$withval, + PATH_RADVD_CONF=${sysconfdir}/radvd.conf) +AC_MSG_RESULT($PATH_RADVD_CONF) + +dnl Checking which syslog facility to use +AC_MSG_CHECKING(which syslog facility to use) +AC_ARG_WITH(facility, +[ --with-facility Syslog facility to use when using syslog logging], + LOG_FACILITY=$withval, + LOG_FACILITY=LOG_DAEMON) +AC_MSG_RESULT($LOG_FACILITY) + +dnl Checks for libraries. + +AC_CHECK_LIB(c, inet_ntop,, + AC_CHECK_LIB(inet6, inet_ntop, + LIBS="$LIBS -linet6" + , + AC_MSG_ERROR(can't continue without libinet6.a library - check your LDFLAGS) + ) +) +# prevent caching +unset ac_cv_lib_inet6_inet_ntop + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(sys/time.h) +AC_HEADER_TIME + +AC_CHECK_HEADER(netinet/ip6.h, hdrfound=yes, hdrfound=no) +if test "$hdrfound" = no +then + # deprecated + AC_CHECK_HEADER(netinet/ipv6.h, hdrfound=yes) +fi +if test "$hdrfound" = no +then + AC_MSG_RESULT(no) +fi +unset hdrfound + +AC_CHECK_HEADERS(sys/sockio.h getopt.h inttypes.h) +AC_CHECK_HEADERS(net/if_dl.h net/if_types.h net/if_arp.h) +AC_CHECK_HEADERS(sys/param.h) +AC_CHECK_HEADERS(machine/param.h) +AC_CHECK_HEADERS(machine/limits.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST + +AC_MSG_CHECKING(whether struct sockaddr_in6 has sin6_scope_id) +AC_TRY_COMPILE([#include +#include ], [static struct sockaddr_in6 ac_sin6; int ac_size = +sizeof (ac_sin6.sin6_scope_id);], [AC_MSG_RESULT(yes); AC_DEFINE([HAVE_SIN6_SCOPE_ID], +1, [whether struct sockaddr_in6 has sin6_scope_id])], +AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(whether struct in6_addr has u6_addrXX and defines s6_addrXX) +AC_TRY_COMPILE([#include ], [static struct in6_addr in6_u; +int u = in6_u.s6_addr16;], [AC_MSG_RESULT(yes); AC_DEFINE([HAVE_IN6_ADDR_S6_ADDR], +1, [whether struct in6_addr has u6_addrXX and defines s6_addrXX])], +AC_MSG_RESULT(no)) + +dnl Checks for library functions. +AC_CHECK_FUNCS(getopt_long) + +AC_LINK_FILES(device-${arch}.c, device.c) + +AC_SUBST(VERSION) +AC_SUBST(PATH_RADVD_CONF) +AC_SUBST(PATH_RADVD_PID) +AC_SUBST(PATH_RADVD_LOG) +AC_SUBST(LOG_FACILITY) + +AM_CONFIG_HEADER(config.h) +AC_OUTPUT(Makefile) diff --git a/support/sdk/c/blip/driver/radvd-1.0/copyright.blurb b/support/sdk/c/blip/driver/radvd-1.0/copyright.blurb new file mode 100644 index 00000000..51923b7c --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/copyright.blurb @@ -0,0 +1,14 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ diff --git a/support/sdk/c/blip/driver/radvd-1.0/defaults.h b/support/sdk/c/blip/driver/radvd-1.0/defaults.h new file mode 100644 index 00000000..03fc62bb --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/defaults.h @@ -0,0 +1,226 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#ifndef DEFAULTS_H +#define DEFAULTS_H + +#include +#include +#include + +/* maximum message size for incoming and outgoing RSs and RAs */ + +#define MSG_SIZE 4096 + +#define MAX2(X,Y) ( (( X ) >= ( Y )) ? ( X ) : ( Y )) + + +/* Router Configuration Variables: */ + +/* For each multicast interface: */ + +#define DFLT_IgnoreIfMissing 0 +#define DFLT_AdvSendAdv 0 +#define DFLT_MaxRtrAdvInterval 600 +#define DFLT_MinRtrAdvInterval(iface) (0.33 * (iface)->MaxRtrAdvInterval) +#define DFLT_AdvManagedFlag 0 +#define DFLT_AdvOtherConfigFlag 0 +#define DFLT_AdvLinkMTU 0 +#define DFLT_AdvReachableTime 0 +#define DFLT_AdvRetransTimer 0 +#define DFLT_AdvCurHopLimit 64 /* as per RFC 1700 or the + next incarnation of it :) */ +#define DFLT_AdvDefaultLifetime(iface) MAX2(1, (int)(3.0 * (iface)->MaxRtrAdvInterval)) +#define DFLT_MinDelayBetweenRAs MIN_DELAY_BETWEEN_RAS +#define DFLT_AdvDefaultPreference 0 + +/* Options sent with RA */ + +#define DFLT_AdvSourceLLAddress 1 + +/* Each prefix has an associated: */ + +#define DFLT_AdvValidLifetime 2592000 /* seconds */ +#define DFLT_AdvOnLinkFlag 1 +#define DFLT_AdvPreferredLifetime 604800 /* seconds */ +#define DFLT_AdvAutonomousFlag 1 + +/* Each route has an associated: */ +#define DFLT_AdvRouteLifetime(iface) (3 * (iface)->MaxRtrAdvInterval) + +#define DFLT_AdvRoutePreference 0 /* medium*/ + +/* RDNSS */ +#define DFLT_AdvRDNSSPreference 8 /* medium */ +#define DFLT_AdvRDNSSOpenFlag 0 +#define DFLT_AdvRDNSSLifetime(iface) (iface)->MaxRtrAdvInterval + +/* Protocol (RFC2461) constants: */ + +/* Router constants: */ + +#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 +#define MAX_INITIAL_RTR_ADVERTISEMENTS 3 +#define MAX_FINAL_RTR_ADVERTISEMENTS 3 +#define MIN_DELAY_BETWEEN_RAS 3.0 +#define MIN_DELAY_BETWEEN_RAS_MIPv6 (30.0/1000.0) +#define MAX_RA_DELAY_TIME (1000.0/2.0) /* milliseconds */ + +/* Host constants: */ + +#define MAX_RTR_SOLICITATION_DELAY 1 +#define RTR_SOLICITATION_INTERVAL 4 +#define MAX_RTR_SOLICITATIONS 3 + +/* Node constants: */ + +#define MAX_MULTICAST_SOLICIT 3 +#define MAX_UNICAST_SOLICIT 3 +#define MAX_ANYCAST_DELAY_TIME 1 +#define MAX_NEIGHBOR_ADVERTISEMENT 3 +#define REACHABLE_TIME 30000 /* milliseconds */ +#define RETRANS_TIMER 1000 /* milliseconds */ +#define DELAY_FIRST_PROBE_TIME 5 +#define MIN_RANDOM_FACTOR (1.0/2.0) +#define MAX_RANDOM_FACTOR (3.0/2.0) + +/* MAX and MIN (RFC2461), Mobile IPv6 extensions will override if in use */ + +#define MIN_MaxRtrAdvInterval 4 +#define MAX_MaxRtrAdvInterval 1800 + +#define MIN_MinRtrAdvInterval 3 +#define MAX_MinRtrAdvInterval(iface) (0.75 * (iface)->MaxRtrAdvInterval) + +#define MIN_AdvDefaultLifetime(iface) (MAX2(1,(iface)->MaxRtrAdvInterval)) +#define MAX_AdvDefaultLifetime 9000 + +#define MIN_AdvLinkMTU 1280 + +#define MAX_AdvReachableTime 3600000 /* 1 hour in milliseconds */ + +#define MAX_AdvCurHopLimit 255 + +#define MAX_PrefixLen 128 + +/* + * Mobile IPv6 extensions, off by default + */ + +#define DFLT_AdvRouterAddr 0 +#define DFLT_AdvHomeAgentFlag 0 +#define DFLT_AdvIntervalOpt 0 +#define DFLT_AdvHomeAgentInfo 0 + +/* Option types (defined also at least in glibc 2.2's netinet/icmp6.h) */ + +#ifndef ND_OPT_RTR_ADV_INTERVAL +#define ND_OPT_RTR_ADV_INTERVAL 7 +#endif +#ifndef ND_OPT_HOME_AGENT_INFO +#define ND_OPT_HOME_AGENT_INFO 8 +#endif + +/* de-facto codepoint used by many implementations was '9', + the official IANA assignment will be '24' */ +#undef ND_OPT_ROUTE_INFORMATION +#define ND_OPT_ROUTE_INFORMATION 24 + +/* XXX: some libc's like KAME already had nd_opt_route_info! */ +struct nd_opt_route_info_local /* route information */ + { + uint8_t nd_opt_ri_type; + uint8_t nd_opt_ri_len; + uint8_t nd_opt_ri_prefix_len; + uint8_t nd_opt_ri_flags_reserved; + uint32_t nd_opt_ri_lifetime; + struct in6_addr nd_opt_ri_prefix; + }; + +/* the reserved field is 8 bits and we're interested of the middle two: 000xx000 */ +#define ND_OPT_RI_PRF_SHIFT 3 +#define ND_OPT_RI_PRF_MASK (3 << ND_OPT_RI_PRF_SHIFT) /* 00011000 = 0x18 */ + +#undef ND_OPT_RDNSS_INFORMATION +#define ND_OPT_RDNSS_INFORMATION 25 + +/* */ +struct nd_opt_rdnss_info_local +{ + uint8_t nd_opt_rdnssi_type; + uint8_t nd_opt_rdnssi_len; + uint16_t nd_opt_rdnssi_pref_flag_reserved; + uint32_t nd_opt_rdnssi_lifetime; + struct in6_addr nd_opt_rdnssi_addr1; + struct in6_addr nd_opt_rdnssi_addr2; + struct in6_addr nd_opt_rdnssi_addr3; +}; +/* pref/flag/reserved field : yyyyx00000000000 (big endian) - 00000000yyyyx000 (little indian); where yyyy = pref, x = flag */ +#if BYTE_ORDER == BIG_ENDIAN +#define ND_OPT_RDNSSI_PREF_SHIFT 12 +#else +#define ND_OPT_RDNSSI_PREF_SHIFT 4 +#endif +#define ND_OPT_RDNSSI_PREF_MASK (0xf << ND_OPT_RDNSSI_PREF_SHIFT) + +/* Flags */ + +#ifndef ND_RA_FLAG_HOME_AGENT +#define ND_RA_FLAG_HOME_AGENT 0x20 +#endif +#ifndef ND_OPT_PI_FLAG_RADDR +#define ND_OPT_PI_FLAG_RADDR 0x20 +#endif +#ifndef ND_OPT_RDNSSI_FLAG_S +#if BYTE_ORDER == BIG_ENDIAN +#define ND_OPT_RDNSSI_FLAG_S 0x0800 +#else +#define ND_OPT_RDNSSI_FLAG_S 0x0008 +#endif +#endif + +/* Configurable values */ + +#define DFLT_HomeAgentPreference 0 +#define DFLT_HomeAgentLifetime(iface) ((iface)->AdvDefaultLifetime) + +/* Other */ + +#define MIN_MinRtrAdvInterval_MIPv6 (3.0/100.0) +#define MIN_MaxRtrAdvInterval_MIPv6 (7.0/100.0) +#define RTR_SOLICITATION_INTERVAL_MIPv6 1 /* Recommended value by MIPv6 */ + +#define Cautious_MaxRtrAdvInterval (2.0/10.0) +#define Cautious_MaxRtrAdvInterval_Leeway (2.0/100.0) + +#define MIN_HomeAgentLifetime 1 /* 0 must NOT be used */ +#define MAX_HomeAgentLifetime 65520 /* 18.2 hours in secs */ + +/* #define MAX_RTR_SOLICITATIONS This MAY be ignored by MIPv6 */ + +/* NEMO extensions, off by default */ +#define DFLT_AdvMobRtrSupportFlag 0 + +/* Flags */ + +#ifndef ND_OPT_HAI_FLAG_SUPPORT_MR +#if BYTE_ORDER == BIG_ENDIAN +#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x8000 +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x0080 +#endif +#endif + +#endif diff --git a/support/sdk/c/blip/driver/radvd-1.0/depcomp b/support/sdk/c/blip/driver/radvd-1.0/depcomp new file mode 100755 index 00000000..edb5d38e --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/depcomp @@ -0,0 +1,479 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000, 2003 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +if test -z "$depfile"; then + base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` + dir=`echo "$object" | sed 's,/.*$,/,'` + if test "$dir" = "$object"; then + dir= + fi + # FIXME: should be _deps on DOS. + depfile="$dir.deps/$base" +fi + +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/support/sdk/c/blip/driver/radvd-1.0/device-bsd44.c b/support/sdk/c/blip/driver/radvd-1.0/device-bsd44.c new file mode 100644 index 00000000..b89ce313 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/device-bsd44.c @@ -0,0 +1,251 @@ +/* + * $Id$ + * + * Authors: + * Craig Metz + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include +#include +#include /* for PATH_PROC_NET_IF_INET6 */ + +static uint8_t ll_prefix[] = { 0xfe, 0x80 }; + +/* + * this function gets the hardware type and address of an interface, + * determines the link layer token length and checks it against + * the defined prefixes + */ +int +setup_deviceinfo(int sock, struct Interface *iface) +{ + struct ifconf ifconf; + struct ifreq ifr; + unsigned int nlen; + uint8_t *p, *end; + struct AdvPrefix *prefix; + char zero[sizeof(iface->if_addr)]; + + /* just allocate 8192 bytes, should be more than enough.. */ + if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len = (32 << 8)))) + { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + goto ret; + } + + if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) + { + flog(LOG_ERR, "ioctl(SIOCGIFCONF) failed: %s(%d)", strerror(errno), errno); + goto ret; + } + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, iface->Name, IFNAMSIZ-1); + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) { + flog(LOG_ERR, "ioctl(SIOCGIFMTU) failed for %s: %s", iface->Name, strerror(errno)); + goto ret; + } + + dlog(LOG_DEBUG, 3, "mtu for %s is %d", iface->Name, ifr.ifr_mtu); + iface->if_maxmtu = ifr.ifr_mtu; + + p = (uint8_t *)ifconf.ifc_buf; + end = p + ifconf.ifc_len; + nlen = strlen(iface->Name); + + while(p < end) + { + p += IFNAMSIZ; + + if ((p + 2) >= end) + break; + + if ((p + *p) >= end) + break; + + if ((*(p + 1) == AF_LINK) && + (((struct sockaddr_dl *)p)->sdl_nlen == nlen) && + (!memcmp(iface->Name, ((struct sockaddr_dl *)p)->sdl_data, nlen))) + { + + if (((struct sockaddr_dl *)p)->sdl_alen > sizeof(iface->if_addr)) + { + flog(LOG_ERR, "address length %d too big for", + ((struct sockaddr_dl *)p)->sdl_alen, + iface->Name); + goto ret; + } + + memcpy(iface->if_hwaddr, LLADDR((struct sockaddr_dl *)p), ((struct sockaddr_dl *)p)->sdl_alen); + iface->if_hwaddr_len = ((struct sockaddr_dl *)p)->sdl_alen << 3; + + switch(((struct sockaddr_dl *)p)->sdl_type) { + case IFT_ETHER: + case IFT_ISO88023: + iface->if_prefix_len = 64; + break; + case IFT_FDDI: + iface->if_prefix_len = 64; + break; + default: + iface->if_prefix_len = -1; + iface->if_maxmtu = -1; + break; + } + + dlog(LOG_DEBUG, 3, "link layer token length for %s is %d", iface->Name, + iface->if_hwaddr_len); + + dlog(LOG_DEBUG, 3, "prefix length for %s is %d", iface->Name, + iface->if_prefix_len); + + if (iface->if_prefix_len != -1) { + memset(zero, 0, ((struct sockaddr_dl *)p)->sdl_alen); + if (!memcmp(iface->if_hwaddr, zero, ((struct sockaddr_dl *)p)->sdl_alen)) + flog(LOG_WARNING, "WARNING, MAC address on %s is all zero!", + iface->Name); + } + + prefix = iface->AdvPrefixList; + while (prefix) + { + if ((iface->if_prefix_len != -1) && + (iface->if_prefix_len != prefix->PrefixLen)) + { + flog(LOG_WARNING, "prefix length should be %d for %s", + iface->if_prefix_len, iface->Name); + } + + prefix = prefix->next; + } + + free(ifconf.ifc_buf); + return 0; + } + + p += *p; + } + +ret: + iface->if_maxmtu = -1; + iface->if_hwaddr_len = -1; + iface->if_prefix_len = -1; + free(ifconf.ifc_buf); + return -1; +} + +int setup_linklocal_addr(int sock, struct Interface *iface) +{ + struct ifconf ifconf; + unsigned int nlen; + uint8_t *p, *end; + int index = 0; + + /* just allocate 8192 bytes, should be more than enough.. */ + if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len = (32 << 8)))) + { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + goto ret; + } + + if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) + { + flog(LOG_ERR, "ioctl(SIOCGIFCONF) failed: %s(%d)", strerror(errno), errno); + goto ret; + } + + p = (uint8_t *)ifconf.ifc_buf; + end = p + ifconf.ifc_len; + nlen = strlen(iface->Name); + + while(p < end) + { + p += IFNAMSIZ; + + if ((p + 2) >= end) + break; + + if ((p + *p) >= end) + break; + + if ((*(p + 1) == AF_LINK) && + (((struct sockaddr_dl *)p)->sdl_nlen == nlen) && + (!memcmp(iface->Name, ((struct sockaddr_dl *)p)->sdl_data, nlen))) + { + index = ((struct sockaddr_dl *)p)->sdl_index; + } + + if (index && (*(p + 1) == AF_INET6)) + if (!memcmp(&((struct sockaddr_in6 *)p)->sin6_addr, ll_prefix, sizeof(ll_prefix))) + { + memcpy(&iface->if_addr, &((struct sockaddr_in6 *)p)->sin6_addr, sizeof(struct in6_addr)); + iface->if_index = index; + + free(ifconf.ifc_buf); + return 0; + } + + p += *p; + + } + +ret: + flog(LOG_ERR, "no linklocal address configured for %s", iface->Name); + free(ifconf.ifc_buf); + return -1; +} + +int setup_allrouters_membership(int sock, struct Interface *iface) +{ + return (0); +} + +int check_allrouters_membership(int sock, struct Interface *iface) +{ + return (0); +} + +int +set_interface_linkmtu(const char *iface, uint32_t mtu) +{ + dlog(LOG_DEBUG, 4, "setting LinkMTU (%u) for %s is not supported", + mtu, iface); + return -1; +} + +int +set_interface_curhlim(const char *iface, uint8_t hlim) +{ + dlog(LOG_DEBUG, 4, "setting CurHopLimit (%u) for %s is not supported", + hlim, iface); + return -1; +} + +int +set_interface_reachtime(const char *iface, uint32_t rtime) +{ + dlog(LOG_DEBUG, 4, "setting BaseReachableTime (%u) for %s is not supported", + rtime, iface); + return -1; +} + +int +set_interface_retranstimer(const char *iface, uint32_t rettimer) +{ + dlog(LOG_DEBUG, 4, "setting RetransTimer (%u) for %s is not supported", + rettimer, iface); + return -1; +} + diff --git a/support/sdk/c/blip/driver/radvd-1.0/device-common.c b/support/sdk/c/blip/driver/radvd-1.0/device-common.c new file mode 100644 index 00000000..823127af --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/device-common.c @@ -0,0 +1,101 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include +#include + +int +check_device(int sock, struct Interface *iface) +{ + struct ifreq ifr; + + strncpy(ifr.ifr_name, iface->Name, IFNAMSIZ-1); + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) + { + if (!iface->IgnoreIfMissing) + flog(LOG_ERR, "ioctl(SIOCGIFFLAGS) failed for %s: %s", + iface->Name, strerror(errno)); + return (-1); + } + + if (!(ifr.ifr_flags & IFF_UP)) + { + if (!iface->IgnoreIfMissing) + flog(LOG_ERR, "interface %s is not UP", iface->Name); + return (-1); + } + + if (! iface->UnicastOnly && !(ifr.ifr_flags & IFF_MULTICAST)) + { + flog(LOG_WARNING, "interface %s does not support multicast", + iface->Name); + flog(LOG_WARNING, " do you need to add the UnicastOnly flag?"); + } + +#if 0 + /* SDH : ignore these warnings... */ + if (! iface->UnicastOnly && !(ifr.ifr_flags & IFF_BROADCAST)) + { + flog(LOG_WARNING, "interface %s does not support broadcast", + iface->Name); + flog(LOG_WARNING, " do you need to add the UnicastOnly flag?"); + } +#endif + + return 0; +} + +int +get_v4addr(const char *ifn, unsigned int *dst) +{ + struct ifreq ifr; + struct sockaddr_in *addr; + int fd; + + if( ( fd = socket(AF_INET,SOCK_DGRAM,0) ) < 0 ) + { + flog(LOG_ERR, "create socket for IPv4 ioctl failed for %s: %s", + ifn, strerror(errno)); + return (-1); + } + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifn, IFNAMSIZ-1); + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + ifr.ifr_addr.sa_family = AF_INET; + + if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) + { + flog(LOG_ERR, "ioctl(SIOCGIFADDR) failed for %s: %s", + ifn, strerror(errno)); + close( fd ); + return (-1); + } + + addr = (struct sockaddr_in *)(&ifr.ifr_addr); + + dlog(LOG_DEBUG, 3, "IPv4 address for %s is %s", ifn, + inet_ntoa( addr->sin_addr ) ); + + *dst = addr->sin_addr.s_addr; + + close( fd ); + + return 0; +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/device-linux.c b/support/sdk/c/blip/driver/radvd-1.0/device-linux.c new file mode 100644 index 00000000..f160c15b --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/device-linux.c @@ -0,0 +1,298 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include +#include +#include /* for PATH_PROC_NET_IF_INET6 */ + +#ifndef IPV6_ADDR_LINKLOCAL +#define IPV6_ADDR_LINKLOCAL 0x0020U +#endif + +/* + * this function gets the hardware type and address of an interface, + * determines the link layer token length and checks it against + * the defined prefixes + */ +int +setup_deviceinfo(int sock, struct Interface *iface) +{ + struct ifreq ifr; + struct AdvPrefix *prefix; + char zero[sizeof(iface->if_addr)]; + + strncpy(ifr.ifr_name, iface->Name, IFNAMSIZ-1); + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) { + flog(LOG_ERR, "ioctl(SIOCGIFMTU) failed for %s: %s", + iface->Name, strerror(errno)); + return (-1); + } + + dlog(LOG_DEBUG, 3, "mtu for %s is %d", iface->Name, ifr.ifr_mtu); + iface->if_maxmtu = ifr.ifr_mtu; + + if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) + { + flog(LOG_ERR, "ioctl(SIOCGIFHWADDR) failed for %s: %s", + iface->Name, strerror(errno)); + return (-1); + } + + dlog(LOG_DEBUG, 3, "hardware type for %s is %d", iface->Name, + ifr.ifr_hwaddr.sa_family); + + switch(ifr.ifr_hwaddr.sa_family) + { + case ARPHRD_ETHER: + iface->if_hwaddr_len = 48; + iface->if_prefix_len = 64; + break; +#ifdef ARPHRD_FDDI + case ARPHRD_FDDI: + iface->if_hwaddr_len = 48; + iface->if_prefix_len = 64; + break; +#endif /* ARPHDR_FDDI */ +#ifdef ARPHRD_ARCNET + case ARPHRD_ARCNET: + iface->if_hwaddr_len = 8; + iface->if_prefix_len = -1; + iface->if_maxmtu = -1; + break; +#endif /* ARPHDR_ARCNET */ + default: + iface->if_hwaddr_len = -1; + iface->if_prefix_len = -1; + iface->if_maxmtu = -1; + break; + } + + dlog(LOG_DEBUG, 3, "link layer token length for %s is %d", iface->Name, + iface->if_hwaddr_len); + + dlog(LOG_DEBUG, 3, "prefix length for %s is %d", iface->Name, + iface->if_prefix_len); + + if (iface->if_hwaddr_len != -1) { + unsigned int if_hwaddr_len_bytes = (iface->if_hwaddr_len + 7) >> 3; + + if (if_hwaddr_len_bytes > sizeof(iface->if_hwaddr)) { + flog(LOG_ERR, "address length %d too big for %s", if_hwaddr_len_bytes, iface->Name); + return(-2); + } + memcpy(iface->if_hwaddr, ifr.ifr_hwaddr.sa_data, if_hwaddr_len_bytes); + + memset(zero, 0, sizeof(zero)); + if (!memcmp(iface->if_hwaddr, zero, if_hwaddr_len_bytes)) + flog(LOG_WARNING, "WARNING, MAC address on %s is all zero!", + iface->Name); + } + + prefix = iface->AdvPrefixList; + while (prefix) + { + if ((iface->if_prefix_len != -1) && + (iface->if_prefix_len != prefix->PrefixLen)) + { + flog(LOG_WARNING, "prefix length should be %d for %s", + iface->if_prefix_len, iface->Name); + } + + prefix = prefix->next; + } + + return (0); +} + +/* + * this function extracts the link local address and interface index + * from PATH_PROC_NET_IF_INET6. Note: 'sock' unused in Linux. + */ +int setup_linklocal_addr(int sock, struct Interface *iface) +{ + FILE *fp; + char str_addr[40]; + unsigned int plen, scope, dad_status, if_idx; + char devname[IFNAMSIZ]; + + if ((fp = fopen(PATH_PROC_NET_IF_INET6, "r")) == NULL) + { + flog(LOG_ERR, "can't open %s: %s", PATH_PROC_NET_IF_INET6, + strerror(errno)); + return (-1); + } + + while (fscanf(fp, "%32s %x %02x %02x %02x %15s\n", + str_addr, &if_idx, &plen, &scope, &dad_status, + devname) != EOF) + { + if (scope == IPV6_ADDR_LINKLOCAL && + strcmp(devname, iface->Name) == 0) + { + struct in6_addr addr; + unsigned int ap; + int i; + + for (i=0; i<16; i++) + { + sscanf(str_addr + i * 2, "%02x", &ap); + addr.s6_addr[i] = (unsigned char)ap; + } + memcpy(&iface->if_addr, &addr, sizeof(iface->if_addr)); + + iface->if_index = if_idx; + fclose(fp); + return 0; + } + } + + flog(LOG_ERR, "no linklocal address configured for %s", iface->Name); + fclose(fp); + return (-1); +} + +int setup_allrouters_membership(int sock, struct Interface *iface) +{ + struct ipv6_mreq mreq; + + memset(&mreq, 0, sizeof(mreq)); + mreq.ipv6mr_interface = iface->if_index; + + /* ipv6-allrouters: ff02::2 */ + mreq.ipv6mr_multiaddr.s6_addr32[0] = htonl(0xFF020000); + mreq.ipv6mr_multiaddr.s6_addr32[3] = htonl(0x2); + + if (setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + { + /* linux-2.6.12-bk4 returns error with HUP signal but keep listening */ + if (errno != EADDRINUSE) + { + flog(LOG_ERR, "can't join ipv6-allrouters on %s", iface->Name); + return (-1); + } + } + + return (0); +} + +int check_allrouters_membership(int sock, struct Interface *iface) +{ + #define ALL_ROUTERS_MCAST "ff020000000000000000000000000002" + + FILE *fp; + unsigned int if_idx, allrouters_ok=0; + char addr[32+1]; + int ret=0; + + if ((fp = fopen(PATH_PROC_NET_IGMP6, "r")) == NULL) + { + flog(LOG_ERR, "can't open %s: %s", PATH_PROC_NET_IGMP6, + strerror(errno)); + return (-1); + } + + while ( (ret=fscanf(fp, "%u %*s %32[0-9A-Fa-f] %*x %*x %*x\n", &if_idx, addr)) != EOF) { + if (ret == 2) { + if (iface->if_index == if_idx) { + if (strncmp(addr, ALL_ROUTERS_MCAST, sizeof(addr)) == 0) + allrouters_ok = 1; + } + } + } + + fclose(fp); + + if (!allrouters_ok) { + flog(LOG_WARNING, "resetting ipv6-allrouters membership on %s", iface->Name); + setup_allrouters_membership(sock, iface); + } + + return(0); +} + +static int +set_interface_var(const char *iface, + const char *var, const char *name, + uint32_t val) +{ + FILE *fp; + char spath[64+IFNAMSIZ]; /* XXX: magic constant */ + snprintf(spath, sizeof(spath), var, iface); + + fp = fopen(spath, "w"); + if (!fp) { + if (name) + flog(LOG_ERR, "failed to set %s (%u) for %s", + name, val, iface); + return -1; + } + fprintf(fp, "%u", val); + fclose(fp); + + return 0; +} + +int +set_interface_linkmtu(const char *iface, uint32_t mtu) +{ + return set_interface_var(iface, + PROC_SYS_IP6_LINKMTU, "LinkMTU", + mtu); +} + +int +set_interface_curhlim(const char *iface, uint8_t hlim) +{ + return set_interface_var(iface, + PROC_SYS_IP6_CURHLIM, "CurHopLimit", + hlim); +} + +int +set_interface_reachtime(const char *iface, uint32_t rtime) +{ + int ret; + ret = set_interface_var(iface, + PROC_SYS_IP6_BASEREACHTIME_MS, + NULL, + rtime); + if (ret) + ret = set_interface_var(iface, + PROC_SYS_IP6_BASEREACHTIME, + "BaseReachableTimer", + rtime / 1000); + return ret; +} + +int +set_interface_retranstimer(const char *iface, uint32_t rettimer) +{ + int ret; + ret = set_interface_var(iface, + PROC_SYS_IP6_RETRANSTIMER_MS, + NULL, + rettimer); + if (ret) + ret = set_interface_var(iface, + PROC_SYS_IP6_RETRANSTIMER, + "RetransTimer", + rettimer / 1000); + return ret; +} + diff --git a/support/sdk/c/blip/driver/radvd-1.0/gram.c b/support/sdk/c/blip/driver/radvd-1.0/gram.c new file mode 100644 index 00000000..09c28173 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/gram.c @@ -0,0 +1,2390 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_INTERFACE = 258, + T_PREFIX = 259, + T_ROUTE = 260, + T_RDNSS = 261, + STRING = 262, + NUMBER = 263, + SIGNEDNUMBER = 264, + DECIMAL = 265, + SWITCH = 266, + IPV6ADDR = 267, + INFINITY = 268, + T_IgnoreIfMissing = 269, + T_AdvSendAdvert = 270, + T_MaxRtrAdvInterval = 271, + T_MinRtrAdvInterval = 272, + T_MinDelayBetweenRAs = 273, + T_AdvManagedFlag = 274, + T_AdvOtherConfigFlag = 275, + T_AdvLinkMTU = 276, + T_AdvReachableTime = 277, + T_AdvRetransTimer = 278, + T_AdvCurHopLimit = 279, + T_AdvDefaultLifetime = 280, + T_AdvDefaultPreference = 281, + T_AdvSourceLLAddress = 282, + T_AdvOnLink = 283, + T_AdvAutonomous = 284, + T_AdvValidLifetime = 285, + T_AdvPreferredLifetime = 286, + T_AdvRouterAddr = 287, + T_AdvHomeAgentFlag = 288, + T_AdvIntervalOpt = 289, + T_AdvHomeAgentInfo = 290, + T_Base6to4Interface = 291, + T_UnicastOnly = 292, + T_HomeAgentPreference = 293, + T_HomeAgentLifetime = 294, + T_AdvRoutePreference = 295, + T_AdvRouteLifetime = 296, + T_AdvRDNSSPreference = 297, + T_AdvRDNSSOpenFlag = 298, + T_AdvRDNSSLifetime = 299, + T_AdvMobRtrSupportFlag = 300, + T_BAD_TOKEN = 301 + }; +#endif +/* Tokens. */ +#define T_INTERFACE 258 +#define T_PREFIX 259 +#define T_ROUTE 260 +#define T_RDNSS 261 +#define STRING 262 +#define NUMBER 263 +#define SIGNEDNUMBER 264 +#define DECIMAL 265 +#define SWITCH 266 +#define IPV6ADDR 267 +#define INFINITY 268 +#define T_IgnoreIfMissing 269 +#define T_AdvSendAdvert 270 +#define T_MaxRtrAdvInterval 271 +#define T_MinRtrAdvInterval 272 +#define T_MinDelayBetweenRAs 273 +#define T_AdvManagedFlag 274 +#define T_AdvOtherConfigFlag 275 +#define T_AdvLinkMTU 276 +#define T_AdvReachableTime 277 +#define T_AdvRetransTimer 278 +#define T_AdvCurHopLimit 279 +#define T_AdvDefaultLifetime 280 +#define T_AdvDefaultPreference 281 +#define T_AdvSourceLLAddress 282 +#define T_AdvOnLink 283 +#define T_AdvAutonomous 284 +#define T_AdvValidLifetime 285 +#define T_AdvPreferredLifetime 286 +#define T_AdvRouterAddr 287 +#define T_AdvHomeAgentFlag 288 +#define T_AdvIntervalOpt 289 +#define T_AdvHomeAgentInfo 290 +#define T_Base6to4Interface 291 +#define T_UnicastOnly 292 +#define T_HomeAgentPreference 293 +#define T_HomeAgentLifetime 294 +#define T_AdvRoutePreference 295 +#define T_AdvRouteLifetime 296 +#define T_AdvRDNSSPreference 297 +#define T_AdvRDNSSOpenFlag 298 +#define T_AdvRDNSSLifetime 299 +#define T_AdvMobRtrSupportFlag 300 +#define T_BAD_TOKEN 301 + + + + +/* Copy the first part of user declarations. */ +#line 16 "gram.y" + +#include +#include +#include +#include + +extern struct Interface *IfaceList; +struct Interface *iface = NULL; +struct AdvPrefix *prefix = NULL; +struct AdvRoute *route = NULL; +struct AdvRDNSS *rdnss = NULL; + +extern char *conf_file; +extern int num_lines; +extern char *yytext; +extern int sock; + +static void cleanup(void); +static void yyerror(char *msg); + +#if 0 /* no longer necessary? */ +#ifndef HAVE_IN6_ADDR_S6_ADDR +# ifdef __FreeBSD__ +# define s6_addr32 __u6_addr.__u6_addr32 +# define s6_addr16 __u6_addr.__u6_addr16 +# endif +#endif +#endif + +#define ABORT do { cleanup(); YYABORT; } while (0); + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 110 "gram.y" +{ + unsigned int num; + int snum; + double dec; + int bool; + struct in6_addr *addr; + char *str; + struct AdvPrefix *pinfo; + struct AdvRoute *rinfo; + struct AdvRDNSS *rdnssinfo; +} +/* Line 187 of yacc.c. */ +#line 233 "y.tab.c" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ +#line 246 "y.tab.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 7 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 151 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 51 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 33 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 81 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 170 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 301 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 50, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 49, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 47, 2, 48, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 6, 8, 14, 17, 19, 24, 25, + 27, 28, 30, 31, 33, 34, 36, 39, 41, 45, + 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, + 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, + 129, 133, 137, 139, 142, 148, 153, 154, 156, 159, + 161, 165, 169, 173, 177, 181, 185, 187, 190, 196, + 201, 202, 204, 207, 209, 213, 217, 219, 222, 228, + 231, 233, 235, 238, 239, 241, 244, 246, 250, 254, + 258, 260 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 52, 0, -1, 52, 53, -1, 53, -1, 54, 47, + 56, 48, 49, -1, 3, 55, -1, 7, -1, 57, + 58, 59, 60, -1, -1, 61, -1, -1, 63, -1, + -1, 69, -1, -1, 75, -1, 61, 62, -1, 62, + -1, 17, 8, 49, -1, 16, 8, 49, -1, 18, + 8, 49, -1, 17, 10, 49, -1, 16, 10, 49, + -1, 18, 10, 49, -1, 14, 11, 49, -1, 15, + 11, 49, -1, 19, 11, 49, -1, 20, 11, 49, + -1, 21, 8, 49, -1, 22, 8, 49, -1, 23, + 8, 49, -1, 25, 8, 49, -1, 26, 9, 49, + -1, 24, 8, 49, -1, 27, 11, 49, -1, 34, + 11, 49, -1, 35, 11, 49, -1, 33, 11, 49, + -1, 38, 8, 49, -1, 39, 8, 49, -1, 37, + 11, 49, -1, 45, 11, 49, -1, 64, -1, 63, + 64, -1, 65, 47, 66, 48, 49, -1, 4, 12, + 50, 8, -1, -1, 67, -1, 67, 68, -1, 68, + -1, 28, 11, 49, -1, 29, 11, 49, -1, 32, + 11, 49, -1, 30, 83, 49, -1, 31, 83, 49, + -1, 36, 55, 49, -1, 70, -1, 69, 70, -1, + 71, 47, 72, 48, 49, -1, 5, 12, 50, 8, + -1, -1, 73, -1, 73, 74, -1, 74, -1, 40, + 9, 49, -1, 41, 83, 49, -1, 76, -1, 75, + 76, -1, 79, 47, 80, 48, 49, -1, 77, 78, + -1, 78, -1, 12, -1, 6, 77, -1, -1, 81, + -1, 81, 82, -1, 82, -1, 42, 8, 49, -1, + 43, 11, 49, -1, 44, 83, 49, -1, 8, -1, + 13, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 124, 124, 125, 128, 172, 187, 194, 202, 203, + 207, 210, 214, 217, 221, 224, 227, 228, 231, 235, + 239, 243, 247, 251, 255, 259, 263, 267, 271, 275, + 279, 283, 287, 291, 295, 299, 303, 307, 311, 315, + 319, 323, 329, 333, 340, 371, 394, 395, 398, 399, + 402, 406, 410, 414, 418, 422, 430, 434, 441, 449, + 473, 474, 477, 478, 482, 486, 492, 496, 503, 510, + 511, 514, 549, 558, 559, 562, 563, 567, 571, 575, + 588, 592 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_INTERFACE", "T_PREFIX", "T_ROUTE", + "T_RDNSS", "STRING", "NUMBER", "SIGNEDNUMBER", "DECIMAL", "SWITCH", + "IPV6ADDR", "INFINITY", "T_IgnoreIfMissing", "T_AdvSendAdvert", + "T_MaxRtrAdvInterval", "T_MinRtrAdvInterval", "T_MinDelayBetweenRAs", + "T_AdvManagedFlag", "T_AdvOtherConfigFlag", "T_AdvLinkMTU", + "T_AdvReachableTime", "T_AdvRetransTimer", "T_AdvCurHopLimit", + "T_AdvDefaultLifetime", "T_AdvDefaultPreference", "T_AdvSourceLLAddress", + "T_AdvOnLink", "T_AdvAutonomous", "T_AdvValidLifetime", + "T_AdvPreferredLifetime", "T_AdvRouterAddr", "T_AdvHomeAgentFlag", + "T_AdvIntervalOpt", "T_AdvHomeAgentInfo", "T_Base6to4Interface", + "T_UnicastOnly", "T_HomeAgentPreference", "T_HomeAgentLifetime", + "T_AdvRoutePreference", "T_AdvRouteLifetime", "T_AdvRDNSSPreference", + "T_AdvRDNSSOpenFlag", "T_AdvRDNSSLifetime", "T_AdvMobRtrSupportFlag", + "T_BAD_TOKEN", "'{'", "'}'", "';'", "'/'", "$accept", "grammar", + "ifacedef", "ifacehead", "name", "ifaceparams", "optional_ifacevlist", + "optional_prefixlist", "optional_routelist", "optional_rdnsslist", + "ifacevlist", "ifaceval", "prefixlist", "prefixdef", "prefixhead", + "optional_prefixplist", "prefixplist", "prefixparms", "routelist", + "routedef", "routehead", "optional_routeplist", "routeplist", + "routeparms", "rdnsslist", "rdnssdef", "rdnssaddrs", "rdnssaddr", + "rdnsshead", "optional_rdnssplist", "rdnssplist", "rdnssparms", + "number_or_infinity", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 123, 125, 59, + 47 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 51, 52, 52, 53, 54, 55, 56, 57, 57, + 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 63, 63, 64, 65, 66, 66, 67, 67, + 68, 68, 68, 68, 68, 68, 69, 69, 70, 71, + 72, 72, 73, 73, 74, 74, 75, 75, 76, 77, + 77, 78, 79, 80, 80, 81, 81, 82, 82, 82, + 83, 83 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 2, 1, 5, 2, 1, 4, 0, 1, + 0, 1, 0, 1, 0, 1, 2, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 2, 5, 4, 0, 1, 2, 1, + 3, 3, 3, 3, 3, 3, 1, 2, 5, 4, + 0, 1, 2, 1, 3, 3, 1, 2, 5, 2, + 1, 1, 2, 0, 1, 2, 1, 3, 3, 3, + 1, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 0, 3, 0, 6, 5, 1, 2, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 9, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12, 11, 42, 0, 16, 24, 25, 19, 22, + 18, 21, 20, 23, 26, 27, 28, 29, 30, 33, + 31, 32, 34, 37, 35, 36, 40, 38, 39, 41, + 4, 0, 0, 14, 13, 56, 0, 43, 46, 0, + 0, 0, 7, 15, 66, 0, 57, 60, 0, 0, + 0, 0, 0, 0, 0, 47, 49, 45, 0, 71, + 72, 70, 67, 73, 0, 0, 0, 61, 63, 0, + 0, 80, 81, 0, 0, 0, 0, 0, 48, 59, + 69, 0, 0, 0, 0, 74, 76, 0, 0, 0, + 62, 50, 51, 53, 54, 52, 55, 44, 0, 0, + 0, 0, 75, 64, 65, 58, 77, 78, 79, 68 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 2, 3, 4, 6, 31, 32, 61, 93, 102, + 33, 34, 62, 63, 64, 114, 115, 116, 94, 95, + 96, 126, 127, 128, 103, 104, 120, 121, 105, 144, + 145, 146, 133 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -112 +static const yytype_int8 yypact[] = +{ + 5, 26, 7, -112, -10, -112, -112, -112, -112, 1, + 38, 39, 33, 34, 37, 40, 41, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, + 58, 0, 56, 1, -112, 9, 12, 21, 22, 23, + 24, 25, 27, 28, 29, 30, 31, 32, 35, 36, + 42, 43, 44, 57, 61, 62, 63, 64, 65, 66, + 70, 78, 56, -112, 69, -112, -112, -112, -112, -112, + -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, + -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, + -112, 67, 74, 81, 78, -112, 71, -112, -27, 80, + 72, 77, -112, 81, -112, 73, -112, -28, 79, 83, + -2, -2, 84, 26, 75, -27, -112, -112, 88, -112, + 77, -112, -112, -13, 89, -2, 76, -28, -112, 82, + 85, -112, -112, 86, 87, 90, 91, 92, -112, -112, + -112, 93, 94, -2, 95, -13, -112, 96, 97, 98, + -112, -112, -112, -112, -112, -112, -112, -112, 99, 100, + 101, 102, -112, -112, -112, -112, -112, -112, -112, -112 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -112, -112, 105, -112, -38, -112, -112, -112, -112, -112, + -112, 104, -112, 68, -112, -112, -112, -18, -112, 6, + -112, -112, -112, -25, -112, -4, -112, -17, -112, -112, + -112, -41, -111 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 134, 108, 109, 110, 111, 112, 131, 7, 1, 113, + 1, 132, 124, 125, 148, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 141, + 142, 143, 160, 5, 24, 25, 26, 9, 27, 28, + 29, 37, 39, 38, 40, 41, 30, 42, 59, 35, + 36, 43, 44, 45, 46, 47, 48, 49, 66, 50, + 60, 67, 51, 52, 53, 54, 55, 56, 57, 58, + 68, 69, 70, 71, 72, 136, 73, 74, 75, 76, + 77, 78, 91, 92, 79, 80, 100, 101, 117, 119, + 129, 81, 82, 83, 130, 135, 139, 138, 147, 122, + 106, 158, 150, 140, 162, 159, 84, 8, 0, 0, + 85, 86, 87, 88, 89, 90, 98, 99, 107, 0, + 123, 0, 118, 137, 149, 0, 0, 0, 0, 0, + 97, 151, 0, 0, 152, 153, 154, 65, 0, 155, + 156, 157, 0, 161, 0, 163, 164, 165, 166, 167, + 168, 169 +}; + +static const yytype_int16 yycheck[] = +{ + 111, 28, 29, 30, 31, 32, 8, 0, 3, 36, + 3, 13, 40, 41, 125, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 42, + 43, 44, 143, 7, 33, 34, 35, 47, 37, 38, + 39, 8, 8, 10, 10, 8, 45, 10, 48, 11, + 11, 11, 11, 8, 8, 8, 8, 8, 49, 9, + 4, 49, 11, 11, 11, 11, 11, 8, 8, 11, + 49, 49, 49, 49, 49, 113, 49, 49, 49, 49, + 49, 49, 12, 5, 49, 49, 12, 6, 8, 12, + 11, 49, 49, 49, 11, 11, 8, 115, 9, 103, + 94, 8, 127, 120, 145, 11, 49, 2, -1, -1, + 49, 49, 49, 49, 49, 49, 47, 50, 47, -1, + 47, -1, 50, 48, 48, -1, -1, -1, -1, -1, + 62, 49, -1, -1, 49, 49, 49, 33, -1, 49, + 49, 49, -1, 48, -1, 49, 49, 49, 49, 49, + 49, 49 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 52, 53, 54, 7, 55, 0, 53, 47, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 33, 34, 35, 37, 38, 39, + 45, 56, 57, 61, 62, 11, 11, 8, 10, 8, + 10, 8, 10, 11, 11, 8, 8, 8, 8, 8, + 9, 11, 11, 11, 11, 11, 8, 8, 11, 48, + 4, 58, 63, 64, 65, 62, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 12, 5, 59, 69, 70, 71, 64, 47, 50, + 12, 6, 60, 75, 76, 79, 70, 47, 28, 29, + 30, 31, 32, 36, 66, 67, 68, 8, 50, 12, + 77, 78, 76, 47, 40, 41, 72, 73, 74, 11, + 11, 8, 13, 83, 83, 11, 55, 48, 68, 8, + 78, 42, 43, 44, 80, 81, 82, 9, 83, 48, + 74, 49, 49, 49, 49, 49, 49, 49, 8, 11, + 83, 48, 82, 49, 49, 49, 49, 49, 49, 49 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: +#line 129 "gram.y" + { + struct Interface *iface2; + + iface2 = IfaceList; + while (iface2) + { + if (!strcmp(iface2->Name, iface->Name)) + { + flog(LOG_ERR, "duplicate interface " + "definition for %s", iface->Name); + ABORT; + } + iface2 = iface2->next; + } + + if (check_device(sock, iface) < 0) { + if (iface->IgnoreIfMissing) { + dlog(LOG_DEBUG, 4, "interface %s did not exist, ignoring the interface", iface->Name); + goto skip_interface; + } + else { + flog(LOG_ERR, "interface %s does not exist", iface->Name); + ABORT; + } + } + if (setup_deviceinfo(sock, iface) < 0) + ABORT; + if (check_iface(iface) < 0) + ABORT; + if (setup_linklocal_addr(sock, iface) < 0) + ABORT; + if (setup_allrouters_membership(sock, iface) < 0) + ABORT; + + iface->next = IfaceList; + IfaceList = iface; + + dlog(LOG_DEBUG, 4, "interface definition for %s is ok", iface->Name); + +skip_interface: + iface = NULL; + } + break; + + case 5: +#line 173 "gram.y" + { + iface = malloc(sizeof(struct Interface)); + + if (iface == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + iface_init_defaults(iface); + strncpy(iface->Name, (yyvsp[(2) - (2)].str), IFNAMSIZ-1); + iface->Name[IFNAMSIZ-1] = '\0'; + } + break; + + case 6: +#line 188 "gram.y" + { + /* check vality */ + (yyval.str) = (yyvsp[(1) - (1)].str); + } + break; + + case 7: +#line 195 "gram.y" + { + iface->AdvPrefixList = (yyvsp[(2) - (4)].pinfo); + iface->AdvRouteList = (yyvsp[(3) - (4)].rinfo); + iface->AdvRDNSSList = (yyvsp[(4) - (4)].rdnssinfo); + } + break; + + case 10: +#line 207 "gram.y" + { + (yyval.pinfo) = NULL; + } + break; + + case 12: +#line 214 "gram.y" + { + (yyval.rinfo) = NULL; + } + break; + + case 14: +#line 221 "gram.y" + { + (yyval.rdnssinfo) = NULL; + } + break; + + case 18: +#line 232 "gram.y" + { + iface->MinRtrAdvInterval = (yyvsp[(2) - (3)].num); + } + break; + + case 19: +#line 236 "gram.y" + { + iface->MaxRtrAdvInterval = (yyvsp[(2) - (3)].num); + } + break; + + case 20: +#line 240 "gram.y" + { + iface->MinDelayBetweenRAs = (yyvsp[(2) - (3)].num); + } + break; + + case 21: +#line 244 "gram.y" + { + iface->MinRtrAdvInterval = (yyvsp[(2) - (3)].dec); + } + break; + + case 22: +#line 248 "gram.y" + { + iface->MaxRtrAdvInterval = (yyvsp[(2) - (3)].dec); + } + break; + + case 23: +#line 252 "gram.y" + { + iface->MinDelayBetweenRAs = (yyvsp[(2) - (3)].dec); + } + break; + + case 24: +#line 256 "gram.y" + { + iface->IgnoreIfMissing = (yyvsp[(2) - (3)].bool); + } + break; + + case 25: +#line 260 "gram.y" + { + iface->AdvSendAdvert = (yyvsp[(2) - (3)].bool); + } + break; + + case 26: +#line 264 "gram.y" + { + iface->AdvManagedFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 27: +#line 268 "gram.y" + { + iface->AdvOtherConfigFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 28: +#line 272 "gram.y" + { + iface->AdvLinkMTU = (yyvsp[(2) - (3)].num); + } + break; + + case 29: +#line 276 "gram.y" + { + iface->AdvReachableTime = (yyvsp[(2) - (3)].num); + } + break; + + case 30: +#line 280 "gram.y" + { + iface->AdvRetransTimer = (yyvsp[(2) - (3)].num); + } + break; + + case 31: +#line 284 "gram.y" + { + iface->AdvDefaultLifetime = (yyvsp[(2) - (3)].num); + } + break; + + case 32: +#line 288 "gram.y" + { + iface->AdvDefaultPreference = (yyvsp[(2) - (3)].snum); + } + break; + + case 33: +#line 292 "gram.y" + { + iface->AdvCurHopLimit = (yyvsp[(2) - (3)].num); + } + break; + + case 34: +#line 296 "gram.y" + { + iface->AdvSourceLLAddress = (yyvsp[(2) - (3)].bool); + } + break; + + case 35: +#line 300 "gram.y" + { + iface->AdvIntervalOpt = (yyvsp[(2) - (3)].bool); + } + break; + + case 36: +#line 304 "gram.y" + { + iface->AdvHomeAgentInfo = (yyvsp[(2) - (3)].bool); + } + break; + + case 37: +#line 308 "gram.y" + { + iface->AdvHomeAgentFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 38: +#line 312 "gram.y" + { + iface->HomeAgentPreference = (yyvsp[(2) - (3)].num); + } + break; + + case 39: +#line 316 "gram.y" + { + iface->HomeAgentLifetime = (yyvsp[(2) - (3)].num); + } + break; + + case 40: +#line 320 "gram.y" + { + iface->UnicastOnly = (yyvsp[(2) - (3)].bool); + } + break; + + case 41: +#line 324 "gram.y" + { + iface->AdvMobRtrSupportFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 42: +#line 330 "gram.y" + { + (yyval.pinfo) = (yyvsp[(1) - (1)].pinfo); + } + break; + + case 43: +#line 334 "gram.y" + { + (yyvsp[(2) - (2)].pinfo)->next = (yyvsp[(1) - (2)].pinfo); + (yyval.pinfo) = (yyvsp[(2) - (2)].pinfo); + } + break; + + case 44: +#line 341 "gram.y" + { + unsigned int dst; + + if (prefix->AdvPreferredLifetime > + prefix->AdvValidLifetime) + { + flog(LOG_ERR, "AdvValidLifeTime must be " + "greater than AdvPreferredLifetime in %s, line %d", + conf_file, num_lines); + ABORT; + } + + if( prefix->if6to4[0] ) + { + if (get_v4addr(prefix->if6to4, &dst) < 0) + { + flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 ); + prefix->enabled = 0; + } else + { + *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002); + memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) ); + } + } + + (yyval.pinfo) = prefix; + prefix = NULL; + } + break; + + case 45: +#line 372 "gram.y" + { + prefix = malloc(sizeof(struct AdvPrefix)); + + if (prefix == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + prefix_init_defaults(prefix); + + if ((yyvsp[(4) - (4)].num) > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid prefix length in %s, line %d", conf_file, num_lines); + ABORT; + } + + prefix->PrefixLen = (yyvsp[(4) - (4)].num); + + memcpy(&prefix->Prefix, (yyvsp[(2) - (4)].addr), sizeof(struct in6_addr)); + } + break; + + case 50: +#line 403 "gram.y" + { + prefix->AdvOnLinkFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 51: +#line 407 "gram.y" + { + prefix->AdvAutonomousFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 52: +#line 411 "gram.y" + { + prefix->AdvRouterAddr = (yyvsp[(2) - (3)].bool); + } + break; + + case 53: +#line 415 "gram.y" + { + prefix->AdvValidLifetime = (yyvsp[(2) - (3)].num); + } + break; + + case 54: +#line 419 "gram.y" + { + prefix->AdvPreferredLifetime = (yyvsp[(2) - (3)].num); + } + break; + + case 55: +#line 423 "gram.y" + { + dlog(LOG_DEBUG, 4, "using interface %s for 6to4", (yyvsp[(2) - (3)].str)); + strncpy(prefix->if6to4, (yyvsp[(2) - (3)].str), IFNAMSIZ-1); + prefix->if6to4[IFNAMSIZ-1] = '\0'; + } + break; + + case 56: +#line 431 "gram.y" + { + (yyval.rinfo) = (yyvsp[(1) - (1)].rinfo); + } + break; + + case 57: +#line 435 "gram.y" + { + (yyvsp[(2) - (2)].rinfo)->next = (yyvsp[(1) - (2)].rinfo); + (yyval.rinfo) = (yyvsp[(2) - (2)].rinfo); + } + break; + + case 58: +#line 442 "gram.y" + { + (yyval.rinfo) = route; + route = NULL; + } + break; + + case 59: +#line 450 "gram.y" + { + route = malloc(sizeof(struct AdvRoute)); + + if (route == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + route_init_defaults(route, iface); + + if ((yyvsp[(4) - (4)].num) > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid route prefix length in %s, line %d", conf_file, num_lines); + ABORT; + } + + route->PrefixLen = (yyvsp[(4) - (4)].num); + + memcpy(&route->Prefix, (yyvsp[(2) - (4)].addr), sizeof(struct in6_addr)); + } + break; + + case 64: +#line 483 "gram.y" + { + route->AdvRoutePreference = (yyvsp[(2) - (3)].snum); + } + break; + + case 65: +#line 487 "gram.y" + { + route->AdvRouteLifetime = (yyvsp[(2) - (3)].num); + } + break; + + case 66: +#line 493 "gram.y" + { + (yyval.rdnssinfo) = (yyvsp[(1) - (1)].rdnssinfo); + } + break; + + case 67: +#line 497 "gram.y" + { + (yyvsp[(2) - (2)].rdnssinfo)->next = (yyvsp[(1) - (2)].rdnssinfo); + (yyval.rdnssinfo) = (yyvsp[(2) - (2)].rdnssinfo); + } + break; + + case 68: +#line 504 "gram.y" + { + (yyval.rdnssinfo) = rdnss; + rdnss = NULL; + } + break; + + case 71: +#line 515 "gram.y" + { + if (!rdnss) { + /* first IP found */ + rdnss = malloc(sizeof(struct AdvRDNSS)); + + if (rdnss == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + rdnss_init_defaults(rdnss, iface); + } + + switch (rdnss->AdvRDNSSNumber) { + case 0: + memcpy(&rdnss->AdvRDNSSAddr1, (yyvsp[(1) - (1)].addr), sizeof(struct in6_addr)); + rdnss->AdvRDNSSNumber++; + break; + case 1: + memcpy(&rdnss->AdvRDNSSAddr2, (yyvsp[(1) - (1)].addr), sizeof(struct in6_addr)); + rdnss->AdvRDNSSNumber++; + break; + case 2: + memcpy(&rdnss->AdvRDNSSAddr3, (yyvsp[(1) - (1)].addr), sizeof(struct in6_addr)); + rdnss->AdvRDNSSNumber++; + break; + default: + flog(LOG_CRIT, "Too many addresses in RDNSS section"); + ABORT; + } + + } + break; + + case 72: +#line 550 "gram.y" + { + if (!rdnss) { + flog(LOG_CRIT, "No address specified in RDNSS section"); + ABORT; + } + } + break; + + case 77: +#line 568 "gram.y" + { + rdnss->AdvRDNSSPreference = (yyvsp[(2) - (3)].num); + } + break; + + case 78: +#line 572 "gram.y" + { + rdnss->AdvRDNSSOpenFlag = (yyvsp[(2) - (3)].bool); + } + break; + + case 79: +#line 576 "gram.y" + { + if ((yyvsp[(2) - (3)].num) < iface->MaxRtrAdvInterval && (yyvsp[(2) - (3)].num) != 0) { + flog(LOG_ERR, "AdvRDNSSLifetime must be at least MaxRtrAdvInterval"); + ABORT; + } + if ((yyvsp[(2) - (3)].num) > 2*(iface->MaxRtrAdvInterval)) + flog(LOG_WARNING, "Warning: AdvRDNSSLifetime <= 2*MaxRtrAdvInterval would allow stale DNS servers to be deleted faster"); + + rdnss->AdvRDNSSLifetime = (yyvsp[(2) - (3)].num); + } + break; + + case 80: +#line 589 "gram.y" + { + (yyval.num) = (yyvsp[(1) - (1)].num); + } + break; + + case 81: +#line 593 "gram.y" + { + (yyval.num) = (uint32_t)~0; + } + break; + + +/* Line 1267 of yacc.c. */ +#line 2152 "y.tab.c" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 598 "gram.y" + + +static +void cleanup(void) +{ + if (iface) + free(iface); + + if (prefix) + free(prefix); + + if (route) + free(route); + + if (rdnss) + free(rdnss); +} + +static void +yyerror(char *msg) +{ + cleanup(); + flog(LOG_ERR, "%s in %s, line %d: %s", msg, conf_file, num_lines, yytext); +} + diff --git a/support/sdk/c/blip/driver/radvd-1.0/gram.h b/support/sdk/c/blip/driver/radvd-1.0/gram.h new file mode 100644 index 00000000..368c1632 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/gram.h @@ -0,0 +1,160 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_INTERFACE = 258, + T_PREFIX = 259, + T_ROUTE = 260, + T_RDNSS = 261, + STRING = 262, + NUMBER = 263, + SIGNEDNUMBER = 264, + DECIMAL = 265, + SWITCH = 266, + IPV6ADDR = 267, + INFINITY = 268, + T_IgnoreIfMissing = 269, + T_AdvSendAdvert = 270, + T_MaxRtrAdvInterval = 271, + T_MinRtrAdvInterval = 272, + T_MinDelayBetweenRAs = 273, + T_AdvManagedFlag = 274, + T_AdvOtherConfigFlag = 275, + T_AdvLinkMTU = 276, + T_AdvReachableTime = 277, + T_AdvRetransTimer = 278, + T_AdvCurHopLimit = 279, + T_AdvDefaultLifetime = 280, + T_AdvDefaultPreference = 281, + T_AdvSourceLLAddress = 282, + T_AdvOnLink = 283, + T_AdvAutonomous = 284, + T_AdvValidLifetime = 285, + T_AdvPreferredLifetime = 286, + T_AdvRouterAddr = 287, + T_AdvHomeAgentFlag = 288, + T_AdvIntervalOpt = 289, + T_AdvHomeAgentInfo = 290, + T_Base6to4Interface = 291, + T_UnicastOnly = 292, + T_HomeAgentPreference = 293, + T_HomeAgentLifetime = 294, + T_AdvRoutePreference = 295, + T_AdvRouteLifetime = 296, + T_AdvRDNSSPreference = 297, + T_AdvRDNSSOpenFlag = 298, + T_AdvRDNSSLifetime = 299, + T_AdvMobRtrSupportFlag = 300, + T_BAD_TOKEN = 301 + }; +#endif +/* Tokens. */ +#define T_INTERFACE 258 +#define T_PREFIX 259 +#define T_ROUTE 260 +#define T_RDNSS 261 +#define STRING 262 +#define NUMBER 263 +#define SIGNEDNUMBER 264 +#define DECIMAL 265 +#define SWITCH 266 +#define IPV6ADDR 267 +#define INFINITY 268 +#define T_IgnoreIfMissing 269 +#define T_AdvSendAdvert 270 +#define T_MaxRtrAdvInterval 271 +#define T_MinRtrAdvInterval 272 +#define T_MinDelayBetweenRAs 273 +#define T_AdvManagedFlag 274 +#define T_AdvOtherConfigFlag 275 +#define T_AdvLinkMTU 276 +#define T_AdvReachableTime 277 +#define T_AdvRetransTimer 278 +#define T_AdvCurHopLimit 279 +#define T_AdvDefaultLifetime 280 +#define T_AdvDefaultPreference 281 +#define T_AdvSourceLLAddress 282 +#define T_AdvOnLink 283 +#define T_AdvAutonomous 284 +#define T_AdvValidLifetime 285 +#define T_AdvPreferredLifetime 286 +#define T_AdvRouterAddr 287 +#define T_AdvHomeAgentFlag 288 +#define T_AdvIntervalOpt 289 +#define T_AdvHomeAgentInfo 290 +#define T_Base6to4Interface 291 +#define T_UnicastOnly 292 +#define T_HomeAgentPreference 293 +#define T_HomeAgentLifetime 294 +#define T_AdvRoutePreference 295 +#define T_AdvRouteLifetime 296 +#define T_AdvRDNSSPreference 297 +#define T_AdvRDNSSOpenFlag 298 +#define T_AdvRDNSSLifetime 299 +#define T_AdvMobRtrSupportFlag 300 +#define T_BAD_TOKEN 301 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 110 "gram.y" +{ + unsigned int num; + int snum; + double dec; + int bool; + struct in6_addr *addr; + char *str; + struct AdvPrefix *pinfo; + struct AdvRoute *rinfo; + struct AdvRDNSS *rdnssinfo; +} +/* Line 1489 of yacc.c. */ +#line 153 "y.tab.h" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +extern YYSTYPE yylval; + diff --git a/support/sdk/c/blip/driver/radvd-1.0/gram.y b/support/sdk/c/blip/driver/radvd-1.0/gram.y new file mode 100644 index 00000000..06b7acfc --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/gram.y @@ -0,0 +1,621 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996-2000 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ +%{ +#include +#include +#include +#include + +extern struct Interface *IfaceList; +struct Interface *iface = NULL; +struct AdvPrefix *prefix = NULL; +struct AdvRoute *route = NULL; +struct AdvRDNSS *rdnss = NULL; + +extern char *conf_file; +extern int num_lines; +extern char *yytext; +extern int sock; + +static void cleanup(void); +static void yyerror(char *msg); + +#if 0 /* no longer necessary? */ +#ifndef HAVE_IN6_ADDR_S6_ADDR +# ifdef __FreeBSD__ +# define s6_addr32 __u6_addr.__u6_addr32 +# define s6_addr16 __u6_addr.__u6_addr16 +# endif +#endif +#endif + +#define ABORT do { cleanup(); YYABORT; } while (0); + +%} + +%token T_INTERFACE +%token T_PREFIX +%token T_ROUTE +%token T_RDNSS + +%token STRING +%token NUMBER +%token SIGNEDNUMBER +%token DECIMAL +%token SWITCH +%token IPV6ADDR +%token INFINITY + +%token T_IgnoreIfMissing +%token T_AdvSendAdvert +%token T_MaxRtrAdvInterval +%token T_MinRtrAdvInterval +%token T_MinDelayBetweenRAs +%token T_AdvManagedFlag +%token T_AdvOtherConfigFlag +%token T_AdvLinkMTU +%token T_AdvReachableTime +%token T_AdvRetransTimer +%token T_AdvCurHopLimit +%token T_AdvDefaultLifetime +%token T_AdvDefaultPreference +%token T_AdvSourceLLAddress + +%token T_AdvOnLink +%token T_AdvAutonomous +%token T_AdvValidLifetime +%token T_AdvPreferredLifetime + +%token T_AdvRouterAddr +%token T_AdvHomeAgentFlag +%token T_AdvIntervalOpt +%token T_AdvHomeAgentInfo + +%token T_Base6to4Interface +%token T_UnicastOnly + +%token T_HomeAgentPreference +%token T_HomeAgentLifetime + +%token T_AdvRoutePreference +%token T_AdvRouteLifetime + +%token T_AdvRDNSSPreference +%token T_AdvRDNSSOpenFlag +%token T_AdvRDNSSLifetime + +%token T_AdvMobRtrSupportFlag + +%token T_BAD_TOKEN + +%type name +%type optional_prefixlist prefixdef prefixlist +%type optional_routelist routedef routelist +%type optional_rdnsslist rdnssdef rdnsslist +%type number_or_infinity + +%union { + unsigned int num; + int snum; + double dec; + int bool; + struct in6_addr *addr; + char *str; + struct AdvPrefix *pinfo; + struct AdvRoute *rinfo; + struct AdvRDNSS *rdnssinfo; +}; + +%% + +grammar : grammar ifacedef + | ifacedef + ; + +ifacedef : ifacehead '{' ifaceparams '}' ';' + { + struct Interface *iface2; + + iface2 = IfaceList; + while (iface2) + { + if (!strcmp(iface2->Name, iface->Name)) + { + flog(LOG_ERR, "duplicate interface " + "definition for %s", iface->Name); + ABORT; + } + iface2 = iface2->next; + } + + if (check_device(sock, iface) < 0) { + if (iface->IgnoreIfMissing) { + dlog(LOG_DEBUG, 4, "interface %s did not exist, ignoring the interface", iface->Name); + goto skip_interface; + } + else { + flog(LOG_ERR, "interface %s does not exist", iface->Name); + ABORT; + } + } + if (setup_deviceinfo(sock, iface) < 0) + ABORT; + if (check_iface(iface) < 0) + ABORT; + if (setup_linklocal_addr(sock, iface) < 0) + ABORT; + if (setup_allrouters_membership(sock, iface) < 0) + ABORT; + + iface->next = IfaceList; + IfaceList = iface; + + dlog(LOG_DEBUG, 4, "interface definition for %s is ok", iface->Name); + +skip_interface: + iface = NULL; + }; + +ifacehead : T_INTERFACE name + { + iface = malloc(sizeof(struct Interface)); + + if (iface == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + iface_init_defaults(iface); + strncpy(iface->Name, $2, IFNAMSIZ-1); + iface->Name[IFNAMSIZ-1] = '\0'; + } + ; + +name : STRING + { + /* check vality */ + $$ = $1; + } + ; + +ifaceparams : optional_ifacevlist optional_prefixlist optional_routelist optional_rdnsslist + { + iface->AdvPrefixList = $2; + iface->AdvRouteList = $3; + iface->AdvRDNSSList = $4; + } + ; + +optional_ifacevlist: /* empty */ + | ifacevlist + ; + +optional_prefixlist: /* empty */ + { + $$ = NULL; + } + | prefixlist + ; + +optional_routelist: /* empty */ + { + $$ = NULL; + } + | routelist + ; + +optional_rdnsslist: /* empty */ + { + $$ = NULL; + } + | rdnsslist + ; + +ifacevlist : ifacevlist ifaceval + | ifaceval + ; + +ifaceval : T_MinRtrAdvInterval NUMBER ';' + { + iface->MinRtrAdvInterval = $2; + } + | T_MaxRtrAdvInterval NUMBER ';' + { + iface->MaxRtrAdvInterval = $2; + } + | T_MinDelayBetweenRAs NUMBER ';' + { + iface->MinDelayBetweenRAs = $2; + } + | T_MinRtrAdvInterval DECIMAL ';' + { + iface->MinRtrAdvInterval = $2; + } + | T_MaxRtrAdvInterval DECIMAL ';' + { + iface->MaxRtrAdvInterval = $2; + } + | T_MinDelayBetweenRAs DECIMAL ';' + { + iface->MinDelayBetweenRAs = $2; + } + | T_IgnoreIfMissing SWITCH ';' + { + iface->IgnoreIfMissing = $2; + } + | T_AdvSendAdvert SWITCH ';' + { + iface->AdvSendAdvert = $2; + } + | T_AdvManagedFlag SWITCH ';' + { + iface->AdvManagedFlag = $2; + } + | T_AdvOtherConfigFlag SWITCH ';' + { + iface->AdvOtherConfigFlag = $2; + } + | T_AdvLinkMTU NUMBER ';' + { + iface->AdvLinkMTU = $2; + } + | T_AdvReachableTime NUMBER ';' + { + iface->AdvReachableTime = $2; + } + | T_AdvRetransTimer NUMBER ';' + { + iface->AdvRetransTimer = $2; + } + | T_AdvDefaultLifetime NUMBER ';' + { + iface->AdvDefaultLifetime = $2; + } + | T_AdvDefaultPreference SIGNEDNUMBER ';' + { + iface->AdvDefaultPreference = $2; + } + | T_AdvCurHopLimit NUMBER ';' + { + iface->AdvCurHopLimit = $2; + } + | T_AdvSourceLLAddress SWITCH ';' + { + iface->AdvSourceLLAddress = $2; + } + | T_AdvIntervalOpt SWITCH ';' + { + iface->AdvIntervalOpt = $2; + } + | T_AdvHomeAgentInfo SWITCH ';' + { + iface->AdvHomeAgentInfo = $2; + } + | T_AdvHomeAgentFlag SWITCH ';' + { + iface->AdvHomeAgentFlag = $2; + } + | T_HomeAgentPreference NUMBER ';' + { + iface->HomeAgentPreference = $2; + } + | T_HomeAgentLifetime NUMBER ';' + { + iface->HomeAgentLifetime = $2; + } + | T_UnicastOnly SWITCH ';' + { + iface->UnicastOnly = $2; + } + | T_AdvMobRtrSupportFlag SWITCH ';' + { + iface->AdvMobRtrSupportFlag = $2; + } + ; + +prefixlist : prefixdef + { + $$ = $1; + } + | prefixlist prefixdef + { + $2->next = $1; + $$ = $2; + } + ; + +prefixdef : prefixhead '{' optional_prefixplist '}' ';' + { + unsigned int dst; + + if (prefix->AdvPreferredLifetime > + prefix->AdvValidLifetime) + { + flog(LOG_ERR, "AdvValidLifeTime must be " + "greater than AdvPreferredLifetime in %s, line %d", + conf_file, num_lines); + ABORT; + } + + if( prefix->if6to4[0] ) + { + if (get_v4addr(prefix->if6to4, &dst) < 0) + { + flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 ); + prefix->enabled = 0; + } else + { + *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002); + memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) ); + } + } + + $$ = prefix; + prefix = NULL; + } + ; + +prefixhead : T_PREFIX IPV6ADDR '/' NUMBER + { + prefix = malloc(sizeof(struct AdvPrefix)); + + if (prefix == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + prefix_init_defaults(prefix); + + if ($4 > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid prefix length in %s, line %d", conf_file, num_lines); + ABORT; + } + + prefix->PrefixLen = $4; + + memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr)); + } + ; + +optional_prefixplist: /* empty */ + | prefixplist + ; + +prefixplist : prefixplist prefixparms + | prefixparms + ; + +prefixparms : T_AdvOnLink SWITCH ';' + { + prefix->AdvOnLinkFlag = $2; + } + | T_AdvAutonomous SWITCH ';' + { + prefix->AdvAutonomousFlag = $2; + } + | T_AdvRouterAddr SWITCH ';' + { + prefix->AdvRouterAddr = $2; + } + | T_AdvValidLifetime number_or_infinity ';' + { + prefix->AdvValidLifetime = $2; + } + | T_AdvPreferredLifetime number_or_infinity ';' + { + prefix->AdvPreferredLifetime = $2; + } + | T_Base6to4Interface name ';' + { + dlog(LOG_DEBUG, 4, "using interface %s for 6to4", $2); + strncpy(prefix->if6to4, $2, IFNAMSIZ-1); + prefix->if6to4[IFNAMSIZ-1] = '\0'; + } + ; + +routelist : routedef + { + $$ = $1; + } + | routelist routedef + { + $2->next = $1; + $$ = $2; + } + ; + +routedef : routehead '{' optional_routeplist '}' ';' + { + $$ = route; + route = NULL; + } + ; + + +routehead : T_ROUTE IPV6ADDR '/' NUMBER + { + route = malloc(sizeof(struct AdvRoute)); + + if (route == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + route_init_defaults(route, iface); + + if ($4 > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid route prefix length in %s, line %d", conf_file, num_lines); + ABORT; + } + + route->PrefixLen = $4; + + memcpy(&route->Prefix, $2, sizeof(struct in6_addr)); + } + ; + + +optional_routeplist: /* empty */ + | routeplist + ; + +routeplist : routeplist routeparms + | routeparms + ; + + +routeparms : T_AdvRoutePreference SIGNEDNUMBER ';' + { + route->AdvRoutePreference = $2; + } + | T_AdvRouteLifetime number_or_infinity ';' + { + route->AdvRouteLifetime = $2; + } + ; + +rdnsslist : rdnssdef + { + $$ = $1; + } + | rdnsslist rdnssdef + { + $2->next = $1; + $$ = $2; + } + ; + +rdnssdef : rdnsshead '{' optional_rdnssplist '}' ';' + { + $$ = rdnss; + rdnss = NULL; + } + ; + +rdnssaddrs : rdnssaddrs rdnssaddr + | rdnssaddr + ; + +rdnssaddr : IPV6ADDR + { + if (!rdnss) { + /* first IP found */ + rdnss = malloc(sizeof(struct AdvRDNSS)); + + if (rdnss == NULL) { + flog(LOG_CRIT, "malloc failed: %s", strerror(errno)); + ABORT; + } + + rdnss_init_defaults(rdnss, iface); + } + + switch (rdnss->AdvRDNSSNumber) { + case 0: + memcpy(&rdnss->AdvRDNSSAddr1, $1, sizeof(struct in6_addr)); + rdnss->AdvRDNSSNumber++; + break; + case 1: + memcpy(&rdnss->AdvRDNSSAddr2, $1, sizeof(struct in6_addr)); + rdnss->AdvRDNSSNumber++; + break; + case 2: + memcpy(&rdnss->AdvRDNSSAddr3, $1, sizeof(struct in6_addr)); + rdnss->AdvRDNSSNumber++; + break; + default: + flog(LOG_CRIT, "Too many addresses in RDNSS section"); + ABORT; + } + + } + ; + +rdnsshead : T_RDNSS rdnssaddrs + { + if (!rdnss) { + flog(LOG_CRIT, "No address specified in RDNSS section"); + ABORT; + } + } + ; + +optional_rdnssplist: /* empty */ + | rdnssplist + ; + +rdnssplist : rdnssplist rdnssparms + | rdnssparms + ; + + +rdnssparms : T_AdvRDNSSPreference NUMBER ';' + { + rdnss->AdvRDNSSPreference = $2; + } + | T_AdvRDNSSOpenFlag SWITCH ';' + { + rdnss->AdvRDNSSOpenFlag = $2; + } + | T_AdvRDNSSLifetime number_or_infinity ';' + { + if ($2 < iface->MaxRtrAdvInterval && $2 != 0) { + flog(LOG_ERR, "AdvRDNSSLifetime must be at least MaxRtrAdvInterval"); + ABORT; + } + if ($2 > 2*(iface->MaxRtrAdvInterval)) + flog(LOG_WARNING, "Warning: AdvRDNSSLifetime <= 2*MaxRtrAdvInterval would allow stale DNS servers to be deleted faster"); + + rdnss->AdvRDNSSLifetime = $2; + } + ; + +number_or_infinity : NUMBER + { + $$ = $1; + } + | INFINITY + { + $$ = (uint32_t)~0; + } + ; + +%% + +static +void cleanup(void) +{ + if (iface) + free(iface); + + if (prefix) + free(prefix); + + if (route) + free(route); + + if (rdnss) + free(rdnss); +} + +static void +yyerror(char *msg) +{ + cleanup(); + flog(LOG_ERR, "%s in %s, line %d: %s", msg, conf_file, num_lines, yytext); +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/includes.h b/support/sdk/c/blip/driver/radvd-1.0/includes.h new file mode 100644 index 00000000..83845803 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/includes.h @@ -0,0 +1,98 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#ifndef INCLUDES_H +#define INCLUDES_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef HAVE_INTTYPES_H +# include +#endif + +#ifdef HAVE_SYS_PARAM_H +# include +#else +# ifdef HAVE_MACHINE_PARAM_H +# include +# endif +# ifdef HAVE_MACHINE_LIMITS_H +# include +# endif +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include + +#include + +#ifdef HAVE_NET_IF_DL_H +# include +#endif +#ifdef HAVE_NET_IF_TYPES_H +# include +#endif +#if defined(HAVE_NET_IF_ARP_H) && !defined(ARPHRD_ETHER) +# include +#endif /* defined(HAVE_NET_IF_ARP_H) && !defined(ARPHRD_ETHER) */ + +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif + +#ifdef HAVE_GETOPT_H +# include +#endif + +#endif /* INCLUDES_H */ diff --git a/support/sdk/c/blip/driver/radvd-1.0/install-sh b/support/sdk/c/blip/driver/radvd-1.0/install-sh new file mode 100755 index 00000000..e9de2384 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/support/sdk/c/blip/driver/radvd-1.0/interface.c b/support/sdk/c/blip/driver/radvd-1.0/interface.c new file mode 100644 index 00000000..923b7d09 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/interface.c @@ -0,0 +1,248 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include +#include + +void +iface_init_defaults(struct Interface *iface) +{ + memset(iface, 0, sizeof(struct Interface)); + + iface->HasFailed = 0; + iface->IgnoreIfMissing = DFLT_IgnoreIfMissing; + iface->AdvSendAdvert = DFLT_AdvSendAdv; + iface->MaxRtrAdvInterval = DFLT_MaxRtrAdvInterval; + iface->AdvSourceLLAddress = DFLT_AdvSourceLLAddress; + iface->AdvReachableTime = DFLT_AdvReachableTime; + iface->AdvRetransTimer = DFLT_AdvRetransTimer; + iface->AdvLinkMTU = DFLT_AdvLinkMTU; + iface->AdvCurHopLimit = DFLT_AdvCurHopLimit; + iface->AdvIntervalOpt = DFLT_AdvIntervalOpt; + iface->AdvHomeAgentInfo = DFLT_AdvHomeAgentInfo; + iface->AdvHomeAgentFlag = DFLT_AdvHomeAgentFlag; + iface->HomeAgentPreference = DFLT_HomeAgentPreference; + iface->MinDelayBetweenRAs = DFLT_MinDelayBetweenRAs; + iface->AdvMobRtrSupportFlag = DFLT_AdvMobRtrSupportFlag; + + iface->MinRtrAdvInterval = -1; + iface->AdvDefaultLifetime = -1; + iface->AdvDefaultPreference = DFLT_AdvDefaultPreference; + iface->HomeAgentLifetime = -1; +} + +void +prefix_init_defaults(struct AdvPrefix *prefix) +{ + memset(prefix, 0, sizeof(struct AdvPrefix)); + + prefix->AdvOnLinkFlag = DFLT_AdvOnLinkFlag; + prefix->AdvAutonomousFlag = DFLT_AdvAutonomousFlag; + prefix->AdvRouterAddr = DFLT_AdvRouterAddr; + prefix->AdvValidLifetime = DFLT_AdvValidLifetime; + prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime; + prefix->if6to4[0] = 0; + prefix->enabled = 1; +} + +void +route_init_defaults(struct AdvRoute *route, struct Interface *iface) +{ + memset(route, 0, sizeof(struct AdvRoute)); + + route->AdvRouteLifetime = DFLT_AdvRouteLifetime(iface); + route->AdvRoutePreference = DFLT_AdvRoutePreference; +} + +void +rdnss_init_defaults(struct AdvRDNSS *rdnss, struct Interface *iface) +{ + memset(rdnss, 0, sizeof(struct AdvRDNSS)); + + rdnss->AdvRDNSSPreference = DFLT_AdvRDNSSPreference; + rdnss->AdvRDNSSOpenFlag = DFLT_AdvRDNSSOpenFlag; + rdnss->AdvRDNSSLifetime = DFLT_AdvRDNSSLifetime(iface); + rdnss->AdvRDNSSNumber = 0; +} + +int +check_iface(struct Interface *iface) +{ + struct AdvPrefix *prefix; + struct AdvRoute *route; + int res = 0; + int MIPv6 = 0; + + /* Check if we use Mobile IPv6 extensions */ + if (iface->AdvHomeAgentFlag || iface->AdvHomeAgentInfo || + iface->AdvIntervalOpt) + { + MIPv6 = 1; + flog(LOG_INFO, "using Mobile IPv6 extensions"); + } + + prefix = iface->AdvPrefixList; + while (!MIPv6 && prefix) + { + if (prefix->AdvRouterAddr) + { + MIPv6 = 1; + } + prefix = prefix->next; + } + + if (iface->MinRtrAdvInterval < 0) + iface->MinRtrAdvInterval = DFLT_MinRtrAdvInterval(iface); + + if ((iface->MinRtrAdvInterval < (MIPv6 ? MIN_MinRtrAdvInterval_MIPv6 : MIN_MinRtrAdvInterval)) || + (iface->MinRtrAdvInterval > MAX_MinRtrAdvInterval(iface))) + { + flog(LOG_ERR, + "MinRtrAdvInterval for %s (%.2f) must be at least %.2f but no more than 3/4 of MaxRtrAdvInterval (%.2f)", + iface->Name, iface->MinRtrAdvInterval, + MIPv6 ? MIN_MinRtrAdvInterval_MIPv6 : (int)MIN_MinRtrAdvInterval, + MAX_MinRtrAdvInterval(iface)); + res = -1; + } + + if ((iface->MaxRtrAdvInterval < (MIPv6 ? MIN_MaxRtrAdvInterval_MIPv6 : MIN_MaxRtrAdvInterval)) + || (iface->MaxRtrAdvInterval > MAX_MaxRtrAdvInterval)) + { + flog(LOG_ERR, + "MaxRtrAdvInterval for %s (%.2f) must be between %.2f and %d", + iface->Name, iface->MaxRtrAdvInterval, + MIPv6 ? MIN_MaxRtrAdvInterval_MIPv6 : (int)MIN_MaxRtrAdvInterval, + MAX_MaxRtrAdvInterval); + res = -1; + } + + if (iface->MinDelayBetweenRAs < (MIPv6 ? MIN_DELAY_BETWEEN_RAS_MIPv6 : MIN_DELAY_BETWEEN_RAS)) + { + flog(LOG_ERR, + "MinDelayBetweenRAs for %s (%.2f) must be at least %.2f", + iface->Name, iface->MinDelayBetweenRAs, + MIPv6 ? MIN_DELAY_BETWEEN_RAS_MIPv6 : MIN_DELAY_BETWEEN_RAS); + res = -1; + } + + if ((iface->AdvLinkMTU != 0) && + ((iface->AdvLinkMTU < MIN_AdvLinkMTU) || + (iface->if_maxmtu != -1 && (iface->AdvLinkMTU > iface->if_maxmtu)))) + { + flog(LOG_ERR, "AdvLinkMTU for %s (%u) must be zero or between %u and %u", + iface->Name, iface->AdvLinkMTU, MIN_AdvLinkMTU, iface->if_maxmtu); + res = -1; + } + + if (iface->AdvReachableTime > MAX_AdvReachableTime) + { + flog(LOG_ERR, + "AdvReachableTime for %s (%u) must not be greater than %u", + iface->Name, iface->AdvReachableTime, MAX_AdvReachableTime); + res = -1; + } + + if (iface->AdvCurHopLimit > MAX_AdvCurHopLimit) + { + flog(LOG_ERR, "AdvCurHopLimit for %s (%u) must not be greater than %u", + iface->Name, iface->AdvCurHopLimit, MAX_AdvCurHopLimit); + res = -1; + } + + if (iface->AdvDefaultLifetime < 0) + iface->AdvDefaultLifetime = DFLT_AdvDefaultLifetime(iface); + + if ((iface->AdvDefaultLifetime != 0) && + ((iface->AdvDefaultLifetime > MAX_AdvDefaultLifetime) || + (iface->AdvDefaultLifetime < MIN_AdvDefaultLifetime(iface)))) + { + flog(LOG_ERR, + "AdvDefaultLifetime for %s (%u) must be zero or between %u and %u", + iface->Name, iface->AdvDefaultLifetime, (int)MIN_AdvDefaultLifetime(iface), + MAX_AdvDefaultLifetime); + res = -1; + } + + /* Mobile IPv6 ext */ + if (iface->HomeAgentLifetime < 0) + iface->HomeAgentLifetime = DFLT_HomeAgentLifetime(iface); + + /* Mobile IPv6 ext */ + if (iface->AdvHomeAgentInfo) + { + if ((iface->HomeAgentLifetime > MAX_HomeAgentLifetime) || + (iface->HomeAgentLifetime < MIN_HomeAgentLifetime)) + { + flog(LOG_ERR, + "HomeAgentLifetime for %s (%u) must be between %u and %u", + iface->Name, iface->HomeAgentLifetime, + MIN_HomeAgentLifetime, MAX_HomeAgentLifetime); + res = -1; + } + } + + /* Mobile IPv6 ext */ + if (iface->AdvHomeAgentInfo && !(iface->AdvHomeAgentFlag)) + { + flog(LOG_ERR, + "AdvHomeAgentFlag for %s must be set with HomeAgentInfo", iface->Name); + res = -1; + } + if (iface->AdvMobRtrSupportFlag && !(iface->AdvHomeAgentInfo)) + { + flog(LOG_ERR, + "AdvHomeAgentInfo for %s must be set with AdvMobRtrSupportFlag", iface->Name); + res = -1; + } + + /* XXX: need this? prefix = iface->AdvPrefixList; */ + + while (prefix) + { + if (prefix->PrefixLen > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid prefix length (%u) for %s", prefix->PrefixLen, iface->Name); + res = -1; + } + + if (prefix->AdvPreferredLifetime > prefix->AdvValidLifetime) + { + flog(LOG_ERR, "AdvValidLifetime for %s (%u) must be " + "greater than AdvPreferredLifetime for", + iface->Name, prefix->AdvValidLifetime); + res = -1; + } + + prefix = prefix->next; + } + + + route = iface->AdvRouteList; + + while(route) + { + if (route->PrefixLen > MAX_PrefixLen) + { + flog(LOG_ERR, "invalid route prefix length (%u) for %s", route->PrefixLen, iface->Name); + res = -1; + } + + route = route->next; + } + + return res; +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/log.c b/support/sdk/c/blip/driver/radvd-1.0/log.c new file mode 100644 index 00000000..e64dfec3 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/log.c @@ -0,0 +1,182 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file + * COPYRIGHT applies to this software. If your distribution is missing + * this file, you may request it from . + * + */ + +#include +#include +#include + +static int log_method = L_NONE; +static char *log_ident; +static char *log_file; +static FILE *log_file_fd; +static int log_facility; +static int debug_level = 0; + +int +log_open(int method, char *ident, char *log, int facility) +{ + log_method = method; + log_ident = ident; + + switch (log_method) { + case L_NONE: + case L_STDERR: + break; + case L_STDERR_SYSLOG: + /* fallthrough */ + case L_SYSLOG: + if (facility == -1) + log_facility = LOG_DAEMON; + else + log_facility = facility; + + openlog(log_ident, LOG_PID, log_facility); + break; + case L_LOGFILE: + if (!log) + { + fprintf(stderr, "%s: no logfile specified\n", log_ident); + return (-1); + } + log_file = log; + if ((log_file_fd = fopen(log_file, "a")) == NULL) + { + fprintf(stderr, "%s: can't open %s: %s\n", log_ident, log_file, strerror(errno)); + return (-1); + } + break; + default: + fprintf(stderr, "%s: unknown logging method: %d\n", log_ident, log_method); + log_method = L_NONE; + return (-1); + } + return 0; +} + +static int +vlog(int prio, char *format, va_list ap) +{ + char tstamp[64], buff[1024]; + struct tm *tm; + time_t current; + + switch (log_method) { + case L_NONE: + break; + case L_SYSLOG: + vsnprintf(buff, sizeof(buff), format, ap); + syslog(prio, "%s", buff); + break; + case L_STDERR_SYSLOG: + vsnprintf(buff, sizeof(buff), format, ap); + syslog(prio, "%s", buff); + if (prio > LOG_ERR) /* fall through for messages with high priority */ + break; + case L_STDERR: + current = time(NULL); + tm = localtime(¤t); + (void) strftime(tstamp, sizeof(tstamp), LOG_TIME_FORMAT, tm); + + fprintf(stderr, "[%s] %s: ", tstamp, log_ident); + vfprintf(stderr, format, ap); + fputs("\n", stderr); + fflush(stderr); + break; + case L_LOGFILE: + current = time(NULL); + tm = localtime(¤t); + (void) strftime(tstamp, sizeof(tstamp), LOG_TIME_FORMAT, tm); + + fprintf(log_file_fd, "[%s] %s: ", tstamp, log_ident); + vfprintf(log_file_fd, format, ap); + fputs("\n", log_file_fd); + fflush(log_file_fd); + break; + default: + fprintf(stderr, "%s: unknown logging method: %d\n", log_ident, log_method); + log_method = L_NONE; + return (-1); + } + return 0; +} + +void +dlog(int prio, int level, char *format, ...) +{ + va_list ap; + int res; + + if (debug_level < level) + return; + + va_start(ap, format); + res = vlog(prio, format, ap); + va_end(ap); + + /* XXX: should we do something if res < 0.. */ +} + +void +flog(int prio, char *format, ...) +{ + va_list ap; + int res; + + va_start(ap, format); + res = vlog(prio, format, ap); + va_end(ap); + + /* XXX: should we do something if res < 0.. */ +} + +int +log_close(void) +{ + switch (log_method) { + case L_NONE: + case L_STDERR: + break; + case L_SYSLOG: + closelog(); + break; + case L_LOGFILE: + fclose(log_file_fd); + break; + default: + fprintf(stderr, "%s: unknown logging method: %d\n", log_ident, log_method); + log_method = L_NONE; + return (-1); + } + return 0; +} + +int +log_reopen(void) +{ + log_close(); + return log_open(log_method, log_ident, log_file, log_facility); +} + +void +set_debuglevel(int level) +{ + debug_level = level; +} + +int +get_debuglevel(void) +{ + return debug_level; +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/missing b/support/sdk/c/blip/driver/radvd-1.0/missing new file mode 100755 index 00000000..fc54c64e --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/missing @@ -0,0 +1,336 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.4 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/support/sdk/c/blip/driver/radvd-1.0/mkinstalldirs b/support/sdk/c/blip/driver/radvd-1.0/mkinstalldirs new file mode 100755 index 00000000..6b3b5fc5 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/support/sdk/c/blip/driver/radvd-1.0/pathnames.h b/support/sdk/c/blip/driver/radvd-1.0/pathnames.h new file mode 100644 index 00000000..c061455e --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/pathnames.h @@ -0,0 +1,48 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#ifndef PATHNAMES_H +#define PATHNAMES_H + +#ifndef PATH_RADVD_CONF +#define PATH_RADVD_CONF "/etc/radvd.conf" +#endif + +#ifndef PATH_RADVD_PID +#define PATH_RADVD_PID "/var/run/radvd.pid" +#endif + +#ifndef PATH_RADVD_LOG +#define PATH_RADVD_LOG "/var/log/radvd.log" +#endif + +#define PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6" +#define PATH_PROC_NET_IGMP6 "/proc/net/igmp6" + +#ifdef __linux__ +#define SYSCTL_IP6_FORWARDING CTL_NET, NET_IPV6, NET_IPV6_CONF, NET_PROTO_CONF_ALL, NET_IPV6_FORWARDING +#define PROC_SYS_IP6_FORWARDING "/proc/sys/net/ipv6/conf/all/forwarding" +#define PROC_SYS_IP6_LINKMTU "/proc/sys/net/ipv6/conf/%s/mtu" +#define PROC_SYS_IP6_CURHLIM "/proc/sys/net/ipv6/conf/%s/hop_limit" +#define PROC_SYS_IP6_BASEREACHTIME_MS "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms" +#define PROC_SYS_IP6_BASEREACHTIME "/proc/sys/net/ipv6/neigh/%s/base_reachable_time" +#define PROC_SYS_IP6_RETRANSTIMER_MS "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms" +#define PROC_SYS_IP6_RETRANSTIMER "/proc/sys/net/ipv6/neigh/%s/retrans_time" +#else /* BSD */ +#define SYSCTL_IP6_FORWARDING CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_FORWARDING +#endif + +#endif diff --git a/support/sdk/c/blip/driver/radvd-1.0/process.c b/support/sdk/c/blip/driver/radvd-1.0/process.c new file mode 100644 index 00000000..bcd9589c --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/process.c @@ -0,0 +1,454 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +static void process_rs(int, struct Interface *, unsigned char *msg, + int len, struct sockaddr_in6 *); +static void process_ra(struct Interface *, unsigned char *msg, int len, + struct sockaddr_in6 *); +static int addr_match(struct in6_addr *a1, struct in6_addr *a2, + int prefixlen); + +void +process(int sock, struct Interface *ifacel, unsigned char *msg, int len, + struct sockaddr_in6 *addr, struct in6_pktinfo *pkt_info, int hoplimit) +{ + struct Interface *iface; + struct icmp6_hdr *icmph; + char addr_str[INET6_ADDRSTRLEN]; + + if ( ! pkt_info ) + { + flog(LOG_WARNING, "received packet with no pkt_info!" ); + return; + } + + /* + * can this happen? + */ + + if (len < sizeof(struct icmp6_hdr)) + { + flog(LOG_WARNING, "received icmpv6 packet with invalid length: %d", + len); + return; + } + + icmph = (struct icmp6_hdr *) msg; + + if (icmph->icmp6_type != ND_ROUTER_SOLICIT && + icmph->icmp6_type != ND_ROUTER_ADVERT) + { + /* + * We just want to listen to RSs and RAs + */ + + flog(LOG_ERR, "icmpv6 filter failed"); + return; + } + + if (icmph->icmp6_type == ND_ROUTER_ADVERT) + { + if (len < sizeof(struct nd_router_advert)) { + flog(LOG_WARNING, "received icmpv6 RA packet with invalid length: %d", + len); + return; + } + + if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { + flog(LOG_WARNING, "received icmpv6 RA packet with non-linklocal source address"); + return; + } + } + + if (icmph->icmp6_type == ND_ROUTER_SOLICIT) + { + if (len < sizeof(struct nd_router_solicit)) { + flog(LOG_WARNING, "received icmpv6 RS packet with invalid length: %d", + len); + return; + } + } + + if (icmph->icmp6_code != 0) + { + flog(LOG_WARNING, "received icmpv6 RS/RA packet with invalid code: %d", + icmph->icmp6_code); + return; + } + + dlog(LOG_DEBUG, 4, "if_index %u", pkt_info->ipi6_ifindex); + + /* get iface by received if_index */ + + for (iface = ifacel; iface; iface=iface->next) + { + if (iface->if_index == pkt_info->ipi6_ifindex) + { + break; + } + } + + if (iface == NULL) + { + dlog(LOG_DEBUG, 2, "received packet from unknown interface: %d", + pkt_info->ipi6_ifindex); + return; + } + + if (hoplimit != 255) + { + print_addr(&addr->sin6_addr, addr_str); + flog(LOG_WARNING, "received RS or RA with invalid hoplimit %d from %s", + hoplimit, addr_str); + return; + } + + if (!iface->AdvSendAdvert) + { + dlog(LOG_DEBUG, 2, "AdvSendAdvert is off for %s", iface->Name); + return; + } + + dlog(LOG_DEBUG, 4, "found Interface: %s", iface->Name); + + if (icmph->icmp6_type == ND_ROUTER_SOLICIT) + { + process_rs(sock, iface, msg, len, addr); + } + else if (icmph->icmp6_type == ND_ROUTER_ADVERT) + { + process_ra(iface, msg, len, addr); + } +} + +static void +process_rs(int sock, struct Interface *iface, unsigned char *msg, int len, + struct sockaddr_in6 *addr) +{ + double delay; + double next; + struct timeval tv; + uint8_t *opt_str; + + /* validation */ + len -= sizeof(struct nd_router_solicit); + + opt_str = (uint8_t *)(msg + sizeof(struct nd_router_solicit)); + + while (len > 0) + { + int optlen; + + if (len < 2) + { + flog(LOG_WARNING, "trailing garbage in RS"); + return; + } + + optlen = (opt_str[1] << 3); + + if (optlen == 0) + { + flog(LOG_WARNING, "zero length option in RS"); + return; + } + else if (optlen > len) + { + flog(LOG_WARNING, "option length greater than total length in RS"); + return; + } + + if (*opt_str == ND_OPT_SOURCE_LINKADDR && + IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) { + flog(LOG_WARNING, "received icmpv6 RS packet with unspecified source address and there is a lladdr option"); + return; + } + + len -= optlen; + opt_str += optlen; + } + + gettimeofday(&tv, NULL); + + delay = MAX_RA_DELAY_TIME*rand()/(RAND_MAX+1.0); + dlog(LOG_DEBUG, 3, "random mdelay for %s: %.2f", iface->Name, delay); + + if (iface->UnicastOnly) { + mdelay(delay); + send_ra(sock, iface, &addr->sin6_addr); + } + else if ((tv.tv_sec + tv.tv_usec / 1000000.0) - (iface->last_multicast_sec + + iface->last_multicast_usec / 1000000.0) < iface->MinDelayBetweenRAs) { + /* last RA was sent only a few moments ago, don't send another immediately */ + clear_timer(&iface->tm); + next = iface->MinDelayBetweenRAs - (tv.tv_sec + tv.tv_usec / 1000000.0) + + (iface->last_multicast_sec + iface->last_multicast_usec / 1000000.0) + delay/1000.0; + set_timer(&iface->tm, next); + } + else { + /* no RA sent in a while, send an immediate multicast reply */ + clear_timer(&iface->tm); + send_ra(sock, iface, NULL); + + next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval); + set_timer(&iface->tm, next); + } +} + +/* + * check router advertisements according to RFC 2461, 6.2.7 + */ +static void +process_ra(struct Interface *iface, unsigned char *msg, int len, + struct sockaddr_in6 *addr) +{ + struct nd_router_advert *radvert; + char addr_str[INET6_ADDRSTRLEN]; + uint8_t *opt_str; + + print_addr(&addr->sin6_addr, addr_str); + + radvert = (struct nd_router_advert *) msg; + + if ((radvert->nd_ra_curhoplimit && iface->AdvCurHopLimit) && + (radvert->nd_ra_curhoplimit != iface->AdvCurHopLimit)) + { + flog(LOG_WARNING, "our AdvCurHopLimit on %s doesn't agree with %s", + iface->Name, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && !iface->AdvManagedFlag) + { + flog(LOG_WARNING, "our AdvManagedFlag on %s doesn't agree with %s", + iface->Name, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && !iface->AdvOtherConfigFlag) + { + flog(LOG_WARNING, "our AdvOtherConfigFlag on %s doesn't agree with %s", + iface->Name, addr_str); + } + + /* note: we don't check the default router preference here, because they're likely different */ + + if ((radvert->nd_ra_reachable && iface->AdvReachableTime) && + (ntohl(radvert->nd_ra_reachable) != iface->AdvReachableTime)) + { + flog(LOG_WARNING, "our AdvReachableTime on %s doesn't agree with %s", + iface->Name, addr_str); + } + + if ((radvert->nd_ra_retransmit && iface->AdvRetransTimer) && + (ntohl(radvert->nd_ra_retransmit) != iface->AdvRetransTimer)) + { + flog(LOG_WARNING, "our AdvRetransTimer on %s doesn't agree with %s", + iface->Name, addr_str); + } + + len -= sizeof(struct nd_router_advert); + + if (len == 0) + return; + + opt_str = (uint8_t *)(msg + sizeof(struct nd_router_advert)); + + while (len > 0) + { + int optlen; + struct nd_opt_prefix_info *pinfo; + struct nd_opt_rdnss_info_local *rdnssinfo; + struct nd_opt_mtu *mtu; + struct AdvPrefix *prefix; + struct AdvRDNSS *rdnss; + char prefix_str[INET6_ADDRSTRLEN]; + char rdnss_str[INET6_ADDRSTRLEN]; + uint32_t preferred, valid, count; + + if (len < 2) + { + flog(LOG_ERR, "trailing garbage in RA on %s from %s", + iface->Name, addr_str); + break; + } + + optlen = (opt_str[1] << 3); + + if (optlen == 0) + { + flog(LOG_ERR, "zero length option in RA on %s from %s", + iface->Name, addr_str); + break; + } + else if (optlen > len) + { + flog(LOG_ERR, "option length greater than total" + " length in RA on %s from %s", + iface->Name, addr_str); + break; + } + + switch (*opt_str) + { + case ND_OPT_MTU: + mtu = (struct nd_opt_mtu *)opt_str; + + if (iface->AdvLinkMTU && (ntohl(mtu->nd_opt_mtu_mtu) != iface->AdvLinkMTU)) + { + flog(LOG_WARNING, "our AdvLinkMTU on %s doesn't agree with %s", + iface->Name, addr_str); + } + break; + case ND_OPT_PREFIX_INFORMATION: + pinfo = (struct nd_opt_prefix_info *) opt_str; + preferred = ntohl(pinfo->nd_opt_pi_preferred_time); + valid = ntohl(pinfo->nd_opt_pi_valid_time); + + prefix = iface->AdvPrefixList; + while (prefix) + { + if (prefix->enabled && + (prefix->PrefixLen == pinfo->nd_opt_pi_prefix_len) && + addr_match(&prefix->Prefix, &pinfo->nd_opt_pi_prefix, + prefix->PrefixLen)) + { + print_addr(&prefix->Prefix, prefix_str); + + if (valid != prefix->AdvValidLifetime) + { + flog(LOG_WARNING, "our AdvValidLifetime on" + " %s for %s doesn't agree with %s", + iface->Name, + prefix_str, + addr_str + ); + } + if (preferred != prefix->AdvPreferredLifetime) + { + flog(LOG_WARNING, "our AdvPreferredLifetime on" + " %s for %s doesn't agree with %s", + iface->Name, + prefix_str, + addr_str + ); + } + } + + prefix = prefix->next; + } + break; + case ND_OPT_ROUTE_INFORMATION: + /* not checked: these will very likely vary a lot */ + break; + case ND_OPT_SOURCE_LINKADDR: + /* not checked */ + break; + case ND_OPT_TARGET_LINKADDR: + case ND_OPT_REDIRECTED_HEADER: + flog(LOG_ERR, "invalid option %d in RA on %s from %s", + (int)*opt_str, iface->Name, addr_str); + break; + /* Mobile IPv6 extensions */ + case ND_OPT_RTR_ADV_INTERVAL: + case ND_OPT_HOME_AGENT_INFO: + /* not checked */ + break; + case ND_OPT_RDNSS_INFORMATION: + rdnssinfo = (struct nd_opt_rdnss_info_local *) opt_str; + count = rdnssinfo->nd_opt_rdnssi_len; + + /* Check the RNDSS addresses received */ + switch (count) { + case 7: + rdnss = iface->AdvRDNSSList; + if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr3 )) { + /* no match found in iface->AdvRDNSSList */ + print_addr(&rdnssinfo->nd_opt_rdnssi_addr3, rdnss_str); + flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us", + rdnss_str, iface->Name, addr_str); + } + /* FALLTHROUGH */ + case 5: + rdnss = iface->AdvRDNSSList; + if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr2 )) { + /* no match found in iface->AdvRDNSSList */ + print_addr(&rdnssinfo->nd_opt_rdnssi_addr2, rdnss_str); + flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us", + rdnss_str, iface->Name, addr_str); + } + /* FALLTHROUGH */ + case 3: + rdnss = iface->AdvRDNSSList; + if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr1 )) { + /* no match found in iface->AdvRDNSSList */ + print_addr(&rdnssinfo->nd_opt_rdnssi_addr1, rdnss_str); + flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us", + rdnss_str, iface->Name, addr_str); + } + + break; + default: + flog(LOG_ERR, "invalid len %i in RDNSS option on %s from %s", + count, iface->Name, addr_str); + } + + break; + default: + dlog(LOG_DEBUG, 1, "unknown option %d in RA on %s from %s", + (int)*opt_str, iface->Name, addr_str); + break; + } + + len -= optlen; + opt_str += optlen; + } +} + +static int +addr_match(struct in6_addr *a1, struct in6_addr *a2, int prefixlen) +{ + unsigned int pdw; + unsigned int pbi; + + pdw = prefixlen >> 0x05; /* num of whole uint32_t in prefix */ + pbi = prefixlen & 0x1f; /* num of bits in incomplete uint32_t in prefix */ + + if (pdw) + { + if (memcmp(a1, a2, pdw << 2)) + return 0; + } + + if (pbi) + { + uint32_t w1, w2; + uint32_t mask; + + w1 = *((uint32_t *)a1 + pdw); + w2 = *((uint32_t *)a2 + pdw); + + mask = htonl(((uint32_t) 0xffffffff) << (0x20 - pbi)); + + if ((w1 ^ w2) & mask) + return 0; + } + + return 1; +} + diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvd.8.man b/support/sdk/c/blip/driver/radvd-1.0/radvd.8.man new file mode 100644 index 00000000..5fe0e94b --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvd.8.man @@ -0,0 +1,173 @@ +.\" +.\" $Id$ +.\" +.\" Authors: +.\" Lars Fenneberg +.\" +.\" This software is Copyright 1996-2000 by the above mentioned author(s), +.\" All Rights Reserved. +.\" +.\" The license which is distributed with this software in the file COPYRIGHT +.\" applies to this software. If your distribution is missing this file, you +.\" may request it from . +.\" +.\" +.\" +.TH RADVD 8 "29 Mar 2001" "radvd @VERSION@" "" +.SH NAME +radvd \- router advertisement daemon for IPv6 +.SH SYNOPSIS +.B radvd +.B "[ \-vh ]" +.BI "[ \-d " debuglevel " ]" +.BI "[ \-C " configfile " ]" +.BI "[ \-p " pidfile " ]" +.BI "[ \-m " logmethod " ]" +.BI "[ \-l " logfile " ]" +.BI "[ \-f " facility " ]" +.BI "[ \-t " chrootdir " ]" +.BI "[ \-u " username " ]" + +.SH DESCRIPTION +.B radvd +is the router advertisement daemon for IPv6. It listens to router +solicitations and sends router advertisements as described in +"Neighbor Discovery for IP Version 6 (IPv6)" (RFC 2461). +With these advertisements hosts can automatically configure their +addresses and some other parameters. They also can choose a default +router based on these advertisements. + +Note that if debugging is not enabled, +.B radvd +will not start if IPv6 forwarding is disabled. IPv6 forwarding can be +controlled via sysctl(8), +.B net.ipv6.conf.all.forwarding +on Linux or +.B net.inet6.ip6.forwarding +on BSD. + +Similarly, the configuration file must not be writable by others, and if +non-root operation is requested, not even by self/own group. + +.SH OPTIONS + +For every one character option there is also a long option, which +is listed right next to the "short" option name: + +.TP +.BR "\-v" , " \-\-version" +Displays the version of +.I radvd +and then aborts. +.TP +.BR "\-h" , " \-\-help" +Displays a short usage description and then aborts. +.TP +.BR "\-d " debuglevel, " \-\-debug " debuglevel +With this option you turn on debugging information. The debugging level is +an integer in the range from 1 to 5, from quiet to very verbose. A +debugging level of 0 completely turns off debugging. If a debugging level +greater than 0 is used, +.I radvd +doesn't background itself on start. The default debugging level is 0. +.TP +.BR "\-C " configfile, " \-\-config " configfile +Specifies an alternate config file. Normally the compiled in default +.I @PATH_RADVD_CONF@ +is used. +.TP +.BR "\-p " pidfile, " \-\-pidfile " pidfile +Specifies an alternate pidfile. Normally the compiled in default +.I @PATH_RADVD_PID@ +is used. +.TP +.BR "\-m " method, " \-\-logmethod " method +Specifies the logging method to use. Possibly values are: +.RS +.TP +.B none +Completely disables any logging. +.TP +.B logfile +Logs to the logfile which is specified by the +.I \-l +option. If no logfile is specified on the command line, then +a compiled in default is used (see next option). +.TP +.B stderr +Logs to standard error. +.TP +.B stderr_syslog +Logs only the high messages (of at least LOG_ERR priority) to standard +error, and everything to syslog (default method). +.TP +.B syslog +Logs to syslog. +.RE +.PP +.TP +.BR "\-l " logfile, " \-\-logfile " logfile +Specifies the logfile to use when using the logging method +.IR logfile . +The default logfile is +.IR @PATH_RADVD_LOG@ . +.TP +.BR "\-f " facility, " \-\-facility " facility +Specifies the facility (as an integer) when using syslog logging. Default +is @LOG_FACILITY@. +.TP +.BR "\-t " chrootdir, " \-\-chrootdir " chrootdir +If specified, switches to +.I chrootdir +before doing anything else. This directory and its +subdirectories must have been populated first. +For security reasons, +.I \-u +must always be used when using +.IR chrootdir . + +Note that on Linux +.I radvd +requires access to the +.I /proc +filesystem, +so it is more challenging to set up the chroot environment. +.TP +.BR "\-u " username, " \-\-username " username +If specified, drops root privileges and changes user ID to +.I username +and group ID to the primary group of +.IR username . +This is recommended for security reasons. +You might also need to use +.I \-p +to point to a file in a +.I username +-writable directory (e.g. /var/run/radvd/radvd.pid). +.SH FILES + +.nf +@sbindir@/radvd +@PATH_RADVD_CONF@ +@PATH_RADVD_PID@ +@PATH_RADVD_LOG@ +.fi +.SH BUGS + +There certainly are some bugs. If you find them or have other +suggestions please contact Pekka Savola . + +.SH "SEE ALSO" + +.BR radvd.conf (5), +.BR radvdump (8) +.SH AUTHORS + +.nf +Pedro Roque - wrote first version for Linux +Lars Fenneberg - previous maintainer +Nathan Lutchansky - previous maintainer +Pekka Savola - current maintainer +Craig Metz - port to NRL's IPv6 code for BSD4.4 +Marko Myllynen - RFC 2461 update, Mobile IPv6 support +.fi diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvd.c b/support/sdk/c/blip/driver/radvd-1.0/radvd.c new file mode 100644 index 00000000..91258508 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvd.c @@ -0,0 +1,638 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996-2000 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include +#include + +struct Interface *IfaceList = NULL; + +char usage_str[] = + "[-vh] [-d level] [-C config_file] [-m log_method] [-l log_file]\n" + "\t[-f facility] [-p pid_file] [-u username] [-t chrootdir]"; + +#ifdef HAVE_GETOPT_LONG +struct option prog_opt[] = { + {"debug", 1, 0, 'd'}, + {"config", 1, 0, 'C'}, + {"pidfile", 1, 0, 'p'}, + {"logfile", 1, 0, 'l'}, + {"logmethod", 1, 0, 'm'}, + {"facility", 1, 0, 'f'}, + {"username", 1, 0, 'u'}, + {"chrootdir", 1, 0, 't'}, + {"version", 0, 0, 'v'}, + {"help", 0, 0, 'h'}, + {NULL, 0, 0, 0} +}; +#endif + +extern FILE *yyin; + +char *conf_file = NULL; +char *pname; +int sock = -1; + +volatile int sighup_received = 0; +volatile int sigterm_received = 0; +volatile int sigint_received = 0; + +void sighup_handler(int sig); +void sigterm_handler(int sig); +void sigint_handler(int sig); +void timer_handler(void *data); +void config_interface(void); +void kickoff_adverts(void); +void stop_adverts(void); +void version(void); +void usage(void); +int drop_root_privileges(const char *); +int readin_config(char *); +int check_conffile_perm(const char *, const char *); + +int +main(int argc, char *argv[]) +{ + unsigned char msg[MSG_SIZE]; + char pidstr[16]; + int c, log_method; + char *logfile, *pidfile; + sigset_t oset, nset; + int facility, fd; + char *username = NULL; + char *chrootdir = NULL; +#ifdef HAVE_GETOPT_LONG + int opt_idx; +#endif + + pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0]; + + srand((unsigned int)time(NULL)); + + log_method = L_STDERR_SYSLOG; + logfile = PATH_RADVD_LOG; + conf_file = PATH_RADVD_CONF; + facility = LOG_FACILITY; + pidfile = PATH_RADVD_PID; + + /* parse args */ +#ifdef HAVE_GETOPT_LONG + while ((c = getopt_long(argc, argv, "d:C:l:m:p:t:u:vh", prog_opt, &opt_idx)) > 0) +#else + while ((c = getopt(argc, argv, "d:C:l:m:p:t:u:vh")) > 0) +#endif + { + switch (c) { + case 'C': + conf_file = optarg; + break; + case 'd': + set_debuglevel(atoi(optarg)); + break; + case 'f': + facility = atoi(optarg); + break; + case 'l': + logfile = optarg; + break; + case 'p': + pidfile = optarg; + break; + case 'm': + if (!strcmp(optarg, "syslog")) + { + log_method = L_SYSLOG; + } + else if (!strcmp(optarg, "stderr_syslog")) + { + log_method = L_STDERR_SYSLOG; + } + else if (!strcmp(optarg, "stderr")) + { + log_method = L_STDERR; + } + else if (!strcmp(optarg, "logfile")) + { + log_method = L_LOGFILE; + } + else if (!strcmp(optarg, "none")) + { + log_method = L_NONE; + } + else + { + fprintf(stderr, "%s: unknown log method: %s\n", pname, optarg); + exit(1); + } + break; + case 't': + chrootdir = strdup(optarg); + break; + case 'u': + username = strdup(optarg); + break; + case 'v': + version(); + break; + case 'h': + usage(); +#ifdef HAVE_GETOPT_LONG + case ':': + fprintf(stderr, "%s: option %s: parameter expected\n", pname, + prog_opt[opt_idx].name); + exit(1); +#endif + case '?': + exit(1); + } + } + + if (chrootdir) { + if (!username) { + fprintf(stderr, "Chroot as root is not safe, exiting\n"); + exit(1); + } + + if (chroot(chrootdir) == -1) { + perror("chroot"); + exit (1); + } + + if (chdir("/") == -1) { + perror("chdir"); + exit (1); + } + /* username will be switched later */ + } + + if (log_open(log_method, pname, logfile, facility) < 0) + exit(1); + + flog(LOG_INFO, "version %s started", VERSION); + + /* get a raw socket for sending and receiving ICMPv6 messages */ + sock = open_icmpv6_socket(); + if (sock < 0) + exit(1); + + /* drop root privileges if requested. */ + if (username) { + if (drop_root_privileges(username) < 0) + exit(1); + } + + /* check that 'other' cannot write the file + * for non-root, also that self/own group can't either + */ + if (check_conffile_perm(username, conf_file) < 0) { + if (get_debuglevel() == 0) + exit(1); + else + flog(LOG_WARNING, "Insecure file permissions, but continuing anyway"); + } + + /* if we know how to do it, check whether forwarding is enabled */ + if (check_ip6_forwarding()) { + if (get_debuglevel() == 0) { + flog(LOG_ERR, "IPv6 forwarding seems to be disabled, exiting"); + exit(1); + } + else + flog(LOG_WARNING, "IPv6 forwarding seems to be disabled, but continuing anyway."); + } + + /* parse config file */ + if (readin_config(conf_file) < 0) + exit(1); + + /* FIXME: not atomic if pidfile is on an NFS mounted volume */ + if ((fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0) + { + flog(LOG_ERR, "another radvd seems to be already running, terminating"); + exit(1); + } + + /* + * okay, config file is read in, socket and stuff is setup, so + * lets fork now... + */ + + if (get_debuglevel() == 0) { + + /* Detach from controlling terminal */ + if (daemon(0, 0) < 0) + perror("daemon"); + + /* close old logfiles, including stderr */ + log_close(); + + /* reopen logfiles, but don't log to stderr unless explicitly requested */ + if (log_method == L_STDERR_SYSLOG) + log_method = L_SYSLOG; + if (log_open(log_method, pname, logfile, facility) < 0) + exit(1); + + } + + /* + * config signal handlers, also make sure ALRM isn't blocked and raise a warning if so + * (some stupid scripts/pppd appears to do this...) + */ + sigemptyset(&nset); + sigaddset(&nset, SIGALRM); + sigprocmask(SIG_UNBLOCK, &nset, &oset); + if (sigismember(&oset, SIGALRM)) + flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong."); + + signal(SIGHUP, sighup_handler); + signal(SIGTERM, sigterm_handler); + signal(SIGINT, sigint_handler); + + snprintf(pidstr, sizeof(pidstr), "%d\n", getpid()); + + write(fd, pidstr, strlen(pidstr)); + + close(fd); + + config_interface(); + kickoff_adverts(); + + /* enter loop */ + + for (;;) + { + int len, hoplimit; + struct sockaddr_in6 rcv_addr; + struct in6_pktinfo *pkt_info = NULL; + + len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); + if (len > 0) + process(sock, IfaceList, msg, len, + &rcv_addr, pkt_info, hoplimit); + + if (sigterm_received || sigint_received) { + stop_adverts(); + break; + } + + if (sighup_received) + { + reload_config(); + sighup_received = 0; + } + } + + unlink(pidfile); + exit(0); +} + +void +timer_handler(void *data) +{ + struct Interface *iface = (struct Interface *) data; + double next; + + dlog(LOG_DEBUG, 4, "timer_handler called for %s", iface->Name); + + send_ra(sock, iface, NULL); + + next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval); + + if (iface->init_racount < MAX_INITIAL_RTR_ADVERTISEMENTS) + { + iface->init_racount++; + next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, next); + } + + set_timer(&iface->tm, next); +} + +void +config_interface(void) +{ + struct Interface *iface; + for(iface=IfaceList; iface; iface=iface->next) + { + if (iface->AdvLinkMTU) + set_interface_linkmtu(iface->Name, iface->AdvLinkMTU); + if (iface->AdvCurHopLimit) + set_interface_curhlim(iface->Name, iface->AdvCurHopLimit); + if (iface->AdvReachableTime) + set_interface_reachtime(iface->Name, iface->AdvReachableTime); + if (iface->AdvRetransTimer) + set_interface_retranstimer(iface->Name, iface->AdvRetransTimer); + } +} + +void +kickoff_adverts(void) +{ + struct Interface *iface; + + /* + * send initial advertisement and set timers + */ + + for(iface=IfaceList; iface; iface=iface->next) + { + if( ! iface->UnicastOnly ) + { + init_timer(&iface->tm, timer_handler, (void *) iface); + if (iface->AdvSendAdvert) + { + /* send an initial advertisement */ + send_ra(sock, iface, NULL); + + iface->init_racount++; + + set_timer(&iface->tm, + min(MAX_INITIAL_RTR_ADVERT_INTERVAL, + iface->MaxRtrAdvInterval)); + } + } + } +} + +void +stop_adverts(void) +{ + struct Interface *iface; + + /* + * send final RA (a SHOULD in RFC2461 section 6.2.5) + */ + + for (iface=IfaceList; iface; iface=iface->next) { + if( ! iface->UnicastOnly ) { + if (iface->AdvSendAdvert) { + /* send a final advertisement with zero Router Lifetime */ + iface->AdvDefaultLifetime = 0; + send_ra(sock, iface, NULL); + } + } + } +} + +void reload_config(void) +{ + struct Interface *iface; + + flog(LOG_INFO, "attempting to reread config file"); + + dlog(LOG_DEBUG, 4, "reopening log"); + if (log_reopen() < 0) + exit(1); + + /* disable timers, free interface and prefix structures */ + for(iface=IfaceList; iface; iface=iface->next) + { + /* check that iface->tm was set in the first place */ + if (iface->tm.next && iface->tm.prev) + { + dlog(LOG_DEBUG, 4, "disabling timer for %s", iface->Name); + clear_timer(&iface->tm); + } + } + + iface=IfaceList; + while(iface) + { + struct Interface *next_iface = iface->next; + struct AdvPrefix *prefix; + struct AdvRoute *route; + struct AdvRDNSS *rdnss; + + dlog(LOG_DEBUG, 4, "freeing interface %s", iface->Name); + + prefix = iface->AdvPrefixList; + while (prefix) + { + struct AdvPrefix *next_prefix = prefix->next; + + free(prefix); + prefix = next_prefix; + } + + route = iface->AdvRouteList; + while (route) + { + struct AdvRoute *next_route = route->next; + + free(route); + route = next_route; + } + + rdnss = iface->AdvRDNSSList; + while (rdnss) + { + struct AdvRDNSS *next_rdnss = rdnss->next; + + free(rdnss); + rdnss = next_rdnss; + } + + free(iface); + iface = next_iface; + } + + IfaceList = NULL; + + /* reread config file */ + if (readin_config(conf_file) < 0) + exit(1); + + config_interface(); + kickoff_adverts(); + + flog(LOG_INFO, "resuming normal operation"); +} + +void +sighup_handler(int sig) +{ + /* Linux has "one-shot" signals, reinstall the signal handler */ + signal(SIGHUP, sighup_handler); + + dlog(LOG_DEBUG, 4, "sighup_handler called"); + + sighup_received = 1; +} + +void +sigterm_handler(int sig) +{ + /* Linux has "one-shot" signals, reinstall the signal handler */ + signal(SIGTERM, sigterm_handler); + + dlog(LOG_DEBUG, 4, "sigterm_handler called"); + + sigterm_received = 1; +} + +void +sigint_handler(int sig) +{ + /* Linux has "one-shot" signals, reinstall the signal handler */ + signal(SIGINT, sigint_handler); + + dlog(LOG_DEBUG, 4, "sigint_handler called"); + + sigint_received = 1; +} + +int +drop_root_privileges(const char *username) +{ + struct passwd *pw = NULL; + pw = getpwnam(username); + if (pw) { + if (initgroups(username, pw->pw_gid) != 0 || setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { + flog(LOG_ERR, "Couldn't change to '%.32s' uid=%d gid=%d\n", + username, pw->pw_uid, pw->pw_gid); + return (-1); + } + } + else { + flog(LOG_ERR, "Couldn't find user '%.32s'\n", username); + return (-1); + } + return 0; +} + +int +check_conffile_perm(const char *username, const char *conf_file) +{ + struct stat *st = NULL; + struct passwd *pw = NULL; + FILE *fp = fopen(conf_file, "r"); + + if (fp == NULL) { + flog(LOG_ERR, "can't open %s: %s", conf_file, strerror(errno)); + return (-1); + } + fclose(fp); + + st = malloc(sizeof(struct stat)); + if (st == NULL) + goto errorout; + + if (!username) + username = "root"; + + pw = getpwnam(username); + + if (stat(conf_file, st) || pw == NULL) + goto errorout; + + if (st->st_mode & S_IWOTH) { + flog(LOG_ERR, "Insecure file permissions (writable by others): %s", conf_file); + goto errorout; + } + + /* for non-root: must not be writable by self/own group */ + if (strncmp(username, "root", 5) != 0 && + ((st->st_mode & S_IWGRP && pw->pw_gid == st->st_gid) || + (st->st_mode & S_IWUSR && pw->pw_uid == st->st_uid))) { + flog(LOG_ERR, "Insecure file permissions (writable by self/group): %s", conf_file); + goto errorout; + } + + free(st); + return 0; + +errorout: + if (st) + free(st); + return(-1); +} + +int +check_ip6_forwarding(void) +{ + int forw_sysctl[] = { SYSCTL_IP6_FORWARDING }; + int value; + size_t size = sizeof(value); + FILE *fp = NULL; + +#ifdef __linux__ + fp = fopen(PROC_SYS_IP6_FORWARDING, "r"); + if (fp) { + fscanf(fp, "%d", &value); + fclose(fp); + } + else + flog(LOG_DEBUG, "Correct IPv6 forwarding procfs entry not found, " + "perhaps the procfs is disabled, " + "or the kernel interface has changed?"); +#endif /* __linux__ */ + + if (!fp && sysctl(forw_sysctl, sizeof(forw_sysctl)/sizeof(forw_sysctl[0]), + &value, &size, NULL, 0) < 0) { + flog(LOG_DEBUG, "Correct IPv6 forwarding sysctl branch not found, " + "perhaps the kernel interface has changed?"); + return(0); /* this is of advisory value only */ + } + + if (value != 1) { + flog(LOG_DEBUG, "IPv6 forwarding setting is: %u, should be 1", value); + return(-1); + } + + return(0); +} + +int +readin_config(char *fname) +{ + if ((yyin = fopen(fname, "r")) == NULL) + { + flog(LOG_ERR, "can't open %s: %s", fname, strerror(errno)); + return (-1); + } + + if (yyparse() != 0) + { + flog(LOG_ERR, "error parsing or activating the config file: %s", fname); + return (-1); + } + + fclose(yyin); + return 0; +} + +void +version(void) +{ + fprintf(stderr, "Version: %s\n\n", VERSION); + fprintf(stderr, "Compiled in settings:\n"); + fprintf(stderr, " default config file \"%s\"\n", PATH_RADVD_CONF); + fprintf(stderr, " default pidfile \"%s\"\n", PATH_RADVD_PID); + fprintf(stderr, " default logfile \"%s\"\n", PATH_RADVD_LOG); + fprintf(stderr, " default syslog facililty %d\n", LOG_FACILITY); + fprintf(stderr, "Please send bug reports or suggestions to %s.\n", + CONTACT_EMAIL); + + exit(1); +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s %s\n", pname, usage_str); + exit(1); +} + diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvd.conf.5.man b/support/sdk/c/blip/driver/radvd-1.0/radvd.conf.5.man new file mode 100644 index 00000000..8e06194d --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvd.conf.5.man @@ -0,0 +1,591 @@ +.\" +.\" $Id$ +.\" +.\" Authors: +.\" Lars Fenneberg +.\" Marko Myllynen +.\" +.\" This software is Copyright 1996-2000 by the above mentioned author(s), +.\" All Rights Reserved. +.\" +.\" The license which is distributed with this software in the file COPYRIGHT +.\" applies to this software. If your distribution is missing this file, you +.\" may request it from . +.\" +.\" +.\" +.TH RADVD.CONF 5 "20 Aug 2004" "radvd @VERSION@" "" +.SH NAME +radvd.conf \- configuration file of the router advertisement daemon +.B radvd +.SH DESCRIPTION +This file describes the information which is included in the router +advertisement (RA) of a specific interface. +.P +The file contains one or more interface definitions of the form: + +.nf +.BR "interface " "name " { + list of interface specific options + list of prefix definitions + list of route definitions + list of RDNSS definitions +.B }; +.fi + +All the possible interface specific options are detailed below. Each +option has to be terminated by a semicolon. + +Prefix definitions are of the form: + +.nf +.BR "prefix " prefix / "length " { + list of prefix specific options +.B }; +.fi + +Prefix can be network prefix or the address of the inferface. +The address of interface should be used when using Mobile IPv6 +extensions. + +All the possible prefix specific options are described below. Each +option has to be terminated by a semicolon. + +Decimal values are allowed only for MinDelayBetweenRAs, +MaxRtrAdvInterval and MinRtrAdvInterval. Decimal values should +be used only when using Mobile IPv6 extensions. + +Route definitions are of the form: + +.nf +.BR "route " prefix / "length " { + list of route specific options +.B }; +.fi + +The prefix of a route definition should be network prefix; it can be used to +advertise more specific routes to the hosts. + +RDNSS (Recursive DNS server) definitions are of the form: + +.nf +.BR "RDNSS " "ip [ip] [ip] " { + list of rdnss specific options +.B }; +.fi + +.SH INTERFACE SPECIFIC OPTIONS + +.TP +.BR IgnoreIfMissing " " on | off + +A flag indicating whether or not the interface is ignored +if it does not exist at start-up. By default, radvd exits. + +This is useful for dynamic interfaces which are not active when radvd +starts or which are dynamically disabled and re-enabled during the time +radvd runs. + +Current versions of radvd automatically try to re-enable interfaces. + +Enabling IgnoreIfMissing also quenches certain warnings in log messages +relating to missing interfaces. + +Default: off + +.TP +.BR AdvSendAdvert " " on | off + +A flag indicating whether or not the router sends +periodic router advertisements and responds to +router solicitations. + +This option no longer has to be specified first, but it +needs to be +.B on +to enable advertisement on this interface. + +Default: off + +.TP +.BR UnicastOnly " " on | off + +Indicates that the interface link type only supports unicast. +This will prevent unsolicited advertisements from being sent, and +will cause solicited advertisements to be unicast to the +soliciting node. This option is necessary for non-broadcast, +multiple-access links, such as ISATAP. + +Default: off + +.TP +.BR "MaxRtrAdvInterval " seconds + +The maximum time allowed between sending unsolicited multicast +router advertisements from the interface, in seconds. + +Must be no less than 4 seconds and no greater than 1800 seconds. + +Minimum when using Mobile IPv6 extensions: 0.07. + +For values less than 0.2 seconds, 0.02 seconds is added to account for +scheduling granularities as specified in RFC3775. + +Default: 600 seconds + +.TP +.BR "MinRtrAdvInterval " seconds + +The minimum time allowed between sending unsolicited multicast +router advertisements from the interface, in seconds. + +Must be no less than 3 seconds and no greater than 0.75 * +MaxRtrAdvInterval. + +Minimum when using Mobile IPv6 extensions: 0.03. + +Default: 0.33 * MaxRtrAdvInterval + +.TP +.BR "MinDelayBetweenRAs " seconds + +The minimum time allowed between sending multicast +router advertisements from the interface, in seconds. + +This applies to solicited multicast RAs. +This is defined as the protocol constant MIN_DELAY_BETWEEN_RAS in RFC2461. +MIPv6 redefines this parameter to have a minimum of 0.03 seconds. + +Minimum when using Mobile IPv6 extensions: 0.03. + +Default: 3 + +.TP +.BR AdvManagedFlag " " on | off + +When set, hosts use the administered (stateful) protocol for address +autoconfiguration in addition to any addresses autoconfigured using +stateless address autoconfiguration. The use of this flag is +described in RFC 2462. + +Default: off + +.TP +.BR AdvOtherConfigFlag " " on | off + +When set, hosts use the administered (stateful) protocol for +autoconfiguration of other (non-address) information. The use of +this flag is described in RFC 2462. + +Default: off + +.TP +.BR "AdvLinkMTU " integer + +The MTU option is used in router advertisement messages to insure +that all nodes on a link use the same MTU value in those cases where +the link MTU is not well known. + +If specified, i.e. not 0, must not be smaller than 1280 and not greater +than the maximum MTU allowed for this link (e.g. ethernet has +a maximum MTU of 1500. See RFC 2464). + +Default: 0 + +.TP +.BR "AdvReachableTime " milliseconds + +The time, in milliseconds, that a node assumes a neighbor is +reachable after having received a reachability confirmation. Used +by the Neighbor Unreachability Detection algorithm (see Section +7.3 of RFC 2461). A value of zero means unspecified (by this router). + +Must be no greater than 3,600,000 milliseconds (1 hour). + +Default: 0 + +.TP +.BR "AdvRetransTimer " milliseconds + +The time, in milliseconds, between retransmitted Neighbor +Solicitation messages. Used by address resolution and the Neighbor +Unreachability Detection algorithm (see Sections 7.2 and 7.3 of RFC 2461). +A value of zero means unspecified (by this router). + +Default: 0 + +.TP +.BR "AdvCurHopLimit " integer + +The default value that should be placed in the Hop Count field of +the IP header for outgoing (unicast) IP packets. The value should +be set to the current diameter of the Internet. The value zero +means unspecified (by this router). + +Default: 64 + +.TP +.BR "AdvDefaultLifetime " seconds + +The lifetime associated with the default router in units of seconds. +The maximum value corresponds to 18.2 hours. A lifetime of 0 +indicates that the router is not a default router and should not +appear on the default router list. The router lifetime applies only +to the router's usefulness as a default router; it does not apply to +information contained in other message fields or options. Options +that need time limits for their information include their own +lifetime fields. + +Must be either zero or between MaxRtrAdvInterval and 9000 seconds. + +Default: 3 * MaxRtrAdvInterval (Minimum 1 second). + +.TP +.BR AdvDefaultPreference " " low | medium | high + +The preference associated with the default router, as either "low", +"medium", or "high". + +Default: medium + +.TP +.BR AdvSourceLLAddress " " on | off + +When set, the link-layer address of the outgoing interface is +included in the RA. + +Default: on + +.TP +.BR AdvHomeAgentFlag " " on | off + +When set, indicates that sending router is able to serve as Mobile +IPv6 Home Agent. When set, minimum limits specified by Mobile IPv6 +are used for MinRtrAdvInterval and MaxRtrAdvInterval. + +Default: off + +.TP +.BR AdvHomeAgentInfo " " on | off + +When set, Home Agent Information Option (specified by Mobile IPv6) +is included in Router Advertisements. AdvHomeAgentFlag must also +be set when using this option. + +Default: off + +.TP +.BR "HomeAgentLifetime " seconds + +The length of time in seconds (relative to the time the packet is +sent) that the router is offering Mobile IPv6 Home Agent services. +A value 0 must not be used. The maximum lifetime is 65520 seconds +(18.2 hours). This option is ignored, if AdvHomeAgentInfo is not +set. + +If both HomeAgentLifetime and HomeAgentPreference are set to their +default values, Home Agent Information Option will not be sent. + +Default: AdvDefaultLifetime + +.TP +.BR "HomeAgentPreference " integer + +The preference for the Home Agent sending this Router Advertisement. +Values greater than 0 indicate more preferable Home Agent, values +less than 0 indicate less preferable Home Agent. This option is +ignored, if AdvHomeAgentInfo is not set. + +If both HomeAgentLifetime and HomeAgentPreference are set to their +default values, Home Agent Information Option will not be sent. + +Default: 0 + +.TP +.BR AdvMobRtrSupportFlag " " on | off + +When set, the Home Agent signals it supports Mobile Router +registrations (specified by NEMO Basic). AdvHomeAgentInfo must also +be set when using this option. + +Default: off + +.TP +.BR AdvIntervalOpt " " on | off + +When set, Advertisement Interval Option (specified by Mobile IPv6) +is included in Router Advertisements. When set, minimum limits +specified by Mobile IPv6 are used for MinRtrAdvInterval and +MaxRtrAdvInterval. + +The advertisement interval is based on the configured MaxRtrAdvInterval +parameter except where this is less than 200ms. In this case, +the advertised interval is ( MaxRtrAdvInterval + 20ms ). + +Default: off + +.SH PREFIX SPECIFIC OPTIONS + +.TP +.BR AdvOnLink " " on | off + +When set, indicates that this prefix can be used for on-link +determination. When not set the advertisement makes no statement +about on-link or off-link properties of the prefix. For instance, +the prefix might be used for address configuration with some of the +addresses belonging to the prefix being on-link and others being +off-link. + +Default: on + +.TP +.BR AdvAutonomous " " on | off + +When set, indicates that this prefix can be used for autonomous +address configuration as specified in RFC 2462. + +Default: on + +.TP +.BR AdvRouterAddr " " on | off + +When set, indicates that the address of interface is sent instead of +network prefix, as is required by Mobile IPv6. When set, minimum +limits specified by Mobile IPv6 are used for MinRtrAdvInterval and +MaxRtrAdvInterval. + +Default: off + +.TP +.BR "AdvValidLifetime " seconds "" | infinity + +The length of time in seconds (relative to the time the packet is +sent) that the prefix is valid for the purpose of on-link +determination. The symbolic value +.B infinity +represents infinity (i.e. a value of all one bits (0xffffffff)). +The valid lifetime is also used by RFC 2462. + +Default: 2592000 seconds (30 days) + +.TP +.BR "AdvPreferredLifetime " seconds "" | infinity + +The length of time in seconds (relative to the time the packet is +sent) that addresses generated from the prefix via stateless address +autoconfiguration remain preferred. +The symbolic value +.B infinity +represents infinity (i.e. a value of all one bits (0xffffffff)). +See RFC 2462. + +Default: 604800 seconds (7 days) + +.TP +.BR "Base6to4Interface " name + +If this option is specified, this prefix will be combined with the +IPv4 address of interface +.B name +to produce a valid 6to4 prefix. The first 16 bits of this prefix +will be replaced by +.B 2002 +and the next 32 bits of this prefix will be replaced by the IPv4 +address assigned to interface +.B name +at configuration time. The remaining 80 bits of the prefix (including +the SLA ID) will be advertised as specified in the configuration file. +See the next section for an example. + +If interface +.B name +is not available at configuration time, a warning will be written to +the log and this prefix will be disabled until radvd is reconfigured. + +This option enables systems with dynamic IPv4 addresses to update their +advertised 6to4 prefixes simply by restarting radvd or sending a SIGHUP +signal to cause radvd to reconfigure itself. + +Note that 6to4 prefixes derived from dynamically-assigned IPv4 addresses +should be advertised with a significantly shorter lifetime (see the +.B AdvValidLifetime +and +.B AdvPreferredLifetime +options). + +For more information on 6to4, see RFC 3056. + +Default: 6to4 is not used + +.SH ROUTE SPECIFIC OPTIONS + +.TP +.BR "AdvRouteLifetime " seconds "" | infinity + +The lifetime associated with the route in units of seconds. +The symbolic value +.B infinity +represents infinity (i.e. a value of all one bits (0xffffffff)). + +Default: 3 * MaxRtrAdvInterval + +.TP +.BR AdvRoutePreference " " low | medium | high + +The preference associated with the default router, as either "low", +"medium", or "high". + +Default: medium + +.SH RDNSS SPECIFIC OPTIONS + +.TP +.BR "AdvRDNSSPreference " integer; + +The preference of the DNS server, compared to other DNS servers advertised and used. +0 to 7 means less important than manually configured nameservers in resolv.conf, while 12 to 15 means more important. + +Default: 8 + +.TP +.BR "AdvRDNSSOpen " on | off; + +"Service Open" flag. When set, indicates that RDNSS continues to be available to hosts even if they moved to a different subnet. + +Default: off + +.TP +.BR "AdvRDNSSLifetime " seconds | infinity; +The maximum duration how long the RDNSS entries are used for name resolution. A value of 0 means the nameserver should no longer be used. +The maximum duration how long the RDNSS entries are used for name resolution. A value of 0 means the nameserver should no longer be used. +The value, if not 0, must be at least MaxRtrAdvInterval. To ensure stale +RDNSS info gets removed in a timely fashion, this should not be greater than +2*MaxRtrAdvInterval. + +Default: 2*MaxRtrAdvInterval + +.SH EXAMPLES + +.nf +interface eth0 +{ + AdvSendAdvert on; + prefix 2001:db8:0:1::/64 + { + AdvOnLink on; + AdvAutonomous on; + }; +}; +.fi + +It says that router advertisement daemon should advertise +(AdvSendAdvert on;) the prefix 2001:db8:0:1:: which has a lenght of 64 +on the interface eth0. Also the prefix should be marked as autonomous +(AdvAutonomous on;) and as on-link (AdvOnLink on;). All the other +options are left on their default values. + +To support movement detection of Mobile IPv6 Mobile Nodes, the +address of interface should be used instead of network prefix: + +.nf +interface eth0 +{ + AdvSendAdvert on; + prefix 2001:db8:0:1::4/64 + { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + }; +}; +.fi + +For 6to4 support, include the +.B Base6to4Interface +option in each prefix section. When using a dynamic IPv4 address, set +small prefix lifetimes to prevent hosts from retaining unreachable +prefixes after a new IPv4 address has been assigned. When advertising to on +a dynamic interface (e.g., Bluetooth), skip the interface if it is not +active yet. + +.nf +interface bnep0 +{ + IgnoreIfMissing on; + AdvSendAdvert on; + + # Advertise at least every 30 seconds + MaxRtrAdvInterval 30; + + prefix 0:0:0:5678::/64 + { + AdvOnLink on; + AdvAutonomous on; + Base6to4Interface ppp0; + + # Very short lifetimes for dynamic addresses + AdvValidLifetime 300; + AdvPreferredLifetime 120; + }; +}; +.fi + +Since 6to4 is enabled, the prefix will be advertised as +2002:WWXX:YYZZ:5678::/64, where WW.XX.YY.ZZ is the IPv4 address of +ppp0 at configuration time. (IPv6 addresses are written in hexadecimal +whereas IPv4 addresses are written in decimal, so the IPv4 address +WW.XX.YY.ZZ in the 6to4 prefix will be represented in hex.) + +In this specific case, the configuration scripts may send HUP signal to +radvd when taking bnep0 up or down to notify about the status; in the +current radvd releases, sending HUP is no longer mandatory when the link +comes back up. + +.SH FILES + +.nf +@sbindir@/radvd +@PATH_RADVD_CONF@ +@PATH_RADVD_PID@ +@PATH_RADVD_LOG@ +.fi + +.SH CREDIT +The description of the different flags and variables is in large +parts taken from RFC 2461. + +.SH RFCS +Narten, T., E. Nordmark, W. Simpson, "Neighbor Discovery for IP +Version 6 (IPv6)", RFC 2461, December 1998 +.PP +Thomson, S., and T. Narten, "IPv6 Stateless Address Autoconfiguration", +RFC 2462, December 1998. +.PP +Deering, S., and R. Hinden, "IP Version 6 Addressing +Architecture", RFC 3513, April 2003. +.PP +Conta, A., and S. Deering, "Internet Control Message Protocol (ICMPv6) +for the Internet Protocol Version 6 (IPv6)", RFC 2463, December 1998. +.PP +Crawford, M., "Transmission of IPv6 Packets over Ethernet Networks", +RFC 2464, December 1998. +.PP +Carpenter B., K. Moore, "Connection of IPv6 Domains via IPv4 Clouds", +RFC 3056, February 2001. (6to4 specification) +.PP +Draves, R., D. Thaler, "Default Router Preferences and More-Specific Routes", +RFC 4191, November 2005. +.PP +Johnson, D., Perkins, C., and J. Arkko, "Mobility Support in IPv6", +RFC 3775, June 2004. +.PP +Devarapalli, V., Wakikawa, R., Petrescu, A., and P. Thubert "Network Mobility (NEMO) Basic Support Protocol", +RFC 3963, January 2005. +.PP +J. Jeong, L. Beloeil, and S. Madanapalli, "IPv6 Router Advertisement Option for DNS Configuration", +IETF Draft v08 (January 18, 2006). + +.SH "SEE ALSO" + +.BR radvd (8), +.BR radvdump (8) diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvd.conf.example b/support/sdk/c/blip/driver/radvd-1.0/radvd.conf.example new file mode 100644 index 00000000..b4bc5b90 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvd.conf.example @@ -0,0 +1,116 @@ +# +# NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +# NOTE NOTE +# NOTE This is an EXAMPLE, which serves only to demonstrate the NOTE +# NOTE syntax of radvd.conf, and is not meant to be used for a NOTE +# NOTE real radvd configuration. NOTE +# NOTE NOTE +# NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +# + +interface eth0 +{ + AdvSendAdvert on; + +# This may be needed on some interfaces which are not active when +# radvd starts, but becomoe available later on; see man page for details. + + # IgnoreIfMissing on; + +# +# These settings cause advertisements to be sent every 3-10 seconds. This +# range is good for 6to4 with a dynamic IPv4 address, but can be greatly +# increased when not using 6to4 prefixes. +# + + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + +# +# You can use AdvDefaultPreference setting to advertise the preference of +# the router for the purposes of default router determination. +# NOTE: This feature is still being specified and is not widely supported! +# + AdvDefaultPreference low; + +# +# Disable Mobile IPv6 support +# + AdvHomeAgentFlag off; + +# +# example of a standard prefix +# + prefix 2001:db8:1:0::/64 + { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr off; + }; + +# +# example of a 6to4 prefix +# +# Note that the first 48 bits are specified here as zeros. These will be +# replaced with the appropriate 6to4 address when radvd starts or is +# reconfigured. Be sure that the SLA ID (1234 in this case) is specified +# here! +# + prefix 0:0:0:1234::/64 + { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr off; + +# +# This setting causes radvd to replace the first 48 bits of the prefix +# with the 6to4 address generated from the specified interface. For example, +# if the address of ppp0 is 192.0.2.25 when radvd configures itself, this +# prefix will be advertised as 2002:C000:0219:1234::/64. +# +# If ppp0 is not available at configuration time, this prefix will not be +# advertised, but other prefixes listed in the configuration will be +# advertised as usual. +# +# When using the Base6to4Interface option, make sure radvd receives a +# SIGHUP every time the ppp0 interface goes up, down, or is assigned a +# new IPv4 address. The SIGHUP will cause radvd to recognize that the +# ppp0 interface has changed and will adjust the advertisements +# accordingly. +# + + Base6to4Interface ppp0; + +# +# If the IP address of ppp0 is assigned dynamically, be sure to set the +# lifetimes for this prefix to be small. Otherwise, hosts on your network +# may continue to use a prefix that no longer corresponds to the address +# on ppp0! +# + AdvPreferredLifetime 120; + AdvValidLifetime 300; + }; +# +# example of a more specific route +# NOTE: This feature is still being specified and is not widely supported! +# + route 2001:db0:fff::/48 + { + AdvRoutePreference high; + AdvRouteLifetime 3600; + }; + +# +# RDNSS +# NOTE: This feature is still a draft has no IANA number type for the moment +# + RDNSS 2001:db8::1 2001:db8::2 + { + AdvRDNSSPreference 8; + AdvRDNSSOpen off; + AdvRDNSSLifetime 30; + }; + + +}; + diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvd.h b/support/sdk/c/blip/driver/radvd-1.0/radvd.h new file mode 100644 index 00000000..57b74805 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvd.h @@ -0,0 +1,225 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#ifndef RADV_H +#define RADV_H + +#include +#include +#include + +#define CONTACT_EMAIL "Pekka Savola " + +/* for log.c */ +#define L_NONE 0 +#define L_SYSLOG 1 +#define L_STDERR 2 +#define L_STDERR_SYSLOG 3 +#define L_LOGFILE 4 + +#define LOG_TIME_FORMAT "%b %d %H:%M:%S" + +struct timer_lst { + struct timeval expires; + void (*handler)(void *); + void * data; + struct timer_lst *next; + struct timer_lst *prev; +}; + +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +struct AdvPrefix; + +#define HWADDR_MAX 16 + +struct Interface { + char Name[IFNAMSIZ]; /* interface name */ + + struct in6_addr if_addr; + unsigned int if_index; + + uint8_t init_racount; /* Initial RAs */ + + uint8_t if_hwaddr[HWADDR_MAX]; + int if_hwaddr_len; + int if_prefix_len; + int if_maxmtu; + + int IgnoreIfMissing; + int AdvSendAdvert; + double MaxRtrAdvInterval; + double MinRtrAdvInterval; + double MinDelayBetweenRAs; + int AdvManagedFlag; + int AdvOtherConfigFlag; + uint32_t AdvLinkMTU; + uint32_t AdvReachableTime; + uint32_t AdvRetransTimer; + uint8_t AdvCurHopLimit; + int32_t AdvDefaultLifetime; /* XXX: really uint16_t but we need to use -1 */ + int AdvDefaultPreference; + int AdvSourceLLAddress; + int UnicastOnly; + + /* Mobile IPv6 extensions */ + int AdvIntervalOpt; + int AdvHomeAgentInfo; + int AdvHomeAgentFlag; + uint16_t HomeAgentPreference; + int32_t HomeAgentLifetime; /* XXX: really uint16_t but we need to use -1 */ + + /* NEMO extensions */ + int AdvMobRtrSupportFlag; + + struct AdvPrefix *AdvPrefixList; + struct AdvRoute *AdvRouteList; + struct AdvRDNSS *AdvRDNSSList; + struct timer_lst tm; + time_t last_multicast_sec; + suseconds_t last_multicast_usec; + + /* Info whether this interface has failed in the past (and may need to be reinitialized) */ + int HasFailed; + + struct Interface *next; +}; + +struct AdvPrefix { + struct in6_addr Prefix; + uint8_t PrefixLen; + + int AdvOnLinkFlag; + int AdvAutonomousFlag; + uint32_t AdvValidLifetime; + uint32_t AdvPreferredLifetime; + + /* Mobile IPv6 extensions */ + int AdvRouterAddr; + + /* 6to4 extensions */ + char if6to4[IFNAMSIZ]; + int enabled; + + struct AdvPrefix *next; +}; + +/* More-Specific Routes extensions */ + +struct AdvRoute { + struct in6_addr Prefix; + uint8_t PrefixLen; + + int AdvRoutePreference; + uint32_t AdvRouteLifetime; + + struct AdvRoute *next; +}; + +/* Option for DNS configuration */ +struct AdvRDNSS { + int AdvRDNSSNumber; + uint8_t AdvRDNSSPreference; + int AdvRDNSSOpenFlag; + uint32_t AdvRDNSSLifetime; + struct in6_addr AdvRDNSSAddr1; + struct in6_addr AdvRDNSSAddr2; + struct in6_addr AdvRDNSSAddr3; + + struct AdvRDNSS *next; +}; + +/* Mobile IPv6 extensions */ + +struct AdvInterval { + uint8_t type; + uint8_t length; + uint16_t reserved; + uint32_t adv_ival; +}; + +struct HomeAgentInfo { + uint8_t type; + uint8_t length; + uint16_t flags_reserved; + uint16_t preference; + uint16_t lifetime; +}; + + +/* gram.y */ +int yyparse(void); + +/* scanner.l */ +int yylex(void); + +/* radvd.c */ +int check_ip6_forwarding(void); +void reload_config(void); + +/* timer.c */ +void set_timer(struct timer_lst *tm, double); +void clear_timer(struct timer_lst *tm); +void init_timer(struct timer_lst *, void (*)(void *), void *); + +/* log.c */ +int log_open(int, char *, char*, int); +void flog(int, char *, ...); +void dlog(int, int, char *, ...); +int log_close(void); +int log_reopen(void); +void set_debuglevel(int); +int get_debuglevel(void); + +/* device.c */ +int setup_deviceinfo(int, struct Interface *); +int check_device(int, struct Interface *); +int setup_linklocal_addr(int, struct Interface *); +int setup_allrouters_membership(int, struct Interface *); +int check_allrouters_membership(int, struct Interface *); +int get_v4addr(const char *, unsigned int *); +int set_interface_linkmtu(const char *, uint32_t); +int set_interface_curhlim(const char *, uint8_t); +int set_interface_reachtime(const char *, uint32_t); +int set_interface_retranstimer(const char *, uint32_t); + +/* interface.c */ +void iface_init_defaults(struct Interface *); +void prefix_init_defaults(struct AdvPrefix *); +void route_init_defaults(struct AdvRoute *, struct Interface *); +void rdnss_init_defaults(struct AdvRDNSS *, struct Interface *); +int check_iface(struct Interface *); + +/* socket.c */ +int open_icmpv6_socket(void); + +/* send.c */ +void send_ra(int, struct Interface *iface, struct in6_addr *dest); + +/* process.c */ +void process(int sock, struct Interface *, unsigned char *, int, + struct sockaddr_in6 *, struct in6_pktinfo *, int); + +/* recv.c */ +int recv_rs_ra(int, unsigned char *, struct sockaddr_in6 *, struct in6_pktinfo **, int *); + +/* util.c */ +void mdelay(double); +double rand_between(double, double); +void print_addr(struct in6_addr *, char *); +int check_rdnss_presence(struct AdvRDNSS *, struct in6_addr *); + +#endif diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvdump.8.man b/support/sdk/c/blip/driver/radvd-1.0/radvdump.8.man new file mode 100644 index 00000000..98ee6b86 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvdump.8.man @@ -0,0 +1,87 @@ +.\" +.\" $Id$ +.\" +.\" Authors: +.\" Lars Fenneberg +.\" Marko Myllynen +.\" +.\" This software is Copyright 1996 by the above mentioned author(s), +.\" All Rights Reserved. +.\" +.\" The license which is distributed with this software in the file COPYRIGHT +.\" applies to this software. If your distribution is missing this file, you +.\" may request it from . +.\" +.\" +.\" +.TH RADVDUMP 8 "29 Dec 2001" "radvd @VERSION@" "" +.SH NAME +radvdump \- dump router advertisements +.SH SYNOPSIS +.B radvdump +.B "[ \-vhfe ]" +.BI "[ \-d " debuglevel " ]" + +.SH DESCRIPTION +.B radvdump +prints out the contents of incoming router advertisements sent by +.B radvd +or some other software implementing (parts of) +"Neighbor Discovery for IP Version 6 (IPv6)" (RFC 2461). + +.SH OPTIONS + +For every one character option there is also a long option, which +is listed right next to the "short" option name: + +.TP +.BR "\-v" , " \-\-version" +Displays the version of +.I radvdump +and then aborts. +.TP +.BR "\-h" , " \-\-help" +Displays a short usage description and then aborts. +.TP +.BR "\-f" , " \-\-file\-format" +Output received router advertisements in the format of the +.B radvd +configuration file. +Since radvd 0.9, this is the default and the switch is provided +for backward compatibility only. +.TP +.BR "\-e" , " \-\-exclude-defaults" +Exclude default valued options from configuration file format. +This option is ignored if option +.B "\-f" +is not set. +.TP +.BR "\-d " debuglevel, " \-\-debug " debuglevel +With this option you turn on debugging information. The debugging level is +an integer in the range from 1 to 4, from quiet to very verbose. A +debugging level of 0 completely turns off debugging. + +The default debugging level is 0. + +.SH FILES + +.nf +@sbindir@/radvdump +.fi +.SH BUGS + +There certainly are some bugs. If you find them or have other +suggestions please contact Pekka Savola . + +.SH "SEE ALSO" + +.BR radvd (8), +.BR radvd.conf (5) +.SH AUTHORS + +.nf +Lars Fenneberg - previous maintainer +Nathan Lutchansky - previous maintainer +Pekka Savola - current maintainer +Marko Myllynen - Mobile IPv6 support +.fi diff --git a/support/sdk/c/blip/driver/radvd-1.0/radvdump.c b/support/sdk/c/blip/driver/radvd-1.0/radvdump.c new file mode 100644 index 00000000..e4beaf5e --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/radvdump.c @@ -0,0 +1,477 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * Marko Myllynen + * + * This software is Copyright 1996-2000 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +char usage_str[] = "[-vhfe] [-d level]"; + +#ifdef HAVE_GETOPT_LONG +struct option prog_opt[] = { + {"debug", 1, 0, 'd'}, + {"file-format", 0, 0, 'f'}, + {"exclude-defaults", 0, 0, 'e'}, + {"version", 0, 0, 'v'}, + {"help", 0, 0, 'h'}, + {NULL, 0, 0, 0} +}; +#endif + +char *pname; +int sock = -1; + +void version(void); +void usage(void); +void print_ff(unsigned char *, int, struct sockaddr_in6 *, int, unsigned int, int); +void print_preferences(int); + +int +main(int argc, char *argv[]) +{ + unsigned char msg[MSG_SIZE]; + int c, len, hoplimit; + int edefs = 0; + struct sockaddr_in6 rcv_addr; + struct in6_pktinfo *pkt_info = NULL; +#ifdef HAVE_GETOPT_LONG + int opt_idx; +#endif + + pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0]; + + /* parse args */ +#ifdef HAVE_GETOPT_LONG + while ((c = getopt_long(argc, argv, "d:fehv", prog_opt, &opt_idx)) > 0) +#else + while ((c = getopt(argc, argv, "d:fehv")) > 0) +#endif + { + switch (c) { + case 'd': + set_debuglevel(atoi(optarg)); + break; + case 'f': + break; + case 'e': + edefs = 1; + break; + case 'v': + version(); + break; + case 'h': + usage(); +#ifdef HAVE_GETOPT_LONG + case ':': + fprintf(stderr, "%s: option %s: parameter expected\n", pname, + prog_opt[opt_idx].name); + exit(1); +#endif + case '?': + exit(1); + } + } + + if (log_open(L_STDERR, pname, NULL, 0) < 0) + exit(1); + + /* get a raw socket for sending and receiving ICMPv6 messages */ + sock = open_icmpv6_socket(); + if (sock < 0) + exit(1); + + for(;;) + { + len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); + if (len > 0) + { + struct icmp6_hdr *icmph; + + /* + * can this happen? + */ + + if (len < sizeof(struct icmp6_hdr)) + { + flog(LOG_WARNING, "received icmpv6 packet with invalid length: %d", + len); + exit(1); + } + + icmph = (struct icmp6_hdr *) msg; + + if (icmph->icmp6_type != ND_ROUTER_SOLICIT && + icmph->icmp6_type != ND_ROUTER_ADVERT) + { + /* + * We just want to listen to RSs and RAs + */ + + flog(LOG_ERR, "icmpv6 filter failed"); + exit(1); + } + + dlog(LOG_DEBUG, 4, "receiver if_index: %u", pkt_info->ipi6_ifindex); + + if (icmph->icmp6_type == ND_ROUTER_SOLICIT) + { + /* not yet */ + } + else if (icmph->icmp6_type == ND_ROUTER_ADVERT) + print_ff(msg, len, &rcv_addr, hoplimit, (unsigned int)pkt_info->ipi6_ifindex, edefs); + } + else if (len == 0) + { + flog(LOG_ERR, "received zero lenght packet"); + exit(1); + } + else + { + flog(LOG_ERR, "recv_rs_ra: %s", strerror(errno)); + exit(1); + } + } + + exit(0); +} + +void +print_ff(unsigned char *msg, int len, struct sockaddr_in6 *addr, int hoplimit, unsigned int if_index, int edefs) +{ + /* XXX: hoplimit not being used for anything here.. */ + struct nd_router_advert *radvert; + char addr_str[INET6_ADDRSTRLEN]; + uint8_t *opt_str; + int orig_len = len; + char if_name[IFNAMSIZ] = ""; + + print_addr(&addr->sin6_addr, addr_str); + printf("#\n# radvd configuration generated by radvdump %s\n", VERSION); + printf("# based on Router Advertisement from %s\n", addr_str); + if_indextoname(if_index, if_name); + printf("# received by interface %s\n", if_name); + printf("#\n\ninterface %s\n{\n\tAdvSendAdvert on;\n", if_name); + + printf("\t# Note: {Min,Max}RtrAdvInterval cannot be obtained with radvdump\n"); + + radvert = (struct nd_router_advert *) msg; + + if (!edefs || DFLT_AdvManagedFlag != (ND_RA_FLAG_MANAGED == (radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED))) + printf("\tAdvManagedFlag %s;\n", + (radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)?"on":"off"); + + if (!edefs || DFLT_AdvOtherConfigFlag != (ND_RA_FLAG_OTHER == (radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER))) + printf("\tAdvOtherConfigFlag %s;\n", + (radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)?"on":"off"); + + if (!edefs || DFLT_AdvReachableTime != ntohl(radvert->nd_ra_reachable)) + printf("\tAdvReachableTime %u;\n", ntohl(radvert->nd_ra_reachable)); + + if (!edefs || DFLT_AdvRetransTimer != ntohl(radvert->nd_ra_retransmit)) + printf("\tAdvRetransTimer %u;\n", ntohl(radvert->nd_ra_retransmit)); + + if (!edefs || DFLT_AdvCurHopLimit != radvert->nd_ra_curhoplimit) + printf("\tAdvCurHopLimit %u;\n", radvert->nd_ra_curhoplimit); + + /* Mobile IPv6 ext */ + if (!edefs || DFLT_AdvHomeAgentFlag != (ND_RA_FLAG_HOME_AGENT == (radvert->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT))) + printf("\tAdvHomeAgentFlag %s;\n", + (radvert->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT)?"on":"off"); + + /* Route Preferences and more specific routes */ + /* XXX two middlemost bits from 8 bit field */ + if (!edefs || (((radvert->nd_ra_flags_reserved & 0x18) >> 3) & 0xff) != DFLT_AdvDefaultPreference) { + printf("\tAdvDefaultPreference "); + print_preferences(((radvert->nd_ra_flags_reserved & 0x18) >> 3) & 0xff); + printf(";\n"); + } + + len -= sizeof(struct nd_router_advert); + + if (len == 0) + return; + + opt_str = (uint8_t *)(msg + sizeof(struct nd_router_advert)); + + while (len > 0) + { + int optlen; + struct nd_opt_mtu *mtu; + struct HomeAgentInfo *ha_info; + + if (len < 2) + { + flog(LOG_ERR, "trailing garbage in RA from %s", + addr_str); + break; + } + + optlen = (opt_str[1] << 3); + + if (optlen == 0) + { + flog(LOG_ERR, "zero length option in RA"); + break; + } + else if (optlen > len) + { + flog(LOG_ERR, "option length greater than total" + " length in RA (type %d, optlen %d, len %d)", + (int)*opt_str, optlen, len); + break; + } + + switch (*opt_str) + { + case ND_OPT_MTU: + mtu = (struct nd_opt_mtu *)opt_str; + + if (!edefs || DFLT_AdvLinkMTU != ntohl(mtu->nd_opt_mtu_mtu)) + printf("\tAdvLinkMTU %u;\n", ntohl(mtu->nd_opt_mtu_mtu)); + break; + case ND_OPT_SOURCE_LINKADDR: + /* XXX: !DFLT depends on current DFLT_ value */ + if (!edefs || !DFLT_AdvSourceLLAddress) + printf("\tAdvSourceLLAddress on;\n"); + break; + /* Mobile IPv6 ext */ + case ND_OPT_RTR_ADV_INTERVAL: + /* XXX: !DFLT depends on current DFLT_ value */ + if (!edefs || !DFLT_AdvIntervalOpt) + printf("\tAdvIntervalOpt on;\n"); + break; + /* Mobile IPv6 ext */ + case ND_OPT_HOME_AGENT_INFO: + ha_info = (struct HomeAgentInfo *)opt_str; + + /* XXX: we check DFLT_HomeAgentInfo by interface, and it's outside + of context here, so we always need to print it out.. */ + printf("\tAdvHomeAgentInfo on;\n"); + + /* NEMO ext */ + if (!edefs || DFLT_AdvMobRtrSupportFlag != (ha_info->flags_reserved & ND_OPT_HAI_FLAG_SUPPORT_MR)) + printf("\tAdvMobRtrSupportFlag %s;\n", (ha_info->flags_reserved & ND_OPT_HAI_FLAG_SUPPORT_MR)?"on":"off"); + + if (!edefs || DFLT_HomeAgentPreference != ntohs(ha_info->preference)) + printf("\tHomeAgentPreference %hu;\n", ntohs(ha_info->preference)); + /* Hum.. */ + if (!edefs || (3*DFLT_MaxRtrAdvInterval) != ntohs(ha_info->lifetime)) + printf("\tHomeAgentLifetime %hu;\n", ntohs(ha_info->lifetime)); + break; + case ND_OPT_TARGET_LINKADDR: + case ND_OPT_REDIRECTED_HEADER: + flog(LOG_ERR, "invalid option %d in RA", (int)*opt_str); + break; + case ND_OPT_PREFIX_INFORMATION: + break; + case ND_OPT_ROUTE_INFORMATION: + break; + case ND_OPT_RDNSS_INFORMATION: + break; + default: + dlog(LOG_DEBUG, 1, "unknown option %d in RA", + (int)*opt_str); + break; + } + + len -= optlen; + opt_str += optlen; + } + + orig_len -= sizeof(struct nd_router_advert); + + if (orig_len == 0) + return; + + opt_str = (uint8_t *)(msg + sizeof(struct nd_router_advert)); + + while (orig_len > 0) + { + int optlen; + struct nd_opt_prefix_info *pinfo; + struct nd_opt_route_info_local *rinfo; + struct nd_opt_rdnss_info_local *rdnss_info; + char prefix_str[INET6_ADDRSTRLEN]; + + if (orig_len < 2) + { + flog(LOG_ERR, "trailing garbage in RA from %s", + addr_str); + break; + } + + optlen = (opt_str[1] << 3); + + if (optlen == 0) + { + flog(LOG_ERR, "zero length option in RA"); + break; + } + else if (optlen > orig_len) + { + flog(LOG_ERR, "option length greater than total" + " length in RA (type %d, optlen %d, len %d)", + (int)*opt_str, optlen, orig_len); + break; + } + + switch (*opt_str) + { + case ND_OPT_PREFIX_INFORMATION: + pinfo = (struct nd_opt_prefix_info *) opt_str; + + print_addr(&pinfo->nd_opt_pi_prefix, prefix_str); + + printf("\n\tprefix %s/%d\n\t{\n", prefix_str, pinfo->nd_opt_pi_prefix_len); + + if (ntohl(pinfo->nd_opt_pi_valid_time) == 0xffffffff) + { + if (!edefs || DFLT_AdvValidLifetime != 0xffffffff) + printf("\t\tAdvValidLifetime infinity; # (0xffffffff)\n"); + } + else + { + if (!edefs || DFLT_AdvValidLifetime != ntohl(pinfo->nd_opt_pi_valid_time)) + printf("\t\tAdvValidLifetime %u;\n", ntohl(pinfo->nd_opt_pi_valid_time)); + } + if (ntohl(pinfo->nd_opt_pi_preferred_time) == 0xffffffff) + { + if (!edefs || DFLT_AdvPreferredLifetime != 0xffffffff) + printf("\t\tAdvPreferredLifetime infinity; # (0xffffffff)\n"); + } + else + { + if (!edefs || DFLT_AdvPreferredLifetime != ntohl(pinfo->nd_opt_pi_preferred_time)) + printf("\t\tAdvPreferredLifetime %u;\n", ntohl(pinfo->nd_opt_pi_preferred_time)); + } + + if (!edefs || DFLT_AdvOnLinkFlag != (ND_OPT_PI_FLAG_ONLINK == (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK))) + printf("\t\tAdvOnLink %s;\n", + (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK)?"on":"off"); + + if (!edefs || DFLT_AdvAutonomousFlag != (ND_OPT_PI_FLAG_AUTO == (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO))) + printf("\t\tAdvAutonomous %s;\n", + (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO)?"on":"off"); + + /* Mobile IPv6 ext */ + if (!edefs || DFLT_AdvRouterAddr != (ND_OPT_PI_FLAG_RADDR == (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_RADDR))) + printf("\t\tAdvRouterAddr %s;\n", + (pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_RADDR)?"on":"off"); + + printf("\t}; # End of prefix definition\n\n"); + break; + case ND_OPT_ROUTE_INFORMATION: + rinfo = (struct nd_opt_route_info_local *) opt_str; + + print_addr(&rinfo->nd_opt_ri_prefix, prefix_str); + + printf("\n\troute %s/%d\n\t{\n", prefix_str, rinfo->nd_opt_ri_prefix_len); + + if (!edefs || (((radvert->nd_ra_flags_reserved & 0x18) >> 3) & 0xff) != DFLT_AdvRoutePreference) { + printf("\t\tAdvRoutePreference "); + print_preferences(((rinfo->nd_opt_ri_flags_reserved & 0x18) >> 3) & 0xff); + printf(";\n"); + } + + /* XXX: we check DFLT_AdvRouteLifetime by interface, and it's outside of context here */ + if (ntohl(rinfo->nd_opt_ri_lifetime) == 0xffffffff) + printf("\t\tAdvRouteLifetime infinity; # (0xffffffff)\n"); + else + printf("\t\tAdvRouteLifetime %u;\n", ntohl(rinfo->nd_opt_ri_lifetime)); + + printf("\t}; # End of route definition\n\n"); + break; + case ND_OPT_RDNSS_INFORMATION: + rdnss_info = (struct nd_opt_rdnss_info_local *) opt_str; + + printf("\n\tRDNSS"); + + print_addr(&rdnss_info->nd_opt_rdnssi_addr1, prefix_str); + printf(" %s", prefix_str); + + if (rdnss_info->nd_opt_rdnssi_len >= 5) { + print_addr(&rdnss_info->nd_opt_rdnssi_addr2, prefix_str); + printf(" %s", prefix_str); + } + if (rdnss_info->nd_opt_rdnssi_len >= 7) { + print_addr(&rdnss_info->nd_opt_rdnssi_addr3, prefix_str); + printf(" %s", prefix_str); + } + + printf("\n\t{\n"); + if (!edefs + || ((rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_PREF_MASK) >> ND_OPT_RDNSSI_PREF_SHIFT) != DFLT_AdvRDNSSPreference) + printf("\t\tAdvRDNSSPreference %d;\n", + (rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_PREF_MASK) >> ND_OPT_RDNSSI_PREF_SHIFT); + + if (!edefs + || ((rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_FLAG_S) == 0 ) == DFLT_AdvRDNSSOpenFlag) + printf("\t\tAdvRDNSSOpen %s;\n", rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_FLAG_S ? "on" : "off"); + + /* as AdvRDNSSLifetime may depend on MaxRtrAdvInterval, it could change */ + if (ntohl(rdnss_info->nd_opt_rdnssi_lifetime) == 0xffffffff) + printf("\t\tAdvRDNSSLifetime infinity; # (0xffffffff)\n"); + else + printf("\t\tAdvRDNSSLifetime %u;\n", ntohl(rdnss_info->nd_opt_rdnssi_lifetime)); + + printf("\t}; # End of RDNSS definition\n\n"); + break; + default: + break; + } + orig_len -= optlen; + opt_str += optlen; + } + + printf("}; # End of interface definition\n"); + + fflush(stdout); +} + +void +print_preferences(int p) +{ + switch (p) { + case 0: + printf("medium"); + break; + case 1: + printf("high"); + break; + case 2: + /* reserved, ignore */ + break; + case 3: + printf("low"); + break; + } +} + +void +version(void) +{ + fprintf(stderr,"Version: %s\n\n", VERSION); + fprintf(stderr,"Please send bug reports and suggestions to %s\n", + CONTACT_EMAIL); + exit(1); +} + +void +usage(void) +{ + fprintf(stderr,"usage: %s %s\n", pname, usage_str); + exit(1); +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/recv.c b/support/sdk/c/blip/driver/radvd-1.0/recv.c new file mode 100644 index 00000000..b78644dd --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/recv.c @@ -0,0 +1,119 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +int +recv_rs_ra(int sock, unsigned char *msg, struct sockaddr_in6 *addr, + struct in6_pktinfo **pkt_info, int *hoplimit) +{ + struct msghdr mhdr; + struct cmsghdr *cmsg; + struct iovec iov; + static unsigned char *chdr = NULL; + static unsigned int chdrlen = 0; + int len; + fd_set rfds; + + if( ! chdr ) + { + chdrlen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + + CMSG_SPACE(sizeof(int)); + if ((chdr = malloc(chdrlen)) == NULL) { + flog(LOG_ERR, "recv_rs_ra: malloc: %s", strerror(errno)); + return -1; + } + } + + FD_ZERO( &rfds ); + FD_SET( sock, &rfds ); + + if( select( sock+1, &rfds, NULL, NULL, NULL ) < 0 ) + { + if (errno != EINTR) + flog(LOG_ERR, "select: %s", strerror(errno)); + + return -1; + } + + iov.iov_len = MSG_SIZE; + iov.iov_base = (caddr_t) msg; + + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_name = (caddr_t)addr; + mhdr.msg_namelen = sizeof(*addr); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = chdrlen; + + len = recvmsg(sock, &mhdr, 0); + + if (len < 0) + { + if (errno != EINTR) + flog(LOG_ERR, "recvmsg: %s", strerror(errno)); + + return len; + } + + *hoplimit = 255; + + for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) + { + if (cmsg->cmsg_level != IPPROTO_IPV6) + continue; + + switch(cmsg->cmsg_type) + { +#ifdef IPV6_HOPLIMIT + case IPV6_HOPLIMIT: + if ((cmsg->cmsg_len == CMSG_LEN(sizeof(int))) && + (*(int *)CMSG_DATA(cmsg) >= 0) && + (*(int *)CMSG_DATA(cmsg) < 256)) + { + *hoplimit = *(int *)CMSG_DATA(cmsg); + } + else + { + flog(LOG_ERR, "received a bogus IPV6_HOPLIMIT from the kernel! len=%d, data=%d", + cmsg->cmsg_len, *(int *)CMSG_DATA(cmsg)); + return (-1); + } + break; +#endif /* IPV6_HOPLIMIT */ + case IPV6_PKTINFO: + if ((cmsg->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) && + ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex) + { + *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); + } + else + { + flog(LOG_ERR, "received a bogus IPV6_PKTINFO from the kernel! len=%d, index=%d", + cmsg->cmsg_len, ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex); + return (-1); + } + break; + } + } + + dlog(LOG_DEBUG, 4, "recvmsg len=%d", len); + + return len; +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/scanner.c b/support/sdk/c/blip/driver/radvd-1.0/scanner.c new file mode 100644 index 00000000..47d63616 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/scanner.c @@ -0,0 +1,2398 @@ + +#line 3 "lex.yy.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 33 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 53 +#define YY_END_OF_BUFFER 54 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[514] = + { 0, + 0, 0, 54, 52, 3, 2, 52, 52, 51, 41, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 3, 0, + 1, 42, 0, 41, 0, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 50, 0, 50, 50, + 50, 50, 50, 50, 45, 50, 50, 43, 41, 0, + 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 50, 50, 50, 50, 50, 50, 47, 50, 46, 50, + 50, 41, 0, 0, 0, 40, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 50, 50, 49, 50, + 50, 50, 50, 50, 41, 0, 0, 40, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 50, 50, 50, 50, 50, 6, + 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 50, 50, 48, 5, 0, 0, 40, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 50, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 44, 50, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 17, 0, 0, 0, 0, 27, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 8, 0, + 0, 0, 0, 40, 0, 0, 0, 26, 28, 0, + 0, 0, 37, 0, 15, 34, 0, 0, 23, 0, + 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 32, 0, 10, 0, + 11, 40, 0, 18, 0, 0, 13, 0, 35, 33, + + 20, 0, 38, 0, 0, 0, 0, 31, 0, 19, + 39, 24, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 5, 6, 7, 8, 8, 8, + 8, 9, 8, 10, 8, 8, 8, 11, 12, 1, + 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, + 1, 19, 20, 1, 1, 21, 22, 23, 24, 25, + 1, 26, 27, 28, 29, 30, 1, 1, 1, 1, + 1, 1, 1, 1, 31, 1, 32, 33, 34, 35, + + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 41, 48, 49, 50, 51, 52, 53, 54, + 55, 41, 56, 1, 57, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[58] = + { 0, + 1, 1, 1, 1, 1, 2, 1, 3, 3, 3, + 4, 1, 5, 5, 5, 5, 5, 5, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 6, 3, 3, 3, 3, 3, 3, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[555] = + { 0, + 0, 0, 884, 885, 881, 885, 879, 50, 885, 55, + 870, 56, 62, 63, 834, 841, 38, 862, 832, 89, + 65, 69, 66, 73, 76, 139, 104, 102, 874, 872, + 885, 80, 108, 145, 863, 75, 885, 151, 152, 829, + 827, 817, 825, 846, 828, 151, 196, 156, 90, 162, + 171, 163, 164, 180, 172, 179, 183, 171, 187, 181, + 856, 0, 222, 830, 829, 818, 837, 67, 835, 827, + 210, 245, 214, 234, 196, 258, 245, 259, 260, 261, + 277, 281, 849, 848, 847, 846, 805, 804, 818, 807, + 807, 811, 254, 251, 802, 259, 238, 817, 838, 834, + + 798, 795, 808, 793, 815, 809, 291, 298, 304, 305, + 306, 307, 308, 315, 314, 829, 828, 827, 0, 787, + 788, 798, 790, 783, 787, 786, 797, 808, 789, 791, + 803, 207, 774, 779, 772, 779, 771, 782, 783, 770, + 774, 768, 885, 766, 320, 326, 327, 328, 329, 330, + 803, 802, 801, 800, 764, 790, 776, 771, 770, 763, + 772, 777, 762, 765, 763, 772, 764, 749, 746, 760, + 746, 753, 746, 755, 770, 776, 756, 774, 736, 334, + 341, 349, 350, 351, 774, 773, 772, 737, 735, 729, + 766, 730, 755, 738, 725, 729, 725, 736, 744, 731, + + 737, 732, 754, 732, 730, 755, 718, 725, 726, 705, + 724, 734, 357, 359, 746, 745, 744, 708, 706, 709, + 713, 698, 721, 712, 699, 704, 730, 696, 350, 711, + 697, 328, 706, 704, 718, 718, 687, 714, 683, 720, + 681, 687, 367, 371, 720, 719, 685, 707, 677, 690, + 693, 695, 688, 695, 885, 675, 672, 679, 671, 669, + 683, 666, 674, 665, 699, 659, 689, 669, 663, 359, + 667, 686, 669, 684, 660, 379, 691, 690, 689, 653, + 658, 367, 652, 653, 885, 677, 643, 648, 656, 654, + 654, 653, 645, 659, 649, 649, 649, 647, 661, 644, + + 630, 639, 630, 628, 631, 625, 629, 618, 661, 660, + 619, 625, 628, 619, 616, 641, 621, 616, 625, 626, + 624, 614, 621, 621, 616, 619, 617, 618, 604, 638, + 614, 613, 611, 611, 597, 595, 591, 593, 885, 631, + 630, 629, 590, 598, 600, 600, 129, 588, 602, 586, + 592, 610, 580, 885, 593, 600, 583, 576, 589, 576, + 573, 587, 571, 572, 583, 581, 577, 580, 579, 578, + 602, 601, 885, 561, 574, 572, 565, 562, 556, 567, + 558, 565, 562, 561, 552, 559, 562, 557, 548, 885, + 885, 560, 554, 556, 542, 555, 545, 541, 552, 539, + + 575, 574, 573, 885, 533, 546, 549, 543, 885, 885, + 531, 560, 540, 532, 539, 530, 525, 528, 535, 522, + 525, 536, 527, 518, 527, 512, 518, 510, 550, 549, + 519, 510, 519, 510, 505, 511, 517, 516, 506, 514, + 885, 513, 503, 511, 510, 511, 500, 407, 885, 394, + 385, 378, 398, 397, 395, 361, 368, 885, 885, 385, + 370, 351, 885, 366, 885, 885, 365, 349, 885, 361, + 360, 350, 351, 376, 344, 375, 368, 333, 322, 316, + 308, 285, 268, 267, 244, 885, 885, 251, 885, 227, + 885, 257, 239, 885, 193, 194, 885, 144, 885, 885, + + 885, 136, 885, 160, 110, 76, 56, 885, 74, 885, + 885, 885, 885, 412, 417, 421, 426, 429, 433, 436, + 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, + 469, 472, 475, 478, 481, 484, 487, 490, 493, 496, + 499, 502, 505, 508, 511, 514, 517, 520, 523, 526, + 529, 532, 535, 538 + } ; + +static yyconst flex_int16_t yy_def[555] = + { 0, + 513, 1, 513, 513, 513, 513, 514, 513, 513, 515, + 513, 515, 515, 515, 513, 513, 513, 513, 513, 513, + 516, 516, 516, 516, 516, 516, 516, 516, 513, 514, + 513, 513, 513, 517, 518, 517, 513, 517, 517, 513, + 513, 513, 513, 513, 513, 513, 20, 518, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 513, 519, 519, + 520, 521, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 20, 520, 516, 516, 516, 516, 516, 516, 516, + 516, 513, 513, 522, 523, 524, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + + 513, 513, 513, 513, 513, 513, 516, 522, 516, 516, + 516, 516, 516, 516, 513, 525, 526, 527, 521, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 525, 516, 516, 516, 516, 516, + 513, 528, 529, 530, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 516, 516, 516, 516, 531, 532, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 516, 516, 513, 533, 534, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 516, 516, 535, 536, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 516, 513, 537, 538, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + + 513, 513, 513, 513, 513, 513, 513, 513, 539, 540, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 541, 542, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 543, 544, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + + 513, 545, 546, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 547, 548, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 549, 550, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 551, 552, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 553, 513, 513, 513, 513, 513, 513, 513, + + 513, 513, 513, 554, 513, 513, 513, 513, 513, 513, + 513, 513, 0, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513 + } ; + +static yyconst flex_int16_t yy_nxt[943] = + { 0, + 4, 5, 6, 7, 8, 4, 9, 10, 10, 10, + 11, 9, 12, 13, 14, 14, 14, 14, 15, 16, + 4, 17, 4, 4, 4, 18, 4, 4, 19, 4, + 4, 20, 20, 20, 20, 20, 20, 21, 22, 23, + 21, 21, 24, 25, 21, 26, 27, 28, 21, 21, + 21, 21, 21, 21, 21, 9, 9, 32, 32, 32, + 33, 513, 34, 34, 34, 35, 35, 513, 513, 42, + 46, 46, 35, 35, 46, 46, 46, 43, 46, 46, + 513, 46, 103, 46, 455, 35, 46, 32, 32, 32, + 38, 512, 104, 39, 46, 46, 47, 47, 47, 48, + + 46, 36, 36, 36, 36, 36, 36, 46, 50, 46, + 51, 53, 46, 511, 46, 58, 58, 58, 52, 49, + 47, 47, 47, 47, 47, 47, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 46, 510, 377, 57, 378, 46, + 33, 56, 59, 59, 59, 35, 513, 513, 71, 71, + 71, 35, 35, 73, 73, 73, 62, 46, 46, 46, + 455, 508, 46, 46, 46, 54, 46, 46, 58, 58, + 58, 46, 46, 55, 46, 46, 513, 507, 46, 46, + 46, 35, 33, 46, 82, 82, 82, 35, 78, 74, + + 64, 46, 63, 72, 72, 72, 46, 75, 60, 60, + 60, 60, 60, 60, 80, 77, 79, 71, 71, 71, + 76, 108, 108, 108, 85, 506, 505, 72, 72, 72, + 72, 72, 72, 81, 87, 110, 88, 89, 167, 46, + 90, 91, 92, 93, 46, 94, 95, 96, 97, 455, + 46, 98, 107, 107, 107, 46, 168, 83, 83, 83, + 83, 83, 83, 46, 46, 46, 46, 455, 46, 46, + 46, 46, 109, 134, 131, 503, 107, 107, 107, 107, + 107, 107, 46, 135, 502, 126, 33, 46, 115, 115, + 115, 35, 501, 111, 132, 128, 46, 113, 112, 127, + + 129, 48, 500, 499, 133, 145, 145, 145, 85, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, + 46, 115, 115, 115, 498, 46, 114, 180, 180, 180, + 85, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 71, 71, 71, 85, 497, 46, 149, 263, 146, + 150, 46, 264, 147, 46, 46, 46, 148, 496, 46, + 46, 46, 46, 182, 46, 181, 495, 46, 494, 46, + 258, 183, 46, 259, 260, 265, 46, 46, 455, 302, + 214, 46, 184, 303, 46, 455, 491, 313, 490, 46, + 213, 314, 244, 489, 488, 487, 486, 485, 484, 483, + + 482, 481, 480, 479, 478, 62, 276, 455, 403, 475, + 474, 243, 30, 30, 30, 30, 30, 30, 36, 36, + 36, 36, 49, 49, 49, 473, 49, 60, 60, 60, + 60, 61, 61, 61, 83, 83, 83, 83, 84, 84, + 84, 86, 472, 86, 116, 116, 116, 117, 117, 117, + 118, 118, 118, 151, 151, 151, 152, 152, 152, 154, + 154, 154, 185, 185, 185, 186, 186, 186, 187, 187, + 187, 215, 215, 215, 216, 216, 216, 245, 245, 245, + 246, 246, 246, 277, 277, 277, 278, 278, 278, 309, + 309, 309, 310, 310, 310, 340, 340, 340, 341, 341, + + 341, 371, 371, 371, 372, 372, 372, 401, 401, 401, + 402, 402, 402, 429, 429, 429, 430, 430, 430, 453, + 453, 453, 454, 454, 454, 476, 476, 476, 477, 477, + 477, 492, 492, 492, 493, 493, 493, 504, 504, 504, + 509, 509, 509, 471, 470, 469, 468, 467, 466, 465, + 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, + 403, 452, 451, 450, 449, 448, 447, 446, 445, 444, + 443, 442, 441, 440, 439, 438, 437, 436, 435, 434, + 433, 432, 431, 62, 403, 342, 428, 427, 426, 425, + 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, + + 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, + 404, 403, 342, 400, 399, 398, 397, 396, 395, 394, + 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, + 383, 382, 381, 380, 379, 376, 375, 374, 373, 62, + 342, 279, 370, 369, 368, 367, 366, 365, 364, 363, + 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, + 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, + 342, 279, 339, 338, 337, 336, 335, 334, 333, 332, + 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, + 321, 320, 319, 318, 317, 316, 315, 312, 311, 62, + + 279, 217, 308, 307, 306, 305, 304, 301, 300, 299, + 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, + 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, + 217, 275, 274, 273, 272, 271, 270, 269, 268, 267, + 266, 262, 261, 257, 256, 255, 254, 253, 252, 251, + 250, 249, 248, 247, 62, 217, 153, 242, 241, 240, + 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, + 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, + 219, 218, 119, 217, 153, 212, 211, 210, 209, 208, + 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, + + 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, + 119, 62, 153, 85, 179, 178, 177, 176, 175, 174, + 173, 172, 171, 170, 169, 166, 165, 164, 163, 162, + 161, 160, 159, 158, 157, 156, 155, 119, 153, 85, + 144, 143, 142, 141, 140, 139, 138, 137, 136, 130, + 125, 124, 123, 122, 121, 120, 119, 62, 85, 35, + 106, 105, 102, 101, 100, 99, 85, 70, 69, 68, + 67, 66, 65, 62, 31, 29, 45, 44, 41, 40, + 37, 31, 29, 513, 3, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513 + } ; + +static yyconst flex_int16_t yy_chk[943] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, + 10, 12, 10, 10, 10, 10, 12, 13, 14, 17, + 21, 23, 13, 14, 22, 21, 23, 17, 24, 22, + 36, 25, 68, 24, 509, 36, 25, 32, 32, 32, + 12, 507, 68, 13, 20, 49, 20, 20, 20, 20, + + 49, 20, 20, 20, 20, 20, 20, 28, 22, 27, + 23, 25, 28, 506, 27, 33, 33, 33, 24, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 26, 505, 347, 28, 347, 26, + 34, 27, 34, 34, 34, 34, 38, 39, 46, 46, + 46, 38, 39, 48, 48, 48, 48, 50, 52, 53, + 504, 502, 50, 52, 53, 26, 51, 55, 58, 58, + 58, 51, 55, 26, 56, 54, 60, 498, 57, 56, + 54, 60, 59, 57, 59, 59, 59, 59, 53, 50, + + 39, 75, 38, 47, 47, 47, 75, 51, 47, 47, + 47, 47, 47, 47, 56, 52, 54, 71, 71, 71, + 51, 73, 73, 73, 73, 496, 495, 47, 47, 47, + 47, 47, 47, 57, 63, 75, 63, 63, 132, 74, + 63, 63, 63, 63, 74, 63, 63, 63, 63, 493, + 77, 63, 72, 72, 72, 77, 132, 72, 72, 72, + 72, 72, 72, 76, 78, 79, 80, 492, 76, 78, + 79, 80, 74, 97, 96, 490, 72, 72, 72, 72, + 72, 72, 81, 97, 488, 93, 82, 81, 82, 82, + 82, 82, 485, 76, 96, 94, 107, 80, 78, 93, + + 94, 107, 484, 483, 96, 108, 108, 108, 108, 109, + 110, 111, 112, 113, 109, 110, 111, 112, 113, 115, + 114, 115, 115, 115, 482, 114, 81, 145, 145, 145, + 145, 146, 147, 148, 149, 150, 146, 147, 148, 149, + 150, 180, 180, 180, 180, 481, 181, 113, 232, 110, + 114, 181, 232, 111, 182, 183, 184, 112, 480, 182, + 183, 184, 213, 147, 214, 146, 479, 213, 478, 214, + 229, 148, 243, 229, 229, 232, 244, 243, 477, 270, + 182, 244, 149, 270, 276, 476, 475, 282, 474, 276, + 181, 282, 214, 473, 472, 471, 470, 468, 467, 464, + + 462, 461, 460, 457, 456, 455, 244, 454, 453, 452, + 451, 213, 514, 514, 514, 514, 514, 514, 515, 515, + 515, 515, 516, 516, 516, 450, 516, 517, 517, 517, + 517, 518, 518, 518, 519, 519, 519, 519, 520, 520, + 520, 521, 448, 521, 522, 522, 522, 523, 523, 523, + 524, 524, 524, 525, 525, 525, 526, 526, 526, 527, + 527, 527, 528, 528, 528, 529, 529, 529, 530, 530, + 530, 531, 531, 531, 532, 532, 532, 533, 533, 533, + 534, 534, 534, 535, 535, 535, 536, 536, 536, 537, + 537, 537, 538, 538, 538, 539, 539, 539, 540, 540, + + 540, 541, 541, 541, 542, 542, 542, 543, 543, 543, + 544, 544, 544, 545, 545, 545, 546, 546, 546, 547, + 547, 547, 548, 548, 548, 549, 549, 549, 550, 550, + 550, 551, 551, 551, 552, 552, 552, 553, 553, 553, + 554, 554, 554, 447, 446, 445, 444, 443, 442, 440, + 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, + 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, + 419, 418, 417, 416, 415, 414, 413, 412, 411, 408, + 407, 406, 405, 403, 402, 401, 400, 399, 398, 397, + 396, 395, 394, 393, 392, 389, 388, 387, 386, 385, + + 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, + 374, 372, 371, 370, 369, 368, 367, 366, 365, 364, + 363, 362, 361, 360, 359, 358, 357, 356, 355, 353, + 352, 351, 350, 349, 348, 346, 345, 344, 343, 342, + 341, 340, 338, 337, 336, 335, 334, 333, 332, 331, + 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, + 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, + 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, + 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, + 290, 289, 288, 287, 286, 284, 283, 281, 280, 279, + + 278, 277, 275, 274, 273, 272, 271, 269, 268, 267, + 266, 265, 264, 263, 262, 261, 260, 259, 258, 257, + 256, 254, 253, 252, 251, 250, 249, 248, 247, 246, + 245, 242, 241, 240, 239, 238, 237, 236, 235, 234, + 233, 231, 230, 228, 227, 226, 225, 224, 223, 222, + 221, 220, 219, 218, 217, 216, 215, 212, 211, 210, + 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, + 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, + 189, 188, 187, 186, 185, 179, 178, 177, 176, 175, + 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, + + 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, + 154, 153, 152, 151, 144, 142, 141, 140, 139, 138, + 137, 136, 135, 134, 133, 131, 130, 129, 128, 127, + 126, 125, 124, 123, 122, 121, 120, 118, 117, 116, + 106, 105, 104, 103, 102, 101, 100, 99, 98, 95, + 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, + 70, 69, 67, 66, 65, 64, 61, 45, 44, 43, + 42, 41, 40, 35, 30, 29, 19, 18, 16, 15, + 11, 7, 5, 3, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "scanner.l" +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996-2000 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ +#line 17 "scanner.l" +#include +#include +#include +#include + +extern char *conf_file; + +int num_lines = 1; +#line 864 "lex.yy.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 38 "scanner.l" + + +#line 1020 "lex.yy.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 514 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 885 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 40 "scanner.l" +{/* ignore comments */} + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 41 "scanner.l" +{num_lines++;} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 42 "scanner.l" +{} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 44 "scanner.l" +{ return T_INTERFACE; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 45 "scanner.l" +{ return T_PREFIX; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 46 "scanner.l" +{ return T_ROUTE; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 47 "scanner.l" +{ return T_RDNSS; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 49 "scanner.l" +{ return T_IgnoreIfMissing; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 50 "scanner.l" +{ return T_AdvSendAdvert; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 51 "scanner.l" +{ return T_MaxRtrAdvInterval; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 52 "scanner.l" +{ return T_MinRtrAdvInterval; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 53 "scanner.l" +{ return T_AdvManagedFlag; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 54 "scanner.l" +{ return T_AdvOtherConfigFlag; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 55 "scanner.l" +{ return T_AdvLinkMTU; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 56 "scanner.l" +{ return T_AdvReachableTime; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 57 "scanner.l" +{ return T_AdvRetransTimer; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 58 "scanner.l" +{ return T_AdvCurHopLimit; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 59 "scanner.l" +{ return T_AdvDefaultLifetime; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 60 "scanner.l" +{ return T_AdvDefaultPreference; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 61 "scanner.l" +{ return T_AdvSourceLLAddress; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 63 "scanner.l" +{ return T_AdvOnLink; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 64 "scanner.l" +{ return T_AdvAutonomous; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 65 "scanner.l" +{ return T_AdvValidLifetime; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 66 "scanner.l" +{ return T_AdvPreferredLifetime; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 68 "scanner.l" +{ return T_AdvRouterAddr; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 69 "scanner.l" +{ return T_AdvHomeAgentFlag; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 70 "scanner.l" +{ return T_AdvIntervalOpt; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 71 "scanner.l" +{ return T_AdvHomeAgentInfo; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 72 "scanner.l" +{ return T_UnicastOnly; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 74 "scanner.l" +{ return T_Base6to4Interface; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 76 "scanner.l" +{ return T_HomeAgentPreference; } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 77 "scanner.l" +{ return T_HomeAgentLifetime; } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 79 "scanner.l" +{ return T_AdvRoutePreference; } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 80 "scanner.l" +{ return T_AdvRouteLifetime; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 82 "scanner.l" +{ return T_AdvRDNSSPreference; } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 83 "scanner.l" +{ return T_AdvRDNSSOpenFlag; } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 84 "scanner.l" +{ return T_AdvRDNSSLifetime; } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 86 "scanner.l" +{ return T_MinDelayBetweenRAs; } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 88 "scanner.l" +{ return T_AdvMobRtrSupportFlag; } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 90 "scanner.l" +{ + static struct in6_addr addr; + int i; + + i = inet_pton(AF_INET6, yytext, &addr); + + dlog(LOG_DEBUG, 4, "inet_pton returned %d", i); + + /* BSD API draft and NRL's code don't aggree on + * this. the draft specifies a return value of 1 on + * success, NRL's code returns the address length in + * bytes on success (16 for an IPv6 address) + */ + if (i < 1) { + flog(LOG_ERR, "invalid address in %s, line %d", conf_file, + num_lines); + return T_BAD_TOKEN; + } + + yylval.addr = &addr; + return IPV6ADDR; + } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 113 "scanner.l" +{ + unsigned long lnum; + char *endp; + lnum = strtoul(yytext, &endp, 10); + if (*yytext == '\0' || *endp != '\0') + return T_BAD_TOKEN; + if (lnum > 0xFFFFFFFFUL) + return T_BAD_TOKEN; /* XXX */ + yylval.num = lnum; + return NUMBER; + } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 125 "scanner.l" +{ yylval.snum = atoi(yytext); return SIGNEDNUMBER; } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 127 "scanner.l" +{ yylval.dec = atof(yytext); return DECIMAL; } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 129 "scanner.l" +{ return INFINITY; } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 131 "scanner.l" +{ yylval.bool = 1; return SWITCH; } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 133 "scanner.l" +{ yylval.bool = 0; return SWITCH; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 135 "scanner.l" +{ yylval.snum = -1; return SIGNEDNUMBER; } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 137 "scanner.l" +{ yylval.snum = 0; return SIGNEDNUMBER; } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 139 "scanner.l" +{ yylval.snum = 1; return SIGNEDNUMBER; } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 141 "scanner.l" +{ + static char name[IFNAMSIZ]; + + strncpy(name, yytext, IFNAMSIZ-1); + name[IFNAMSIZ-1] = '\0'; + yylval.str = name; + return STRING; + } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 150 "scanner.l" +{ return *yytext; } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 152 "scanner.l" +{ return T_BAD_TOKEN; } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 153 "scanner.l" +ECHO; + YY_BREAK +#line 1410 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 514 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 514 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 513); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 153 "scanner.l" + + + diff --git a/support/sdk/c/blip/driver/radvd-1.0/scanner.l b/support/sdk/c/blip/driver/radvd-1.0/scanner.l new file mode 100644 index 00000000..45c3a17d --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/scanner.l @@ -0,0 +1,153 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996-2000 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ +%{ +#include +#include +#include +#include + +extern char *conf_file; + +int num_lines = 1; +%} + +digit [0-9] +number ({digit})+ +snum -?({digit})+ +decimal ({number}"."{number}) +hexdigit ([a-f]|[A-F]|[0-9]) +addr1 {hexdigit}{1,4}":"({hexdigit}{1,4}":")*(":"{hexdigit}{1,4})+ +addr2 {hexdigit}{1,4}(":"{hexdigit}{1,4})*"::" +addr3 ({hexdigit}{1,4}":"){7}{hexdigit}{1,4} +addr ({addr1}|{addr2}|{addr3}|"::") +whitespace ([ \t])+ +string [a-z]([a-z]|{digit}|_)*([:.]{digit}+)? +%% + +#.*$ {/* ignore comments */} +\n {num_lines++;} +{whitespace} {} + +interface { return T_INTERFACE; } +prefix { return T_PREFIX; } +route { return T_ROUTE; } +RDNSS { return T_RDNSS; } + +IgnoreIfMissing { return T_IgnoreIfMissing; } +AdvSendAdvert { return T_AdvSendAdvert; } +MaxRtrAdvInterval { return T_MaxRtrAdvInterval; } +MinRtrAdvInterval { return T_MinRtrAdvInterval; } +AdvManagedFlag { return T_AdvManagedFlag; } +AdvOtherConfigFlag { return T_AdvOtherConfigFlag; } +AdvLinkMTU { return T_AdvLinkMTU; } +AdvReachableTime { return T_AdvReachableTime; } +AdvRetransTimer { return T_AdvRetransTimer; } +AdvCurHopLimit { return T_AdvCurHopLimit; } +AdvDefaultLifetime { return T_AdvDefaultLifetime; } +AdvDefaultPreference { return T_AdvDefaultPreference; } +AdvSourceLLAddress { return T_AdvSourceLLAddress; } + +AdvOnLink { return T_AdvOnLink; } +AdvAutonomous { return T_AdvAutonomous; } +AdvValidLifetime { return T_AdvValidLifetime; } +AdvPreferredLifetime { return T_AdvPreferredLifetime; } + +AdvRouterAddr { return T_AdvRouterAddr; } +AdvHomeAgentFlag { return T_AdvHomeAgentFlag; } +AdvIntervalOpt { return T_AdvIntervalOpt; } +AdvHomeAgentInfo { return T_AdvHomeAgentInfo; } +UnicastOnly { return T_UnicastOnly; } + +Base6to4Interface { return T_Base6to4Interface; } + +HomeAgentPreference { return T_HomeAgentPreference; } +HomeAgentLifetime { return T_HomeAgentLifetime; } + +AdvRoutePreference { return T_AdvRoutePreference; } +AdvRouteLifetime { return T_AdvRouteLifetime; } + +AdvRDNSSPreference { return T_AdvRDNSSPreference; } +AdvRDNSSOpen { return T_AdvRDNSSOpenFlag; } +AdvRDNSSLifetime { return T_AdvRDNSSLifetime; } + +MinDelayBetweenRAs { return T_MinDelayBetweenRAs; } + +AdvMobRtrSupportFlag { return T_AdvMobRtrSupportFlag; } + +{addr} { + static struct in6_addr addr; + int i; + + i = inet_pton(AF_INET6, yytext, &addr); + + dlog(LOG_DEBUG, 4, "inet_pton returned %d", i); + + /* BSD API draft and NRL's code don't aggree on + * this. the draft specifies a return value of 1 on + * success, NRL's code returns the address length in + * bytes on success (16 for an IPv6 address) + */ + if (i < 1) { + flog(LOG_ERR, "invalid address in %s, line %d", conf_file, + num_lines); + return T_BAD_TOKEN; + } + + yylval.addr = &addr; + return IPV6ADDR; + } + +{number} { + unsigned long lnum; + char *endp; + lnum = strtoul(yytext, &endp, 10); + if (*yytext == '\0' || *endp != '\0') + return T_BAD_TOKEN; + if (lnum > 0xFFFFFFFFUL) + return T_BAD_TOKEN; /* XXX */ + yylval.num = lnum; + return NUMBER; + } + +{snum} { yylval.snum = atoi(yytext); return SIGNEDNUMBER; } + +{decimal} { yylval.dec = atof(yytext); return DECIMAL; } + +infinity { return INFINITY; } + +on { yylval.bool = 1; return SWITCH; } + +off { yylval.bool = 0; return SWITCH; } + +low { yylval.snum = -1; return SIGNEDNUMBER; } + +medium { yylval.snum = 0; return SIGNEDNUMBER; } + +high { yylval.snum = 1; return SIGNEDNUMBER; } + +{string} { + static char name[IFNAMSIZ]; + + strncpy(name, yytext, IFNAMSIZ-1); + name[IFNAMSIZ-1] = '\0'; + yylval.str = name; + return STRING; + } + +"{"|"}"|";"|"/" { return *yytext; } + +. { return T_BAD_TOKEN; } +%% diff --git a/support/sdk/c/blip/driver/radvd-1.0/send.c b/support/sdk/c/blip/driver/radvd-1.0/send.c new file mode 100644 index 00000000..43145f8d --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/send.c @@ -0,0 +1,331 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +void +send_ra(int sock, struct Interface *iface, struct in6_addr *dest) +{ + uint8_t all_hosts_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + struct sockaddr_in6 addr; + struct in6_pktinfo *pkt_info; + struct msghdr mhdr; + struct cmsghdr *cmsg; + struct iovec iov; + char chdr[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct nd_router_advert *radvert; + struct AdvPrefix *prefix; + struct AdvRoute *route; + struct AdvRDNSS *rdnss; + /* XXX: we don't keep track if buff gets overflowed. In theory the sysadmin could + do that with e.g., too many advertised prefixes or routes, but buff is just so + large that this should never happen and if it does, it's admin's fault :-) */ + unsigned char buff[MSG_SIZE]; + int len = 0; + int err; + + /* First we need to check that the interface hasn't been removed or deactivated */ + if(check_device(sock, iface) < 0) { + if (iface->IgnoreIfMissing) /* a bit more quiet warning message.. */ + dlog(LOG_DEBUG, 4, "interface %s does not exist, ignoring the interface", iface->Name); + else { + flog(LOG_WARNING, "interface %s does not exist, ignoring the interface", iface->Name); + } + iface->HasFailed = 1; + } else { + /* check_device was successful, act if it has failed previously */ + if (iface->HasFailed == 1) { + flog(LOG_WARNING, "interface %s seems to have come back up, trying to reinitialize", iface->Name); + iface->HasFailed = 0; + /* XXX: reinitializes 'iface', so this probably isn't going to work until next send_ra().. */ + /* SDH : don't do this since we're not doing config the same way */ + /* reload_config(); */ + } + } + + /* Make sure that we've joined the all-routers multicast group */ + if (check_allrouters_membership(sock, iface) < 0) + flog(LOG_WARNING, "problem checking all-routers membership on %s", iface->Name); + + dlog(LOG_DEBUG, 3, "sending RA on %s", iface->Name); + + if (dest == NULL) + { + struct timeval tv; + + dest = (struct in6_addr *)all_hosts_addr; + gettimeofday(&tv, NULL); + + iface->last_multicast_sec = tv.tv_sec; + iface->last_multicast_usec = tv.tv_usec; + } + + memset((void *)&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(IPPROTO_ICMPV6); + memcpy(&addr.sin6_addr, dest, sizeof(struct in6_addr)); + + memset(&buff, 0, sizeof(buff)); + radvert = (struct nd_router_advert *) buff; + + radvert->nd_ra_type = ND_ROUTER_ADVERT; + radvert->nd_ra_code = 0; + radvert->nd_ra_cksum = 0; + + radvert->nd_ra_curhoplimit = iface->AdvCurHopLimit; + radvert->nd_ra_flags_reserved = + (iface->AdvManagedFlag)?ND_RA_FLAG_MANAGED:0; + radvert->nd_ra_flags_reserved |= + (iface->AdvOtherConfigFlag)?ND_RA_FLAG_OTHER:0; + /* Mobile IPv6 ext */ + radvert->nd_ra_flags_reserved |= + (iface->AdvHomeAgentFlag)?ND_RA_FLAG_HOME_AGENT:0; + + /* if forwarding is disabled, send zero router lifetime */ + /* SDH : disable this check too */ + /* radvert->nd_ra_router_lifetime = !check_ip6_forwarding() ? htons(iface->AdvDefaultLifetime) : 0; */ + radvert->nd_ra_flags_reserved |= + (iface->AdvDefaultPreference << ND_OPT_RI_PRF_SHIFT) & ND_OPT_RI_PRF_MASK; + + radvert->nd_ra_reachable = htonl(iface->AdvReachableTime); + radvert->nd_ra_retransmit = htonl(iface->AdvRetransTimer); + + len = sizeof(struct nd_router_advert); + + prefix = iface->AdvPrefixList; + + /* + * add prefix options + */ + + while(prefix) + { + if( prefix->enabled ) + { + struct nd_opt_prefix_info *pinfo; + + pinfo = (struct nd_opt_prefix_info *) (buff + len); + + pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pinfo->nd_opt_pi_len = 4; + pinfo->nd_opt_pi_prefix_len = prefix->PrefixLen; + + pinfo->nd_opt_pi_flags_reserved = + (prefix->AdvOnLinkFlag)?ND_OPT_PI_FLAG_ONLINK:0; + pinfo->nd_opt_pi_flags_reserved |= + (prefix->AdvAutonomousFlag)?ND_OPT_PI_FLAG_AUTO:0; + /* Mobile IPv6 ext */ + pinfo->nd_opt_pi_flags_reserved |= + (prefix->AdvRouterAddr)?ND_OPT_PI_FLAG_RADDR:0; + + pinfo->nd_opt_pi_valid_time = htonl(prefix->AdvValidLifetime); + pinfo->nd_opt_pi_preferred_time = htonl(prefix->AdvPreferredLifetime); + pinfo->nd_opt_pi_reserved2 = 0; + + memcpy(&pinfo->nd_opt_pi_prefix, &prefix->Prefix, + sizeof(struct in6_addr)); + + len += sizeof(*pinfo); + } + + prefix = prefix->next; + } + + route = iface->AdvRouteList; + + /* + * add route options + */ + + while(route) + { + struct nd_opt_route_info_local *rinfo; + + rinfo = (struct nd_opt_route_info_local *) (buff + len); + + rinfo->nd_opt_ri_type = ND_OPT_ROUTE_INFORMATION; + /* XXX: the prefixes are allowed to be sent in smaller chunks as well */ + rinfo->nd_opt_ri_len = 3; + rinfo->nd_opt_ri_prefix_len = route->PrefixLen; + + rinfo->nd_opt_ri_flags_reserved = + (route->AdvRoutePreference << ND_OPT_RI_PRF_SHIFT) & ND_OPT_RI_PRF_MASK; + rinfo->nd_opt_ri_lifetime = htonl(route->AdvRouteLifetime); + + memcpy(&rinfo->nd_opt_ri_prefix, &route->Prefix, + sizeof(struct in6_addr)); + len += sizeof(*rinfo); + + route = route->next; + } + + rdnss = iface->AdvRDNSSList; + + /* + * add rdnss options + */ + + while(rdnss) + { + struct nd_opt_rdnss_info_local *rdnssinfo; + + rdnssinfo = (struct nd_opt_rdnss_info_local *) (buff + len); + + rdnssinfo->nd_opt_rdnssi_type = ND_OPT_RDNSS_INFORMATION; + rdnssinfo->nd_opt_rdnssi_len = 1 + 2*rdnss->AdvRDNSSNumber; + rdnssinfo->nd_opt_rdnssi_pref_flag_reserved = + ((rdnss->AdvRDNSSPreference << ND_OPT_RDNSSI_PREF_SHIFT) & ND_OPT_RDNSSI_PREF_MASK); + rdnssinfo->nd_opt_rdnssi_pref_flag_reserved |= + ((rdnss->AdvRDNSSOpenFlag)?ND_OPT_RDNSSI_FLAG_S:0); + + rdnssinfo->nd_opt_rdnssi_lifetime = htonl(rdnss->AdvRDNSSLifetime); + + memcpy(&rdnssinfo->nd_opt_rdnssi_addr1, &rdnss->AdvRDNSSAddr1, + sizeof(struct in6_addr)); + memcpy(&rdnssinfo->nd_opt_rdnssi_addr2, &rdnss->AdvRDNSSAddr2, + sizeof(struct in6_addr)); + memcpy(&rdnssinfo->nd_opt_rdnssi_addr3, &rdnss->AdvRDNSSAddr3, + sizeof(struct in6_addr)); + len += sizeof(*rdnssinfo) - (3-rdnss->AdvRDNSSNumber)*sizeof(struct in6_addr); + + rdnss = rdnss->next; + } + + /* + * add MTU option + */ + + if (iface->AdvLinkMTU != 0) { + struct nd_opt_mtu *mtu; + + mtu = (struct nd_opt_mtu *) (buff + len); + + mtu->nd_opt_mtu_type = ND_OPT_MTU; + mtu->nd_opt_mtu_len = 1; + mtu->nd_opt_mtu_reserved = 0; + mtu->nd_opt_mtu_mtu = htonl(iface->AdvLinkMTU); + + len += sizeof(*mtu); + } + + /* + * add Source Link-layer Address option + */ + + if (iface->AdvSourceLLAddress && iface->if_hwaddr_len != -1) + { + uint8_t *ucp; + unsigned int i; + + ucp = (uint8_t *) (buff + len); + + *ucp++ = ND_OPT_SOURCE_LINKADDR; + *ucp++ = (uint8_t) ((iface->if_hwaddr_len + 16 + 63) >> 6); + + len += 2 * sizeof(uint8_t); + + i = (iface->if_hwaddr_len + 7) >> 3; + memcpy(buff + len, iface->if_hwaddr, i); + len += i; + } + + /* + * Mobile IPv6 ext: Advertisement Interval Option to support + * movement detection of mobile nodes + */ + + if(iface->AdvIntervalOpt) + { + struct AdvInterval a_ival; + uint32_t ival; + if(iface->MaxRtrAdvInterval < Cautious_MaxRtrAdvInterval){ + ival = ((iface->MaxRtrAdvInterval + + Cautious_MaxRtrAdvInterval_Leeway ) * 1000); + + } + else { + ival = (iface->MaxRtrAdvInterval * 1000); + } + a_ival.type = ND_OPT_RTR_ADV_INTERVAL; + a_ival.length = 1; + a_ival.reserved = 0; + a_ival.adv_ival = htonl(ival); + + memcpy(buff + len, &a_ival, sizeof(a_ival)); + len += sizeof(a_ival); + } + + /* + * Mobile IPv6 ext: Home Agent Information Option to support + * Dynamic Home Agent Address Discovery + */ + + if(iface->AdvHomeAgentInfo && + (iface->AdvMobRtrSupportFlag || iface->HomeAgentPreference != 0 || + iface->HomeAgentLifetime != iface->AdvDefaultLifetime)) + + { + struct HomeAgentInfo ha_info; + ha_info.type = ND_OPT_HOME_AGENT_INFO; + ha_info.length = 1; + ha_info.flags_reserved = + (iface->AdvMobRtrSupportFlag)?ND_OPT_HAI_FLAG_SUPPORT_MR:0; + ha_info.preference = htons(iface->HomeAgentPreference); + ha_info.lifetime = htons(iface->HomeAgentLifetime); + + memcpy(buff + len, &ha_info, sizeof(ha_info)); + len += sizeof(ha_info); + } + + iov.iov_len = len; + iov.iov_base = (caddr_t) buff; + + memset(chdr, 0, sizeof(chdr)); + cmsg = (struct cmsghdr *) chdr; + + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + + pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); + pkt_info->ipi6_ifindex = iface->if_index; + memcpy(&pkt_info->ipi6_addr, &iface->if_addr, sizeof(struct in6_addr)); + +#ifdef HAVE_SIN6_SCOPE_ID + if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&addr.sin6_addr)) + addr.sin6_scope_id = iface->if_index; +#endif + + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_name = (caddr_t)&addr; + mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *) cmsg; + mhdr.msg_controllen = sizeof(chdr); + + err = sendmsg(sock, &mhdr, 0); + + if (err < 0) { + if (!iface->IgnoreIfMissing || !(errno == EINVAL || errno == ENODEV)) + flog(LOG_WARNING, "sendmsg: %s", strerror(errno)); + else + dlog(LOG_DEBUG, 3, "sendmsg: %s", strerror(errno)); + } +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/socket.c b/support/sdk/c/blip/driver/radvd-1.0/socket.c new file mode 100644 index 00000000..082f8835 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/socket.c @@ -0,0 +1,107 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +/* Note: these are applicable to receiving sockopts only */ +#if defined IPV6_HOPLIMIT && !defined IPV6_RECVHOPLIMIT +# define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT +#endif + +#if defined IPV6_PKTINFO && !defined IPV6_RECVPKTINFO +# define IPV6_RECVPKTINFO IPV6_PKTINFO +#endif + +int +open_icmpv6_socket(void) +{ + int sock; + struct icmp6_filter filter; + int err, val; + + sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + if (sock < 0) + { + flog(LOG_ERR, "can't create socket(AF_INET6): %s", strerror(errno)); + return (-1); + } + + val = 1; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)); + if (err < 0) + { + flog(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO): %s", strerror(errno)); + return (-1); + } + + val = 2; +#ifdef __linux__ + err = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val)); +#else + err = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val)); +#endif + if (err < 0) + { + flog(LOG_ERR, "setsockopt(IPV6_CHECKSUM): %s", strerror(errno)); + return (-1); + } + + val = 255; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val)); + if (err < 0) + { + flog(LOG_ERR, "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno)); + return (-1); + } + + val = 255; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)); + if (err < 0) + { + flog(LOG_ERR, "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno)); + return (-1); + } + +#ifdef IPV6_RECVHOPLIMIT + val = 1; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val)); + if (err < 0) + { + flog(LOG_ERR, "setsockopt(IPV6_RECVHOPLIMIT): %s", strerror(errno)); + return (-1); + } +#endif + + /* + * setup ICMP filter + */ + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); + + err = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, + sizeof(filter)); + if (err < 0) + { + flog(LOG_ERR, "setsockopt(ICMPV6_FILTER): %s", strerror(errno)); + return (-1); + } + + return sock; +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/stamp-h b/support/sdk/c/blip/driver/radvd-1.0/stamp-h new file mode 100644 index 00000000..9788f702 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/stamp-h @@ -0,0 +1 @@ +timestamp diff --git a/support/sdk/c/blip/driver/radvd-1.0/stamp-h.in b/support/sdk/c/blip/driver/radvd-1.0/stamp-h.in new file mode 100644 index 00000000..e69de29b diff --git a/support/sdk/c/blip/driver/radvd-1.0/timer.c b/support/sdk/c/blip/driver/radvd-1.0/timer.c new file mode 100644 index 00000000..82d54584 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/timer.c @@ -0,0 +1,204 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996-2000 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +static struct timer_lst timers_head = { + {LONG_MAX, LONG_MAX}, + NULL, NULL, + &timers_head, &timers_head +}; + +static void alarm_handler(int sig); +int inline check_time_diff(struct timer_lst *tm, struct timeval tv); + +static void +schedule_timer(void) +{ + struct timer_lst *tm = timers_head.next; + struct timeval tv; + + gettimeofday(&tv, NULL); + + if (tm != &timers_head) + { + struct itimerval next; + + memset(&next, 0, sizeof(next)); + + timersub(&tm->expires, &tv, &next.it_value); + + signal(SIGALRM, alarm_handler); + + if ((next.it_value.tv_sec > 0) || + ((next.it_value.tv_sec == 0) && (next.it_value.tv_usec > 0))) + { + dlog(LOG_DEBUG, 4, "calling alarm: %ld secs, %ld usecs", + next.it_value.tv_sec, next.it_value.tv_usec); + + if(setitimer(ITIMER_REAL, &next, NULL)) + flog(LOG_WARNING, "schedule_timer setitimer for %ld.%ld failed: %s", + next.it_value.tv_sec, next.it_value.tv_usec, strerror(errno)); + } + else + { + dlog(LOG_DEBUG, 4, "next timer has already expired, queueing signal"); + kill(getpid(), SIGALRM); + } + } +} + +void +set_timer(struct timer_lst *tm, double secs) +{ + struct timeval tv; + struct timer_lst *lst; + sigset_t bmask, oldmask; + struct timeval firein; + + dlog(LOG_DEBUG, 3, "setting timer: %.2f secs", secs); + + firein.tv_sec = (long)secs; + firein.tv_usec = (long)((secs - (double)firein.tv_sec) * 1000000); + + dlog(LOG_DEBUG, 5, "setting timer: %ld secs %ld usecs", firein.tv_sec, firein.tv_usec); + + gettimeofday(&tv, NULL); + timeradd(&tv, &firein, &tm->expires); + + sigemptyset(&bmask); + sigaddset(&bmask, SIGALRM); + sigprocmask(SIG_BLOCK, &bmask, &oldmask); + + lst = &timers_head; + + /* the timers are in the list in the order they expire, the soonest first */ + do { + lst = lst->next; + } while ((tm->expires.tv_sec > lst->expires.tv_sec) || + ((tm->expires.tv_sec == lst->expires.tv_sec) && + (tm->expires.tv_usec > lst->expires.tv_usec))); + + tm->next = lst; + tm->prev = lst->prev; + lst->prev = tm; + tm->prev->next = tm; + + dlog(LOG_DEBUG, 5, "calling schedule_timer from set_timer context"); + schedule_timer(); + + sigprocmask(SIG_SETMASK, &oldmask, NULL); +} + +void +clear_timer(struct timer_lst *tm) +{ + sigset_t bmask, oldmask; + + sigemptyset(&bmask); + sigaddset(&bmask, SIGALRM); + sigprocmask(SIG_BLOCK, &bmask, &oldmask); + + tm->prev->next = tm->next; + tm->next->prev = tm->prev; + + tm->prev = tm->next = NULL; + + dlog(LOG_DEBUG, 5, "calling schedule_timer from clear_timer context"); + schedule_timer(); + + sigprocmask(SIG_SETMASK, &oldmask, NULL); +} + +static void +alarm_handler(int sig) +{ + struct timer_lst *tm, *back; + struct timeval tv; + gettimeofday(&tv, NULL); + tm = timers_head.next; + + /* + * This handler is called when the alarm goes off, so at least one of + * the interfaces' timers should satisfy the while condition. + * + * Sadly, this is not always the case, at least on Linux kernels: + * see http://lkml.org/lkml/2005/4/29/163. :-(. It seems some + * versions of timers are not accurate and get called up to a couple of + * hundred microseconds before they expire. + * + * Therefore we allow some inaccuracy here; it's sufficient for us + * that a timer should go off in a millisecond. + */ + + /* unused timers are initialized to LONG_MAX so we skip them */ + while (tm->expires.tv_sec != LONG_MAX && check_time_diff(tm, tv)) + { + tm->prev->next = tm->next; + tm->next->prev = tm->prev; + + back = tm; + tm = tm->next; + back->prev = back->next = NULL; + + (*back->handler)(back->data); + } + + dlog(LOG_DEBUG, 5, "calling schedule_timer from alarm_handler context"); + schedule_timer(); +} + + +void +init_timer(struct timer_lst *tm, void (*handler)(void *), void *data) +{ + memset(tm, 0, sizeof(struct timer_lst)); + tm->handler = handler; + tm->data = data; +} + +int inline +check_time_diff(struct timer_lst *tm, struct timeval tv) +{ + struct itimerval diff; + memset(&diff, 0, sizeof(diff)); + + #define ALLOW_CLOCK_USEC 1000 + + timersub(&tm->expires, &tv, &diff.it_value); + dlog(LOG_DEBUG, 5, "check_time_diff, difference: %ld sec + %ld usec", + diff.it_value.tv_sec, diff.it_value.tv_usec); + + if (diff.it_value.tv_sec <= 0) { + /* already gone, this is the "good" case */ + if (diff.it_value.tv_sec < 0) + return 1; +#ifdef __linux__ /* we haven't seen this on other OSes */ + /* still OK if the expiry time is not too much in the future */ + else if (diff.it_value.tv_usec > 0 && + diff.it_value.tv_usec <= ALLOW_CLOCK_USEC) { + dlog(LOG_DEBUG, 4, "alarm_handler clock was probably off by %ld usec, allowing %u", + tm->expires.tv_usec-tv.tv_usec, ALLOW_CLOCK_USEC); + return 2; + } +#endif /* __linux__ */ + else /* scheduled intentionally in the future? */ + return 0; + } + return 0; +} diff --git a/support/sdk/c/blip/driver/radvd-1.0/util.c b/support/sdk/c/blip/driver/radvd-1.0/util.c new file mode 100644 index 00000000..0ea15e7b --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/util.c @@ -0,0 +1,65 @@ +/* + * $Id$ + * + * Authors: + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include +#include +#include + +void +mdelay(double msecs) +{ + struct timeval tv; + + tv.tv_sec = (time_t)(msecs / 1000.0); + tv.tv_usec = (suseconds_t)((msecs - tv.tv_sec * 1000.0) * 1000.0); + + select(0,(fd_set *)NULL,(fd_set *)NULL,(fd_set *)NULL, &tv); +} + +double +rand_between(double lower, double upper) +{ + return ((upper - lower) / (RAND_MAX + 1.0) * rand() + lower); +} + +void +print_addr(struct in6_addr *addr, char *str) +{ + const char *res; + + /* XXX: overflows 'str' if it isn't big enough */ + res = inet_ntop(AF_INET6, (void *)addr, str, INET6_ADDRSTRLEN); + + if (res == NULL) + { + flog(LOG_ERR, "print_addr: inet_ntop: %s", strerror(errno)); + strcpy(str, "[invalid address]"); + } +} + +/* Check if an in6_addr exists in the rdnss list */ +int +check_rdnss_presence(struct AdvRDNSS *rdnss, struct in6_addr *addr) +{ + while (rdnss) { + if ( !memcmp(&rdnss->AdvRDNSSAddr1, addr, sizeof(struct in6_addr)) + || !memcmp(&rdnss->AdvRDNSSAddr2, addr, sizeof(struct in6_addr)) + || !memcmp(&rdnss->AdvRDNSSAddr3, addr, sizeof(struct in6_addr)) ) + break; /* rdnss address found in the list */ + else + rdnss = rdnss->next; /* no match */ + } + return (rdnss != NULL); +} diff --git a/support/sdk/c/blip/driver/radvd-wrapper.c b/support/sdk/c/blip/driver/radvd-wrapper.c new file mode 100644 index 00000000..b5562aa2 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-wrapper.c @@ -0,0 +1,162 @@ +/* + * radvd-wrapper.c + * author: Stephen Dawson-Haggerty + * + * Alternate set of call points for the IPv6 router advertisement + * daemon. Using this interface the daemon may be integrated into + * another program (like ip-driver). radvd is distributed under a + * BSD-like license. + * + * radvd_init() must be called to set up state for the specified + * interface. If successful, it will return a file descriptor; + * radvd_process() must be called whenever there is pending data on + * this descriptor (ie, from a select() loop.) + * + * radvd has its own logging infrastructure; by default radvd_init() + * sends that log to stderr and makes no attempt to integrate it with + * whatever logging facilities may be availabile. See radvd/log.c for + * more. + * + * NB: radvd uses SIGALRM for its internal timer. Thus, once + * radvd_init() has been called, SIGALRM must not be used elsewhere in + * the application. + * + */ + + +#include +#include +#include + +#include "logging.h" +#include "config.h" + +struct Interface *iface; +int sock; + +void radvd_timer_handler(void *data) { + struct Interface *iface = (struct Interface *) data; + double next; + + dlog(LOG_DEBUG, 4, "timer_handler called for %s", iface->Name); + + send_ra(sock, iface, NULL); + + next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval); + + if (iface->init_racount < MAX_INITIAL_RTR_ADVERTISEMENTS) { + iface->init_racount++; + next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, next); + } + + set_timer(&iface->tm, next); +} + + +void radvd_kickoff_adverts(void) { + init_timer(&iface->tm, radvd_timer_handler, (void *) iface); + if (iface->AdvSendAdvert) { + /* send an initial advertisement */ + send_ra(sock, iface, NULL); + + iface->init_racount++; + + set_timer(&iface->tm, + min(MAX_INITIAL_RTR_ADVERT_INTERVAL, + iface->MaxRtrAdvInterval)); + } +} + +void radvd_process() { + unsigned char msg[MSG_SIZE]; + int len, hoplimit; + struct sockaddr_in6 rcv_addr; + struct in6_pktinfo *pkt_info = NULL; + + len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit); + if (len > 0) + process(sock, iface, msg, len, + &rcv_addr, pkt_info, hoplimit); + +} + + +/* Set up all the radvd internal stuff from our own configuration */ +int radvd_init(char *ifname, struct config *c) { + struct AdvPrefix *prefix; + sigset_t oset, nset; + + + if (log_open(L_STDERR, "radvd", NULL, -1) < 0) { + error("log_open\n"); + return -1; + } + srand((unsigned int)time(NULL)); + info("starting radvd on device %s\n", ifname); + + sock = open_icmpv6_socket(); + if (sock < 0) { + error("open_icmpv6_socket\n"); + return -1; + } + sigemptyset(&nset); + sigaddset(&nset, SIGALRM); + sigprocmask(SIG_UNBLOCK, &nset, &oset); + if (sigismember(&oset, SIGALRM)) + flog(LOG_WARNING, "SIGALRM has been unblocked. Your startup environment might be wrong."); + + + /* setup the radvd struct Interface to know about all our defaults */ + iface = malloc(sizeof(struct Interface)); + if (iface == NULL) + return -1; + + iface_init_defaults(iface); + strncpy(iface->Name, ifname, IFNAMSIZ-1); + iface->Name[IFNAMSIZ-1] = '\0'; + + iface->next = NULL; + iface->AdvSendAdvert = 1; + + /* check the interface exists... this probably shouldn't fail */ + if (check_device(sock, iface) < 0) { + error("check_device!\n"); + return -1; + } + + if (setup_deviceinfo(sock, iface) < 0) { + error("setup_deviceinfo\n"); + return -1; + } + if (check_iface(iface) < 0) { + error("check_iface\n"); + return -1; + } + if (setup_linklocal_addr(sock, iface) < 0) { + error("setup_linklocal_addr\n"); + return -1; + } + if (setup_allrouters_membership(sock, iface) < 0) { + error("setup_allrouters_membership\n"); + return -1; + } + + + /* set up the prefix we're advertising from the config struct we get passed in. */ + prefix = malloc(sizeof(struct AdvPrefix)); + if (prefix == NULL) + return -1; + + prefix_init_defaults(prefix); + prefix->PrefixLen = 64; + memcpy(&prefix->Prefix, c->router_addr.s6_addr, sizeof(struct in6_addr)); + prefix->next = NULL; + + iface->AdvPrefixList = prefix; + + + // config_interface(); + radvd_kickoff_adverts(); + + return sock; +} diff --git a/support/sdk/c/blip/driver/routing.c b/support/sdk/c/blip/driver/routing.c new file mode 100644 index 00000000..f883f32c --- /dev/null +++ b/support/sdk/c/blip/driver/routing.c @@ -0,0 +1,272 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include +#include +#include +#include + +#include <6lowpan.h> +#include +#include "routing.h" +#include "nwstate.h" +#include "logging.h" +#include "config.h" + +static hw_addr_t my_short_addr; +extern struct in6_addr __my_address; + +char proxy_dev[IFNAMSIZ], tun_dev[IFNAMSIZ]; + +/* + * Call to setup routing tables. + * + */ +uint8_t routing_init(struct config *c, char *tun_name) { + nw_init(); + my_short_addr = ntohs(__my_address.s6_addr16[7]); + strncpy(proxy_dev, c->proxy_dev, IFNAMSIZ); + strncpy(tun_dev, tun_name, IFNAMSIZ); +/* nl_fd = socket(AF_NETLINK, SOCK_RAW, protocol); */ +/* if (nl_fd < 0) */ +/* return -1; */ + + return 0; +} + +/* + * @returns: truth value indicating if the destination of the packet + * is a single hop, and requires no source route. + */ +uint8_t routing_is_onehop(struct split_ip_msg *msg) { + path_t *path; + uint8_t ret = ROUTE_NO_ROUTE; + + if (cmpPfx(msg->hdr.ip6_dst.s6_addr, multicast_prefix)) + return ROUTE_ONEHOP; + + if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) { + debug("routing_is_onehop: Source header\n"); + return ROUTE_SOURCE; + } + + path = nw_get_route(my_short_addr, ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + + if (path != NULL) { + if (path->length == 1) + ret = ROUTE_ONEHOP; + else + ret = ROUTE_MHOP; + } + debug("routing_is_onehop: 0x%x\n", ret); + nw_free_path(path); + return ret; +} + +/* + * Identical to routing_insert_route, except allows for a detour route + */ +/*uint8_t routing_insert_route_indirect(struct split_ip_msg *orig, ip6_addr_t detour) { + int offset = 0; + path_t *path = nw_get_route(my_short_addr, l2fromIP(detour)); + path_t *path_second = nw_get_route(l2fromIP(detour), l2fromIP(orig->hdr.dst_addr)); + path_t *i; + struct generic_header *g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header)); + struct source_header *sh; + + debug("routing_insert_route_indirect len1: 0x%x, len2: 0x%x\n", path->length, path_second->length); + + if (ntoh16(orig->hdr.plen) + sizeof(struct source_header) + ((path->length + path_second->length) * sizeof(uint16_t)) + sizeof(struct ip6_hdr) > INET_MTU) { + warn("packet plus source header too long\n"); + return 1; + } + + sh = (struct source_header *)malloc(sizeof(struct source_header) + (path->length + path_second->length)*sizeof(uint16_t)); + if (sh == NULL || g_hdr == NULL) return 1; + + sh->nxt_hdr = orig->hdr.nxt_hdr; + sh->len = sizeof(struct source_header) + ((path->length + path_second->length) * sizeof(uint16_t)); + sh->dispatch = IP_EXT_SOURCE_DISPATCH; + sh->current = 0; + orig->hdr.nxt_hdr = NXTHDR_SOURCE; + + fprintf(stderr, "to 0x%x [%i]: ", noths(orig->hdr.ip6_dst.s6_addr16[7]), path->length + path_second->length); + for (i = path; i != NULL; i = i->next) { + fprintf(stderr, "0x%x ", i->node); + sh->hops[offset++] = hton16(i->node); + } + for (i = path_second; i != NULL; i = i->next) { + fprintf(stderr, "0x%x ", i->node); + sh->hops[offset++] = hton16(i->node); + } + + fprintf(stderr, "\n"); + + orig->hdr.plen = hton16(ntoh16(orig->hdr.plen) + sh->len); + + g_hdr->payload_malloced = 1; + g_hdr->len = sh->len; + g_hdr->hdr.sh = sh; + g_hdr->next = orig->headers; + orig->headers = g_hdr; + + nw_free_path(path); + nw_free_path(path_second); + + return 0; +} +*/ + +/* + * Copys the IP message at orig to the empty one at ret, inserting + * necessary routing information. + */ +uint8_t routing_insert_route(struct split_ip_msg *orig) { + int offset = 0; + path_t *path = nw_get_route(my_short_addr, ntohs(orig->hdr.ip6_dst.s6_addr16[7])); + path_t *i; + struct generic_header *g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header)); + struct source_header *sh; + + if (g_hdr == NULL || path == NULL) { + if (g_hdr) free(g_hdr); + if (path) nw_free_path(path); + return 1; + } + if (path->length == 1) { + free(g_hdr); + nw_free_path(path); + return 1; + } + debug("routing_insert_route len: 0x%x\n", path->length); + + // if the packet with the source route is longer then the buffer + // we're putting it into, drop it. + if (ntoh16(orig->hdr.plen) + sizeof(struct source_header) + + (path->length * sizeof(uint16_t)) + sizeof(struct ip6_hdr) > INET_MTU) { + warn("packet plus source header too long\n"); + free(g_hdr); + nw_free_path(path); + return 1; + } + + sh = (struct source_header *)malloc(sizeof(struct source_header) + path->length * sizeof(uint16_t)); + if (sh == NULL) { + free (g_hdr); + nw_free_path(path); + return 1; + } + + sh->nxt_hdr = orig->hdr.nxt_hdr; + sh->len = sizeof(struct source_header) + (path->length * sizeof(uint16_t)); + sh->dispatch = IP_EXT_SOURCE_DISPATCH | IP_EXT_SOURCE_CONTROLLER; + sh->current = 0; + + orig->hdr.nxt_hdr = NXTHDR_SOURCE; + + log_clear(LOGLVL_DEBUG, "to 0x%x [%i]: ", ntohs(orig->hdr.ip6_dst.s6_addr16[7]), path->length); + for (i = path; i != NULL; i = i->next) { + log_clear(LOGLVL_DEBUG, "0x%x ", i->node); + sh->hops[offset++] = hton16(i->node); + } + log_clear(LOGLVL_DEBUG, "\n"); + + orig->hdr.plen = hton16(ntoh16(orig->hdr.plen) + sh->len); + + g_hdr->payload_malloced = 1; + g_hdr->len = sh->len; + g_hdr->hdr.sh = sh; + g_hdr->next = orig->headers; + orig->headers = g_hdr; + + nw_free_path(path); + + return 0; + +} + +/* + * Returns the address of the next router this packet should be send to. + */ +hw_addr_t routing_get_nexthop(struct split_ip_msg *msg) { + hw_addr_t ret = 0xffff;; + path_t * path; + if (cmpPfx(msg->hdr.ip6_dst.s6_addr, multicast_prefix)) + return ret; + + // If it's source routed, just grab the next hop out of the header + if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) { + debug("routing_get_nexthop: src header\n"); + return ntoh16((msg->headers->hdr.sh->hops[msg->headers->hdr.sh->current])); + } + + path = nw_get_route(my_short_addr, ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + + if (path != NULL) + ret = path->node; + + nw_free_path(path); + + return ret; +} + +void routing_proc_msg(struct split_ip_msg *msg) { + struct generic_header *g_hdr, **prev_hdr; + uint8_t *prev_next, nxt_hdr = msg->hdr.nxt_hdr; + int i; + node_id_t reporter = ntohs(msg->hdr.ip6_src.s6_addr16[7]); + + prev_next = &msg->hdr.nxt_hdr; + prev_hdr = &msg->headers; + + nw_report_node(reporter); + for (g_hdr = msg->headers; g_hdr != NULL; g_hdr = g_hdr->next) { + if (nxt_hdr == NXTHDR_TOPO) { + // add the topology reports to the database + nw_unmark_links(reporter); + for (i = 0; i < (g_hdr->len - sizeof(struct topology_header))/sizeof(struct topology_entry); i++) { + //debug("topo neigh: 0x%x hop: %i qual: 0x%x\n", g_hdr->hdr.th->topo[i].hwaddr, + // g_hdr->hdr.th->topo[i].hops, g_hdr->hdr.th->topo[i].link); + nw_add_incr_edge(reporter, &g_hdr->hdr.th->topo[i]); + } + nw_clear_unmarked(reporter); + // remove the topology header + *prev_next = g_hdr->hdr.ext->nxt_hdr; + *prev_hdr = g_hdr->next; + if (g_hdr->payload_malloced) free(g_hdr->hdr.data); + msg->hdr.plen = hton16(ntoh16(msg->hdr.plen) - g_hdr->len); + free(g_hdr); + return; + } else { + nxt_hdr = g_hdr->hdr.ext->nxt_hdr; + prev_next = &g_hdr->hdr.ext->nxt_hdr; + prev_hdr = &g_hdr->next; + } + } +} + + +void routing_add_table_entry(node_id_t id) { + /* static const char* route_add_fmt = "ip -6 route add %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x/128 dev %s"; */ + /* static const char* route_proxy_fmt = "ip -6 neigh add proxy %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x dev %s"; */ + +} diff --git a/support/sdk/c/blip/driver/routing.h b/support/sdk/c/blip/driver/routing.h new file mode 100644 index 00000000..cfb31934 --- /dev/null +++ b/support/sdk/c/blip/driver/routing.h @@ -0,0 +1,71 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef __ROUTING_H_ +#define __ROUTING_H_ + +#include +#include +#include "nwstate.h" +#include "config.h" + +enum { + ROUTE_NO_ROUTE, + ROUTE_ONEHOP, + ROUTE_MHOP, + ROUTE_SOURCE, +}; + + +uint8_t routing_init(struct config *c, char *tun_dev); + +/* + * @returns: truth value indicating if the destination of the packet + * is a single hop, and requires no source route. + */ +uint8_t routing_is_onehop(struct split_ip_msg *msg); + + +/* + * Copys the IP message at orig to the empty one at ret, inserting + * necessary routing information. + */ +uint8_t routing_insert_route(struct split_ip_msg *orig); + +/* + * Returns the address of the next router this packet should be send to. + */ +hw_addr_t routing_get_nexthop(struct split_ip_msg *msg); + + +/* + * Called for all reconstructed packets off serial. + * allows the router to inpect and remove any extra headers in the message. + */ +void routing_proc_msg(struct split_ip_msg *msg); + +/* + * Update kernel routing state to reflect a new node + */ +void routing_add_table_entry(node_id_t id); + + +#endif diff --git a/support/sdk/c/blip/driver/serial_tun.c b/support/sdk/c/blip/driver/serial_tun.c new file mode 100644 index 00000000..0462f35a --- /dev/null +++ b/support/sdk/c/blip/driver/serial_tun.c @@ -0,0 +1,1108 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* + * Copyright (c) 2007 Matus Harvan + * All rights reserved + * + * Copyright (c) 2008 Stephen Dawson-Haggerty + * Extensivly modified to use lib6lowpan / b6lowpan. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tun_dev.h" +#include "serialsource.h" +#include "serialpacket.h" +#include "serialprotocol.h" +#include "sfsource.h" + +#include "6lowpan.h" +#include "ip.h" +#include "lib6lowpan.h" +#include "IEEE154.h" +#include "routing.h" +#include "devconf.h" +#include "logging.h" +#include "config.h" +#include "nwstate.h" + +#define min(a,b) ( (a>b) ? b : a ) +#define max(a,b) ( (a>b) ? a : b ) + +int tun_fd, radvd_fd = -1; +int radvd_init(char *ifname, struct config *c); +void radvd_process(); + +#ifndef SIM +serial_source ser_src; +#define write_pan_packet(DATA, LEN) write_serial_packet(ser_src, DATA, LEN) +#define read_pan_packet(LENP) read_serial_packet(ser_src, LENP) +#else +int sf_fd; +#define write_pan_packet(DATA, LEN) write_sf_packet(sf_fd, DATA, LEN) +#define read_pan_packet(LENP) read_sf_packet(sf_fd, LENP) +#endif + +enum { + N_RECONSTRUCTIONS = 10, +}; + +/* + * This is not the right way to detect we're on that platform, but I + * can't find a better macro. + */ +#ifdef __TARGET_mips__ +char *def_configfile = "/etc/lowpan/serial_tun.conf"; +#else +char *def_configfile = "serial_tun.conf"; +#endif + +#ifdef DBG_TRACK_FLOWS +FILE *dbg_file; +#endif + + +extern struct in6_addr __my_address; +uint16_t local_seqno = 0; + +volatile sig_atomic_t config_success = 0; +struct config driver_config; +char dev[IFNAMSIZ]; +struct { + time_t boot_time; + unsigned long tx_pkts; + unsigned long tx_frags; + unsigned long tx_bytes; + unsigned long rx_pkts; + unsigned long rx_frags; + unsigned long rx_bytes; + unsigned long fw_pkts; +} stats = {0, 0, 0, 0, 0, 0, 0, 0}; + + +/* ------------------------------------------------------------------------- */ + +void stderr_msg(serial_source_msg problem) +{ + // fprintf(stderr, "Note: %s\n", msgs[problem]); +} + + +void print_ip_packet(struct split_ip_msg *msg) { + int i; + struct generic_header *g_hdr; + if (log_getlevel() > LOGLVL_DEBUG) return; + + printf(" nxthdr: 0x%x hlim: 0x%x\n", msg->hdr.nxt_hdr, msg->hdr.hlim); + printf(" src: "); + for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.ip6_src.s6_addr[i]); + printf("\n"); + printf(" dst: "); + for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.ip6_dst.s6_addr[i]); + printf("\n"); + + g_hdr = msg->headers; + while (g_hdr != NULL) { + printf("header [%i]: ", g_hdr->len); + for (i = 0; i < g_hdr->len; i++) + printf("0x%x ", g_hdr->hdr.data[i]); + printf("\n"); + g_hdr = g_hdr->next; + } + + printf("data [%i]:\n\t", msg->data_len); + for (i = 0; i < msg->data_len; i++) { + if (i == 0x40) { + printf (" ...\n"); + break; + } + printf("0x%x ", msg->data[i]); + if (i % 16 == 15) printf("\n\t"); + if (i % 16 == 7) printf (" "); + } + printf("\n"); +} + +/* + * frees the linked list structs, and their payloads if we have + * malloc'ed them at some other point. + * + * does not free the payload buffer or the actual split_ip_msg struct, + * since those are malloc'ed seperatly in this implementation. + */ +void free_split_msg(struct split_ip_msg *msg) { + struct generic_header *cur, *next; + cur = msg->headers; + while (cur != NULL) { + next = cur->next; + if (cur->payload_malloced) + free(cur->hdr.data); + free(cur); + cur = next; + } +} + +void configure_timeout() { + if (config_success == 0) { + fatal("configuring interface failed! aborting!\n"); + exit(2); + } else { + signal(SIGALRM, SIG_DFL); + } +} + +void configure_reboot() { + uint8_t buf[sizeof(config_cmd_t) + 1]; + config_cmd_t *cmd = (config_cmd_t *)(&buf[1]); + memset(buf, 0, sizeof(config_cmd_t) + 1); + buf[0] = TOS_SERIAL_DEVCONF; + cmd->cmd = CONFIG_REBOOT; + + signal(SIGALRM, configure_timeout); + write_pan_packet(buf, CONFIGURE_MSG_SIZE + 1); + alarm(5); +} + +void configure_setparms(struct config *c) { + uint8_t buf[sizeof(config_cmd_t) + 1]; + config_cmd_t *cmd = (config_cmd_t *)(&buf[1]); + memset(buf, 0, sizeof(config_cmd_t) + 1); + buf[0] = TOS_SERIAL_DEVCONF; + cmd->cmd = CONFIG_SET_PARM; + cmd->rf.addr = c->router_addr.s6_addr16[7]; // is network byte-order + cmd->rf.channel = c->channel; + cmd->retx.retries = htons(10); + cmd->retx.delay = htons(30); + + write_pan_packet(buf, CONFIGURE_MSG_SIZE + 1); +} + + +/* ------------------------------------------------------------------------- */ +/* + * the first byte the TOS serial stack sends is a dispatch byte. One + * dispatch value is for forwarded 802;.15.4 packets; we use a few + * others to talk directly to the attached IPBaseStation. + */ +void handle_other_pkt(uint8_t *data, int len) { + config_reply_t *rep; + switch (data[0]) { + case TOS_SERIAL_DEVCONF: + rep = (config_reply_t *)(&data[1]); + debug("interface configured (0x%x) addr: 0x%x\n", rep->error, ntohs(rep->addr)); + switch (rep->error) { + case CONFIG_ERROR_BOOTED: + configure_setparms(&driver_config); + break; + default: + info("interface device successfully initialized\n"); + config_success = 1; + + /* put this here because we already use SIGALRM for the + configure timeout, and radvd needs it for its own timer. */ + if ((radvd_fd = radvd_init(dev, &driver_config)) < 0) { + fatal("radvd init failed!\n"); + exit(1); + } + } + break; + default: + warn("received serial packet with unknown dispatch 0x%x\n",data[0]); + log_dump_serial_packet(data, len); + } +} + + +/* ------------------------------------------------------------------------- */ +/* handling of data arriving on the tun interface */ +void write_radio_header(uint8_t *serial, hw_addr_t dest, uint16_t payload_len) { +#ifndef SIM + IEEE154_header_t *radioPacket = (IEEE154_header_t *)(serial + 1); + radioPacket->length = payload_len + MAC_HEADER_SIZE + MAC_FOOTER_SIZE +#ifdef DBG_TRACK_FLOWS + + sizeof(struct flow_id); +#else + ; +#endif + // don't include the length byte + radioPacket->fcf = htons(0x4188); + // dsn will get set on mote + radioPacket->destpan = 0; + radioPacket->dest = htole16(dest); + // src will get set on mote + + serial[0] = SERIAL_TOS_SERIAL_802_15_4_ID; +#else + serial_header_t *serialHeader = (serial_header_t *)(serial + 1); + serialHeader->length = payload_len +#ifdef DBG_TRACK_FLOWS + + sizeof(struct flow_id); +#else + ; +#endif + serialHeader->dest = htons(dest); + serialHeader->type = 0; + + serial[0] = 0; +#endif +} + +void send_fragments (struct split_ip_msg *msg, hw_addr_t dest) { + int result; + uint16_t frag_len; + fragment_t progress; + uint8_t serial[LOWPAN_LINK_MTU + 1]; +#ifndef SIM + IEEE154_header_t *radioPacket = (IEEE154_header_t *)(serial + 1); +#define PKTLEN(X) ((X)->length + 2) +#else + serial_header_t *radioPacket = (serial_header_t *)(serial + 1); +#define PKTLEN(X) ((X)->length + sizeof(serial_header_t) + 1) +#endif + + uint8_t *lowpan = (uint8_t *)(radioPacket + 1); + +#ifdef DBG_TRACK_FLOWS +#define LOWPAN_PAYLOAD_LENGTH (LOWPAN_LINK_MTU - MAC_HEADER_SIZE \ + - MAC_FOOTER_SIZE - sizeof(struct flow_id)) + lowpan += sizeof(struct flow_id); +#else +#define LOWPAN_PAYLOAD_LENGTH (LOWPAN_LINK_MTU - MAC_HEADER_SIZE \ + - MAC_FOOTER_SIZE) +#endif + + progress.offset = 0; + + // and IEEE 802.15.4 header + // write_radio_header(serial, dest, frag_len); +#ifdef DBG_TRACK_FLOWS +#ifndef SIM + ip_memcpy(serial + 1 + sizeof(IEEE154_header_t), &msg->id, sizeof(struct flow_id)); +#else + ip_memcpy(serial + 1 + sizeof(serial_header_t), &msg->id, sizeof(struct flow_id)); +#endif + if (dest != 0xffff) { + fprintf(dbg_file, "DEBUG (%i): %i\t%i\t%i\t%i\t%i\t%i\t%i\n", + 100, msg->id.src, msg->id.dst, msg->id.id, msg->id.seq, + msg->id.nxt_hdr, 100, dest); + fflush(dbg_file); + } +#endif + + while ((frag_len = getNextFrag(msg, &progress, lowpan, + LOWPAN_PAYLOAD_LENGTH)) > 0) { + + //debug("frag len: 0x%x offset: 0x%x plen: 0x%x\n", frag_len, progress.offset * 8, ntohs(ip_header->plen)); + + write_radio_header(serial, dest, frag_len); + + // if this is sent too fast, the base station can't keep up. The effect of this is + // we send incomplete fragment. 25ms seems to work pretty well. + // usleep(30000); + // 6-9-08 : SDH : this is a bad fix that does not address the + // problem. + // at the very least, the serial ack's seem to be + // working, so we should be retrying if the ack is failing + // because the hardware cannot keep up. +#ifdef __TARGET_mips__ + usleep(50000); +#endif + + log_dump_serial_packet(serial, PKTLEN(radioPacket)); + result = write_pan_packet(serial, PKTLEN(radioPacket)); + if (result != 0) + result = write_pan_packet(serial, PKTLEN(radioPacket)); + + debug("send_fragments: result: 0x%x len: 0x%x\n", result, frag_len); + log_dump_serial_packet(serial, PKTLEN(radioPacket)); + stats.tx_frags++; + stats.tx_bytes += PKTLEN(radioPacket); + } + stats.tx_pkts++; +} + +void icmp_unreachable(struct split_ip_msg *msg) { + +} + +/* + * this function takes a complete IP packet, and sends it out to a + * destination in the PAN. It will insert source routing headers and + * recompute L4 checksums as necessary. + * + */ +uint8_t ip_to_pan(struct split_ip_msg *msg) { + uint16_t dest; + + debug("ip_to_pan\n"); + print_ip_packet(msg); + + // if this packet has a source route (rinstall header, or prexisting + // source header, we don't want to mess with it + switch (routing_is_onehop(msg)) { + case ROUTE_MHOP: + debug("Multihop packet"); + if (routing_insert_route(msg)) goto fail; + break; + + case ROUTE_NO_ROUTE: + info("destination unreachable: 0x%x: dropping\n", ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + return 0; + } + + + dest = routing_get_nexthop(msg); + debug("next hop: 0x%x\n", dest); + send_fragments(msg, dest); + return 0; + fail: + error("ip_to_pan: no route to host\n"); + return 1; +} + +void upd_source_route(struct source_header *sh, hw_addr_t addr) { + if (sh->current < SH_NENTRIES(sh)) { + sh->hops[sh->current] = leton16(addr); + sh->current++; + } +} + +int remove_sourceroute(struct split_ip_msg *msg) { + struct source_header *sh; + struct rinstall_header *rih; + struct generic_header *g_hdr; + uint8_t removeSource = 1; + if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) { + sh = msg->headers->hdr.sh; + upd_source_route(sh, msg->metadata.sender); + + // Our thinking here is that if something is source_routed + // from inside the network and it is not destined to us + // then its either a rinstall being forwarded, or a path + // that's been set up, so we shouldn't strip it away + if (cmpPfx(msg->hdr.ip6_dst.s6_addr, __my_address.s6_addr) && + msg->hdr.ip6_dst.s6_addr16[7] != __my_address.s6_addr16[7]) { +/* ((msg->hdr.ip6_dst.s6_addr[14] != __my_address[14] || */ +/* msg->hdr.ip6_dst.s6_addr[15] != __my_address[15]))) { */ + info("Packet with source header not destined for me\n"); + + if ((sh->dispatch & IP_EXT_SOURCE_INVAL) != IP_EXT_SOURCE_INVAL) { + debug("Removing invalid source header\n"); + removeSource = 0; + } + + if ((sh->dispatch & IP_EXT_SOURCE_CONTROLLER) == IP_EXT_SOURCE_CONTROLLER) { + debug("WE sent this packet! dropping...\n"); + return 1; + } + + + // If this is an rinstall header moving through, we need to + // updated the current position of the path, similar to + // what we do for source headers. + if (sh->nxt_hdr == NXTHDR_INSTALL) { + rih = msg->headers->next->hdr.rih; + rih->current++; + info("Incrementing current of rih to 0x%x\n", rih->current); + } + } + if (removeSource) { + msg->hdr.nxt_hdr = sh->nxt_hdr; + msg->hdr.plen = htons(ntohs(msg->hdr.plen) - sh->len); + g_hdr = msg->headers; + msg->headers = msg->headers->next; + free(g_hdr); + } + } + return 0; +} + + +void handle_serial_packet(struct split_ip_msg *msg) { + path_t* tPath; + path_t* i; +#ifdef DBG_TRACK_FLOWS + uint8_t flags = 0x00; +#endif + if (ntohs(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) { + warn("handle_ip_packet: too long: 0x%x\n", ntohs(msg->hdr.plen)); + return; + } + + // print_ip_packet(msg); + // if this packet has a source route that we inserted, we need to + // drop it to prevent loops. + if (remove_sourceroute(msg)) + return; + routing_proc_msg(msg); + remove_sourceroute(msg); + + if (cmpPfx(msg->hdr.ip6_dst.s6_addr, __my_address.s6_addr) && + msg->hdr.ip6_dst.s6_addr16[7] != __my_address.s6_addr16[7]) { +/* ((msg->hdr.ip6_dst.s6_addr[14] != __my_address[14] || */ +/* msg->hdr.ip6_dst.s6_addr[15] != __my_address[15]))) { */ + info("Received packet destined to 0x%x\n", msg->hdr.ip6_dst.s6_addr[15]); + + // If this packet is not source routed, check to see if we're on the best path before + // issuing a route install + if (msg->hdr.nxt_hdr != NXTHDR_SOURCE) { + tPath = nw_get_route(ntohs(msg->hdr.ip6_src.s6_addr16[7]), ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + for (i = tPath; i != NULL; i = i->next) { + if (i->node == ntohs(__my_address.s6_addr16[7])) { + info("Not installing route for packet from 0x%x to 0x%x (on best path)\n", + ntohs(msg->hdr.ip6_src.s6_addr16[7]), ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + nw_free_path(tPath); + ip_to_pan(msg); + return; + } + } + nw_free_path(tPath); + } + + // We send the route installation packet before forwarding the actual + // packet, with the thinking being that the route can be set up, in + // case acks are issued by the destination on the packet + // + // We have to first select the flags that we want: + + // At this point, if it's not source routed, then this packet + // shouldn't be coming through us so we install a route + if (msg->hdr.nxt_hdr != NXTHDR_SOURCE) { + info("installing route for packet from 0x%x to 0x%x\n", + ntohs(msg->hdr.ip6_src.s6_addr16[7]), ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + } else { + info("Packet had a source header so no route install\n"); + } + stats.fw_pkts++; + ip_to_pan(msg); + // do routing + } else { + // give it to linux + // need to remove route info here. + stats.rx_pkts++; + tun_write(tun_fd, msg); + debug("tun_write: wrote 0x%x bytes\n", sizeof(struct ip6_hdr) + ntohs(msg->hdr.plen)); + } +} + +void add_header_list(struct split_ip_msg *msg) { + uint8_t nxt_hdr; + struct generic_header *g_hdr, **g_list; + struct ip6_ext *ext = (struct ip6_ext *)msg->next; + uint16_t hdr_len = 0; + debug("add_header_list for message destined to 0x%x\n", ntohs(msg->hdr.ip6_dst.s6_addr16[7])); + nxt_hdr = msg->hdr.nxt_hdr; + msg->headers = NULL; + g_list = &(msg->headers); + while (KNOWN_HEADER(nxt_hdr)) { + g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header)); + g_hdr->payload_malloced = 0; + g_hdr->hdr.ext = ext; + g_hdr->next = NULL; + *g_list = g_hdr; + g_list = &g_hdr->next; + + switch(nxt_hdr) { + case IANA_UDP: + // a UDP header terminates a chain of headers we can compress... + g_hdr->len = sizeof(struct udp_hdr); + ext = (struct ip6_ext *)(((uint8_t *)ext) + sizeof(struct udp_hdr)); + nxt_hdr = NXTHDR_UNKNOWN; + break; + // XXX : SDH : these are all "ip extension" headers and so can be treated genericlly. + case NXTHDR_INSTALL: + info("inserted NXTHDR_INSTALL\n"); + case NXTHDR_TOPO: + case NXTHDR_SOURCE: + g_hdr->len = ext->len; + + nxt_hdr = ext->nxt_hdr; + ext = (struct ip6_ext *)(((uint8_t *)ext) + ext->len); + break; + default: + // TODO : SDH : discard the packet here since we can get in a + // bad place with invalid header types. this isn't all that + // likely, but you never know. + break; + } + hdr_len += g_hdr->len; + } + msg->data = (uint8_t *)ext; + msg->data_len = ntohs(msg->hdr.plen) - hdr_len; +} + +/* + * read data from the tun device and send it to the serial port + * does also fragmentation + */ +int tun_input() +{ + uint8_t buf[sizeof(struct split_ip_msg) + INET_MTU]; + struct split_ip_msg *msg = (struct split_ip_msg *)buf; + int len; + + len = tun_read(tun_fd, (void *)(&msg->pi), INET_MTU + sizeof(struct ip6_hdr)); + + if (len <= 0) { + return 0; + } + debug("tun_read: read 0x%x bytes\n", len); + + if ((msg->hdr.vlfc[0] >> 4) != IPV6_VERSION) { + warn("tun_read: discarding non-ip packet\n"); + goto fail; + } + if (ntohs(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) { + debug("tun_input: dropping packet due to length: 0x%x\n", ntohs(msg->hdr.plen)); + goto fail; + } + if (msg->hdr.nxt_hdr == 0) { + debug("tun_input: dropping packet with IPv6 options\n"); + goto fail; + } + + add_header_list(msg); +#ifdef DBG_TRACK_FLOWS + msg->id.src = 100; + msg->id.dst = ntohs(msg->hdr.ip6_dst.s6_addr16[7]); //l2fromIP(msg->hdr.dst_addr); + msg->id.id = local_seqno++; + msg->id.seq = 0; + msg->id.nxt_hdr = msg->hdr.nxt_hdr; +#endif + + ip_to_pan(msg); + + free_split_msg(msg); + + return 1; + fail: + /* error("Invalid packet or version received\n"); */ + return 1; +} + +/* ------------------------------------------------------------------------- */ +/* handling of data arriving on the serial port */ + +reconstruct_t reconstructions [N_RECONSTRUCTIONS]; + +void age_reconstructions() { + int i; + for (i = 0; i < N_RECONSTRUCTIONS; i++) { + // switch "active" buffers to "zombie" + if (reconstructions[i].timeout == T_ACTIVE) { + reconstructions[i].timeout = T_ZOMBIE; + } else if (reconstructions[i].timeout == T_ZOMBIE) { + reconstructions[i].timeout = T_UNUSED; + free(reconstructions[i].buf); + reconstructions[i].buf = NULL; + } + } +} + + +reconstruct_t *getReassembly(packed_lowmsg_t *lowmsg) { + int i, free_spot = N_RECONSTRUCTIONS + 1; + uint16_t mytag, size; + if (getFragDgramTag(lowmsg, &mytag)) return NULL; + if (getFragDgramSize(lowmsg, &size)) return NULL; + + for (i = 0; i < N_RECONSTRUCTIONS; i++) { + if (reconstructions[i].timeout > T_UNUSED && reconstructions[i].tag == mytag) { + reconstructions[i].timeout = T_ACTIVE; + return &(reconstructions[i]); + } + if (reconstructions[i].timeout == T_UNUSED) free_spot = i; + } + // allocate a new struct for doing reassembly. + if (free_spot != N_RECONSTRUCTIONS + 1) { + // if we don't get the packet with the protocol in it first, we + // don't know who to ask for a buffer, and so give up. + + reconstructions[free_spot].tag = mytag; + + reconstructions[free_spot].size = size; + reconstructions[free_spot].buf = malloc(size + offsetof(struct split_ip_msg, hdr)); + reconstructions[free_spot].bytes_rcvd = 0; + reconstructions[free_spot].timeout = T_ACTIVE; + + debug("checking buffer size 0x%x\n", reconstructions[free_spot].size); + if (reconstructions[free_spot].buf == NULL) { + reconstructions[free_spot].timeout = T_UNUSED; + return NULL; + } + return &(reconstructions[free_spot]); + } + return NULL; +} + +/* + * read data on serial port and send it to the tun interface + * does fragment reassembly + */ +int serial_input() { + packed_lowmsg_t pkt; + reconstruct_t *recon; + struct split_ip_msg *msg; +#ifndef SIM + IEEE154_header_t *mac_hdr; +#else + serial_header_t *mac_hdr; +#endif + + uint8_t *ser_data = NULL; /* data read from serial port */ + int ser_len = 0; /* length of data read from serial port */ + uint8_t shortMsg[INET_MTU]; + uint8_t *payload; +#ifdef DBG_TRACK_FLOWS + struct flow_id *fl_id; +#endif + + int rv = 1; + + /* read data from serial port */ + ser_data = (uint8_t *)read_pan_packet(&ser_len); + + /* process the packet we have received */ + if (ser_len && ser_data) { +#ifndef SIM + if (ser_data[0] != TOS_SERIAL_802_15_4_ID) { + handle_other_pkt(ser_data, ser_len); + goto discard_packet; + } + mac_hdr = (IEEE154_header_t *)(ser_data + 1); + +#ifdef DBG_TRACK_FLOWS + fl_id = (struct flow_id *)(ser_data + 1 + sizeof(IEEE154_header_t)); + + // size is one for the length byte, minus two for the checksum + pkt.len = mac_hdr->length - MAC_HEADER_SIZE - MAC_FOOTER_SIZE - sizeof(struct flow_id); + // add one for the dispatch byte. + pkt.data = ser_data + 1 + sizeof(IEEE154_header_t) + sizeof(struct flow_id); +#else + // size is one for the length byte, minus two for the checksum + pkt.len = mac_hdr->length - MAC_HEADER_SIZE - MAC_FOOTER_SIZE; + // add one for the dispatch byte. + pkt.data = ser_data + 1 + sizeof(IEEE154_header_t); +#endif // DBG_TRACK_FLOWS + + // for some reason these are little endian so we don't do any conversion. + pkt.src = mac_hdr->src; + pkt.dst = mac_hdr->dest; +#else + mac_hdr = (serial_header_t *)(ser_data + 1); + + if (mac_hdr->type != 0) { + goto discard_packet; + } + +#ifdef DBG_TRACK_FLOWS + fl_id = (struct flow_id *)(ser_data + 1 + sizeof(serial_header_t)); + pkt.len = mac_hdr->length - sizeof(struct flow_id); + pkt.data = ser_data + 1 + sizeof(serial_header_t) + sizeof(struct flow_id); +#else + pkt.len = mac_hdr->length;; + pkt.data = ser_data + 1 + sizeof(serial_header_t); +#endif // DBG_TRACK_FLOWS + + // except in serial packets, they __are__ little endian... + pkt.src = ntohs(mac_hdr->src); + pkt.dst = ntohs(mac_hdr->dest); +#endif + + debug("serial_input: read 0x%x bytes\n", ser_len); + + pkt.headers = getHeaderBitmap(&pkt); + if (pkt.headers == LOWPAN_NALP_PATTERN) goto discard_packet; + + stats.rx_frags++; + stats.rx_bytes += ser_len - 1; + if (hasFrag1Header(&pkt) || hasFragNHeader(&pkt)) { + unpack_info_t u_info; + uint8_t amount_here; + + recon = getReassembly(&pkt); + if (recon == NULL || recon->buf == NULL) goto discard_packet; + msg = (struct split_ip_msg *)recon->buf; + + if (hasFrag1Header(&pkt)) { + if (unpackHeaders(&pkt, &u_info, + (uint8_t *)&msg->hdr, recon->size) == NULL) goto discard_packet; + amount_here = pkt.len - (u_info.payload_start - pkt.data); + ip_memcpy(u_info.header_end, u_info.payload_start, amount_here); + recon->bytes_rcvd = sizeof(struct ip6_hdr) + u_info.payload_offset + amount_here; + } else { + uint8_t offset_cmpr; + uint16_t offset; + if (getFragDgramOffset(&pkt, &offset_cmpr)) goto discard_packet; + offset = offset_cmpr * 8; + payload = getLowpanPayload(&pkt); + amount_here = pkt.len - (payload - pkt.data); + + if (offset + amount_here > recon->size) goto discard_packet; + ip_memcpy(((uint8_t *)&msg->hdr) + offset, payload, amount_here); + recon->bytes_rcvd += amount_here; + + if (recon->size == recon->bytes_rcvd) { + // got all the fragments... + debug ("serial: reconstruction finished\n"); + add_header_list(msg); + + msg->metadata.sender = pkt.src; + + handle_serial_packet(msg); + + recon->timeout = T_UNUSED; + free_split_msg(msg); + free(recon->buf); + } + } + + } else { + unpack_info_t u_info; + u_info.rih = NULL; + msg = (struct split_ip_msg *)shortMsg; + if (unpackHeaders(&pkt, &u_info, + (uint8_t *)&msg->hdr, INET_MTU) == NULL) goto discard_packet; + if (ntohs(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) goto discard_packet; + + msg->metadata.sender = pkt.src; + if (u_info.rih != NULL) + info("Has a rinstall_header for src 0x%x with match: 0x%x\n", + pkt.src, ntohs(u_info.rih->match.dest));; + + ip_memcpy(u_info.header_end, u_info.payload_start, ntohs(msg->hdr.plen)); +#ifdef DBG_TRACK_FLOWS + ip_memcpy(&msg->id, fl_id, sizeof(struct flow_id)); +#endif + + add_header_list(msg); + + handle_serial_packet(msg); + free_split_msg(msg); + } + } else { + //printf("no data on serial port, but FD triggered select\n"); + rv = 0; + } + discard_packet: + // debug("serial_input: discard packet\n"); + free(ser_data); + return rv; +} + +void print_stats() { + printf("Up since %s", ctime(&stats.boot_time)); + printf(" receive packets: %lu fragments: %lu bytes: %lu\n", + stats.tx_pkts, stats.tx_frags, stats.tx_bytes); + printf(" transmit packets: %lu fragments: %lu bytes: %lu\n", + stats.rx_pkts, stats.rx_frags, stats.rx_bytes); + printf(" forward packets: %lu\n", stats.fw_pkts); +} + +int eval_cmd(char *cmd) { + char arg[1024]; + int int_arg; + switch (cmd[0]) { + case 'c': + config_print(&driver_config); + return 0; + case 'd': + if (sscanf(cmd, "d %s\n", arg) == 1) { + nw_print_dotfile(arg); + } else { + printf("error: include a filename!\n"); + } + return 0; + case 'i': + if (sscanf(cmd, "i %i\n", &int_arg) == 1) { + info("invalidating node 0x%x\n", int_arg); + nw_inval_node(int_arg); + } + return 0; + case 'l': + nw_print_links(); + return 0; + case 'p': + nw_print_routes(); + return 0; + case 's': + print_stats(); + return 0; + case 't': + nw_test_routes(); + return 0; + case 'v': + if (sscanf(cmd, "v %s\n", arg) == 1) { + int i; + for (i = 0; i < 5; i++) { + if (strcmp(log_names[i], arg) == 0) { + printf("setting verbosity to %s\n", log_names[i]); + log_setlevel(i); + } + } + } + return 0; + case 'h': + default: + printf("ip-driver console\n"); + printf(" c: print configuration info\n"); + printf(" d : print dot-file of topology\n"); + printf(" i : invalidate a router\n"); + printf(" l: print link detail\n"); + printf(" p: print routes\n"); + printf(" t: recalculate routes\n"); + printf(" v {DEBUG INFO WARN ERROR FATAL}: set verbosity\n"); + printf(" s: print statistics\n"); + printf("\n"); + printf(" h: print this help\n"); + } + + return 0; +} + +/* shifts data between the serial port and the tun interface */ +int serial_tunnel(int tun_fd) { + char cmd_buf[2][1024], *cmd_cur; + int cur_buf = 0; + fd_set fs; + int maxfd = 0; + time_t last_aging, current_time; + time(&last_aging); +#ifndef SIM + int pan_fd = serial_source_fd(ser_src); +#else + int pan_fd = sf_fd; +#endif + cmd_cur = cmd_buf[0]; + + /* disable input buffering on stdin since we're going to accumulate + the input outselves, and don't want to block */ + if (isatty(fileno(stdin))) { + struct termios tio; + /* disable it on the fd */ + if (tcgetattr(fileno(stdin), &tio)) + return -1; + tio.c_lflag &= ~ICANON; + if (tcsetattr(fileno(stdin), TCSANOW, &tio)) + return -1; + /* and also in libc */ + setbuf(stdin, NULL); + } + + while (1) { + FD_ZERO(&fs); + FD_SET(tun_fd, &fs); + FD_SET(pan_fd, &fs); + + maxfd = max(tun_fd, pan_fd); + if (isatty(fileno(stdin))) { + FD_SET(fileno(stdin), &fs); + maxfd = max(fileno(stdin), maxfd); + } + if (radvd_fd >= 0) { + FD_SET(radvd_fd, &fs); + maxfd = max(radvd_fd, maxfd); + } + + if (select(maxfd + 1, &fs, NULL, NULL, NULL) < 0) + continue; + + + /* data available on tunnel device */ + if (FD_ISSET(tun_fd, &fs)) + while(tun_input()); + + if (FD_ISSET(pan_fd, &fs)) + while(serial_input()); + + if (FD_ISSET(fileno(stdin), &fs)) { + *cmd_cur++ = getc(stdin); + if (*(cmd_cur - 1) == '\n' || + cmd_cur - cmd_buf[cur_buf] == 1024) { + *cmd_cur = '\0'; + if (cmd_cur == cmd_buf[cur_buf] + 1) { + eval_cmd(cmd_buf[(cur_buf + 1) % 2]); + } else { + eval_cmd(cmd_buf[cur_buf]); + cur_buf = (cur_buf + 1) % 2; + } + cmd_cur = cmd_buf[cur_buf]; + } + } + + if (radvd_fd >= 0 && FD_ISSET(radvd_fd, &fs)) { + radvd_process(); + } + +#ifndef SIM +/* if (tcdrain(pan_fd) < 0) { */ +/* fatal("tcdrain error: %i\n", errno); */ +/* exit(3); */ +/* } */ +#endif + + /* end of data available */ + time(¤t_time); + if (current_time > last_aging + (FRAG_EXPIRE_TIME / 1024)) { + last_aging = current_time; + age_reconstructions(); + } + } + + return 0; +} + +#ifdef DBG_TRACK_FLOWS +void truncate_dbg() { + ftruncate(fileno(dbg_file), 0); +} +#endif + +int main(int argc, char **argv) { + int i, c; + + time(&stats.boot_time); + + log_init(); + while ((c = getopt(argc, argv, "c:")) != -1) { + switch (c) { + case 'c': + def_configfile = optarg; + break; + default: + fatal("Invalid command line argument.\n"); + exit(1); + } + } + + if (argc - optind != 2) { +#ifndef SIM + fatal("usage: %s [-c config] \n", argv[0]); +#else + fatal("usage: %s [-c config] \n", argv[0]); +#endif + exit(2); + } + +#ifdef DBG_TRACK_FLOWS + dbg_file = fopen("dbg.txt", "w"); + if (dbg_file == NULL) { + perror("main: opening dbg file:"); + exit(1); + } + signal(SIGUSR2, truncate_dbg); +#endif + + if (config_parse(def_configfile, &driver_config) != 0) { + fatal ("config parse of %s failed!\n", def_configfile); + exit(1); + } + globalPrefix = 1; + memcpy(&__my_address, &driver_config.router_addr, sizeof(struct in6_addr)); + + /* create the tunnel device */ + dev[0] = 0; + tun_fd = tun_open(dev); + if (tun_fd < 1) { + fatal("Could not create tunnel device. Fatal.\n"); + return 1; + } else { + info("created tun device: %s\n", dev); + } + if (tun_setup(dev, &__my_address) < 0) { + fatal("configuring the tun failed; aborting\n"); + perror("tun_setup"); + return 1; + } + + + for (i = 0; i < N_RECONSTRUCTIONS; i++) { + reconstructions[i].timeout = T_UNUSED; + } + + /* open the serial port */ +#ifndef SIM + ser_src = open_serial_source(argv[optind], platform_baud_rate(argv[optind + 1]), + 1, stderr_msg); + if (!ser_src) { + fatal("Couldn't open serial port at %s:%s\n", argv[optind], argv[optind + 1]); + exit(1); + } +#else + sf_fd = open_sf_source(argv[optind], atoi(argv[optind + 1])); + if (sf_fd < 0) { + fatal("Couldn't connect to serial forwarder sf@%s:%s\n", argv[optind], argv[optind + 1]); + exit(1); + } +#endif + + info("Press 'h' for help\n"); + + routing_init(&driver_config, dev); +#ifndef SIM + configure_reboot(); +#endif + + /* start tunneling */ + serial_tunnel(tun_fd); + + /* clean up */ + // close_serial_source(ser_src); + // close(ser_fd); + tun_close(tun_fd, dev); + return 0; +} diff --git a/support/sdk/c/blip/driver/tun_dev.c b/support/sdk/c/blip/driver/tun_dev.c new file mode 100644 index 00000000..684efb94 --- /dev/null +++ b/support/sdk/c/blip/driver/tun_dev.c @@ -0,0 +1,211 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* + * Copyright (c) 2007 Matus Harvan + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "lib6lowpan.h" +#include "tun_dev.h" + + +/* + * This is in linux/include/net/ipv6.h. + * Thanks, net-tools! + */ +struct in6_ifreq { + struct in6_addr ifr6_addr; + __u32 ifr6_prefixlen; + unsigned int ifr6_ifindex; +}; + + +int tun_open(char *dev) +{ + struct ifreq ifr; + int fd; + + if ((fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + /* By default packets are tagged as IPv4. To tag them as IPv6, + * they need to be prefixed by struct tun_pi. + */ + //ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + ifr.ifr_flags = IFF_TUN; + if (*dev) + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) + goto failed; + + strcpy(dev, ifr.ifr_name); + return fd; + + failed: + perror("tun_open"); + close(fd); + return -1; +} + +int tun_setup(char *dev, struct in6_addr *addr) { + struct in6_ifreq ifr6; + struct ifreq ifr; + int fd; + + if ((fd = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) + return -1; + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + /* set the interface up */ + if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { + perror("SIOCGIFFLAGS"); + return -1; + } + ifr.ifr_flags |= IFF_UP; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { + perror("SIOCSIFFLAGS"); + return -1; + } + + /* MTU */ + ifr.ifr_mtu = 1280; + if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) { + perror("SIOCSIFMTU"); + return -1; + } + + /* Global address */ + memset(&ifr6, 0, sizeof(struct in6_ifreq)); + memcpy(&ifr6.ifr6_addr, addr, 16); + if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { + perror("SIOGIFINDEX"); + return -1; + } + + ifr6.ifr6_ifindex = ifr.ifr_ifindex; + ifr6.ifr6_prefixlen = 64; + if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { + perror("SIOCSIFADDR (global)"); + return -1; + } + + memset(&ifr6.ifr6_addr.s6_addr[0], 0, 16); + ifr6.ifr6_addr.s6_addr16[0] = htons(0xfe80); + ifr6.ifr6_addr.s6_addr16[7] = addr->s6_addr16[7]; + + if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { + perror("SIOCSIFADDR (local)"); + return -1; + } + + close(fd); + + return 0; +} + +int tun_close(int fd, char *dev) +{ + return close(fd); +} + +/* Read/write frames from TUN device */ +int tun_write(int fd, struct split_ip_msg *msg) +{ + uint8_t buf[INET_MTU + sizeof(struct tun_pi)], *packet; + struct tun_pi *pi = (struct tun_pi *)buf; + struct generic_header *cur; + packet = (uint8_t *)(pi + 1); + + + if (ntohs(msg->hdr.plen) + sizeof(struct ip6_hdr) >= INET_MTU) + return 1; + + pi->flags = 0; + pi->proto = htons(ETH_P_IPV6); + + memcpy(packet, &msg->hdr, sizeof(struct ip6_hdr)); + packet += sizeof(struct ip6_hdr); + + cur = msg->headers; + while (cur != NULL) { + memcpy(packet, cur->hdr.data, cur->len); + packet += cur->len; + cur = cur->next; + } + + memcpy(packet, msg->data, msg->data_len); + + return write(fd, buf, sizeof(struct tun_pi) + sizeof(struct ip6_hdr) + ntohs(msg->hdr.plen)); +} + +int tun_read(int fd, char *buf, int len) +{ + int out; + out = read(fd, buf, sizeof(struct tun_pi) + len); + + return out - sizeof(struct tun_pi); +} diff --git a/support/sdk/c/blip/driver/tun_dev.h b/support/sdk/c/blip/driver/tun_dev.h new file mode 100644 index 00000000..e0b32d3c --- /dev/null +++ b/support/sdk/c/blip/driver/tun_dev.h @@ -0,0 +1,64 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* + * Copyright (c) 2007 Matus Harvan + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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 _TUN_DEV_H +#define _TUN_DEV_H + +#include + +int tun_open(char *dev); +int tun_close(int fd, char *dev); +int tun_setup(char *dev, struct in6_addr *addr); +int tun_write(int fd, struct split_ip_msg *msg); +int tun_read(int fd, char *buf, int len); + +#endif diff --git a/support/sdk/c/blip/driver/tunnel.c b/support/sdk/c/blip/driver/tunnel.c new file mode 100644 index 00000000..6d6a64eb --- /dev/null +++ b/support/sdk/c/blip/driver/tunnel.c @@ -0,0 +1,70 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* + * Implementation of user-mode driver and IP gateway using a node + * running IPBaseStation as 802.15.4 hardware. Uses kernel tun + * interface to route addresses. + * + */ +#include +#include +#include + +#include +#include +#include + +uint16_t shortAddr; +int tun_fd; +char *tun_dev = "/dev/net/tun"; + +void usage(char **args) { + fprintf(stderr, "\n\t%s \n\n", args[0]); +} + +int create_tunnel() { + struct ifreq ifr; + if ((tun_fd = open(tun_dev, O_RDWR)) < 0) { + fprintf(stderr, "Failed to open '%s' : ", tun_dev); + perror(""); + return 1; + } + ifr.irf_flags = IFF_TAP | IFF_NO_PI; + str + + return 0; +} + +int main(int argc, char **argv) { + if (argc != 2) { + usage(argv); + return 1; + } + shortAddr = atoi(argv[1]); + + if (create_tunnel()) + return 1; + + sleep(20); + + return 0; +} diff --git a/support/sdk/c/blip/include/6lowpan.h b/support/sdk/c/blip/include/6lowpan.h new file mode 100644 index 00000000..76ddd758 --- /dev/null +++ b/support/sdk/c/blip/include/6lowpan.h @@ -0,0 +1,240 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + + +/* + * Header file for the 6lowpan/IPv6 stack. + * + * @author Stephen Dawson-Haggerty + * + */ + +#ifndef __6LOWPAN_H__ +#define __6LOWPAN_H__ + +#include +/* + * Typedefs and static library data. + */ +typedef uint8_t ip6_addr_t [16]; +typedef uint16_t cmpr_ip6_addr_t; +#ifdef PC +typedef uint16_t hw_addr_t; +typedef uint16_t hw_pan_t; +enum { + HW_BROADCAST_ADDR = 0xffff, +}; +#else +#include +#endif + +/* + * shared variables which contain addressing information for 6lowpan + * devices + */ +extern uint8_t globalPrefix; +extern uint8_t multicast_prefix[8]; +extern uint8_t linklocal_prefix[8]; + +uint8_t cmpPfx(ip6_addr_t a, uint8_t *pfx); + +void ip_memclr(uint8_t *buf, uint16_t len); +void *ip_memcpy(void *dst0, const void *src0, uint16_t len); + +/* + * A packed 6lowpan packet. + * + * The data buffer points at the start of 6lowpan packed data. We + * included a few other fields from L2 with this information so that + * we are able to infer things like source and destination IP from it. + * + */ +typedef struct packed_lowmsg { + uint8_t headers; + uint8_t len; + // we preprocess the headers bitmap for easy processing. + hw_addr_t src; + hw_addr_t dst; + uint8_t *data; +} packed_lowmsg_t; + +/* + * bit fields we use to keep track of which optional header fields are + * present in a message + */ +enum { + LOWMSG_MESH_HDR = (1 << 0), + LOWMSG_BCAST_HDR = (1 << 1), + LOWMSG_FRAG1_HDR = (1 << 2), + LOWMSG_FRAGN_HDR = (1 << 3), + LOWMSG_NALP = (1 << 4), + LOWMSG_IPNH_HDR = (1 << 5), +}; + +/* + * lengths of different lowpan headers + */ +enum { + LOWMSG_MESH_LEN = 5, + LOWMSG_BCAST_LEN = 2, + LOWMSG_FRAG1_LEN = 4, + LOWMSG_FRAGN_LEN = 5, +}; + +enum { + LOWPAN_LINK_MTU = 110, + INET_MTU = 1280, + LIB6LOWPAN_MAX_LEN = LOWPAN_LINK_MTU, +}; + +/* + * magic numbers from rfc4944; some of them shifted: mostly dispatch values. + */ +enum { + LOWPAN_NALP_PATTERN = 0x0, + LOWPAN_MESH_PATTERN = 0x2, + LOWPAN_FRAG1_PATTERN = 0x18, + LOWPAN_FRAGN_PATTERN = 0x1c, + LOWPAN_BCAST_PATTERN = 0x50, + LOWPAN_HC1_PATTERN = 0x42, + LOWPAN_HC_LOCAL_PATTERN = 0x3, + LOWPAN_HC_CRP_PATTERN = 0x4, +}; + +enum { + LOWPAN_MESH_V_MASK = 0x20, + LOWPAN_MESH_F_MASK = 0x10, + LOWPAN_MESH_HOPS_MASK = 0x0f, +}; + +/* + * IP protocol numbers + */ +enum { + IANA_ICMP = 58, + IANA_UDP = 17, + IANA_TCP = 6, + + NXTHDR_SOURCE = 0, + NXTHDR_INSTALL = 253, // Use for experimentation and testing(IANA.org) + NXTHDR_TOPO = 252, + NXTHDR_UNKNOWN = 0xff, +}; + +#define KNOWN_HEADER(X) ((X) == NXTHDR_SOURCE || (X) == IANA_UDP || (X) == NXTHDR_INSTALL || (X) == NXTHDR_TOPO) + +/* + * constants to unpack HC-packed headers + */ +enum { + LOWPAN_IPHC_VTF_MASK = 0x80, + LOWPAN_IPHC_VTF_INLINE = 0, + LOWPAN_IPHC_NH_MASK = 0x40, + LOWPAN_IPHC_NH_INLINE = 0, + LOWPAN_IPHC_HLIM_MASK = 0x20, + LOWPAN_IPHC_HLIM_INLINE = 0, + + LOWPAN_IPHC_SC_OFFSET = 3, + LOWPAN_IPHC_DST_OFFSET = 1, + LOWPAN_IPHC_ADDRFLAGS_MASK = 0x3, + + LOWPAN_IPHC_ADDR_128 = 0x0, + LOWPAN_IPHC_ADDR_64 = 0x1, + LOWPAN_IPHC_ADDR_16 = 0x2, + LOWPAN_IPHC_ADDR_0 = 0x3, + + LOWPAN_IPHC_SHORT_MASK = 0x80, + LOWPAN_IPHC_SHORT_LONG_MASK= 0xe0, + + LOWPAN_IPHC_HC1_MCAST = 0x80, + LOWPAN_IPHC_HC_MCAST = 0xa0, + + LOWPAN_HC_MCAST_SCOPE_MASK = 0x1e, + LOWPAN_HC_MCAST_SCOPE_OFFSET = 1, + + LOWPAN_UDP_PORT_BASE_MASK = 0xfff0, + LOWPAN_UDP_PORT_BASE = 0xf0b0, + LOWPAN_UDP_DISPATCH = 0x80, + + LOWPAN_UDP_S_MASK = 0x40, + LOWPAN_UDP_D_MASK = 0x20, + LOWPAN_UDP_C_MASK = 0x10, +}; + + +/* + * nonstandard source routing header fields + */ +enum { + IP_EXT_SOURCE_DISPATCH = 0x40, + IP_EXT_SOURCE_MASK = 0xc0, + + // dispatch values + IP_EXT_SOURCE_RECORD = 0x01, + IP_EXT_SOURCE_RECORD_MASK = 0x01, + IP_EXT_SOURCE_INVAL = 0x02, + IP_EXT_SOURCE_INVAL_MASK = 0x02, + IP_EXT_SOURCE_CONTROLLER = 0x04, + + // dispatch values for route installation if this flag is set, the + // source_header must be immediately followed by a + // source_install_opt struct. + IP_EXT_SOURCE_INSTALL = 0x10, + IP_EXT_SOURCE_INSTALL_MASK= 0x10, + + // indicates weather the forward and reverse paths should be + // installed. Are these needed? the only case when we don't want + // to install the reverse path is when the destination is a + // multicast? + IP_EXT_SOURCE_INST_SRC = 0x20, + IP_EXT_SOURCE_INST_DST = 0x40, +}; + +#define SH_NENTRIES(SH) ((sh->len - (sizeof(struct source_header))) / (sizeof(uint16_t))) + +struct source_header { + uint8_t nxt_hdr; + uint8_t len; + // the equalivent of the "routing type" field + uint8_t dispatch; + uint8_t current; + uint16_t hops[0]; +}; + +// AT: These are really 16 bit values, but after a certain point the numbers +// beyond 255 aren't important to us, or rather no different than 255 +struct topology_entry { + uint8_t etx; + uint8_t conf; + hw_addr_t hwaddr; +}; +struct topology_header { + uint8_t nxt_hdr; + uint8_t len; + struct topology_entry topo[0]; +}; + +enum { + IP_NUMBER_FRAGMENTS = 12, +}; + +#endif diff --git a/support/sdk/c/blip/include/IEEE154.h b/support/sdk/c/blip/include/IEEE154.h new file mode 100644 index 00000000..4a47e162 --- /dev/null +++ b/support/sdk/c/blip/include/IEEE154.h @@ -0,0 +1,49 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _IEEE154_H_ +#define _IEEE154_H_ + +typedef struct IEEE154_header { + uint8_t length; + uint16_t fcf; + uint8_t dsn; + uint16_t destpan; + uint16_t dest; + uint16_t src; +} __attribute__((packed)) IEEE154_header_t; + +typedef struct serial_header { + uint16_t dest; + uint16_t src; + uint8_t length; + uint8_t group; + uint8_t type; +} __attribute__((packed)) serial_header_t; + +enum { + // size of the header not including the length byte + MAC_HEADER_SIZE = sizeof( IEEE154_header_t ) - 1, + // size of the footer (FCS field) + MAC_FOOTER_SIZE = sizeof( uint16_t ), +}; + +#endif diff --git a/support/sdk/c/blip/include/devconf.h b/support/sdk/c/blip/include/devconf.h new file mode 100644 index 00000000..3a56d1b9 --- /dev/null +++ b/support/sdk/c/blip/include/devconf.h @@ -0,0 +1,100 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _CONFIGURE_H_ +#define _CONFIGURE_H_ + +#include "6lowpan.h" + +enum { + CONFIG_ECHO = 0, // ping the device for status information + CONFIG_SET_PARM = 1, // instruct the device to set its hardware addr + CONFIG_REBOOT = 2, +}; + +enum { + CONFIG_ERROR_OK, + CONFIG_ERROR_FAIL, + CONFIG_ERROR_BOOTED, +}; + +#ifndef PC + + +typedef nx_struct config_cmd { + nx_uint8_t cmd; + nx_struct { + nx_uint16_t retries; + nx_uint16_t delay; + } retx; + nx_struct { + nx_uint16_t addr; + nx_uint8_t channel; + } rf; +} config_cmd_t; + + +typedef nx_struct { + nx_uint8_t error; + nx_uint16_t addr; + nx_uint16_t serial_read; + nx_uint16_t radio_read; + nx_uint16_t serial_fail; + nx_uint16_t radio_fail; +} config_reply_t; + +#else + +enum { + CONFIGURE_MSG_SIZE = 8, +}; +typedef struct config_cmd { + uint8_t cmd; + struct { + uint16_t retries; + uint16_t delay; + } retx; + struct { + hw_addr_t addr; + uint8_t channel; + } rf; +} __attribute__((packed)) config_cmd_t; + + + +typedef struct { + uint8_t error; + hw_addr_t addr; + uint16_t serial_read; + uint16_t radio_read; + uint16_t serial_fail; + uint16_t radio_fail; +} __attribute__((packed)) config_reply_t; + +enum { + TOS_SERIAL_802_15_4_ID = 2, + TOS_SERIAL_DEVCONF = 3, +}; + +#endif + +#endif + diff --git a/support/sdk/c/blip/include/in_cksum.h b/support/sdk/c/blip/include/in_cksum.h new file mode 100644 index 00000000..b6108fad --- /dev/null +++ b/support/sdk/c/blip/include/in_cksum.h @@ -0,0 +1,45 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _IN_CKSUM_H_ +#define _IN_CKSUM_H_ + +/* in_cksum.h + * Declaration of Internet checksum routine. + * + * $Id$ + */ + +#include +#include "ip.h" + +typedef struct { + const uint8_t *ptr; + int len; +} vec_t; + +extern int in_cksum(const vec_t *vec, int veclen); + +// extern uint16_t in_cksum(const vec_t *vec, int veclen); + +extern uint16_t msg_cksum(struct split_ip_msg *msg, uint8_t nxt_hdr); + +#endif diff --git a/support/sdk/c/blip/include/ip.h b/support/sdk/c/blip/include/ip.h new file mode 100644 index 00000000..e48163f8 --- /dev/null +++ b/support/sdk/c/blip/include/ip.h @@ -0,0 +1,269 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _IP_H_ +#define _IP_H_ + +/* + * define message structures for internet communication + * + */ + +#ifdef PC +#include +#include +#endif + +#include "6lowpan.h" + +enum { + /* + * The time, in binary milliseconds, after which we stop waiting for + * fragments and report a failed receive. We + */ + FRAG_EXPIRE_TIME = 4096, +}; + + +#ifndef PC +// update to use netinet/in definition of an IPv6 address; this is a +// lot more elegent. +struct in6_addr + { + union + { + uint8_t u6_addr8[16]; + uint16_t u6_addr16[8]; + uint32_t u6_addr32[4]; + } in6_u; +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 + }; + +struct sockaddr_in6 { + uint16_t sin6_port; + struct in6_addr sin6_addr; +}; +#endif + +/* + * Definition for internet protocol version 6. + * RFC 2460 + */ +struct ip6_hdr { + uint8_t vlfc[4]; + uint16_t plen; /* payload length */ + uint8_t nxt_hdr; /* next header */ + uint8_t hlim; /* hop limit */ + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ +} __attribute__((packed)); + +#define IPV6_VERSION 0x6 +#define IPV6_VERSION_MASK 0xf0 + + +/* + * Extension Headers + */ + +struct ip6_ext { + uint8_t nxt_hdr; + uint8_t len; + uint8_t data[0]; +}; + +/* + * icmp + */ +struct icmp6_hdr { + uint8_t type; /* type field */ + uint8_t code; /* code field */ + uint16_t cksum; /* checksum field */ +}; + +enum { + ICMP_TYPE_ECHO_DEST_UNREACH = 1, + ICMP_TYPE_ECHO_PKT_TOO_BIG = 2, + ICMP_TYPE_ECHO_TIME_EXCEEDED = 3, + ICMP_TYPE_ECHO_PARAM_PROBLEM = 4, + ICMP_TYPE_ECHO_REQUEST = 128, + ICMP_TYPE_ECHO_REPLY = 129, + ICMP_TYPE_ROUTER_SOL = 133, + ICMP_TYPE_ROUTER_ADV = 134, + ICMP_TYPE_NEIGHBOR_SOL = 135, + ICMP_TYPE_NEIGHBOR_ADV = 136, + ICMP_NEIGHBOR_HOPLIMIT = 255, + + ICMP_CODE_HOPLIMIT_EXCEEDED = 0, + ICMP_CODE_ASSEMBLY_EXCEEDED = 1, +}; + +/* + * UDP protocol header. + */ +struct udp_hdr { + uint16_t srcport; /* source port */ + uint16_t dstport; /* destination port */ + uint16_t len; /* udp length */ + uint16_t chksum; /* udp checksum */ +}; + +/* + * TCP transport headers and flags + */ +enum { + TCP_FLAG_FIN = 0x1, + TCP_FLAG_SYN = 0x2, + TCP_FLAG_RST = 0x4, + TCP_FLAG_PSH = 0x8, + TCP_FLAG_ACK = 0x10, + TCP_FLAG_URG = 0x20, + TCP_FLAG_ECE = 0x40, + TCP_FLAG_CWR = 0x80, +}; + +struct tcp_hdr { + uint16_t srcport; + uint16_t dstport; + uint32_t seqno; + uint32_t ackno; + uint8_t offset; + uint8_t flags; + uint16_t window; + uint16_t chksum; + uint16_t urgent; +}; + +/* + * IP metadata and routing structures + */ +struct ip_metadata { + hw_addr_t sender; + uint8_t lqi; + uint8_t padding[1]; +}; + +struct flow_match { + cmpr_ip6_addr_t src; + cmpr_ip6_addr_t dest; // Need to make this more extensible at some point + cmpr_ip6_addr_t prev_hop; +}; + +struct rinstall_header { + struct ip6_ext ext; + uint16_t flags; + struct flow_match match; + uint8_t path_len; + uint8_t current; + cmpr_ip6_addr_t path[0]; +}; + +enum { + R_SRC_FULL_PATH_INSTALL_MASK = 0x01, + R_DEST_FULL_PATH_INSTALL_MASK = 0x02, + R_HOP_BY_HOP_PATH_INSTALL_MASK = 0x04, + R_REVERSE_PATH_INSTALL_MASK = 0x08, + R_SRC_FULL_PATH_UNINSTALL_MASK = 0x10, + R_DEST_FULL_PATH_UNINSTALL_MASK = 0x20, + R_HOP_BY_HOP_PATH_UNINSTALL_MASK = 0x40, + R_REVERSE_PATH_UNINSTALL_MASK = 0x80, +}; + +#define IS_FULL_SRC_INSTALL(r) (((r)->flags & R_SRC_FULL_PATH_INSTALL_MASK) == R_SRC_FULL_PATH_INSTALL_MASK) +#define IS_FULL_DST_INSTALL(r) (((r)->flags & R_DEST_FULL_PATH_INSTALL_MASK) == R_DEST_FULL_PATH_INSTALL_MASK) +#define IS_HOP_INSTALL(r) (((r)->flags & R_HOP_BY_HOP_PATH_INSTALL_MASK) == R_HOP_BY_HOP_PATH_INSTALL_MASK) +#define IS_REV_INSTALL(r) (((r)->flags & R_REVERSE_PATH_INSTALL_MASK) == R_REVERSE_PATH_INSTALL_MASK) +#define IS_FULL_SRC_UNINSTALL(r) (((r)->flags & R_SRC_FULL_PATH_UNINSTALL_MASK) == R_SRC_FULL_PATH_UNINSTALL_MASK) +#define IS_FULL_DST_UNINSTALL(r) (((r)->flags & R_DEST_FULL_PATH_UNINSTALL_MASK) == R_DEST_FULL_PATH_UNINSTALL_MASK) +#define IS_HOP_UNINSTALL(r) (((r)->flags & R_HOP_BY_HOP_PATH_UNINSTALL_MASK) == R_HOP_BY_HOP_PATH_UNINSTALL_MASK) +#define IS_REV_UNINSTALL(r) (((r)->flags & R_REVERSE_PATH_UNINSTALL_MASK) == R_REVERSE_PATH_UNINSTALL_MASK) + +enum { + T_INVAL_NEIGH = 0xef, + T_SET_NEIGH = 0xee, +}; + +struct flow_id { + uint16_t src; + uint16_t dst; + uint16_t id; + uint16_t seq; + uint16_t nxt_hdr; +}; + + +/* + * These are data structures to hold IP messages. We used a linked + * list of headers so that we can easily add extra headers with no + * copy; similar to the linux iovec's or BSD mbuf structs. + * Every split_ip_msg contains a full IPv6 header (40 bytes), but it + * is placed at the end of the struct so that we can read() a message + * straight into one of these structs, and then just set up the header + * chain. + * + * Due to the way fragmentation is currently implemented, the total + * length of the data referenced from this chain must not be longer + * then what can fit into a single fragment. This is a limitation of + * the current fragmentation code, but is perfectly usable in most + * cases. + */ +struct generic_header { +#ifdef PC + int payload_malloced:1; +#endif + uint8_t len; + union { + // this could be an eumeration of all the valid headers we can have here. + struct ip6_ext *ext; + struct source_header *sh; + struct udp_hdr *udp; + struct tcp_hdr *tcp; + struct rinstall_header *rih; + struct topology_header *th; + uint8_t *data; + } hdr; + struct generic_header *next; +}; + +struct split_ip_msg { + struct generic_header *headers; + uint16_t data_len; + uint8_t *data; +#ifdef PC + struct ip_metadata metadata; +#ifdef DBG_TRACK_FLOWS + struct flow_id id; +#endif + // this must be last so we can read() straight into the end of the buffer. + struct tun_pi pi; +#endif + struct ip6_hdr hdr; + uint8_t next[0]; +}; + +/* + * parse a string representation of an IPv6 address + */ +void inet_pton6(char *addr, struct in6_addr *dest); + +#endif diff --git a/support/sdk/c/blip/include/ip_malloc.h b/support/sdk/c/blip/include/ip_malloc.h new file mode 100644 index 00000000..dbd0db59 --- /dev/null +++ b/support/sdk/c/blip/include/ip_malloc.h @@ -0,0 +1,28 @@ +#ifndef NO_IP_MALLOC +#ifndef IP_MALLOC_H_ +#define IP_MALLOC_H_ + +#include + +// align on this number of byte boundarie#s +#define IP_MALLOC_ALIGN 2 +#define IP_MALLOC_LEN 0x0fff +#define IP_MALLOC_FLAGS 0x7000 +#define IP_MALLOC_INUSE 0x8000 +#define IP_MALLOC_HEAP_SIZE 1500 + +extern uint8_t heap[IP_MALLOC_HEAP_SIZE]; +typedef uint16_t bndrt_t; + +void ip_malloc_init(); +void *ip_malloc(uint16_t sz); +void ip_free(void *ptr); +uint16_t ip_malloc_freespace(); + +#ifndef PC +#define malloc(X) ip_malloc(X) +#define free(X) ip_free(X) +#endif + +#endif +#endif diff --git a/support/sdk/c/blip/include/lib6lowpan.h b/support/sdk/c/blip/include/lib6lowpan.h new file mode 100644 index 00000000..8723c292 --- /dev/null +++ b/support/sdk/c/blip/include/lib6lowpan.h @@ -0,0 +1,239 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _LIB6LOWPAN_H_ +#define _LIB6LOWPAN_H_ + +#include +#include + +#include "6lowpan.h" +#include "ip.h" + +#ifdef __TARGET_mips__ +// #warning "Using big endian byte order" +#define ntoh16(X) (X) +#define hton16(X) (X) +#define ntoh32(X) (X) +#define hton32(X) (X) +#define leton16(X) (((((uint16_t)(X)) << 8) | ((uint16_t)(X) >> 8)) & 0xffff) +#define htole16(X) leton16(X) +#else +// #warning "Using little endian byte order" +#define ntoh16(X) (((((uint16_t)(X)) >> 8) | ((uint16_t)(X) << 8)) & 0xffff) +#define hton16(X) (((((uint16_t)(X)) << 8) | ((uint16_t)(X) >> 8)) & 0xffff) +#define leton16(X) hton16(X) +#define htole16(X) (X) +#define ntoh32(X) ((((uint32_t)(X) >> 24) & 0x000000ff)| \ + ((((uint32_t)(X) >> 8)) & 0x0000ff00) | \ + ((((uint32_t)(X) << 8)) & 0x00ff0000) | \ + ((((uint32_t)(X) << 24)) & 0xff000000)) + +#define hton32(X) ((((uint32_t)(X) << 24) & 0xff000000)| \ + ((((uint32_t)(X) << 8)) & 0x00ff0000) | \ + ((((uint32_t)(X) >> 8)) & 0x0000ff00) | \ + ((((uint32_t)(X) >> 24)) & 0x000000ff)) +#endif + + +#define ntohs(X) ntoh16(X) +#define htons(X) hton16(X) + +#define ntohl(X) ntoh32(X) +#define htonl(X) hton32(X) + + +#ifdef DEF_MEMCPY +#define memcpy(X,Y,Z) ip_memcpy(X,Y,Z) +#endif + +/* + * This interface implements the 6loWPAN header structures. Support + * for the HC1 and HC2 compressed IP and UDP headers is also + * available, and the interface is presented in lib6lowpanIP.h. + * + */ + +// only 16-bit address handling modes +#define __6LOWPAN_16BIT_ADDRESS + +/* + * Library implementation of packing of 6lowpan packets. + * + * This should allow uniform code treatment between pc and mote code; + * the goal is to write ANSI C here... This means no nx_ types, + * unfortunately. + */ + +/* + * 6lowpan header functions + */ + +uint16_t getHeaderBitmap(packed_lowmsg_t *lowmsg); +/* + * Return the length of the buffer required to pack lowmsg + * into a buffer. + */ + +uint8_t *getLowpanPayload(packed_lowmsg_t *lowmsg); + +/* + * Initialize the header bitmap in 'packed' so that + * we know how long the headers are. + * + * @return FAIL if the buffer is not long enough. + */ +uint8_t setupHeaders(packed_lowmsg_t *packed, uint16_t headers); + +/* + * Test if various protocol features are enabled + */ +uint8_t hasMeshHeader(packed_lowmsg_t *msg); +uint8_t hasBcastHeader(packed_lowmsg_t *msg); +uint8_t hasFrag1Header(packed_lowmsg_t *msg); +uint8_t hasFragNHeader(packed_lowmsg_t *msg); + +/* + * Mesh header fields + * + * return FAIL if the message doesn't have a mesh header + */ +uint8_t getMeshHopsLeft(packed_lowmsg_t *msg, uint8_t *hops); +uint8_t getMeshOriginAddr(packed_lowmsg_t *msg, hw_addr_t *origin); +uint8_t getMeshFinalAddr(packed_lowmsg_t *msg, hw_addr_t *final); + +uint8_t setMeshHopsLeft(packed_lowmsg_t *msg, uint8_t hops); +uint8_t setMeshOriginAddr(packed_lowmsg_t *msg, hw_addr_t origin); +uint8_t setMeshFinalAddr(packed_lowmsg_t *msg, hw_addr_t final); + +/* + * Broadcast header fields + */ +uint8_t getBcastSeqno(packed_lowmsg_t *msg, uint8_t *seqno); + +uint8_t setBcastSeqno(packed_lowmsg_t *msg, uint8_t seqno); + +/* + * Fragmentation header fields + */ +uint8_t getFragDgramSize(packed_lowmsg_t *msg, uint16_t *size); +uint8_t getFragDgramTag(packed_lowmsg_t *msg, uint16_t *tag); +uint8_t getFragDgramOffset(packed_lowmsg_t *msg, uint8_t *size); + +uint8_t setFragDgramSize(packed_lowmsg_t *msg, uint16_t size); +uint8_t setFragDgramTag(packed_lowmsg_t *msg, uint16_t tag); +uint8_t setFragDgramOffset(packed_lowmsg_t *msg, uint8_t size); + +/* + * IP header compression functions + * + */ +int getCompressedLen(packed_lowmsg_t *pkt); + +/* + * Pack the header fields of msg into buffer 'buf'. + * it returns the number of bytes written to 'buf', or zero if it encountered a problem. + * + * it will pack the IP header and all headers in the header chain of + * msg into the buffer; the only thing it will not pack is the + * payload. + */ +uint8_t packHeaders(struct split_ip_msg *msg, + uint8_t *buf, uint8_t len); +/* + * Unpack the packed data from pkt into dest. + * + * It turns out that we need to keep track of a lot of different + * locations in order to be able to unpack and forward efficiently. + * If we don't save these during the unpack, we end up reconstructing + * them in various places so it's less error-prone to compute them + * while we're parsing the packed fields. + */ +typedef struct { + // the final header in the header chain; should be the transport header + uint8_t nxt_hdr; + // a pointer to the point in the source where we stopped unpacking + uint8_t *payload_start; + // a pointer to the point in the destination right after all headers + uint8_t *header_end; + // the total, uncompressed length of the headers which were unpacked + uint8_t payload_offset; + // points to the hop limit field of the packet message + uint8_t *hlim; + // points to the tranport header in the destination region, + // if it was within the unpacked region header. + // if it was not, it is the same as header_end + uint8_t *transport_ptr; + // points to the source header within the packed fields, IF it contains one. + struct source_header *sh; + struct rinstall_header *rih; +} unpack_info_t; + +uint8_t *unpackHeaders(packed_lowmsg_t *pkt, unpack_info_t *u_info, + uint8_t *dest, uint16_t len); + +/* + * Fragmentation routines. + */ + +extern uint16_t lib6lowpan_frag_tag; + +typedef struct { + uint16_t tag; /* datagram label */ + uint16_t size; /* the size of the packet we are reconstructing */ + void *buf; /* the reconstruction location */ + uint16_t bytes_rcvd; /* how many bytes from the packet we have + received so far */ + uint8_t timeout; + uint8_t *transport_hdr; + struct ip_metadata metadata; +} reconstruct_t; + +typedef struct { + uint16_t tag; /* the label of the datagram */ + uint16_t offset; /* how far into the packet we have sent, in bytes */ +} fragment_t; + + +/* + * this function writes the next fragment which needs to be sent into + * the buffer passed in. It updates the structures in process to + * reflect how much of the packet has been sent so far. + * + * if the packet does not require fragmentation, this function will + * not insert a fragmentation header and will merely compress the + * headers into the packet. + * + */ +uint8_t getNextFrag(struct split_ip_msg *msg, fragment_t *progress, + uint8_t *buf, uint16_t len); + + +enum { + T_FAILED1 = 0, + T_FAILED2 = 1, + T_UNUSED = 2, + T_ACTIVE = 3, + T_ZOMBIE = 4, +}; + +uint8_t* getLinkLocalPrefix(); +#endif diff --git a/support/sdk/c/blip/lib6lowpan/Makefile b/support/sdk/c/blip/lib6lowpan/Makefile new file mode 100644 index 00000000..fb34df22 --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/Makefile @@ -0,0 +1,45 @@ + +SOURCES=lib6lowpan.c lib6lowpanIP.c lib6lowpanFrag.c +INCLUDE=../include/ + +############### +## +## Use these for PC +ifndef GCC +GCC=gcc +endif +ifndef AR +AR=ar +endif + +CFLAGS=-DPC -g -I$(INCLUDE) +TEST=testhc.c + +############### +## +## These for msp430 +# GCC=msp430-gcc +# AR=msp430-ar +# TEST=msp_test.c +# CFLAGS=-DMSP + +LIB=lib6lowpan.a +OBJS=$(SOURCES:.c=.o) + +$(LIB): $(OBJS) + $(AR) crv $(LIB) $(OBJS) + +test: $(SOURCES) $(TEST) $(LIB) + $(GCC) -o $@ $(TEST) $(CFLAGS) $(LIB) printpacket.c + +%.o: %.c + $(GCC) -o $@ $< $(CFLAGS) -c + +clean: + rm -f test $(OBJS) $(LIB) + +lib6lowpan.o: lib6lowpan.c ip-hdrs +lib6lowpanIP.o: lib6lowpanIP.c ip-hdrs +lib6lowpanFrag.o: lib6lowpanFrag.c ip-hdrs + +ip-hdrs: $(INCLUDE)/6lowpan.h $(INCLUDE)/ip.h $(INCLUDE)/lib6lowpan.h \ No newline at end of file diff --git a/support/sdk/c/blip/lib6lowpan/in_cksum.c b/support/sdk/c/blip/lib6lowpan/in_cksum.c new file mode 100644 index 00000000..bcad3fd5 --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/in_cksum.c @@ -0,0 +1,222 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* in_cksum.c + * 4.4-Lite-2 Internet checksum routine, modified to take a vector of + * pointers/lengths giving the pieces to be checksummed. + * + * $Id$ + */ + +/* + * Copyright (c) 1988, 1992, 1993 + * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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. + * + * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 + */ + +#include +#include "in_cksum.h" +#include "lib6lowpan.h" + + +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) +#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} + +int +in_cksum(const vec_t *vec, int veclen) { + + uint32_t sum = 0; + uint16_t res = 0; + uint16_t cur = 0; + int i; + + + uint8_t *w; + + for (; veclen != 0; vec++, veclen--) { + if (vec->len == 0) + continue; + + w = (uint8_t *)vec->ptr; + for (i = 0; i < vec->len; i++) { + if (i % 2 == 0) { + cur |= ((uint16_t)w[i]) << 8; + if (i + 1 == vec->len) { + goto finish; + } + } else { + cur |= w[i]; + finish: + sum += cur; + res = (sum & 0xffff) + (sum >> 16); + cur = 0; + } + } + } + return ~res ; +#if 0 + register const uint16_t *w; + register uint32_t sum = 0; + register uint32_t mlen = 0; + int byte_swapped = 0; + + union { + uint8_t c[2]; + uint16_t s; + } s_util; + union { + uint16_t s[2]; + uint32_t l; + } l_util; + + for (; veclen != 0; vec++, veclen--) { + if (vec->len == 0) + continue; + w = (const uint16_t *)vec->ptr; + if (mlen == -1) { + /* + * The first byte of this chunk is the continuation + * of a word spanning between this chunk and the + * last chunk. + * + * s_util.c[0] is already saved when scanning previous + * chunk. + */ + s_util.c[1] = *(const uint8_t *)w; + sum += s_util.s; + w = (const uint16_t *)((const uint8_t *)w + 1); + mlen = vec->len - 1; + } else + mlen = vec->len; + /* + * Force to even boundary. + */ + if ((1 & (int) w) && (mlen > 0)) { + REDUCE; + sum <<= 8; + s_util.c[0] = *(const uint8_t *)w; + w = (const uint16_t *)((const uint8_t *)w + 1); + mlen--; + byte_swapped = 1; + } + /* + * Unroll the loop to make overhead from + * branches &c small. + */ + while ((mlen -= 32) >= 0) { + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; + sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; + sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; + sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; + w += 16; + } + mlen += 32; + while ((mlen -= 8) >= 0) { + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; + w += 4; + } + mlen += 8; + if (mlen == 0 && byte_swapped == 0) + continue; + REDUCE; + while ((mlen -= 2) >= 0) { + sum += *w++; + } + if (byte_swapped) { + REDUCE; + sum <<= 8; + byte_swapped = 0; + if (mlen == -1) { + s_util.c[1] = *(const uint8_t *)w; + sum += s_util.s; + mlen = 0; + } else + mlen = -1; + } else if (mlen == -1) + s_util.c[0] = *(const uint8_t *)w; + } + if (mlen == -1) { + /* The last mbuf has odd # of bytes. Follow the + standard (the odd byte may be shifted left by 8 bits + or not as determined by endian-ness of the machine) */ + s_util.c[1] = 0; + sum += s_util.s; + } + REDUCE; + return (~sum & 0xffff); +#endif +} + +/* SDH : Added to allow for friendly message checksumming */ +uint16_t msg_cksum(struct split_ip_msg *msg, uint8_t nxt_hdr) { + struct generic_header *cur; + int n_headers = 4; + vec_t cksum_vec[7]; + uint32_t hdr[2]; + + cksum_vec[0].ptr = (uint8_t *)(msg->hdr.ip6_src.s6_addr); + cksum_vec[0].len = 16; + cksum_vec[1].ptr = (uint8_t *)(msg->hdr.ip6_dst.s6_addr); + cksum_vec[1].len = 16; + cksum_vec[2].ptr = (uint8_t *)hdr; + cksum_vec[2].len = 8; + hdr[0] = msg->data_len; + hdr[1] = htonl(nxt_hdr); + cksum_vec[3].ptr = msg->data; + cksum_vec[3].len = msg->data_len; + + cur = msg->headers; + while (cur != NULL) { + cksum_vec[n_headers].ptr = cur->hdr.data; + cksum_vec[n_headers].len = cur->len; + hdr[0] += cur->len; + n_headers++; + cur = cur->next; + } + hdr[0] = htonl(hdr[0]); + + return in_cksum(cksum_vec, n_headers); +} diff --git a/support/sdk/c/blip/lib6lowpan/ip_malloc.c b/support/sdk/c/blip/lib6lowpan/ip_malloc.c new file mode 100644 index 00000000..0ace8e7a --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/ip_malloc.c @@ -0,0 +1,97 @@ +#ifndef NO_IP_MALLOC +#include +#include +#include "ip_malloc.h" + +uint8_t heap[IP_MALLOC_HEAP_SIZE]; + +void ip_malloc_init() { + bndrt_t *b = (bndrt_t *)heap; + *b = IP_MALLOC_HEAP_SIZE & IP_MALLOC_LEN; +} + +void *ip_malloc(uint16_t sz) { + bndrt_t *cur = (bndrt_t *)heap; + sz += sizeof(bndrt_t) * 2; + sz += (sz % IP_MALLOC_ALIGN); + + while (((*cur & IP_MALLOC_LEN) < sz || (*cur & IP_MALLOC_INUSE) != 0) + && (uint8_t *)cur - heap < IP_MALLOC_HEAP_SIZE) { + cur = (bndrt_t *)(((uint8_t *)cur) + ((*cur) & IP_MALLOC_LEN)); + } + + if ((uint8_t *)cur < heap + IP_MALLOC_HEAP_SIZE) { + uint16_t oldsize = *cur & IP_MALLOC_LEN; + bndrt_t *next; + sz -= sizeof(bndrt_t); + next = ((bndrt_t *)(((uint8_t *)cur) + sz)); + + *cur = (sz & IP_MALLOC_LEN) | IP_MALLOC_INUSE; + *next = (oldsize - sz) & IP_MALLOC_LEN; + + return cur + 1; + } else return NULL; +} + +void ip_free(void *ptr) { + bndrt_t *prev = NULL, *cur, *next = NULL; + cur = (bndrt_t *)heap; + + while (cur + 1 != ptr && (uint8_t *)cur - heap < IP_MALLOC_HEAP_SIZE) { + prev = cur; + cur = (bndrt_t *)(((uint8_t *)cur) + ((*cur) & IP_MALLOC_LEN)); + } + if (cur + 1 == ptr) { + next = (bndrt_t *)((*cur & IP_MALLOC_LEN) + ((uint8_t *)cur)); + + *cur &= ~IP_MALLOC_INUSE; + if ((((uint8_t *)next) - heap) < IP_MALLOC_HEAP_SIZE && + (*next & IP_MALLOC_INUSE) == 0) { + *cur = (*cur & IP_MALLOC_LEN) + (*next & IP_MALLOC_LEN); + } + if (prev != NULL && (*prev & IP_MALLOC_INUSE) == 0) { + *prev = (*prev & IP_MALLOC_LEN) + (*cur & IP_MALLOC_LEN); + } + } +} + +uint16_t ip_malloc_freespace() { + uint16_t ret = 0; + bndrt_t *cur = (bndrt_t *)heap; + + while ((uint8_t *)cur - heap < IP_MALLOC_HEAP_SIZE) { + if ((*cur & IP_MALLOC_INUSE) == 0) + ret += *cur & IP_MALLOC_LEN; + cur = (bndrt_t *)(((uint8_t *)cur) + ((*cur) & IP_MALLOC_LEN)); + } + return ret; +} + +#ifdef PC +void dump_heap() { + int i; + for (i = 0; i < IP_MALLOC_HEAP_SIZE; i++) { + printf("0x%x ", heap[i]); + if (i % 8 == 7) printf(" "); + if (i % 16 == 15) printf ("\n"); + if (i > 64) break; + } + printf("\n"); +} + +void ip_print_heap() { + bndrt_t *cur = (bndrt_t *)heap; + while (((uint8_t *)cur) - heap < IP_MALLOC_HEAP_SIZE) { + printf ("heap region start: 0x%x length: %i used: %i\n", + cur, (*cur & IP_MALLOC_LEN), (*cur & IP_MALLOC_INUSE) >> 15); + if ((*cur & IP_MALLOC_LEN) == 0) { + printf("ERROR: zero length cell detected!\n"); + dump_heap(); + exit(1); + } + cur = (bndrt_t *)(((uint8_t *)cur) + ((*cur) & IP_MALLOC_LEN)); + + } +} +#endif +#endif diff --git a/support/sdk/c/blip/lib6lowpan/lib6lowpan.c b/support/sdk/c/blip/lib6lowpan/lib6lowpan.c new file mode 100644 index 00000000..3ebe2f67 --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/lib6lowpan.c @@ -0,0 +1,346 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#include "6lowpan.h" +#include "ip.h" +#include "lib6lowpan.h" + + +#ifndef __6LOWPAN_16BIT_ADDRESS +#error "Only 16-bit short addresses are supported" +#endif + +/* + * Library implementation of packing of 6lowpan packets. + * + * This should allow uniform code treatment between pc and mote code; + * the goal is to write ANSI C here... This means no nx_ types, + * unfortunately. + * + * Accessing fields programtically is probably a little less + * efficient, but that can be improved. By precomputing the packet + * headers present, we can make the overhead not too bad. The #1 + * goal of this library is portability and readability. + * + * The broadcast and mesh headers may or may not be useful, and are + * off by default to reduce code size. Removing them reduces the + * library size by about 600 bytes. + */ + + +/* + * Return the length (in bytes) of the buffer required to pack lowmsg + * into a buffer. + */ +uint8_t *getLowpanPayload(packed_lowmsg_t *lowmsg) { + uint8_t len = 0; +#if LIB6LOWPAN_FULL + if (lowmsg->headers & LOWMSG_MESH_HDR) + len += LOWMSG_MESH_LEN; + if (lowmsg->headers & LOWMSG_BCAST_HDR) + len += LOWMSG_BCAST_LEN; +#endif + if (lowmsg->headers & LOWMSG_FRAG1_HDR) + len += LOWMSG_FRAG1_LEN; + if (lowmsg->headers & LOWMSG_FRAGN_HDR) + len += LOWMSG_FRAGN_LEN; + return lowmsg->data + len; +} + +/* + * Return a bitmap indicating which lowpan headers are + * present in the message pointed to by lowmsg. + * + */ +uint16_t getHeaderBitmap(packed_lowmsg_t *lowmsg) { + uint16_t headers = 0; + uint8_t *buf = lowmsg->data; + uint16_t len = lowmsg->len; + if (buf == NULL) return headers; + + if (len > 0 && ((*buf) >> 6) == LOWPAN_NALP_PATTERN) { + return LOWMSG_NALP; + } + +#if LIB6LOWPAN_FULL + if (len > 0 && ((*buf) >> 6) == LOWPAN_MESH_PATTERN) { + if (!(*buf & LOWPAN_MESH_V_MASK) || + !(*buf & LOWPAN_MESH_F_MASK)) { + // we will not parse a packet with 64-bit addressing. + return LOWMSG_NALP; + } + headers |= LOWMSG_MESH_HDR; + buf += LOWMSG_MESH_LEN; + len -= LOWMSG_MESH_LEN; + } + if (len > 0 && (*buf) == LOWPAN_BCAST_PATTERN) { + headers |= LOWMSG_BCAST_HDR; + buf += LOWMSG_BCAST_LEN; + len -= LOWMSG_BCAST_LEN; + } +#endif + + if (len > 0 && ((*buf) >> 3) == LOWPAN_FRAG1_PATTERN) { + headers |= LOWMSG_FRAG1_HDR; + buf += LOWMSG_FRAG1_LEN; + len -= LOWMSG_FRAG1_LEN; + } + if (len > 0 && ((*buf) >> 3) == LOWPAN_FRAGN_PATTERN) { + headers |= LOWMSG_FRAGN_HDR; + buf += LOWMSG_FRAGN_LEN; + len -= LOWMSG_FRAGN_LEN; + } + return headers; +} + +/* + * Fill in dispatch values + */ +uint8_t setupHeaders(packed_lowmsg_t *packed, uint16_t headers) { + uint8_t *buf = packed->data; + uint16_t len = packed->len; + if (packed == NULL) return 1; + if (buf == NULL) return 1; + packed->headers = 0; +#if LIB6LOWPAN_FULL + if (headers & LOWMSG_MESH_HDR) { + if (len < LOWMSG_MESH_LEN) return 1; + packed->headers |= LOWMSG_MESH_HDR; + *buf = LOWPAN_MESH_PATTERN << 6 | LOWPAN_MESH_V_MASK | LOWPAN_MESH_F_MASK; + buf += LOWMSG_MESH_LEN; + len -= LOWMSG_MESH_LEN; + } + if (headers & LOWMSG_BCAST_HDR) { + if (len < LOWMSG_BCAST_LEN) return 1; + packed->headers |= LOWMSG_BCAST_HDR; + *buf = LOWPAN_BCAST_PATTERN; + buf += LOWMSG_BCAST_LEN; + len -= LOWMSG_BCAST_LEN; + } +#endif + if (headers & LOWMSG_FRAG1_HDR) { + if (len < LOWMSG_FRAG1_HDR) return 1; + packed->headers |= LOWMSG_FRAG1_HDR; + *buf = LOWPAN_FRAG1_PATTERN << 3; + buf += LOWMSG_FRAG1_LEN; + len -= LOWMSG_FRAG1_LEN; + } + if (headers & LOWMSG_FRAGN_HDR) { + if (len < LOWMSG_FRAGN_HDR) return 1; + packed->headers |= LOWMSG_FRAGN_HDR; + *buf = LOWPAN_FRAGN_PATTERN << 3; + } + return 0; + +} + +/* + * Test if various headers are present are enabled + */ +#ifdef LIB6LOWPAN_FULL +inline uint8_t hasMeshHeader(packed_lowmsg_t *msg) { + return (msg->headers & LOWMSG_MESH_HDR); +} +inline uint8_t hasBcastHeader(packed_lowmsg_t *msg) { + return (msg->headers & LOWMSG_BCAST_HDR); +} +#endif +inline uint8_t hasFrag1Header(packed_lowmsg_t *msg) { + return (msg->headers & LOWMSG_FRAG1_HDR); +} +inline uint8_t hasFragNHeader(packed_lowmsg_t *msg) { + return (msg->headers & LOWMSG_FRAGN_HDR); +} +#ifdef LIB6LOWPAN_FULL +/* + * Mesh header fields + * + * return FAIL if the message doesn't have a mesh header + */ +inline uint8_t getMeshHopsLeft(packed_lowmsg_t *msg, uint8_t *hops) { + uint8_t *buf = msg->data; + if (!hasMeshHeader(msg) || msg->data == NULL || hops == NULL) return 1; + *hops = (*buf) & LOWPAN_MESH_HOPS_MASK; + return 0; +} +inline uint8_t getMeshOriginAddr(packed_lowmsg_t *msg, hw_addr_t *origin) { + uint8_t *buf = msg->data; + if (!hasMeshHeader(msg) || msg->data == NULL || origin == NULL) return 1; + // skip 64-bit addresses + if (!(*buf & LOWPAN_MESH_V_MASK)) return 1; + buf += 1; + *origin = ntoh16(*((uint16_t *)buf)); + return 0; +} +inline uint8_t getMeshFinalAddr(packed_lowmsg_t *msg, hw_addr_t *final) { + uint8_t *buf = msg->data; + if (!hasMeshHeader(msg) || msg->data == NULL || final == NULL) return 1; + // skip 64-bit addresses + if (!(*buf & LOWPAN_MESH_F_MASK)) return 1; + buf += 3; + *final = ntoh16(*((uint16_t *)buf)); + return 0; +} + + +inline uint8_t setMeshHopsLeft(packed_lowmsg_t *msg, uint8_t hops) { + uint8_t *buf = msg->data; + if (!hasMeshHeader(msg) || msg->data == NULL) return 1; + + *buf = 0xb0; + *buf |= hops & LOWPAN_MESH_HOPS_MASK; + return 0; +} +inline uint8_t setMeshOriginAddr(packed_lowmsg_t *msg, hw_addr_t origin) { + uint8_t *buf = msg->data; + if (!hasMeshHeader(msg) || msg->data == NULL) return 1; + // skip 64-bit addresses + if (!(*buf & LOWPAN_MESH_V_MASK)) return 1; + buf += 1; + *((uint16_t *)buf) = hton16(origin); + return 0; +} +inline uint8_t setMeshFinalAddr(packed_lowmsg_t *msg, hw_addr_t final) { + uint8_t *buf = msg->data; + if (!hasMeshHeader(msg) || msg->data == NULL) return 1; + // skip 64-bit addresses + if (!(*buf & LOWPAN_MESH_F_MASK)) return 1; + buf += 3; + *((uint16_t *)buf) = hton16(final); + return 0; +} + +/* + * Broadcast header fields + */ +inline uint8_t getBcastSeqno(packed_lowmsg_t *msg, uint8_t *seqno) { + uint8_t *buf = msg->data; + if (buf == NULL || seqno == NULL || !hasBcastHeader(msg)) return 1; + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (*buf != LOWPAN_BCAST_PATTERN) return 2; + buf += 1; + *seqno = *buf; + return 0; +} + +inline uint8_t setBcastSeqno(packed_lowmsg_t *msg, uint8_t seqno) { + uint8_t *buf = msg->data; + if (buf == NULL || !hasBcastHeader(msg)) return 1; + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (*buf != LOWPAN_BCAST_PATTERN) return 2; + buf += 1; + *buf = seqno; + return 0; +} +#endif + +/* + * Fragmentation header fields + */ +inline uint8_t getFragDgramSize(packed_lowmsg_t *msg, uint16_t *size) { + uint8_t *buf = msg->data; + uint8_t s[2]; + if (buf == NULL || size == NULL) return 1; +#ifdef LIB6LOWPAN_FULL + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (hasBcastHeader(msg)) buf += LOWMSG_BCAST_LEN; +#endif + if ((*buf >> 3) != LOWPAN_FRAG1_PATTERN && + (*buf >> 3) != LOWPAN_FRAGN_PATTERN) return 1; + + s[0] = *buf & 0x7; + buf++; + s[1] = *buf; + *size = ntoh16 ( *(uint16_t *)s); + return 0; +} +inline uint8_t getFragDgramTag(packed_lowmsg_t *msg, uint16_t *tag) { + uint8_t *buf = msg->data; + if (buf == NULL || tag == NULL) return 1; +#ifdef LIB6LOWPAN_FULL + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (hasBcastHeader(msg)) buf += LOWMSG_BCAST_LEN; +#endif + if ((*buf >> 3) != LOWPAN_FRAG1_PATTERN && + (*buf >> 3) != LOWPAN_FRAGN_PATTERN) return 1; + buf += 2; + //*tag = (*buf << 8) | *(buf + 1); ; + *tag = ntoh16( *(uint16_t *)buf); + return 0; +} +inline uint8_t getFragDgramOffset(packed_lowmsg_t *msg, uint8_t *size) { + uint8_t *buf = msg->data; + if (buf == NULL || size == NULL) return 1; +#ifdef LIB6LOWPAN_FULL + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (hasBcastHeader(msg)) buf += LOWMSG_BCAST_LEN; +#endif + if ((*buf >> 3) != LOWPAN_FRAGN_PATTERN) return 1; + buf += 4; + *size = *buf; + return 0; + +} + + +inline uint8_t setFragDgramSize(packed_lowmsg_t *msg, uint16_t size) { + uint8_t *buf = msg->data; + if (buf == NULL) return 1; +#ifdef LIB6LOWPAN_FULL + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (hasBcastHeader(msg)) buf += LOWMSG_BCAST_LEN; +#endif + if ((*buf >> 3) != LOWPAN_FRAG1_PATTERN && + (*buf >> 3) != LOWPAN_FRAGN_PATTERN) return 1; + // zero out the dgram size first. + *buf &= 0xf8; + *(buf + 1) = 0; + *((uint16_t *)buf) |= hton16(size & 0x7ff); + return 0; +} + +inline uint8_t setFragDgramTag(packed_lowmsg_t *msg, uint16_t tag) { + uint8_t *buf = msg->data; + if (buf == NULL) return 1; +#ifdef LIB6LOWPAN_FULL + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (hasBcastHeader(msg)) buf += LOWMSG_BCAST_LEN; +#endif + + if ((*buf >> 3) != LOWPAN_FRAG1_PATTERN && + (*buf >> 3) != LOWPAN_FRAGN_PATTERN) return 1; + buf += 2; + *(uint16_t *)buf = ntoh16(tag); + return 0; +} +inline uint8_t setFragDgramOffset(packed_lowmsg_t *msg, uint8_t size) { + uint8_t *buf = msg->data; + if (buf == NULL) return 1; +#ifdef LIB6LOWPAN_FULL + if (hasMeshHeader(msg)) buf += LOWMSG_MESH_LEN; + if (hasBcastHeader(msg)) buf += LOWMSG_BCAST_LEN; +#endif + + if ((*buf >> 3) != LOWPAN_FRAGN_PATTERN) return 1; + buf += 4; + *buf = size; + return 0; +} diff --git a/support/sdk/c/blip/lib6lowpan/lib6lowpanFrag.c b/support/sdk/c/blip/lib6lowpan/lib6lowpanFrag.c new file mode 100644 index 00000000..dfb4df4a --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/lib6lowpanFrag.c @@ -0,0 +1,205 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* + * @author Stephen Dawson-Haggerty + */ + +#include +#include +#include +#include + +#include "ip.h" +#include "ip_malloc.h" +#include "6lowpan.h" +#include "lib6lowpan.h" + +#define min(a,b) ( ((a)>(b)) ? (b) : (a) ) +#define max(a,b) ( ((a)<(b)) ? (b) : (a) ) + +uint16_t lib6lowpan_frag_tag = 0; + +void ip_memclr(uint8_t *buf, uint16_t len) { + for (; len > 0; len--) + *buf++ = 0; + +} + +void *ip_memcpy(void *dst0, const void *src0, uint16_t len) { + uint8_t *dst = (uint8_t *) dst0; + uint8_t *src = (uint8_t *) src0; + void *ret = dst0; + + for (; len > 0; len--) + *dst++ = *src++; + + return ret; +} + +/* + * this function writes the next fragment which needs to be sent into + * the buffer passed in. It updates the structures in process to + * reflect how much of the packet has been sent so far. + * + * if the packet does not require fragmentation, this function will + * not insert a fragmentation header and will merely compress the + * headers into the packet. + * + * returns the number of bytes used in buf, or zero if there was no + * fragment to be sent. + * + */ +uint8_t getNextFrag(struct split_ip_msg *msg, fragment_t *progress, + uint8_t *buf, uint16_t len) { + if (msg == NULL || progress == NULL || buf == NULL) return 0; + packed_lowmsg_t pkt; + uint16_t frag_length = 0; + pkt.headers = 0; + pkt.data = buf; + pkt.len = len; + + // if this is the first fragment, we will compress the headers in + // the ip message, and only insert a fragmentation header if + // necessary to pack it into buffer + if (progress->offset == 0) { + uint8_t *compressed_headers; + uint8_t lowpan_len = 0; + uint8_t cmpr_header_len = 0, header_length = 0; + + compressed_headers = malloc(LIB6LOWPAN_MAX_LEN); + if (compressed_headers == NULL) return 0; + + // pack the headers into a temporary buffer + cmpr_header_len = packHeaders(msg, compressed_headers, LIB6LOWPAN_MAX_LEN); + + { + struct generic_header *cur = msg->headers; + while (cur != NULL) { + header_length += cur->len; + cur = cur->next; + } + } + + // printBuf(compressed_headers, compressed_len); + // printf("payload: %p\n", payload); + + // maybe add a fragmentation header + if (cmpr_header_len + msg->data_len > len) { + pkt.headers |= LOWMSG_FRAG1_HDR; + if (setupHeaders(&pkt, pkt.headers)) goto free_fail; + if (setFragDgramTag(&pkt, ++lib6lowpan_frag_tag)) goto free_fail; + if (setFragDgramSize(&pkt, ntoh16(msg->hdr.plen) + sizeof(struct ip6_hdr))) goto free_fail; + lowpan_len += LOWMSG_FRAG1_LEN; + } else { + if (setupHeaders(&pkt, pkt.headers)) goto free_fail; + } + ip_memcpy(getLowpanPayload(&pkt), compressed_headers, cmpr_header_len); + + /* + * calculate how much to put into this fragment + * + * if the whole packet fits in the buffer, this is easy; it's the + * compressed headers plus the payload length. + * + * given fragmentation, we need to do a little more work. + */ + if (pkt.headers & LOWMSG_FRAG1_HDR) { + frag_length = len - cmpr_header_len - LOWMSG_FRAG1_LEN + sizeof(struct ip6_hdr) + header_length; + frag_length -= (frag_length % 8); + frag_length -= (sizeof(struct ip6_hdr) + header_length); + } else { + frag_length = ntoh16(msg->hdr.plen) - header_length; + } + // frag_length contains the number of bytes in uncompressed headers. + + ip_memcpy(getLowpanPayload(&pkt) + cmpr_header_len, + msg->data, frag_length); + + progress->tag = lib6lowpan_frag_tag; + progress->offset = frag_length + sizeof(struct ip6_hdr) + header_length; + + // printfUART("frag: 0x%x 0x%x 0x%x\n", header_len, frag_length, compressed_len); + + // return the length we wrote, which comes in three pieces; + free(compressed_headers); + return lowpan_len + cmpr_header_len + frag_length; + free_fail: + free(compressed_headers); + goto fail; + } else { + /* + * we've already sent the first fragment; we only need to send a + * subsequent one or return zero if we're at the end of the buffer; + * + */ + //printf("offset: 0x%x plen: 0x%x\n", progress->offset, ntoh16(ip->plen) + sizeof(struct ip6_hdr)); + + // NOTE : this should be a >= to detect runaway lengths. However, + // it is useful for debugging to require equality. + if (progress->offset == ntoh16(msg->hdr.plen) + sizeof(struct ip6_hdr)) return 0; + // the only headers we need now is the fragn header. + + pkt.headers |= LOWMSG_FRAGN_HDR; + + // send out the fragments some frasgments. + //printf ("--- sending fragment\n"); + // now we're pointing at the start of the 6loWPAN frame in the packet. + pkt.data = buf; + pkt.len = len; + // setup the fragmentation headers + if (setupHeaders(&pkt, pkt.headers)) goto fail; + if (setFragDgramTag(&pkt, progress->tag)) goto fail; + + //printf ("frag dgram size 0x%x progress: 0x%x\n", ntoh16(ip->plen) + sizeof(struct ip6_hdr), +/* progress->offset); */ + + if (setFragDgramSize(&pkt, ntoh16(msg->hdr.plen) + sizeof(struct ip6_hdr))) goto fail; + if (setFragDgramOffset(&pkt, (progress->offset) / 8)) goto fail; + + frag_length = min(len - LOWMSG_FRAGN_LEN, + ntoh16(msg->hdr.plen) + sizeof(struct ip6_hdr) - progress->offset); + + + + // unless this is the last fragment, we must sent a multiple of 8 bytes; + if (frag_length + progress->offset != ntoh16(msg->hdr.plen) + sizeof(struct ip6_hdr)) + frag_length -= (frag_length % 8); + + pkt.len = frag_length + LOWMSG_FRAGN_LEN; + + { + uint8_t header_length = sizeof(struct ip6_hdr); + struct generic_header *cur = msg->headers; + while (cur != NULL) { + header_length += cur->len; + cur = cur->next; + } + ip_memcpy(buf + LOWMSG_FRAGN_LEN, msg->data + progress->offset - header_length, frag_length); + } + progress->offset += frag_length; + //printf("frag length is: 0x%x offset: 0x%x max: 0x%x\n", frag_length, progress->offset, LOWPAN_MTU); + + return frag_length + LOWMSG_FRAGN_LEN; + } + fail: + return 0; +} diff --git a/support/sdk/c/blip/lib6lowpan/lib6lowpanIP.c b/support/sdk/c/blip/lib6lowpan/lib6lowpanIP.c new file mode 100644 index 00000000..16b77d20 --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/lib6lowpanIP.c @@ -0,0 +1,628 @@ +/*l + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include +#include "lib6lowpan.h" +/* + * This file presents an interface for parsing IP and UDP headers in a + * 6loWPAN packet. + * + * @author Stephen Dawson-Haggerty + */ + +uint8_t linklocal_prefix [] = {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +uint8_t multicast_prefix [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +struct in6_addr __my_address = {{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65}}}; +uint8_t globalPrefix = 0; + +uint8_t *getLinkLocalPrefix() { + return &linklocal_prefix[0]; +} + +uint8_t cmpPfx(ip6_addr_t a, uint8_t *pfx) { + return (a[0] == pfx[0] && + a[1] == pfx[1] && + a[2] == pfx[2] && + a[3] == pfx[3] && + a[4] == pfx[4] && + a[5] == pfx[5] && + a[6] == pfx[6] && + a[7] == pfx[7]); +} + +int ipv6_addr_suffix_is_long(const ip6_addr_t addr) { + return (!(addr[8] == 0 && + addr[9] == 0 && + addr[10] == 0 && + addr[11] == 0 && + addr[12] == 0 && + addr[13] == 0)); +} + +/* + * return the length of the compressed fields in buf + */ +int getCompressedLen(packed_lowmsg_t *pkt) { + // min lenght is DISPATCH + ENCODING + uint8_t encoding, len = 2; + uint8_t *buf = getLowpanPayload(pkt); + + if (!(*buf == LOWPAN_HC_LOCAL_PATTERN || *buf == LOWPAN_HC_CRP_PATTERN)) + return 0; + + encoding = *(buf + 1); + if ((encoding & LOWPAN_IPHC_VTF_MASK) == LOWPAN_IPHC_VTF_INLINE) + len += 4; + if ((encoding & LOWPAN_IPHC_NH_MASK) == LOWPAN_IPHC_NH_INLINE) + len += 1; + if ((encoding &LOWPAN_IPHC_HLIM_MASK) == LOWPAN_IPHC_HLIM_INLINE) + len += 1; + + switch ((encoding >> LOWPAN_IPHC_SC_OFFSET) & LOWPAN_IPHC_ADDRFLAGS_MASK) { + case LOWPAN_IPHC_ADDR_128: len += 16; break; + case LOWPAN_IPHC_ADDR_64: len += 8; break; + case LOWPAN_IPHC_ADDR_16: len += 2; break; + case LOWPAN_IPHC_ADDR_0: len += 0; break; + } + switch ((encoding >> LOWPAN_IPHC_DST_OFFSET) & LOWPAN_IPHC_ADDRFLAGS_MASK) { + case LOWPAN_IPHC_ADDR_128: len += 16; break; + case LOWPAN_IPHC_ADDR_64: len += 8; break; + case LOWPAN_IPHC_ADDR_16: len += 2; break; + case LOWPAN_IPHC_ADDR_0: len += 0; break; + } + + if ((encoding & LOWPAN_IPHC_NH_MASK) != LOWPAN_IPHC_NH_INLINE) { + // figure out how long the next header encoding is + uint8_t *nh = buf + len; + if ((*nh & LOWPAN_UDP_DISPATCH) == LOWPAN_UDP_DISPATCH) { + // are at a udp packet + len += 1; // add LOWPAN_HCNH + uint8_t udp_enc = *nh; + //printf("udp_enc: 0x%x\n", udp_enc); + if ((udp_enc & LOWPAN_UDP_S_MASK) && (udp_enc & LOWPAN_UDP_D_MASK)) + len += 1; + else if ((udp_enc & LOWPAN_UDP_S_MASK) || (udp_enc & LOWPAN_UDP_D_MASK)) + len += 3; + else + len += 4; + if ((udp_enc & LOWPAN_UDP_C_MASK) == 0) + len += 2; + } + } + + len += (buf - pkt->data); + return len; +} + +int decompressShortAddress(uint8_t dispatch, uint8_t *s_addr, uint8_t *dest) { + if ((*s_addr & LOWPAN_IPHC_SHORT_MASK) == 0) { + // simplest case, just use the appropriate prefix. + if (dispatch == LOWPAN_HC_LOCAL_PATTERN) + ip_memcpy(dest, linklocal_prefix, 8); + else + ip_memcpy(dest, __my_address.s6_addr, 8); + ip_memclr(dest + 8, 8); + dest[14] = (*s_addr) & ~LOWPAN_IPHC_SHORT_MASK; + dest[15] = *(s_addr + 1); + return 0; + } + // otherwise we either have an invalid compression, or else it's a + // multicast address + ip_memcpy(dest, multicast_prefix, 8); + ip_memclr(dest + 8, 8); + switch (*s_addr & LOWPAN_IPHC_SHORT_LONG_MASK) { + case LOWPAN_IPHC_HC1_MCAST: + dest[14] = (*s_addr) & ~LOWPAN_IPHC_SHORT_LONG_MASK; + dest[15] = *(s_addr + 1); + break; + case LOWPAN_IPHC_HC_MCAST: + dest[1] = ((*s_addr) & LOWPAN_HC_MCAST_SCOPE_MASK) >> LOWPAN_HC_MCAST_SCOPE_OFFSET; + + // we'll just direct map the bottom 9 bits in for the moment, + // since HC doesn't specify anything that would break this. In + // the future, a more complicated mapping is likely. + dest[14] = (*s_addr) & 0x1; + dest[15] = *(s_addr + 1); + break; + default: + return 1; + } + return 0; +} + +int decompressAddress(uint8_t dispatch, uint16_t src, uint8_t addr_flags, + uint8_t **buf, uint8_t *dest) { + uint8_t *prefix; + uint16_t tmp; + int rc = 0; + if (dispatch == LOWPAN_HC_LOCAL_PATTERN) + prefix = linklocal_prefix; + else + prefix = __my_address.s6_addr; + + switch (addr_flags) { + case LOWPAN_IPHC_ADDR_128: + ip_memcpy(dest, *buf, 16); + *buf += 16; + break; + case LOWPAN_IPHC_ADDR_64: + ip_memcpy(dest, prefix, 8); + ip_memcpy(dest + 8, *buf, 8); + *buf += 8; + break; + case LOWPAN_IPHC_ADDR_16: + rc = decompressShortAddress(dispatch, *buf, dest); + *buf += 2; + break; + case LOWPAN_IPHC_ADDR_0: + ip_memcpy(dest, prefix, 8); + ip_memclr(dest + 8, 6); + tmp = hton16(src); + ip_memcpy(dest + 14, (uint8_t *)&tmp, 2); + break; + } + return rc; +} + +/* + * Unpacks all headers, including any compressed transport headers if + * there is a compression scheme defined for them. + * + * @pkt - the wrapped struct pointing to the compressed headers + * @dest - buffer to unpack the headers into + * @len - the len of 'dest' + * @return the number of bytes written to dest, or zero if decompression failed. + * should be >= sizeof(struct ip6_hdr) + */ +uint8_t *unpackHeaders(packed_lowmsg_t *pkt, unpack_info_t *u_info, + uint8_t *dest, uint16_t len) { + uint8_t dispatch, encoding; + uint16_t size, extra_header_length = 0; + uint8_t *buf = (uint8_t *)getLowpanPayload(pkt); + + // pointers to fields we may come back to fill in later + uint8_t *plen, *prot_len, *nxt_hdr; + + u_info->payload_offset = 0; + u_info->rih = NULL; + u_info->sh = NULL; + u_info->transport_ptr = NULL; + + // a buffer we can write addresses prefixes and suffexes into. + // now we don't need to check sizes until we get to next headers + if (buf == NULL || len < sizeof(struct ip6_hdr)) return NULL; + len -= sizeof(struct ip6_hdr); + + dispatch = *buf; buf++; + encoding = *buf; buf++; + + if (dispatch != LOWPAN_HC_LOCAL_PATTERN && dispatch != LOWPAN_HC_CRP_PATTERN) + return NULL; + + if ((encoding & LOWPAN_IPHC_VTF_MASK) == LOWPAN_IPHC_VTF_INLINE) { + // copy the inline 4 bytes of fields. + ip_memcpy(dest, buf, 4); + buf += 4; + } else { + // cler the traffic class and flow label fields, and write the version. + ip_memclr(dest, 4); + *dest = IPV6_VERSION << 4; + } + dest += 4; + + plen = dest; + prot_len = dest; + // payload length field requires some computation... + dest += 2; + + if ((encoding & LOWPAN_IPHC_NH_MASK) == LOWPAN_IPHC_NH_INLINE) { + *dest = *buf; + buf++; + } + nxt_hdr = dest; + + dest += 1; + // otherwise, decompress IPNH compression once we reach the end of + // the packed data. + + u_info->hlim = NULL; + if ((encoding & LOWPAN_IPHC_HLIM_MASK) == LOWPAN_IPHC_HLIM_INLINE) { + *dest = *buf; + u_info->hlim = buf; + buf++; + } + dest += 1; + // otherwise, follow instructions for reconstructing hop limit once + // destination address is known. + + + // dest points at the start of the source address IP header field. + decompressAddress(dispatch, pkt->src, + (encoding >> LOWPAN_IPHC_SC_OFFSET) & LOWPAN_IPHC_ADDRFLAGS_MASK, + &buf, dest); + dest += 16; + + decompressAddress(dispatch, pkt->src, + (encoding >> LOWPAN_IPHC_DST_OFFSET) & LOWPAN_IPHC_ADDRFLAGS_MASK, + &buf, dest); + dest += 16; + + // we're done with the IP headers; time to decompress any compressed + // headers which follow... We need to re-check that there's enough + // buffer to do this. + + + if ((encoding & LOWPAN_IPHC_NH_MASK) != LOWPAN_IPHC_NH_INLINE) { + // time to decode some next header fields + // we ought to be pointing at the HCNH encoding byte now. + if ((*buf & LOWPAN_UDP_DISPATCH) == LOWPAN_UDP_DISPATCH) { + pkt->headers |= LOWMSG_IPNH_HDR; + if (len < sizeof(struct udp_hdr)) return NULL; + len -= sizeof(struct udp_hdr); + struct udp_hdr *udp = (struct udp_hdr *)dest; + uint8_t udp_enc = *buf; + uint8_t dst_shift = 4; + + extra_header_length = sizeof(struct udp_hdr); + buf += 1; + // UDP + *nxt_hdr = IANA_UDP; + if (udp_enc & LOWPAN_UDP_S_MASK) { + // recover from 4 bit packing + udp->srcport = hton16((*buf >> 4) + LOWPAN_UDP_PORT_BASE); + dst_shift = 0; + } else { + ip_memcpy((uint8_t *)&udp->srcport, buf, 2); + buf += 2; + } + + if (udp_enc & LOWPAN_UDP_D_MASK) { + udp->dstport = hton16((((*buf >> dst_shift)) & 0x0f) + LOWPAN_UDP_PORT_BASE); + buf += 1; + } else { + if (dst_shift == 0) buf += 1; + ip_memcpy((uint8_t *)&udp->dstport, buf, 2); + buf += 2; + } + + if (udp_enc & LOWPAN_UDP_C_MASK) { + // we elided the checksum and so are supposed to recompute it here. + // however, we won't do this. + } else { + ip_memcpy((uint8_t *)&udp->chksum, buf, 2); + buf += 2; + } + + // still must fill in the length field, but we must first + // recompute the IP length, which we couldn't do until now. + // lamers... + prot_len = (uint8_t *)&udp->len; + dest += sizeof(struct udp_hdr); + + u_info->nxt_hdr = IANA_UDP; + u_info->payload_offset += sizeof(struct udp_hdr); + u_info->transport_ptr = (uint8_t *)udp; + + } else { + // otherwise who knows what's here... it's an error because the + // NH bit said we were inline but when we got here, we didn't + // recognize the NH encoding. + return NULL; + } + } else { + // there was no IPNH field, but there might be uncompressed fields + // we want to copy out for consistency (since we always unpack all + // headers not part of the payload). + uint8_t nhdr = *nxt_hdr; + uint8_t nhdr_len = 0; + struct ip6_ext *hdr; + u_info->nxt_hdr = nhdr; + while (KNOWN_HEADER(nhdr)) { + hdr = (struct ip6_ext *)buf; + u_info->nxt_hdr = nhdr; + switch (nhdr) { + case IANA_UDP: + nhdr = NXTHDR_UNKNOWN; + nhdr_len = sizeof(struct udp_hdr); + u_info->transport_ptr = dest; + break; + case NXTHDR_SOURCE: + u_info->sh = (struct source_header *)buf; + nhdr = hdr->nxt_hdr; + nhdr_len = hdr->len; + u_info->nxt_hdr = nhdr; + break; + case NXTHDR_INSTALL: + // this is how to handle all ipv6 options headers: should we + // use "default" here? + u_info->rih = (struct rinstall_header *)buf; + default: + nhdr = hdr->nxt_hdr; + nhdr_len = hdr->len; + u_info->nxt_hdr = nhdr; + } + if (len < nhdr_len) return NULL; + ip_memcpy(dest, buf, nhdr_len); + dest += nhdr_len; + buf += nhdr_len; + + u_info->payload_offset += nhdr_len; + extra_header_length += nhdr_len; + } + } + + u_info->payload_start = buf; + u_info->header_end = dest; + if (u_info->transport_ptr == NULL) + u_info->transport_ptr = dest; + + // we can go back and figure out the payload length now that we know + // how long the compressed headers were + if (hasFrag1Header(pkt) || hasFragNHeader(pkt)) { + getFragDgramSize(pkt, &size); + size -= sizeof(struct ip6_hdr); + } else { + // it's a one fragment packet + size = pkt->len - (buf - pkt->data); + size += extra_header_length; + size -= getLowpanPayload(pkt) - pkt->data; + } + + *plen = size >> 8; + *(plen + 1) = size & 0xff; + + // finally fill in the udp length field that we finally can recompute + switch (*nxt_hdr) { + case IANA_UDP: + *prot_len = size >> 8; + *(prot_len + 1) = size & 0xff; + } + + + return buf; +} + +/* packs addr into *buf, and updates the pointer relative to the length + * that was needed. + * @returns the bit flags indicating which length was used + */ +uint8_t packAddress(uint8_t dispatch, uint8_t **buf, ip6_addr_t addr) { + + if ((dispatch == LOWPAN_HC_CRP_PATTERN && globalPrefix && + cmpPfx(addr, __my_address.s6_addr)) || + (dispatch == LOWPAN_HC_LOCAL_PATTERN && + cmpPfx(addr, linklocal_prefix))) { + // only choice here are 64-bit and 16-bit addresses + if (ipv6_addr_suffix_is_long(addr)) { + // use the 64-bit compression + ip_memcpy(*buf, &addr[8], 8); + *buf += 8; + return LOWPAN_IPHC_ADDR_64; + } else { + // down to 16 bits: we never use the 0-bit compression + // (althought we could for link local). + ip_memcpy(*buf, &addr[14], 2); + *buf += 2; + return LOWPAN_IPHC_ADDR_16; + } + } else if (addr[0] == 0xff && // is multicast + addr[1] < 0x0f) { // the scope is small enough + // XXX : SDH : Need to check that the group is small enough + **buf = LOWPAN_IPHC_HC_MCAST; // set the encoding bits + **buf |= (addr[1] << LOWPAN_HC_MCAST_SCOPE_OFFSET); // scope + + // direct mapped group id + **buf |= addr[14] & 0x1; + *(*buf + 1) = addr[15]; + *buf += 2; + return LOWPAN_IPHC_ADDR_16; + } else { + // fuck it, send the whole thing + ip_memcpy(*buf, addr, 16); + *buf += 16; + return LOWPAN_IPHC_ADDR_128; + } +} + +/* + * pack the headers of msg into the buffer pointed to by buf. + * + * @returns a pointer to where we stopped writing + */ +uint8_t packHeaders(struct split_ip_msg *msg, + uint8_t *buf, uint8_t len) { + uint8_t *dispatch, *encoding, addr_enc, nxt_hdr; + struct ip6_hdr *hdr = &msg->hdr; + dispatch = buf; + buf += 1; + encoding = buf; + buf += 1; + *encoding = 0; + + if (!(hdr->vlfc[0] == (IPV6_VERSION << 4) && + hdr->vlfc[1] == 0 && + hdr->vlfc[2] == 0 && + hdr->vlfc[3] == 0)) { + ip_memcpy(buf, &hdr->vlfc, 4); + buf += 4; + } else { + *encoding |= LOWPAN_IPHC_VTF_MASK; + } + + nxt_hdr = hdr->nxt_hdr; + if (hdr->nxt_hdr == IANA_UDP /* or other compressed values... */) { + // we will add the HCNH encoding at the end of the header + *encoding |= LOWPAN_IPHC_NH_MASK; + } else { + *buf = hdr->nxt_hdr; + buf += 1; + } + + // always carry hop limit + *buf = hdr->hlim; + buf += 1; + + if (globalPrefix && cmpPfx(hdr->ip6_src.s6_addr, __my_address.s6_addr)) { + *dispatch = LOWPAN_HC_CRP_PATTERN; + } else if (globalPrefix && cmpPfx(hdr->ip6_dst.s6_addr, __my_address.s6_addr)) { + *dispatch = LOWPAN_HC_CRP_PATTERN; + } else if (cmpPfx(hdr->ip6_src.s6_addr, linklocal_prefix)) { + *dispatch = LOWPAN_HC_LOCAL_PATTERN; + } else { + *dispatch = LOWPAN_HC_LOCAL_PATTERN; + } + + addr_enc = packAddress(*dispatch, &buf, hdr->ip6_src.s6_addr); + *encoding |= addr_enc << LOWPAN_IPHC_SC_OFFSET; + + addr_enc = packAddress(*dispatch, &buf, hdr->ip6_dst.s6_addr); + *encoding |= addr_enc << LOWPAN_IPHC_DST_OFFSET; + + len -= (buf - dispatch); + // now come the compressions for special next header values. + // we pack all the headers in the split message into this fragment, and fail if we cannot; + { + int i = 0; + struct generic_header *cur = msg->headers; + while (cur != NULL) { + if (nxt_hdr == IANA_UDP && i == 0) { + struct udp_hdr *udp = cur->hdr.udp; + + uint8_t *udp_enc = buf; + uint8_t *cmpr_port = NULL; + // do the LOWPAN_UDP coding + + if (len < sizeof(struct udp_hdr)) return (buf - dispatch); + + *udp_enc = LOWPAN_UDP_DISPATCH;; + buf += 1; + + + if ((ntoh16(udp->srcport) & LOWPAN_UDP_PORT_BASE_MASK) == + LOWPAN_UDP_PORT_BASE) { + //printf("compr to 4b\n"); + cmpr_port = buf; + *cmpr_port = (ntoh16(udp->srcport) & ~LOWPAN_UDP_PORT_BASE_MASK) << 4; + *udp_enc |= LOWPAN_UDP_S_MASK; + buf += 1; + } else { + ip_memcpy(buf, (uint8_t *)&udp->srcport, 2); + buf += 2; + } + + if ((ntoh16(udp->dstport) & LOWPAN_UDP_PORT_BASE_MASK) == + LOWPAN_UDP_PORT_BASE) { + if (cmpr_port == NULL) { + // the source port must not have been compressed, so + // allocate a new byte for this guy + *buf = ((ntoh16(udp->dstport) & ~LOWPAN_UDP_PORT_BASE_MASK) << 4); + buf += 1; + } else { + // already in the middle of a byte for the port compression, + // so fill in the rest of the byte + *cmpr_port = *cmpr_port | ((ntoh16(udp->dstport) & ~LOWPAN_UDP_PORT_BASE_MASK)); + } + *udp_enc |= LOWPAN_UDP_D_MASK; + } else { + ip_memcpy(buf, (uint8_t *)&udp->dstport, 2); + buf += 2; + } + + // we never elide the checksum + ip_memcpy(buf, (uint8_t *)&udp->chksum, 2); + buf += 2; + } else { + // otherwise we just need to copy the extension header + if (len < cur->len) return 0; + ip_memcpy(buf, (uint8_t *)cur->hdr.ext, cur->len); + len -= cur->len; + buf += cur->len; + } + cur = cur->next; + i++; + } + } + // I think we're done here... + return buf - dispatch; +} + +/* + * indicates how much of the packet after the IP header we will pack + * + */ +/* int packs_header(struct split_ip_msg *msg) { */ +/* switch (hdr->nxt_hdr) { */ +/* case IANA_UDP: */ +/* return sizeof(struct udp_hdr); */ +/* default: */ +/* return 0; */ +/* } */ +/* } */ + + +#define CHAR_VAL(X) (((X) >= '0' && (X) <= '9') ? ((X) - '0') : \ + (((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : ((X) - 'a' + 10))) + + +void inet_pton6(char *addr, struct in6_addr *dest) { + uint16_t cur = 0; + char *p = addr; + uint8_t block = 0, shift = 0; + if (addr == NULL || dest == NULL) return; + ip_memclr(dest->s6_addr, 16); + + // first fill in from the front + while (*p != '\0') { + if (*p != ':') { + cur <<= 4; + cur |= CHAR_VAL(*p); + } else { + dest->s6_addr16[block++] = hton16(cur); + cur = 0; + } + p++; + if (*p == '\0') + return; + if (*(p - 1) == ':' && *p == ':') { + break; + } + } + // we must have hit a "::" which means we need to start filling in from the end. + block = 7; + cur = 0; + while (*p != '\0') p++; + p--; + // now pointing at the end of the address string + while (p > addr) { + if (*p != ':') { + cur |= (CHAR_VAL(*p) << shift); + shift += 4; + } else { + dest->s6_addr16[block--] = hton16(cur); + cur = 0; shift = 0; + } + p --; + if (*(p + 1) == ':' && *p == ':') break; + } +} diff --git a/support/sdk/c/blip/lib6lowpan/printpacket.c b/support/sdk/c/blip/lib6lowpan/printpacket.c new file mode 100644 index 00000000..effa0830 --- /dev/null +++ b/support/sdk/c/blip/lib6lowpan/printpacket.c @@ -0,0 +1,101 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include +#include +// #include +#include "6lowpan.h" +#include "lib6lowpan.h" +#include "lib6lowpanIP.h" + + +void printBuf(uint8_t *buf, uint16_t len) { + int i; + for (i = 1; i <= len; i++) { + printf(" 0x%02x", buf[i-1]); + if (i % 16 == 0) printf("\n"); + + } + printf("\n\n"); +} + + +void printPacket(uint8_t *buf, int len) { + uint8_t val; + uint16_t origin, final; + packed_lowmsg_t pkt; + + // used for autoconfiguration; would be provided by lower layers. + pkt.src = 0xaa; + pkt.dst = 0xbb; + + printBuf(buf, len); + + pkt.data = buf; + pkt.len = len; + pkt.headers = getHeaderBitmap(&pkt); + printf("6loWPAN Packet (headers: 0x%x)\n", pkt.headers); + if (hasBcastHeader(&pkt)) { + getBcastSeqno(&pkt, &val); + printf(" BCast seqno: 0x%x\n", val); + } + if (hasMeshHeader(&pkt)) { + getMeshHopsLeft(&pkt, &val); + getMeshOriginAddr(&pkt, &origin); + getMeshFinalAddr(&pkt, &final); + printf(" Mesh hops: 0x%x origin: 0x%x final: 0x%x\n", val, origin, final); + } + if (hasFrag1Header(&pkt) || hasFragNHeader(&pkt)) { + getFragDgramSize(&pkt, &origin); + getFragDgramTag(&pkt, &final); + printf(" Frag size: 0x%x tag: 0x%x\n", origin, final); + } + if (hasFragNHeader(&pkt)) { + getFragDgramOffset(&pkt, &val); + printf(" Frag offset: 0x%x\n", val); + } + + + uint8_t data[100]; + struct ip6_hdr *h = (struct ip6_hdr *)data; + unpackHeaders(&pkt, (uint8_t *)h, 100); + + printf(" ip first bytes: 0x%x\n", ntohl(*((uint32_t *)h->vlfc))); + printf(" plen: 0x%x next: 0x%x hlim: 0x%x\n", ntohs(h->plen), h->nxt_hdr, h->hlim); + printf(" src: "); + for (val = 0; val < 16; val++) + printf("0x%x ", h->src_addr[val]); + printf("\n dst: "); + for (val = 0; val < 16; val++) + printf("0x%x ", h->dst_addr[val]); + printf("\n"); + + if (h->nxt_hdr == IANA_UDP) { + struct udp_hdr *udp = (struct udp_hdr *)&data[sizeof(struct ip6_hdr)]; + printf("udp src: 0x%x dst: 0x%x len: 0x%x cksum: 0x%x\n", + ntoh16(udp->srcport), ntoh16(udp->dstport), + ntoh16(udp->len), ntoh16(udp->chksum)); + } + + + printf("\n\n"); +} diff --git a/support/sdk/c/blip/libtcp/Makefile b/support/sdk/c/blip/libtcp/Makefile new file mode 100644 index 00000000..d6278736 --- /dev/null +++ b/support/sdk/c/blip/libtcp/Makefile @@ -0,0 +1,18 @@ + +GCC=gcc +CFLAGS=-I../include -I../driver/ -DPC -g + + +all: test_client test_server + +test_circ: test_circ.c circ.c + $(GCC) -o $@ $^ + +test_client: test_client.c tcplib.h tcplib.c circ.c + $(GCC) -o $@ $< tcplib.c circ.c ../driver/tun_dev.c ../lib6lowpan/ip_malloc.c ../lib6lowpan/in_cksum.c $(CFLAGS) + +test_server: test_server.c tcplib.h tcplib.c circ.c + $(GCC) -o $@ $< tcplib.c circ.c ../driver/tun_dev.c ../lib6lowpan/ip_malloc.c ../lib6lowpan/in_cksum.c $(CFLAGS) + +clean: + rm -rf test_server test_circ \ No newline at end of file diff --git a/support/sdk/c/blip/libtcp/circ.c b/support/sdk/c/blip/libtcp/circ.c new file mode 100644 index 00000000..de8bff1f --- /dev/null +++ b/support/sdk/c/blip/libtcp/circ.c @@ -0,0 +1,219 @@ + +#include +#include +// #include +#include + +#include "tcplib.h" + +struct circ_buf { + uint8_t *map; + uint16_t map_len; + uint8_t *data_start; + uint8_t *data_head; + uint16_t data_len; + uint32_t head_seqno; +}; + +int circ_buf_init(void *data, int len, uint32_t seqno, int incl_map) { + struct circ_buf *b = (struct circ_buf *)data; + int bitmap_len = ((len - sizeof(struct circ_buf)) / 9); + // int data_len = bitmap_len * 8; + + // printf("circ_buf_init: len: %i data_len: %i bitmap_len: %i\n", len, data_len, bitmap_len); + // assert(bitmap_len + data_len + sizeof(struct circ_buf) <= len); + + if (len < sizeof(struct circ_buf)) + return -1; + + if (incl_map) { + b->map = (uint8_t *)(b + 1); + b->map_len = bitmap_len; + b->data_start = b->map + bitmap_len; + b->data_len= bitmap_len * 8; + memset(b->map, 0, bitmap_len * 9); + } else { + b->map = NULL; + b->map_len = 0; + b->data_start = (uint8_t *)(b + 1); + b->data_len = len - sizeof(struct circ_buf); + memset(b->data_start, 0, b->data_len); + } + b->data_head = b->data_start; + b->head_seqno = seqno; + + // printf("circ_buf_init: buf: %p data_start: %p data_head: %p data_len: %i\n", + // b, b->data_start, b->data_head, b->data_len); + + return 0; +} + +#define BIT_SET(off,map) map[(off)/8] |= (1 << (7 - ((off) % 8))) +#define BIT_UNSET(off,map) map[(off)/8] &= ~(1 << (7 - ((off) % 8))) +#define BIT_ISSET(off, map) map[(off)/8] & 1 << (7 - (off) % 8) + +static void bitmap_mark(struct circ_buf *b, uint8_t *data, int len) { + int offset = data - b->data_start; + if (b->map_len == 0) return; + while (len-- > 0) { + BIT_SET(offset, b->map); + offset = (offset + 1) % b->data_len; + } +} + +/* return the sequence number of the first byte of data in the buffer; + this is what the stack can ACK. */ +uint32_t circ_get_seqno(void *buf) { + struct circ_buf *b = (struct circ_buf *)buf; + return b->head_seqno; +} + +void circ_set_seqno(void *buf, uint32_t seqno) { + struct circ_buf *b = (struct circ_buf *)buf; + b->head_seqno = seqno; +} + +uint16_t circ_get_window(void *buf) { + struct circ_buf *b = (struct circ_buf *)buf; + return b->data_len; +} + +/* read as many contiguous bytes from the head of the buffer as + * possible, and update the internal data structures to shorten the + * buffer + * + * buf: the circular buffer + * data: a pointer which will be updated with the location of the data + * return: the number of bytes available + */ +int circ_buf_read_head(void *buf, char **data) { + struct circ_buf *b = (struct circ_buf *)buf; + int off = b->data_head - b->data_start; + int rlen = 0; + *data = b->data_head; + while (BIT_ISSET(off, b->map) && off < b->data_len) { + BIT_UNSET(off, b->map); + rlen++; + b->head_seqno++; + b->data_head ++; + if (b->data_head == b->data_start + b->data_len) + b->data_head = b->data_start; + off++; + } + return rlen; +} + + +static void get_ptr_off_1(struct circ_buf *b, uint32_t sseqno, int len, + uint8_t **writeptr, int *w_len) { + uint8_t *endptr = b->data_start + b->data_len; + int offset; + + *writeptr = NULL; + *w_len = 0; + + /* write up to either the end of the buffer */ + offset = sseqno - b->head_seqno; + if (b->data_head + offset < endptr) { + *w_len = len; + *writeptr = b->data_head + offset; + if (*writeptr + *w_len > endptr) { + *w_len = endptr - *writeptr; + } + } +} + +int circ_shorten_head(void *buf, uint32_t seqno) { + struct circ_buf *b = (struct circ_buf *)buf; + int offset = seqno - b->head_seqno; + + b->head_seqno = seqno; + + b->data_head += offset; + while (b->data_head > b->data_start + b->data_len) + b->data_head -= b->data_len; + + return 0; +} + +int circ_buf_read(void *buf, uint32_t sseqno, + uint8_t *data, int len) { + struct circ_buf *b = (struct circ_buf *)buf; + uint8_t *readptr; + int r_len, rc = 0; + + get_ptr_off_1(b, sseqno, len, &readptr, &r_len); + memcpy(data, readptr, r_len); + data += r_len; + rc += r_len; + + if (r_len != len) { + readptr = b->data_start; + r_len = min(len - r_len, b->data_head - b->data_start); + memcpy(data, readptr, r_len); + rc += r_len; + } + return rc; +} + +int circ_buf_write(void *buf, uint32_t sseqno, + uint8_t *data, int len) { + struct circ_buf *b = (struct circ_buf *)buf; + uint8_t *writeptr; + int w_len; + + /* we can't write any bytes since we're trying to write too far + ahead */ + // printf("circ_buf_write: sseqno: %i head_seqno: %i len: %i\n", + // sseqno, b->head_seqno, len); + + if (sseqno > b->head_seqno + b->data_len) + return -1; + + if (sseqno < b->head_seqno) { + /* old data, but already received */ + if (sseqno < b->head_seqno - len) return -1; + /* a segment which overlaps with data we've already received */ + data += (b->head_seqno - sseqno); + len -= (b->head_seqno - sseqno); + sseqno = b->head_seqno; + } + if (len == 0) return 0; + + // printf("circ_buf_write: buf: %p data_start: %p data_head: %p data_len: %i\n", + // b, b->data_start, b->data_head, b->data_len); + get_ptr_off_1(b, sseqno, len, &writeptr, &w_len); + memcpy(writeptr, data, w_len); + data += w_len; + bitmap_mark(b, writeptr, w_len); + + if (w_len != len) { + writeptr = b->data_start; + w_len = min(len - w_len, b->data_head - b->data_start); + memcpy(writeptr, data, w_len); + bitmap_mark(b, writeptr, w_len); + // printf("circ_buf_write (2): write: %p len: %i\n", writeptr, w_len); + } + return 0; +} + +#ifdef PC +void circ_buf_dump(void *buf) { + struct circ_buf *b = (struct circ_buf *)buf; + int i; +/* printf("circ buf: %p\n\tmap: %p\n\tmap_len: %i\n\tdata_start: %p\n\t" */ +/* "data_head: %p\n\tdata_len: %i\n\thead_seqno: %i\n", */ +/* b, b->map, */ +/* b->map_len, b->data_start, b->data_head, b->data_len, b->head_seqno); */ + + for (i = 1; i <= b->data_len; i++) { + if (BIT_ISSET(i-1, b->map)) + putc('x',stdout); + else + putc('_',stdout); + if (i % 80 == 0 || i == b->data_len) { + putc('\n',stdout); + } + } +} +#endif diff --git a/support/sdk/c/blip/libtcp/circ.h b/support/sdk/c/blip/libtcp/circ.h new file mode 100644 index 00000000..d937b06d --- /dev/null +++ b/support/sdk/c/blip/libtcp/circ.h @@ -0,0 +1,26 @@ +#ifndef __CIRC_H_ +#define __CIRC_H_ + +#include + +int circ_buf_init(void *data, int len, uint32_t seqno, int inc_map); + + +int circ_buf_write(void *buf, uint32_t sseqno, + uint8_t *data, int len); + + +int circ_buf_read(void *buf, uint32_t sseqno, + uint8_t *data, int len); + + +int circ_shorten_head(void *buf, uint32_t seqno); + +/* read from the head of the buffer, moving the data pointer forward */ +int circ_buf_read_head(void *buf, char **data); + +void circ_buf_dump(void *buf); + +void circ_set_seqno(void *buf, uint32_t seqno); + +#endif diff --git a/support/sdk/c/blip/libtcp/tcplib.c b/support/sdk/c/blip/libtcp/tcplib.c new file mode 100644 index 00000000..21b8c4d2 --- /dev/null +++ b/support/sdk/c/blip/libtcp/tcplib.c @@ -0,0 +1,562 @@ + +/* A nonblocking library-based implementation of TCP + * + * There are some things like timers which need to be handled + * externally with callbacks. + * + */ + +#include +#include +#include "ip_malloc.h" +#include "in_cksum.h" +#include "6lowpan.h" +#include "ip.h" +#include "tcplib.h" +#include "circ.h" + +static struct tcplib_sock *conns = NULL; + +#define ONE_SEGMENT(X) ((X)->mss) + +uint16_t alloc_local_port() { + return 32012; +} + +static inline void conn_add_once(struct tcplib_sock *sock) { + struct tcplib_sock *iter; + + for (iter = conns; iter != NULL; iter = iter->next) { + if (iter == sock) break; + } + if (iter == NULL) { + sock->next = conns; + conns = sock; + } + +} +static int isInaddrAny(struct in6_addr *addr) { + int i; + for (i = 0; i < 8; i++) + if (addr->s6_addr16[i] != 0) break; + if (i != 8) return 0; + return 1; +} + +static struct tcplib_sock *conn_lookup(struct ip6_hdr *iph, + struct tcp_hdr *tcph) { + struct tcplib_sock *iter; + printfUART("looking up conns...\n"); + for (iter = conns; iter != NULL; iter = iter->next) { + printf("conn lport: %i\n", ntohs(iter->l_ep.sin6_port)); + if (((memcmp(iph->ip6_dst.s6_addr, iter->l_ep.sin6_addr.s6_addr, 16) == 0) || + isInaddrAny(&iter->l_ep.sin6_addr)) && + tcph->dstport == iter->l_ep.sin6_port && + (iter->r_ep.sin6_port == 0 || + (memcmp(&iph->ip6_src, &iter->r_ep.sin6_addr, 16) == 0 && + tcph->srcport == iter->r_ep.sin6_port))) + return iter; + } + return NULL; +} + +static int conn_checkport(uint16_t port) { + struct tcplib_sock *iter; + + for (iter = conns; iter != NULL; iter = iter->next) { + if (iter->l_ep.sin6_port == port) + return -1; + } + return 0; +} + +struct tcp_hdr *find_tcp_hdr(struct split_ip_msg *msg) { + if (msg->hdr.nxt_hdr == IANA_TCP) { + return (struct tcp_hdr *)((msg->headers == NULL) ? msg->data : + msg->headers->hdr.data); + } +} + +static struct split_ip_msg *get_ipmsg(int plen) { + struct split_ip_msg *msg = + (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg) + sizeof(struct tcp_hdr) + plen); + if (msg == NULL) return NULL; + memset(msg, 0, sizeof(struct split_ip_msg) + sizeof(struct tcp_hdr)); + msg->hdr.nxt_hdr = IANA_TCP; + msg->hdr.plen = htons(sizeof(struct tcp_hdr) + plen); + + msg->headers = NULL; + msg->data = (void *)(msg + 1); + msg->data_len = sizeof(struct tcp_hdr) + plen; + + return msg; +} + +static void __tcplib_send(struct tcplib_sock *sock, + struct split_ip_msg *msg) { + struct tcp_hdr *tcph = find_tcp_hdr(msg); + memcpy(&msg->hdr.ip6_dst, &sock->r_ep.sin6_addr, 16); + + sock->flags &= ~TCP_ACKPENDING; + + // sock->ackno = ntohl(tcph->ackno); + + tcph->srcport = sock->l_ep.sin6_port; + tcph->dstport = sock->r_ep.sin6_port; + tcph->offset = sizeof(struct tcp_hdr) * 4; + tcph->window = htons(circ_get_window(sock->rx_buf)); + tcph->chksum = 0; + tcph->urgent = 0; + + tcplib_send_out(msg, tcph); +} + +static void tcplib_send_ack(struct tcplib_sock *sock, int fin_seqno, uint8_t flags) { + struct split_ip_msg *msg = get_ipmsg(0); + + if (msg != NULL) { + struct tcp_hdr *tcp_rep = (struct tcp_hdr *)(msg + 1); + tcp_rep->flags = flags; + + tcp_rep->seqno = htonl(sock->seqno); + tcp_rep->ackno = htonl(circ_get_seqno(sock->rx_buf) + + (fin_seqno ? 1 : 0)); + __tcplib_send(sock, msg); + ip_free(msg); + } +} + +static void tcplib_send_rst(struct ip6_hdr *iph, struct tcp_hdr *tcph) { + struct split_ip_msg *msg = get_ipmsg(0); + + if (msg != NULL) { + struct tcp_hdr *tcp_rep = (struct tcp_hdr *)(msg + 1); + + memcpy(&msg->hdr.ip6_dst, &iph->ip6_src, 16); + + tcp_rep->flags = TCP_FLAG_RST; + + tcp_rep->ackno = tcph->seqno + 1; + tcp_rep->seqno = tcph->ackno;; + + tcp_rep->srcport = tcph->dstport; + tcp_rep->dstport = tcph->srcport; + tcp_rep->offset = sizeof(struct tcp_hdr) * 4; + tcp_rep->window = 0; + tcp_rep->chksum = 0; + tcp_rep->urgent = 0; + + tcplib_send_out(msg, tcp_rep); + + ip_free(msg); + + } +} + +/* send all the data in the tx buffer, starting at sseqno */ +static int tcplib_output(struct tcplib_sock *sock, uint32_t sseqno) { + // the output size is the minimum of the advertised window and the + // conjestion window. of course, if we have less data we send even + // less. + int seg_size = min(sock->seqno - sseqno, sock->r_wind); + seg_size = min(seg_size, sock->cwnd); + while (seg_size > 0 && sock->seqno > sseqno) { + // printf("sending seg_size: %i\n", seg_size); + struct split_ip_msg *msg = get_ipmsg(seg_size); + struct tcp_hdr *tcph; + uint8_t *data; + if (msg == NULL) return -1; + tcph = (struct tcp_hdr *)(msg + 1); + data = (uint8_t *)(tcph + 1); + + tcph->flags = TCP_FLAG_ACK; + tcph->seqno = htonl(sseqno); + tcph->ackno = htonl(circ_get_seqno(sock->rx_buf)); + + circ_buf_read(sock->tx_buf, sseqno, data, seg_size); + __tcplib_send(sock, msg); + ip_free(msg); + + sseqno += seg_size; + seg_size = min(sock->seqno - sseqno, sock->mss); + } + return 0; +} + +int tcplib_init_sock(struct tcplib_sock *sock) { + memset(sock, 0, sizeof(struct tcplib_sock) - sizeof(struct tcplib_sock *)); + sock->mss = 100; + sock->cwnd = ONE_SEGMENT(sock); + sock->ssthresh = 0xffff; + conn_add_once(sock); + return 0; +} + +/* called when a new segment arrives. */ +/* deliver as much data to the app as possible, and update the ack + * number of the socket to reflect how much was delivered + */ +static void add_data(struct tcplib_sock *sock, struct tcp_hdr *tcph, int len) { + char *ptr; + int payload_len; + ptr = ((uint8_t *)tcph) + (tcph->offset / 4); + payload_len = len - (tcph->offset / 4); + // TODO : SDH : optimize out the extra copy for in-sequence data + circ_buf_write(sock->rx_buf, ntohl(tcph->seqno), + ptr, payload_len); + // now try to deliver any data ahead of the ack pointer that's in + // the buffer + + /* if we wrapped around the buffer, we'll actually recieve twice. */ + while ((payload_len = circ_buf_read_head(sock->rx_buf, &ptr)) > 0) { + sock->ops.recvfrom(sock, ptr, payload_len); + } +} + +static void reset_ssthresh(struct tcplib_sock *conn) { + uint16_t new_ssthresh = min(conn->cwnd, conn->r_wind) / 2; + if (new_ssthresh < 2 * ONE_SEGMENT(conn)) + new_ssthresh = 2 * ONE_SEGMENT(conn); + conn->ssthresh = new_ssthresh; +} + +int tcplib_process(struct ip6_hdr *iph, void *payload) { + int rc = 0; + struct tcp_hdr *tcph; + struct tcplib_sock *this_conn; + // uint8_t *ptr; + int payload_len; + int len = ntohs(iph->plen) + sizeof(struct ip6_hdr);; + tcph = (struct tcp_hdr *)payload; + + // printf("tcplib_process\n"); + + /* malformed ip packet? could happen I supppose... */ +/* if (len < sizeof(struct ip6_hdr) || */ +/* len != ntohs(iph->plen) + sizeof(struct ip6_hdr)) { */ +/* fprintf(stderr, "tcplib_process: warn: length mismatch\n"); */ +/* return -1; */ +/* } */ + + /* if there's no local */ + this_conn = conn_lookup(iph, tcph); + if (this_conn != NULL) { + if (tcph->flags & TCP_FLAG_RST) { + /* Really hose this connection if we get a RST packet. + * still TODO: RST generation for unbound ports */ + printf("connection reset by peer\n"); + + if (this_conn->ops.closed) + this_conn->ops.close_done(this_conn); + tcplib_init_sock(this_conn); + return 0; + } + // always get window updates from new segments + // TODO : this should be after we detect out-of-sequence ACK + // numbers! + this_conn->r_wind = ntohs(tcph->window); + + switch (this_conn->state) { + case TCP_LAST_ACK: + if (tcph->flags & TCP_FLAG_ACK && + ntohl(tcph->ackno) == this_conn->seqno + 1) { + // printf("closing connection\n"); + this_conn->state = TCP_CLOSED; + this_conn->ops.close_done(this_conn); + break; + } + + case TCP_SYN_SENT: + if (tcph->flags & (TCP_FLAG_SYN | TCP_FLAG_ACK)) { + // got a syn-ack + // send the ACK + this_conn->state = TCP_ESTABLISHED; + circ_set_seqno(this_conn->rx_buf, ntohl(tcph->seqno) + 1); + // skip the LISTEN processing + // this will also generate an ACK + goto ESTABLISHED; + } else if (this_conn->flags & TCP_FLAG_SYN) { + // otherwise the state machine says we're in a simultaneous open, so continue doen + this_conn->state = TCP_SYN_RCVD; + } else { + printf("sending RST on bad data in state SYN_SENT\n"); + tcplib_send_rst(iph, tcph); + break; + } + case TCP_SYN_RCVD: + case TCP_LISTEN: + /* not connected. */ + if (tcph->flags & TCP_FLAG_SYN) { + struct tcplib_sock *new_sock; + + if (this_conn->state == TCP_LISTEN) { + memcpy(&this_conn->r_ep.sin6_addr, &iph->ip6_src, 16); + this_conn->r_ep.sin6_port = tcph->srcport; + new_sock = tcplib_accept(this_conn, &this_conn->r_ep); + if (new_sock != this_conn) { + memset(this_conn->r_ep.sin6_addr.s6_addr, 0, 16); + this_conn->r_ep.sin6_port = 0; + if (new_sock != NULL) { + memcpy(&new_sock->r_ep.sin6_addr, &iph->ip6_src, 16); + new_sock->r_ep.sin6_port = tcph->srcport; + conn_add_once(new_sock); + } + } + if (new_sock == NULL) { + tcplib_send_rst(iph, tcph); + break; + } + memcpy(&new_sock->l_ep.sin6_addr, &iph->ip6_dst, 16); + new_sock->l_ep.sin6_port = tcph->dstport; + + circ_buf_init(new_sock->rx_buf, new_sock->rx_buf_len, + ntohl(tcph->seqno) + 1, 1); + circ_buf_init(new_sock->tx_buf, new_sock->tx_buf_len, + 0xcafebabe + 1, 0); + } else { + /* recieved a SYN retransmission. */ + new_sock = this_conn; + } + + if (new_sock != NULL) { + new_sock->seqno = 0xcafebabe + 1; + new_sock->state = TCP_SYN_RCVD; + tcplib_send_ack(new_sock, 0, TCP_FLAG_ACK | TCP_FLAG_SYN); + new_sock->seqno++; + } else { + memset(&this_conn->r_ep, 0, sizeof(struct sockaddr_in6)); + } + } else if (this_conn->state == TCP_LISTEN) { + printf("sending RST on out-of-sequence data\n"); + tcplib_send_rst(iph, tcph); + break; + } + /* this is SYN_RECVd */ + if (tcph->flags & TCP_FLAG_ACK) { + // printf("recv ack, in state TCP_SYN_RCVD\n"); + this_conn->state = TCP_ESTABLISHED; + } + /* fall through to handle any data. */ + + case TCP_CLOSE_WAIT: + case TCP_ESTABLISHED: + ESTABLISHED: + // ptr = ((uint8_t *)(iph + 1)) + (tcph->offset / 4); + payload_len = len - sizeof(struct ip6_hdr) - (tcph->offset / 4); + // printf("recv data len: %i\n", payload_len); + + /* ack any data in this packet */ + if (this_conn->state == TCP_ESTABLISHED) { + if (payload_len > 0) + this_conn->flags ++; + + + // receive side sequence check and add data + // printf("seqno: %i ackno: %i\n", ntohl(tcph->seqno), ntohl(tcph->ackno)); + + + // send side recieve sequence check and congestion window updates. + if (ntohl(tcph->ackno) > circ_get_seqno(this_conn->tx_buf)) { + // new data is being ACKed + // or we haven't sent anything new + if (this_conn->cwnd <= this_conn->ssthresh) { + // in slow start; increase the cwnd by one segment + this_conn->cwnd += ONE_SEGMENT(this_conn); + // printf("in slow start\n"); + } else { + // in congestion avoidance + this_conn->cwnd += (ONE_SEGMENT(this_conn) * ONE_SEGMENT(this_conn)) / this_conn->cwnd; + // printf("in congestion avoidence\n"); + } + // printf("ACK new data: cwnd: %i ssthresh: %i\n", this_conn->cwnd, this_conn->ssthresh); + // reset the duplicate ack counter + UNSET_ACK_COUNT(this_conn->flags); + // truncates the ack buffer + circ_shorten_head(this_conn->tx_buf, ntohl(tcph->ackno)); + // printf("ack_count: %i\n", GET_ACK_COUNT(this_conn->flags)); + } else if (this_conn->seqno > circ_get_seqno(this_conn->tx_buf)) { + // this is a duplicate ACK + // - increase the counter of the number of duplicate ACKs + // - if we get to three duplicate ACK's, start resending at + // the ACK number because this probably means we lost a segment + + INCR_ACK_COUNT(this_conn->flags); + // printf("ack_count: %i\n", GET_ACK_COUNT(this_conn->flags)); + // printf("dup ack count: %i\n", GET_ACK_COUNT(this_conn->flags)); + // a "dup ack count" of 2 is really 3 total acks because we start with zero + if (GET_ACK_COUNT(this_conn->flags) == 2) { + UNSET_ACK_COUNT(this_conn->flags); + printf("detected multiple duplicate ACKs-- doing fast retransmit [%u, %u]\n", + circ_get_seqno(this_conn->tx_buf), + this_conn->seqno); + + // this is our detection of a "duplicate ack" event. + // we are going to reset ssthresh and retransmit the data. + reset_ssthresh(this_conn); + tcplib_output(this_conn, circ_get_seqno(this_conn->tx_buf)); + this_conn->timer.retx = 6; + + } + } else if (ntohl(tcph->seqno) != circ_get_seqno(this_conn->rx_buf)) { + printf("==> received out-of-sequence data!\n"); + tcplib_send_ack(this_conn, 0, TCP_FLAG_ACK); + } + add_data(this_conn, tcph, len - sizeof(struct ip6_hdr)); + + + // printf("tx seqno: %i ackno: %i\n", circ_get_seqno(this_conn->tx_buf), + // ntohl(tcph->ackno)); + + + // reset the retransmission timer + if (this_conn->timer.retx == 0) + this_conn->timer.retx = 6; + } + if ((payload_len > 0 && (this_conn->flags & TCP_ACKPENDING) >= 2) + || tcph->flags & TCP_FLAG_FIN) { + ///|| ntohl(tcph->seqno) != circ_get_seqno(this_conn->rx_buf)) { + tcplib_send_ack(this_conn, (payload_len == 0 && tcph->flags & TCP_FLAG_FIN), TCP_FLAG_ACK); + /* only close the connection if we've gotten all the data */ + if (this_conn->state == TCP_ESTABLISHED + && tcph->flags & TCP_FLAG_FIN + && ntohl(tcph->seqno) == circ_get_seqno(this_conn->rx_buf)) { + this_conn->state = TCP_CLOSE_WAIT; + this_conn->ops.closed(this_conn); + } + } + break; + case TCP_CLOSED: + default: + rc = -1; + // printf("sending RST\n"); + // tcplib_send_ack(this_conn, 0, TCP_FLAG_ACK | TCP_FLAG_RST); + } + } else { + /* this_conn was NULL */ + /* TODO : SDH : send ICMP error */ + } + return rc; +} + + +/* bind the socket to a local address */ +int tcplib_bind(struct tcplib_sock *sock, + struct sockaddr_in6 *addr) { + /* not using an already-bound port */ + /* TODO : SDH : check local address */ + if (conn_checkport(addr->sin6_port)) + return -1; + + memcpy(&sock->l_ep, addr, sizeof(struct sockaddr_in6)); + /* passive open */ + sock->state = TCP_LISTEN; +} + +/* connect the socket to a remote endpoint */ +int tcplib_connect(struct tcplib_sock *sock, + struct sockaddr_in6 *serv_addr) { + if (sock->rx_buf == NULL || sock->tx_buf == NULL) + return -1; + + switch (sock->state) { + case TCP_CLOSED: + // passive open; need to set up the local endpoint. + memset(&sock->l_ep, 0, sizeof(struct sockaddr_in6)); + sock->l_ep.sin6_port = htons(alloc_local_port()); + break; + case TCP_LISTEN: + // we got here by calling bind, so we're cool. + break; + default: + return -1; + } + circ_buf_init(sock->rx_buf, sock->rx_buf_len, + 0, 1); + circ_buf_init(sock->tx_buf, sock->tx_buf_len, + 0xcafebabe + 1, 0); + + sock->seqno = 0xcafebabe; + memcpy(&sock->r_ep, serv_addr, sizeof(struct sockaddr_in6)); + tcplib_send_ack(sock, 0, TCP_FLAG_SYN); + sock->state = TCP_SYN_SENT; + sock->seqno++; + return 0; +} + + +int tcplib_send(struct tcplib_sock *sock, void *data, int len) { + /* have enough tx buffer left? */ + if (sock->state != TCP_ESTABLISHED) + return -1; + if (sock->seqno - circ_get_seqno(sock->tx_buf) + len > circ_get_window(sock->tx_buf)) + return -1; + + circ_buf_write(sock->tx_buf, sock->seqno, data, len); + + sock->seqno += len; + // printf("tcplib_output from send\n"); + tcplib_output(sock, sock->seqno - len); + + // 3 seconds + if (sock->timer.retx == 0) + sock->timer.retx = 6; + + return 0; +} + +void tcplib_retx_expire(struct tcplib_sock *sock) { + // printf("retransmission timer expired!\n"); + if (sock->state == TCP_ESTABLISHED && + circ_get_seqno(sock->tx_buf) != sock->seqno) { + printf("retransmitting [%u, %u]\n", circ_get_seqno(sock->tx_buf), + sock->seqno); + reset_ssthresh(sock); + // restart slow start + sock->cwnd = ONE_SEGMENT(sock); + // printf("tcplib_output from timer\n"); + tcplib_output(sock, circ_get_seqno(sock->tx_buf)); + sock->timer.retx = 6; + } else if (sock->state == TCP_LAST_ACK) { + // printf("resending FIN\n"); + tcplib_send_ack(sock, 1, TCP_FLAG_ACK | TCP_FLAG_FIN); + sock->timer.retx = 6; + } +} + +int tcplib_close(struct tcplib_sock *sock) { + int rc = -1; + + switch (sock->state) { + /* passive close */ + case TCP_CLOSE_WAIT: + tcplib_send_ack(sock, 1, TCP_FLAG_ACK | TCP_FLAG_FIN); + sock->timer.retx = 6; + sock->state = TCP_LAST_ACK; + break; + /* active close */ + case TCP_ESTABLISHED: + // kick off the close + + break; + case TCP_SYN_SENT: + sock->state = TCP_CLOSED; + break; + default: + /* this is meaningless in other states */ + rc = -1; + } + return rc; +} + +int tcplib_timer_process() { + struct tcplib_sock *iter; + for (iter = conns; iter != NULL; iter = iter->next) { + if (iter->timer.retx > 0 && (--iter->timer.retx) == 0) + tcplib_retx_expire(iter); + if (iter->flags & TCP_ACKPENDING) { + // printf("sending delayed ACK\n"); + tcplib_send_ack(iter, 0, TCP_FLAG_ACK); + } + } + return 0; +} diff --git a/support/sdk/c/blip/libtcp/tcplib.h b/support/sdk/c/blip/libtcp/tcplib.h new file mode 100644 index 00000000..6b25d1fb --- /dev/null +++ b/support/sdk/c/blip/libtcp/tcplib.h @@ -0,0 +1,162 @@ +#ifndef TCPLIB_H_ +#define TCPLIB_H_ + +// #include +#include "ip.h" + +#define min(X,Y) (((X) > (Y)) ? (Y) : (X)) +#ifndef PC +#define printf(X, args ...) dbg("stdout", X, ## args) +#define fprintf(X, Y, args ...) dbg("fprintf", Y, ## args) +#endif + +typedef enum { + TCP_CLOSED = 0, + TCP_LISTEN, + TCP_SYN_RCVD, + TCP_SYN_SENT, + TCP_ESTABLISHED, + TCP_CLOSE_WAIT, + TCP_LAST_ACK, + TCP_FIN_WAIT_1, + TCP_FIN_WAIT_2, + TCP_CLOSING, + TCP_TIME_WAIT, +} tcplib_sock_state_t; + +enum { + TCP_ACKPENDING = 0x3, + TCP_DUPACKS = 0x3c, + TCP_DUPACKS_OFF = 2, +}; + +#define GET_ACK_COUNT(X) (((X) & TCP_DUPACKS) >> TCP_DUPACKS_OFF) +#define UNSET_ACK_COUNT(X) ((X) &= ~TCP_DUPACKS) +#define INCR_ACK_COUNT(X) ((X) += 1 << TCP_DUPACKS_OFF) +#define ACK_COUNT_IS_3(X) (((X) & TCP_DUPACKS) == TCP_DUPACKS) + +struct tcplib_sock { + uint8_t flags; + + /* local and remote endpoints */ + struct sockaddr_in6 l_ep; + struct sockaddr_in6 r_ep; + + /* current connection state */ + tcplib_sock_state_t state; + + /* a buffer allocated for data on this connection */ + void *rx_buf; + uint16_t rx_buf_len; + + void *tx_buf; + uint16_t tx_buf_len; + + /* max segment size, or default if + we didn't bother to pull it out + of the options field */ + uint16_t mss; + /* the window the other end is + reporting */ + uint16_t r_wind; + uint16_t cwnd; + uint16_t ssthresh; + + // the current next sequence number for ourgoing data. + // the ack number is stored in the receive buffer. + uint32_t seqno; + // uint32_t ackno; + + struct { + int8_t retx; + } timer; + + /* callbacks for this connection */ + struct { + /* a previous connection request has finished */ + void (*connect_done)(struct tcplib_sock *sock, int error); + + /* a callback to signal new data is ready */ + void (*recvfrom)(struct tcplib_sock *sock, void *data, int len); + + /* the connection was closed by the other party */ + void (*closed)(struct tcplib_sock *sock); + + /* you called close(); we've finished closing the socket. */ + void (*close_done)(struct tcplib_sock *sock); + } ops; + + /* this needs to be at the end so + we can call init() on a socket + without blowing away the linked + list */ + struct tcplib_sock *next; +}; + +/* EVENTS + * ------------------------------------------------------------ + * + * calls generated by tcplib that must be dealt with elsewhere in the + * program. + */ + + +/* called when a new connection request is recieved on a socket which + * is LISTENing. + * + * + * return 0 if it wants to accept the connection and allocated a + * buffer for it; -1 otherwise. + */ +struct tcplib_sock *tcplib_accept(struct tcplib_sock *conn, + struct sockaddr_in6 *from); + +/* a call-out point for tcplib to send a message */ +void tcplib_send_out(struct split_ip_msg *msg, struct tcp_hdr *tcph); + +/* upcall for new data; may be dispatched all the way out to a + * handler. + * + * Returns: 0 on success, + * -1 otherwise. The error may be safely ignored. + */ +int tcplib_process(struct ip6_hdr *ip_packet, void *payload); + +/* + * should be called every 500ms to increment all the tcp timers + */ +int tcplib_timer_process(); + +/* Just fill in the fields of the socket. + * + * If you perform a send on a socket in this state, an ephemeral port + * will be allocated to it. + * + * This must be called once on any socket that might be sent on, or + * might have bind() called. + */ +int tcplib_init_sock(struct tcplib_sock *sock); + +/* bind the socket to a local address */ +int tcplib_bind(struct tcplib_sock *sock, + struct sockaddr_in6 *addr); + +/* connect the socket to a remote endpoint */ +int tcplib_connect(struct tcplib_sock *sock, + struct sockaddr_in6 *serv_addr); + + +/* send data on an open socket. + * + * returns: 0 on success + * other errors + * - no local buffer is available, + * + */ +int tcplib_send(struct tcplib_sock *sock, + void *data, int len); + +int tcplib_close(struct tcplib_sock *sock); + + +#endif diff --git a/support/sdk/c/blip/libtcp/test_circ.c b/support/sdk/c/blip/libtcp/test_circ.c new file mode 100644 index 00000000..b6ae8fc1 --- /dev/null +++ b/support/sdk/c/blip/libtcp/test_circ.c @@ -0,0 +1,78 @@ + +#include +#include "circ.h" + +void do_head_read(void *buf) { + char *read_data; + int i, data_len; + data_len = circ_buf_read_head(buf, (void **)&read_data); + printf("buf_read_head: %i\n", data_len); + for (i = 0; i < data_len; i++) + putc(((char *)read_data)[i], stdout); + putc('\n', stdout); +} + +void do_read(void *buf, uint32_t sseqno) { + char data[20]; + int data_len, i; + data_len = circ_buf_read(buf, sseqno, data, 20); + + printf("buf_read: %i\n", data_len); + for (i = 0; i < data_len; i++) + putc(((char *)data)[i], stdout); + putc('\n', stdout); + +} + +int main(int argc, char **argv) { + char buf[200]; + char data[20], readbuf[30]; + int i = 20, data_len; + char *read_data; + if (circ_buf_init(buf, 200, 0, 1) < 0) + printf("cir_buf_init: error\n"); + + for (i=0;i<20;i++) + data[i] = 'a' + i; + + if (circ_buf_write(buf, 0, data, 20) < 0) + printf("circ_buf_write: error\n"); + + if (circ_buf_write(buf, 10, data, 20) < 0) + printf("circ_buf_write: error\n"); + + + if (circ_buf_write(buf, 50, data, 20) < 0) + printf("circ_buf_write: error\n"); + + circ_buf_dump(buf); + + do_head_read(buf); + circ_buf_dump(buf); + + if (circ_buf_write(buf, 30, data, 20) < 0) + printf("circ_buf_write: error\n"); + + circ_buf_dump(buf); + + if (circ_buf_write(buf, 70, data, 20) < 0) + printf("circ_buf_write: error\n"); + + circ_buf_dump(buf); + + do_read(buf, 50); +/* do_head_read(buf); */ +/* circ_buf_dump(buf); */ + +/* if (circ_buf_write(buf, 90, data, 20) < 0) */ +/* printf("circ_buf_write: error\n"); */ +/* if (circ_buf_write(buf, 110, data, 20) < 0) */ +/* printf("circ_buf_write: error\n"); */ +/* if (circ_buf_write(buf, 130, data, 20) < 0) */ +/* printf("circ_buf_write: error\n"); */ + +/* circ_buf_dump(buf); */ +/* do_head_read(buf); */ +/* do_head_read(buf); */ +/* circ_buf_dump(buf); */ +} diff --git a/support/sdk/c/blip/libtcp/test_server.c b/support/sdk/c/blip/libtcp/test_server.c new file mode 100644 index 00000000..4f39e570 --- /dev/null +++ b/support/sdk/c/blip/libtcp/test_server.c @@ -0,0 +1,175 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "ip.h" +#include "tcplib.h" +#include "tun_dev.h" +#include "ip_malloc.h" + + +#define BUFSZ 1024 +#define LOSS_RATE_RECPR 100 + +int sock = 0; +uint8_t iface_addr[16] = {0x20, 0x01, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +struct sockaddr_in6 laddr; + + +void printBuf(uint8_t *buf, uint16_t len) { + int i; + // print("len: %i: ", len); + for (i = 1; i <= len; i++) { + printf(" 0x%02x", buf[i-1]); + // if (i % 16 == 0) printf("\n"); + } + printf("\n"); +} + +void print_split_msg(struct split_ip_msg *msg) { + int i; + printf("src_addr: "); + for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.src_addr[i]); + printf("\ndst_addr: "); + for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.dst_addr[i]); + printf("\nplen: %i hlim: %i\n", ntohs(msg->hdr.plen), msg->hdr.hlim); + + printBuf(msg->data, msg->data_len); +} + +void rx(struct tcplib_sock *sock, void *data, int len) { + // printBuf(data, len); + if (tcplib_send(sock, data, len) < 0) + printf("tcplib_send: fail\n"); +} + +void cl(struct tcplib_sock *sock) { + printf("remote conn closed\n"); + tcplib_close(sock); +} + +void cd(struct tcplib_sock *sock) { + printf("local close done\n"); + free(sock->rx_buf); + free(sock->tx_buf); + tcplib_init_sock(sock); +/* printf("rebinding...\n"); */ +} + +/* called when a new connection request is received: not + * + * return: a tcplib_struc, with the ops table filled in and send and + * receive buffers allocated. + */ + +struct tcplib_sock *tcplib_accept(struct tcplib_sock *conn, + struct sockaddr_in6 *from) { + printf("tcplib_accept\n"); + conn->rx_buf = malloc(BUFSZ); + conn->rx_buf_len = BUFSZ; + + conn->tx_buf = malloc(BUFSZ); + conn->tx_buf_len = BUFSZ; + + conn->ops.recvfrom = rx; + conn->ops.closed = cl; + conn->ops.close_done = cd; + + return conn; +} + +void tcplib_send_out(struct split_ip_msg *msg, struct tcp_hdr *tcph) { + uint8_t buf[8192]; + if (sock <= 0) return; + + memcpy(msg->hdr.src_addr, iface_addr, 16); + msg->hdr.src_addr[15] = 2; + msg->hdr.hlim = 64; + + memset(msg->hdr.vlfc, 0, 4); + msg->hdr.vlfc[0] = 6 << 4; + + tcph->chksum = msg_cksum(msg, IANA_TCP); + + // print_split_msg(msg); + if (rand() % LOSS_RATE_RECPR == 0) { + printf("dropping packet on write\n"); + } else { + tun_write(sock, msg); + } +} + +/* practice accepting connections and transfering data */ +int main(int argg, char **argv) { + char buf[8192], dev[IFNAMSIZ]; + uint8_t *payload; + int len, i, flags; + + ip_malloc_init(); + + payload = buf + sizeof(struct tun_pi); + dev[0] = 0; + if ((sock = tun_open(dev)) < 0) + exit(1); + + if (tun_setup(dev, iface_addr) < 0) + exit(1); + + /* tun_setup turns on non-blocking IO. Turn it off. */ + flags = fcntl(sock, F_GETFL); + flags &= ~O_NONBLOCK; + fcntl(sock,F_SETFL, flags); + + struct tcplib_sock srv_sock; + tcplib_init_sock(&srv_sock); + memcpy(laddr.sin6_addr.s6_addr, iface_addr, 16); + laddr.sin6_addr.s6_addr[15] = 2; + laddr.sin6_port = htons(atoi(argv[1])); + + tcplib_bind(&srv_sock, &laddr); + + fd_set fds; + struct timeval timeout; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + + while (select(sock + 1, &fds, NULL, NULL, &timeout) >= 0) { + if (FD_ISSET(sock, &fds)) { + if ((len = read(sock, buf, 8192)) <= 0) break; + struct ip6_hdr *iph = (struct ip6_hdr *)payload; + if (iph->nxt_hdr == IANA_TCP) { + if (rand() % LOSS_RATE_RECPR == 0) { + printf("dropping packet on rx\n"); + } else { + if (tcplib_process(payload, len - sizeof(struct tun_pi))) + printf("TCPLIB_PROCESS: ERROR!\n"); + } + } + } else { + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + tcplib_timer_process(); + } + if (srv_sock.state == TCP_CLOSED) { + tcplib_bind(&srv_sock, &laddr); + } + + FD_ZERO(&fds); + FD_SET(sock, &fds); + } + tun_close(sock, dev); +} diff --git a/support/sdk/c/blip/serial_tun.conf b/support/sdk/c/blip/serial_tun.conf new file mode 100644 index 00000000..1949d88a --- /dev/null +++ b/support/sdk/c/blip/serial_tun.conf @@ -0,0 +1,22 @@ + +# Before you can run the adaptation layer and router, you must +# configure the address your router will advertise to the subnet, and +# which network interface to proxy neighbor advertisements on. +# + +# set the debug level of the output +# choices are DEBUG, INFO, WARN, ERROR, and FATAL +# log DEBUG + +# set the address of the router's 802.15.4 interface. The interface +# ID must be a 16-bit short identifier. +addr 2001:470:1f04:56d::64 + +# the router can proxy neighbor IPv6 neighbor discovery on another +# interface so that other machines on the subnet can discover hosts +# routing through this router. This specifies which interface to proxy +# the NDP on. +proxy eth1 + +# which 802.15.4 channel to operate on. valid choices are 11-26. +channel 15 diff --git a/support/sdk/c/sf/serialsource.c b/support/sdk/c/sf/serialsource.c index de06e535..dd8c78a8 100644 --- a/support/sdk/c/sf/serialsource.c +++ b/support/sdk/c/sf/serialsource.c @@ -47,7 +47,7 @@ enum { #endif BUFSIZE = 256, MTU = 256, - ACK_TIMEOUT = 1000000, /* in us */ + ACK_TIMEOUT = 100000, /* in us */ SYNC_BYTE = SERIAL_HDLC_FLAG_BYTE, ESCAPE_BYTE = SERIAL_HDLC_CTLESC_BYTE, diff --git a/tos/lib/net/blip/ICMP.h b/tos/lib/net/blip/ICMP.h new file mode 100644 index 00000000..d9657ece --- /dev/null +++ b/tos/lib/net/blip/ICMP.h @@ -0,0 +1,91 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _ICMP_H_ +#define _ICMP_H_ + +enum { + ICMP_EXT_TYPE_PREFIX = 3, + ICMP_EXT_TYPE_BEACON = 17, +}; + +enum { + // jitter start requests by 10 seconds + TRICKLE_JITTER = 10240, + // have a trickle timer with a period of 4 + TRICKLE_PERIOD = 4096, + + // send a maximum of three trickle messages + TRICKLE_MAX = (TRICKLE_PERIOD << 5), + +}; + +typedef nx_struct icmp6_echo_hdr { + nx_uint8_t type; /* type field */ + nx_uint8_t code; /* code field */ + nx_uint16_t cksum; /* checksum field */ + nx_uint16_t ident; + nx_uint16_t seqno; +} icmp_echo_hdr_t; + +typedef nx_struct radv { + nx_uint8_t type; + nx_uint8_t code; + nx_uint16_t cksum; + nx_uint8_t hlim; + nx_uint8_t flags; + nx_uint16_t lifetime; + nx_uint32_t reachable_time; + nx_uint32_t retrans_time; + nx_uint8_t options[0]; +} radv_t; + +typedef nx_struct rsol { + nx_uint8_t type; + nx_uint8_t code; + nx_uint16_t cksum; + nx_uint32_t reserved; +} rsol_t; + +typedef nx_struct rpfx { + nx_uint8_t type; + nx_uint8_t length; + nx_uint8_t pfx_len; + nx_uint8_t flags; + nx_uint32_t valid_lifetime; + nx_uint32_t preferred_lifetime; + nx_uint32_t reserved; + nx_uint8_t prefix[16]; +} pfx_t; + +typedef nx_struct { + nx_uint8_t type; + nx_uint8_t length; + nx_uint16_t metric; +} rqual_t; + +struct icmp_stats { + uint16_t seq; + uint8_t ttl; + uint32_t rtt; +}; + +#endif diff --git a/tos/lib/net/blip/ICMPResponderC.nc b/tos/lib/net/blip/ICMPResponderC.nc new file mode 100644 index 00000000..1438171f --- /dev/null +++ b/tos/lib/net/blip/ICMPResponderC.nc @@ -0,0 +1,57 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include <6lowpan.h> + +configuration ICMPResponderC { + provides interface ICMP; + provides interface ICMPPing[uint16_t client]; + provides interface Statistics; +} implementation { + components NoLedsC as LedsC; + components IPDispatchC, IPRoutingP, ICMPResponderP, IPAddressC; + + ICMP = ICMPResponderP; + ICMPPing = ICMPResponderP; + Statistics = ICMPResponderP; + + ICMPResponderP.Leds -> LedsC; + + ICMPResponderP.IP -> IPDispatchC.IP[IANA_ICMP]; + + ICMPResponderP.IPAddress -> IPAddressC; + + ICMPResponderP.IPRouting -> IPRoutingP; + + components RandomC; + ICMPResponderP.Random -> RandomC; + + components new TimerMilliC() as STimer, + new TimerMilliC() as ATimer, + new TimerMilliC() as PTimer; + ICMPResponderP.Solicitation -> STimer; + ICMPResponderP.Advertisement -> ATimer; + ICMPResponderP.PingTimer -> PTimer; + + components HilTimerMilliC; + ICMPResponderP.LocalTime -> HilTimerMilliC; +} diff --git a/tos/lib/net/blip/ICMPResponderP.nc b/tos/lib/net/blip/ICMPResponderP.nc new file mode 100644 index 00000000..102d077b --- /dev/null +++ b/tos/lib/net/blip/ICMPResponderP.nc @@ -0,0 +1,417 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include +#include <6lowpan.h> +#include +#include "in_cksum.h" +#include "PrintfUART.h" +#include "ICMP.h" + +extern uint8_t multicast_prefix[8]; + +module ICMPResponderP { + provides interface ICMP; + provides interface ICMPPing[uint16_t client]; + provides interface Statistics; + + uses interface IP; + uses interface IPAddress; + + uses interface Leds; + + uses interface Timer as Solicitation; + uses interface Timer as Advertisement; + uses interface Timer as PingTimer; + uses interface LocalTime; + uses interface Random; + + uses interface IPRouting; + +} implementation { + + icmp_statistics_t stats; + uint32_t solicitation_period; + uint32_t advertisement_period; + + uint16_t ping_seq, ping_n, ping_rcv, ping_ident; + struct in6_addr ping_dest; + +#ifndef SIM +#define CHECK_NODE_ID +#else +#define CHECK_NODE_ID if (TOS_NODE_ID == BASESTATION_ID) return +#endif + + command uint16_t ICMP.cksum(struct split_ip_msg *msg, uint8_t nxt_hdr) { + return msg_cksum(msg, nxt_hdr); + } + + + command void ICMP.sendSolicitations() { + uint16_t jitter = (call Random.rand16()) % TRICKLE_JITTER; + CHECK_NODE_ID; + if (call Solicitation.isRunning()) return; + solicitation_period = TRICKLE_PERIOD; + call Solicitation.startOneShot(jitter); + } + + command void ICMP.sendAdvertisements() { + uint16_t jitter = (call Random.rand16()) % TRICKLE_JITTER; + CHECK_NODE_ID; + if (call Advertisement.isRunning()) return; + advertisement_period = TRICKLE_PERIOD; + call Advertisement.startOneShot(jitter); + } + + command void ICMP.sendTimeExceeded(struct ip6_hdr *hdr, unpack_info_t *u_info, uint16_t amount_here) { + uint8_t i_hdr_buf[sizeof(struct icmp6_hdr) + 4]; + struct split_ip_msg *msg = (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg)); + struct generic_header g_hdr[3]; + struct icmp6_hdr *i_hdr = (struct icmp6_hdr *)i_hdr_buf; + + if (msg == NULL) return; + + dbg("ICMPResponder", "send time exceeded\n"); + + msg->headers = NULL; + msg->data = u_info->payload_start; + msg->data_len = amount_here; + + // make sure to include the udp header if necessary + if (u_info->nxt_hdr == IANA_UDP) { + g_hdr[2].hdr.udp = (struct udp_hdr *)u_info->transport_ptr; + g_hdr[2].len = sizeof(struct udp_hdr); + g_hdr[2].next = NULL; + + // since the udp headers are included in the offset we need to + // add that length so the payload length in the encapsulated + // packet will be correct. + hdr->plen = htons(ntohs(hdr->plen) + sizeof(struct udp_hdr)); + msg->headers = &g_hdr[2]; + } + // the fields in the packed packet is not necessarily the same as + // the fields in canonical packet which was packed. This is due + // to the insertion of transient routing headers. + hdr->nxt_hdr = u_info->nxt_hdr; + hdr->plen = htons(ntohs(hdr->plen) - u_info->payload_offset); + + // the IP header is part of the payload + g_hdr[1].hdr.data = (void *)hdr; + g_hdr[1].len = sizeof(struct ip6_hdr); + g_hdr[1].next = msg->headers; + msg->headers = &g_hdr[1]; + + // and is preceeded by the icmp time exceeded message + g_hdr[0].hdr.data = (void *)i_hdr; + g_hdr[0].len = sizeof(struct icmp6_hdr) + 4; + g_hdr[0].next = msg->headers; + msg->headers = &g_hdr[0]; + + ip_memcpy(&msg->hdr.ip6_dst, &hdr->ip6_src, 16); + call IPAddress.getIPAddr(&msg->hdr.ip6_src); + + i_hdr->type = ICMP_TYPE_ECHO_TIME_EXCEEDED; + i_hdr->code = ICMP_CODE_HOPLIMIT_EXCEEDED; + i_hdr->cksum = 0; + ip_memclr((void *)(i_hdr + 1), 4); + + msg->hdr.nxt_hdr = IANA_ICMP; + + i_hdr->cksum = call ICMP.cksum(msg, IANA_ICMP); + + call IP.send(msg); + + ip_free(msg); + } + /* + * Solicitations + */ + void sendSolicitation() { + struct split_ip_msg *ipmsg = (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg) + sizeof(rsol_t)); + rsol_t *msg = (rsol_t *)(ipmsg + 1); + + if (ipmsg == NULL) return; + + dbg("ICMPResponder", "Solicitation\n"); + //stats.sol_tx++; + + msg->type = ICMP_TYPE_ROUTER_SOL; + msg->code = 0; + msg->cksum = 0; + msg->reserved = 0; + + ipmsg->headers = NULL; + ipmsg->data = (void *)msg; + ipmsg->data_len = sizeof(rsol_t); + + // this is required for solicitation messages + ipmsg->hdr.hlim = 0xff; + + + call IPAddress.getLLAddr(&ipmsg->hdr.ip6_src); + inet_pton6("ff02::2", &ipmsg->hdr.ip6_dst); + + msg->cksum = call ICMP.cksum(ipmsg, IANA_ICMP); + + call IP.send(ipmsg); + + ip_free(ipmsg); + } + + void sendPing(struct in6_addr *dest, uint16_t seqno) { + struct split_ip_msg *ipmsg = (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg) + + sizeof(icmp_echo_hdr_t) + + sizeof(nx_uint32_t)); + icmp_echo_hdr_t *e_hdr = (icmp_echo_hdr_t *)ipmsg->next; + nx_uint32_t *sendTime = (nx_uint32_t *)(e_hdr + 1); + + if (ipmsg == NULL) return; + ipmsg->headers = NULL; + ipmsg->data = (void *)e_hdr; + ipmsg->data_len = sizeof(icmp_echo_hdr_t) + sizeof(nx_uint32_t); + + e_hdr->type = ICMP_TYPE_ECHO_REQUEST; + e_hdr->code = 0; + e_hdr->cksum = 0; + e_hdr->ident = ping_ident; + e_hdr->seqno = seqno; + *sendTime = call LocalTime.get(); + + memcpy(&ipmsg->hdr.ip6_dst, dest->s6_addr, 16); + call IPAddress.getIPAddr(&ipmsg->hdr.ip6_src); + + e_hdr->cksum = call ICMP.cksum(ipmsg,IANA_ICMP); + + call IP.send(ipmsg); + ip_free(ipmsg); + } + + /* + * Router advertisements + */ + void handleRouterAdv(void *payload, uint16_t len, struct ip_metadata *meta) { + + radv_t *r = (radv_t *)payload; + pfx_t *pfx = (pfx_t *)(r->options); + uint16_t cost = 0; + rqual_t *beacon = (rqual_t *)(pfx + 1); + + if (len > sizeof(radv_t) + sizeof(pfx_t) && + beacon->type == ICMP_EXT_TYPE_BEACON) { + cost = beacon->metric; + dbg("ICMPResponder", " * beacon cost: 0x%x\n", cost); + } else + dbg("ICMPResponder", " * no beacon cost\n"); + + call IPRouting.reportAdvertisement(meta->sender, r->hlim, + meta->lqi, cost); + + if (pfx->type != ICMP_EXT_TYPE_PREFIX) return; + + call IPAddress.setPrefix((uint8_t *)pfx->prefix); + + // TODO : get short address here... + } + + void sendAdvertisement() { + struct split_ip_msg *ipmsg = (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg) + + sizeof(radv_t) + + sizeof(pfx_t) + + sizeof(rqual_t)); + uint16_t len = sizeof(radv_t); + radv_t *r = (radv_t *)(ipmsg + 1); + pfx_t *p = (pfx_t *)r->options; + rqual_t *q = (rqual_t *)(p + 1); + + if (ipmsg == NULL) return; + // don't sent the advertisement if we don't have a valid route + if (!call IPRouting.hasRoute()) { + ip_free(ipmsg); + return; + } + + r->type = ICMP_TYPE_ROUTER_ADV; + r->code = 0; + r->hlim = call IPRouting.getHopLimit(); + r->flags = 0; + r->lifetime = 1; + r->reachable_time = 0; + r->retrans_time = 0; + + ipmsg->hdr.hlim = 0xff; + + if (globalPrefix) { + len += sizeof(pfx_t); + p->type = ICMP_EXT_TYPE_PREFIX; + p->length = 8; + memcpy(p->prefix, call IPAddress.getPublicAddr(), 8); + } + + len += sizeof(rqual_t); + q->type = ICMP_EXT_TYPE_BEACON; + q->length = 2; + q->metric = call IPRouting.getQuality(); + + call IPAddress.getLLAddr(&ipmsg->hdr.ip6_src); + inet_pton6("ff02::1", &ipmsg->hdr.ip6_dst); + + //dbg("ICMPResponder", "My Address: [0x%x] [0x%x] [0x%x] [0x%x]\n", ipmsg->hdr.src_addr[12], ipmsg->hdr.src_addr[13], ipmsg->hdr.src_addr[14], ipmsg->hdr.src_addr[15]); + dbg("ICMPResponder", "adv hop limit: 0x%x\n", r->hlim); + + if (r->hlim >= 0xf0) { + ip_free(ipmsg); + return; + } + + ipmsg->data = (void *)r; + ipmsg->data_len = len; + ipmsg->headers = NULL; + + r->cksum = 0; + r->cksum = call ICMP.cksum(ipmsg, IANA_ICMP); + + call IP.send(ipmsg); + ip_free(ipmsg); + } + + + event void IP.recv(struct ip6_hdr *iph, + void *payload, + struct ip_metadata *meta) { + icmp_echo_hdr_t *req = (icmp_echo_hdr_t *)payload; + uint16_t len = ntohs(iph->plen); + stats.rx++; + + // for checksum calculation + printfUART ("icmp type: 0x%x code: 0x%x cksum: 0x%x ident: 0x%x seqno: 0x%x len: 0x%x\n", + req->type, req->code, req->cksum, req->ident, req->seqno, len); + + switch (req->type) { + case ICMP_TYPE_ROUTER_ADV: + handleRouterAdv(payload, len, meta); + //stats.adv_rx++; + break; + case ICMP_TYPE_ROUTER_SOL: + // only reply to solicitations if we have established a default route. + if (call IPRouting.hasRoute()) { + call ICMP.sendAdvertisements(); + } + break; + case ICMP_TYPE_ECHO_REPLY: + { + nx_uint32_t *sendTime = (nx_uint32_t *)(req + 1); + struct icmp_stats p_stat; + p_stat.seq = req->seqno; + p_stat.ttl = 0;// buf->hdr.hlim; + p_stat.rtt = (call LocalTime.get()) - (*sendTime); + signal ICMPPing.pingReply[req->ident](&iph->ip6_src, &p_stat); + ping_rcv++; + } + break; + case ICMP_TYPE_ECHO_REQUEST: + { + // send a ping reply. + struct split_ip_msg msg; + msg.headers = NULL; + msg.data = payload; + msg.data_len = len; + call IPAddress.getIPAddr(&msg.hdr.ip6_src); + memcpy(&msg.hdr.ip6_dst, &iph->ip6_src, 16); + + req->type = ICMP_TYPE_ECHO_REPLY; + req->code = 0; + req->cksum = 0; + req->cksum = call ICMP.cksum(&msg, IANA_ICMP); + + // remember, this can't really fail in a way we care about + call IP.send(&msg); + break; + } + } + } + + + event void Solicitation.fired() { + sendSolicitation(); + dbg("ICMPResponder", "solicitation period: 0x%x max: 0x%x\n", solicitation_period, TRICKLE_MAX); + solicitation_period <<= 1; + if (solicitation_period < TRICKLE_MAX) { + call Solicitation.startOneShot(solicitation_period); + } else { + signal ICMP.solicitationDone(); + } + } + + event void Advertisement.fired() { + dbg("ICMPResponder", "==> Sending router advertisement\n"); + sendAdvertisement(); + advertisement_period <<= 1; + if (advertisement_period < TRICKLE_MAX) { + call Advertisement.startOneShot(advertisement_period); + } + } + + + + command error_t ICMPPing.ping[uint16_t client](struct in6_addr *target, uint16_t period, uint16_t n) { + if (call PingTimer.isRunning()) return ERETRY; + call PingTimer.startPeriodic(period); + + memcpy(&ping_dest, target, 16); + ping_n = n; + ping_seq = 0; + ping_rcv = 0; + ping_ident = client; + return SUCCESS; + } + + event void PingTimer.fired() { + // send a ping request + if (ping_seq == ping_n) { + signal ICMPPing.pingDone[ping_ident](ping_rcv, ping_n); + call PingTimer.stop(); + return; + } + sendPing(&ping_dest, ping_seq); + ping_seq++; + } + + + + command void Statistics.get(icmp_statistics_t *statistics) { + statistics = &stats; + } + + command void Statistics.clear() { + ip_memclr((uint8_t *)&stats, sizeof(icmp_statistics_t)); + } + + default event void ICMPPing.pingReply[uint16_t client](struct in6_addr *source, + struct icmp_stats *ping_stats) { + } + + default event void ICMPPing.pingDone[uint16_t client](uint16_t n, uint16_t m) { + + } + +} diff --git a/tos/lib/net/blip/IPAddressC.nc b/tos/lib/net/blip/IPAddressC.nc new file mode 100644 index 00000000..c096468f --- /dev/null +++ b/tos/lib/net/blip/IPAddressC.nc @@ -0,0 +1,37 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + + +configuration IPAddressC { + provides interface IPAddress; + +} implementation { + components IPAddressP, ActiveMessageAddressC; + + IPAddress = IPAddressP; + +#ifndef SIM + IPAddressP.ActiveMessageAddress -> ActiveMessageAddressC; +#else + IPAddressP.setAmAddress -> ActiveMessageAddressC; +#endif +} diff --git a/tos/lib/net/blip/IPAddressP.nc b/tos/lib/net/blip/IPAddressP.nc new file mode 100644 index 00000000..b8af3520 --- /dev/null +++ b/tos/lib/net/blip/IPAddressP.nc @@ -0,0 +1,84 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include <6lowpan.h> + +// defined in lib6lowpan +extern struct in6_addr __my_address; +extern uint8_t globalPrefix; + +module IPAddressP { + provides interface IPAddress; + +#ifndef SIM + uses interface ActiveMessageAddress; +#else + uses async command void setAmAddress(am_addr_t a); +#endif +} implementation { + + + command hw_addr_t IPAddress.getShortAddr() { + return TOS_NODE_ID; + } + + command void IPAddress.setShortAddr(hw_addr_t newAddr) { + TOS_NODE_ID = newAddr; +#ifndef SIM + call ActiveMessageAddress.setAddress(call ActiveMessageAddress.amGroup(), newAddr); +#else + call setAmAddress(newAddr); +#endif + } + + command void IPAddress.getLLAddr(struct in6_addr *addr) { + memcpy(addr->s6_addr, linklocal_prefix, 8); + memcpy(&addr->s6_addr[8], &__my_address.s6_addr[8], 8); + } + + command void IPAddress.getIPAddr(struct in6_addr *addr) { + __my_address.s6_addr16[7] = htons(TOS_NODE_ID); + memcpy(addr, &__my_address, 16); + } + + command struct in6_addr *IPAddress.getPublicAddr() { + __my_address.s6_addr16[7] = htons(TOS_NODE_ID); + return &__my_address; + } + + command void IPAddress.setPrefix(uint8_t *pfx) { + ip_memclr(__my_address.s6_addr, sizeof(struct in6_addr)); + ip_memcpy(__my_address.s6_addr, pfx, 8); + globalPrefix = 1; + } + + command bool IPAddress.haveAddress() { + return globalPrefix; + } + +#ifndef SIM + async event void ActiveMessageAddress.changed() { + + } +#endif + +} diff --git a/tos/lib/net/blip/IPDispatch.h b/tos/lib/net/blip/IPDispatch.h new file mode 100644 index 00000000..ffb2641b --- /dev/null +++ b/tos/lib/net/blip/IPDispatch.h @@ -0,0 +1,272 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _IPDISPATCH_H_ +#define _IPDISPATCH_H_ + +#include +#include + +enum { + N_PARENTS = 3, + N_EPOCHS = 2, + N_EPOCHS_COUNTED = 1, + N_RECONSTRUCTIONS = 2, + N_FORWARD_ENT = IP_NUMBER_FRAGMENTS, +}; + +enum { + CONF_EVICT_THRESHOLD = 5, // Neighbor is 'mature' + CONF_PROM_THRESHOLD = 5, // Acceptable threshold for promotion + MAX_CONSEC_FAILURES = 40, // Max Failures before reroute is attempted + PATH_COST_DIFF_THRESH = 10, // Threshold for 'similar' path costs + LQI_DIFF_THRESH = 10, // Threshold for 'similar' LQI's + LINK_EVICT_THRESH = 50, // ETX * 10 + LQI_ADMIT_THRESH = 0x200, + RSSI_ADMIT_THRESH = 0, + RANDOM_ROUTE = 20, //Percentage of time to select random default route +}; + +enum { + WITHIN_THRESH = 1, + ABOVE_THRESH = 2, + BELOW_THRESH = 3, +}; + +enum { + TGEN_BASE_TIME = 512, + TGEN_MAX_INTERVAL = 60L * 1024L * 5L, +}; + +struct epoch_stats { + uint16_t success; + uint16_t total; + uint16_t receptions; +}; + +struct report_stats { + uint8_t messages; + uint8_t transmissions; + uint8_t successes; +}; + +enum { + T_PIN_OFFSET = 0, + T_PIN_MASK = 1 << T_PIN_OFFSET, + T_VALID_OFFSET = 2, + T_VALID_MASK = 1 << T_VALID_OFFSET, + T_MARKED_OFFSET = 3, + T_MARKED_MASK = 1 << T_MARKED_OFFSET, + T_MATURE_OFFSET = 4, + T_MATURE_MASK = 1 << T_MATURE_OFFSET, + T_EVICT_OFFSET = 5, + T_EVICT_MASK = 1 << T_EVICT_OFFSET, +}; + +enum { + // store the top-k neighbors. This could be a poor topology + // formation critera is very dense networks. we may be able to + // really use the fact that the "base" has infinite memory. + N_NEIGH = 8, + N_LOW_NEIGH = 2, + N_FREE_NEIGH = (N_NEIGH - N_LOW_NEIGH), + N_FLOW_ENT = 6, + N_FLOW_CHOICES = 2, + N_PARENT_CHOICES = 3, + T_DEF_PARENT = 0xfffd, + T_DEF_PARENT_SLOT = 0, +}; + +typedef struct { + // The extra 2 is because one dest could be from source route, other + // from the dest being a direct neighbor + hw_addr_t dest[N_FLOW_CHOICES + N_PARENT_CHOICES + 2]; + uint8_t current:4; + uint8_t nchoices:4; + uint8_t retries; + uint8_t actRetries; + uint8_t delay; +} send_policy_t; + +typedef struct { + send_policy_t policy; + uint8_t frags_sent; + bool failed; + uint8_t refcount; +} send_info_t; + +typedef struct { + send_info_t *info; + message_t *msg; +} send_entry_t; + +typedef struct { + uint8_t timeout; + hw_addr_t l2_src; + uint16_t old_tag; + uint16_t new_tag; + send_info_t *s_info; +} forward_entry_t; + +/* typedef struct { */ +/* /\* how to dispatch this packet *\/ */ +/* union { */ +/* struct sockaddr_in6 sock; */ +/* ip6_addr_t src; */ +/* } address; */ +/* /\* packet metadata *\/ */ +/* union { */ +/* uint16_t udp_port; */ +/* } dispatch; */ +/* struct ip_metadata metadata; */ + +/* /\* the lib6lowpan reconstruct structure *\/ */ +/* reconstruct_t recon; */ +/* } ip_recon_t; */ + +enum { + F_VALID_MASK = 0x01, + //F_TOTAL_VALID_ENTRY_MASK = 0x80, // For entire entry (not just specific choice) + F_FULL_PATH_OFFSET = 1, + F_FULL_PATH_MASK = 0x02, + + MAX_PATH_LENGTH = 10, + N_FULL_PATH_ENTRIES = (N_FLOW_CHOICES * N_FLOW_ENT), +}; + +struct flow_path { + uint8_t path_len; + cmpr_ip6_addr_t path[MAX_PATH_LENGTH]; +}; + +struct f_entry { + uint8_t flags; + union { + struct flow_path *pathE; + cmpr_ip6_addr_t nextHop; + }; +}; + +// Need to add another entry to avoid useless padding +// Or can make sure that the flow_table has an even +// number of entries. +struct flow_entry { + uint8_t flags; + uint8_t count; + struct flow_match match; + struct f_entry entries[N_FLOW_CHOICES]; +}; + +//#define IS_VALID_SLOT(f) (((f)->entries[0].flags & F_TOTAL_VALID_ENTRY_MASK) == F_TOTAL_VALID_ENTRY_MASK) +#define IS_VALID_SLOT(f) (((f)->flags & F_VALID_MASK) == F_VALID_MASK) +//#define SET_VALID_SLOT(f) (f)->entries[0].flags |= F_TOTAL_VALID_ENTRY_MASK +#define SET_VALID_SLOT(f) (f)->flags |= F_VALID_MASK +//#define SET_INVALID_SLOT(f) (f)->entries[0].flags &= ~F_TOTAL_VALID_ENTRY_MASK +#define SET_INVALID_SLOT(f) (f)->flags &= ~F_VALID_MASK +#define IS_VALID_ENTRY(e) (((e).flags & F_VALID_MASK) == F_VALID_MASK) +#define SET_VALID_ENTRY(e) (e).flags |= F_VALID_MASK +#define SET_INVALID_ENTRY(e) (e).flags &= ~F_VALID_MASK +#define IS_FULL_TYPE(e) (((e).flags & F_FULL_PATH_MASK) == F_FULL_PATH_MASK) +#define IS_HOP_TYPE(e) !IS_FULL_TYPE(e) +#define SET_FULL_TYPE(e) ((e).flags |= F_FULL_PATH_MASK) +#define SET_HOP_TYPE(e) ((e).flags &= ~F_FULL_PATH_MASK) + + +struct neigh_entry { + uint8_t flags; + uint8_t hops; // Put this before neighbor to remove potential padding issues + hw_addr_t neighbor; + uint16_t costEstimate; + uint16_t linkEstimate; + struct epoch_stats stats[N_EPOCHS]; +} +#ifdef MIG + __attribute__((packed)); +#else +; +#endif + +#define IS_NEIGH_VALID(e) (((e)->flags & T_VALID_MASK) == T_VALID_MASK) +#define SET_NEIGH_VALID(e) ((e)->flags |= T_VALID_MASK) +#define SET_NEIGH_INVALID(e) ((e)->flags &= ~T_VALID_MASK) +#define PINNED(e) (((e)->flags & T_PIN_MASK) == T_PIN_MASK) +#define REMOVABLE(e) (((e)->refCount == 0) && !(PINNED(e))) +#define SET_PIN(e) (((e)->flags |= T_PIN_MASK)) +#define UNSET_PIN(e) (((e)->flags &= ~T_PIN_MASK)) +#define IS_MARKED(e) (((e)->flags & T_MARKED_MASK) == T_MARKED_MASK) +#define SET_MARK(e) (((e)->flags |= T_MARKED_MASK)) +#define UNSET_MARK(e) (((e)->flags &= ~T_MARKED_MASK)) +#define IS_MATURE(e) (((e)->flags & T_MATURE_MASK) == T_MATURE_MASK) +#define SET_MATURE(e) ((e)->flags |= T_MATURE_MASK) +#define SET_EVICT(e) ((e).flags |= T_EVICT_MASK) +#define UNSET_EVICT(e) ((e).flags &= ~T_EVICT_MASK) +#define SHOULD_EVICT(e) ((e).flags & T_EVICT_MASK) + + +typedef enum { + S_FORWARD, + S_REQ, +} send_type_t; + + +typedef nx_struct { + nx_uint16_t sent; + nx_uint16_t forwarded; + nx_uint8_t rx_drop; + nx_uint8_t tx_drop; + nx_uint8_t fw_drop; + nx_uint8_t rx_total; + nx_uint8_t real_drop; + nx_uint8_t hlim_drop; + nx_uint8_t senddone_el; + nx_uint8_t fragpool; + nx_uint8_t sendinfo; + nx_uint8_t sendentry; + nx_uint8_t sndqueue; + nx_uint8_t encfail; + nx_uint16_t heapfree; +} ip_statistics_t; + + +typedef nx_struct { + nx_uint8_t hop_limit; + nx_uint16_t parent; + nx_uint16_t parent_metric; + nx_uint16_t parent_etx; +} route_statistics_t; + +typedef nx_struct { +/* nx_uint8_t sol_rx; */ +/* nx_uint8_t sol_tx; */ +/* nx_uint8_t adv_rx; */ +/* nx_uint8_t adv_tx; */ +/* nx_uint8_t unk_rx; */ + nx_uint16_t rx; +} icmp_statistics_t; + +typedef nx_struct { + nx_uint16_t total; + nx_uint16_t failed; + nx_uint16_t seqno; + nx_uint16_t sender; +} udp_statistics_t; + +#endif diff --git a/tos/lib/net/blip/IPDispatchC.nc b/tos/lib/net/blip/IPDispatchC.nc new file mode 100644 index 00000000..e74d70d2 --- /dev/null +++ b/tos/lib/net/blip/IPDispatchC.nc @@ -0,0 +1,123 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +/* + * Provides message dispatch based on the next header field of IP packets. + * + */ +#include "IPDispatch.h" + +configuration IPDispatchC { + provides { + interface SplitControl; + interface IPAddress; + interface IP[uint8_t nxt_hdr]; + + interface Statistics as IPStats; + interface Statistics as RouteStats; + interface Statistics as ICMPStats; + + } +} implementation { + +#ifndef SIM + components CC2420ActiveMessageC as MessageC; +#else + components ActiveMessageC as MessageC; +#endif + components MainC, IPDispatchP, IPAddressC, IPRoutingP; + components NoLedsC as LedsC; + components RandomC; + + SplitControl = IPDispatchP.SplitControl; + IPAddress = IPAddressC; + IP = IPDispatchP; + + IPDispatchP.Boot -> MainC; + +#ifndef SIM + IPDispatchP.IEEE154Send -> MessageC; + IPDispatchP.IEEE154Receive -> MessageC; +#else + IPDispatchP.IEEE154Send -> MessageC.AMSend[0]; + IPDispatchP.IEEE154Receive -> MessageC.Receive[0]; +#endif + IPDispatchP.Packet -> MessageC.SubAMPacket; +#ifdef LOW_POWER_LISTENING + IPDispatchP.LowPowerListening -> MessageC; +#endif + + + IPDispatchP.IEEE154Packet -> MessageC; + IPDispatchP.PacketLink -> MessageC; + IPDispatchP.CC2420Packet -> MessageC; + +#ifdef DBG_TRACK_FLOWS + IPDispatchP.getFlowID -> MessageC; +#endif + + + IPDispatchP.Leds -> LedsC; + + IPDispatchP.IPAddress -> IPAddressC; + + components new TimerMilliC(); + IPDispatchP.ExpireTimer -> TimerMilliC; + + components new PoolC(message_t, IP_NUMBER_FRAGMENTS) as FragPool; + + components new PoolC(send_entry_t, IP_NUMBER_FRAGMENTS) as SendEntryPool; + components new QueueC(send_entry_t *, IP_NUMBER_FRAGMENTS); + + components new PoolC(send_info_t, N_FORWARD_ENT) as SendInfoPool; + + IPDispatchP.FragPool -> FragPool; + IPDispatchP.SendEntryPool -> SendEntryPool; + IPDispatchP.SendInfoPool -> SendInfoPool; + IPDispatchP.SendQueue -> QueueC; + + components ICMPResponderC; + components new TimerMilliC() as TGenTimer; + IPDispatchP.ICMP -> ICMPResponderC; + IPRoutingP.ICMP -> ICMPResponderC; + IPDispatchP.RadioControl -> MessageC; + + IPDispatchP.IPRouting -> IPRoutingP; + IPRoutingP.Boot -> MainC; + IPRoutingP.Leds -> LedsC; + IPRoutingP.IPAddress -> IPAddressC; + IPRoutingP.Random -> RandomC; + IPRoutingP.TrafficGenTimer -> TGenTimer; + IPRoutingP.TGenSend -> IPDispatchP.IP[NXTHDR_UNKNOWN]; + + IPStats = IPDispatchP; + RouteStats = IPRoutingP; + ICMPStats = ICMPResponderC; + + components new TimerMilliC() as RouteTimer; + IPRoutingP.SortTimer -> RouteTimer; + +#ifdef DELUGE + components NWProgC; +#endif + +} diff --git a/tos/lib/net/blip/IPDispatchP.nc b/tos/lib/net/blip/IPDispatchP.nc new file mode 100644 index 00000000..214b7cd5 --- /dev/null +++ b/tos/lib/net/blip/IPDispatchP.nc @@ -0,0 +1,1013 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +/* + * This file has the potential to be rather confusing, here are a few + * notes about what is happening. There are several state machines in + * this file. Together, they take care of packet forwarding and + * sending (which is accomplished by injecting new packets into the + * outgoing queue.) + * + * Messages enter from two places: either from the bottom (from the + * radio), or from the top (from the application). Messages also + * leave from two places: either out over the radio, or up to an + * application. + * + * + * IP.send ---- - ---> IP.recvfrom + * \ / + * X + * / \ + * IEEE154.receive ---- - ---> IEEE154.send + * + * + * All of the queueing is done on the output; when each message + * arrives, it is dispatched all the way to an output queue. + * + * There are four paths through the system, so here they are: + * + * IP.send -> IP.recvfrom : local delivery: not implemented + * IP.send -> IEEE154.send : enqueue fragments on radio queue + * IEEE154.receive -> IP.recv : deliver to this mote : reassemble and deliver + * IEEE154.receive -> IEEE154.send : forwarding : enqueue fragments + * + * the IP receive queue + * data structures: + * recon_cache: holds state about packets which are to be consumed + * by this mote, and have fragments pending. + * + * radio send queue + * data structures: + * send_info_t: packet metadata for a single packet flow through + * the mote (could either come from a forwarded stream + * or a local send. + * send_entry_t: the actual queue items, pointing to a fragment + * and the packet metadata (send_info_t) + * + * extra forwarding structures: + * forward_cache: used to match up incoming fragments with their flow metadata, + * stored in a send_info_t. + * fragment pool: + */ +#include <6lowpan.h> +#include +#include +#include +#include +#include "IPDispatch.h" +#include "table.h" +#include "PrintfUART.h" +#ifdef PRINTF_LIBRARY +#include "printf.h" +#endif + +/* + * Provides IP layer reception to applications on motes. + * + * @author Stephen Dawson-Haggerty + */ + +module IPDispatchP { + provides { + interface SplitControl; + // interface for protocols not requiring special hand-holding + interface IP[uint8_t nxt_hdr]; + interface Statistics; + } + uses { + interface Boot; + interface SplitControl as RadioControl; + + interface CC2420Packet; + interface Packet; + +#ifndef SIM + interface IEEE154Send; + interface IEEE154Packet; +#else + interface AMSend as IEEE154Send; + interface AMPacket as IEEE154Packet; +#endif + interface Receive as IEEE154Receive; + + interface PacketLink; + + // outgoing fragments + interface Pool as FragPool; + interface Pool as SendInfoPool; + interface Pool as SendEntryPool; + interface Queue as SendQueue; + + interface Timer as ExpireTimer; + + interface IPRouting; + interface ICMP; + + interface LowPowerListening; + + interface Leds; + + interface IPAddress; + +#ifdef DBG_TRACK_FLOWS + command flow_id_t *getFlowID(message_t *); +#endif + + } +} implementation { + + enum { + S_RUNNING, + S_STOPPED, + S_STOPPING, + }; + uint8_t state = S_STOPPED; + bool radioBusy; + ip_statistics_t stats; + + // this in theory could be arbitrarily large; however, it needs to + // be large enough to hold all active reconstructions, and any tags + // which we are dropping. It's important to keep dropped tags + // around for a while, or else there are pathological situations + // where you continually allocate buffers for packets which will + // never complete. + + //////////////////////////////////////// + // + // + + table_t recon_cache, forward_cache; + + + // table of packets we are currently receiving fragments from, that + // are destined to us + reconstruct_t recon_data[N_RECONSTRUCTIONS]; + + // table of fragmented flows who are going through us, so we must + // remember the next hop. + forward_entry_t forward_data[N_FORWARD_ENT]; + + // + // + //////////////////////////////////////// + +#ifdef DBG_TRACK_FLOWS + uint16_t dbg_flowid = 0; +#endif + +#ifndef SIM +#define CHECK_NODE_ID if (0) return +#else +#define CHECK_NODE_ID if (TOS_NODE_ID == BASESTATION_ID) return +#endif + + task void sendTask(); + + void reconstruct_clear(void *ent) { + reconstruct_t *recon = (reconstruct_t *)ent; + ip_memclr((uint8_t *)&recon->metadata, sizeof(struct ip_metadata)); + recon->timeout = T_UNUSED; + recon->buf = NULL; + } + + void forward_clear(void *ent) { + forward_entry_t *fwd = (forward_entry_t *)ent; + fwd->timeout = T_UNUSED; + } + + int forward_unused(void *ent) { + forward_entry_t *fwd = (forward_entry_t *)ent; + if (fwd->timeout == T_UNUSED) + return 1; + return 0; + } + + uint16_t forward_lookup_tag; + uint16_t forward_lookup_src; + int forward_lookup(void *ent) { + forward_entry_t *fwd = (forward_entry_t *)ent; + if (fwd->timeout > T_UNUSED && + fwd->l2_src == forward_lookup_src && + fwd->old_tag == forward_lookup_tag) { + fwd->timeout = T_ACTIVE; + return 1; + } + return 0; + } + + + send_info_t *getSendInfo() { + send_info_t *ret = call SendInfoPool.get(); + if (ret == NULL) return ret; + ret->refcount = 1; + ret->failed = FALSE; + ret->frags_sent = 0; + return ret; + } +#define SENDINFO_INCR(X) ((X)->refcount)++ +#define SENDINFO_DECR(X) if (--((X)->refcount) == 0) call SendInfoPool.put(X) + + command error_t SplitControl.start() { + CHECK_NODE_ID FAIL; + return call RadioControl.start(); + } + + command error_t SplitControl.stop() { + if (!radioBusy) { + state = S_STOPPED; + return call RadioControl.stop(); + } else { + // if there's a packet in the radio, wait for it to exit before + // stopping + state = S_STOPPING; + return SUCCESS; + } + } + + event void RadioControl.startDone(error_t error) { +#ifdef LPL_SLEEP_INTERVAL + call LowPowerListening.setLocalSleepInterval(LPL_SLEEP_INTERVAL); +#endif + if (error == SUCCESS) { + call ICMP.sendSolicitations(); + state = S_RUNNING; + } + signal SplitControl.startDone(error); + } + + event void RadioControl.stopDone(error_t error) { + signal SplitControl.stopDone(error); + } + + event void Boot.booted() { + CHECK_NODE_ID; + call Statistics.clear(); + + ip_malloc_init(); + + table_init(&recon_cache, recon_data, sizeof(reconstruct_t), N_RECONSTRUCTIONS); + table_init(&forward_cache, forward_data, sizeof(forward_entry_t), N_FORWARD_ENT); + + table_map(&recon_cache, reconstruct_clear); + table_map(&forward_cache, forward_clear); + + radioBusy = FALSE; + + call ExpireTimer.startPeriodic(FRAG_EXPIRE_TIME); + + call SplitControl.start(); + return; + } + + /* + * Receive-side code. + */ + + /* + * Logic which must process every received IP datagram. + * + * Each IP packet may be consumed and/or forwarded. + */ + void signalDone(reconstruct_t *recon) { + struct ip6_hdr *iph = (struct ip6_hdr *)recon->buf; + signal IP.recv[iph->nxt_hdr](iph, recon->transport_hdr, &recon->metadata); + ip_free(recon->buf); + recon->timeout = T_UNUSED; + recon->buf = NULL; + } + + /* + * Bulletproof recovery logic is very important to make sure we + * don't get wedged with no free buffers. + * + * The table is managed as follows: + * - unused entries are marked T_UNUSED + * - entries which + * o have a buffer allocated + * o have had a fragment reception before we fired + * are marked T_ACTIVE + * - entries which have not had a fragment reception during the last timer period + * and were active are marked T_ZOMBIE + * - zombie receptions are deleted: their buffer is freed and table entry marked unused. + * - when a fragment is dropped, it is entered into the table as T_FAILED1. + * no buffer is allocated + * - when the timer fires, T_FAILED1 entries are aged to T_FAILED2. + * - T_FAILED2 entries are deleted. Incomming fragments with tags + * that are marked either FAILED1 or FAILED2 are dropped; this + * prevents us from allocating a buffer for a packet which we + * have already dropped fragments from. + * + */ + void reconstruct_age(void *elt) { + reconstruct_t *recon = (reconstruct_t *)elt; + switch (recon->timeout) { + case T_ACTIVE: + recon->timeout = T_ZOMBIE; break; // age existing receptions + case T_FAILED1: + recon->timeout = T_FAILED2; break; // age existing receptions + case T_ZOMBIE: + case T_FAILED2: + // deallocate the space for reconstruction + if (recon->buf != NULL) { + ip_free(recon->buf); + } + recon->timeout = T_UNUSED; + recon->buf = NULL; + break; + } + } + + void forward_age(void *elt) { + forward_entry_t *fwd = (forward_entry_t *)elt; + switch (fwd->timeout) { + case T_ACTIVE: + fwd->timeout = T_ZOMBIE; break; // age existing receptions + case T_FAILED1: + fwd->timeout = T_FAILED2; break; // age existing receptions + case T_ZOMBIE: + case T_FAILED2: + fwd->s_info->failed = TRUE; + SENDINFO_DECR(fwd->s_info); + fwd->timeout = T_UNUSED; + break; + } + } + + void ip_print_heap() { +#ifdef PRINTFUART_ENABLED + bndrt_t *cur = (bndrt_t *)heap; + while (((uint8_t *)cur) - heap < IP_MALLOC_HEAP_SIZE) { + //printfUART ("heap region start: 0x%x length: %i used: %i\n", + //cur, (*cur & IP_MALLOC_LEN), (*cur & IP_MALLOC_INUSE) >> 15); + cur = (bndrt_t *)(((uint8_t *)cur) + ((*cur) & IP_MALLOC_LEN)); + } +#endif + } + + event void ExpireTimer.fired() { + CHECK_NODE_ID; + table_map(&recon_cache, reconstruct_age); + table_map(&forward_cache, forward_age); + + /* + printfUART("Frag pool size: %i\n", call FragPool.size()); + printfUART("SendInfo pool size: %i\n", call SendInfoPool.size()); + printfUART("SendEntry pool size: %i\n", call SendEntryPool.size()); + printfUART("Forward queue length: %i\n", call SendQueue.size()); + */ + ip_print_heap(); + } + + /* + * allocate a structure for recording information about incomming fragments. + */ + + reconstruct_t *get_reconstruct(hw_addr_t src, uint16_t tag) { + reconstruct_t *ret = NULL; + int i; + for (i = 0; i < N_RECONSTRUCTIONS; i++) { + reconstruct_t *recon = (reconstruct_t *)&recon_data[i]; + dbg("IPDispatch", " 0x%x 0x%x 0x%x\n", recon->timeout, recon->metadata.sender, recon->tag); + + if (recon->tag == tag && + recon->metadata.sender == src) { + + if (recon->timeout > T_UNUSED) { + + recon->timeout = T_ACTIVE; + return recon; + + } else if (recon->timeout < T_UNUSED) { + // if we have already tried and failed to get a buffer, we + // need to drop remaining fragments. + return NULL; + } + } + if (recon->timeout == T_UNUSED) + ret = recon; + } + return ret; + } + + /* + * This is called before a receive on packets with a source routing header. + * + * it updates the path stored in the header to remove our address + * and include our predicessor. + * + * However, if this is not a source record path and we are not in the current + * spot, this means we are along the default path and so should invalidate this + * source header. + */ + void updateSourceRoute(hw_addr_t prev_hop, struct source_header *sh) { + uint16_t my_address = call IPAddress.getShortAddr(); + if ((sh->dispatch & IP_EXT_SOURCE_INVAL) == IP_EXT_SOURCE_INVAL) return; + if (((sh->dispatch & IP_EXT_SOURCE_RECORD) != IP_EXT_SOURCE_RECORD) && + (ntohs(sh->hops[sh->current]) != my_address)) { + sh->dispatch |= IP_EXT_SOURCE_INVAL; + dbg("IPDispatch", "Invalidating source route!\n"); + return; + } + if (sh->current == SH_NENTRIES(sh)) return; + sh->hops[sh->current] = htons(prev_hop); + sh->current++; + } + + + + + message_t *handle1stFrag(message_t *msg, packed_lowmsg_t *lowmsg) { + uint8_t *unpack_buf; + struct ip6_hdr *ip; + + // uint16_t real_payload_length, real_offset = sizeof(struct ip6_hdr); + + unpack_info_t u_info; + + unpack_buf = ip_malloc(LIB6LOWPAN_MAX_LEN + LOWPAN_LINK_MTU); + if (unpack_buf == NULL) return msg; + + // unpack all the compressed headers. this means the IP headers, + // and possibly also the UDP ones if there are no hop-by-hop + // options. + ip_memclr(unpack_buf, LIB6LOWPAN_MAX_LEN + LOWPAN_LINK_MTU); + if (unpackHeaders(lowmsg, &u_info, + unpack_buf, LIB6LOWPAN_MAX_LEN) == NULL) { + ip_free(unpack_buf); + return msg; + } + + ip = (struct ip6_hdr *)unpack_buf; + + + // first check if we forward or consume it + if (call IPRouting.isForMe(ip)) { + struct ip_metadata metadata; + dbg("IPDispatch", "is for me!\n"); + // consume it: + // - get a buffer + // - if fragmented, wait for remaining fragments + // - if not, dispatch from here. + + metadata.sender = call IEEE154Packet.source(msg); + metadata.lqi = call CC2420Packet.getLqi(msg); + + ip->plen = htons(ntohs(ip->plen) - u_info.payload_offset); + switch (ip->nxt_hdr) { + case IANA_UDP: + ip->plen = htons(ntohs(ip->plen) + sizeof(struct udp_hdr)); + } + + if (!hasFrag1Header(lowmsg)) { + uint16_t amount_here = lowmsg->len - (u_info.payload_start - lowmsg->data); + + // we can fill in the data and deliver the packet from here. + // this is the easy case... + // we malloc'ed a bit extra in this case so we don't have to + // copy the IP header; we can just add the payload after the unpacked + // buffers. + // if (rcv_buf == NULL) goto done; + ip_memcpy(u_info.header_end, u_info.payload_start, amount_here); + signal IP.recv[ip->nxt_hdr](ip, u_info.transport_ptr, &metadata); + } else { + // in this case, we need to set up a reconstruction + // structure so when the next packets come in, they can be + // filled in. + reconstruct_t *recon; + uint16_t tag, amount_here = lowmsg->len - (u_info.payload_start - lowmsg->data); + void *rcv_buf; + + if (getFragDgramTag(lowmsg, &tag)) goto fail; + + dbg("IPDispatch", "looking up frag tag: 0x%x\n", tag); + recon = get_reconstruct(lowmsg->src, tag); + + // allocate a new struct for doing reassembly. + if (recon == NULL) { + goto fail; + } + + // the total size of the IP packet + rcv_buf = ip_malloc(ntohs(ip->plen) + sizeof(struct ip6_hdr)); + + recon->metadata.sender = lowmsg->src; + recon->tag = tag; + recon->size = ntohs(ip->plen) + sizeof(struct ip6_hdr); + recon->buf = rcv_buf; + recon->transport_hdr = ((uint8_t *)rcv_buf) + (u_info.transport_ptr - unpack_buf); + recon->bytes_rcvd = u_info.payload_offset + amount_here + sizeof(struct ip6_hdr); + recon->timeout = T_ACTIVE; + + if (rcv_buf == NULL) { + // if we didn't get a buffer better not memcopy anything + recon->timeout = T_FAILED1; + recon->size = 0; + goto fail; + } + if (amount_here > recon->size - sizeof(struct ip6_hdr)) { + call Leds.led1Toggle(); + recon->timeout = T_FAILED1; + recon->size = 0; + ip_free(rcv_buf); + recon->buf = NULL; + goto fail; + } + + ip_memcpy(rcv_buf, unpack_buf, u_info.payload_offset + sizeof(struct ip6_hdr)); + ip_memcpy(rcv_buf + u_info.payload_offset + sizeof(struct ip6_hdr), + u_info.payload_start, amount_here); + ip_memcpy(&recon->metadata, &metadata, sizeof(struct ip_metadata)); + + goto done; + // that's it, we just filled in the first piece of the fragment + } + } else { + // otherwise set up forwarding information for the next + // fragments and enqueue this message_t on its merry way. + send_info_t *s_info; + send_entry_t *s_entry; + forward_entry_t *fwd; + message_t *msg_replacement; + + *u_info.hlim = *u_info.hlim - 1; + if (*u_info.hlim == 0) { + uint16_t amount_here = lowmsg->len - (u_info.payload_start - lowmsg->data); + call ICMP.sendTimeExceeded(ip, &u_info, amount_here); + // by bailing here and not setting up an entry in the + // forwarding cache, following fragments will be dropped like + // they should be. we don't strictly follow the RFC that says + // we should return at least 64 bytes of payload. + ip_free(unpack_buf); + return msg; + } + s_info = getSendInfo(); + s_entry = call SendEntryPool.get(); + msg_replacement = call FragPool.get(); + if (s_info == NULL || s_entry == NULL || msg_replacement == NULL) { + if (s_info != NULL) + SENDINFO_DECR(s_info); + if (s_entry != NULL) + call SendEntryPool.put(s_entry); + if (msg_replacement != NULL) + call FragPool.put(msg_replacement); + goto fail; + } + + if (ip->nxt_hdr == NXTHDR_SOURCE) { + // this updates the source route in the message_t, if it + // exists... + updateSourceRoute(call IEEE154Packet.source(msg), + u_info.sh); + } + + if (call IPRouting.getNextHop(ip, u_info.sh, lowmsg->src, &s_info->policy) != SUCCESS) + goto fwd_fail; + + dbg("IPDispatch", "next hop is: 0x%x\n", s_info->policy.dest); + + if (hasFrag1Header(lowmsg)) { + fwd = table_search(&forward_cache, forward_unused); + if (fwd == NULL) { + goto fwd_fail; + } + + fwd->timeout = T_ACTIVE; + fwd->l2_src = call IEEE154Packet.source(msg); + getFragDgramTag(lowmsg, &fwd->old_tag); + fwd->new_tag = ++lib6lowpan_frag_tag; + // forward table gets a reference + SENDINFO_INCR(s_info); + fwd->s_info = s_info; + setFragDgramTag(lowmsg, lib6lowpan_frag_tag); + } + + // give a reference to the send_entry + SENDINFO_INCR(s_info); + s_entry->msg = msg; + s_entry->info = s_info; + + if (call SendQueue.enqueue(s_entry) != SUCCESS) + stats.encfail++; + post sendTask(); + + // s_info leaves lexical scope; + SENDINFO_DECR(s_info); + ip_free(unpack_buf); + return msg_replacement; + + fwd_fail: + call FragPool.put(msg_replacement); + call SendInfoPool.put(s_info); + call SendEntryPool.put(s_entry); + } + + + + fail: + done: + ip_free(unpack_buf); + return msg; + } + + event message_t *IEEE154Receive.receive(message_t *msg, void *msg_payload, uint8_t len) { + packed_lowmsg_t lowmsg; + CHECK_NODE_ID msg; + + // set up the ip message structaddFragment + lowmsg.data = msg_payload; + lowmsg.len = len; + lowmsg.src = call IEEE154Packet.source(msg); + lowmsg.dst = call IEEE154Packet.destination(msg); + + stats.rx_total++; + + call IPRouting.reportReception(call IEEE154Packet.source(msg), + call CC2420Packet.getLqi(msg)); + + lowmsg.headers = getHeaderBitmap(&lowmsg); + if (lowmsg.headers == LOWPAN_NALP_PATTERN) { + goto fail; + } + + // consume it + if (!hasFragNHeader(&(lowmsg))) { + // in this case, we need to unpack the addressing information + // and either dispatch the packet locally or forward it. + msg = handle1stFrag(msg, &lowmsg); + goto done; + } else { + // otherwise, it's a fragN packet, and we just need to copy it + // into a buffer or forward it. + forward_entry_t *fwd; + reconstruct_t *recon; + uint8_t offset_cmpr; + uint16_t offset, amount_here, tag; + uint8_t *payload; + + if (getFragDgramTag(&lowmsg, &tag)) goto fail; + if (getFragDgramOffset(&lowmsg, &offset_cmpr)) goto fail; + + forward_lookup_tag = tag; + forward_lookup_src = call IEEE154Packet.source(msg); + + fwd = table_search(&forward_cache, forward_lookup); + payload = getLowpanPayload(&lowmsg); + + recon = get_reconstruct(lowmsg.src, tag); + if (recon != NULL && recon->timeout > T_UNUSED && recon->buf != NULL) { + // for packets we are reconstructing. + + offset = (offset_cmpr * 8); + amount_here = lowmsg.len - (payload - lowmsg.data); + + if (offset + amount_here > recon->size) goto fail; + ip_memcpy(recon->buf + offset, payload, amount_here); + + recon->bytes_rcvd += amount_here; + + if (recon->size == recon->bytes_rcvd) { + // signal and free the recon. + signalDone(recon); + } + } else if (fwd != NULL && fwd->timeout > T_UNUSED) { + // this only catches if we've forwarded all the past framents + // successfully. + message_t *replacement = call FragPool.get(); + send_entry_t *s_entry = call SendEntryPool.get(); + uint16_t lowpan_size; + uint8_t lowpan_offset; + + if (replacement == NULL || s_entry == NULL) { + // we have to drop the rest of the framents if we don't have + // a buffer... + if (replacement != NULL) + call FragPool.put(replacement); + if (s_entry != NULL) + call SendEntryPool.put(s_entry); + + stats.fw_drop++; + fwd->timeout = T_FAILED1; + goto fail; + } + // keep a reference for ourself, and pass it off to the + // send_entry_t + SENDINFO_INCR(fwd->s_info); + + getFragDgramOffset(&lowmsg, &lowpan_offset); + getFragDgramSize(&lowmsg, &lowpan_size); + if ((lowpan_offset * 8) + (lowmsg.len - (payload - lowmsg.data)) == lowpan_size) { + // this is the last fragment. since delivery is in-order, + // we want to free up that forwarding table entry. + // take back the reference the table had. + SENDINFO_DECR(fwd->s_info); + fwd->timeout = T_UNUSED; + } + + setFragDgramTag(&lowmsg, fwd->new_tag); + + s_entry->msg = msg; + s_entry->info = fwd->s_info; + + dbg("IPDispatch", "forwarding: dest: 0x%x\n", + fwd->s_info->policy.dest[s_entry->info->policy.current]); + + if (call SendQueue.enqueue(s_entry) != SUCCESS) { + stats.encfail++; + dbg("Drops", "drops: receive enqueue failed\n"); + } + post sendTask(); + return replacement; + + } else goto fail; + goto done; + } + + fail: + dbg("Drops", "drops: receive()\n");; + stats.rx_drop++; + done: + return msg; + } + + + /* + * Send-side functionality + */ + + task void sendTask() { + send_entry_t *s_entry; + if (radioBusy || state != S_RUNNING) return; + if (call SendQueue.empty()) return; + // this does not dequeue + s_entry = call SendQueue.head(); + + + call IEEE154Packet.setDestination(s_entry->msg, + s_entry->info->policy.dest[s_entry->info->policy.current]); + call PacketLink.setRetries(s_entry->msg, s_entry->info->policy.retries); + call PacketLink.setRetryDelay(s_entry->msg, s_entry->info->policy.delay); +#ifdef LPL_SLEEP_INTERVAL + call LowPowerListening.setRxSleepInterval(s_entry->msg, LPL_SLEEP_INTERVAL); +#endif + + dbg("IPDispatch", "sendTask dest: 0x%x len: 0x%x \n", call IEEE154Packet.destination(s_entry->msg), + call Packet.payloadLength(s_entry->msg)); + + if (s_entry->info->failed) { + dbg("Drops", "drops: sendTask: dropping failed fragment\n"); + goto fail; + } + + if ((call IEEE154Send.send(call IEEE154Packet.destination(s_entry->msg), + s_entry->msg, + call Packet.payloadLength(s_entry->msg))) != SUCCESS) { + dbg("Drops", "drops: sendTask: send failed\n"); + goto fail; + } + radioBusy = TRUE; + if (call SendQueue.empty()) return; + // this does not dequeue + s_entry = call SendQueue.head(); + + return; + fail: + post sendTask(); + stats.tx_drop++; + + // deallocate the memory associated with this request. + // other fragments associated with this packet will get dropped. + s_entry->info->failed = TRUE; + SENDINFO_DECR(s_entry->info); + call FragPool.put(s_entry->msg); + call SendEntryPool.put(s_entry); + call SendQueue.dequeue(); + } + + + /* + * this interface is only for grownups; it is also only called for + * local sends. + * + * it will pack the message into the fragment pool and enqueue + * those fragments for sending + * + * it will set + * - payload length + * - version, traffic class and flow label + * + * the source and destination IP addresses must be set by higher + * layers. + */ + command error_t IP.send[uint8_t prot](struct split_ip_msg *msg) { + uint16_t payload_length; + + if (state != S_RUNNING) { + return EOFF; + } + + if (msg->hdr.hlim != 0xff) + msg->hdr.hlim = call IPRouting.getHopLimit(); + + msg->hdr.nxt_hdr = prot; + ip_memclr(msg->hdr.vlfc, 4); + msg->hdr.vlfc[0] = IPV6_VERSION << 4; + + call IPRouting.insertRoutingHeaders(msg); + + payload_length = msg->data_len; + + { + struct generic_header *cur = msg->headers; + while (cur != NULL) { + payload_length += cur->len; + cur = cur->next; + } + } + + msg->hdr.plen = htons(payload_length); + + // okay, so we ought to have a fully setup chain of headers here, + // so we ought to be able to compress everything into fragments. + // + + { + send_info_t *s_info; + send_entry_t *s_entry; + uint8_t frag_len = 1; + message_t *outgoing; + fragment_t progress; + struct source_header *sh; + progress.offset = 0; + + s_info = getSendInfo(); + if (s_info == NULL) return ERETRY; + + // fill in destination information on outgoing fragments. + sh = (msg->headers != NULL) ? (struct source_header *)msg->headers->hdr.ext : NULL; + if (call IPRouting.getNextHop(&msg->hdr, sh, 0x0, + &s_info->policy) != SUCCESS) { + dbg("Drops", "drops: IP send: getNextHop failed\n"); + goto done; + } + +#ifdef DBG_TRACK_FLOWS + dbg_flowid++; +#endif + + //goto done; + while (frag_len > 0) { + s_entry = call SendEntryPool.get(); + outgoing = call FragPool.get(); + + if (s_entry == NULL || outgoing == NULL) { + if (s_entry != NULL) + call SendEntryPool.put(s_entry); + if (outgoing != NULL) + call FragPool.put(outgoing); + // this will cause any fragments we have already enqueued to + // be dropped by the send task. + s_info->failed = TRUE; + dbg("Drops", "drops: IP send: no fragments\n"); + goto done; + } + +#ifdef DBG_TRACK_FLOWS + (call getFlowID(outgoing))->src = TOS_NODE_ID; + (call getFlowID(outgoing))->dst = ((uint16_t )msg->hdr.dst_addr[14]) << 8 | + (uint16_t)msg->hdr.dst_addr[15]; + (call getFlowID(outgoing))->id = dbg_flowid; + (call getFlowID(outgoing))->seq = 0; + (call getFlowID(outgoing))->nxt_hdr = prot; +#endif + + frag_len = getNextFrag(msg, &progress, + call Packet.getPayload(outgoing, call Packet.maxPayloadLength()), + call Packet.maxPayloadLength()); + if (frag_len == 0) { + call FragPool.put(outgoing); + call SendEntryPool.put(s_entry); + goto done; + } + call Packet.setPayloadLength(outgoing, frag_len); + + s_entry->msg = outgoing; + s_entry->info = s_info; + + if (call SendQueue.enqueue(s_entry) != SUCCESS) { + stats.encfail++; + dbg("Drops", "drops: IP send: enqueue failed\n"); + goto done; + } + + SENDINFO_INCR(s_info); + printfUART("enqueue len 0x%x dest: 0x%x retries: 0x%x delay: 0x%x\n",frag_len, + s_info->policy.dest, s_info->policy.retries, s_info->policy.delay); + } + done: + SENDINFO_DECR(s_info); + post sendTask(); + return SUCCESS; + + } + } + + event void IEEE154Send.sendDone(message_t *msg, error_t error) { + send_entry_t *s_entry = call SendQueue.head(); + CHECK_NODE_ID; + + radioBusy = FALSE; + + if (state == S_STOPPING) { + call RadioControl.stop(); + state = S_STOPPED; + goto fail; + } + + + if (!call PacketLink.wasDelivered(msg)) { + + // if we haven't sent out any fragments yet, we can try rerouting + if (s_entry->info->frags_sent == 0) { + // SDH : TODO : if sending a fragment fails, abandon the rest of + // the fragments + s_entry->info->policy.current++; + if (s_entry->info->policy.current < s_entry->info->policy.nchoices) { + // this is the retry case; we don't need to change anything. + post sendTask(); + return; + } + // no more next hops to try, so free the buffers and move on + } + // a fragment failed, and it wasn't the first. we drop all + // remaining fragments. + goto fail; + } else { + // the fragment was successfully sent. + s_entry->info->frags_sent++; + goto done; + } + goto done; + + fail: + s_entry->info->failed = TRUE; + if (s_entry->info->policy.dest[0] != 0xffff) + dbg("Drops", "drops: sendDone: frag was not delivered\n"); + + done: + s_entry->info->policy.actRetries = call PacketLink.getRetries(msg); + call IPRouting.reportTransmission(&s_entry->info->policy); + // kill off any pending fragments + SENDINFO_DECR(s_entry->info); + call FragPool.put(s_entry->msg); + call SendEntryPool.put(s_entry); + call SendQueue.dequeue(); + + post sendTask(); + } + + + + event void ICMP.solicitationDone() { + + } + + /* + * Statistics interface + */ + command void Statistics.get(ip_statistics_t *statistics) { + stats.fragpool = call FragPool.size(); + stats.sendinfo = call SendInfoPool.size(); + stats.sendentry= call SendEntryPool.size(); + stats.sndqueue = call SendQueue.size(); + stats.heapfree = ip_malloc_freespace(); + ip_memcpy(statistics, &stats, sizeof(ip_statistics_t)); + } + + command void Statistics.clear() { + ip_memclr((uint8_t *)&stats, sizeof(ip_statistics_t)); + } + + default event void IP.recv[uint8_t nxt_hdr](struct ip6_hdr *iph, + void *payload, + struct ip_metadata *meta) { + } +} diff --git a/tos/lib/net/blip/IPRoutingP.nc b/tos/lib/net/blip/IPRoutingP.nc new file mode 100644 index 00000000..83ade730 --- /dev/null +++ b/tos/lib/net/blip/IPRoutingP.nc @@ -0,0 +1,915 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include "IPDispatch.h" +#include "PrintfUART.h" + +module IPRoutingP { + provides interface IPRouting; + provides interface Statistics; + uses interface ICMP; + uses interface Boot; + uses interface IPAddress; + uses interface Random; + + uses interface Timer as SortTimer; + + uses interface IP as TGenSend; + uses interface Timer as TrafficGenTimer; + + uses interface Leds; + +} implementation { + + enum { + SHORT_EPOCH = 0, + LONG_EPOCH = 1, + }; + + //uint16_t current_epoch; + //route_statistics_t stats; + uint16_t last_qual; + uint8_t last_hops; + + uint8_t num_low_neigh; + + bool soliciting; + + // pointer into the neighbor table of the current entry that is our + // first choice. + struct neigh_entry *default_route; + uint16_t default_route_failures; + + uint32_t traffic_interval; + bool traffic_sent; + + struct neigh_entry neigh_table[N_NEIGH]; + + void printTable(); + error_t freeFullPath(struct flow_path* path); + void updateFlowCounts(struct flow_entry *target); + void updateRankings(); + void swapNodes(struct neigh_entry *highNode, struct neigh_entry *lowNode); + uint8_t checkThresh(uint32_t firstVal, uint32_t secondVal, uint16_t thresh); + void evictNeighbor(struct neigh_entry *neigh); + uint16_t getMetric(struct neigh_entry *neigh); + + uint16_t adjustLQI(uint8_t val) { + uint16_t result = (80 - (val - 50)); + result = (((result * result) >> 3) * result) >> 3; // result = (result ^ 3) / 64 + dbg("Lqi", "adjustLqi in: 0x%x out: 0x%x\n", val, result); + return result; + } + + void clearStats(struct neigh_entry *r) { + int j; + for (j = 0; j < N_EPOCHS; j++) { + r->stats[j].total = 0; + r->stats[j].success = 0; + r->stats[j].receptions = 0; + } + } + + void clearEpoch(uint8_t target_epoch) { + int i; + for (i = 0; i < N_NEIGH; i++) { + neigh_table[i].stats[target_epoch].total = 0; + neigh_table[i].stats[target_epoch].success = 0; + neigh_table[i].stats[target_epoch].receptions = 0; + } + } + + cmpr_ip6_addr_t shortenAddr(ip6_addr_t addr) { + cmpr_ip6_addr_t shortAddr; + ip_memcpy(&shortAddr, &addr[14],2); + return shortAddr; + } + + void restartTrafficGen() { + traffic_interval = TGEN_BASE_TIME; + // jitter the period by 10% to prevent synchronization + traffic_interval += (call Random.rand16()) % (TGEN_BASE_TIME); + if (call TrafficGenTimer.isRunning()) + call TrafficGenTimer.stop(); + + call TrafficGenTimer.startOneShot(traffic_interval); + } + + event void TrafficGenTimer.fired() { + struct split_ip_msg *msg; + if (traffic_sent) goto done; + msg = (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg)); + if (msg == NULL) goto done; + + ip_memclr((uint8_t *)&msg->hdr, sizeof(struct ip6_hdr)); + inet_pton6("ff05::1", &msg->hdr.ip6_dst); + call IPAddress.getIPAddr(&msg->hdr.ip6_src); + msg->data = NULL; + msg->data_len = 0; + msg->headers = NULL; + + dbg("IPRouting", "Sending generated message\n"); + call TGenSend.send(msg); + ip_free(msg); + done: + // restart timer + dbg("IPRouting", "Done checking for tgen\n"); + traffic_sent = FALSE; + traffic_interval *= 2; + if (traffic_interval > TGEN_MAX_INTERVAL) + traffic_interval = TGEN_MAX_INTERVAL; + call TrafficGenTimer.startOneShot(traffic_interval); + } + + event void TGenSend.recv(struct ip6_hdr *iph, + void *payload, + struct ip_metadata *meta) { + + } + + event void Boot.booted() { + int i; + + for (i = 0; i < N_NEIGH; i++) { + neigh_table[i].flags = 0; + clearStats(&neigh_table[i]); + } + + // current_epoch = 0; + soliciting = FALSE; + //reRouting = FALSE; + default_route_failures = 0; + default_route = &neigh_table[0]; + // boot with this true so the router will invalidate any state + // associated from us when it gets the first packet. + last_qual = 0xffff; + last_hops = 0xff; + num_low_neigh = 0; + call Statistics.clear(); + call SortTimer.startPeriodic(1024L * 60); + + traffic_sent = FALSE; + restartTrafficGen(); + } + + command bool IPRouting.isForMe(struct ip6_hdr *hdr) { + // the destination prefix is either link-local or global, or + // multicast (we accept all multicast packets), and the suffix is + // me. + struct in6_addr *my_address = call IPAddress.getPublicAddr(); + return (((cmpPfx(my_address->s6_addr, hdr->ip6_dst.s6_addr) || + cmpPfx(linklocal_prefix, hdr->ip6_dst.s6_addr)) + && cmpPfx(&my_address->s6_addr[8], &hdr->ip6_dst.s6_addr[8])) + || cmpPfx(multicast_prefix, hdr->ip6_dst.s6_addr)); + } + + + struct neigh_entry *getNeighEntry(cmpr_ip6_addr_t a) { + int i; + for (i = 0; i < N_NEIGH; i++) { + if (neigh_table[i].neighbor == a) + return &(neigh_table[i]); + } + return NULL; + } + + + uint16_t getConfidence(struct neigh_entry *neigh) { + //uint8_t i; + uint16_t conf = 0; + if (neigh != NULL && IS_NEIGH_VALID(neigh)) { + //for (i = 0; i < N_EPOCHS_COUNTED; i++) { + //conf += neigh->stats[(current_epoch + N_EPOCHS - i) % N_EPOCHS].total; + //} + conf = neigh->stats[LONG_EPOCH].total; + } + return conf; + } + + uint16_t getReceptions(struct neigh_entry *neigh) { + //uint8_t i; + uint16_t receptions = 0; + if ((neigh != NULL) && (IS_NEIGH_VALID(neigh))) { + //for (i = 0; i < N_EPOCHS_COUNTED; i++) { + //receptions += neigh->stats[(current_epoch + N_EPOCHS - i) % N_EPOCHS].receptions; + //} + receptions += neigh->stats[receptions].receptions; + } + return receptions; + } + + uint16_t getSuccess(struct neigh_entry *neigh) { + //uint8_t i; + uint16_t succ = 0; + if ((neigh != NULL) && (IS_NEIGH_VALID(neigh))) { + //for (i = 0; i < N_EPOCHS_COUNTED; i++) { + //succ += neigh->stats[(current_epoch + N_EPOCHS - i) % N_EPOCHS].success; + //} + succ += neigh->stats[LONG_EPOCH].success; + } + return succ; + } + + uint16_t getLinkCost(struct neigh_entry *neigh) { + uint16_t conf, succ; + conf = getConfidence(neigh); + succ = getSuccess(neigh); + // we can return a real confidence if we have enough data + if (succ == 0 || conf == 0) return 0xff; + return ((conf * 10) / succ); + } + + + void printTable() { +#ifdef PRINTFUART_ENABLED + uint8_t i; +#ifdef CENTRALIZED_ROUTING + uint8_t j, k; +#endif + dbg("Table", "----------------------------------------___\n"); + dbg("Table", "ind\tvalid\tmature\tneigh\thops\tconf\trecep\tcost\tetx\tlqi\tmetric\n"); + for (i = 0; i < N_NEIGH; i++) { + if (&neigh_table[i] == default_route) + dbg("Table", "-- default --\n"); + dbg("Table", "0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\n", i, + (neigh_table[i].flags & T_VALID_MASK), (IS_MATURE(&(neigh_table[i]))), + neigh_table[i].neighbor, neigh_table[i].hops, getConfidence(&(neigh_table[i])), + getReceptions(&(neigh_table[i])), neigh_table[i].costEstimate, + getLinkCost(&(neigh_table[i])), neigh_table[i].linkEstimate, + getMetric(&(neigh_table[i]))); + } + dbg("Table", "----------------------------------------\n"); +#endif + } + + uint16_t getMetric(struct neigh_entry *r) { + return (((r == NULL) || (!(IS_NEIGH_VALID(r)))) ? + 0xffff : (r->costEstimate + getLinkCost(r))); + } + + // Selects a potential neighbor that is not the current default route + void chooseNewRandomDefault(bool force) { + uint8_t i; + uint8_t numNeigh = 0; + uint8_t chosenNeigh; + + dbg("IPRouting", "Looking for a new default route\n"); + + for (i = 1; i < N_NEIGH; i++) { + if (!(IS_NEIGH_VALID(&(neigh_table[i])))) break; + if (&neigh_table[i] == default_route) continue; + if (neigh_table[i].hops < neigh_table[0].hops) + numNeigh++; + } + + // There exist other neighbors with respectable hop counts + if (numNeigh) { + chosenNeigh = (call Random.rand16()) % numNeigh; + for (i = 1; i < N_NEIGH; i++) { + if (&neigh_table[i] == default_route) continue; + if (neigh_table[i].hops < neigh_table[0].hops) { + if (chosenNeigh) { + chosenNeigh--; + } else { + default_route = &neigh_table[i]; + default_route_failures = 0; + return; + } + } + } + } + + if (!force) goto done; + + numNeigh = 0; + for (i = 1; i < N_NEIGH; i++) { + if (!(IS_NEIGH_VALID(&(neigh_table[i])))) break; + if (&neigh_table[i] == default_route) continue; + if (neigh_table[i].costEstimate < neigh_table[0].costEstimate) + numNeigh++; + } + + if (numNeigh) { + chosenNeigh = (call Random.rand16()) % numNeigh; + for (i = 1; i < N_NEIGH; i++) { + if (&neigh_table[i] == default_route) continue; + //if (neigh_table[i].costEstimate < getMetric(&(neigh_table[0]))) { + if (neigh_table[i].costEstimate < neigh_table[0].costEstimate) { + if (chosenNeigh) { + chosenNeigh--; + } else { + default_route = &neigh_table[i]; + default_route_failures = 0; + return; + } + } + } + } + done: + dbg("IPRouting", "No random route found\n"); + default_route = &neigh_table[0]; + default_route_failures = 0; + } + /* + * return: a send policy for a given attempt, including destination and one-hop neighbor. + * if no default route is available, returns FAIL unless the + * packet is destined to a link-local address, or a + * all-node/all-routers local multicast group. + * + */ + command error_t IPRouting.getNextHop(struct ip6_hdr *hdr, + struct source_header *sh, + hw_addr_t prev_hop, + send_policy_t *ret) { + + int i; + prev_hop = 0; + ret->retries = 10; + ret->delay = 30; + ret->current = 0; + ret->nchoices = 0; + + + // we only use the address in the source header if the record option is not used + // otherwise, we use normal routing. + if (hdr->nxt_hdr == NXTHDR_SOURCE && + (sh->dispatch & IP_EXT_SOURCE_RECORD_MASK) != IP_EXT_SOURCE_RECORD && + (sh->dispatch & IP_EXT_SOURCE_INVAL) != IP_EXT_SOURCE_INVAL) { + // if it's source routed, grab the next address out of the header. + + // if (sh->current == sh->nentries) return FAIL; + + ret->dest[0] = ntohs(sh->hops[sh->current]); + ret->nchoices = 1; + + dbg("IPRouting", "source dispatch: 0x%x, next hop: 0x%x, current: 0x%x\n", + sh->dispatch, ntohs(sh->hops[sh->current]), sh->current); + + } else if (hdr->ip6_dst.s6_addr16[0] == htons(0xff02)) { + //hdr->dst_addr[0] == 0xff && (hdr->dst_addr[1] & 0xf) == 0x2) { + // if it's multicast, for now, we send it to the local broadcast + ret->dest[0] = 0xffff; + ret->nchoices = 1; + ret->retries = 0; + ret->delay = 0; + return SUCCESS; + } else if (cmpPfx(hdr->ip6_dst.s6_addr, linklocal_prefix)) { + ret->dest[0] = ntohs(hdr->ip6_dst.s6_addr16[7]); // (hdr->dst_addr[14] << 8) | hdr->dst_addr[15]; + ret->nchoices = 1; + return SUCCESS; // Currently only want one choice for broadcast + } + // if (getNeighEntry(ntohs(shortenAddr(hdr->dst_addr))) != NULL) { + // dbg("IPRouting", "Directly adding next hop of dest: 0x%x\n", ntohs(shortenAddr(hdr->dst_addr))); + // ret->dest[ret->nchoices++] = ntohs(shortenAddr(hdr->dst_addr)); + // } + + + //dbg("IPRouting", "flags: 0x%x neigh: 0x%x\n", r->flags, r->neighbor); + if (IS_NEIGH_VALID(default_route) && prev_hop != default_route->neighbor) { + ret->dest[ret->nchoices++] = default_route->neighbor; + } else { + dbg("IPRouting", "Invalid default route... quitting\n"); + return FAIL; + } + i = 0; + while (ret->nchoices < N_PARENT_CHOICES && i < N_NEIGH) { + if (IS_NEIGH_VALID(&neigh_table[i]) && + &neigh_table[i] != default_route && + neigh_table[i].neighbor != prev_hop) { + ret->dest[ret->nchoices++] = neigh_table[i].neighbor; + } + i++; + } + + if (ret->nchoices == 0) + return FAIL; + + dbg("IPRouting", "getNextHop: nchoices: 0x%x\n", ret->nchoices); + + return SUCCESS; + } + + command uint8_t IPRouting.getHopLimit() { + // advertise our best path to the root + if (IS_NEIGH_VALID(&(neigh_table[0])))// && IS_MATURE(&neigh_table[0])) + return neigh_table[0].hops + 1; + else return 0xf0; + } + + command uint16_t IPRouting.getQuality() { + if (IS_NEIGH_VALID(&(neigh_table[0]))) + return getMetric(&(neigh_table[0])); + else return 0xffff; + } + + + /* + * An advertisement was received from a neighboring node + * + * Processing steps: + * 1) First must check to see if the neighbor already exists in the table + * a) If so, we are just updating its information + * 2) If not in table, check to make sure that the lqi passes the low-filter bar. + * a) If not, return + * 3) If there is an empty space + * a) Insert it in the open space + * b) (Do we then want to move it up to where it belongs based on total path cost?) + * 4) If there is no open space + * a) If the last entry doesn't meet the confidence threshold (CONF_EVICT_THRESHOLD), do nothing + * b) Otherwise, replace last entry if: + * i) Advertised Path Cost difference is greater than PATH_COST_DIFF_THRESH + * ii) Advertised Path Cost difference is within PATH_COST_DIFF_THRESH, + * and Link estimate is lower by at least LQI_DIFF_THRESH + * 5) Make sure to update the receptions statistic + */ + command void IPRouting.reportAdvertisement(hw_addr_t neigh, uint8_t hops, + uint8_t lqi, uint16_t cost) { + //int i, place = N_NEIGH; + //bool mustInsert = FALSE, exists = FALSE; + //uint8_t maxCost = 0; + //bool recount = FALSE; + struct neigh_entry *neigh_slot = NULL; + dbg("IPRouting", "report adv: 0x%x 0x%x 0x%x 0x%x\n", neigh, hops, lqi, cost); + dbg("IPRouting", "my Cost: 0x%x, num_low_neigh: 0x%x, N_LOW_NEIGH: 0x%x\n", + getMetric(&(neigh_table[0])), num_low_neigh, N_LOW_NEIGH); + + // If neighbor does not exist in table + if ((neigh_slot = getNeighEntry(neigh)) == NULL) { + dbg("IPRouting", "Advertisement from new neighbor 0x%x!\n", neigh); + if (adjustLQI(lqi) > LQI_ADMIT_THRESH || cost == 0xffff) { + dbg("IPRouting", "Poor Link. Rejecting\n"); + return; + } + // free spots in the table. + if(!(IS_NEIGH_VALID(&(neigh_table[N_NEIGH - 1])))) { + + dbg("IPRouting", "Neighbor being inserted in empty slot: 0x%x\n", N_NEIGH - 1); + for (neigh_slot = &(neigh_table[N_NEIGH - 1]); + neigh_slot > &(neigh_table[0]); neigh_slot--) { + // we might go ahead of other neighbors if we haven't heard + // from them either and our cost is better. + if (IS_NEIGH_VALID(neigh_slot - 1) && + getConfidence(neigh_slot - 1) == 0 && + (((struct neigh_entry *)(neigh_slot - 1))->costEstimate > cost)) { + swapNodes((neigh_slot - 1), neigh_slot); + } else if (IS_NEIGH_VALID(neigh_slot - 1)) { + // if we didn't catch on the first check and the next + // highest guy in the table is valid, we'll just go at the + // end. If this never catches, the loop will terminate + // with neigh_slot == &neigh_table[0]. + break; + } + } + ip_memclr((void *)neigh_slot, sizeof(struct neigh_entry)); + } else { + // evict the bottom guy? + dbg("IPRouting", "No empty slots...looking to replace bottom entry\n"); + //if (getConfidence(&(neigh_table[N_NEIGH - 1])) >= CONF_EVICT_THRESHOLD) { + if (IS_MATURE(&(neigh_table[N_NEIGH - 1])) || + hops <= neigh_table[N_NEIGH - 1].hops) { + dbg("IPRouting", "Bottom entry evictable\n"); + // we're a lot better, + if ((checkThresh(neigh_table[N_NEIGH - 1].costEstimate, cost, + PATH_COST_DIFF_THRESH) == BELOW_THRESH) || + // or we're about equal and the link estimate is better + ((checkThresh(neigh_table[N_NEIGH - 1].costEstimate, cost, + PATH_COST_DIFF_THRESH) == WITHIN_THRESH) && + (checkThresh(neigh_table[N_NEIGH - 1].linkEstimate, adjustLQI(lqi), + LQI_DIFF_THRESH) == BELOW_THRESH))) { + dbg("Evictions", "evict: bottom entry\n"); + + // use evict to correctly handle the case when we evict + // the default route. + evictNeighbor(&neigh_table[N_NEIGH - 1]); + neigh_slot = &(neigh_table[N_NEIGH - 1]); + } + } + } + } else { + if (cost == 0xffff) { + dbg("Evictions", "evict with cost 0xffff\n"); + evictNeighbor(neigh_slot); + return; + } + // Do this to prevent double counting because of reportReception + neigh_slot->stats[SHORT_EPOCH].receptions--; + } + + if (neigh_slot != NULL) { + SET_NEIGH_VALID(neigh_slot); + neigh_slot->neighbor = neigh; + neigh_slot->hops = hops; + neigh_slot->costEstimate = cost; + neigh_slot->linkEstimate = adjustLQI(lqi); + neigh_slot->stats[SHORT_EPOCH].receptions++; + dbg("IPRouting", "currentEpoch: 0x%x, Receptions in epoch: 0x%x, Total Receptions: 0x%x\n", + SHORT_EPOCH, neigh_slot->stats[SHORT_EPOCH].receptions, getReceptions(neigh_slot)); + } + printTable(); + } + + /* + * Reports packet reception + * + * Updates the link estimate, as well as the number of receptions + */ + command void IPRouting.reportReception(hw_addr_t neigh, uint8_t lqi) { + struct neigh_entry *e = getNeighEntry(neigh); + dbg("IPRouting", "Packet received from 0x%x lqi: %u\n", neigh, lqi); + //if (e == NULL) e = addNeighEntry(neigh); + if (e != NULL) { + e->linkEstimate = adjustLQI(lqi); + // e->stats[current_epoch].receptions++; + //if (e == &(neigh_table[0])) + //resetNeighLow(); + //else if (getMetric(e) < getMetric(&(neigh_table[0]))) { + //sortFlowTable(); + //resetNeighLow(); + //} + } + } + + // Updates success (and failure) statistics + // Also needs to reroute if the number of failures hits the threshold + command void IPRouting.reportTransmission(send_policy_t *policy) { + int i; + struct neigh_entry *e = NULL; + + // If not a broadcast address: + // 1. If none of the provided addresses worked, then we should send out a solicitation + // 2. All the failed nodes should have their totals increased by the max number of retries + // 3. The successful node should update both its total and success by one + // 4. If the successful node meets one of the following two conditions, it should be moved up one spot: + // a) It has a lower path cost and higher confidence than the above entry + // b) It has a similar path cost and confidence above a threshold (CONF_PROM_THRESHOLD) + // 5. If we have had too many consecutive losses (MAX_CONSEC_FAILURES) toggle ReRouting + if (policy->dest[0] != HW_BROADCAST_ADDR) { + // stats.messages++; + dbg("IPRouting", "reportTransmission: current: 0x%x, nchoices: 0x%x, retries: 0x%x\n", + policy->current, policy->nchoices, policy->actRetries); + + // update the failed neighbor statistics + for (i = 0; i < policy->current; i++) { + e = getNeighEntry(policy->dest[i]); + if (e != NULL) { + // SDH : presumably retries == actRetries + e->stats[SHORT_EPOCH].total += policy->retries; + + if (e == default_route) { + default_route_failures++; + } + + dbg("IPRouting", "reportTransmissions: 0x%x failed\n", e->neighbor); + + // stats.transmissions += policy->retries; + } + } + + if (default_route_failures > MAX_CONSEC_FAILURES) { + dbg("IPRouting", "Too many consecutive failures!\n"); + chooseNewRandomDefault(TRUE); + } + + // if we succeeded sending the packet, increment the success on that one. + e = getNeighEntry(policy->dest[policy->current]); + if ((policy->current < policy->nchoices) && e != NULL) { + e->stats[SHORT_EPOCH].success += 1; + e->stats[SHORT_EPOCH].total += policy->actRetries; + + dbg("IPRouting", "Success: 0x%x, Total: 0x%x, ETX: 0x%x (addr 0x%x)\n", + getSuccess(e), getConfidence(e), getLinkCost(e), e->neighbor); + dbg("IPRouting", "Actual attempts was 0x%x\n", policy->actRetries); + + if (e == default_route) + default_route_failures++; + + + if ((e != &(neigh_table[0])) && + // we have higher confidence and lower cost + (((getConfidence(e) > CONF_PROM_THRESHOLD) && // getConfidence(e - 1)) && + (checkThresh(getMetric(e), getMetric(e-1), PATH_COST_DIFF_THRESH) == BELOW_THRESH)) || + // we have similar cost and sufficient confidenceIP + ((checkThresh(getMetric(e), getMetric(e-1), PATH_COST_DIFF_THRESH) == WITHIN_THRESH) && + (getConfidence(e) > CONF_PROM_THRESHOLD)))) { + + dbg("IPRouting", "Promoting node 0x%x over node 0x%x\n", e->neighbor, (e-1)->neighbor); + swapNodes((e - 1), e); + } + + // stats.successes += 1; + // stats.transmissions += policy->actRetries; + } else { + dbg("IPRouting", "FAILURE!!!!!\n"); + } + } + } + + /* + * @returns TRUE if the routing engine has established a default route. + */ + command bool IPRouting.hasRoute() { + return (IS_NEIGH_VALID(&(neigh_table[0]))); + } + + void insertSourceHeader(struct split_ip_msg *msg, struct flow_entry *entry) { + // these actually need to be static + static uint8_t source_buf[sizeof(struct source_header) + MAX_PATH_LENGTH * sizeof(uint16_t)]; + static struct generic_header g_sh; + struct source_header *sh = (struct source_header *)source_buf; + uint8_t i; + + sh->len = sizeof(struct source_header) + entry->entries[0].pathE->path_len * sizeof(uint16_t); + sh->current = 0; + sh->dispatch = IP_EXT_SOURCE_DISPATCH; + sh->nxt_hdr = msg->hdr.nxt_hdr; + msg->hdr.nxt_hdr = NXTHDR_SOURCE; + g_sh.hdr.ext = (struct ip6_ext *)sh; + g_sh.len = sh->len; + g_sh.next = msg->headers; + msg->headers = &g_sh; + + dbg("Install", "Inserted source header with length 0x%x and next hop: 0x%x and dispatch 0x%x\n", + entry->entries[0].pathE->path_len, entry->entries[0].pathE->path[0], sh->dispatch); + + for (i = 0; i < entry->entries[0].pathE->path_len; i++) { + sh->hops[i] = ntohs(entry->entries[0].pathE->path[i]); + } + } + + uint8_t convertTo8(uint16_t target) { + if (target > 0xFF) + return 0xFF; + return target; + } + +#ifdef DBG_TRACK_FLOWS + command void IPRouting.clearFlows() { + int i, j; + for (i = 0; i < N_FLOW_ENT; i++) { + SET_INVALID_SLOT((&(flow_table[i]))); + flow_table[i].count = N_FLOW_ENT; + for (j = 0; j < N_FLOW_CHOICES; j++) { + SET_INVALID_ENTRY(flow_table[i].entries[j]); + } + } + + for (i = 0; i < N_FULL_PATH_ENTRIES; i++) { + full_path_entries[i].path_len = 0; + } + } +#endif + + /* + * Inserts all necessary routing headers for the packet + * + * If packet is going to the root, inserts a topology information + * collection header + * + * AT: Should move source-routing header insertion to another function + * to avoid unnecessary allocation of buffer space + */ + command void IPRouting.insertRoutingHeaders(struct split_ip_msg *msg) { + // these actually need to be static + static uint8_t sh_buf[sizeof(struct topology_header) + + (sizeof(struct topology_entry) * N_NEIGH)]; + static struct generic_header record_route; + struct topology_header *th = (struct topology_header *)sh_buf; + int i, j = 0; + + // AT: We theoretically only want to attach this topology header if we're + // sending this message to a controller. Isn't it easier to just check + // to see if the dest address matches that of the sink? + // SDH: how do you know what the address of the sink is? + if (msg->hdr.nxt_hdr == IANA_UDP || msg->hdr.nxt_hdr == NXTHDR_UNKNOWN) { + traffic_sent = TRUE; + + th->len = sizeof(struct topology_header); + // only add topology information directly behind actual payload + // headers. + // SDH : TODO : check that this will not fragment the packet... + // AT: Why do we care about the number of hops? Debugging purposes? + th->nxt_hdr = msg->hdr.nxt_hdr; + + // For all these 16-bit values, we're only using 8 bit values + for (i = 0; i < N_NEIGH; i++) { + if (IS_NEIGH_VALID(&neigh_table[i]) && j < 4 && + (IS_MATURE(&neigh_table[i]) || default_route == &neigh_table[i])) { + th->topo[j].etx = convertTo8(getLinkCost(&neigh_table[i])); + th->topo[j].conf = convertTo8(getConfidence(&neigh_table[i])); + th->topo[j].hwaddr = htons(neigh_table[i].neighbor); + j++; + th->len += sizeof(struct topology_entry); + dbg("Lqi", "link est: 0x%x hops: 0x%x\n", + neigh_table[i].linkEstimate, neigh_table[i].hops); + } + } + + record_route.hdr.ext = (struct ip6_ext *)th; + record_route.len = th->len; + record_route.next = msg->headers; + if (j > 0) { + msg->hdr.nxt_hdr = NXTHDR_TOPO; + msg->headers = &record_route; + } + } + + } + + /* + * Sort timer will no longer be used only for sorting, but rather to expire an epoch and + * change entry statistics + */ + event void SortTimer.fired() { + dbg("IPRouting", "Epoch ended!\n"); + printTable(); + + if (!call IPRouting.hasRoute() && !soliciting) { + call ICMP.sendSolicitations(); + soliciting = TRUE; + } + + if (checkThresh(call IPRouting.getQuality(), last_qual, 5) != WITHIN_THRESH || + last_hops != call IPRouting.getHopLimit()) { + call ICMP.sendAdvertisements(); + last_qual = call IPRouting.getQuality(); + last_hops = call IPRouting.getHopLimit(); + } + + updateRankings(); + + if (call Random.rand16() % 32 < 8) { + dbg("IPRouting", "Attemting exploration\n"); + chooseNewRandomDefault(FALSE); + } else { + // default_route = &neigh_table[0]; + default_route_failures = 0; + } + } + + + /* + * This is called when the ICMP engine finishes sending out router solicitations. + * + * We will keep sending solicitations so long as we have not + * established a default route. + * + */ + event void ICMP.solicitationDone() { + //int i; + + dbg("IPRouting", "done soliciting\n"); + + soliciting = FALSE; + + if (!call IPRouting.hasRoute()) { + call ICMP.sendSolicitations(); + soliciting = TRUE; + } + } + + command void Statistics.get(route_statistics_t *statistics) { + //struct neigh_entry *p = getNeighEntry((getFlowEntry_Header(NULL))->entries[0].nextHop); + // struct neigh_entry *p = &(neigh_table[0]); + // stats.hop_limit = call IPRouting.getHopLimit(); +// if (p != NULL) { +// ip_memcpy(&stats.parent, p, sizeof(struct neigh_entry)); + // stats.parentmetric = getMetric(p); +// } + statistics->hop_limit = call IPRouting.getHopLimit(); + statistics->parent = (uint16_t) default_route->neighbor; + statistics->parent_metric = call IPRouting.getQuality(); + statistics->parent_etx = getMetric(default_route); + } + + command void Statistics.clear() { + // ip_memclr((uint8_t *)&stats, sizeof(route_statistics_t)); + } + + void evictNeighbor(struct neigh_entry *neigh) { + struct neigh_entry *iterator; + bool reset_default = FALSE; + + dbg("IPRouting", "Evicting neighbor 0x%x\n", neigh->neighbor); + dbg("Evictions", "evict: 0x%x\n", neigh->neighbor); + + SET_NEIGH_INVALID(neigh); + + if (neigh == default_route) { + reset_default = TRUE; + } + + ip_memclr((uint8_t *)(neigh), sizeof(struct neigh_entry)); + for (iterator = neigh; iterator < &(neigh_table[N_NEIGH - 1]); iterator++) { + if (!IS_NEIGH_VALID(iterator + 1)) break; + swapNodes(iterator, iterator + 1); + } + + if (reset_default) { + // send new topology updates quickly to let an edge router know + // that something happened. + restartTrafficGen(); + default_route = &neigh_table[0]; + default_route_failures = 0; + } + + printTable(); + } + + // Typically called after an epoch change + void updateRankings() { + uint8_t i; + bool evicted = FALSE; + + for (i = 0; i < N_NEIGH; i++) { + UNSET_EVICT(neigh_table[i]); + if (!IS_NEIGH_VALID(&neigh_table[i])) continue; + neigh_table[i].stats[LONG_EPOCH].total += neigh_table[i].stats[SHORT_EPOCH].total; + neigh_table[i].stats[LONG_EPOCH].receptions += neigh_table[i].stats[SHORT_EPOCH].receptions; + neigh_table[i].stats[LONG_EPOCH].success += neigh_table[i].stats[SHORT_EPOCH].success; + + if (neigh_table[i].stats[LONG_EPOCH].total & (0xf000)) { + // if we're this big, the etx computation might overflow. + // Make it smaller by dividing top and bottom by 2. + neigh_table[i].stats[LONG_EPOCH].total >>= 1; + neigh_table[i].stats[LONG_EPOCH].success >>= 1; + } + + if (neigh_table[i].stats[LONG_EPOCH].total > CONF_EVICT_THRESHOLD) + SET_MATURE(&neigh_table[i]); + + if (IS_MATURE(&(neigh_table[i]))) { + uint16_t cost; + // if we didn't try the link, don't evict it + if (neigh_table[i].stats[SHORT_EPOCH].total == 0) goto done_iter; + if (neigh_table[i].stats[SHORT_EPOCH].success == 0) { + cost = 0xff; + } else { + cost = (10 * neigh_table[i].stats[SHORT_EPOCH].total) / + neigh_table[i].stats[SHORT_EPOCH].success; + } + if (cost > LINK_EVICT_THRESH) { + dbg("Evictions", "cost: 0x%x, slot %i\n", cost, i); + SET_EVICT(neigh_table[i]); + } + } + done_iter: + neigh_table[i].stats[SHORT_EPOCH].total = 0; + neigh_table[i].stats[SHORT_EPOCH].receptions = 0; + neigh_table[i].stats[SHORT_EPOCH].success = 0; + } + for (i = 0; i < N_NEIGH; i++) { + if (IS_NEIGH_VALID(&neigh_table[i]) && + SHOULD_EVICT(neigh_table[i])) { +#if 0 + // SDH : because of the overflow bug, this was never being + // triggered. I'm not sure it's actually a good idea because + // it seems to increase path lengths for heavily used routes. + // Let's disable it for now. + dbg("Evictions", "performing evict: %i\n", i); + evictNeighbor(&neigh_table[i]); + i --; +#endif + evicted = TRUE; + } + } + if (evicted) + call ICMP.sendSolicitations(); + } + + void swapNodes(struct neigh_entry *highNode, struct neigh_entry *lowNode) { + struct neigh_entry tempNode; + if (highNode == NULL || lowNode == NULL) return; + ip_memcpy(&tempNode, highNode, sizeof(struct neigh_entry)); + ip_memcpy(highNode, lowNode, sizeof(struct neigh_entry)); + ip_memcpy(lowNode, &tempNode, sizeof(struct neigh_entry)); + + if (highNode == default_route) default_route = lowNode; + else if (lowNode == default_route) default_route = highNode; + } + + uint8_t checkThresh(uint32_t firstVal, uint32_t secondVal, uint16_t thresh) { + if (((firstVal > secondVal) && ((firstVal - secondVal) <= thresh)) || + ((secondVal >= firstVal) && (secondVal - firstVal) <= thresh)) return WITHIN_THRESH; + if (((firstVal > secondVal) && ((firstVal - secondVal) > thresh))) return ABOVE_THRESH; + return BELOW_THRESH; + } +} diff --git a/tos/lib/net/blip/PrintfUART.h b/tos/lib/net/blip/PrintfUART.h new file mode 100644 index 00000000..2d7e39f6 --- /dev/null +++ b/tos/lib/net/blip/PrintfUART.h @@ -0,0 +1,368 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* + * Copyright (c) 2005 + * The President and Fellows of Harvard College. + * + * 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 University 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 UNIVERSITY 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 UNIVERSITY 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. + */ + +/* + * Writes printf like output to the UART. + * This works only on the AVR and MSP430 Microcontrollers! + *

+ * Note: For AVR we explicitly place the print statements in ROM; for + * MSP430 this is done by default! For AVR, if we don't place it + * explicitely in ROM, the statements will go in RAM, which will + * quickly cause a descent size program to run out of RAM. By default + * it doesn't disable the interupts; disabling the interupts when + * writing to the UART, slows down/makes the mote quite unresponsive, + * and can lead to problems! If you wish to disable all printfs to + * the UART, then comment the flag: PRINTFUART_ENABLED. + + *

+ * How to use:
+ *   // (0) In your Makefile, define PRINTFUART_ENABLED
+ *   CFLAGS += -DPRINTFUART_ENABLED
+ *   // (1) Call printfUART_init() from your initialization function 
+ *   //     to initialize the UART
+ *   printfUART_init();
+ *   // (2) Set your UART client to the correct baud rate.  Look at 
+ *   //     the comments in printfUART_init(), to figure out what 
+ *   //     baud to use for your particular mote
+ *
+ *   // (3) Send printf statements like this:
+ *   printfUART("Hello World, we are in year= %u\n", 2004);
+ *   printfUART("Printing uint32_t variable, value= %lu\n", 4294967295);
+ *
+ * Examples and caveats:
+ *   // (1) - Must use curly braces in single section statements.  
+ *            (Look in the app.c to see why -- hint: it's a macro)
+ *   if (x < 3)
+ *       {printfUART("The value of x is %i\n", x);}
+ *   // (2) - Otherwise it more or less works like regular printf
+ *   printfUART("\nThe value of x=%u, and y=%u\n", x, y); 
+ * 
+ *
URL: http://www.eecs.harvard.edu/~konrad/projects/motetrack
+ * @author Konrad Lorincz + * @version 2.0, January 5, 2005 + */ +#ifndef PRINTFUART_H +#define PRINTFUART_H +#include +#include + +// ------------------------------------------------------------------- +#ifdef PRINTFUART_ENABLED + #define DEBUGBUF_SIZE 256 + char debugbuf[DEBUGBUF_SIZE]; + char debugbufROMtoRAM[DEBUGBUF_SIZE]; + + #if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT) + #define printfUART(__format...) { \ + static const char strROM[] PROGMEM = __format; \ + strcpy_P((char*) &debugbufROMtoRAM, (PGM_P) &strROM); \ + sprintf(debugbuf, debugbufROMtoRAM); \ + writedebug(); \ + } + #else // assume MSP430 architecture (e.g. TelosA, TelosB, etc.) + #define printfUART(__format...) { \ + sprintf(debugbuf, __format); \ + writedebug(); \ + } + #endif +#else + #define printfUART(X, args...) dbg("printf", X, ## args) +// #define printfUART(__format...) {} + void printfUART_init() {} +#endif + +#define NOprintfUART(__format...) + + +// ------------------------------------------------------------------- +#ifdef PRINTFUART_ENABLED + +/** + * Initialize the UART port. Call this from your startup routine. + */ +#define printfUART_init() {atomic printfUART_init_private();} +void printfUART_init_private() +{ + #if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) + // 56K baud + outp(0,UBRR0H); + outp(15, UBRR0L); //set baud rate + outp((1< = STDRXD = ALT2(in) + GPIO<47> = STDTXD = ALT1(out) + *********/ + //atomic{ + + //configure the GPIO Alt functions and directions + _GPIO_setaltfn(46,2); // STD_RXD + _GPIO_setaltfn(47,1); // STD_TXD + + _GPDR(46) &= ~_GPIO_bit(46); // input + _GPDR(47) |= _GPIO_bit(47); // output + + STLCR |=LCR_DLAB; //turn on DLAB so we can change the divisor + STDLL = 8; //configure to 115200; + STDLH = 0; + STLCR &= ~(LCR_DLAB); //turn off DLAB + + STLCR |= 0x3; //configure to 8 bits + + STMCR &= ~MCR_LOOP; + STMCR |= MCR_OUT2; + STIER |= IER_RAVIE; + STIER |= IER_TIE; + STIER |= IER_UUE; //enable the UART + + //STMCR |= MCR_AFE; //Auto flow control enabled; + //STMCR |= MCR_RTS; + + STFCR |= FCR_TRFIFOE; //enable the fifos + +// call Interrupt.allocate(); +// call Interrupt.enable(); + //configure all the interrupt stuff + //make sure that the interrupt causes an IRQ not an FIQ + // __REG(0x40D00008) &= ~(1<<21); + //configure the priority as IPR1 + //__REG(0x40D00020) = (1<<31 | 21); + //unmask the interrupt + //__REG(0x40D00004) |= (1<<21); + + CKEN |= CKEN5_STUART; //enable the UART's clk + + + #else // assume TelosA, TelosB, etc. + // Variabel baud + // To change the baud rate, see /tos/platform/msp430/msp430baudrates.h + uint8_t source = SSEL_SMCLK; + uint16_t baudrate = 0x0012; // UBR_SMCLK_57600=0x0012 + uint8_t mctl = 0x84; // UMCTL_SMCLK_57600=0x84 + //uint16_t baudrate = 0x0009; // UBR_SMCLK_115200=0x0009 + //uint8_t mctl = 0x10; // UMCTL_SMCLK_115200=0x10 + + + uint16_t l_br = 0; + uint8_t l_mctl = 0; + uint8_t l_ssel = 0; + + TOSH_SEL_UTXD1_MODFUNC(); + TOSH_SEL_URXD1_MODFUNC(); + + + UCTL1 = SWRST; + UCTL1 |= CHAR; // 8-bit char, UART-mode + + U1RCTL &= ~URXEIE; // even erroneous characters trigger interrupts + + UCTL1 = SWRST; + UCTL1 |= CHAR; // 8-bit char, UART-mode + + if (l_ssel & 0x80) { + U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3); + U1TCTL |= (l_ssel & 0x7F); + } + else { + U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3); + U1TCTL |= SSEL_ACLK; // use ACLK, assuming 32khz + } + + if ((l_mctl != 0) || (l_br != 0)) { + U1BR0 = l_br & 0x0FF; + U1BR1 = (l_br >> 8) & 0x0FF; + U1MCTL = l_mctl; + } + else { + U1BR0 = 0x03; // 9600 baud + U1BR1 = 0x00; + U1MCTL = 0x4A; + } + + ME2 &= ~USPIE1; // USART1 SPI module disable + ME2 |= (UTXE1 | URXE1); // USART1 UART module enable + + U1CTL &= ~SWRST; + + IFG2 &= ~(UTXIFG1 | URXIFG1); + IE2 &= ~(UTXIE1 | URXIE1); // interrupt disabled + + + + //async command void USARTControl.setClockSource(uint8_t source) { + // atomic { + l_ssel = source | 0x80; + U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3); + U1TCTL |= (l_ssel & 0x7F); + // } + //} + //async command void USARTControl.setClockRate(uint16_t baudrate, uint8_t mctl) { + //atomic { + l_br = baudrate; + l_mctl = mctl; + U1BR0 = baudrate & 0x0FF; + U1BR1 = (baudrate >> 8) & 0x0FF; + U1MCTL = mctl; + //} + //} + + //async command result_t USARTControl.enableRxIntr(){ + //atomic { + IFG2 &= ~URXIFG1; + IE2 |= URXIE1; + //} + //return SUCCESS; + //} + + //async command result_t USARTControl.enableTxIntr(){ + //atomic { + IFG2 &= ~UTXIFG1; + IE2 |= UTXIE1; + //} + //return SUCCESS; + //} + + #endif + #endif + #endif +} + +#if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT) +#else +#if defined(PLATFORM_IMOTE2) +#else // assume AVR architecture (e.g. TelosA, TelosB) + bool isTxIntrPending() + { + if (U1TCTL & TXEPT) { + return TRUE; + } + return FALSE; + } +#endif +#endif + +/** + * Outputs a char to the UART. + */ +void UARTPutChar(char c) +{ + if (c == '\n') + UARTPutChar('\r'); + + + #if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT) + loop_until_bit_is_set(UCSR0A, UDRE); + outb(UDR0,c); + + #else + #if defined(PLATFORM_IMOTE2) + STTHR = c; + + #else // assume AVR architecture (e.g. TelosA, TelosB) + U1TXBUF = c; + while( !isTxIntrPending() ) + continue; + #endif + #endif +} + +/** + * Outputs the entire debugbuf to the UART, or until it encounters '\0'. + */ +void writedebug() +{ + uint16_t i = 0; + + while (debugbuf[i] != '\0' && i < DEBUGBUF_SIZE) + UARTPutChar(debugbuf[i++]); +} + +#endif // PRINTFUART_ENABLED +// ------------------------------------------------------------------- + +#if 0 +// -------------------------------------------------------------- +#define assertUART(x) if (!(x)) { __assertUART(__FILE__, __LINE__); } +void __assertUART(const char* file, int line) +{ + printfUART("ASSERT FAILED: file= %s, lineNbr= %i\n", file, line); + // for some reason, CLR means on + TOSH_MAKE_RED_LED_OUTPUT(); + TOSH_MAKE_YELLOW_LED_OUTPUT(); + TOSH_MAKE_GREEN_LED_OUTPUT(); + TOSH_CLR_RED_LED_PIN(); + TOSH_CLR_YELLOW_LED_PIN(); + TOSH_CLR_GREEN_LED_PIN(); + exit(1); +} +// -------------------------------------------------------------- +#endif + +#endif // PRINTFUART_H + diff --git a/tos/lib/net/blip/TcpC.nc b/tos/lib/net/blip/TcpC.nc new file mode 100644 index 00000000..87a21673 --- /dev/null +++ b/tos/lib/net/blip/TcpC.nc @@ -0,0 +1,17 @@ + +configuration TcpC { + provides interface Tcp[uint8_t client]; +} implementation { + + components MainC, IPDispatchC, TcpP, IPAddressC; + components new TimerMilliC(); + + Tcp = TcpP; + + MainC -> TcpP.Init; + TcpP.Boot -> MainC; + TcpP.IP -> IPDispatchC.IP[IANA_TCP]; + + TcpP.Timer -> TimerMilliC; + TcpP.IPAddress -> IPAddressC; +} diff --git a/tos/lib/net/blip/TcpP.nc b/tos/lib/net/blip/TcpP.nc new file mode 100644 index 00000000..f594914e --- /dev/null +++ b/tos/lib/net/blip/TcpP.nc @@ -0,0 +1,177 @@ + +#include +#include + +module TcpP { + provides interface Tcp[uint8_t client]; + provides interface Init; + uses { + interface Boot; + + interface IP; + interface Timer; + interface IPAddress; + } +} implementation { + + enum { + N_CLIENTS = uniqueCount("TCP_CLIENT"), + }; + +#include + struct tcplib_sock socks[N_CLIENTS]; + + int find_client(struct tcplib_sock *conn) { + int i; + for (i = 0; i < N_CLIENTS; i++) + if (&socks[i] == conn) break; + + return i; + } + + void conn_d(struct tcplib_sock *sock, int error) { + int cid = find_client(sock); + if (cid < N_CLIENTS) + signal Tcp.connectDone[cid](error == 0); + } + + void rx(struct tcplib_sock *sock, void *data, int len) { + int cid = find_client(sock); + if (cid < N_CLIENTS) + signal Tcp.recv[cid](data, len); + } + + void cl(struct tcplib_sock *sock) { + tcplib_close(sock); + } + + void cd(struct tcplib_sock *sock) { + int cid = find_client(sock); + tcplib_init_sock(sock); + if (cid < N_CLIENTS) + signal Tcp.closed[cid](0); + } + + void init_ops(struct tcplib_sock *sock) { + sock->ops.connect_done = conn_d; + sock->ops.recvfrom = rx; + sock->ops.closed = cl; + sock->ops.close_done = cd; + } + + + + void setSrcAddr(struct split_ip_msg *msg) { + if (msg->hdr.ip6_dst.s6_addr16[0] == htons(0xff02) || + msg->hdr.ip6_dst.s6_addr16[0] == htons(0xfe80)) { +// (msg->hdr.dst_addr[0] == 0xff && (msg->hdr.dst_addr[1] & 0xf) == 0x2) || +// (msg->hdr.dst_addr[0] == 0xfe && msg->hdr.dst_addr[2] == 0x80)) { + call IPAddress.getLLAddr(&msg->hdr.ip6_src); + } else { + call IPAddress.getIPAddr(&msg->hdr.ip6_src); + } + } + + struct tcplib_sock socks[uniqueCount("TCP_CLIENT")]; + + struct tcplib_sock *tcplib_accept(struct tcplib_sock *conn, + struct sockaddr_in6 *from) { + void *rx_buf = NULL, *tx_buf = NULL; + int rx_buf_len, tx_buf_len; + int cid = find_client(conn); + + printfUART("tcplib_accept: cid: %i\n", cid); + + if (cid == N_CLIENTS) return NULL; + if (signal Tcp.accept[cid](from, &rx_buf, &rx_buf_len, + &tx_buf, &tx_buf_len)) { + if (rx_buf == NULL || tx_buf == NULL) return NULL; + conn->rx_buf = rx_buf; + conn->rx_buf_len = rx_buf_len; + conn->tx_buf = tx_buf; + conn->tx_buf_len = tx_buf_len; + init_ops(conn); + return conn; + } + return NULL; + } + + void tcplib_send_out(struct split_ip_msg *msg, struct tcp_hdr *tcph) { + printfUART("tcp output\n"); + setSrcAddr(msg); + tcph->chksum = htons(msg_cksum(msg, IANA_TCP)); + call IP.send(msg); + } + +#include "circ.c" +#include "tcplib.c" + + command error_t Init.init() { + int i; + for (i = 0; i < uniqueCount("TCP_CLIENT"); i++) { + tcplib_init_sock(&socks[i]); + } + return SUCCESS; + } + + event void Boot.booted() { + call Timer.startPeriodic(512); + } + + event void Timer.fired() { + tcplib_timer_process(); + } + + event void IP.recv(struct ip6_hdr *iph, + void *payload, + struct ip_metadata *meta) { + + printfUART("tcp packet received\n"); + tcplib_process(iph, payload); + } + + + command error_t Tcp.bind[uint8_t client](uint16_t port) { + struct sockaddr_in6 addr; + ip_memclr(addr.sin6_addr.s6_addr, 16); + addr.sin6_port = htons(port); + tcplib_bind(&socks[client], &addr); + return SUCCESS; + } + + command error_t Tcp.connect[uint8_t client](struct sockaddr_in6 *dest, + void *rx_buf, int rx_buf_len, + void *tx_buf, int tx_buf_len) { + socks[client].rx_buf; + socks[client].rx_buf_len = rx_buf_len; + socks[client].tx_buf = tx_buf; + socks[client].tx_buf_len = tx_buf_len; + tcplib_connect(&socks[client], dest); + } + + command error_t Tcp.send[uint8_t client](void *payload, uint16_t len) { + tcplib_send(&socks[client], payload, len); + return SUCCESS; + } + + command error_t Tcp.close[uint8_t client]() { + if (!tcplib_close(&socks[client])) + return SUCCESS; + return FAIL; + } + + default event bool Tcp.accept[uint8_t cid](struct sockaddr_in6 *from, + void **rx_buf, int *rx_buf_len, + void **tx_buf, int *tx_buf_len) { + return FALSE; + } + + default event void Tcp.connectDone[uint8_t cid](error_t e) {} + default event void Tcp.recv[uint8_t cid](void *payload, uint16_t len) { } + default event void Tcp.closed[uint8_t cid](error_t e) { } + + + + + +} diff --git a/tos/lib/net/blip/TcpSocketC.nc b/tos/lib/net/blip/TcpSocketC.nc new file mode 100644 index 00000000..1c832f1f --- /dev/null +++ b/tos/lib/net/blip/TcpSocketC.nc @@ -0,0 +1,11 @@ + + +generic configuration TcpSocketC() { + provides interface Tcp; +} implementation { + + components TcpC; + + Tcp = TcpC.Tcp[unique("TCP_CLIENT")]; + +} diff --git a/tos/lib/net/blip/UdpC.nc b/tos/lib/net/blip/UdpC.nc new file mode 100644 index 00000000..31cb2170 --- /dev/null +++ b/tos/lib/net/blip/UdpC.nc @@ -0,0 +1,12 @@ + +configuration UdpC { + provides interface UDP[uint8_t clnt]; +} implementation { + + components MainC, IPDispatchC, UdpP, IPAddressC; + UDP = UdpP; + + MainC -> UdpP.Init; + UdpP.IP -> IPDispatchC.IP[IANA_UDP]; + UdpP.IPAddress -> IPAddressC; +} diff --git a/tos/lib/net/blip/UdpP.nc b/tos/lib/net/blip/UdpP.nc new file mode 100644 index 00000000..8cb0e5fb --- /dev/null +++ b/tos/lib/net/blip/UdpP.nc @@ -0,0 +1,154 @@ + +#include +#include + +module UdpP { + provides interface UDP[uint8_t clnt]; + provides interface Init; + uses interface IP; + uses interface IPAddress; +} implementation { + + enum { + N_CLIENTS = uniqueCount("UDP_CLIENT"), + }; + + uint16_t local_ports[N_CLIENTS]; + + enum { + LOCAL_PORT_START = 51024U, + LOCAL_PORT_STOP = 54999U, + }; + uint16_t last_localport = LOCAL_PORT_START; + + uint16_t alloc_lport(uint8_t clnt) { + int i, done = 0; + uint16_t compare = htons(last_localport); + last_localport = (last_localport < LOCAL_PORT_START) ? last_localport + 1 : LOCAL_PORT_START; + while (!done) { + done = 1; + for (i = 0; i < N_CLIENTS; i++) { + if (local_ports[i] == compare) { + last_localport = (last_localport < LOCAL_PORT_START) ? last_localport + 1 : LOCAL_PORT_START; + compare = htons(last_localport); + done = 0; + break; + } + } + } + return last_localport; + } + + command error_t Init.init() { + ip_memclr((uint8_t *)local_ports, sizeof(uint16_t) * N_CLIENTS); + return SUCCESS; + } + + void setSrcAddr(struct split_ip_msg *msg) { + if (msg->hdr.ip6_dst.s6_addr16[7] == htons(0xff02) || + msg->hdr.ip6_dst.s6_addr16[7] == htons(0xfe80)) { + call IPAddress.getLLAddr(&msg->hdr.ip6_src); + } else { + call IPAddress.getIPAddr(&msg->hdr.ip6_src); + } + } + + + command error_t UDP.bind[uint8_t clnt](uint16_t port) { + int i; + port = htons(port); + for (i = 0; i < N_CLIENTS; i++) + if (i != clnt && local_ports[i] == port) + return FAIL; + local_ports[clnt] = port; + return SUCCESS; + } + + + event void IP.recv(struct ip6_hdr *iph, + void *payload, + struct ip_metadata *meta) { + int i; + struct sockaddr_in6 addr; + struct udp_hdr *udph = (struct udp_hdr *)payload; + + dbg("UDP", "UDP - IP.recv: len: %i srcport: %i dstport: %i\n", + ntohs(iph->plen), ntohs(udph->srcport), ntohs(udph->dstport)); + + for (i = 0; i < N_CLIENTS; i++) + if (local_ports[i] == udph->dstport) + break; + + if (i == N_CLIENTS) { + // TODO : send ICMP port closed message here. + return; + } + ip_memcpy(&addr.sin6_addr, &iph->ip6_src, 16); + addr.sin6_port = udph->srcport; + + signal UDP.recvfrom[i](&addr, (void *)(udph + 1), ntohs(iph->plen) - sizeof(struct udp_hdr), meta); + } + + /* + * Injection point of IP datagrams. This is only called for packets + * being sent from this mote; packets which are being forwarded + * never lave the stack and so never use this entry point. + * + * @msg an IP datagram with header fields (except for length) + * @plen the length of the data payload added after the headers. + */ + command error_t UDP.sendto[uint8_t clnt](struct sockaddr_in6 *dest, void *payload, + uint16_t len) { + struct split_ip_msg *msg; + struct udp_hdr *udp; + struct generic_header *g_udp; + error_t rc; + + // todo check + alloc local port + + msg = (struct split_ip_msg *)ip_malloc(sizeof(struct split_ip_msg) + + sizeof(struct udp_hdr) + + sizeof(struct generic_header)); + + if (msg == NULL) { + dbg("Drops", "drops: UDP send: malloc failure\n"); + return ERETRY; + } + udp = (struct udp_hdr *)(msg + 1); + g_udp = (struct generic_header *)(udp + 1); + + // fill in all the packet fields + ip_memclr((uint8_t *)&msg->hdr, sizeof(struct ip6_hdr)); + ip_memclr((uint8_t *)udp, sizeof(struct udp_hdr)); + + setSrcAddr(msg); + memcpy(&msg->hdr.ip6_dst, dest->sin6_addr.s6_addr, 16); + + if (local_ports[clnt] == 0 && alloc_lport(clnt) == 0) return FAIL; + udp->srcport = local_ports[clnt]; + udp->dstport = dest->sin6_port; + udp->len = htons(len + sizeof(struct udp_hdr)); + udp->chksum = 0; + + // set up the pointers + g_udp->len = sizeof(struct udp_hdr); + g_udp->hdr.udp = udp; + g_udp->next = NULL; + msg->headers = g_udp; + msg->data_len = len; + msg->data = payload; + + udp->chksum = htons(msg_cksum(msg, IANA_UDP)); + + rc = call IP.send(msg); + + ip_free(msg); + return rc; + + } + + default event void UDP.recvfrom[uint8_t clnt](struct sockaddr_in6 *from, void *payload, + uint16_t len, struct ip_metadata *meta) { + + } +} diff --git a/tos/lib/net/blip/UdpSocketC.nc b/tos/lib/net/blip/UdpSocketC.nc new file mode 100644 index 00000000..e4323b7d --- /dev/null +++ b/tos/lib/net/blip/UdpSocketC.nc @@ -0,0 +1,9 @@ + +generic configuration UdpSocketC() { + provides interface UDP; +} implementation { + + components UdpC; + + UDP = UdpC.UDP[unique("UDP_CLIENT")]; +} diff --git a/tos/lib/net/blip/interfaces/ICMP.nc b/tos/lib/net/blip/interfaces/ICMP.nc new file mode 100644 index 00000000..c1de09ff --- /dev/null +++ b/tos/lib/net/blip/interfaces/ICMP.nc @@ -0,0 +1,37 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +interface ICMP { + + command uint16_t cksum(struct split_ip_msg *msg, uint8_t nxt_hdr); + + // called to start sending router solicitations + command void sendSolicitations(); + + // called when we are done sending router solicitations + event void solicitationDone(); + + command void sendAdvertisements(); + + command void sendTimeExceeded(struct ip6_hdr *hdr, unpack_info_t *u_info, uint16_t amount_here); + +} diff --git a/tos/lib/net/blip/interfaces/ICMPPing.nc b/tos/lib/net/blip/interfaces/ICMPPing.nc new file mode 100644 index 00000000..24fc1ec9 --- /dev/null +++ b/tos/lib/net/blip/interfaces/ICMPPing.nc @@ -0,0 +1,12 @@ + +#include + +interface ICMPPing { + + command error_t ping(struct in6_addr *target, uint16_t period, uint16_t n); + + event void pingReply(struct in6_addr *source, struct icmp_stats *stats); + + event void pingDone(uint16_t ping_rcv, uint16_t ping_n); + +} diff --git a/tos/lib/net/blip/interfaces/IP.nc b/tos/lib/net/blip/interfaces/IP.nc new file mode 100644 index 00000000..05214b7a --- /dev/null +++ b/tos/lib/net/blip/interfaces/IP.nc @@ -0,0 +1,23 @@ + +interface IP { + + /* + * sends the message with the headers and payload given. Things + * which we know how to compress should be part of the data passed + * in as headers; things which we cannot compress must be passed as + * payload. + + * the interface is this way so that the stack may insert extra + * (routing, snooping) headers between the two sections. + * once the call returns, the stack has no claim on the buffer + * pointed to + */ + command error_t send(struct split_ip_msg *msg); + + /* + * indicate that the stack has finished writing data into the + * receive buffer. + */ + event void recv(struct ip6_hdr *iph, void *payload, struct ip_metadata *meta); + +} diff --git a/tos/lib/net/blip/interfaces/IPAddress.nc b/tos/lib/net/blip/interfaces/IPAddress.nc new file mode 100644 index 00000000..38d30846 --- /dev/null +++ b/tos/lib/net/blip/interfaces/IPAddress.nc @@ -0,0 +1,35 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#include <6lowpan.h> + +interface IPAddress { + command hw_addr_t getShortAddr(); + command void setShortAddr(hw_addr_t newaddr); + + command struct in6_addr *getPublicAddr(); + command void getLLAddr(struct in6_addr *addr); + command void getIPAddr(struct in6_addr *addr); + + command void setPrefix(uint8_t *prefix); + + command bool haveAddress(); +} diff --git a/tos/lib/net/blip/interfaces/IPRouting.nc b/tos/lib/net/blip/interfaces/IPRouting.nc new file mode 100644 index 00000000..8c0f4dd6 --- /dev/null +++ b/tos/lib/net/blip/interfaces/IPRouting.nc @@ -0,0 +1,94 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +/* + * This interface presents the interface to the IP routing engine. + * Related interfaces are the forwarding engine, which implements + * the routing decision whare are communicated by this interface, + * and the ICMP interface, which deals with sending and receiving + * ICMP traffic. + * + */ + +#include "IPDispatch.h" + +interface IPRouting { + /* + * returns weather or not the node should consume a packet addressed + * to a given address. Interprets link-local and global addresses, + * and manages multicast group membership. + */ + command bool isForMe(struct ip6_hdr *a); + + /* + * returns a policy for sending this message to someone else. + * the send policy includes the layer 2 address, number of retransmissions, + * and spacing between them. + * + */ + command error_t getNextHop(struct ip6_hdr *hdr, + struct source_header *sh, + hw_addr_t prev_hop, + send_policy_t *ret); + + + /* + * returns the currently configured default IP hop limit. + * + */ + command uint8_t getHopLimit(); + + command uint16_t getQuality(); + + /* + * + * + */ + command void reportAdvertisement(hw_addr_t neigh, uint8_t hops, + uint8_t lqi, uint16_t cost); + + /* + * informs the router of a reception from a neighbor, along with the + * the rssi of the received packet. + * + */ + command void reportReception(hw_addr_t neigh, uint8_t lqi); + + /* + * the result of sending to a neighbor. + */ + command void reportTransmission(send_policy_t *send); + + /* + * @returns TRUE if the routing engine has established a default route. + */ + command bool hasRoute(); + + command void insertRoutingHeaders(struct split_ip_msg *msg); + +#ifdef CENTRALIZED_ROUTING + command error_t installFlowEntry(struct rinstall_header* rih, bool isMine); + + command void clearFlows(); +#endif + +} diff --git a/tos/lib/net/blip/interfaces/Statistics.nc b/tos/lib/net/blip/interfaces/Statistics.nc new file mode 100644 index 00000000..230a6bec --- /dev/null +++ b/tos/lib/net/blip/interfaces/Statistics.nc @@ -0,0 +1,36 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + + +interface Statistics { + + /* + * Fills the given structure with the requested statistics. + */ + command void get(stat_str *stats); + + /* + * Reset whatever statistics are being collected. + */ + command void clear(); + +} diff --git a/tos/lib/net/blip/interfaces/Tcp.nc b/tos/lib/net/blip/interfaces/Tcp.nc new file mode 100644 index 00000000..25f66ecb --- /dev/null +++ b/tos/lib/net/blip/interfaces/Tcp.nc @@ -0,0 +1,46 @@ + + +interface Tcp { + + /* + * Bind the socket to a local address + */ + command error_t bind(uint16_t port); + + /* + * Accept an incomming connection. + */ + event bool accept(struct sockaddr_in6 *from, + void **rx_buf, int *rx_buf_len, + void **tx_buf, int *tx_buf_len); + + /* + * Split-phase connect: connect to a remote endpoint. + * + * The socket should not be used until connectDone is signaled. + */ + command error_t connect(struct sockaddr_in6 *dest, + void *rx_buf, int rx_buf_len, + void *tx_buf, int tx_buf_len); + event void connectDone(error_t e); + + /* + * Send and receive data on a socket. The socket must be CONNECTed + * for these to succeed. + */ + command error_t send(void *payload, uint16_t len); + + event void recv(void *payload, uint16_t len); + + /* + * terminate a connection. + */ + command error_t close(); + + /* + * notify the app that the socket connection has been closed or + * reset by the other end, or else a timeout has occured and the + * local side has given up. + */ + event void closed(error_t e); +} diff --git a/tos/lib/net/blip/interfaces/UDP.nc b/tos/lib/net/blip/interfaces/UDP.nc new file mode 100644 index 00000000..a2db7cfc --- /dev/null +++ b/tos/lib/net/blip/interfaces/UDP.nc @@ -0,0 +1,27 @@ + +interface UDP { + /* + * bind a local address. to cut down memory requirements and handle the + * common case well, you can only bind a port; all local interfaces are + * implicitly bound. the port should be passed in host byte-order (is + * this confusing? + */ + + command error_t bind(uint16_t port); + + /* + * send a payload to the socket address indicated + * once the call returns, the stack has no claim on the buffer pointed to + */ + command error_t sendto(struct sockaddr_in6 *dest, void *payload, + uint16_t len); + + /* + * indicate that the stack has finished writing data into the + * receive buffer. if error is not SUCCESS, the payload does not + * contain valid data and the src pointer should not be used. + */ + event void recvfrom(struct sockaddr_in6 *src, void *payload, + uint16_t len, struct ip_metadata *meta); + +} diff --git a/tos/lib/net/blip/nwprog/BootImage.nc b/tos/lib/net/blip/nwprog/BootImage.nc new file mode 100644 index 00000000..034d1b07 --- /dev/null +++ b/tos/lib/net/blip/nwprog/BootImage.nc @@ -0,0 +1,8 @@ + +interface BootImage { + command void reboot(); + command error_t boot(uint8_t img_num); + + // Added by Jaein Jeong + command error_t erase(uint8_t img_num); +} diff --git a/tos/lib/net/blip/nwprog/Deluge.h b/tos/lib/net/blip/nwprog/Deluge.h new file mode 100644 index 00000000..1a0e99ef --- /dev/null +++ b/tos/lib/net/blip/nwprog/Deluge.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Chieh-Jan Mike Liang + * @author Razvan Musaloiu-E. + */ + +#ifndef __DELUGE_H__ +#define __DELUGE_H__ + +typedef nx_struct DelugeIdent { + nx_uint32_t uidhash; // unique id of the image + nx_uint32_t size; // size of the whole image (ident + CRCs + binary) + nx_uint8_t numPgs; // number of pages of complete image + nx_uint8_t reserved; + nx_uint16_t crc; // crc over the above 4 fields + nx_uint8_t appname[16]; + nx_uint8_t username[16]; + nx_uint8_t hostname[16]; + nx_uint8_t platform[16]; + nx_uint32_t timestamp; + nx_uint32_t userhash; +} DelugeIdent; + +typedef nx_struct DelugePatchCmd { + nx_uint16_t linenum; // sequence number of patches, starting from 0 + nx_uint8_t cmd; // patch cmd: 16 for upload, 17 for copy + nx_uint16_t dst_offset; + nx_uint16_t data_length; // byte length of the data + nx_uint16_t src_offset; + nx_uint8_t reserved[7]; + nx_uint8_t data[0]; // data for the upload command +} DelugePatchCmd; + +enum { + DELUGE_INVALID_UID = 0xffffffff, + DELUGE_NUM_VOLUMES = 4, + DELUGE_IDENT_SIZE = 128, + DELUGE_MAX_PAGES = 128, + DELUGE_CRC_SIZE = sizeof(uint16_t), + DELUGE_CRC_BLOCK_SIZE = DELUGE_MAX_PAGES * DELUGE_CRC_SIZE, + DELUGE_BYTES_PER_PAGE = 23 * 48, +}; + +enum { + MAX_PATCH_DATA_SIZE = 512, + PATCH_LINE_SIZE = 16, +}; + +#define UQ_DELUGE_METADATA "DelugeMetadata.client" +#define UQ_DELUGE_VOLUME_MANAGER "DelugeVolumeManager.client" +#define UQ_DELUGE_VERIFY "DelugeVerify.client" +#define UQ_DELUGE_PATCH "DelugePatch.client" +#define UQ_DELUGE_READ_IDENT "DelugeReadIdent.client" + +typedef struct BootArgs { + uint16_t address; + uint32_t imageAddr; + uint8_t gestureCount; + bool noReprogram; +} BootArgs; + +enum { + NWPROG_CMD_ERASE = 1, + NWPROG_CMD_WRITE = 2, +}; + +enum{ + PATCH_CMD_UPLOAD = 16, + PATCH_CMD_COPY = 17, +}; + +typedef nx_struct prog_req { + nx_uint8_t cmd; + nx_uint8_t imgno; + nx_uint16_t offset; + nx_uint8_t data[0]; +} prog_req_t; + +typedef nx_struct prog_reply { + nx_uint8_t error; + nx_struct prog_req req; +} prog_reply_t; + +#endif diff --git a/tos/lib/net/blip/nwprog/DelugePatch.nc b/tos/lib/net/blip/nwprog/DelugePatch.nc new file mode 100644 index 00000000..ae94655f --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugePatch.nc @@ -0,0 +1,14 @@ +/** + * An interface for obtaining the identification data of an + * image. The pointer returned by readDone will be destroyed by the + * next read. + * + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +interface DelugePatch +{ + command error_t decodePatch(uint8_t imgNumPatch, uint8_t imgNumSrc, uint8_t imgNumDst); + event void decodePatchDone(uint8_t imgNumPatch, uint8_t imgNumSrc, uint8_t imgNumDst, error_t error); +} diff --git a/tos/lib/net/blip/nwprog/DelugePatchC.nc b/tos/lib/net/blip/nwprog/DelugePatchC.nc new file mode 100644 index 00000000..1c901db9 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugePatchC.nc @@ -0,0 +1,60 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +configuration DelugePatchC +{ + provides interface DelugePatch[uint8_t client]; + uses event void storageReady(); +} + +implementation +{ + components MainC; + components DelugePatchP; + + DelugePatch = DelugePatchP; + storageReady = DelugePatchP; + + components new BlockReaderC(VOLUME_GOLDENIMAGE) as BlockReaderGoldenImage; + components new BlockReaderC(VOLUME_DELUGE1) as BlockReaderDeluge1; + components new BlockReaderC(VOLUME_DELUGE2) as BlockReaderDeluge2; + components new BlockReaderC(VOLUME_DELUGE3) as BlockReaderDeluge3; + + DelugePatchP.BlockRead[VOLUME_GOLDENIMAGE] -> BlockReaderGoldenImage; + DelugePatchP.BlockRead[VOLUME_DELUGE1] -> BlockReaderDeluge1; + DelugePatchP.BlockRead[VOLUME_DELUGE2] -> BlockReaderDeluge2; + DelugePatchP.BlockRead[VOLUME_DELUGE3] -> BlockReaderDeluge3; + + components new BlockWriterC(VOLUME_GOLDENIMAGE) as BlockWriterGoldenImage; + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; + + DelugePatchP.BlockWrite[VOLUME_GOLDENIMAGE] -> BlockWriterGoldenImage; + DelugePatchP.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + DelugePatchP.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + DelugePatchP.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; +} diff --git a/tos/lib/net/blip/nwprog/DelugePatchClientC.nc b/tos/lib/net/blip/nwprog/DelugePatchClientC.nc new file mode 100644 index 00000000..999c55a8 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugePatchClientC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic configuration DelugePatchClientC() +{ + provides interface DelugePatch; +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_DELUGE_PATCH) + }; + + components DelugePatchC; + DelugePatch = DelugePatchC.DelugePatch[CLIENT_ID]; +} diff --git a/tos/lib/net/blip/nwprog/DelugePatchP.nc b/tos/lib/net/blip/nwprog/DelugePatchP.nc new file mode 100644 index 00000000..d2c78785 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugePatchP.nc @@ -0,0 +1,244 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "imgNum2volumeId.h" + +module DelugePatchP +{ + provides interface DelugePatch[uint8_t client]; + uses { + interface BlockRead[uint8_t volumeId]; + interface BlockWrite[uint8_t volumeId]; + interface StorageMap[uint8_t volumeId]; + event void storageReady(); + } +} + +implementation +{ + enum { + S_READ_IDENT, + S_READY, + S_BUSY, + S_READ_PATCH_CMD, + S_READ_PATCH_DATA, + S_READ_PATCH_COPY, + S_WRITE_PATCH, + }; + + DelugeIdent ident; + DelugePatchCmd patch; + + uint8_t patchData[MAX_PATCH_DATA_SIZE]; + + uint8_t state; + uint8_t currentClient; + + uint16_t patchNumLinesRead; + uint16_t patchNumLines; + + uint32_t patchByteAddr; + uint8_t patchVolume; + uint8_t patchImageIdx; + uint8_t patchPage; + + uint32_t dstByteAddr; + uint8_t srcVolume; + uint8_t srcImageIdx; + uint8_t srcPage; + + uint32_t dstByteAddr; + uint8_t dstVolume; + uint8_t dstImageIdx; + uint8_t dstPage; + + + void setStorageReady() + { + signal storageReady(); + state = S_READY; + } + + void notifySuccess() + { + signal DelugePatch.decodePatchDone[currentClient]( + patchImageIdx, srcImageIdx, dstImageIdx, SUCCESS); + setStorageReady(); + } + + void notifyFailure(error_t error) + { + signal DelugePatch.decodePatchDone[currentClient]( + patchImageIdx, srcImageIdx, dstImageIdx, error); + setStorageReady(); + } + + command error_t DelugePatch.decodePatch[uint8_t client](uint8_t imgNumPatch, + uint8_t imgNumSrc, + uint8_t imgNumDst) + { + patchImageIdx = imgNumPatch; + patchVolume = _imgNum2volumeId[patchImageIdx]; + srcImageIdx = imgNumSrc; + srcVolume = _imgNum2volumeId[srcImageIdx]; + dstImageIdx = imgNumDst; + dstVolume = _imgNum2volumeId[dstImageIdx]; + + // First, read the DelugeIdent section. + if (patchImageIdx < DELUGE_NUM_VOLUMES) { + state = S_READ_IDENT; + call BlockRead.read[patchVolume](0, &ident, sizeof(ident)); + } else { + signal storageReady(); + state = S_READY; + } + + return SUCCESS; + } + + event void BlockRead.readDone[uint8_t imgNum]( + storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + switch (state) { + case S_BUSY: + notifyFailure(error); + break; + // Read the DelugeIdent structure into ident. + // If it is valid, ident.userhash contains + // number of patch command lines. + // Initialize patchByteAddr to the beginning of + // the patch commands. + case S_READ_IDENT: + if (error == SUCCESS) { + if (ident.uidhash != DELUGE_INVALID_UID) { + patchNumLines = ident.userhash; + state = S_READ_PATCH_CMD; + patchByteAddr = DELUGE_IDENT_SIZE + DELUGE_CRC_BLOCK_SIZE; + call BlockRead.read[patchVolume](patchByteAddr, &patch, sizeof(patch)); + break; + } + } + notifyFailure(error); + break; + // Read a patch command. + // If successful, check it is UPLOAD or COPY. + // For an UPLOAD commandy + // increment the number of patch lines read, + // increase patchByteAddr by PATCH_LINE_SIZE, + // and read the patch data. + // For a COPY command, + // increment the number of patch lines read, + // increase patchByteAddr by PATCH_LINE_SIZE, + // and read data from the source volume. + case S_READ_PATCH_CMD: + if (error == SUCCESS) { + if (patch.cmd == PATCH_CMD_UPLOAD) { + patchNumLinesRead++; + patchByteAddr += PATCH_LINE_SIZE; // read the next line of patch + state = S_READ_PATCH_DATA; + call BlockRead.read[patchVolume](patchByteAddr, patchData, patch.data_length); + break; + } + else if (patch.cmd == PATCH_CMD_COPY) { + patchNumLinesRead++; + patchByteAddr += PATCH_LINE_SIZE; // read the next line of patch + state = S_READ_PATCH_COPY; + call BlockRead.read[srcVolume](patch.src_offset, patchData, patch.data_length); + break; + } + } + notifyFailure(error); + break; + // When the patch data of PATCH_UPLOAD is ready, + // increase patchByteAddr ceiling(len / PATCH_LINE_SIZE) * PATCH_LINE_SIZE, + // and write it into the destination volume. + case S_READ_PATCH_DATA: + if (error == SUCCESS) { + state = S_WRITE_PATCH; + patchByteAddr += ((len + PATCH_LINE_SIZE - 1) / PATCH_LINE_SIZE * PATCH_LINE_SIZE); + call BlockWrite.write[dstVolume](patch.dst_offset, buf, len); + break; + } + notifyFailure(error); + break; + // When the source data of PATCH_COPY is ready, + // write it into the destination volume. + case S_READ_PATCH_COPY: + if (error == SUCCESS) { + state = S_WRITE_PATCH; + call BlockWrite.write[dstVolume](patch.dst_offset, buf, len); + break; + } + notifyFailure(error); + break; + } + } + + event void BlockWrite.writeDone[uint8_t imgNum]( + storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + switch (state) { + case S_WRITE_PATCH: + if (error == SUCCESS) { + // When more patch commands remaining, read the next one. + if (patchNumLinesRead < patchNumLines) { + state = S_READ_PATCH_CMD; + call BlockRead.read[patchVolume](patchByteAddr, &patch, sizeof(patch)); + } + else { + notifySuccess(); + } + break; + } + notifyFailure(error); + break; + } + } + + event void BlockWrite.eraseDone[uint8_t imgNum](error_t error) + { + switch (state) { + case S_READY: + signal BlockWrite.eraseDone[imgNum](error); + break; + } + } + + default command error_t BlockWrite.write[uint8_t imgNum]( + storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockRead.read[uint8_t imgNum]( + storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockRead.computeCrc[uint8_t imgNum]( + storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + event void BlockRead.computeCrcDone[uint8_t imgNum]( + storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) {} + event void BlockWrite.syncDone[uint8_t imgNum](error_t error) {} + default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; } + default event void storageReady() {} + default event void DelugePatch.decodePatchDone[uint8_t client]( + uint8_t imgNumPatch, uint8_t imgNumSrc, uint8_t imgNumDst, error_t error) {} + +} diff --git a/tos/lib/net/blip/nwprog/DelugeReadIdent.nc b/tos/lib/net/blip/nwprog/DelugeReadIdent.nc new file mode 100644 index 00000000..efa1c1a1 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeReadIdent.nc @@ -0,0 +1,20 @@ +/** + * An interface for obtaining the identification data of an + * image. The pointer returned by readDone will be destroyed by the + * next read. + * + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +interface DelugeReadIdent +{ + command error_t readNumVolumes(); + command error_t readVolume(uint8_t imgNum); + + event void readNumVolumesDone(uint8_t validVolumes, uint8_t volumeFields, error_t error); + event void readVolumeDone(uint8_t imgNum, DelugeIdent* ident, error_t error); + + //command error_t read(uint8_t imgNum); + //event void readDone(uint8_t imgNum, DelugeIdent* ident, error_t error); +} diff --git a/tos/lib/net/blip/nwprog/DelugeReadIdentC.nc b/tos/lib/net/blip/nwprog/DelugeReadIdentC.nc new file mode 100644 index 00000000..2656e62f --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeReadIdentC.nc @@ -0,0 +1,51 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +configuration DelugeReadIdentC +{ + provides interface DelugeReadIdent[uint8_t client]; + uses event void storageReady(); +} + +implementation +{ + components MainC; + components DelugeReadIdentP; + + DelugeReadIdent = DelugeReadIdentP; + storageReady = DelugeReadIdentP; + DelugeReadIdentP.Boot -> MainC; + + components new BlockReaderC(VOLUME_GOLDENIMAGE) as BlockReaderGoldenImage; + components new BlockReaderC(VOLUME_DELUGE1) as BlockReaderDeluge1; + components new BlockReaderC(VOLUME_DELUGE2) as BlockReaderDeluge2; + components new BlockReaderC(VOLUME_DELUGE3) as BlockReaderDeluge3; + + DelugeReadIdentP.BlockRead[VOLUME_GOLDENIMAGE] -> BlockReaderGoldenImage; + DelugeReadIdentP.BlockRead[VOLUME_DELUGE1] -> BlockReaderDeluge1; + DelugeReadIdentP.BlockRead[VOLUME_DELUGE2] -> BlockReaderDeluge2; + DelugeReadIdentP.BlockRead[VOLUME_DELUGE3] -> BlockReaderDeluge3; +} diff --git a/tos/lib/net/blip/nwprog/DelugeReadIdentClientC.nc b/tos/lib/net/blip/nwprog/DelugeReadIdentClientC.nc new file mode 100644 index 00000000..53c80c5d --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeReadIdentClientC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic configuration DelugeReadIdentClientC() +{ + provides interface DelugeReadIdent; +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_DELUGE_READ_IDENT) + }; + + components DelugeReadIdentC; + DelugeReadIdent = DelugeReadIdentC.DelugeReadIdent[CLIENT_ID]; +} diff --git a/tos/lib/net/blip/nwprog/DelugeReadIdentP.nc b/tos/lib/net/blip/nwprog/DelugeReadIdentP.nc new file mode 100644 index 00000000..ba5116d4 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeReadIdentP.nc @@ -0,0 +1,147 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "imgNum2volumeId.h" + +module DelugeReadIdentP +{ + provides interface DelugeReadIdent[uint8_t client]; + uses { + interface Boot; + interface BlockRead[uint8_t volumeId]; + interface StorageMap[uint8_t volumeId]; + event void storageReady(); + } +} + +implementation +{ + enum { + S_READY, + S_READ_VOLUME, + S_READ_NUM_VOLUMES, + }; + + DelugeIdent ident; + uint8_t state; + uint8_t currentClient; + uint8_t currentIdx; + uint8_t currentVolume; + uint8_t fields; + uint8_t validVolumes; + + event void Boot.booted() { } + + command error_t DelugeReadIdent.readVolume[uint8_t client](uint8_t imgNum) + { + if (state != S_READY) { + return FAIL; + } + else { + currentClient = client; + currentIdx = imgNum; + currentVolume = _imgNum2volumeId[currentIdx]; + if (imgNum < DELUGE_NUM_VOLUMES) { + state = S_READ_VOLUME; + return call BlockRead.read[currentVolume](0, &ident, sizeof(ident)); + } + else { + return FAIL; + } + } + } + + command error_t DelugeReadIdent.readNumVolumes[uint8_t client]() + { + if (state != S_READY) { + return FAIL; + } + else { + fields = 0; + validVolumes = 0; + currentClient = client; + currentIdx = 0; + currentVolume = _imgNum2volumeId[currentIdx]; + state = S_READ_NUM_VOLUMES; + return call BlockRead.read[currentVolume](0, &ident, sizeof(ident)); + } + } + + + event void BlockRead.readDone[uint8_t imgNum]( + storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + switch (state) { + case S_READ_VOLUME: + if (error == SUCCESS && ident.uidhash != DELUGE_INVALID_UID) { + signal DelugeReadIdent.readVolumeDone[currentClient](currentIdx, buf, SUCCESS); + } + else { + signal DelugeReadIdent.readVolumeDone[currentClient](currentIdx, buf, FAIL); + } + state = S_READY; + signal storageReady(); + break; + case S_READ_NUM_VOLUMES: + if (error == SUCCESS && ident.uidhash != DELUGE_INVALID_UID) { + // Increment valid volumes only when uidhash is valid. + fields |= (1 << currentIdx); + validVolumes++; + } + + // Increment the number volumes read. + currentIdx++; + currentVolume = _imgNum2volumeId[currentIdx]; + + // Read the next volume when it didn't reach the end. + if (currentIdx < DELUGE_NUM_VOLUMES) { + call BlockRead.read[currentVolume](0, &ident, sizeof(ident)); + } + // Otherwise, notify the success. + else { + state = S_READY; + signal storageReady(); + signal DelugeReadIdent.readNumVolumesDone[currentClient]( + validVolumes, fields, SUCCESS); + } + break; + } + } + + event void BlockRead.computeCrcDone[uint8_t imgNum]( + storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) {} + default command error_t BlockRead.read[uint8_t imgNum]( + storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockRead.computeCrc[uint8_t imgNum]( + storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + default event void storageReady() {} + default event void DelugeReadIdent.readNumVolumesDone[uint8_t client]( + uint8_t validVols, uint8_t volumeFields, error_t error) {} + default event void DelugeReadIdent.readVolumeDone[uint8_t client]( + uint8_t imgNum, DelugeIdent* id, error_t error) {} + +} + diff --git a/tos/lib/net/blip/nwprog/DelugeVerify.nc b/tos/lib/net/blip/nwprog/DelugeVerify.nc new file mode 100644 index 00000000..979392d2 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeVerify.nc @@ -0,0 +1,14 @@ +/** + * An interface for obtaining the identification data of an + * image. The pointer returned by readDone will be destroyed by the + * next read. + * + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +interface DelugeVerify +{ + command error_t verifyImg(uint8_t imgNum); + event void verifyImgDone(uint8_t imgNum, error_t error); +} diff --git a/tos/lib/net/blip/nwprog/DelugeVerifyC.nc b/tos/lib/net/blip/nwprog/DelugeVerifyC.nc new file mode 100644 index 00000000..67c05562 --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeVerifyC.nc @@ -0,0 +1,60 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +configuration DelugeVerifyC +{ + provides interface DelugeVerify[uint8_t client]; + uses event void storageReady(); +} + +implementation +{ + components MainC; + components DelugeVerifyP; + + DelugeVerify = DelugeVerifyP; + storageReady = DelugeVerifyP; + + components new BlockReaderC(VOLUME_GOLDENIMAGE) as BlockReaderGoldenImage; + components new BlockReaderC(VOLUME_DELUGE1) as BlockReaderDeluge1; + components new BlockReaderC(VOLUME_DELUGE2) as BlockReaderDeluge2; + components new BlockReaderC(VOLUME_DELUGE3) as BlockReaderDeluge3; + + DelugeVerifyP.BlockRead[VOLUME_GOLDENIMAGE] -> BlockReaderGoldenImage; + DelugeVerifyP.BlockRead[VOLUME_DELUGE1] -> BlockReaderDeluge1; + DelugeVerifyP.BlockRead[VOLUME_DELUGE2] -> BlockReaderDeluge2; + DelugeVerifyP.BlockRead[VOLUME_DELUGE3] -> BlockReaderDeluge3; + + components new BlockWriterC(VOLUME_GOLDENIMAGE) as BlockWriterGoldenImage; + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; + + DelugeVerifyP.BlockWrite[VOLUME_GOLDENIMAGE] -> BlockWriterGoldenImage; + DelugeVerifyP.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + DelugeVerifyP.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + DelugeVerifyP.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; +} diff --git a/tos/lib/net/blip/nwprog/DelugeVerifyClientC.nc b/tos/lib/net/blip/nwprog/DelugeVerifyClientC.nc new file mode 100644 index 00000000..045eb07c --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeVerifyClientC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic configuration DelugeVerifyClientC() +{ + provides interface DelugeVerify; +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_DELUGE_VERIFY) + }; + + components DelugeVerifyC; + DelugeVerify = DelugeVerifyC.DelugeVerify[CLIENT_ID]; +} diff --git a/tos/lib/net/blip/nwprog/DelugeVerifyP.nc b/tos/lib/net/blip/nwprog/DelugeVerifyP.nc new file mode 100644 index 00000000..8a1e8afe --- /dev/null +++ b/tos/lib/net/blip/nwprog/DelugeVerifyP.nc @@ -0,0 +1,161 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) 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 Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "imgNum2volumeId.h" + +module DelugeVerifyP +{ + provides interface DelugeVerify[uint8_t client]; + uses { + interface BlockRead[uint8_t volumeId]; + interface BlockWrite[uint8_t volumeId]; + interface StorageMap[uint8_t volumeId]; + event void storageReady(); + } +} + +implementation +{ + enum { + S_READ_IDENT, + S_READ_CRC, + S_CRC, + S_READY, + S_BUSY, + }; + + DelugeIdent ident; + uint8_t state; + uint8_t currentVolume; + uint8_t currentImageIdx; + uint8_t currentPage; + nx_uint16_t currentCrc; + uint8_t currentClient; + + void setStorageReady() + { + signal storageReady(); + state = S_READY; + } + + uint32_t calcCrcAddr() + { + return DELUGE_IDENT_SIZE + currentPage * sizeof(uint16_t); + } + + uint32_t calcPageAddr() + { + return DELUGE_IDENT_SIZE + DELUGE_CRC_BLOCK_SIZE + currentPage * DELUGE_BYTES_PER_PAGE; + } + + command error_t DelugeVerify.verifyImg[uint8_t client](uint8_t imgNum) + { + // We are going to verify the integrity of the specified image. + // We first read the ident to find the number of pages and + // then iterate over all of them, compute the CRC and + // check it against the corresponding value from the CRCs block. + state = S_READ_IDENT; + currentImageIdx = imgNum; + currentVolume = _imgNum2volumeId[currentImageIdx]; + + if (currentImageIdx < DELUGE_NUM_VOLUMES) { + state = S_READ_IDENT; + call BlockRead.read[currentVolume](0, &ident, sizeof(ident)); + } else { + signal storageReady(); + state = S_READY; + } + + return SUCCESS; + } + + event void BlockRead.readDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + switch (state) { + case S_BUSY: + setStorageReady(); + signal DelugeVerify.verifyImgDone[currentClient](imgNum, error); + break; + case S_READ_IDENT: + if (error == SUCCESS) { + if (ident.uidhash != DELUGE_INVALID_UID) { + currentPage = 0; + state = S_READ_CRC; + call BlockRead.read[currentVolume](calcCrcAddr(), ¤tCrc, sizeof(currentCrc)); + break; + } + } + setStorageReady(); + signal DelugeVerify.verifyImgDone[currentClient](imgNum, FAIL); + break; + case S_READ_CRC: + state = S_CRC; + call BlockRead.computeCrc[currentVolume](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0); + break; + } + } + + event void BlockRead.computeCrcDone[uint8_t imgNum](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) + { + switch (state) { + case S_CRC: + if (crc != currentCrc) { + setStorageReady(); + signal DelugeVerify.verifyImgDone[currentClient](imgNum, FAIL); + } else { + currentPage++; + if (currentPage < ident.numPgs) { + state = S_READ_CRC; + call BlockRead.read[currentVolume](calcCrcAddr(), ¤tCrc, sizeof(currentCrc)); + } + else { + setStorageReady(); + signal DelugeVerify.verifyImgDone[currentClient](imgNum, error); + } + } + break; + } + } + + default command error_t BlockRead.read[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockRead.computeCrc[uint8_t imgNum](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + + event void BlockWrite.writeDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} + event void BlockWrite.eraseDone[uint8_t imgNum](error_t error) + { + switch (state) { + case S_READY: + signal BlockWrite.eraseDone[imgNum](error); + break; + } + } + + event void BlockWrite.syncDone[uint8_t imgNum](error_t error) {} + default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; } + default event void storageReady() {} + default event void DelugeVerify.verifyImgDone[uint8_t client](uint8_t imgNum, error_t error) {} + +} diff --git a/tos/lib/net/blip/nwprog/NWProgC.nc b/tos/lib/net/blip/nwprog/NWProgC.nc new file mode 100644 index 00000000..3796ec5e --- /dev/null +++ b/tos/lib/net/blip/nwprog/NWProgC.nc @@ -0,0 +1,40 @@ + +#include "StorageVolumes.h" +#include "Deluge.h" + +configuration NWProgC { + provides interface BootImage; +} implementation { + + // send and receive pages + components MainC, IPDispatchC; + components NetProgC, NWProgP; + + BootImage = NWProgP; + + components BlockStorageManagerC; + components new BlockStorageLockClientC(); + components new BlockWriterC(VOLUME_GOLDENIMAGE) as BlockWriterDeluge0; + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; + + NWProgP.Boot -> MainC; + NWProgP.NetProg -> NetProgC; + NWProgP.StorageMap -> BlockStorageManagerC; + NWProgP.Recv -> IPDispatchC.UDP[5213]; + NWProgP.Resource -> BlockStorageLockClientC; + + NWProgP.BlockWrite[VOLUME_GOLDENIMAGE] -> BlockWriterDeluge0; + NWProgP.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + NWProgP.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + NWProgP.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; + + components new ShellCommandC("nwprog"); + NWProgP.ShellCommand -> ShellCommandC; + components new TimerMilliC(); + NWProgP.RebootTimer -> TimerMilliC; + components new DelugeMetadataClientC(); + NWProgP.DelugeMetadata -> DelugeMetadataClientC; + +} diff --git a/tos/lib/net/blip/nwprog/NWProgP.nc b/tos/lib/net/blip/nwprog/NWProgP.nc new file mode 100644 index 00000000..5974126f --- /dev/null +++ b/tos/lib/net/blip/nwprog/NWProgP.nc @@ -0,0 +1,215 @@ + +#include +#include +#include "imgNum2volumeId.h" +#include "Deluge.h" + +module NWProgP { + provides interface BootImage; + uses { + interface Boot; + interface UDP as Recv; + interface StorageMap[uint8_t imag_num]; + interface NetProg; + interface BlockWrite[uint8_t img_num]; + interface Resource; + interface ShellCommand; + interface DelugeMetadata; + interface Timer as RebootTimer; + event void storageReady(); + } +} implementation { + + enum { + S_IDLE, + S_BUSY, + }; + uint8_t state; + struct sockaddr_in6 endpoint; + prog_reply_t reply; + + // Begin-added by Jaein Jeong + command error_t BootImage.erase(uint8_t img_num) { + error_t error = call BlockWrite.erase[img_num](); + return error; + } + // End-added + + command void BootImage.reboot() { + call NetProg.reboot(); + } + + command error_t BootImage.boot(uint8_t img_num) { + return call NetProg.programImageAndReboot(call StorageMap.getPhysicalAddress[img_num](0)); + } + + event void Boot.booted() { + state = S_IDLE; + } + + void sendDone(error_t error) { + reply.error = error; + call Recv.sendto(&endpoint, &reply, sizeof(prog_reply_t)); + } + + event void Recv.recvfrom(struct sockaddr_in6 *from, + void *payload, uint16_t len, + struct ip_metadata *meta) { + prog_req_t *req = (prog_req_t *)payload; + uint8_t imgNum = imgNum2volumeId(req->imgno); + error_t error = FAIL; + void *buffer; + // just copy the payload out and write it into flash + // we'll send the ack from the write done event. + if (state != S_IDLE) return; + + memcpy(&endpoint, from, sizeof(struct sockaddr_in6)); + memcpy(&reply.req, req, sizeof(prog_req_t)); + + if (!call Resource.isOwner()) { + error = call Resource.immediateRequest(); + } + if (error == SUCCESS) { + switch (req->cmd) { + case NWPROG_CMD_ERASE: + error = call BlockWrite.erase[imgNum](); + break; + case NWPROG_CMD_WRITE: + len -= sizeof(prog_req_t); + buffer = ip_malloc(len); + if (buffer == NULL) { + error = ENOMEM; + break; + } + memcpy(buffer, req->data, len); + error = call BlockWrite.write[imgNum](req->offset, + buffer, + len); + if (error != SUCCESS) ip_free(buffer); + break; + default: + error = FAIL; + } + } + + if (error != SUCCESS) { + sendDone(error); + call Resource.release(); + } else { + state = S_BUSY; + } + } + + event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) { + if (state != S_BUSY) return; + sendDone(error); + call Resource.release(); + state = S_IDLE; + ip_free(buf); + } + + event void BlockWrite.eraseDone[uint8_t img_num](error_t error) { + if (state != S_BUSY) return; + if (error == SUCCESS) + call BlockWrite.sync[img_num](); + else { + sendDone(error); + state = S_IDLE; + call Resource.release(); + } + } + + event void BlockWrite.syncDone[uint8_t img_num](error_t error) { + if (state != S_BUSY) return; + sendDone(error); + state = S_IDLE; + call Resource.release(); + } + + event void Resource.granted() { + + } + + + /* + * Shell command implementation + */ + char *nwprog_help_str = "nwprog [list | boot [when] | reboot]\n"; + uint8_t nwprog_currentvol, nwprog_validvols; + uint8_t boot_image; + + uint8_t volumeID2imgNum(uint8_t volumeID) { + switch(volumeID) { + case VOLUME_GOLDENIMAGE: return 0; + case VOLUME_DELUGE1: return 1; + case VOLUME_DELUGE2: return 2; + case VOLUME_DELUGE3: return 3; + } + } + event void DelugeMetadata.readDone(uint8_t imgNum, DelugeIdent* ident, error_t error) { + int len; + char *reply_buf = call ShellCommand.getBuffer(MAX_REPLY_LEN); + if (error == SUCCESS) { + if (ident->uidhash != DELUGE_INVALID_UID) { + len = snprintf(reply_buf, MAX_REPLY_LEN, + "image: %i\n\t[size: %li]\n\t[app: %s]\n\t[user: %s]\n\t[host: %s]\n\t[arch: %s]\n\t[time: 0x%lx]\n", + volumeID2imgNum(imgNum), ident->size, (char *)ident->appname, (char *) ident->username, + (char *)ident->hostname, (char *)ident->platform, (uint32_t)ident->timestamp); + nwprog_validvols++; + call ShellCommand.write(reply_buf, len); + } + + } + if (++nwprog_currentvol < DELUGE_NUM_VOLUMES) { + call DelugeMetadata.read(imgNum2volumeId(nwprog_currentvol)); + } else { + len = snprintf(reply_buf, MAX_REPLY_LEN, + "%i valid image(s)\n", nwprog_validvols); + call ShellCommand.write(reply_buf, len); + } + } + + event void RebootTimer.fired() { + call BootImage.boot(boot_image); + } + + + event char *ShellCommand.eval(int argc, char **argv) { + if (argc >= 2) { + if (memcmp(argv[1], "list", 4) == 0) { + nwprog_currentvol = 0; + nwprog_validvols = 0; + call DelugeMetadata.read(imgNum2volumeId(nwprog_currentvol)); + return NULL; + } else if (memcmp(argv[1], "boot", 4) == 0 && (argc == 3 || argc == 4)) { + uint32_t when = 15; + boot_image = atoi(argv[2]), + boot_image = imgNum2volumeId(boot_image); + if (argc == 4) + when = atoi(argv[3]); + if (when == 0) + call RebootTimer.stop(); + else { + char *ack = call ShellCommand.getBuffer(15); + snprintf(ack, 15, "REBOOT %li\n", when); + call RebootTimer.startOneShot(when); + return ack; + } + return NULL; + } else if (memcmp(argv[1], "reboot", 6) == 0) { + call BootImage.reboot(); + } else if (memcmp(argv[1], "erase", 5) == 0 && argc == 3) { + uint8_t img = atoi(argv[2]); + img = imgNum2volumeId(img); + + return NULL; + } + } + return nwprog_help_str; + } + + default command error_t BlockWrite.write[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; } + default command error_t BlockWrite.sync[uint8_t imgNum]() { return FAIL; } + +} diff --git a/tos/lib/net/blip/serial/SerialDevConf.h b/tos/lib/net/blip/serial/SerialDevConf.h new file mode 100644 index 00000000..ab1ec8aa --- /dev/null +++ b/tos/lib/net/blip/serial/SerialDevConf.h @@ -0,0 +1,29 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +#ifndef _SERIALDEVCONF_H_ +#define _SERIALDEVCONF_H_ + +enum { + TOS_SERIAL_DEVCONF = 3, +}; + +#endif diff --git a/tos/lib/net/blip/serial/SerialDevConfC.nc b/tos/lib/net/blip/serial/SerialDevConfC.nc new file mode 100644 index 00000000..f3214edb --- /dev/null +++ b/tos/lib/net/blip/serial/SerialDevConfC.nc @@ -0,0 +1,69 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +//$Id$ + +/* "Copyright (c) 2000-2005 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +/** + * Implementation of communication 802.15.4 message_t packets over the + * serial port. + * + * @author Philip Levis + * @author Ben Greenstein + * @date August 7 2005 + * + */ + +#include "SerialDevConf.h" +configuration SerialDevConfC { + provides { + interface Send; + interface Receive; + } + uses interface Leds; +} +implementation { + components SerialPacketInfoDevConfP as Info, SerialDispatcherC; + + Leds = SerialDispatcherC; + Send = SerialDispatcherC.Send[TOS_SERIAL_DEVCONF]; + Receive = SerialDispatcherC.Receive[TOS_SERIAL_DEVCONF]; + SerialDispatcherC.SerialPacketInfo[TOS_SERIAL_DEVCONF] -> Info; +} diff --git a/tos/lib/net/blip/serial/SerialPacketInfoDevConfP.nc b/tos/lib/net/blip/serial/SerialPacketInfoDevConfP.nc new file mode 100644 index 00000000..99ac36e9 --- /dev/null +++ b/tos/lib/net/blip/serial/SerialPacketInfoDevConfP.nc @@ -0,0 +1,57 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ +/* "Copyright (c) 2000-2005 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY + * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + */ + +module SerialPacketInfoDevConfP { + provides interface SerialPacketInfo as Info; +} +implementation { + async command uint8_t Info.offset() { + // no header + return sizeof(message_header_t); + } + async command uint8_t Info.dataLinkLength(message_t* msg, uint8_t upperLen) { + // no header or footer + return upperLen; + } + async command uint8_t Info.upperLength(message_t* msg, uint8_t dataLinkLen) { + return dataLinkLen; + } +} diff --git a/tos/lib/net/blip/shell/FlashShellC.nc b/tos/lib/net/blip/shell/FlashShellC.nc new file mode 100644 index 00000000..cc09e4e7 --- /dev/null +++ b/tos/lib/net/blip/shell/FlashShellC.nc @@ -0,0 +1,14 @@ + +#include "StorageVolumes.h" + +configuration FlashShellC { + +} implementation { + components new ShellCommandC("flash"); + FlashShellP.ShellCommand -> ShellCommandC; + + components new BlockStorageC(VOLUME_DELUGE1); + FlashShellP.BlockRead -> BlockStorageC; + FlashShellP.BlockWrite -> BlockStorageC; + +} diff --git a/tos/lib/net/blip/shell/FlashShellP.nc b/tos/lib/net/blip/shell/FlashShellP.nc new file mode 100644 index 00000000..cb87f9a8 --- /dev/null +++ b/tos/lib/net/blip/shell/FlashShellP.nc @@ -0,0 +1,46 @@ +module FlashShellP { + uses { + interface Boot; + interface Leds; + interface ShellCommand; + interface BlockRead; + interface BlockWrite; + } +} implementation { + + event void Boot.booted() { + if (call BlockWrite.erase() != SUCCESS) + call Leds.led1Toggle(); + } + + event void BlockRead.readDone(storage_addr_t addr, void* buf, storage_len_t len, + error_t error) { + uint16_t r_len = snprintf(reply_buf, MAX_REPLY_LEN,"read done addr: 0x%x len: %i error: %i data: ", + addr, len, error); + if (len < MAX_REPLY_LEN - r_len - 1) + memcpy(reply_buf + r_len, buf, len); + reply_buf[r_len + len + 1] = '\n'; + call UDP.sendto(&session_endpoint, reply_buf, r_len + len + 1); + + } + + event void BlockRead.computeCrcDone(storage_addr_t addr, storage_len_t len, + uint16_t crc, error_t error) { + + } + + event void BlockWrite.writeDone(storage_addr_t addr, void* buf, storage_len_t len, + error_t error) { + uint16_t r_len = snprintf(reply_buf, MAX_REPLY_LEN,"write done addr: 0x%x len: %i error: %i\n", + addr, len, error); + call UDP.sendto(&session_endpoint, reply_buf, r_len); + } + + event void BlockWrite.eraseDone(error_t error) { + call Leds.led0Toggle(); + } + + event void BlockWrite.syncDone(error_t error) { + + } +} diff --git a/tos/lib/net/blip/shell/RegisterShellCommand.nc b/tos/lib/net/blip/shell/RegisterShellCommand.nc new file mode 100644 index 00000000..fb980138 --- /dev/null +++ b/tos/lib/net/blip/shell/RegisterShellCommand.nc @@ -0,0 +1,4 @@ + +interface RegisterShellCommand { + event char *getCommandName(); +} diff --git a/tos/lib/net/blip/shell/Shell.h b/tos/lib/net/blip/shell/Shell.h new file mode 100644 index 00000000..04e28900 --- /dev/null +++ b/tos/lib/net/blip/shell/Shell.h @@ -0,0 +1,8 @@ +#ifndef _SHELL_H +#define _SHELL_H + +enum { + MAX_REPLY_LEN = 128, +}; + +#endif diff --git a/tos/lib/net/blip/shell/ShellCommand.nc b/tos/lib/net/blip/shell/ShellCommand.nc new file mode 100644 index 00000000..075c55c9 --- /dev/null +++ b/tos/lib/net/blip/shell/ShellCommand.nc @@ -0,0 +1,25 @@ + +interface ShellCommand { + + /* + * evaluate the command that this command provides + * @argc the number of arguments + * @argv the arguments + * @return a string to send back as the reply to the shell client. + * if NULL, nothing is sent. + */ + event char *eval(int argc, char **argv); + + /* + * request a buffer. The result of this command may be returned + * from 'eval', but otherwise the buffer may not be used outside of + * the context it is called from. + */ + command char *getBuffer(uint16_t len); + + /* + * write a string to the shell buffer; if no client is connected it + * will fail silently + */ + command void write(char *str, int len); +} diff --git a/tos/lib/net/blip/shell/ShellCommandC.nc b/tos/lib/net/blip/shell/ShellCommandC.nc new file mode 100644 index 00000000..7343617b --- /dev/null +++ b/tos/lib/net/blip/shell/ShellCommandC.nc @@ -0,0 +1,14 @@ + +generic configuration ShellCommandC(char cmd_name[]) { + provides interface ShellCommand; +} implementation { + + enum { + CMD_ID = unique("UDPSHELL_CLIENTCOUNT"), + }; + + components new ShellCommandP(cmd_name), UDPShellP; + + ShellCommandP.RegisterShellCommand -> UDPShellP.RegisterShellCommand[CMD_ID]; + ShellCommand = UDPShellP.ShellCommand[CMD_ID]; +} diff --git a/tos/lib/net/blip/shell/ShellCommandP.nc b/tos/lib/net/blip/shell/ShellCommandP.nc new file mode 100644 index 00000000..6f9af62d --- /dev/null +++ b/tos/lib/net/blip/shell/ShellCommandP.nc @@ -0,0 +1,8 @@ + +generic module ShellCommandP(char cmd_name[]) { + uses interface RegisterShellCommand; +} implementation { + event char *RegisterShellCommand.getCommandName() { + return cmd_name; + } +} diff --git a/tos/lib/net/blip/shell/UDPShellC.nc b/tos/lib/net/blip/shell/UDPShellC.nc new file mode 100644 index 00000000..d3d3a03c --- /dev/null +++ b/tos/lib/net/blip/shell/UDPShellC.nc @@ -0,0 +1,47 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include <6lowpan.h> + +configuration UDPShellC { + + +} implementation { + + components new UdpSocketC(); + components UDPShellP, LedsC; + + UDPShellP.UDP -> UdpSocketC; + + UDPShellP.Leds -> LedsC; + components ICMPResponderC; + UDPShellP.ICMPPing -> ICMPResponderC.ICMPPing[unique("PING")]; + +#if defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC) + components CounterMilli32C; + UDPShellP.Uptime -> CounterMilli32C; +#endif + + components MainC; + UDPShellP.Boot -> MainC; + +} diff --git a/tos/lib/net/blip/shell/UDPShellP.nc b/tos/lib/net/blip/shell/UDPShellP.nc new file mode 100644 index 00000000..8de6f888 --- /dev/null +++ b/tos/lib/net/blip/shell/UDPShellP.nc @@ -0,0 +1,289 @@ +/* + * "Copyright (c) 2008 The Regents of the University of California. + * All rights reserved." + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice, the following + * two paragraphs and the author appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." + * + */ + +#include +#include +#include +#include "Shell.h" + +module UDPShellP { + provides { + interface ShellCommand[uint8_t cmd_id]; + interface RegisterShellCommand[uint8_t cmd_id]; + } + uses { + interface Boot; + interface UDP; + interface Leds; + + interface ICMPPing; +#if defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC) + interface Counter as Uptime; +#endif + + } + +} implementation { + + bool session_active; + struct sockaddr_in6 session_endpoint; + uint32_t boot_time; + uint64_t uptime; + + enum { + N_EXTERNAL = uniqueCount("UDPSHELL_CLIENTCOUNT"), + }; + + // and corresponding indeces + enum { + N_BUILTINS = 5, + // the maximum number of arguments a command can take + N_ARGS = 10, + CMD_HELP = 0, + CMD_ECHO = 1, + CMD_PING6 = 2, + CMD_TRACERT6 = 3, + + CMD_NO_CMD = 0xfe, + CMDNAMSIZ = 10, + }; + + struct cmd_name { + uint8_t c_len; + char c_name[CMDNAMSIZ]; + }; + struct cmd_builtin { + void (*action)(int, char **); + }; + + struct cmd_name externals[N_EXTERNAL]; + + + event void Boot.booted() { + int i; + atomic { + uptime = 0; +#if defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC) + boot_time = call Uptime.get(); +#endif + } + for (i = 0; i < N_EXTERNAL; i++) { + externals[i].c_name[CMDNAMSIZ-1] = '\0'; + strncpy(externals[i].c_name, signal RegisterShellCommand.getCommandName[i](), CMDNAMSIZ); + externals[i].c_len = strlen(externals[i].c_name); + } + call UDP.bind(2000); + } + + char reply_buf[MAX_REPLY_LEN]; + char *help_str = "sdsh-0.9\tbuiltins: [help, echo, ping6, uptime, ident]\n"; + const char *ping_fmt = "%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x: icmp_seq=%i ttl=%i time=%i ms\n"; + const char *ping_summary = "%i packets transmitted, %i received\n"; + + void action_help(int argc, char **argv) { + int i = 0; + char *pos = reply_buf; + call UDP.sendto(&session_endpoint, help_str, strlen(help_str)); + if (N_EXTERNAL > 0) { + strcpy(pos, "\t\t["); + pos += 3; + for (i = 0; i < N_EXTERNAL; i++) { + if (externals[i].c_len + 4 < MAX_REPLY_LEN - (pos - reply_buf)) { + memcpy(pos, externals[i].c_name, externals[i].c_len); + pos += externals[i].c_len; + if (i < N_EXTERNAL-1) { + pos[0] = ','; + pos[1] = ' '; + pos += 2; + } + } else { + pos[0] = '.'; + pos[1] = '.'; + pos[2] = '.'; + pos += 3; + break; + } + } + *pos++ = ']'; + *pos++ = '\n'; + call UDP.sendto(&session_endpoint, reply_buf, pos - reply_buf); + } + } + + command char *ShellCommand.getBuffer[uint8_t cmd_id](uint16_t len) { + reply_buf[0] = '\0'; + if (len <= MAX_REPLY_LEN) return reply_buf; + return NULL; + } + + command void ShellCommand.write[uint8_t cmd_id](char *str, int len) { + call UDP.sendto(&session_endpoint, str, len); + } + + void action_echo(int argc, char **argv) { + int i, arg_len; + char *payload = reply_buf; + + if (argc < 2) return; + for (i = 1; i < argc; i++) { + arg_len = strlen(argv[i]); + if ((payload - reply_buf) + arg_len + 1 > MAX_REPLY_LEN) break; + memcpy(payload, argv[i], arg_len); + payload += arg_len; + *payload = ' '; + payload++; + } + *(payload - 1) = '\n'; + + call UDP.sendto(&session_endpoint, reply_buf, payload - reply_buf); + } + + void action_ping6(int argc, char **argv) { + struct in6_addr dest; + + if (argc < 2) return; + inet_pton6(argv[1], &dest); + call ICMPPing.ping(&dest, 1024, 10); + } + + + void action_uptime(int argc, char **argv) { +#if defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC) + int len; + uint64_t tval = call Uptime.get(); + atomic + tval = (uptime + tval - boot_time) / 1024; + len = snprintf(reply_buf, MAX_REPLY_LEN, "up %li seconds\n", + (uint32_t)tval); + call UDP.sendto(&session_endpoint, reply_buf, len); +#endif + } + + void action_ident(int argc, char **argv) { + int len; + len = snprintf(reply_buf, MAX_REPLY_LEN, + "\t[app: %s]\n\t[user: %s]\n\t[host: %s]\n\t[time: 0x%lx]\n", + IDENT_APPNAME, IDENT_USERNAME, IDENT_HOSTNAME, IDENT_TIMESTAMP); + call UDP.sendto(&session_endpoint, reply_buf, len); + } + + // commands + struct cmd_name builtins[N_BUILTINS] = {{4, "help"}, + {4, "echo"}, + {5, "ping6"}, + {6, "uptime"}, + {5, "ident"}}; + struct cmd_builtin builtin_actions[N_BUILTINS] = {{action_help}, + {action_echo}, + {action_ping6}, + {action_uptime}, + {action_ident}}; + + + // break up a command given as a string into a sequence of null terminated + // strings, and initialize the argv array to point into it. + void init_argv(char *cmd, uint16_t len, char **argv, int *argc) { + int inArg = 0; + *argc = 0; + while (len > 0 && *argc < N_ARGS) { + if (*cmd == ' ' || *cmd == '\n' || *cmd == '\t' || *cmd == '\0' || len == 1){ + if (inArg) { + *argc = *argc + 1; + inArg = 0; + *cmd = '\0'; + } + } else if (!inArg) { + argv[*argc] = cmd; + inArg = 1; + } + cmd ++; + len --; + } + } + + int lookup_cmd(char *cmd, int dbsize, struct cmd_name *db) { + int i; + for (i = 0; i < dbsize; i++) { + if (memcmp(cmd, db[i].c_name, db[i].c_len) == 0 + && cmd[db[i].c_len] == '\0') + return i; + } + return CMD_NO_CMD; + } + + event void UDP.recvfrom(struct sockaddr_in6 *from, void *data, + uint16_t len, struct ip_metadata *meta) { + char *argv[N_ARGS]; + int argc, cmd; + + memcpy(&session_endpoint, from, sizeof(struct sockaddr_in6)); + init_argv((char *)data, len, argv, &argc); + + if (argc > 0) { + cmd = lookup_cmd(argv[0], N_BUILTINS, builtins); + if (cmd != CMD_NO_CMD) { + builtin_actions[cmd].action(argc, argv); + return; + } + cmd = lookup_cmd(argv[0], N_EXTERNAL, externals); + if (cmd != CMD_NO_CMD) { + char *reply = signal ShellCommand.eval[cmd](argc, argv); + if (reply != NULL) + call UDP.sendto(&session_endpoint, reply, strlen(reply)); + return; + } + cmd = snprintf(reply_buf, MAX_REPLY_LEN, "sdsh: %s: command not found\n", argv[0]); + call UDP.sendto(&session_endpoint, reply_buf, cmd); + } + } + + event void ICMPPing.pingReply(struct in6_addr *source, struct icmp_stats *stats) { + int len; + len = snprintf(reply_buf, MAX_REPLY_LEN, ping_fmt, + source->s6_addr[0],source->s6_addr[1],source->s6_addr[2],source->s6_addr[3], + source->s6_addr[4],source->s6_addr[5],source->s6_addr[6],source->s6_addr[7], + source->s6_addr[8],source->s6_addr[9],source->s6_addr[10],source->s6_addr[11], + source->s6_addr[12],source->s6_addr[13],source->s6_addr[14],source->s6_addr[15], + stats->seq, stats->ttl, stats->rtt); + call UDP.sendto(&session_endpoint, reply_buf, len); + } + + event void ICMPPing.pingDone(uint16_t ping_rcv, uint16_t ping_n) { + int len; + len = snprintf(reply_buf, MAX_REPLY_LEN, ping_summary, ping_n, ping_rcv); + call UDP.sendto(&session_endpoint, reply_buf, len); + } + +#if defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC) + async event void Uptime.overflow() { + atomic + uptime += 0xffffffff; + } +#endif + + default event char *ShellCommand.eval[uint8_t cmd_id](int argc, char **argv) { + return NULL; + } + default event char *RegisterShellCommand.getCommandName[uint8_t cmd_id]() { + return NULL; + } +} diff --git a/tos/lib/net/blip/table.c b/tos/lib/net/blip/table.c new file mode 100644 index 00000000..52e262f1 --- /dev/null +++ b/tos/lib/net/blip/table.c @@ -0,0 +1,31 @@ + +#include +#include "table.h" + +void table_init(table_t *table, void *data, + uint16_t elt_len, uint16_t n_elts) { + table->data = data; + table->elt_len = elt_len; + table->n_elts = n_elts; +} + +void *table_search(table_t *table, int (*pred)(void *)) { + int i; + void *cur; + for (i = 0; i < table->n_elts; i++) { + cur = table->data + (i * table->elt_len); + switch (pred(cur)) { + case 1: return cur; + case -1: return NULL; + default: continue; + } + } + return NULL; +} + +void table_map(table_t *table, void(*fn)(void *)) { + int i; + for (i = 0; i < table->n_elts; i++) + fn(table->data + (i * table->elt_len)); +} + diff --git a/tos/lib/net/blip/table.h b/tos/lib/net/blip/table.h new file mode 100644 index 00000000..346e940a --- /dev/null +++ b/tos/lib/net/blip/table.h @@ -0,0 +1,16 @@ +#ifndef TABLE_H_ +#define TABLE_H_ + +#include + +typedef struct { + void *data; + uint16_t elt_len; + uint16_t n_elts; +} table_t; + +void table_init(table_t *table, void *data,uint16_t elt_len, uint16_t n_elts); +void *table_search(table_t *table, int (*pred)(void *)); +void table_map(table_t *table, void (*fn)(void *)); + +#endif -- 2.39.2