]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
- initial commit of blip (berkeley low-power ip) stack
authorsdhsdh <sdhsdh>
Tue, 20 Jan 2009 00:28:14 +0000 (00:28 +0000)
committersdhsdh <sdhsdh>
Tue, 20 Jan 2009 00:28:14 +0000 (00:28 +0000)
147 files changed:
support/sdk/c/blip/Makefile [new file with mode: 0644]
support/sdk/c/blip/driver/Makefile [new file with mode: 0644]
support/sdk/c/blip/driver/config.c [new file with mode: 0644]
support/sdk/c/blip/driver/config.h [new file with mode: 0644]
support/sdk/c/blip/driver/hashtable.c [new file with mode: 0644]
support/sdk/c/blip/driver/hashtable.h [new file with mode: 0644]
support/sdk/c/blip/driver/hashtable_private.h [new file with mode: 0644]
support/sdk/c/blip/driver/logging.c [new file with mode: 0644]
support/sdk/c/blip/driver/logging.h [new file with mode: 0644]
support/sdk/c/blip/driver/nwstate.c [new file with mode: 0644]
support/sdk/c/blip/driver/nwstate.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/CHANGES [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/COPYRIGHT [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/INTRO.html [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/Makefile [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/Makefile.am [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/Makefile.in [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/README [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/TODO [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/VERSION [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/aclocal.m4 [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/config.cache [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/config.guess [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/config.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/config.h.in [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/config.log [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/config.status [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/config.sub [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/configure [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/configure.in [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/copyright.blurb [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/defaults.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/depcomp [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/device-bsd44.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/device-common.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/device-linux.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/gram.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/gram.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/gram.y [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/includes.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/install-sh [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/interface.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/log.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/missing [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/mkinstalldirs [new file with mode: 0755]
support/sdk/c/blip/driver/radvd-1.0/pathnames.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/process.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvd.8.man [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvd.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvd.conf.5.man [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvd.conf.example [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvd.h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvdump.8.man [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/radvdump.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/recv.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/scanner.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/scanner.l [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/send.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/socket.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/stamp-h [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/stamp-h.in [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/timer.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-1.0/util.c [new file with mode: 0644]
support/sdk/c/blip/driver/radvd-wrapper.c [new file with mode: 0644]
support/sdk/c/blip/driver/routing.c [new file with mode: 0644]
support/sdk/c/blip/driver/routing.h [new file with mode: 0644]
support/sdk/c/blip/driver/serial_tun.c [new file with mode: 0644]
support/sdk/c/blip/driver/tun_dev.c [new file with mode: 0644]
support/sdk/c/blip/driver/tun_dev.h [new file with mode: 0644]
support/sdk/c/blip/driver/tunnel.c [new file with mode: 0644]
support/sdk/c/blip/include/6lowpan.h [new file with mode: 0644]
support/sdk/c/blip/include/IEEE154.h [new file with mode: 0644]
support/sdk/c/blip/include/devconf.h [new file with mode: 0644]
support/sdk/c/blip/include/in_cksum.h [new file with mode: 0644]
support/sdk/c/blip/include/ip.h [new file with mode: 0644]
support/sdk/c/blip/include/ip_malloc.h [new file with mode: 0644]
support/sdk/c/blip/include/lib6lowpan.h [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/Makefile [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/in_cksum.c [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/ip_malloc.c [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/lib6lowpan.c [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/lib6lowpanFrag.c [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/lib6lowpanIP.c [new file with mode: 0644]
support/sdk/c/blip/lib6lowpan/printpacket.c [new file with mode: 0644]
support/sdk/c/blip/libtcp/Makefile [new file with mode: 0644]
support/sdk/c/blip/libtcp/circ.c [new file with mode: 0644]
support/sdk/c/blip/libtcp/circ.h [new file with mode: 0644]
support/sdk/c/blip/libtcp/tcplib.c [new file with mode: 0644]
support/sdk/c/blip/libtcp/tcplib.h [new file with mode: 0644]
support/sdk/c/blip/libtcp/test_circ.c [new file with mode: 0644]
support/sdk/c/blip/libtcp/test_server.c [new file with mode: 0644]
support/sdk/c/blip/serial_tun.conf [new file with mode: 0644]
support/sdk/c/sf/serialsource.c
tos/lib/net/blip/ICMP.h [new file with mode: 0644]
tos/lib/net/blip/ICMPResponderC.nc [new file with mode: 0644]
tos/lib/net/blip/ICMPResponderP.nc [new file with mode: 0644]
tos/lib/net/blip/IPAddressC.nc [new file with mode: 0644]
tos/lib/net/blip/IPAddressP.nc [new file with mode: 0644]
tos/lib/net/blip/IPDispatch.h [new file with mode: 0644]
tos/lib/net/blip/IPDispatchC.nc [new file with mode: 0644]
tos/lib/net/blip/IPDispatchP.nc [new file with mode: 0644]
tos/lib/net/blip/IPRoutingP.nc [new file with mode: 0644]
tos/lib/net/blip/PrintfUART.h [new file with mode: 0644]
tos/lib/net/blip/TcpC.nc [new file with mode: 0644]
tos/lib/net/blip/TcpP.nc [new file with mode: 0644]
tos/lib/net/blip/TcpSocketC.nc [new file with mode: 0644]
tos/lib/net/blip/UdpC.nc [new file with mode: 0644]
tos/lib/net/blip/UdpP.nc [new file with mode: 0644]
tos/lib/net/blip/UdpSocketC.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/ICMP.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/ICMPPing.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/IP.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/IPAddress.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/IPRouting.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/Statistics.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/Tcp.nc [new file with mode: 0644]
tos/lib/net/blip/interfaces/UDP.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/BootImage.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/Deluge.h [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugePatch.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugePatchC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugePatchClientC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugePatchP.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeReadIdent.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeReadIdentC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeReadIdentClientC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeReadIdentP.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeVerify.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeVerifyC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeVerifyClientC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/DelugeVerifyP.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/NWProgC.nc [new file with mode: 0644]
tos/lib/net/blip/nwprog/NWProgP.nc [new file with mode: 0644]
tos/lib/net/blip/serial/SerialDevConf.h [new file with mode: 0644]
tos/lib/net/blip/serial/SerialDevConfC.nc [new file with mode: 0644]
tos/lib/net/blip/serial/SerialPacketInfoDevConfP.nc [new file with mode: 0644]
tos/lib/net/blip/shell/FlashShellC.nc [new file with mode: 0644]
tos/lib/net/blip/shell/FlashShellP.nc [new file with mode: 0644]
tos/lib/net/blip/shell/RegisterShellCommand.nc [new file with mode: 0644]
tos/lib/net/blip/shell/Shell.h [new file with mode: 0644]
tos/lib/net/blip/shell/ShellCommand.nc [new file with mode: 0644]
tos/lib/net/blip/shell/ShellCommandC.nc [new file with mode: 0644]
tos/lib/net/blip/shell/ShellCommandP.nc [new file with mode: 0644]
tos/lib/net/blip/shell/UDPShellC.nc [new file with mode: 0644]
tos/lib/net/blip/shell/UDPShellP.nc [new file with mode: 0644]
tos/lib/net/blip/table.c [new file with mode: 0644]
tos/lib/net/blip/table.h [new file with mode: 0644]

diff --git a/support/sdk/c/blip/Makefile b/support/sdk/c/blip/Makefile
new file mode 100644 (file)
index 0000000..38caf56
--- /dev/null
@@ -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 (file)
index 0000000..8c4de95
--- /dev/null
@@ -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 (file)
index 0000000..4cbb4f8
--- /dev/null
@@ -0,0 +1,79 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#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 (file)
index 0000000..0a79dd3
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+#include <net/if.h>
+
+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 (file)
index 0000000..763357e
--- /dev/null
@@ -0,0 +1,274 @@
+/* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/*
+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 (file)
index 0000000..b90781a
--- /dev/null
@@ -0,0 +1,199 @@
+/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#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 (file)
index 0000000..f622701
--- /dev/null
@@ -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 <firstname.lastname@cl.cam.ac.uk> */
+
+#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 (file)
index 0000000..4df083d
--- /dev/null
@@ -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 <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdarg.h>
+#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 (file)
index 0000000..c0f9837
--- /dev/null
@@ -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 <stdio.h>
+
+// 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 (file)
index 0000000..9657540
--- /dev/null
@@ -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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <float.h>
+#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 (&not_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 (file)
index 0000000..7374047
--- /dev/null
@@ -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 (file)
index 0000000..2165e2e
--- /dev/null
@@ -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 <msa@burp.tkv.asdf.org>.
+               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 <maeda.naoaki@jp.fujitsu.com>
+               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 <yoshfuji@linux-ipv6.org>).
+
+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 <kuznet@ms2.inr.ac.ru>.
+
+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 <pjb27@cam.ac.uk>
+               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 <cmetz@inner.net>
+
+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 (file)
index 0000000..1f464b0
--- /dev/null
@@ -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 (file)
index 0000000..29ea681
--- /dev/null
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<!-- $Id$ -->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>RADVD Introduction</title>
+</head>
+
+<body>
+<h1>RADVD Introduction</h1>
+
+<p>
+by <a href="mailto:lf@elemental.net">Lars Fenneberg</a> et al. Updated
+2002-01-12.
+</p>
+
+<p>
+<a href="http://www.ietf.org/rfc/rfc2460.txt">IPv6</a> has a lot more
+support for autoconfiguration than
+<a href="http://www.ietf.org/rfc/rfc791.txt">IPv4</a>. But for this
+autoconfiguration to work on the hosts of a network, the <em>routers</em>
+of the local network have to run a program which answers the
+autoconfiguration requests of the hosts.
+</p>
+
+<p>
+On Linux this program is called
+<a href="http://v6web.litech.org/radvd/">radvd</a>, 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.
+<a href="http://www.ietf.org/rfc/rfc2461.txt">RFC 2461</a> defines most
+functions of radvd.
+</p>
+
+<p>
+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.
+</p>
+
+<p>
+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.
+</p>
+
+<p>
+A small and simple configuration file for radvd might look like this:
+</p>
+
+<p>
+<pre>
+
+interface eth0
+{
+        AdvSendAdvert on;
+        prefix 2001:db8:0:1::/64
+        {
+                AdvOnLink on;
+                AdvAutonomous on;
+        };
+};
+
+</pre>
+
+<p>
+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.
+</p>
+
+<p>
+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.
+</p>
+
+<p>
+The prefix must be 64 bits long (apart from very few exceptions), as dictated by
+<a href="http://www.ietf.org/rfc/rfc2464.txt">RFC 2464</a> and other
+standards for different link-layer technologies. For more
+details, see <a href="http://www.ietf.org/rfc/rfc2462.txt">RFC 2462</a>
+(IPv6 Stateless Address Autoconfiguration) and
+<a href="http://www.ietf.org/rfc/rfc2464.txt">RFC 2464</a>
+(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.
+</p>
+
+<p>
+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:
+</p>
+
+<p>
+<pre>
+
+   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
+
+</pre>
+
+<p>
+The host can also choose a default router by examining the RA.
+the rest works automatically.
+</p>
+
+<p>
+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:
+</p>
+
+<p>
+<ul>
+<li><a href="http://www.bieringer.de/linux/IPv6/IPv6-HOWTO/IPv6-HOWTO.html">http://www.bieringer.de/linux/IPv6/IPv6-HOWTO/IPv6-HOWTO.html</a></li>
+<li><a href="http://people.debian.org/~csmall/ipv6/setup.html">http://people.debian.org/~csmall/ipv6/setup.html</a> (for non-Debian too)</li>
+</ul>
+
+<hr>
+
+<p>
+Copyright &copy; 1997 <a href="mailto:lf@elemental.net">Lars Fenneberg</a>
+</p>
+
+</body>
+</html>
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 (file)
index 0000000..647d35b
--- /dev/null
@@ -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            <lf@elemental.net>       
+#
+#   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 <pekkas@netcore.fi>.
+#
+
+
+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 (file)
index 0000000..506e32f
--- /dev/null
@@ -0,0 +1,63 @@
+#
+#   $Id$
+#
+#   Authors:
+#    Lars Fenneberg            <lf@elemental.net>       
+#
+#   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 <pekkas@netcore.fi>.
+#
+
+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 (file)
index 0000000..cb9df34
--- /dev/null
@@ -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            <lf@elemental.net>       
+#
+#   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 <pekkas@netcore.fi>.
+#
+
+
+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 (file)
index 0000000..98a722e
--- /dev/null
@@ -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 (file)
index 0000000..d1444a7
--- /dev/null
@@ -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 (file)
index 0000000..9fb98e8
--- /dev/null
@@ -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 (file)
index 0000000..f12013e
--- /dev/null
@@ -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>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; 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 (file)
index 0000000..c9dfd23
--- /dev/null
@@ -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 (executable)
index 0000000..aa6ea3f
--- /dev/null
@@ -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 <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  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 <config-patches@gnu.org>."
+
+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 <<EOF >$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 <stdio.h>  /* 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 <sys/systemcfg.h>
+
+               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 <stdlib.h>
+              #include <unistd.h>
+
+              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 <unistd.h>
+       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 <features.h>
+       #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' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/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 <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # 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 <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <sys/param.h>
+  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 <sys/param.h>
+#  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 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> 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 (file)
index 0000000..b1c13a5
--- /dev/null
@@ -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 <sys/time.h> and <time.h>.  */
+#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 <getopt.h> header file.  */
+#define HAVE_GETOPT_H 1
+
+/* Define if you have the <inttypes.h> header file.  */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the <machine/limits.h> header file.  */
+/* #undef HAVE_MACHINE_LIMITS_H */
+
+/* Define if you have the <machine/param.h> header file.  */
+/* #undef HAVE_MACHINE_PARAM_H */
+
+/* Define if you have the <net/if_arp.h> header file.  */
+#define HAVE_NET_IF_ARP_H 1
+
+/* Define if you have the <net/if_dl.h> header file.  */
+/* #undef HAVE_NET_IF_DL_H */
+
+/* Define if you have the <net/if_types.h> header file.  */
+/* #undef HAVE_NET_IF_TYPES_H */
+
+/* Define if you have the <sys/param.h> header file.  */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/sockio.h> header file.  */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define if you have the <sys/time.h> 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 (file)
index 0000000..87932a4
--- /dev/null
@@ -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 <sys/time.h> and <time.h>.  */
+#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 <getopt.h> header file.  */
+#undef HAVE_GETOPT_H
+
+/* Define if you have the <inttypes.h> header file.  */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have the <machine/limits.h> header file.  */
+#undef HAVE_MACHINE_LIMITS_H
+
+/* Define if you have the <machine/param.h> header file.  */
+#undef HAVE_MACHINE_PARAM_H
+
+/* Define if you have the <net/if_arp.h> header file.  */
+#undef HAVE_NET_IF_ARP_H
+
+/* Define if you have the <net/if_dl.h> header file.  */
+#undef HAVE_NET_IF_DL_H
+
+/* Define if you have the <net/if_types.h> header file.  */
+#undef HAVE_NET_IF_TYPES_H
+
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/sockio.h> header file.  */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define if you have the <sys/time.h> 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 (file)
index 0000000..b2a9a4d
--- /dev/null
@@ -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 <sys/sockio.h>
+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 <net/if_dl.h>
+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 <net/if_types.h>
+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 <machine/param.h>
+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 <machine/limits.h>
+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 (executable)
index 0000000..4eaf46d
--- /dev/null
@@ -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 <<CEOF
+${ac_dA}YYTEXT_POINTER${ac_dB}YYTEXT_POINTER${ac_dC}1${ac_dD}
+${ac_uA}YYTEXT_POINTER${ac_uB}YYTEXT_POINTER${ac_uC}1${ac_uD}
+${ac_eA}YYTEXT_POINTER${ac_eB}YYTEXT_POINTER${ac_eC}1${ac_eD}
+${ac_dA}HAVE_LIBC${ac_dB}HAVE_LIBC${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LIBC${ac_uB}HAVE_LIBC${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LIBC${ac_eB}HAVE_LIBC${ac_eC}1${ac_eD}
+${ac_dA}STDC_HEADERS${ac_dB}STDC_HEADERS${ac_dC}1${ac_dD}
+${ac_uA}STDC_HEADERS${ac_uB}STDC_HEADERS${ac_uC}1${ac_uD}
+${ac_eA}STDC_HEADERS${ac_eB}STDC_HEADERS${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SYS_TIME_H${ac_dB}HAVE_SYS_TIME_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_TIME_H${ac_uB}HAVE_SYS_TIME_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_TIME_H${ac_eB}HAVE_SYS_TIME_H${ac_eC}1${ac_eD}
+CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+
+  cat > conftest.frag <<CEOF
+${ac_dA}TIME_WITH_SYS_TIME${ac_dB}TIME_WITH_SYS_TIME${ac_dC}1${ac_dD}
+${ac_uA}TIME_WITH_SYS_TIME${ac_uB}TIME_WITH_SYS_TIME${ac_uC}1${ac_uD}
+${ac_eA}TIME_WITH_SYS_TIME${ac_eB}TIME_WITH_SYS_TIME${ac_eC}1${ac_eD}
+${ac_dA}HAVE_GETOPT_H${ac_dB}HAVE_GETOPT_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GETOPT_H${ac_uB}HAVE_GETOPT_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GETOPT_H${ac_eB}HAVE_GETOPT_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_INTTYPES_H${ac_dB}HAVE_INTTYPES_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_INTTYPES_H${ac_uB}HAVE_INTTYPES_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_INTTYPES_H${ac_eB}HAVE_INTTYPES_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_NET_IF_ARP_H${ac_dB}HAVE_NET_IF_ARP_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_NET_IF_ARP_H${ac_uB}HAVE_NET_IF_ARP_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_NET_IF_ARP_H${ac_eB}HAVE_NET_IF_ARP_H${ac_eC}1${ac_eD}
+CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+
+  cat > conftest.frag <<CEOF
+${ac_dA}HAVE_SYS_PARAM_H${ac_dB}HAVE_SYS_PARAM_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_PARAM_H${ac_uB}HAVE_SYS_PARAM_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_PARAM_H${ac_eB}HAVE_SYS_PARAM_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SIN6_SCOPE_ID${ac_dB}HAVE_SIN6_SCOPE_ID${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SIN6_SCOPE_ID${ac_uB}HAVE_SIN6_SCOPE_ID${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SIN6_SCOPE_ID${ac_eB}HAVE_SIN6_SCOPE_ID${ac_eC}1${ac_eD}
+${ac_dA}HAVE_IN6_ADDR_S6_ADDR${ac_dB}HAVE_IN6_ADDR_S6_ADDR${ac_dC}1${ac_dD}
+${ac_uA}HAVE_IN6_ADDR_S6_ADDR${ac_uB}HAVE_IN6_ADDR_S6_ADDR${ac_uC}1${ac_uD}
+${ac_eA}HAVE_IN6_ADDR_S6_ADDR${ac_eB}HAVE_IN6_ADDR_S6_ADDR${ac_eC}1${ac_eD}
+${ac_dA}HAVE_GETOPT_LONG${ac_dB}HAVE_GETOPT_LONG${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GETOPT_LONG${ac_uB}HAVE_GETOPT_LONG${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GETOPT_LONG${ac_eB}HAVE_GETOPT_LONG${ac_eC}1${ac_eD}
+CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+
+  cat > conftest.frag <<CEOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+CEOF
+  sed -f conftest.frag conftest.in > 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 (executable)
index 0000000..1657334
--- /dev/null
@@ -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 <config-patches@gnu.org>.  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 <config-patches@gnu.org>."
+
+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 (executable)
index 0000000..531cbcf
--- /dev/null
@@ -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 <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1088: \"$ac_try\") 1>&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 <<EOF
+#line 1367 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 1384 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 1401 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 1512 "configure"
+#include "confdefs.h"
+/* 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 yywrap();
+
+int main() {
+yywrap()
+; return 0; }
+EOF
+if { (eval echo configure:1523: \"$ac_link\") 1>&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 <<EOF
+#line 1579 "configure"
+#include "confdefs.h"
+`cat $LEX_OUTPUT_ROOT.c`
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1586: \"$ac_link\") 1>&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 <<EOF
+#line 1736 "configure"
+#include "confdefs.h"
+/* 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 inet_ntop();
+
+int main() {
+inet_ntop()
+; return 0; }
+EOF
+if { (eval echo configure:1747: \"$ac_link\") 1>&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 <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lc $LIBS"
+
+else
+  echo "$ac_t""no" 1>&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 <<EOF
+#line 1781 "configure"
+#include "confdefs.h"
+/* 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 inet_ntop();
+
+int main() {
+inet_ntop()
+; return 0; }
+EOF
+if { (eval echo configure:1792: \"$ac_link\") 1>&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 <<EOF
+#line 1827 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+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
+#line 1852 "configure"
+#include "confdefs.h"
+#include <string.h>
+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
+#line 1870 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+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 <<EOF
+#line 1891 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#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
+#line 1934 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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 <<EOF
+#line 1971 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+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
+#line 2008 "configure"
+#include "confdefs.h"
+#include <netinet/ip6.h>
+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
+#line 2045 "configure"
+#include "confdefs.h"
+#include <netinet/ipv6.h>
+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
+#line 2087 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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
+#line 2127 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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
+#line 2167 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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
+#line 2207 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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
+#line 2247 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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 <<EOF
+#line 2285 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this.  */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this.  */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this.  */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+   It does not let you subtract one const X* pointer from another in an arm
+   of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this.  */
+  char *t;
+  char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+  *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+  int x[] = {25, 17};
+  const int *foo = &x[0];
+  ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+  typedef const int *iptr;
+  iptr p = 0;
+  ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+     "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+  struct s { int j; const int *ap[3]; };
+  struct s *b; b->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 <<EOF
+#line 2358 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <netinet/in.h>
+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 <<EOF
+#line 2384 "configure"
+#include "confdefs.h"
+#include <netinet/in.h>
+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 <<EOF
+#line 2414 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&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 <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/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 <<EOF
+
+# 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
+$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 <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $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 <<EOF
+  CONFIG_HEADERS="config.h"
+EOF
+cat >> $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 <<CEOF' >> $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 <<EOF
+ac_sources="device-${arch}.c"
+ac_dests="device.c"
+EOF
+
+cat >> $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 <<EOF
+
+
+EOF
+cat >> $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 (file)
index 0000000..39ea262
--- /dev/null
@@ -0,0 +1,157 @@
+dnl
+dnl  $Id$
+dnl
+dnl   Authors:
+dnl    Lars Fenneberg          <lf@elemental.net>       
+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 <pekkas@netcore.fi>.
+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 <sys/types.h>
+#include <netinet/in.h>], [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 <netinet/in.h>], [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 (file)
index 0000000..51923b7
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
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 (file)
index 0000000..03fc62b
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#ifndef DEFAULTS_H
+#define DEFAULTS_H
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+/* 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 (executable)
index 0000000..edb5d38
--- /dev/null
@@ -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 <oliva@dcc.unicamp.br>.
+
+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 (file)
index 0000000..b89ce31
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Craig Metz               <cmetz@inner.net>
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+#include <pathnames.h>         /* 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 (file)
index 0000000..823127a
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+
+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 (file)
index 0000000..f160c15
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+#include <pathnames.h>         /* 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 (file)
index 0000000..09c2817
--- /dev/null
@@ -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 <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+
+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 <stddef.h> /* 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 <libintl.h> /* 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 <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* 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 <stdlib.h> /* 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 <stdlib.h> /* 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 <stdio.h> /* 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
+
+\f
+
+#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 */
+\f
+
+/*-----------------------------------------------.
+| 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;
+    }
+}
+\f
+
+/* 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 (file)
index 0000000..368c163
--- /dev/null
@@ -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 (file)
index 0000000..06b7acf
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+%{
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+
+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 <str>   STRING
+%token <num>   NUMBER
+%token <snum>  SIGNEDNUMBER
+%token <dec>   DECIMAL
+%token <bool>  SWITCH
+%token <addr>  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  <str>   name
+%type  <pinfo> optional_prefixlist prefixdef prefixlist
+%type  <rinfo> optional_routelist routedef routelist
+%type  <rdnssinfo> optional_rdnsslist rdnssdef rdnsslist
+%type   <num>  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 (file)
index 0000000..8384580
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#ifndef INCLUDES_H
+#define INCLUDES_H
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <sys/types.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#else
+# ifdef HAVE_MACHINE_PARAM_H
+#  include <machine/param.h>
+# endif
+# ifdef HAVE_MACHINE_LIMITS_H
+#  include <machine/limits.h>
+# endif
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <netinet/in.h>
+
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+
+#include <arpa/inet.h>
+
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+
+#ifdef HAVE_NET_IF_DL_H
+# include <net/if_dl.h>
+#endif
+#ifdef HAVE_NET_IF_TYPES_H
+# include <net/if_types.h>
+#endif
+#if defined(HAVE_NET_IF_ARP_H) && !defined(ARPHRD_ETHER)
+# include <net/if_arp.h>
+#endif /* defined(HAVE_NET_IF_ARP_H) && !defined(ARPHRD_ETHER) */
+
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#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 (executable)
index 0000000..e9de238
--- /dev/null
@@ -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 (file)
index 0000000..923b7d0
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+
+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 (file)
index 0000000..e64dfec
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *     $Id$
+ *
+ *     Authors:
+ *      Lars Fenneberg         <lf@elemental.net>       
+ *
+ *     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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+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(&current);
+                       (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(&current);
+                       (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 (executable)
index 0000000..fc54c64
--- /dev/null
@@ -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 <pinard@iro.umontreal.ca>, 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 (executable)
index 0000000..6b3b5fc
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# 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 (file)
index 0000000..c061455
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#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 (file)
index 0000000..bcd9589
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+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 (file)
index 0000000..5fe0e94
--- /dev/null
@@ -0,0 +1,173 @@
+.\"
+.\"   $Id$
+.\"
+.\"   Authors:
+.\"    Lars Fenneberg          <lf@elemental.net>       
+.\"
+.\"   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 <pekkas@netcore.fi>.
+.\"
+.\"
+.\"
+.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 <pekkas@netcore.fi>.
+
+.SH "SEE ALSO"
+
+.BR radvd.conf (5),
+.BR radvdump (8)
+.SH AUTHORS
+
+.nf
+Pedro Roque    <roque@di.fc.ul.pt>     - wrote first version for Linux
+Lars Fenneberg <lf@elemental.net>      - previous maintainer
+Nathan Lutchansky      <lutchann@litech.org>   - previous maintainer
+Pekka Savola   <pekkas@netcore.fi>     - current maintainer
+Craig Metz     <cmetz@inner.net>       - port to NRL's IPv6 code for BSD4.4
+Marko Myllynen <myllynen@lut.fi>       - 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 (file)
index 0000000..9125850
--- /dev/null
@@ -0,0 +1,638 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <pathnames.h>
+
+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 (file)
index 0000000..8e06194
--- /dev/null
@@ -0,0 +1,591 @@
+.\"
+.\"   $Id$
+.\"
+.\"   Authors:
+.\"    Lars Fenneberg          <lf@elemental.net>
+.\"    Marko Myllynen           <myllynen@lut.fi>       
+.\"
+.\"   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 <pekkas@netcore.fi>.
+.\"
+.\"
+.\"
+.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 (file)
index 0000000..b4bc5b9
--- /dev/null
@@ -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 (file)
index 0000000..57b7480
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#ifndef RADV_H
+#define RADV_H
+
+#include <config.h>
+#include <includes.h>
+#include <defaults.h>
+
+#define CONTACT_EMAIL  "Pekka Savola <pekkas@netcore.fi>"
+
+/* 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 (file)
index 0000000..98ee6b8
--- /dev/null
@@ -0,0 +1,87 @@
+.\"
+.\"   $Id$
+.\"
+.\"   Authors:
+.\"    Lars Fenneberg          <lf@elemental.net>       
+.\"    Marko Myllynen          <myllynen@lut.fi>       
+.\"
+.\"   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 <pekkas@netcore.fi>.
+.\"
+.\"
+.\"
+.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 <pekkas@netcore.fi>.
+
+.SH "SEE ALSO"
+
+.BR radvd (8),
+.BR radvd.conf (5)
+.SH AUTHORS
+
+.nf
+Lars Fenneberg <lf@elemental.net>      - previous maintainer
+Nathan Lutchansky <lutchann@litech.org> - previous maintainer
+Pekka Savola   <pekkas@netcore.fi>     - current maintainer
+Marko Myllynen <myllynen@lut.fi>       - 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 (file)
index 0000000..e4beaf5
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>
+ *    Marko Myllynen           <myllynen@lut.fi>
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+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 (file)
index 0000000..b78644d
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+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 (file)
index 0000000..47d6361
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. 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 <inttypes.h>
+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              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+#line 17 "scanner.l"
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <gram.h>
+
+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 <unistd.h>
+#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 (file)
index 0000000..45c3a17
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+%{
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <gram.h>
+
+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 (file)
index 0000000..43145f8
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+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 (file)
index 0000000..082f883
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+/* 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 (file)
index 0000000..9788f70
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
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 (file)
index 0000000..82d5458
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+
+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 (file)
index 0000000..0ea15e7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   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 <pekkas@netcore.fi>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+               
+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 (file)
index 0000000..b5562aa
--- /dev/null
@@ -0,0 +1,162 @@
+/* 
+ * radvd-wrapper.c
+ * author: Stephen Dawson-Haggerty <stevedh@eecs.berkeley.edu>
+ *
+ * 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 <includes.h>
+#include <radvd.h>
+#include <pathnames.h>
+
+#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 (file)
index 0000000..f883f32
--- /dev/null
@@ -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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <net/if.h>
+
+#include <6lowpan.h>
+#include <lib6lowpan.h>
+#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 (file)
index 0000000..cfb3193
--- /dev/null
@@ -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 <ip.h>
+#include <string.h>
+#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 (file)
index 0000000..0462f35
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <termios.h>
+#include <errno.h>
+#include <signal.h>
+
+#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 <dotfile>: print dot-file of topology\n");
+    printf("  i <nodeid>: 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(&current_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] <device> <rate>\n", argv[0]);
+#else
+    fatal("usage: %s [-c config] <host> <port>\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 (file)
index 0000000..684efb9
--- /dev/null
@@ -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 <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+
+#include <netinet/in.h>
+
+#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 (file)
index 0000000..e0b32d3
--- /dev/null
@@ -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 <ip.h>
+
+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 (file)
index 0000000..6d6a64e
--- /dev/null
@@ -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 <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+uint16_t shortAddr;
+int tun_fd;
+char *tun_dev = "/dev/net/tun";
+
+void usage(char **args) {
+  fprintf(stderr, "\n\t%s <my-short-addr>\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 (file)
index 0000000..76ddd75
--- /dev/null
@@ -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 <stdint.h>
+/*
+ * 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 <IEEE802154.h>
+#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 (file)
index 0000000..4a47e16
--- /dev/null
@@ -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 (file)
index 0000000..3a56d1b
--- /dev/null
@@ -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 (file)
index 0000000..b6108fa
--- /dev/null
@@ -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 <stdint.h>
+#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 (file)
index 0000000..e48163f
--- /dev/null
@@ -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 <linux/if_tun.h>
+#include <netinet/in.h>
+#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 (file)
index 0000000..dbd0db5
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef NO_IP_MALLOC
+#ifndef IP_MALLOC_H_
+#define IP_MALLOC_H_
+
+#include <stdint.h>
+
+// 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 (file)
index 0000000..8723c29
--- /dev/null
@@ -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 <stdint.h>
+#include <stddef.h>
+
+#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 (file)
index 0000000..fb34df2
--- /dev/null
@@ -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 (file)
index 0000000..bcad3fd
--- /dev/null
@@ -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 <stdlib.h>
+#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 (file)
index 0000000..0ace8e7
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef NO_IP_MALLOC
+#include <stdint.h>
+#include <stdio.h>
+#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 (file)
index 0000000..3ebe2f6
--- /dev/null
@@ -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 (file)
index 0000000..dfb4df4
--- /dev/null
@@ -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 <stevedh@cs.berkeley.edu>
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#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 (file)
index 0000000..16b77d2
--- /dev/null
@@ -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 <string.h>
+#include "lib6lowpan.h"
+/*
+ * This file presents an interface for parsing IP and UDP headers in a
+ * 6loWPAN packet.  
+ *
+ * @author Stephen Dawson-Haggerty <stevedh@cs.berkeley.edu>
+ */
+
+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 (file)
index 0000000..effa083
--- /dev/null
@@ -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 <stdint.h>
+#include <stdio.h>
+// #include <arpa/inet.h>
+#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 (file)
index 0000000..d627873
--- /dev/null
@@ -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 (file)
index 0000000..de8bff1
--- /dev/null
@@ -0,0 +1,219 @@
+
+#include <stdio.h>
+#include <stdint.h>
+// #include <assert.h>
+#include <string.h>
+
+#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 (file)
index 0000000..d937b06
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __CIRC_H_
+#define __CIRC_H_
+
+#include <stdint.h>
+
+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 (file)
index 0000000..21b8c4d
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#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 (file)
index 0000000..6b25d1f
--- /dev/null
@@ -0,0 +1,162 @@
+#ifndef TCPLIB_H_
+#define TCPLIB_H_
+
+// #include <netinet/in.h>
+#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 (file)
index 0000000..b6ae8fc
--- /dev/null
@@ -0,0 +1,78 @@
+
+#include <stdio.h>
+#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 (file)
index 0000000..4f39e57
--- /dev/null
@@ -0,0 +1,175 @@
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/if.h>
+#include <signal.h>
+#include <string.h>
+
+
+#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 (file)
index 0000000..1949d88
--- /dev/null
@@ -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
index de06e535c725a8c483aa9f1fad44981b35b723bf..dd8c78a8ddbdb3415f1fac468d5e332cec8885d7 100644 (file)
@@ -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 (file)
index 0000000..d9657ec
--- /dev/null
@@ -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 (file)
index 0000000..1438171
--- /dev/null
@@ -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<icmp_statistics_t>;
+} 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 (file)
index 0000000..102d077
--- /dev/null
@@ -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 <lib6lowpan.h>
+#include <6lowpan.h>
+#include <ip_malloc.h>
+#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<icmp_statistics_t>;
+
+  uses interface IP;
+  uses interface IPAddress;
+
+  uses interface Leds;
+
+  uses interface Timer<TMilli> as Solicitation;
+  uses interface Timer<TMilli> as Advertisement;
+  uses interface Timer<TMilli> as PingTimer;
+  uses interface LocalTime<TMilli>;
+  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 (file)
index 0000000..c096468
--- /dev/null
@@ -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 (file)
index 0000000..b8af352
--- /dev/null
@@ -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 (file)
index 0000000..ffb2641
--- /dev/null
@@ -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 <message.h>
+#include <lib6lowpan.h>
+
+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 (file)
index 0000000..e74d70d
--- /dev/null
@@ -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<ip_statistics_t> as IPStats;
+    interface Statistics<route_statistics_t> as RouteStats;
+    interface Statistics<icmp_statistics_t> 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 (file)
index 0000000..214b7cd
--- /dev/null
@@ -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 <lib6lowpan.h>
+#include <ip.h>
+#include <in_cksum.h>
+#include <ip_malloc.h>
+#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 <stevedh@cs.berkeley.edu>
+ */
+
+module IPDispatchP {
+  provides {
+    interface SplitControl;
+    // interface for protocols not requiring special hand-holding
+    interface IP[uint8_t nxt_hdr];
+    interface Statistics<ip_statistics_t>;
+  }
+  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<message_t> as FragPool;
+    interface Pool<send_info_t> as SendInfoPool;
+    interface Pool<send_entry_t> as SendEntryPool;
+    interface Queue<send_entry_t *> as SendQueue;
+
+    interface Timer<TMilli> 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 (file)
index 0000000..83ade73
--- /dev/null
@@ -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<route_statistics_t>;
+  uses interface ICMP;
+  uses interface Boot;
+  uses interface IPAddress;
+  uses interface Random;
+
+  uses interface Timer<TMilli> as SortTimer;
+
+  uses interface IP as TGenSend;
+  uses interface Timer<TMilli> 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 (file)
index 0000000..2d7e39f
--- /dev/null
@@ -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!
+ * <p>
+ * 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: <code>PRINTFUART_ENABLED</code>.
+
+ * <p> <pre>
+ * 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); 
+ * </pre>
+ * <pre>URL: http://www.eecs.harvard.edu/~konrad/projects/motetrack</pre>
+ * @author Konrad Lorincz
+ * @version 2.0, January 5, 2005
+ */
+#ifndef PRINTFUART_H
+#define PRINTFUART_H
+#include <stdarg.h>
+#include <stdio.h>
+
+// -------------------------------------------------------------------
+#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<<U2X),UCSR0A);                         // Set UART double speed
+        outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C);  // Set frame format: 8 data-bits, 1 stop-bit
+        inp(UDR0);
+        outp((1 << TXEN) ,UCSR0B);   // Enable uart reciever and transmitter
+
+    #else
+    #if defined(PLATFORM_MICA2DOT)  
+        // 19.2K baud
+        outp(0,UBRR0H);            // Set baudrate to 19.2 KBps
+        outp(12, UBRR0L);
+        outp(0,UCSR0A);            // Disable U2X and MPCM
+        outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C);
+        inp(UDR0);
+        outp((1 << TXEN) ,UCSR0B);
+  
+    #else
+    #if defined(PLATFORM_IMOTE2)
+      //async command result_t UART.init() {
+        
+        /*** 
+           need to configure the ST UART pins for the correct functionality
+           
+           GPIO<46> = 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 (file)
index 0000000..87a2167
--- /dev/null
@@ -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 (file)
index 0000000..f594914
--- /dev/null
@@ -0,0 +1,177 @@
+
+#include <table.h>
+#include <ip.h>
+
+module TcpP {
+  provides interface Tcp[uint8_t client];
+  provides interface Init;
+  uses {
+    interface Boot;
+
+    interface IP;    
+    interface Timer<TMilli>;
+    interface IPAddress;
+  }
+} implementation {
+
+  enum {
+    N_CLIENTS = uniqueCount("TCP_CLIENT"),
+  };
+
+#include <tcplib.h>
+  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 (file)
index 0000000..1c832f1
--- /dev/null
@@ -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 (file)
index 0000000..31cb217
--- /dev/null
@@ -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 (file)
index 0000000..8cb0e5f
--- /dev/null
@@ -0,0 +1,154 @@
+
+#include <ip_malloc.h>
+#include <in_cksum.h>
+
+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 (file)
index 0000000..e4323b7
--- /dev/null
@@ -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 (file)
index 0000000..c1de09f
--- /dev/null
@@ -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 (file)
index 0000000..24fc1ec
--- /dev/null
@@ -0,0 +1,12 @@
+
+#include <ICMP.h>
+
+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 (file)
index 0000000..05214b7
--- /dev/null
@@ -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 (file)
index 0000000..38d3084
--- /dev/null
@@ -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 (file)
index 0000000..8c0f4dd
--- /dev/null
@@ -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 (file)
index 0000000..230a6be
--- /dev/null
@@ -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 <stat_str> {
+  
+  /*
+   * 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 (file)
index 0000000..25f66ec
--- /dev/null
@@ -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 (file)
index 0000000..a2db7cf
--- /dev/null
@@ -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 (file)
index 0000000..034d1b0
--- /dev/null
@@ -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 (file)
index 0000000..1a0e99e
--- /dev/null
@@ -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 <cliang4@cs.jhu.edu>
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ */
+
+#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 (file)
index 0000000..ae94655
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ *  @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..1c901db
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..999c55a
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..d2c7878
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#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 (file)
index 0000000..efa1c1a
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ *  @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..2656e62
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..53c80c5
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..ba5116d
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#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 (file)
index 0000000..979392d
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ *  @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..67c0556
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..045eb07
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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 (file)
index 0000000..8a1e8af
--- /dev/null
@@ -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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#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(), &currentCrc, 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(), &currentCrc, 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 (file)
index 0000000..3796ec5
--- /dev/null
@@ -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 (file)
index 0000000..5974126
--- /dev/null
@@ -0,0 +1,215 @@
+
+#include <Storage.h>
+#include <Shell.h>
+#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<TMilli> 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 <imgno> [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 (file)
index 0000000..ab1ec8a
--- /dev/null
@@ -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 (file)
index 0000000..f3214ed
--- /dev/null
@@ -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 (file)
index 0000000..99ac36e
--- /dev/null
@@ -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 (file)
index 0000000..cc09e4e
--- /dev/null
@@ -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 (file)
index 0000000..cb87f9a
--- /dev/null
@@ -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 (file)
index 0000000..fb98013
--- /dev/null
@@ -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 (file)
index 0000000..04e2890
--- /dev/null
@@ -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 (file)
index 0000000..075c55c
--- /dev/null
@@ -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 (file)
index 0000000..7343617
--- /dev/null
@@ -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 (file)
index 0000000..6f9af62
--- /dev/null
@@ -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 (file)
index 0000000..d3d3a03
--- /dev/null
@@ -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 (file)
index 0000000..8de6f88
--- /dev/null
@@ -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 <ip.h>
+#include <IPDispatch.h>
+#include <ICMP.h>
+#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<TMilli, uint32_t> 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 (file)
index 0000000..52e262f
--- /dev/null
@@ -0,0 +1,31 @@
+
+#include <stdlib.h>
+#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 (file)
index 0000000..346e940
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef TABLE_H_
+#define TABLE_H_
+
+#include <stdint.h>
+
+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