* applied patches from the most recent FreiFunkFirmware (and fixed compile errors...
authorBernd Petrovitsch <bernd@firmix.at>
Wed, 31 Jan 2007 12:38:26 +0000 (12:38 +0000)
committerBernd Petrovitsch <bernd@firmix.at>
Wed, 31 Jan 2007 12:38:26 +0000 (12:38 +0000)
   to http://www.olsr.org/pipermail/olsr-dev/2006-December/254036.html:
  - olsrd-libsmake.patch
  - olsrd-dyngwplain.patch
  - olsrd-txtinfo.patch
  - olsrd-quagga.patch
  - olsrd-quagga-routehandler.patch
  - olsrd-optimize.patch
  - olsrd-bmf-fixes.patch
  - olsrd-fixes-sven-ola.patch
  - olsrd-fixes-jhay-bsd.patch
  - olsrd-fixes-backport.patch
  - olsrd-fixes-routedel.patch
  - olsrd-cpu-overload.patch
  - olsrd-secure_key_path.patch
  - olsrd-hna_ip_fix.patch
  Not applied:
  - olsrd-nameservice+services.patch: This patch produced too many rejects to fix easily.
  - olsrd-fixes-eric.patch: This was not found on the webserver.
  - olsrd-bmf.patch: We had already a "bmf" plug-in in there.
* made the checksum type in the olsrd_secure plug-in "olsr_u8_t" (instead
   of a wild "char *" and "unsigned char *" mix) everywhere. It killed
   lots of warnings.
* localized the checksum_cache array in olsrd_secure.c.

26 files changed:
lib/dyn_gw_plain/.cvsignore [new file with mode: 0644]
lib/dyn_gw_plain/Makefile [new file with mode: 0644]
lib/dyn_gw_plain/README_DYN_GW_PLAIN [new file with mode: 0644]
lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c [new file with mode: 0644]
lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h [new file with mode: 0644]
lib/dyn_gw_plain/version-script.txt [new file with mode: 0644]
lib/quagga/.cvsignore [new file with mode: 0644]
lib/quagga/ChangeLog [new file with mode: 0644]
lib/quagga/Makefile [new file with mode: 0644]
lib/quagga/README [new file with mode: 0644]
lib/quagga/src/olsrd_plugin.c [new file with mode: 0644]
lib/quagga/src/quagga.c [new file with mode: 0644]
lib/quagga/src/quagga.h [new file with mode: 0644]
lib/quagga/src/quagga/zassert.h [new file with mode: 0644]
lib/quagga/src/quagga/zebra.h [new file with mode: 0644]
lib/quagga/test/foo.c [new file with mode: 0644]
lib/quagga/test/foo.pl [new file with mode: 0644]
lib/quagga/test/quagga.try1.c [new file with mode: 0644]
lib/quagga/version-script.txt [new file with mode: 0644]
lib/txtinfo/.cvsignore [new file with mode: 0644]
lib/txtinfo/Makefile [new file with mode: 0644]
lib/txtinfo/README_TXTINFO [new file with mode: 0644]
lib/txtinfo/src/olsrd_plugin.c [new file with mode: 0644]
lib/txtinfo/src/olsrd_txtinfo.c [new file with mode: 0644]
lib/txtinfo/src/olsrd_txtinfo.h [new file with mode: 0644]
lib/txtinfo/version-script.txt [new file with mode: 0644]

diff --git a/lib/dyn_gw_plain/.cvsignore b/lib/dyn_gw_plain/.cvsignore
new file mode 100644 (file)
index 0000000..8f7ace2
--- /dev/null
@@ -0,0 +1,2 @@
+*.d
+olsrd_dyn_gw_plain.so.*
diff --git a/lib/dyn_gw_plain/Makefile b/lib/dyn_gw_plain/Makefile
new file mode 100644 (file)
index 0000000..a11ba29
--- /dev/null
@@ -0,0 +1,57 @@
+# The olsr.org Optimized Link-State Routing daemon(olsrd)
+# Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+# 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 olsr.org, olsrd 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 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.
+#
+# Visit http://www.olsr.org for more information.
+#
+# If you find this software useful feel free to make a donation
+# to the project. For more information see the website or contact
+# the copyright holders.
+#
+# $Id: Makefile,v 1.1 2007/01/31 12:38:25 bernd67 Exp $
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_dyn_gw_plain
+PLUGIN_VER =   0.4
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS)
+               $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install:       $(PLUGIN_FULLNAME)
+               $(STRIP) $(PLUGIN_FULLNAME)
+               $(INSTALL_LIB)
+
+clean:
+               rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
diff --git a/lib/dyn_gw_plain/README_DYN_GW_PLAIN b/lib/dyn_gw_plain/README_DYN_GW_PLAIN
new file mode 100644 (file)
index 0000000..627cede
--- /dev/null
@@ -0,0 +1,17 @@
+DYNAMIC INTERNET GATEWAY PLAIN PLUGIN FOR olsr.org olsrd
+by Andreas Tønnesen(andreto@olsr.org)
+additions by Sven-Ola Tuecke
+
+This plugin is without Ping/libthread. It is the plain dyn_gw!
+
+HOW TO USE
+
+Add an entry like this to your olsrd configuration file:
+
+LoadPlugin "olsrd_dyn_gw_plain.so.0.4"
+{
+}
+
+ABOUT
+
+Plugin is IPv4 only.
diff --git a/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c b/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c
new file mode 100644 (file)
index 0000000..5bf9fe9
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * 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 olsr.org, olsrd 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 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ */
+
+#include "olsr_types.h"
+#include "olsrd_dyn_gw_plain.h"
+#include "scheduler.h"
+#include "olsr.h"
+#include "local_hna_set.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <net/route.h>
+#include <linux/in_route.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define DEBUGLEV 1
+
+static int has_inet_gateway;
+
+/**
+ * Plugin interface version
+ * Used by main olsrd to check plugin interface version
+ */
+int 
+olsrd_plugin_interface_version()
+{
+  return OLSRD_PLUGIN_INTERFACE_VERSION;
+}
+
+/**
+ * Register parameters from config file
+ * Called for all plugin parameters
+ */
+int
+olsrd_plugin_register_param(char *key, char *value)
+{
+  return 1;
+}
+
+/**
+ * Initialize plugin
+ * Called after all parameters are passed
+ */
+int
+olsrd_plugin_init()
+{
+  gw_net.v4 = INET_NET;
+  gw_netmask.v4 = INET_PREFIX;
+
+  has_inet_gateway = 0;
+  
+  /* Remove all local Inet HNA entries */
+  while(remove_local_hna4_entry(&gw_net, &gw_netmask)) {
+    olsr_printf(DEBUGLEV, "HNA Internet gateway deleted\n");
+  }
+
+  /* Register the GW check */
+  olsr_register_scheduler_event(&olsr_event, NULL, 3, 4, NULL);
+
+  return 1;
+}
+
+int
+check_gw(union olsr_ip_addr *net, union olsr_ip_addr *mask)
+{
+    char buff[1024], iface[16];
+    olsr_u32_t gate_addr, dest_addr, netmask;
+    unsigned int iflags;
+    int num, metric, refcnt, use;
+    int retval = 0;
+
+    FILE *fp = fopen(PROCENTRY_ROUTE, "r");
+
+    if (!fp) 
+      {
+        perror(PROCENTRY_ROUTE);
+        olsr_printf(DEBUGLEV, "INET (IPv4) not configured in this system.\n");
+        return -1;
+      }
+    
+    rewind(fp);
+
+    /*
+    olsr_printf(DEBUGLEV, "Genmask         Destination     Gateway         "
+                "Flags Metric Ref    Use Iface\n");
+    */
+    while (fgets(buff, 1023, fp)) 
+      {        
+       num = sscanf(buff, "%16s %128X %128X %X %d %d %d %128X \n",
+                    iface, &dest_addr, &gate_addr,
+                    &iflags, &refcnt, &use, &metric, &netmask);
+
+       if (num < 8)
+         {
+           continue;
+         }
+
+       /*
+       olsr_printf(DEBUGLEV, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&netmask));
+
+       olsr_printf(DEBUGLEV, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&dest_addr));
+
+       olsr_printf(DEBUGLEV, "%-15s %-6d %-2d %7d %s\n",
+                   olsr_ip_to_string((union olsr_ip_addr *)&gate_addr),
+                   metric, refcnt, use, iface);
+       */
+
+       if(//(iflags & RTF_GATEWAY) &&
+          (iflags & RTF_UP) &&
+          (metric == 0) &&
+          (netmask == mask->v4) && 
+          (dest_addr == net->v4))
+         {
+            olsr_printf(DEBUGLEV, "INTERNET GATEWAY VIA %s detected in routing table.\n", iface);
+            retval=1;
+         }
+
+    }
+
+    fclose(fp);  
+  
+    if(retval == 0)
+      {
+       olsr_printf(DEBUGLEV, "No Internet GWs detected...\n");
+      }
+  
+    return retval;
+}
+
+/**
+ * Scheduled event to update the hna table,
+ * called from olsrd main thread to keep the hna table thread-safe
+ */
+void olsr_event(void* foo)
+{
+  int res = check_gw(&gw_net, &gw_netmask);
+  if (1 == res && 0 == has_inet_gateway) {
+    olsr_printf(DEBUGLEV, "Adding OLSR local HNA entry for Internet\n");
+    add_local_hna4_entry(&gw_net, &gw_netmask);
+    has_inet_gateway = 1;
+  }
+  else if (0 == res && 1 == has_inet_gateway) {
+    /* Remove all local Inet HNA entries */
+    while(remove_local_hna4_entry(&gw_net, &gw_netmask)) {
+      olsr_printf(DEBUGLEV, "Removing OLSR local HNA entry for Internet\n");
+    }
+    has_inet_gateway = 0;
+  }
+}
diff --git a/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h b/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h
new file mode 100644 (file)
index 0000000..ab51c40
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * 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 olsr.org, olsrd 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 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ */
+
+#ifndef _OLSRD_PLUGIN_TEST
+#define _OLSRD_PLUGIN_TEST
+
+#include "olsrd_plugin.h"
+#include "olsr.h"
+
+#define INET_NET       0
+#define INET_PREFIX    0
+
+#define PROCENTRY_ROUTE "/proc/net/route"
+
+union olsr_ip_addr gw_net;
+union olsr_ip_addr gw_netmask;
+
+int check_gw(union olsr_ip_addr *net, union olsr_ip_addr *mask);
+
+/* Event function to register with the scheduler */
+void olsr_event(void* foo);
+
+#endif
diff --git a/lib/dyn_gw_plain/version-script.txt b/lib/dyn_gw_plain/version-script.txt
new file mode 100644 (file)
index 0000000..3d09da3
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_register_param;
+    olsrd_plugin_init;
+
+  local:
+    *;
+};
diff --git a/lib/quagga/.cvsignore b/lib/quagga/.cvsignore
new file mode 100644 (file)
index 0000000..a84a60d
--- /dev/null
@@ -0,0 +1,2 @@
+*.d
+olsrd_quagga.so.*
diff --git a/lib/quagga/ChangeLog b/lib/quagga/ChangeLog
new file mode 100644 (file)
index 0000000..b80cf55
--- /dev/null
@@ -0,0 +1,17 @@
+0.2.1: Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>:
+       * now check (most of the) return-values of syscalls, improvement still
+         possible...
+       * added support for new zebra-protocoll-format (with
+         ZEBRA_HEADER_MARKER and ZCLIENT_VERSION) if new 
+         quagga-headers are found)
+       * Code Cleanup (removed lot of debug and test-stuff)
+       * fixed return-bug in zebra_send_command
+       * added copyright-stuff 
+       * removed memleak in zebra_add/delete_v4_route
+
+0.2.0: Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>:
+       * Initial release, too :-) 
+       * Added support for route-export to the zebra/quagga
+       
+0.1.0: Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>:
+       * Initial release
diff --git a/lib/quagga/Makefile b/lib/quagga/Makefile
new file mode 100644 (file)
index 0000000..1760f48
--- /dev/null
@@ -0,0 +1,65 @@
+# The olsr.org Optimized Link-State Routing daemon(olsrd)
+# Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+# 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 olsr.org, olsrd 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 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.
+#
+# Visit http://www.olsr.org for more information.
+#
+# If you find this software useful feel free to make a donation
+# to the project. For more information see the website or contact
+# the copyright holders.
+#
+# $Id: Makefile,v 1.1 2007/01/31 12:38:26 bernd67 Exp $
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_quagga
+PLUGIN_VER =   0.2.2
+
+#CFLAGS +=-DMY_DEBUG 
+CFLAGS += -g
+CFLAGS +=-DUSE_UNIX_DOMAIN_SOCKET
+
+#uncomment the following line only if you are sure what you're doing, it will 
+#probably break things! 
+# CFLAGS +=-DZEBRA_HEADER_MARKER=255 
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS)
+               $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install:       $(PLUGIN_FULLNAME)
+               $(STRIP) $(PLUGIN_FULLNAME)
+               $(INSTALL_LIB)
+
+clean:
+               rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
diff --git a/lib/quagga/README b/lib/quagga/README
new file mode 100644 (file)
index 0000000..cd53a8d
--- /dev/null
@@ -0,0 +1,58 @@
+---------------------------------------------------------------------
+QUAGGA PLUGIN FOR OLSRD
+by Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>
+---------------------------------------------------------------------
+
+This is the Quagga Plugin for the OLSRD. 
+It allowes olsrd to redistribute from various quagga-protocols 
+as well as to export olsr-routes to quagga so that they can be
+redistributed by the quagga-routing-daemons.
+
+Note Sven-Ola: You also need a source distribution of quagga-0.98.5
+or quagga-0.98.6 (that is the current stable). The quagga source tree 
+needs to be patched with quagga-0.98.6-olsr.diff, compiled and installed
+via 'make install'. Because many people will otherwise have compile
+probs, I've added 2 include files in lib/quagga/src/quagga. If you
+want to use another version of quagga, make sure to remove these
+before you compile the olsrd_quagga plugin.
+
+---------------------------------------------------------------------
+PLUGIN PARAMETERS (PlParam)
+---------------------------------------------------------------------
+
+PlParam "redistribute" "<protocol>"
+       where protocol is one of the following:
+       system, kernel, connect, static, rip, ripng, ospf, ospf6,
+       isis, bgp, hsls
+       May be used more then once
+
+PlParam "ExportRoutes" "<only/both>"
+       exportes olsr-routes to quagga or to both, quagga and kernel
+       no routes are exportet if not set.
+
+PlParam "Localpref" "true"
+        sets the zebra SELECTED-flag on the routes exported to zebra
+       which means these routes are prefered in any case.
+
+PlParam "Distance" "0-255"
+        allowes to set Administrative distance to routes exported 
+       to zebra.
+       
+---------------------------------------------------------------------
+SAMPLE CONFIG
+---------------------------------------------------------------------
+
+add in /etc/olsrd.conf:
+
+LoadPlugin "olsrd_quagga.so.0.2.2"
+{
+       PlParam "redistribute" "ospf"
+       PlParam "redistribute" "bgp"
+       PlParam "ExportRoutes" "only"
+        PlParam "Distance" "125" 
+       PlParam "Localpref" "false"
+}
+
+
+---------------------------------------------------------------------
+EOF / 8.5.2006
diff --git a/lib/quagga/src/olsrd_plugin.c b/lib/quagga/src/olsrd_plugin.c
new file mode 100644 (file)
index 0000000..46e7cf1
--- /dev/null
@@ -0,0 +1,107 @@
+/***************************************************************************
+ projekt              : olsrd-quagga
+ file                 : olsrd_plugin.c  
+ usage                : olsrd-plugin-handler-stuff 
+ copyright            : (C) 2006 by Immo 'FaUl' Wehrenberg
+ e-mail               : immo@chaostreff-dortmund.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License version 2 as     *
+ *   published by the Free Software Foundation.                            *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "olsrd_plugin.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "defs.h"
+#include "quagga.h"
+#include "kernel_routes.h"
+
+#define PLUGIN_NAME    "OLSRD quagga plugin"
+#define PLUGIN_VERSION "0.2.2"
+#define PLUGIN_AUTHOR  "Immo 'FaUl' Wehrenberg"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+
+static void __attribute__ ((constructor)) my_init(void);
+static void __attribute__ ((destructor)) my_fini(void);
+static void redist_hna (void);
+
+
+int olsrd_plugin_interface_version() {
+  return OLSRD_PLUGIN_INTERFACE_VERSION;
+}
+
+
+int olsrd_plugin_register_param(char *key, char *value) {
+  const char *zebra_route_types[] = {"system","kernel","connect","static",
+                             "rip","ripng","ospf","ospf6","isis",
+                             "bgp","hsls", NULL};
+  unsigned char i = 0;
+
+  if(!strcmp(key, "redistribute")) {
+    for (i = 0; zebra_route_types[i]; i++)
+      if (!strcmp(value, zebra_route_types[i])) {
+       zebra_redistribute(i);
+       return 1;
+      }
+  }
+  else if(!strcmp(key, "ExportRoutes")) {
+    if (!strcmp(value, "only")) {
+      if (!olsr_addroute_remove_function(&olsr_ioctl_add_route, AF_INET))
+       puts ("AIII, could not remove the kernel route exporter");
+      if (!olsr_delroute_remove_function(&olsr_ioctl_del_route, AF_INET))
+       puts ("AIII, could not remove the kernel route deleter");
+      olsr_addroute_add_function(&zebra_add_olsr_v4_route, AF_INET);
+      olsr_delroute_add_function(&zebra_del_olsr_v4_route, AF_INET);
+      return 1;
+    }
+    else if (!strcmp(value, "additional")) {
+      olsr_addroute_add_function(&zebra_add_olsr_v4_route, AF_INET);
+      olsr_delroute_add_function(&zebra_del_olsr_v4_route, AF_INET);
+      return 1;
+    }
+  }
+  else if (!strcmp(key, "Distance")) {
+    unsigned int distance = atoi (key);
+    if (distance < 255)
+      zebra_olsr_distance(distance);
+      return 1;
+  }
+  
+  else if (!strcmp(key, "LocalPref")) {
+    if (!strcmp(key, "true")) 
+      zebra_olsr_localpref();
+    else if (strcmp (key, "false"))
+      return -1;
+    return 1;
+  }
+  return -1;
+}
+
+
+int olsrd_plugin_init() {
+  if(olsr_cnf->ip_version != AF_INET) {
+    fputs("see the source - ipv4 so far not supportet\n" ,stderr);
+    return 1;
+  }
+
+  //  olsr_register_timeout_function(&olsr_timeout);
+  olsr_register_scheduler_event(&zebra_check, NULL, 1, 0, NULL);
+  return 0;
+}
+
+static void my_init(void) {
+  init_zebra();
+}
+
+static void my_fini(void) {
+}
+
diff --git a/lib/quagga/src/quagga.c b/lib/quagga/src/quagga.c
new file mode 100644 (file)
index 0000000..1438120
--- /dev/null
@@ -0,0 +1,870 @@
+/***************************************************************************
+ projekt              : olsrd-quagga
+ file                 : quagga.c  
+ usage                : communication with the zebra-daemon 
+ copyright            : (C) 2006 by Immo 'FaUl' Wehrenberg
+ e-mail               : immo@chaostreff-dortmund.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License version 2 as     *
+ *   published by the Free Software Foundation.                            *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#ifdef MY_DEBUG
+#include <stdio.h>
+#endif
+
+#define HAVE_SOCKLEN_T
+#include <quagga/zebra.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "quagga.h"
+
+#include "olsr.h"
+#include "log.h"
+#include "defs.h"
+#include "local_hna_set.h"
+
+#ifdef USE_UNIX_DOMAIN_SOCKET
+#include <sys/un.h>
+#define ZEBRA_SOCKET "/var/run/quagga/zserv.api"
+#endif
+
+#define ZAPI_MESSAGE_NEXTHOP  0x01
+#define ZAPI_MESSAGE_IFINDEX  0x02
+#define ZAPI_MESSAGE_DISTANCE 0x04
+#define ZAPI_MESSAGE_METRIC   0x08
+
+#define BUFSIZE 1024
+
+#define STATUS_CONNECTED 1
+
+static struct {
+  char status; // TODO: internal status
+  int sock; // Socket to zebra...
+  char redistribute[ZEBRA_ROUTE_MAX];
+  char distance;
+  char flags;
+  struct ipv4_route *v4_rt; // routes currently exportet to zebra
+} zebra;
+
+
+/* prototypes intern */
+static char *try_read (ssize_t *);
+static char* zebra_route_packet (struct ipv4_route r, ssize_t *);
+static int parse_interface_add (char *, size_t);
+static int parse_interface_delete (char *, size_t);
+static int parse_interface_up (char *, size_t);
+static int parse_interface_down (char *, size_t);
+static int parse_interface_address_add (char *, size_t);
+static int parse_interface_address_delete (char *, size_t);
+static int parse_ipv4_route (char *, size_t, struct ipv4_route *);
+static int ipv4_route_add (char *, size_t);
+static int ipv4_route_delete (char *, size_t);
+static int parse_ipv6_route_add (char*, size_t);
+static int zebra_reconnect (void);
+static int zebra_connect (void);
+static int add_v4_route_status (struct ipv4_route r);
+static int del_v4_route_status (struct ipv4_route r);
+static uint32_t prefixlentomask (uint8_t);
+static void free_ipv4_route (struct ipv4_route);
+static void update_olsr_zebra_routes (struct ipv4_route*, struct ipv4_route*);
+static struct ipv4_route *zebra_create_ipv4_route_table_entry (uint32_t,
+                                                              uint32_t,
+                                                              uint32_t);
+static struct ipv4_route *zebra_create_ipv4_route_table (void);
+static void zebra_free_ipv4_route_table (struct ipv4_route*);
+static uint8_t masktoprefixlen (uint32_t);
+
+
+
+#ifdef MY_DEBUG
+static void dump_ipv4_route (struct ipv4_route r, char *c) {
+  int i = 0, x = 0;
+
+  puts (c);
+  printf("type: %d\n", r.type);
+  puts("flags:");
+  printf("  Internal: %s\n",r.flags&ZEBRA_FLAG_INTERNAL?"yes":"no");
+  printf("  Selfroute %s\n",r.flags&ZEBRA_FLAG_SELFROUTE?"yes":"no");
+  printf("  Blackhole %s\n",r.flags&ZEBRA_FLAG_BLACKHOLE?"yes":"no");
+  printf("  IBGP: %s\n",r.flags&ZEBRA_FLAG_IBGP?"yes":"no");
+  printf("  Selected: %s\n",r.flags&ZEBRA_FLAG_SELECTED?"yes":"no");
+  printf("  Changed: %s\n",r.flags&ZEBRA_FLAG_CHANGED?"yes":"no");
+  printf("  static: %s\n",r.flags&ZEBRA_FLAG_STATIC?"yes":"no");
+  printf("  reject: %s\n",r.flags&ZEBRA_FLAG_REJECT?"yes":"no");
+  puts("message:");
+  printf("  nexthop: %s\n",r.message&ZAPI_MESSAGE_NEXTHOP?"yes":"no");
+  printf("  ifindex: %s\n",r.message&ZAPI_MESSAGE_IFINDEX?"yes":"no");
+  printf("  distance: %s\n",r.message&ZAPI_MESSAGE_DISTANCE?"yes":"no");
+  printf("  metric: %s\n",r.message&ZAPI_MESSAGE_METRIC?"yes":"no");
+  printf("Prefixlen: %d\n", r.prefixlen);
+  printf("Prefix: %d", (unsigned char)r.prefix);
+  c = (char*) &r.prefix;
+  while (++i < (r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0)))
+    printf(".%d",(unsigned char)*(c + i));
+  while (i++ < 4)
+    printf(".0");
+  puts("");
+  i=0;
+  if (r.message&ZAPI_MESSAGE_NEXTHOP) {
+    printf("nexthop-count: %d\n", r.nh_count);
+    while (i++ < r.nh_count) {
+      if (r.nexthops[i].type == ZEBRA_NEXTHOP_IPV4) {
+       c = (unsigned char*) &r.nexthops[i].payload.v4;
+       printf ("Nexthop %d: %d", i, (unsigned char) *c);
+       while (++x < 4) {
+         printf (".%d", (unsigned char) c[x]);
+       }
+       puts("");
+      }
+    }
+    i=0;
+  }
+  if (r.message&ZAPI_MESSAGE_IFINDEX) {
+    
+    printf("index-number: %d\n", r.ind_num);
+    while (i++ < r.ind_num)
+      printf("Index: %d: %d\n", i, r.index[i]);
+    i=0;
+    if (r.message&ZAPI_MESSAGE_DISTANCE)
+      printf("Distance: %d\n",r.distance);
+    if (r.message&ZAPI_MESSAGE_METRIC)
+      printf("Metric: %d\n",r.metric);
+    puts("\n");
+  }
+}
+#endif
+
+void *my_realloc (void *buf, size_t s, const char *c) {
+  buf = realloc (buf, s);
+  if (!buf) {
+    OLSR_PRINTF (1, "OUT OF MEMORY: %s\n", strerror(errno));
+    olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
+    olsr_exit(c, EXIT_FAILURE);
+  }
+  return buf;
+}
+
+int init_zebra () {
+  if (!zebra_connect()) {
+    olsr_exit ("AIIIII, could not connect to zebra! is zebra running?", 
+              EXIT_FAILURE);
+  }
+}
+
+
+static int zebra_reconnect (void) {
+  struct ipv4_route *tmp;
+  int i;
+
+  if (!zebra_connect()) 
+    // log: zebra-reconnect failed
+    ;
+  for (i = 0; ZEBRA_ROUTE_MAX - 1; i++)
+    if (zebra.redistribute[i]) zebra_redistribute(i + 1);
+
+  for (tmp = zebra.v4_rt; tmp; tmp = tmp->next)
+    zebra_add_v4_route(*tmp);
+}
+
+
+static int add_v4_route_status (struct ipv4_route r) {
+
+  struct ipv4_route *tmp = olsr_malloc (sizeof r, "quagga_v4_route_status");
+  memcpy (tmp, &r, sizeof r);
+
+  if (r.message & ZAPI_MESSAGE_NEXTHOP) {
+    tmp->nexthops = olsr_malloc (r.nh_count * sizeof tmp->nexthops, 
+                                "quagga_v4_route_status");
+    memcpy (tmp->nexthops, &r.nexthops, sizeof *r.nexthops);
+  }
+
+  if (r.message & ZAPI_MESSAGE_IFINDEX) {
+    tmp->index = olsr_malloc (r.ind_num * sizeof *tmp->index, 
+                             "quagga_v4_route_status");
+    memcpy (tmp->index, &r.index, r.ind_num * sizeof *tmp->index);
+  }
+
+  tmp->next = zebra.v4_rt;
+  zebra.v4_rt = tmp;
+
+  return 0;
+
+}
+
+
+static int cmp_v4_route (struct ipv4_route a, struct ipv4_route b) {
+  if (a.type != b.type) return 1;
+  if (a.flags != b.flags) return 1;
+  if (a.message != b.message) return 1;
+  if (a.prefixlen != b.prefixlen) return 1;
+  if (a.message & ZAPI_MESSAGE_NEXTHOP) {
+    if (a.nh_count != b.nh_count) return 1;
+    if (memcmp (a.nexthops, b.nexthops, a.nh_count * sizeof *b.nexthops)) 
+      return 1;
+  }
+  if (a.message & ZAPI_MESSAGE_IFINDEX) {
+    if (a.ind_num != b.ind_num) return 1;
+    if (memcpy (a.index, b.index, a.ind_num * sizeof *a.index)) return 1;
+  }
+  if (a.message & ZAPI_MESSAGE_DISTANCE) 
+    if (a.distance != b.distance) return 1;
+  if (a.message & ZAPI_MESSAGE_METRIC)
+    if (a.metric != b.metric) return 1;
+  return 0;
+}
+
+static int del_v4_route_status (struct ipv4_route r) {
+
+  struct ipv4_route *tmp, *prv = 0;
+
+  for (tmp = zebra.v4_rt; tmp; tmp = tmp->next) {
+    if (!cmp_v4_route(*tmp, r)) {
+      if (prv) prv->next = tmp->next;
+
+      free_ipv4_route(*tmp);
+      free (tmp);
+
+      return 0;
+
+    }
+    prv = tmp;
+  }
+
+  return 1;
+}
+
+
+/* Connect to the zebra-daemon, returns a socket */
+static int zebra_connect (void) {
+
+#ifndef USE_UNIX_DOMAIN_SOCKET
+  struct sockaddr_in i;
+  close (zebra.sock);
+
+  zebra.sock = socket (AF_INET,SOCK_STREAM, 0);
+#else
+  struct sockaddr_un i;
+  close (zebra.sock);
+
+  zebra.sock = socket (AF_UNIX,SOCK_STREAM, 0);
+#endif
+
+  int ret;
+
+  if (zebra.sock <0 )
+    olsr_exit("could not create socket!", EXIT_FAILURE);
+  
+  memset (&i, 0, sizeof i);
+#ifndef USE_UNIX_DOMAIN_SOCKET
+  i.sin_family = AF_INET;
+  i.sin_port = htons (ZEBRA_PORT);
+  i.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+#else
+  i.sun_family = AF_UNIX;
+  strcpy (i.sun_path, ZEBRA_SOCKET);
+#endif
+
+  ret = connect (zebra.sock, (struct sockaddr *)&i, sizeof i);
+  if  (ret < 0) {
+    close (zebra.sock);
+  }
+  else zebra.status |= STATUS_CONNECTED;
+  return zebra.sock;
+}
+
+    
+/* Sends a command to zebra, command is 
+   the command defined in zebra.h, options is the packet-payload, 
+   optlen the length, of the payload */
+char zebra_send_command (unsigned char command, char * options, int optlen) {
+
+#ifdef ZEBRA_HEADER_MARKER
+  char *p = olsr_malloc (optlen + 6, "zebra_send_command");
+  uint16_t length = optlen + 6; /* length of option + command + packet_length +
+                                  marker + zserv-version */
+  uint16_t cmd;
+#else
+  char *p = olsr_malloc (optlen + 3, "zebra_send_command");
+  uint16_t length = optlen + 3;  // length of option + command + packet_length
+#endif
+  
+  int ret;
+  
+  uint16_t len = htons(length);
+  memcpy (p, &len, 2);
+
+#ifdef ZEBRA_HEADER_MARKER
+  p[2] = ZEBRA_HEADER_MARKER;
+  p[3] = ZSERV_VERSION;
+  cmd = htons (command);
+  memcpy (p + 4, &cmd, 2);
+  memcpy (p + 6, options, optlen);
+#else
+  p[2] = command;
+  memcpy (p + 3, options, optlen);
+#endif
+
+  errno = 0;
+
+  do {
+    ret = write (zebra.sock, p, length);
+    if (ret < 0) {
+      if (errno == EINTR) {
+       errno = 0;
+       continue;
+      }
+      else {
+       zebra.status &= ~STATUS_CONNECTED;
+       return -1;
+      }
+    }
+    p = p+ret;
+  } while ((length -= ret));
+
+  return 0;
+}
+
+
+/* Creates a Route-Packet-Payload, needs address, netmask, nexthop, 
+   distance, and a pointer of an size_t */
+static char* zebra_route_packet (struct ipv4_route r, ssize_t *optlen) {
+
+  int count;
+
+  char *cmdopt, *t;
+  *optlen = 4; // first: type, flags, message, prefixlen
+  *optlen += r.prefixlen / 8 + (r.prefixlen % 8 ? 1 : 0); // + prefix
+  if (r.message & ZAPI_MESSAGE_NEXTHOP)
+    if (r.nexthops->type == ZEBRA_NEXTHOP_IPV4 
+       || r.nexthops->type == ZEBRA_NEXTHOP_IPV4_IFINDEX){
+      *optlen += (sizeof r.nexthops->payload.v4 
+                 + sizeof r.nexthops->type) * r.nh_count + 1;
+    }
+    else if (r.nexthops->type == 0) 
+      *optlen += 5;
+  if (r.message & ZAPI_MESSAGE_IFINDEX)
+    *optlen += r.ind_num * sizeof *r.index + 1;
+  if (r.message & ZAPI_MESSAGE_DISTANCE)
+    *optlen++;
+  if (r.message & ZAPI_MESSAGE_METRIC)
+    *optlen += sizeof r.metric;
+
+  cmdopt = olsr_malloc (*optlen, "zebra add_v4_route");
+
+  t = cmdopt;
+  *t++ = r.type; 
+  *t++ = r.flags; 
+  *t++ = r.message;
+  *t++ = r.prefixlen;
+  for (count = 0; count < r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0); count++) {
+    *t++ = *((char*)&r.prefix + count); /* this is so sick!! */
+  }
+
+  if (r.message & ZAPI_MESSAGE_NEXTHOP) {
+    *t++ = r.nh_count;
+    *t++ = r.nexthops->type;
+    if (r.nexthops->type == ZEBRA_NEXTHOP_IPV4 || 
+       r.nexthops->type == ZEBRA_NEXTHOP_IPV4_IFINDEX) {
+      for (count = 0; count != r.nh_count; count++) {
+       memcpy (t, &r.nexthops[count].payload.v4, 
+               sizeof r.nexthops->payload.v4);
+       t += sizeof r.nexthops->payload.v4;
+      }
+    }
+    else if (r.nexthops->type == 0) {
+      *t++ = 0;
+      *t++ = 0;
+      *t++ = 0;
+    }
+  }
+  if (r.message & ZAPI_MESSAGE_IFINDEX) {
+    *t++ = r.ind_num;
+    memcpy (t, r.index, sizeof *r.index * r.ind_num);
+    t += sizeof r.index * r.ind_num;
+  }
+  if (r.message & ZAPI_MESSAGE_METRIC) {
+    memcpy (t, &r.metric, sizeof r.metric);
+    t += sizeof r.metric;
+  }
+  if (r.message & ZAPI_MESSAGE_DISTANCE)
+    *t++ = r.distance;
+  return cmdopt;
+}
+
+
+/* adds a route to zebra-daemon */
+int zebra_add_v4_route (struct ipv4_route r) {
+  
+  char *cmdopt;
+  ssize_t optlen;
+  int retval;
+
+  cmdopt = zebra_route_packet (r, &optlen);
+
+  retval = zebra_send_command (ZEBRA_IPV4_ROUTE_ADD, cmdopt, optlen);
+  free (cmdopt);
+  return retval;
+  
+}
+
+/* deletes a route from the zebra-daemon */
+int zebra_delete_v4_route (struct ipv4_route r) {
+  
+  char *cmdopt;
+  ssize_t optlen;
+  int retval;
+
+  cmdopt = zebra_route_packet (r, &optlen);
+  
+  retval = zebra_send_command (ZEBRA_IPV4_ROUTE_DELETE, cmdopt, optlen);
+  free (cmdopt);
+
+  return retval;
+  
+}
+
+
+/* Check wether there is data from zebra aviable */
+void zebra_check (void* foo) {
+  char *data, *f;
+  ssize_t len, ret;
+
+  if (!(zebra.status & STATUS_CONNECTED)) {
+    if (!zebra_reconnect()) return;
+  }
+  data = try_read (&len);
+  if (data) {
+    f = data;
+    do {
+      ret = zebra_parse_packet (f, len);
+      if (!ret) {//something wired happened
+       puts ("DEBUG: IIIIIIIIIIRGS");
+       exit (EXIT_FAILURE);
+      }
+      f += ret;
+    } while ((f - data) < len);
+    free (data);
+  }
+}
+
+
+// tries to read a packet from zebra_socket
+// if there is something to read - make sure to read whole packages
+static char *try_read (ssize_t *len) {
+  char *buf = NULL;
+  ssize_t ret = 0, bsize = 0;
+  uint16_t length = 0, l = 0;
+  int sockstate;
+
+  *len = 0;
+
+  sockstate = fcntl (zebra.sock, F_GETFL, 0);
+  fcntl (zebra.sock, F_SETFL, sockstate|O_NONBLOCK);
+
+  do { 
+    if (*len == bsize) {
+      bsize += BUFSIZE;
+      buf = my_realloc (buf, bsize, "Zebra try_read");
+    }
+    ret = read (zebra.sock, buf + l, bsize - l);
+    if (ret <= 0) {
+      if (errno == EAGAIN) {
+       errno = 0;
+      }
+      else {
+       olsr_printf(1, "OOPS, something realy wired happened:"
+                   "read returned %s\n", strerror(errno));
+       errno = 0;
+       zebra.status &= ~STATUS_CONNECTED;
+       return 0;
+      }
+      free (buf);
+      return NULL;
+    }
+    *len += ret;
+
+    while ((*len - l) > length) {
+      l += length;
+      memcpy (&length, buf + l, 2);
+      length = ntohs (length);
+    }
+    if (((*len) - l) == length) break; // GOT FULL PACKAGE!!
+    if (*len < l) {
+      fcntl (zebra.sock, F_SETFL, sockstate);
+      continue;
+    }
+  } while (1);
+
+  fcntl (zebra.sock, F_SETFL, sockstate);
+  return buf;
+}
+
+
+/* Parse a packet recived from zebra */
+int zebra_parse_packet (char *packet, ssize_t maxlen) {
+
+  /* Array of functions */
+  int (*foo[ZEBRA_MESSAGE_MAX]) (char *, size_t) = {
+    parse_interface_add,
+    parse_interface_delete,
+    parse_interface_address_add,
+    parse_interface_address_delete,
+    parse_interface_up,
+    parse_interface_down,
+    ipv4_route_add,
+    ipv4_route_delete,
+    parse_ipv6_route_add
+  };
+
+#ifdef MY_DEBUG
+  puts ("DEBUG: zebra_parse_packet");
+#endif
+  uint16_t length;
+  
+  int ret;
+  memcpy (&length, packet, 2);
+  length = ntohs (length);
+  
+  if (maxlen < length) {
+    puts("Error: programmer is an idiot");
+    printf ("DEBUG: maxlen = %d, packet_length = %d\n", maxlen, length);
+    return maxlen;
+  }
+
+  if (packet[2] - 1 < ZEBRA_MESSAGE_MAX && foo[packet[2] - 1]) { 
+    if (!(ret = foo[packet[2] - 1] (packet + 3, length - 3))) 
+      return length;
+    else printf ("DEBUG: Parse error: %d\n", ret);
+  }
+  else
+    printf ("Unknown packet type: %d\n", packet[2]);
+
+  puts ("Quagga: RECIVED PACKET FROM ZEBRA THAT I CAN'T PARSE");
+
+  return length;
+}
+
+
+static int parse_interface_add (char *opt, size_t len) {
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_delete (char *opt, size_t len) {
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_address_add (char *opt, size_t len) {
+  
+  //todo
+  return 0;
+}
+
+static int parse_interface_up (char *opt, size_t len) {
+  
+  //todo
+  return 0;
+}
+
+static int parse_interface_down (char *opt, size_t len) {
+  
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_address_delete (char *opt, size_t  len) {
+  //todo
+  return 0;
+}
+
+
+/* Parse an ipv4-route-packet recived from zebra
+ */
+static int parse_ipv4_route (char *opt, size_t len, struct ipv4_route *r) {
+  int c;
+
+  if (len < 4) return -1;
+  
+  r->type = *opt++;
+  r->flags = *opt++;
+  r->message = *opt++;
+  r->prefixlen = *opt++;
+  len -= 4;
+  r->prefix = 0;
+  
+  if ((int)len < r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0)) return -1;
+  
+  memcpy (&r->prefix, opt, r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0));
+  opt += r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0);
+  
+  if (r->message & ZAPI_MESSAGE_NEXTHOP) {
+    if (len < 1) return -1;
+    r->nh_count = *opt++;
+    len--;
+    if (len < (sizeof (uint32_t) + 1) * r->nh_count) return -1;
+    r->nexthops = olsr_malloc ((sizeof r->nexthops->type +
+                               sizeof r->nexthops->payload) * r->nh_count,
+                              "quagga: parse_ipv4_route_add");
+    for (c = 0; c < r->nh_count; c++) {
+      r->nexthops[c].type = *opt++;
+      memcpy (&r->nexthops[c].payload.v4, opt, sizeof (uint32_t));
+      opt += sizeof (uint32_t);
+      len -= sizeof (uint32_t) + 1;
+    }
+  }
+
+  if (r->message & ZAPI_MESSAGE_IFINDEX) {
+    if (len < 1) return -1;
+    r->ind_num = *opt++;
+    if (len < sizeof (uint32_t) * r->ind_num) return -1;
+    r->index = olsr_malloc (sizeof (uint32_t) * r->ind_num,
+                           "quagga: parse_ipv4_route_add");
+    memcpy (r->index, opt, r->ind_num * sizeof (uint32_t));
+    opt += sizeof (uint32_t) * r->ind_num;
+    len -= sizeof (uint32_t) * r->ind_num;
+  }
+
+  if (r->message & ZAPI_MESSAGE_DISTANCE) {
+    if (len < 1) return -1;
+    r->distance = *opt++;
+    len--;
+  }
+
+  if (r->message & ZAPI_MESSAGE_METRIC) {
+    if (len < sizeof (uint32_t)) return -1;
+    memcpy (&r->metric, opt, sizeof (uint32_t));
+  }
+
+  return 0;
+}
+
+
+static int ipv4_route_add (char *opt, size_t len) {
+
+  struct ipv4_route r;
+  int f;
+    
+  f = parse_ipv4_route (opt, len, &r);
+  if (f < 0) {
+    printf ("parse-error: %d\n",f);
+    return f;
+  }
+  
+  add_hna4_route (r);
+  return 0;
+}
+
+static int ipv4_route_delete (char *opt, size_t len) {
+  struct ipv4_route r;
+  int f;
+  
+  f = parse_ipv4_route (opt, len, &r);
+  if (f < 0) return f;
+
+  return delete_hna4_route (r);
+  
+}
+
+static int parse_ipv6_route_add (char *opt, size_t len) {
+  //todo
+  return 0;
+}
+
+
+/* start redistribution FROM zebra */
+int zebra_redistribute (unsigned char type) {
+
+  if (type > ZEBRA_ROUTE_MAX) return -1;
+  zebra.redistribute[type - 1] = 1;
+
+  return zebra_send_command (ZEBRA_REDISTRIBUTE_ADD, &type, 1);
+  
+  
+}  
+
+
+/* end redistribution FROM zebra */
+int zebra_disable_redistribute (unsigned char type) {
+  
+  if (type > ZEBRA_ROUTE_MAX) return -1;
+  zebra.redistribute[type - 1] = 0;
+
+  return zebra_send_command (ZEBRA_REDISTRIBUTE_DELETE, &type, 1);
+
+}
+  
+static uint32_t prefixlentomask (uint8_t prefix) {
+  uint32_t mask = 0;
+
+  if (prefix) {
+    mask = 0xffffffff<<(32-prefix);
+    mask = ntohl(mask);
+  }
+
+  return mask;
+}
+
+int add_hna4_route (struct ipv4_route r) {
+  union olsr_ip_addr net, mask;
+  
+#ifdef MY_DEBUG
+  dump_ipv4_route(r, "add_hna4_route");
+#endif
+
+  mask.v4 = prefixlentomask(r.prefixlen);
+  net.v4 = r.prefix;
+
+  add_local_hna4_entry(&net, &mask);
+  free_ipv4_route(r);
+  return 0;
+}
+
+int delete_hna4_route (struct ipv4_route r) {
+
+  union olsr_ip_addr net, mask;
+
+#ifdef MY_DEBUG
+  dump_ipv4_route(r, "delete_hna4_route");
+#endif
+
+  mask.v4 = prefixlentomask(r.prefixlen);
+  net.v4 = r.prefix;
+
+  remove_local_hna4_entry(&net, &mask) ? 0 : -1;
+  free_ipv4_route(r);
+  return 0;
+
+}
+
+static void free_ipv4_route (struct ipv4_route r) {
+
+  if(r.message&ZAPI_MESSAGE_IFINDEX && r.ind_num) free(r.index);
+  if(r.message&ZAPI_MESSAGE_NEXTHOP && r.nh_count) free(r.nexthops);
+
+}
+
+static uint8_t masktoprefixlen (uint32_t mask) {
+  
+  uint8_t prefixlen = 0;
+
+  mask = htonl (mask);
+
+  if (mask) while (mask << ++prefixlen && prefixlen < 32);
+
+  return prefixlen;
+  
+}
+
+int zebra_add_olsr_v4_route (struct rt_entry *r) {
+  
+  struct ipv4_route route;
+  int retval;
+  
+  route.type = ZEBRA_ROUTE_OLSR; // OLSR
+  route.message = ZAPI_MESSAGE_METRIC;
+  route.flags = zebra.flags;
+  route.prefixlen = masktoprefixlen (r->rt_mask.v4);
+  route.prefix = r->rt_dst.v4;
+  if ((r->rt_router.v4 == r->rt_dst.v4 && route.prefixlen == 32)){
+    route.message |= ZAPI_MESSAGE_IFINDEX | ZAPI_MESSAGE_NEXTHOP;
+    route.ind_num = 1;
+    route.index = olsr_malloc (sizeof *route.index, 
+                              "zebra_add_olsr_v4_route");
+    *route.index = htonl(r->rt_if->if_index);
+    route.nexthops = olsr_malloc (sizeof route.nexthops->type +
+                                 sizeof route.nexthops->payload,
+                                 "zebra_add_olsr_v4_route");
+    route.nh_count = 1;
+    route.nexthops->type = 0;
+  }
+  else {
+    route.message |= ZAPI_MESSAGE_NEXTHOP;
+    route.nh_count = 1;
+    route.nexthops = olsr_malloc (route.nh_count * 
+                                 (sizeof route.nexthops->type + 
+                                  sizeof route.nexthops->payload), 
+                                  "zebra_add_olsr_v4_route");
+    route.nexthops->type = ZEBRA_NEXTHOP_IPV4;
+    route.nexthops->payload.v4 = r->rt_router.v4;
+  }
+
+  route.metric = r->rt_metric;
+  route.metric = htonl(route.metric);
+
+  if (zebra.distance) {
+    route.message |= ZAPI_MESSAGE_DISTANCE;
+    route.distance = zebra.distance;
+  }
+
+  add_v4_route_status (route);
+  retval = zebra_add_v4_route(route);
+  free_ipv4_route (route);
+  return retval;
+}
+
+int zebra_del_olsr_v4_route (struct rt_entry *r) {
+  
+  struct ipv4_route route;
+  int retval;
+  route.type = ZEBRA_ROUTE_OLSR; // OLSR
+  route.message = ZAPI_MESSAGE_METRIC;
+  route.flags = zebra.flags;
+  route.prefixlen = masktoprefixlen (r->rt_mask.v4);
+  route.prefix = r->rt_dst.v4;
+  if ((r->rt_router.v4 == r->rt_dst.v4 && route.prefixlen == 32)){
+    route.message |= ZAPI_MESSAGE_IFINDEX;
+    route.ind_num = 1;
+    route.index = olsr_malloc (sizeof *route.index, 
+                              "zebra_add_olsr_v4_route");
+    *route.index = htonl (r->rt_if->if_index);
+    route.nexthops = olsr_malloc (sizeof route.nexthops->type +
+                                 sizeof route.nexthops->payload,
+                                 "zebra_add_olsr_v4_route");
+    route.nh_count = 1;
+    route.nexthops->type = 0;
+  }
+  else {
+    route.message |= ZAPI_MESSAGE_NEXTHOP;
+    route.nh_count = 1;
+    route.nexthops = olsr_malloc (route.nh_count * 
+                                 (sizeof route.nexthops->type +
+                                  sizeof route.nexthops->payload), 
+                                 "zebra_add_olsr_v4_route");
+    route.nexthops->type = ZEBRA_NEXTHOP_IPV4;
+    route.nexthops->payload.v4 = r->rt_router.v4;
+  }
+  route.metric = r->rt_metric;
+  route.metric = htonl (route.metric);
+  
+  if (zebra.distance) {
+    route.message |= ZAPI_MESSAGE_DISTANCE;
+    route.distance = zebra.distance;
+  }
+
+  retval = zebra_delete_v4_route(route);
+  del_v4_route_status(route);
+  free_ipv4_route (route);
+  return retval;
+}
+
+void zebra_olsr_distance (char dist) {
+  zebra.distance = dist;
+}
+
+void zebra_olsr_localpref (void) {
+  zebra.flags &= ZEBRA_FLAG_SELECTED;
+}
diff --git a/lib/quagga/src/quagga.h b/lib/quagga/src/quagga.h
new file mode 100644 (file)
index 0000000..779b9fd
--- /dev/null
@@ -0,0 +1,68 @@
+/***************************************************************************
+ projekt              : olsrd-quagga
+ file                 : quagga.h  
+ usage                : header for quagga.c
+ copyright            : (C) 2006 by Immo 'FaUl' Wehrenberg
+ e-mail               : immo@chaostreff-dortmund.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License version 2 as     *
+ *   published by the Free Software Foundation.                            *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "routing_table.h"
+#define HAVE_SOCKLEN_T
+#include <quagga/zebra.h>
+
+#ifndef ZEBRA_PORT
+#define ZEBRA_PORT 2600
+#endif
+
+#ifdef ZEBRA_HEADER_MARKER
+#ifndef ZSERV_VERSION
+#define ZSERV_VERSION 1
+#endif
+#endif
+
+struct ipv4_route {
+  uint8_t type;
+  uint8_t flags;
+  uint8_t message;
+  uint8_t prefixlen;
+  uint32_t prefix;
+  uint8_t nh_count;
+  struct {
+    uint8_t type;
+    union {
+      uint32_t v4;
+    } payload;
+  } *nexthops;
+  uint8_t ind_num;
+  uint32_t *index;
+  uint32_t metric;
+  uint32_t distance;
+  struct ipv4_route *next;
+};
+
+int init_zebra (void);
+char zebra_send_command (unsigned char, char *, int );
+int zebra_add_v4_route (struct ipv4_route r);
+int zebra_delete_v4_route (struct ipv4_route r);
+void zebra_check (void*);
+int zebra_parse_packet (char*, ssize_t);
+int zebra_redistribute (unsigned char);
+int zebra_disable_redistribute (unsigned char);
+int add_hna4_route (struct ipv4_route);
+int delete_hna4_route (struct ipv4_route);
+void *my_realloc (void *, size_t, const char*);
+int zebra_add_olsr_v4_route (struct rt_entry*);
+int zebra_del_olsr_v4_route (struct rt_entry*);
+void zebra_olsr_localpref(void);
+void zebra_olsr_distance(char);
diff --git a/lib/quagga/src/quagga/zassert.h b/lib/quagga/src/quagga/zassert.h
new file mode 100644 (file)
index 0000000..6d89572
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * $Id: zassert.h,v 1.1 2007/01/31 12:38:26 bernd67 Exp $
+ */
+
+#ifndef _QUAGGA_ASSERT_H
+#define _QUAGGA_ASSERT_H
+
+extern void _zlog_assert_failed (const char *assertion, const char *file,
+                                unsigned int line, const char *function)
+                                __attribute__ ((noreturn));
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define __ASSERT_FUNCTION    __func__
+#elif defined(__GNUC__)
+#define __ASSERT_FUNCTION    __FUNCTION__
+#else
+#define __ASSERT_FUNCTION    NULL
+#endif
+
+#define zassert(EX) ((void)((EX) ?  0 :        \
+                           (_zlog_assert_failed(#EX, __FILE__, __LINE__, \
+                                                __ASSERT_FUNCTION), 0)))
+
+#undef assert
+#define assert(EX) zassert(EX)
+
+#endif /* _QUAGGA_ASSERT_H */
diff --git a/lib/quagga/src/quagga/zebra.h b/lib/quagga/src/quagga/zebra.h
new file mode 100644 (file)
index 0000000..c53d73c
--- /dev/null
@@ -0,0 +1,501 @@
+/* Zebra common header.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra 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.
+
+GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#ifndef _ZEBRA_H
+#define _ZEBRA_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef SUNOS_5
+#define _XPG4_2
+#define __EXTENSIONS__
+typedef unsigned int    u_int32_t;
+typedef unsigned short  u_int16_t;
+typedef unsigned char   u_int8_t;
+#endif /* SUNOS_5 */
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif /* HAVE_SOCKLEN_T */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif /* HAVE_STROPTS_H */
+#include <sys/fcntl.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif /* HAVE_SYS_SYSCTL_H */
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_CONF_H
+#include <sys/conf.h>
+#endif /* HAVE_SYS_CONF_H */
+#ifdef HAVE_SYS_KSYM_H
+#include <sys/ksym.h>
+#endif /* HAVE_SYS_KSYM_H */
+#include <syslog.h>
+#include <time.h>
+#include <sys/uio.h>
+#include <sys/utsname.h>
+#ifdef HAVE_RUSAGE
+#include <sys/resource.h>
+#endif /* HAVE_RUSAGE */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif /* HAVE_LIMITS_H */
+
+/* machine dependent includes */
+#ifdef SUNOS_5
+#include <strings.h>
+#endif /* SUNOS_5 */
+
+/* machine dependent includes */
+#ifdef HAVE_LINUX_VERSION_H
+#include <linux/version.h>
+#endif /* HAVE_LINUX_VERSION_H */
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif /* HAVE_ASM_TYPES_H */
+
+/* misc include group */
+#include <stdarg.h>
+#if !(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
+/* Not C99; do we need to define va_copy? */
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy(DST,SRC) __va_copy(DST,SRC)
+#else
+/* Now we are desperate; this should work on many typical platforms. 
+   But this is slightly dangerous, because the standard does not require
+   va_copy to be a macro. */
+#define va_copy(DST,SRC) memcpy(&(DST), &(SRC), sizeof(va_list))
+#warning "Not C99 and no va_copy macro available, falling back to memcpy"
+#endif /* __va_copy */
+#endif /* !va_copy */
+#endif /* !C99 */
+
+
+#ifdef HAVE_LCAPS
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#endif /* HAVE_LCAPS */
+
+/* network include group */
+
+#include <sys/socket.h>
+
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif /* HAVE_SYS_SOCKIO_H */
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#ifdef HAVE_NET_NETOPT_H
+#include <net/netopt.h>
+#endif /* HAVE_NET_NETOPT_H */
+
+#include <net/if.h>
+
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif /* HAVE_NET_IF_DL_H */
+
+#ifdef HAVE_NET_IF_VAR_H
+#include <net/if_var.h>
+#endif /* HAVE_NET_IF_VAR_H */
+
+#ifdef HAVE_NET_ROUTE_H
+#include <net/route.h>
+#endif /* HAVE_NET_ROUTE_H */
+
+#ifdef HAVE_NETLINK
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#else
+#define RT_TABLE_MAIN          0
+#endif /* HAVE_NETLINK */
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif /* HAVE_NETDB_H */
+
+#include <arpa/inet.h>
+#include <arpa/telnet.h>
+
+#ifdef HAVE_INET_ND_H
+#include <inet/nd.h>
+#endif /* HAVE_INET_ND_H */
+
+#ifdef HAVE_NETINET_IN_VAR_H
+#include <netinet/in_var.h>
+#endif /* HAVE_NETINET_IN_VAR_H */
+
+#ifdef HAVE_NETINET6_IN6_VAR_H
+#include <netinet6/in6_var.h>
+#endif /* HAVE_NETINET6_IN6_VAR_H */
+
+#ifdef HAVE_NETINET_IN6_VAR_H
+#include <netinet/in6_var.h>
+#endif /* HAVE_NETINET_IN6_VAR_H */
+
+#ifdef HAVE_NETINET6_IN_H
+#include <netinet6/in.h>
+#endif /* HAVE_NETINET6_IN_H */
+
+
+#ifdef HAVE_NETINET6_IP6_H
+#include <netinet6/ip6.h>
+#endif /* HAVE_NETINET6_IP6_H */
+
+#ifdef HAVE_NETINET_ICMP6_H
+#include <netinet/icmp6.h>
+#endif /* HAVE_NETINET_ICMP6_H */
+
+#ifdef HAVE_NETINET6_ND6_H
+#include <netinet6/nd6.h>
+#endif /* HAVE_NETINET6_ND6_H */
+
+/* Some systems do not define UINT32_MAX */
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xFFFFFFFFU
+#endif /* UINT32_MAX */
+
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif /* HAVE_LIBUTIL_H */
+
+#ifdef HAVE_GLIBC_BACKTRACE
+#include <execinfo.h>
+#endif /* HAVE_GLIBC_BACKTRACE */
+
+#ifdef BSDI_NRL
+
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif /* HAVE_NETINET6_IN6_H */
+
+#ifdef NRL
+#include <netinet6/in6.h>
+#endif /* NRL */
+
+#define IN6_ARE_ADDR_EQUAL IN6_IS_ADDR_EQUAL
+
+#endif /* BSDI_NRL */
+
+/* Local includes: */
+#if !(defined(__GNUC__) || defined(VTYSH_EXTRACT_PL)) 
+#define __attribute__(x)
+#endif  /* !__GNUC__ || VTYSH_EXTRACT_PL */
+
+#include "zassert.h"
+
+
+#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
+/* This bug is present in Solaris 8 and pre-patch Solaris 9 <sys/socket.h>;
+   please refer to http://bugzilla.quagga.net/show_bug.cgi?id=142 */
+
+/* Check that msg_controllen is large enough. */
+#define ZCMSG_FIRSTHDR(mhdr) \
+  (((size_t)((mhdr)->msg_controllen) >= sizeof(struct cmsghdr)) ? \
+   CMSG_FIRSTHDR(mhdr) : (struct cmsghdr *)NULL)
+
+#warning "CMSG_FIRSTHDR is broken on this platform, using a workaround"
+
+#else /* HAVE_BROKEN_CMSG_FIRSTHDR */
+#define ZCMSG_FIRSTHDR(M) CMSG_FIRSTHDR(M)
+#endif /* HAVE_BROKEN_CMSG_FIRSTHDR */
+
+
+
+/* 
+ * RFC 3542 defines several macros for using struct cmsghdr.
+ * Here, we define those that are not present
+ */
+
+/*
+ * Internal defines, for use only in this file.
+ * These are likely wrong on other than ILP32 machines, so warn.
+ */
+#ifndef _CMSG_DATA_ALIGN
+#define _CMSG_DATA_ALIGN(n)           (((n) + 3) & ~3)
+#endif /* _CMSG_DATA_ALIGN */
+
+#ifndef _CMSG_HDR_ALIGN
+#define _CMSG_HDR_ALIGN(n)            (((n) + 3) & ~3)
+#endif /* _CMSG_HDR_ALIGN */
+
+/*
+ * CMSG_SPACE and CMSG_LEN are required in RFC3542, but were new in that
+ * version.
+ */
+#ifndef CMSG_SPACE
+#define CMSG_SPACE(l)       (_CMSG_DATA_ALIGN(sizeof(struct cmsghdr)) + \
+                              _CMSG_HDR_ALIGN(l))
+#warning "assuming 4-byte alignment for CMSG_SPACE"
+#endif  /* CMSG_SPACE */
+
+
+#ifndef CMSG_LEN
+#define CMSG_LEN(l)         (_CMSG_DATA_ALIGN(sizeof(struct cmsghdr)) + (l))
+#warning "assuming 4-byte alignment for CMSG_LEN"
+#endif /* CMSG_LEN */
+
+
+/*  The definition of struct in_pktinfo is missing in old version of
+    GLIBC 2.1 (Redhat 6.1).  */
+#if defined (GNU_LINUX) && ! defined (HAVE_INPKTINFO)
+struct in_pktinfo
+{
+  int ipi_ifindex;
+  struct in_addr ipi_spec_dst;
+  struct in_addr ipi_addr;
+};
+#endif
+
+/* 
+ * OSPF Fragmentation / fragmented writes
+ *
+ * ospfd can support writing fragmented packets, for cases where
+ * kernel will not fragment IP_HDRINCL and/or multicast destined
+ * packets (ie TTBOMK all kernels, BSD, SunOS, Linux). However,
+ * SunOS, probably BSD too, clobber the user supplied IP ID and IP
+ * flags fields, hence user-space fragmentation will not work.
+ * Only Linux is known to leave IP header unmolested.
+ * Further, fragmentation really should be done the kernel, which already
+ * supports it, and which avoids nasty IP ID state problems.
+ *
+ * Fragmentation of OSPF packets can be required on networks with router
+ * with many many interfaces active in one area, or on networks with links
+ * with low MTUs.
+ */
+#ifdef GNU_LINUX
+#define WANT_OSPF_WRITE_FRAGMENT
+#endif
+
+/* 
+ * IP_HDRINCL / struct ip byte order
+ *
+ * Linux: network byte order
+ * *BSD: network, except for length and offset. (cf Stevens)
+ * SunOS: nominally as per BSD. but bug: network order on LE.
+ * OpenBSD: network byte order, apart from older versions which are as per 
+ *          *BSD
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__) \
+   || (defined(__OpenBSD__) && (OpenBSD < 200311)) \
+   || (defined(SUNOS_5) && defined(WORDS_BIGENDIAN))
+#define HAVE_IP_HDRINCL_BSD_ORDER
+#endif
+
+/* MAX / MIN are not commonly defined, but useful */
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif 
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* For old definition. */
+#ifndef IN6_ARE_ADDR_EQUAL
+#define IN6_ARE_ADDR_EQUAL IN6_IS_ADDR_EQUAL
+#endif /* IN6_ARE_ADDR_EQUAL */
+
+/* Zebra message types. */
+#define ZEBRA_INTERFACE_ADD                1
+#define ZEBRA_INTERFACE_DELETE             2
+#define ZEBRA_INTERFACE_ADDRESS_ADD        3
+#define ZEBRA_INTERFACE_ADDRESS_DELETE     4
+#define ZEBRA_INTERFACE_UP                 5
+#define ZEBRA_INTERFACE_DOWN               6
+#define ZEBRA_IPV4_ROUTE_ADD               7
+#define ZEBRA_IPV4_ROUTE_DELETE            8
+#define ZEBRA_IPV6_ROUTE_ADD               9
+#define ZEBRA_IPV6_ROUTE_DELETE           10
+#define ZEBRA_REDISTRIBUTE_ADD            11
+#define ZEBRA_REDISTRIBUTE_DELETE         12
+#define ZEBRA_REDISTRIBUTE_DEFAULT_ADD    13
+#define ZEBRA_REDISTRIBUTE_DEFAULT_DELETE 14
+#define ZEBRA_IPV4_NEXTHOP_LOOKUP         15
+#define ZEBRA_IPV6_NEXTHOP_LOOKUP         16
+#define ZEBRA_IPV4_IMPORT_LOOKUP          17
+#define ZEBRA_IPV6_IMPORT_LOOKUP          18
+#define ZEBRA_INTERFACE_RENAME            19
+#define ZEBRA_ROUTER_ID_ADD               20
+#define ZEBRA_ROUTER_ID_DELETE            21
+#define ZEBRA_ROUTER_ID_UPDATE            22
+#define ZEBRA_MESSAGE_MAX                 23
+
+/* Zebra route's types. */
+#define ZEBRA_ROUTE_SYSTEM               0
+#define ZEBRA_ROUTE_KERNEL               1
+#define ZEBRA_ROUTE_CONNECT              2
+#define ZEBRA_ROUTE_STATIC               3
+#define ZEBRA_ROUTE_RIP                  4
+#define ZEBRA_ROUTE_RIPNG                5
+#define ZEBRA_ROUTE_OSPF                 6
+#define ZEBRA_ROUTE_OSPF6                7
+#define ZEBRA_ROUTE_ISIS                 8
+#define ZEBRA_ROUTE_BGP                  9
+#define ZEBRA_ROUTE_HSLS                10
+#define ZEBRA_ROUTE_OLSR                11
+#define ZEBRA_ROUTE_MAX                  12
+
+/* Zebra's family types. */
+#define ZEBRA_FAMILY_IPV4                1
+#define ZEBRA_FAMILY_IPV6                2
+#define ZEBRA_FAMILY_MAX                 3
+
+/* Error codes of zebra. */
+#define ZEBRA_ERR_RTEXIST               -1
+#define ZEBRA_ERR_RTUNREACH             -2
+#define ZEBRA_ERR_EPERM                 -3
+#define ZEBRA_ERR_RTNOEXIST             -4
+
+/* Zebra message flags */
+#define ZEBRA_FLAG_INTERNAL           0x01
+#define ZEBRA_FLAG_SELFROUTE          0x02
+#define ZEBRA_FLAG_BLACKHOLE          0x04
+#define ZEBRA_FLAG_IBGP               0x08
+#define ZEBRA_FLAG_SELECTED           0x10
+#define ZEBRA_FLAG_CHANGED            0x20
+#define ZEBRA_FLAG_STATIC             0x40
+#define ZEBRA_FLAG_REJECT             0x80
+
+/* Zebra nexthop flags. */
+#define ZEBRA_NEXTHOP_IFINDEX            1
+#define ZEBRA_NEXTHOP_IFNAME             2
+#define ZEBRA_NEXTHOP_IPV4               3
+#define ZEBRA_NEXTHOP_IPV4_IFINDEX       4
+#define ZEBRA_NEXTHOP_IPV4_IFNAME        5
+#define ZEBRA_NEXTHOP_IPV6               6
+#define ZEBRA_NEXTHOP_IPV6_IFINDEX       7
+#define ZEBRA_NEXTHOP_IPV6_IFNAME        8
+#define ZEBRA_NEXTHOP_BLACKHOLE          9
+
+#ifndef INADDR_LOOPBACK
+#define        INADDR_LOOPBACK 0x7f000001      /* Internet address 127.0.0.1.  */
+#endif
+
+/* Address family numbers from RFC1700. */
+#define AFI_IP                    1
+#define AFI_IP6                   2
+#define AFI_MAX                   3
+
+/* Subsequent Address Family Identifier. */
+#define SAFI_UNICAST              1
+#define SAFI_MULTICAST            2
+#define SAFI_UNICAST_MULTICAST    3
+#define SAFI_MPLS_VPN             4
+#define SAFI_MAX                  5
+
+/* Filter direction.  */
+#define FILTER_IN                 0
+#define FILTER_OUT                1
+#define FILTER_MAX                2
+
+/* Default Administrative Distance of each protocol. */
+#define ZEBRA_KERNEL_DISTANCE_DEFAULT      0
+#define ZEBRA_CONNECT_DISTANCE_DEFAULT     0
+#define ZEBRA_STATIC_DISTANCE_DEFAULT      1
+#define ZEBRA_RIP_DISTANCE_DEFAULT       120
+#define ZEBRA_RIPNG_DISTANCE_DEFAULT     120
+#define ZEBRA_OSPF_DISTANCE_DEFAULT      110
+#define ZEBRA_OSPF6_DISTANCE_DEFAULT     110
+#define ZEBRA_ISIS_DISTANCE_DEFAULT      115
+#define ZEBRA_IBGP_DISTANCE_DEFAULT      200
+#define ZEBRA_EBGP_DISTANCE_DEFAULT       20
+
+/* Flag manipulation macros. */
+#define CHECK_FLAG(V,F)      ((V) & (F))
+#define SET_FLAG(V,F)        (V) = (V) | (F)
+#define UNSET_FLAG(V,F)      (V) = (V) & ~(F)
+
+/* AFI and SAFI type. */
+typedef u_int16_t afi_t;
+typedef u_int8_t safi_t;
+
+/* Zebra types. */
+typedef u_int16_t zebra_size_t;
+typedef u_int8_t zebra_command_t;
+
+/* FIFO -- first in first out structure and macros.  */
+struct fifo
+{
+  struct fifo *next;
+  struct fifo *prev;
+};
+
+#define FIFO_INIT(F)                                  \
+  do {                                                \
+    struct fifo *Xfifo = (struct fifo *)(F);          \
+    Xfifo->next = Xfifo->prev = Xfifo;                \
+  } while (0)
+
+#define FIFO_ADD(F,N)                                 \
+  do {                                                \
+    struct fifo *Xfifo = (struct fifo *)(F);          \
+    struct fifo *Xnode = (struct fifo *)(N);          \
+    Xnode->next = Xfifo;                              \
+    Xnode->prev = Xfifo->prev;                        \
+    Xfifo->prev = Xfifo->prev->next = Xnode;          \
+  } while (0)
+
+#define FIFO_DEL(N)                                   \
+  do {                                                \
+    struct fifo *Xnode = (struct fifo *)(N);          \
+    Xnode->prev->next = Xnode->next;                  \
+    Xnode->next->prev = Xnode->prev;                  \
+  } while (0)
+
+#define FIFO_HEAD(F)                                  \
+  ((((struct fifo *)(F))->next == (struct fifo *)(F)) \
+  ? NULL : (F)->next)
+
+#define FIFO_EMPTY(F)                                 \
+  (((struct fifo *)(F))->next == (struct fifo *)(F))
+
+#define FIFO_TOP(F)                                   \
+  (FIFO_EMPTY(F) ? NULL : ((struct fifo *)(F))->next)
+
+#endif /* _ZEBRA_H */
diff --git a/lib/quagga/test/foo.c b/lib/quagga/test/foo.c
new file mode 100644 (file)
index 0000000..8879318
--- /dev/null
@@ -0,0 +1,10 @@
+#include "quagga.h"
+
+int main (void) {
+  
+  init_zebra();
+  zebra_redistribute (2);
+  //  zebra_redistribute (1);
+  while (!sleep (1)) zebra_check();
+  return 0;
+}
diff --git a/lib/quagga/test/foo.pl b/lib/quagga/test/foo.pl
new file mode 100644 (file)
index 0000000..771e3b5
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+use IO::Socket;
+
+$command = 11; # 11 = redistribute_add , 13 = redistribute_default_add
+
+$proto = 2; # connected 
+
+$remote = IO::Socket::INET->new (Proto => "tcp",
+                                 PeerAddr => "127.0.0.1",
+                                 PeerPort => "2600",
+                                 );
+$remote->autoflush (1);
+#print $remote pack ("nc", 3, 13);
+print $remote pack ("nc",3,1);
+print $remote pack ("ncc", 4,$command,2);
+print $remote pack ("ncccccNcNcNN", 25, 7, 10, 16, 11, 25, 0xc0a80206, 0, 0, 1, 5, 1);
+print <$remote>;
+close $remote
diff --git a/lib/quagga/test/quagga.try1.c b/lib/quagga/test/quagga.try1.c
new file mode 100644 (file)
index 0000000..13289c8
--- /dev/null
@@ -0,0 +1,710 @@
+/* 
+ *  (C) 2006 by Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>
+ *  
+ *  This code is covered by the GPLv2
+ *   
+ */
+
+#include <stdint.h>
+#ifdef MY_DEBUG
+#include <stdio.h>
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#define HAVE_SOCKLEN_T
+#include <quagga/zebra.h>
+#include "quagga.h"
+
+#ifdef OLSR_PLUGIN
+#include "olsr.h"
+#include "log.h"
+#include "defs.h"
+#include "local_hna_set.h"
+#endif
+
+#define ZAPI_MESSAGE_NEXTHOP  0x01
+#define ZAPI_MESSAGE_IFINDEX  0x02
+#define ZAPI_MESSAGE_DISTANCE 0x04
+#define ZAPI_MESSAGE_METRIC   0x08
+
+
+#define STATUS_CONNECTED 1
+#define BUFSIZE 1024
+static char status = 0;
+
+static int zsock; // Socket to zebra...
+struct ipv4_route *quagga_routes = 0; // routes currently exportet to zebra
+
+
+/* prototypes ntern */
+static char *try_read (ssize_t *);
+static char* zebra_route_packet (struct ipv4_route r, ssize_t *);
+static int parse_interface_add (char *, size_t);
+static int parse_interface_delete (char *, size_t);
+static int parse_interface_up (char *, size_t);
+static int parse_interface_down (char *, size_t);
+static int parse_interface_address_add (char *, size_t);
+static int parse_interface_address_delete (char *, size_t);
+static int parse_ipv4_route (char *, size_t, struct ipv4_route *);
+static int ipv4_route_add (char *, size_t);
+static int ipv4_route_delete (char *, size_t);
+static int parse_ipv6_route_add (char*, size_t);
+static uint32_t prefixlentomask (uint8_t);
+static void free_ipv4_route (struct ipv4_route);
+static void update_olsr_zebra_routes (struct ipv4_route*, struct ipv4_route*);
+static struct ipv4_route *zebra_create_ipv4_route_table_entry (uint32_t,
+                                                              uint32_t,
+                                                              uint32_t);
+static struct ipv4_route *zebra_create_ipv4_route_table (void);
+static void zebra_free_ipv4_route_table (struct ipv4_route*);
+static uint8_t masktoprefixlen (uint32_t);
+
+
+
+#ifdef MY_DEBUG
+static void dump_ipv4_route (struct ipv4_route r, char *c) {
+  int i = 0, x = 0;
+
+  puts (c);
+  printf("type: %d\n", r.type);
+  puts("flags:");
+  printf("  Internal: %s\n",r.flags&ZEBRA_FLAG_INTERNAL?"yes":"no");
+  printf("  Selfroute %s\n",r.flags&ZEBRA_FLAG_SELFROUTE?"yes":"no");
+  printf("  Blackhole %s\n",r.flags&ZEBRA_FLAG_BLACKHOLE?"yes":"no");
+  printf("  IBGP: %s\n",r.flags&ZEBRA_FLAG_IBGP?"yes":"no");
+  printf("  Selected: %s\n",r.flags&ZEBRA_FLAG_SELECTED?"yes":"no");
+  printf("  Changed: %s\n",r.flags&ZEBRA_FLAG_CHANGED?"yes":"no");
+  printf("  static: %s\n",r.flags&ZEBRA_FLAG_STATIC?"yes":"no");
+  printf("  reject: %s\n",r.flags&ZEBRA_FLAG_REJECT?"yes":"no");
+  puts("message:");
+  printf("  nexthop: %s\n",r.message&ZAPI_MESSAGE_NEXTHOP?"yes":"no");
+  printf("  ifindex: %s\n",r.message&ZAPI_MESSAGE_IFINDEX?"yes":"no");
+  printf("  distance: %s\n",r.message&ZAPI_MESSAGE_DISTANCE?"yes":"no");
+  printf("  metric: %s\n",r.message&ZAPI_MESSAGE_METRIC?"yes":"no");
+  printf("Prefixlen: %d\n", r.prefixlen);
+  printf("Prefix: %d", (unsigned char)r.prefix);
+  c = (char*) &r.prefix;
+  while (++i < (r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0)))
+    printf(".%d",(unsigned char)*(c + i));
+  while (i++ < 4)
+    printf(".0");
+  puts("");
+  i=0;
+  if (r.message&ZAPI_MESSAGE_NEXTHOP) {
+    
+    printf("nexthop-count: %d\n", r.nh_count);
+    while (i++ < r.nh_count) {
+      c = (unsigned char*) &r.nexthops[i];
+      printf ("Nexthop %d: %d", i, (unsigned char) *c);
+      while (++x < 4) {
+       printf (".%d", (unsigned char) c[x]);
+      }
+      puts("");
+    }
+    i=0;
+  }
+  if (r.message&ZAPI_MESSAGE_IFINDEX) {
+    
+    printf("index-number: %d\n", r.ind_num);
+    while (i++ < r.ind_num)
+      printf("Index: %d: %d\n", i, r.index[i]);
+    i=0;
+    if (r.message&ZAPI_MESSAGE_DISTANCE)
+      printf("Distance: %d\n",r.distance);
+    if (r.message&ZAPI_MESSAGE_METRIC)
+      printf("Metric: %d\n",r.metric);
+    puts("\n");
+  }
+}
+#endif
+
+void *my_realloc (void *buf, size_t s, const char *c) {
+  buf = realloc (buf, s);
+  if (!buf) {
+#ifdef OLSR_PLUGIN
+    OLSR_PRINTF (1, "OUT OF MEMORY: %s\n", strerror(errno));
+    olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %m\n");
+    olsr_exit(c, EXIT_FAILURE);
+#else
+    exit (EXIT_FAILURE);
+#endif
+  }
+  return buf;
+}
+
+
+#ifndef OLSR_PLUGIN 
+void *olsr_malloc (size_t f, const char *c) {
+  void* v = malloc (f);
+  return v;
+}
+#endif
+
+/* Connect to the zebra-daemon, returns a socket */
+int init_zebra () {
+  struct sockaddr_in i;
+  int ret;
+
+  zsock = socket (AF_INET,SOCK_STREAM, 0);
+  if (zsock <0 ) // TODO: Could not create socket
+    return -1;
+  memset (&i, 0, sizeof i);
+  i.sin_family = AF_INET;
+  i.sin_port = htons (ZEBRA_PORT);
+  //  i.sin_len = sizeof i;
+  i.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+  
+  ret = connect (zsock, (struct sockaddr *)&i, sizeof i);
+  if  (ret < 0) {
+    close (zsock);
+    return -1;
+  }
+  status |= STATUS_CONNECTED;
+  return zsock;
+}
+
+    
+/* Sends a command to zebra, command is 
+   the command defined in zebra.h, options is the packet-payload, 
+   optlen the length, of the payload */
+char zebra_send_command (unsigned char command, char * options, int optlen) {
+
+  char *p = olsr_malloc (optlen+3, "zebra send_command");
+  uint16_t length = optlen + 3;  // length of option + command + packet_length
+  
+  int ret;
+  
+  uint16_t len = htons(length);
+  memcpy (p, &len, 2);
+  p[2] = command;
+  memcpy (p + 3, options, optlen);
+  
+  do {
+    ret = write (zsock, p, length);
+    if (ret < 0) {
+      if (errno == EINTR) continue;
+    }
+    else return -1;
+    p = p+ret;
+  } while ((length =- ret));
+
+  return 0;
+}
+
+
+/* Creates a Route-Packet-Payload, needs address, netmask, nexthop, 
+   distance, and a pointer of an size_t */
+static char* zebra_route_packet (struct ipv4_route r, ssize_t *optlen) {
+
+  char *cmdopt, *t;
+  *optlen = 9; // first: type, flags, message, prefixlen, nexthop number, nexthop)
+  *optlen += r.prefixlen / 8 + (r.prefixlen % 8 ? 1 : 0);
+  
+  cmdopt = olsr_malloc (*optlen, "zebra add_v4_route");
+  t = cmdopt;
+  *t++ = 10; // Type: olsr
+  *t++ = r.flags; // flags
+  *t++ = r.message; // message: contains nexthop
+  *t++ = r.prefixlen;
+  memcpy (t, &r.prefix, r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0));
+  *t += r.prefixlen/8 + (r.prefixlen % 8 ? 1 : 0);
+  *t++ = r.nh_count;
+  memcpy (t, r.nexthops, r.nh_count * sizeof *r.nexthops);
+  return cmdopt;
+}
+
+
+/* adds a route to zebra-daemon (needs socket from zebra,
+   address = prefix of the route
+   mask = netmask of the route
+   nexthop = nexthop of the route
+   distance = distance-value of the route
+*/
+int zebra_add_v4_route (struct ipv4_route r) {
+  
+  char *cmdopt;
+  ssize_t optlen;
+
+  cmdopt = zebra_route_packet (r, &optlen);
+
+  puts ("DEBUG: zebra_route_packet returned");
+  
+  
+
+  return zebra_send_command (ZEBRA_IPV4_ROUTE_ADD, cmdopt, optlen);
+
+}
+
+/* deletes a route from the zebra-daemon (
+   needs socket from zebra,
+   address = prefix of the route
+   mask = netmask of the route
+   nexthop = nexthop of the route
+   distance = distance-value of the route
+*/
+int zebra_delete_v4_route (struct ipv4_route r) {
+  
+  char *cmdopt;
+  ssize_t optlen;
+  
+  cmdopt = zebra_route_packet (r, &optlen);
+  
+  return zebra_send_command (ZEBRA_IPV4_ROUTE_DELETE, cmdopt, optlen);
+
+}
+
+
+/* Check wether there is data from zebra aviable */
+void zebra_check (void* foo) {
+  char *data, *f;
+  ssize_t len, ret;
+
+  if (!status & STATUS_CONNECTED) {
+  }
+  data = try_read (&len);
+  if (data) {
+    f = data;
+    do {
+      ret = zebra_parse_packet (f, len);
+      if (!ret) {//something wired happened
+       puts ("DEBUG: IIIIIIIIIIRGS");
+       exit (EXIT_FAILURE);
+      }
+      f += ret;
+    } while ((f - data) < len);
+    free (data);
+  }
+}
+
+
+// tries to read a packet from zebra_socket
+// if there is something to read - make sure to read whole packages
+static char *try_read (ssize_t *len) {
+  char *buf = NULL;
+  ssize_t ret = 0, bsize = 0;
+  uint16_t length = 0, l = 0;
+  int sockstate;
+
+  *len = 0;
+
+  sockstate = fcntl (zsock, F_GETFL, 0);
+  fcntl (zsock, F_SETFL, sockstate|O_NONBLOCK);
+
+  do { 
+    if (*len == bsize) {
+      bsize += BUFSIZE;
+      buf = my_realloc (buf, bsize, "Zebra try_read");
+    }
+    ret = read (zsock, buf + l, bsize - l);
+    if (ret <= 0) {
+      if (errno == EAGAIN) {
+       errno = 0;
+      }
+      else {
+       // TODO: errorhandling
+       ;
+      }
+      free (buf);
+      return NULL;
+    }
+    *len += ret;
+
+    while ((*len - l) > length) {
+      //      printf ("DEBUG: *len -l > length - %d - %d > %d\n", *len, l, length);
+      l += length;
+      memcpy (&length, buf + l, 2);
+      length = ntohs (length);
+    }
+    //    printf ("DEBUG: *len, l, length: %d,%d,%d\n", *len, l, length);
+    if (((*len) - l) == length) break; // GOT FULL PACKAGE!!
+    if (*len < l) {
+      //      printf ("DEBUG: *len, l, length: %d,%d,%d\n", *len, l, length);
+      fcntl (zsock, F_SETFL, sockstate);
+      continue;
+    }
+  } while (1);
+
+  fcntl (zsock, F_SETFL, sockstate);
+  return buf;
+}
+
+
+/* Parse a packet recived from zebra */
+int zebra_parse_packet (char *packet, ssize_t maxlen) {
+
+  /* Array of functions */
+  int (*foo[ZEBRA_MESSAGE_MAX]) (char *, size_t) = {
+    parse_interface_add,
+    parse_interface_delete,
+    parse_interface_address_add,
+    parse_interface_address_delete,
+    parse_interface_up,
+    parse_interface_down,
+    ipv4_route_add,
+    ipv4_route_delete,
+    parse_ipv6_route_add
+  };
+  
+  puts ("DEBUG: zebra_parse_packet");
+  uint16_t length;
+  
+  int ret;
+  memcpy (&length, packet, 2);
+  length = ntohs (length);
+  
+  if (maxlen < length) {
+    puts("Error: programmer is an idiot");
+    printf ("DEBUG: maxlen = %d, packet_length = %d\n", maxlen, length);
+    return maxlen;
+  }
+
+  if (packet[2] - 1 < ZEBRA_MESSAGE_MAX && foo[packet[2] - 1]) { 
+    if (!(ret = foo[packet[2] - 1] (packet + 3, length - 3))) 
+      return length;
+    else printf ("DEBUG: Parse error: %d\n", ret);
+  }
+  else
+    printf ("Unknown packet type: %d\n", packet[2]);
+
+  puts ("Quagga: RECIVED PACKET FROM ZEBRA THAT I CAN'T PARSE");
+
+  return length;
+}
+
+
+static int parse_interface_add (char *opt, size_t len) {
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_delete (char *opt, size_t len) {
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_address_add (char *opt, size_t len) {
+  
+  //todo
+  return 0;
+}
+
+static int parse_interface_up (char *opt, size_t len) {
+  
+  //todo
+  return 0;
+}
+
+static int parse_interface_down (char *opt, size_t len) {
+  
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_address_delete (char *opt, size_t  len) {
+  //todo
+  return 0;
+}
+
+
+/* Parse an ipv4-route-packet recived from zebra
+ */
+static int parse_ipv4_route (char *opt, size_t len, struct ipv4_route *r) {
+  //  puts ("DEBUG: parse_ipv4_route");
+  if (len < 4) return -1;
+  
+  r->type = *opt++;
+  r->flags = *opt++;
+  r->message = *opt++;
+  r->prefixlen = *opt++;
+  len -= 4;
+  r->prefix = 0;
+  
+  if ((int)len < r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0)) return -1;
+  
+  memcpy (&r->prefix, opt, r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0));
+  opt += r->prefixlen/8 + (r->prefixlen % 8 ? 1 : 0);
+  
+  if (r->message & ZAPI_MESSAGE_NEXTHOP) {
+    if (len < 1) return -1;
+    r->nh_count = *opt++;
+    if (len < sizeof (uint32_t) * r->nh_count) return -1;
+    r->nexthops = olsr_malloc (sizeof (uint32_t) * r->nh_count, 
+                              "quagga: parse_ipv4_route_add");
+    memcpy (r->nexthops, opt, sizeof (uint32_t) * r->nh_count);
+    opt += sizeof (uint32_t) * r->nh_count;
+    len -= sizeof (uint32_t) * r->nh_count + 1;
+  }
+
+  if (r->message & ZAPI_MESSAGE_IFINDEX) {
+    if (len < 1) return -2;
+    r->ind_num = *opt++;
+    if (len < sizeof (uint32_t) * r->ind_num) return -3;
+    r->index = olsr_malloc (sizeof (uint32_t) * r->ind_num,
+                           "quagga: parse_ipv4_route_add");
+    memcpy (r->index, opt, r->ind_num * sizeof (uint32_t));
+    opt += sizeof (uint32_t) * r->ind_num;
+    len -= sizeof (uint32_t) * r->ind_num;
+  }
+
+  if (r->message & ZAPI_MESSAGE_DISTANCE)
+    // todo
+    ;
+
+  if (r->message & ZAPI_MESSAGE_METRIC) {
+    if (len < sizeof (uint32_t)) return -4;
+    memcpy (&r->metric, opt, sizeof (uint32_t));
+  }
+
+  return 0;
+}
+
+
+static int ipv4_route_add (char *opt, size_t len) {
+
+  struct ipv4_route r;
+  int f;
+  
+  //  puts ("DEBUG: ipv4_route_add");
+  
+  f = parse_ipv4_route (opt, len, &r);
+  if (f < 0) {
+    printf ("parse-error: %d\n",f);
+    return f;
+  }
+  
+  add_hna4_route (r);
+  return 0;
+}
+
+static int ipv4_route_delete (char *opt, size_t len) {
+  struct ipv4_route r;
+  int f;
+  
+  f = parse_ipv4_route (opt, len, &r);
+  if (f < 0) return f;
+
+  return delete_hna4_route (r);
+  // OK, now delete that foo
+  
+}
+
+static int parse_ipv6_route_add (char *opt, size_t len) {
+  //todo
+  return 0;
+}
+
+
+/* start redistribution FROM zebra */
+int zebra_redistribute (unsigned char type) {
+
+  return zebra_send_command (ZEBRA_REDISTRIBUTE_ADD, &type, 1);
+  
+  
+}  
+
+
+/* end redistribution FROM zebra */
+int zebra_disable_redistribute (unsigned char type) {
+  
+  return zebra_send_command (ZEBRA_REDISTRIBUTE_DELETE, &type, 1);
+
+}
+  
+static uint32_t prefixlentomask (uint8_t prefix) {
+  uint32_t mask;
+  mask = 0xffffffff<<(32-prefix);
+  mask = ntohl(mask);
+  return mask;
+}
+
+int add_hna4_route (struct ipv4_route r) {
+  union olsr_ip_addr net, mask;
+  
+#ifdef MY_DEBUG
+  dump_ipv4_route(r, "add_hna4_route");
+#endif
+
+  mask.v4 = prefixlentomask(r.prefixlen);
+  net.v4 = r.prefix;
+
+
+#ifdef OLSR_PLUGIN
+  add_local_hna4_entry(&net, &mask);
+#endif
+  free_ipv4_route(r);
+  return 0;
+}
+
+int delete_hna4_route (struct ipv4_route r) {
+
+  union olsr_ip_addr net, mask;
+
+#ifdef MY_DEBUG
+  dump_ipv4_route(r, "delete_hna4_route");
+#endif
+
+  mask.v4 = prefixlentomask(r.prefixlen);
+  net.v4 = r.prefix;
+
+#ifdef OLSR_PLUGIN
+  return remove_local_hna4_entry(&net, &mask) ? 0 : -1;
+#endif
+  
+  free_ipv4_route(r);
+  return 0;
+
+}
+
+static void free_ipv4_route (struct ipv4_route r) {
+
+  if(r.message&ZAPI_MESSAGE_IFINDEX && r.ind_num) free(r.index);
+  if(r.message&ZAPI_MESSAGE_NEXTHOP && r.nh_count) free(r.nexthops);
+
+}
+void zebra_clear_routes(void) {
+
+  struct ipv4_route *t;
+
+  t = quagga_routes;
+  while (t) {
+    zebra_delete_v4_route(*t);
+    t=t->next;
+  }
+  zebra_free_ipv4_route_table(quagga_routes);
+
+  quagga_routes = NULL;
+}
+
+
+void zebra_update_hna (void* f) {
+  
+  struct ipv4_route *a = zebra_create_ipv4_route_table();
+  update_olsr_zebra_routes(a, quagga_routes);
+  zebra_free_ipv4_route_table(quagga_routes);
+
+  quagga_routes = a;
+
+}
+
+static struct ipv4_route *zebra_create_ipv4_route_table (void) {
+
+  struct ipv4_route *r = 0, *t = 0 /* make compiler happy */;
+  int i;
+  struct hna_entry *e;
+  struct hna_net *n;
+
+  for (i = 0; i < HASHSIZE; i++) {
+    e = hna_set[i].next;
+    for(;e != &hna_set[i];e = e->next) {
+      n = e->networks.next;
+      for(;n != &e->networks; n = n->next) {
+       if (!r) {
+         r = zebra_create_ipv4_route_table_entry(n->A_network_addr.v4, 
+                                                 n->A_netmask.v4,
+                                                 e->A_gateway_addr.v4);
+         t = r;
+       }
+       else {
+         t->next = zebra_create_ipv4_route_table_entry(n->A_network_addr.v4, 
+                                                       n->A_netmask.v4,
+                                                       e->A_gateway_addr.v4);
+         t = t->next;
+       }
+      }
+    }
+  }
+  
+  return r;
+  
+}
+
+
+static struct ipv4_route *zebra_create_ipv4_route_table_entry (uint32_t addr, 
+                                                              uint32_t mask,
+                                                              uint32_t gw) {
+  
+  struct ipv4_route *r;
+  
+
+  r = olsr_malloc (sizeof *r,"zebra_create_ipv4_route_table_entry");
+  memset (r, 0, sizeof *r);
+  r->prefix = addr;
+  r->prefixlen = masktoprefixlen (mask);
+  r->message |= ZAPI_MESSAGE_NEXTHOP;
+  r->nh_count = 1;
+  r->nexthops = olsr_malloc (sizeof (uint32_t), "zebra_create_ipv4_route_table_entry"); 
+  *r->nexthops = gw;
+  r->next = NULL;
+
+  return r;
+}
+
+static uint8_t masktoprefixlen (uint32_t mask) {
+  
+  
+  uint8_t prefixlen = 0;
+  while (mask & (1 << ++prefixlen && prefixlen < 32);
+  return prefixlen;
+
+}
+
+static void update_olsr_zebra_routes (struct ipv4_route *a, 
+                                     struct ipv4_route *r) {
+  
+  struct ipv4_route *t;
+
+  if (!r) {
+    puts("no quagga_routing_table aviable");
+    for (;a;a = a->next) {
+      dump_ipv4_route (*a, "adding this route");
+      //      zebra_add_v4_route(*r);
+    }
+    return;
+  }
+
+  while (a) {
+    for (t = r; t; t = t->next) {
+      if (a->prefix == t->prefix) 
+       if (a->prefixlen == t->prefixlen)
+         if (*a->nexthops == *t->nexthops) {
+           goto foo;
+         }
+    }
+    dump_ipv4_route (*a, "adding this route");
+    //zebra_add_v4_route(*a);
+  foo:
+    a = a->next;
+  }
+
+  while (r) {
+    for (t = a; t; t = t->next) {
+      if (r->prefix == t->prefix) 
+       if (r->prefixlen == t->prefixlen)
+         if (*r->nexthops == *t->nexthops) {
+           goto bar;
+         }
+    }
+    dump_ipv4_route (*r, "deleting this route");
+    //zebra_delete_v4_route(*r);
+  bar:
+    r = r->next;
+  }
+
+}
+
+
+static void zebra_free_ipv4_route_table (struct ipv4_route *r) {
+  struct ipv4_route *n;
+  if (!r) return;
+  while ((n = r->next)) {
+    if (r->message & ZAPI_MESSAGE_NEXTHOP) free (r->nexthops);
+    if (r->message & ZAPI_MESSAGE_IFINDEX) free (r->index);
+    free(r);
+    r = n;
+  }
+}
diff --git a/lib/quagga/version-script.txt b/lib/quagga/version-script.txt
new file mode 100644 (file)
index 0000000..3d09da3
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_register_param;
+    olsrd_plugin_init;
+
+  local:
+    *;
+};
diff --git a/lib/txtinfo/.cvsignore b/lib/txtinfo/.cvsignore
new file mode 100644 (file)
index 0000000..3c79b1b
--- /dev/null
@@ -0,0 +1,2 @@
+*.d
+olsrd_txtinfo.so.*
diff --git a/lib/txtinfo/Makefile b/lib/txtinfo/Makefile
new file mode 100644 (file)
index 0000000..bddb0e7
--- /dev/null
@@ -0,0 +1,57 @@
+# The olsr.org Optimized Link-State Routing daemon(olsrd)
+# Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+# 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 olsr.org, olsrd 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 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.
+#
+# Visit http://www.olsr.org for more information.
+#
+# If you find this software useful feel free to make a donation
+# to the project. For more information see the website or contact
+# the copyright holders.
+#
+# $Id: Makefile,v 1.1 2007/01/31 12:38:26 bernd67 Exp $
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_txtinfo
+PLUGIN_VER =   0.1
+
+TOPDIR =       ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS)
+               $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install:       $(PLUGIN_FULLNAME)
+               $(STRIP) $(PLUGIN_FULLNAME)
+               $(INSTALL_LIB)
+
+clean:
+               rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
diff --git a/lib/txtinfo/README_TXTINFO b/lib/txtinfo/README_TXTINFO
new file mode 100644 (file)
index 0000000..11f5991
--- /dev/null
@@ -0,0 +1,16 @@
+LoadPlugin "olsrd_txtinfo.so.0.1"
+{
+        PlParam "accept" "10.247.200.4"
+}
+
+ABOUT
+
+telnet 127.0.0.1 2006
+or
+wget localhost:2006 -qO -
+
+installation:
+make
+make install
+
+- Lorenz Schori
diff --git a/lib/txtinfo/src/olsrd_plugin.c b/lib/txtinfo/src/olsrd_plugin.c
new file mode 100644 (file)
index 0000000..327e141
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * 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 olsr.org, olsrd 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 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ * $Id: olsrd_plugin.c,v 1.1 2007/01/31 12:38:26 bernd67 Exp $
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "olsrd_plugin.h"
+#include "olsrd_txtinfo.h"
+
+
+#define PLUGIN_NAME    "OLSRD txtinfo plugin"
+#define PLUGIN_VERSION "0.1"
+#define PLUGIN_AUTHOR   "Lorenz Schori"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 4
+
+
+struct in_addr ipc_accept_ip;
+int ipc_port;
+int nompr;
+
+
+static void __attribute__ ((constructor)) 
+my_init(void);
+
+static void __attribute__ ((destructor)) 
+my_fini(void);
+
+
+/**
+ *Constructor
+ */
+static void
+my_init()
+{
+  /* Print plugin info to stdout */
+  printf("%s\n", MOD_DESC);
+
+  /* defaults for parameters */
+  ipc_port = 2006;
+  ipc_accept_ip.s_addr = htonl(INADDR_LOOPBACK);
+
+       /* highlite neighbours by default */
+       nompr = 0;
+}
+
+
+/**
+ *Destructor
+ */
+static void
+my_fini()
+{
+  /* Calls the destruction function
+   * olsr_plugin_exit()
+   * This function should be present in your
+   * sourcefile and all data destruction
+   * should happen there - NOT HERE!
+   */
+  olsr_plugin_exit();
+}
+
+
+int 
+olsrd_plugin_interface_version()
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+
+int
+olsrd_plugin_register_param(char *key, char *value)
+{
+  if(!strcmp(key, "port"))
+    {
+     ipc_port = atoi(value);
+     printf("(TXTINFO) listening on port: %d\n", ipc_port);
+    }
+
+  if(!strcmp(key, "accept"))
+    {
+       inet_aton(value, &ipc_accept_ip);
+       printf("(TXTINFO) accept only: %s\n", inet_ntoa(ipc_accept_ip));
+    }
+/*
+       if(!strcmp(key, "hilitemprneighbours"))
+       {
+               if(!strcmp(value, "false") || !strcmp(value, "0"))
+               {
+                       nompr=1;
+               }
+       }
+       */
+  return 1;
+}
diff --git a/lib/txtinfo/src/olsrd_txtinfo.c b/lib/txtinfo/src/olsrd_txtinfo.c
new file mode 100644 (file)
index 0000000..486b7ea
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ *                     includes code by Bruno Randolf
+ *                     includes code by Andreas Lopatic
+ *                     includes code by Sven-Ola Tuecke
+ *                     includes code by Lorenz Schori
+ * 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 olsr.org, olsrd 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 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ * $Id: olsrd_txtinfo.c,v 1.1 2007/01/31 12:38:26 bernd67 Exp $
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "olsr.h"
+#include "olsr_types.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "mpr_selector_set.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "link_set.h"
+#include "socket_parser.h"
+
+#include "olsrd_txtinfo.h"
+#include "olsrd_plugin.h"
+
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+#endif
+
+
+static int ipc_socket;
+static int ipc_open;
+static int ipc_connection;
+static int ipc_socket_up;
+
+
+/* IPC initialization function */
+static int
+plugin_ipc_init(void);
+
+static void 
+send_info(int neighonly);
+
+static void
+ipc_action(int);
+
+static void inline
+ipc_print_neigh_link(void);
+
+static void inline
+ipc_print_routes(void);
+
+static void inline
+ipc_print_topology(void);
+
+static void inline
+ipc_print_hna(void);
+
+#define TXT_IPC_BUFSIZE 256
+static int 
+ipc_sendf(const char* format, ...);
+
+/**
+ *Do initialization here
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ */
+int
+olsrd_plugin_init()
+{
+  /* Initial IPC value */
+  ipc_open = 0;
+  ipc_socket_up = 0;
+
+  plugin_ipc_init();
+  return 1;
+}
+
+
+/**
+ * destructor - called at unload
+ */
+void
+olsr_plugin_exit()
+{
+  if(ipc_open)
+    close(ipc_socket);
+}
+
+
+
+static int
+plugin_ipc_init()
+{
+  struct sockaddr_in sin;
+  olsr_u32_t yes = 1;
+
+  /* Init ipc socket */
+  if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+    {
+#ifndef NODEBUG
+      olsr_printf(1, "(TXTINFO) socket()=%s\n", strerror(errno));
+#endif
+      return 0;
+    }
+  else
+    {
+      if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
+      {
+#ifndef NODEBUG
+       olsr_printf(1, "(TXTINFO) setsockopt()=%s\n", strerror(errno));
+#endif
+       return 0;
+      }
+
+#if defined __FreeBSD__ && defined SO_NOSIGPIPE
+      if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) 
+      {
+       perror("SO_REUSEADDR failed");
+       return 0;
+      }
+#endif
+
+      /* Bind the socket */
+      
+      /* complete the socket structure */
+      memset(&sin, 0, sizeof(sin));
+      sin.sin_family = AF_INET;
+      sin.sin_addr.s_addr = INADDR_ANY;
+      sin.sin_port = htons(ipc_port);
+      
+      /* bind the socket to the port number */
+      if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
+       {
+#ifndef NODEBUG
+         olsr_printf(1, "(TXTINFO) bind()=%s\n", strerror(errno));
+#endif
+         return 0;
+       }
+      
+      /* show that we are willing to listen */
+      if (listen(ipc_socket, 1) == -1) 
+       {
+#ifndef NODEBUG
+         olsr_printf(1, "(TXTINFO) listen()=%s\n", strerror(errno));
+#endif
+         return 0;
+       }
+       
+      /* Register with olsrd */
+      add_olsr_socket(ipc_socket, &ipc_action);
+
+#ifndef NODEBUG
+      olsr_printf(2, "(TXTINFO) listening on port %d\n",ipc_port);
+#endif
+      ipc_socket_up = 1;
+    }
+
+  return 1;
+}
+
+
+static void
+ipc_action(int fd)
+{
+  struct sockaddr_in pin;
+  socklen_t addrlen;
+  char *addr;  
+
+  addrlen = sizeof(struct sockaddr_in);
+
+  if(ipc_open)
+    return;
+
+  if ((ipc_connection = accept(fd, (struct sockaddr *)  &pin, &addrlen)) == -1)
+    {
+#ifndef NODEBUG
+      olsr_printf(1, "(TXTINFO) accept()=%s\n", strerror(errno));
+#endif
+      exit(1);
+    }
+  else
+    {
+      addr = inet_ntoa(pin.sin_addr);
+      if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
+       {
+         olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
+         close(ipc_connection);
+         return;
+       }
+      else
+       {
+      ipc_open = 1;
+#ifndef NODEBUG
+      olsr_printf(2, "(TXTINFO) Connect from %s\n",addr);
+#endif
+      
+      /* purge read buffer to prevent blocking on linux*/
+      fd_set rfds;
+      FD_ZERO(&rfds);
+      FD_SET(ipc_connection, &rfds);
+      struct timeval tv = {0,0};
+      int neighonly = 0;
+      if(select(ipc_connection+1, &rfds, NULL, NULL, &tv)) {
+        char requ[128];
+        ssize_t s = recv(ipc_connection, &requ, sizeof(requ), 0);
+        if (0 < s) {
+          requ[s] = 0;
+          /* To print out neighbours only on the Freifunk Status
+           * page the normal output is somewhat lengthy. The
+           * header parsing is sufficient for standard wget.
+           */
+          neighonly = (0 != strstr(requ, "/neighbours"));
+        }
+      }
+
+      send_info(neighonly);
+         
+      close(ipc_connection);
+      ipc_open = 0;
+    }
+  }
+}
+
+static void inline
+ipc_print_neigh_link(void)
+{
+  struct neighbor_entry *neigh;
+  struct neighbor_2_list_entry *list_2;
+  struct link_entry *link = NULL;
+  int index, thop_cnt;
+
+       ipc_sendf("Table: Links\nLocal IP\tremote IP\tHysteresis\tLinkQuality\tlost\ttotal\tNLQ\tETX\n");
+
+  /* Link set */
+  link = link_set;
+       while(link)
+       {
+       ipc_sendf( "%s\t%s\t%0.2f\t%0.2f\t%d\t%d\t%0.2f\t%0.2f\t\n",
+                       olsr_ip_to_string(&link->local_iface_addr),
+                       olsr_ip_to_string(&link->neighbor_iface_addr),
+                       link->L_link_quality, 
+                       link->loss_link_quality,
+                       link->lost_packets, 
+                       link->total_packets,
+                       link->neigh_link_quality, 
+                       (link->loss_link_quality * link->neigh_link_quality) ? 1.0 / (link->loss_link_quality * link->neigh_link_quality) : 0.0);
+               link = link->next;
+      }
+       ipc_sendf("\nTable: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWillingness\t2 Hop Neighbors\n");
+
+  /* Neighbors */
+  for(index=0;index<HASHSIZE;index++)
+    {
+      for(neigh = neighbortable[index].next;
+         neigh != &neighbortable[index];
+         neigh = neigh->next)
+       {
+               ipc_sendf( 
+                         "%s\t%s\t%s\t%s\t%d\t", 
+                         olsr_ip_to_string(&neigh->neighbor_main_addr),
+                         (neigh->status == SYM) ? "YES" : "NO",
+                         neigh->is_mpr ? "YES" : "NO",
+                         olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
+                         neigh->willingness);
+
+         thop_cnt = 0;
+
+         for(list_2 = neigh->neighbor_2_list.next;
+             list_2 != &neigh->neighbor_2_list;
+             list_2 = list_2->next)
+           {
+             //size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&list_2->neighbor_2->neighbor_2_addr));
+             thop_cnt ++;
+           }
+               ipc_sendf("%d\n", thop_cnt);
+       }
+    }
+
+       ipc_sendf("\n");
+}
+
+
+static void inline
+ipc_print_routes(void)
+{
+  int size = 0, index;
+  struct rt_entry *routes;
+
+       ipc_sendf("Table: Routes\nDestination\tGateway\tMetric\tETX\tInterface\tType\n");
+
+  /* Neighbors */
+  for(index = 0;index < HASHSIZE;index++)
+    {
+      for(routes = routingtable[index].next;
+         routes != &routingtable[index];
+         routes = routes->next)
+       {
+               size = 0;
+               ipc_sendf( "%s\t%s\t%d\t%.2f\t%s\tHOST\n",
+                         olsr_ip_to_string(&routes->rt_dst),
+                         olsr_ip_to_string(&routes->rt_router),
+                         routes->rt_metric,
+                         routes->rt_etx,
+                         routes->rt_if->int_name);
+       }
+    }
+
+  /* HNA */
+  for(index = 0;index < HASHSIZE;index++)
+    {
+      for(routes = hna_routes[index].next;
+         routes != &hna_routes[index];
+         routes = routes->next)
+       {
+               ipc_sendf("%s\t%s\t%d\t%s\t\tHNA\n",
+                         olsr_ip_to_string(&routes->rt_dst),
+                         olsr_ip_to_string(&routes->rt_router),
+                         routes->rt_metric,
+                         routes->rt_if->int_name);
+       }
+    }
+
+       ipc_sendf("\n");
+
+}
+
+static void inline
+ipc_print_topology(void)
+{
+  olsr_u8_t index;
+  struct tc_entry *entry;
+  struct topo_dst *dst_entry;
+
+
+  ipc_sendf("Table: Topology\nDestination IP\tLast hop IP\tLQ\tILQ\tETX\n");
+
+  /* Topology */  
+  for(index=0;index<HASHSIZE;index++)
+    {
+      /* For all TC entries */
+      entry = tc_table[index].next;
+      while(entry != &tc_table[index])
+       {
+         /* For all destination entries of that TC entry */
+         dst_entry = entry->destinations.next;
+         while(dst_entry != &entry->destinations)
+           {
+                       ipc_sendf( "%s\t%s\t%0.2f\t%0.2f\t%0.2f\n", 
+                             olsr_ip_to_string(&dst_entry->T_dest_addr),
+                             olsr_ip_to_string(&entry->T_last_addr), 
+                             dst_entry->link_quality,
+                             dst_entry->inverse_link_quality,
+                             (dst_entry->link_quality * dst_entry->inverse_link_quality) ? 1.0 / (dst_entry->link_quality * dst_entry->inverse_link_quality) : 0.0);
+               
+             dst_entry = dst_entry->next;
+           }
+         entry = entry->next;
+       }
+    }
+
+  ipc_sendf("\n");
+}
+
+static void inline
+ipc_print_hna(void)
+{
+  int size;
+  olsr_u8_t index;
+  struct hna_entry *tmp_hna;
+  struct hna_net *tmp_net;
+
+  size = 0;
+
+  ipc_sendf("Table: HNA\nNetwork\tNetmask\tGateway\n");
+
+  /* Announced HNA entries */
+       struct hna4_entry *hna4;
+       for(hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
+         {
+                       ipc_sendf("%s\t%s\t%s\n",
+                         olsr_ip_to_string(&hna4->net),
+                         olsr_ip_to_string(&hna4->netmask),
+                               olsr_ip_to_string(&olsr_cnf->main_addr));
+         }
+       struct hna6_entry *hna6;
+       for(hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
+         {
+                       ipc_sendf("%s\t%d\t%s\n",
+                         olsr_ip_to_string(&hna6->net),
+                               hna6->prefix_len,
+                       olsr_ip_to_string(&olsr_cnf->main_addr));
+               }
+
+  /* HNA entries */
+  for(index=0;index<HASHSIZE;index++)
+    {
+      tmp_hna = hna_set[index].next;
+      /* Check all entrys */
+      while(tmp_hna != &hna_set[index])
+       {
+         /* Check all networks */
+         tmp_net = tmp_hna->networks.next;
+             
+         while(tmp_net != &tmp_hna->networks)
+           {
+               if (AF_INET == olsr_cnf->ip_version) {
+                       ipc_sendf("%s\t%s\t%s\n",
+                               olsr_ip_to_string(&tmp_net->A_network_addr),
+                               olsr_ip_to_string((union olsr_ip_addr *)&tmp_net->A_netmask.v4),
+                               olsr_ip_to_string(&tmp_hna->A_gateway_addr));
+               }
+               else {
+                       ipc_sendf("%s\t%d\t%s\n",
+                               olsr_ip_to_string(&tmp_net->A_network_addr),
+                               tmp_net->A_netmask.v6,
+                               olsr_ip_to_string(&tmp_hna->A_gateway_addr));
+               }
+             tmp_net = tmp_net->next;
+           }
+             
+         tmp_hna = tmp_hna->next;
+       }
+    }
+
+       ipc_sendf("\n");
+
+}
+
+
+static void 
+send_info(int neighonly)
+{
+       
+       /* Print minimal http header */
+       ipc_sendf("HTTP/1.0 200 OK\n");
+       ipc_sendf("Content-type: text/plain\n\n");
+
+       /* Print tables to IPC socket */
+       
+       /* links + Neighbors */
+       ipc_print_neigh_link();
+       
+       /* topology */
+       if (!neighonly) ipc_print_topology();
+       
+       /* hna */
+       if (!neighonly) ipc_print_hna();
+
+       /* routes */
+       if (!neighonly) ipc_print_routes();
+}
+
+/*
+ * In a bigger mesh, there are probs with the fixed
+ * bufsize. Because the Content-Length header is
+ * optional, the sprintf() is changed to a more
+ * scalable solution here.
+ */
+static int 
+ipc_sendf(const char* format, ...)
+{
+       char txtnetbuf[TXT_IPC_BUFSIZE];
+
+       va_list arg;
+       int rv;
+#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__
+       int flags = 0;
+#else
+       int flags = MSG_NOSIGNAL;
+#endif
+       va_start(arg, format);
+       rv = vsnprintf(txtnetbuf, sizeof(txtnetbuf), format, arg);
+       va_end(arg);
+       if(ipc_socket_up) {
+               if (0 > send(ipc_connection, txtnetbuf, rv, flags)) {
+#ifndef NODEBUG
+                       olsr_printf(1, "(TXTINFO) Failed sending data to client!\n");
+#endif
+                       close(ipc_connection);
+                       return - 1;
+               }
+       }
+       return rv;
+}
diff --git a/lib/txtinfo/src/olsrd_txtinfo.h b/lib/txtinfo/src/olsrd_txtinfo.h
new file mode 100644 (file)
index 0000000..4f262bf
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ *                     includes code by Bruno Randolf
+ * 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 olsr.org, olsrd 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 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ * $Id: olsrd_txtinfo.h,v 1.1 2007/01/31 12:38:26 bernd67 Exp $
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_DOT_DRAW
+#define _OLSRD_DOT_DRAW
+
+
+extern struct in_addr ipc_accept_ip;
+extern int ipc_port;
+extern int nompr;
+
+
+int
+olsrd_plugin_init(void);
+
+void
+olsr_plugin_exit(void);
+
+#endif
diff --git a/lib/txtinfo/version-script.txt b/lib/txtinfo/version-script.txt
new file mode 100644 (file)
index 0000000..3d09da3
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_register_param;
+    olsrd_plugin_init;
+
+  local:
+    *;
+};