merge olsrd changes with freifunks code changes. compiles completely, but have not...
authorTim Yardley <lst@openwrt.org>
Tue, 6 Feb 2007 16:45:04 +0000 (16:45 +0000)
committerTim Yardley <lst@openwrt.org>
Tue, 6 Feb 2007 16:45:04 +0000 (16:45 +0000)
SVN-Revision: 6273

21 files changed:
net/olsrd/patches/110-olsrd-libsmake.patch [new file with mode: 0644]
net/olsrd/patches/120-olsrd-dyngwplain.patch [new file with mode: 0644]
net/olsrd/patches/120-secure_path.patch [deleted file]
net/olsrd/patches/130-olsrd-nameservice+services.patch [new file with mode: 0644]
net/olsrd/patches/130-olsrd_fixes.patch [deleted file]
net/olsrd/patches/140-olsrd-txtinfo.patch [new file with mode: 0644]
net/olsrd/patches/140-olsrd_optimize.patch [deleted file]
net/olsrd/patches/150-hna_ip_fix.patch [deleted file]
net/olsrd/patches/150-olsrd-quagga.patch [new file with mode: 0644]
net/olsrd/patches/160-olsrd-quagga-routehandler.patch [new file with mode: 0644]
net/olsrd/patches/170-olsrd-bmf.patch [new file with mode: 0644]
net/olsrd/patches/180-olsrd-bmf-fixes.patch [new file with mode: 0644]
net/olsrd/patches/190-olsrd-optimize.patch [new file with mode: 0644]
net/olsrd/patches/200-olsrd-fixes-eric.patch [new file with mode: 0644]
net/olsrd/patches/210-olsrd-fixes-sven-ola.patch [new file with mode: 0644]
net/olsrd/patches/220-olsrd-fixes-jhay-bsd.patch [new file with mode: 0644]
net/olsrd/patches/230-olsrd-fixes-backport.patch [new file with mode: 0644]
net/olsrd/patches/240-olsrd-fixes-routedel.patch [new file with mode: 0644]
net/olsrd/patches/250-olsrd-cpu-overload.patch [new file with mode: 0644]
net/olsrd/patches/260-olsrd-secure_key_path.patch [new file with mode: 0644]
net/olsrd/patches/270-olsrd-hna_ip_fix.patch [new file with mode: 0644]

diff --git a/net/olsrd/patches/110-olsrd-libsmake.patch b/net/olsrd/patches/110-olsrd-libsmake.patch
new file mode 100644 (file)
index 0000000..018604d
--- /dev/null
@@ -0,0 +1,9 @@
+diff -Nur olsrd-0.4.10.orig/lib/Makefile olsrd-0.4.10/lib/Makefile
+--- olsrd-0.4.10.orig/lib/Makefile     2005-05-26 18:09:25.000000000 +0200
++++ olsrd-0.4.10/lib/Makefile  2006-12-01 08:18:12.000000000 +0100
+@@ -1,4 +1,4 @@
+-SUBDIRS = dot_draw dyn_gw httpinfo mini nameservice powerinfo secure tas
++SUBDIRS = $(shell find -maxdepth 1 -type d -not -name ".*" -not -name "CVS" -printf "%f\n")
+ .PHONY: $(SUBDIRS)
diff --git a/net/olsrd/patches/120-olsrd-dyngwplain.patch b/net/olsrd/patches/120-olsrd-dyngwplain.patch
new file mode 100644 (file)
index 0000000..2d0d5f3
--- /dev/null
@@ -0,0 +1,364 @@
+diff -Nur olsrd-0.4.10.orig/lib/dyn_gw_plain/Makefile olsrd-0.4.10/lib/dyn_gw_plain/Makefile
+--- olsrd-0.4.10.orig/lib/dyn_gw_plain/Makefile        1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/dyn_gw_plain/Makefile     2006-12-01 08:26:58.000000000 +0100
+@@ -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: olsrd-dyngwplain.patch,v 1.5 2006/12/04 08:33:46 sven-ola 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 -Nur olsrd-0.4.10.orig/lib/dyn_gw_plain/README_DYN_GW_PLAIN olsrd-0.4.10/lib/dyn_gw_plain/README_DYN_GW_PLAIN
+--- olsrd-0.4.10.orig/lib/dyn_gw_plain/README_DYN_GW_PLAIN     1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/dyn_gw_plain/README_DYN_GW_PLAIN  2006-12-01 08:26:58.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c olsrd-0.4.10/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c
+--- olsrd-0.4.10.orig/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c        1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c     2006-12-01 08:26:58.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h olsrd-0.4.10/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h
+--- olsrd-0.4.10.orig/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h        1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h     2006-12-01 08:26:58.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/dyn_gw_plain/version-script.txt olsrd-0.4.10/lib/dyn_gw_plain/version-script.txt
+--- olsrd-0.4.10.orig/lib/dyn_gw_plain/version-script.txt      1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/dyn_gw_plain/version-script.txt   2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,10 @@
++VERS_1.0
++{
++  global:
++    olsrd_plugin_interface_version;
++    olsrd_plugin_register_param;
++    olsrd_plugin_init;
++
++  local:
++    *;
++};
+diff -Nur olsrd-0.4.10.orig/Makefile olsrd-0.4.10/Makefile
+--- olsrd-0.4.10.orig/Makefile 2006-01-04 09:45:38.000000000 +0100
++++ olsrd-0.4.10/Makefile      2006-12-01 08:26:58.000000000 +0100
+@@ -144,6 +144,11 @@
+               $(MAKE) -C lib/dyn_gw
+               $(MAKE) -C lib/dyn_gw install
++dyn_gw_plain:
++              $(MAKE) -C lib/dyn_gw_plain clean
++              $(MAKE) -C lib/dyn_gw_plain
++              $(MAKE) -C lib/dyn_gw_plain install
++
+ powerinfo:
+               $(MAKE) -C lib/powerinfo clean
+               $(MAKE) -C lib/powerinfo 
diff --git a/net/olsrd/patches/120-secure_path.patch b/net/olsrd/patches/120-secure_path.patch
deleted file mode 100644 (file)
index fcae759..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -ruN olsrd-0.4.9-orig/lib/secure/src/olsrd_secure.h olsrd-0.4.9-1/lib/secure/src/olsrd_secure.h
---- olsrd-0.4.9-orig/lib/secure/src/olsrd_secure.h     2005-03-10 20:57:48.000000000 +0100
-+++ olsrd-0.4.9-1/lib/secure/src/olsrd_secure.h        2005-04-05 00:51:40.000000000 +0200
-@@ -43,7 +43,7 @@
- #include "olsrd_plugin.h"
--#define KEYFILE "/root/.olsr/olsrd_secure_key"
-+#define KEYFILE "/etc/olsrd.d/olsrd_secure_key"
- /* Schemes */
- #define ONE_CHECKSUM          1
diff --git a/net/olsrd/patches/130-olsrd-nameservice+services.patch b/net/olsrd/patches/130-olsrd-nameservice+services.patch
new file mode 100644 (file)
index 0000000..6d23dad
--- /dev/null
@@ -0,0 +1,1287 @@
+diff -Nur olsrd-0.4.10.orig/lib/nameservice/src/nameservice.c olsrd-0.4.10/lib/nameservice/src/nameservice.c
+--- olsrd-0.4.10.orig/lib/nameservice/src/nameservice.c        2005-05-29 14:47:42.000000000 +0200
++++ olsrd-0.4.10/lib/nameservice/src/nameservice.c     2006-12-01 08:26:58.000000000 +0100
+@@ -1,4 +1,5 @@
+ /*
++ * Copyright (c) 2006, Jens Nachtigall <nachtigall@web.de>
+  * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+  * Copyright (c) 2004, Andreas Tønnesen(andreto-at-olsr.org)
+  * All rights reserved.
+@@ -39,6 +40,9 @@
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <ctype.h>
++#include <sys/types.h>
++#include <regex.h>
+ #include "olsr.h"
+ #include "net_olsr.h"
+@@ -53,6 +57,7 @@
+ #include "olsrd_copy.h"
+ #include "compat.h"
++
+ /* send buffer: huge */
+ static char buffer[10240];
+@@ -62,15 +67,35 @@
+ static char my_suffix[MAX_SUFFIX];
+ static int my_interval = EMISSION_INTERVAL;
+ static double my_timeout = NAME_VALID_TIME;
+-static olsr_bool have_dns_server = OLSR_FALSE;
+-static union olsr_ip_addr my_dns_server;
+ static char my_resolv_file[MAX_FILE +1];
++static char my_services_file[MAX_FILE + 1];
+-/* the database (using hashing) */
++/* the databases (using hashing)
++ * for hostnames, service_lines and dns-servers
++ *
++ * my own hostnames, service_lines and dns-servers
++ * are store in a linked list (without hashing)
++ * */
+ struct db_entry* list[HASHSIZE];
+ struct name_entry *my_names = NULL;
+ olsr_bool name_table_changed = OLSR_TRUE;
++struct db_entry* service_list[HASHSIZE];
++struct name_entry *my_services = NULL;
++olsr_bool service_table_changed = OLSR_TRUE;
++
++struct db_entry* forwarder_list[HASHSIZE];
++struct name_entry *my_forwarders = NULL;
++olsr_bool forwarder_table_changed = OLSR_TRUE;
++
++/* regualar expression to be matched by valid hostnames, compiled in name_init() */
++regex_t regex_t_name;
++regmatch_t regmatch_t_name;
++
++/* regualar expression to be matched by valid service_lines, compiled in name_init() */
++regex_t regex_t_service;
++int pmatch_service = 10;
++regmatch_t regmatch_t_service[10];
+ /**
+  * do initialization
+@@ -84,27 +109,39 @@
+       int len;
+       GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
++      GetWindowsDirectory(my_services_file, MAX_FILE - 12);
+       len = strlen(my_hosts_file);
+- 
+       if (my_hosts_file[len - 1] != '\\')
+               my_hosts_file[len++] = '\\';
+- 
+       strcpy(my_hosts_file + len, "hosts_olsr");
++      
++    len = strlen(my_services_file);
++      if (my_services_file[len - 1] != '\\')
++              my_services_file[len++] = '\\';
++      strcpy(my_services_file + len, "services_olsr");
++
++    len = strlen(my_resolv_file);
++      if (my_resolv_file[len - 1] != '\\')
++              my_resolv_file[len++] = '\\';
++      strcpy(my_resolv_file + len, "resolvconf_olsr");
+ #else
+       strcpy(my_hosts_file, "/var/run/hosts_olsr");
++      strcpy(my_services_file, "/var/run/services_olsr");
++      strcpy(my_resolv_file, "/var/run/resolvconf_olsr");
+ #endif
+       my_suffix[0] = '\0';
+       my_add_hosts[0] = '\0';
+-      my_resolv_file[0] = '\0';
+       
+-      /* init list */
++      /* init lists */
+       for(i = 0; i < HASHSIZE; i++) {
+               list[i] = NULL;
++              forwarder_list[i] = NULL;
++        service_list[i] = NULL;
+       }
+       
+-      memset(&my_dns_server, 0, sizeof(my_dns_server));
++
+ }
+@@ -116,56 +153,53 @@
+ {
+       if(!strcmp(key, "interval")) {
+               my_interval = atoi(value);
+-              printf("\nNAME PLUGIN: parameter interval: %d\n", my_interval);
++              olsr_printf(1,"\nNAME PLUGIN: parameter interval: %d", my_interval);
+       }
+       else if(!strcmp(key, "timeout")) {
+               my_timeout = atof(value);
+-              printf("\nNAME PLUGIN: parameter timeout: %f\n", my_timeout);
++              olsr_printf(1,"\nNAME PLUGIN: parameter timeout: %f", my_timeout);
+       } 
+       else if(!strcmp(key, "hosts-file")) {
+               strncpy( my_hosts_file, value, MAX_FILE );
+-              printf("\nNAME PLUGIN: parameter filename: %s\n", my_hosts_file);
++              olsr_printf(1,"\nNAME PLUGIN: parameter filename: %s", my_hosts_file);
+       }
+       else if(!strcmp(key, "resolv-file")) {
+               strncpy(my_resolv_file, value, MAX_FILE);
+-              printf("\nNAME PLUGIN: parameter resolv file: %s\n", my_resolv_file);
++              olsr_printf(1,"\nNAME PLUGIN: parameter resolv-file: %s", my_resolv_file);
+       }
+       else if(!strcmp(key, "suffix")) {
+               strncpy(my_suffix, value, MAX_SUFFIX);
+-              printf("\nNAME PLUGIN: parameter suffix: %s\n", my_suffix);
++              olsr_printf(1,"\nNAME PLUGIN: parameter suffix: %s", my_suffix);
+       }
+       else if(!strcmp(key, "add-hosts")) {
+               strncpy(my_add_hosts, value, MAX_FILE);
+-              printf("\nNAME PLUGIN: parameter additional host: %s\n", my_add_hosts);
++              olsr_printf(1,"\nNAME PLUGIN: parameter additional host: %s", my_add_hosts);
++      }
++      else if(!strcmp(key, "services-file")) {
++              strncpy(my_services_file, value, MAX_FILE);
++              olsr_printf(1,"\nNAME PLUGIN: parameter services-file: %s", my_services_file);
+       }
+       else if(!strcmp(key, "dns-server")) {
+               struct in_addr ip;
+               if (strlen(value) == 0) {
+-                      // set dns server ip to main address
+-                      // which is not known yet
+-                      have_dns_server = OLSR_TRUE;
+-              }
+-              else if (inet_aton(value, &ip)) {
+-                      my_dns_server.v4 = ip.s_addr;
+-                      have_dns_server = OLSR_TRUE;
+-              }
+-              else {
+-                      printf("\nNAME PLUGIN: invalid dns-server IP %s\n", value);
+-              }
++            my_forwarders = add_name_to_list(my_forwarders, "", NAME_FORWARDER, NULL);
++            olsr_printf(1,"\nNAME PLUGIN: parameter dns-server: (main address)");
++        } else if (inet_aton(value, &ip)) {
++            my_forwarders = add_name_to_list(my_forwarders, "", NAME_FORWARDER, &ip);
++            olsr_printf(1,"\nNAME PLUGIN: parameter dns-server: (%s)", value);
++        } else {
++            olsr_printf(1,"\nNAME PLUGIN: invalid parameter dns-server: %s ", value);
++        }
+       }
+       else if(!strcmp(key, "name")) {
+               // name for main address
+-              struct name_entry *tmp;
+-              tmp = malloc(sizeof(struct name_entry));
+-              tmp->name = strndup( value, MAX_NAME );
+-              tmp->len = strlen( tmp->name );
+-              tmp->type = NAME_HOST;
+-              // will be set to main_addr later
+-              memset(&tmp->ip, 0, sizeof(tmp->ip));
+-              tmp->next = my_names;
+-              my_names = tmp;
+-              
+-              printf("\nNAME PLUGIN: parameter name: %s (main address)\n", tmp->name);
++        my_names = add_name_to_list(my_names, value, NAME_HOST, NULL);
++        olsr_printf(1,"\nNAME PLUGIN: parameter name: %s (main address)", value);
++      }
++      else if(!strcmp(key, "service")) {
++              // name for main address
++        my_services = add_name_to_list(my_services, value, NAME_SERVICE, NULL);
++        olsr_printf(1,"\nNAME PLUGIN: parameter service: %s (main address)", value);
+       }
+       else {
+               // assume this is an IP address and hostname
+@@ -173,33 +207,46 @@
+               
+               if (inet_aton(key, &ip)) {
+                       // the IP is validated later
+-                      struct name_entry *tmp;
+-                      tmp = malloc(sizeof(struct name_entry));
+-                      tmp->name = strndup( value, MAX_NAME );
+-                      tmp->len = strlen( tmp->name );
+-                      tmp->type = NAME_HOST;
+-                      tmp->ip.v4 = ip.s_addr;
+-                      tmp->next = my_names;
+-                      my_names = tmp;
+-                      printf("\nNAME PLUGIN: parameter %s (%s)\n", tmp->name,
+-                              olsr_ip_to_string(&tmp->ip));
++            my_names = add_name_to_list(my_names, value, NAME_HOST, &ip);
++                      olsr_printf(1,"\nNAME PLUGIN: parameter name %s (%s)", value, key);
+               } 
+               else {
+-                      printf("\nNAME PLUGIN: invalid IP %s for name %s!\n", key, value);
++                      olsr_printf(1,"\nNAME PLUGIN: invalid parameter name: %s (%s)!", value, key);
+               }
+       }
+       return 1;
+ }
++/**
++ * queue the name/forwarder/service given in value
++ * to the front of my_list
++ */
++struct name_entry* 
++add_name_to_list(struct name_entry *my_list, char *value, int type, struct in_addr *ip) 
++{
++              struct name_entry *tmp;
++              tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry add_name_to_list");
++        tmp->name = strndup( value, MAX_NAME );
++        tmp->len = strlen( tmp->name );
++        tmp->type = type;
++        // all IPs with value 0 will be set to main_addr later
++        if (ip==NULL) 
++            memset(&tmp->ip, 0, sizeof(tmp->ip));
++        else
++            tmp->ip.v4 = ip->s_addr;
++        tmp->next = my_list;
++        return tmp;
++}
++
+ /**
+  * last initialization
+  *
+  * we have to do this here because some things like main_addr 
+- * are not known before
++ * or the dns suffix (for validation) are not known before
+  *
+- * this is beause of the order in which the plugin is initzalized 
++ * this is beause of the order in which the plugin is initialized 
+  * by the plugin loader:
+  *   - first the parameters are sent
+  *   - then register_olsr_data() from olsrd_plugin.c is called
+@@ -210,50 +257,78 @@
+ name_init()
+ {
+       struct name_entry *name;
+-      struct name_entry *prev=NULL;
+-
+-      /* fixup names and IP addresses */
++    int ret;
++    //regex string for validating the hostnames
++    char *regex_name = "^[[:alnum:]_.-]+$";
++    //regex string for the service line
++    char *regex_service = olsr_malloc(256*sizeof(char) + strlen(my_suffix), "new *char from name_init for regex_service");
++
++    //compile the regex from the string
++      if ((ret = regcomp(&regex_t_name, regex_name , REG_EXTENDED)) != 0)
++    {
++              /* #2: call regerror() if regcomp failed 
++         * commented out, because only for debuggin needed
++         *
++        int errmsgsz = regerror(ret, &regex_t_name, NULL, 0);
++        char *errmsg = malloc(errmsgsz);
++        regerror(ret, &regex_t_name, errmsg, errmsgsz);
++        fprintf(stderr, "regcomp: %s", errmsg);
++        free(errmsg);
++        regfree(&regex_t_name);
++         * */
++        olsr_printf(0, "compilation of regex \"%s\" for hostname failed", regex_name);
++      }
++                  
++  // a service line is something like prot://hostname.suffix:port|tcp|my little description about this service
++  //                  for example     http://router.olsr:80|tcp|my homepage
++  //                     prot     ://  (hostname.suffix     OR         ip)
++  //regex_service = "^[[:alnum:]]+://(([[:alnum:]_.-]+.olsr)|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}))
++  //                 :    port              /path      |(tcp OR udp) |short description
++  //                 :[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$";
++  strcat (strcat (strcat(regex_service, "^[[:alnum:]]+://(([[:alnum:]_.-]+"),
++                  my_suffix),
++          ")|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3})):[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$");
++
++      /* #1: call regcomp() to compile the regex */
++      if ((ret = regcomp(&regex_t_service, regex_service , REG_EXTENDED )) != 0)
++    {
++              /* #2: call regerror() if regcomp failed 
++         * commented out, because only for debuggin needed
++         *
++              int errmsgsz = regerror(ret, &regex_t_service, NULL, 0);
++              char *errmsg = malloc(errmsgsz);
++              regerror(ret, &regex_t_service, errmsg, errmsgsz);
++              fprintf(stderr, "regcomp: %s", errmsg);
++              free(errmsg);
++              regfree(&regex_t_service);
++         * */
++        olsr_printf(0, "compilation of regex \"%s\" for hostname failed", regex_name);
++      }
++    free(regex_service);
++    regex_service = NULL;
++
++    //fill in main addr for all entries with ip==0
++    //this does not matter for service, because the ip does not matter
++    //for service
+       for (name = my_names; name != NULL; name = name->next) {
+-              if (name->ip.v4 == 0) {
+-                      // insert main_addr
++        if (name->ip.v4 == 0) {
++            olsr_printf(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
+                       memcpy(&name->ip, &main_addr, ipsize);
+-                      prev = name;
+-              } else {
+-                      // IP from config file
+-                      // check if we are allowed to announce a name for this IP
+-                      // we can only do this if we also announce the IP        
+-                      if (!allowed_ip(&name->ip)) {
+-                              olsr_printf(1, "NAME PLUGIN: name for unknown IP %s not allowed, fix your config!\n", 
+-                                      olsr_ip_to_string(&name->ip));
+-                              if (prev!=NULL) {
+-                                      prev->next = name->next;
+-                                      free(name->name);
+-                                      free(name);
+-                              }
+-                      }
+-                      else {
+-                              prev = name;
+-                      }
+-              }
+-      }
++        }
++    }
++      for (name = my_forwarders; name != NULL; name = name->next) {
++        if (name->ip.v4 == 0) {
++            olsr_printf(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
++                      memcpy(&name->ip, &main_addr, ipsize);
++        }
++    }
++
++    //check if entries I want to announce myself are valid and allowed
++    my_names = remove_nonvalid_names_from_list(my_names, NAME_HOST);
++    my_forwarders = remove_nonvalid_names_from_list(my_forwarders, NAME_FORWARDER);
++    my_services = remove_nonvalid_names_from_list(my_services, NAME_SERVICE);
++
+               
+-      if (have_dns_server) {
+-              if (my_dns_server.v4 == 0) {
+-                      memcpy(&my_dns_server, &main_addr, ipsize);
+-                      printf("\nNAME PLUGIN: announcing upstream DNS server: %s\n", 
+-                              olsr_ip_to_string(&my_dns_server));
+-              }
+-              else if (!allowed_ip(&my_dns_server)) {
+-                      printf("NAME PLUGIN: announcing DNS server on unknown IP %s is not allowed, fix your config!\n", 
+-                              olsr_ip_to_string(&my_dns_server));
+-                      memset(&my_dns_server, 0, sizeof(my_dns_server));
+-                      have_dns_server = OLSR_FALSE;
+-              }
+-              else {
+-                      printf("\nNAME PLUGIN: announcing upstream DNS server: %s\n", 
+-                              olsr_ip_to_string(&my_dns_server));
+-              }
+-      }
+       
+       /* register functions with olsrd */
+       olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
+@@ -263,22 +338,75 @@
+       return 1;
+ }
++struct name_entry*
++remove_nonvalid_names_from_list(struct name_entry *my_list, int type) 
++{
++    struct name_entry *next = my_list;
++    olsr_bool valid = OLSR_FALSE;
++    if (my_list == NULL) {
++        return NULL;
++    } 
++
++    switch (type) {
++        case NAME_HOST:
++            valid = is_name_wellformed(my_list->name) && allowed_ip(&my_list->ip); 
++            break;
++        case NAME_FORWARDER:
++            valid = allowed_ip(&my_list->ip);
++            break;
++        case NAME_SERVICE:
++            valid = allowed_service(my_list->name);
++            break;
++    }
++    
++    if ( !valid  ) {
++        olsr_printf(1, "NAME PLUGIN: invalid or malformed parameter %s (%s), fix your config!\n", my_list->name, olsr_ip_to_string(&my_list->ip));
++        next = my_list->next;
++        free(my_list->name);
++        my_list->name = NULL;
++        free(my_list);
++        my_list = NULL;
++        return remove_nonvalid_names_from_list(next, type);
++    } else {
++        olsr_printf(2, "NAME PLUGIN: validate parameter %s (%s) -> OK\n", my_list->name, olsr_ip_to_string(&my_list->ip));
++        my_list->next = remove_nonvalid_names_from_list(my_list->next, type);
++        return my_list;    
++    }
++}
++
++
+ /**
+  * called at unload: free everything
++ *
++ * XXX: should I delete the hosts/services/resolv.conf files on exit?
+  */
+ void
+ name_destructor()
+ {
+-      int i;
+-      struct db_entry **tmp;
+-      struct db_entry *to_delete;
+-      
+       olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
+       
+       free_name_entry_list(&my_names);
++      free_name_entry_list(&my_services);
++      free_name_entry_list(&my_forwarders);
++
++    free_all_list_entries(list);
++    free_all_list_entries(service_list);
++    free_all_list_entries(forwarder_list);
++
++    regfree(&regex_t_name);
++    regfree(&regex_t_service);
++      
++}
++
++/* free all list entries */
++void 
++free_all_list_entries(struct db_entry **this_db_list) 
++{
++      int i;
++      struct db_entry **tmp;
++      struct db_entry *to_delete;
+       
+-      /* free list entries */
+       for(i = 0; i < HASHSIZE; i++)
+       {
+               tmp = &list[i];
+@@ -296,24 +424,41 @@
+ /**
+  * A timeout function called every time
+- * the scheduler is polled: time out old list entries
++ *
++ * XXX:the scheduler is polled (by default 10 times a sec,
++ * which is far too often):
++ *
++ * time out old list entries
+  * and write changes to file
+  */
+ void
+ olsr_timeout()
+ {
++    timeout_old_names(list, &name_table_changed);
++    timeout_old_names(forwarder_list, &forwarder_table_changed);
++    timeout_old_names(service_list, &service_table_changed);
++     
++      write_resolv_file();
++      write_hosts_file();
++      write_services_file();
++}
++
++void
++timeout_old_names(struct db_entry **this_list, olsr_bool *this_table_changed)
++{
+       struct db_entry **tmp;
+       struct db_entry *to_delete;
+       int index;
+       for(index=0;index<HASHSIZE;index++)
+       {
+-              for (tmp = &list[index]; *tmp != NULL; )
++              for (tmp = &this_list[index]; *tmp != NULL; )
+               {
+-                      /* check if the entry is timed out */
++                      /* check if the entry for this ip is timed out */
+                       if (olsr_timed_out(&(*tmp)->timer))
+                       {
+                               to_delete = *tmp;
++                /* update the pointer in the linked list */
+                               *tmp = (*tmp)->next;
+                               
+                               olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n", 
+@@ -322,17 +467,17 @@
+                               /* Delete */
+                               free_name_entry_list(&to_delete->names);
+                               free(to_delete);
+-                              name_table_changed = OLSR_TRUE;
++                              *this_table_changed = OLSR_TRUE;
+                       } else {
+                               tmp = &(*tmp)->next;
+                       }
+               }
+       }
+-      write_resolv_file();
+-      write_hosts_file();
+ }
++
++
+ /**
+  * Scheduled event: generate and send NAME packet
+  */
+@@ -429,21 +574,19 @@
+               return;
+       }
+-      /* Check if this message has been processed before
+-      * Remeber that this also registeres the message as
++      /* Check if this message has not been processed before
++      * Remember that this also registers the message as
+       * processed if nessecary
+       */
+-      if(!olsr_check_dup_table_proc(&originator, ntohs(m->v4.seqno))) {
+-              /* If so - do not process */
+-              goto forward;
+-      }
+-
+-      update_name_entry(&originator, namemessage, size, vtime);
++      if(olsr_check_dup_table_proc(&originator, ntohs(m->v4.seqno))) {
++              /* If not already processed - do so */
++        update_name_entry(&originator, namemessage, size, vtime);
++      } 
++    
++    /* Forward the message if nessecary
++    * default_fwd does all the work for us! */
++    olsr_forward_message(m, &originator, ntohs(m->v4.seqno), in_if, in_addr);
+-forward:
+-      /* Forward the message if nessecary
+-      * default_fwd does all the work for us! */
+-      olsr_forward_message(m, &originator, ntohs(m->v4.seqno), in_if, in_addr);
+ }
+@@ -457,152 +600,224 @@
+ int
+ encap_namemsg(struct namemsg* msg)
+ {
+-      struct name_entry *my_name = my_names;
+-      struct name* to_packet;
++      struct name_entry *my_name;
++      struct name_entry *my_service;
++
++    // add the hostname, service and forwarder entries after the namemsg header
+       char* pos = (char*)msg + sizeof(struct namemsg);
+       short i=0;
+-        int k;
+-      
+-      // upstream dns server
+-      if (have_dns_server) {
+-              olsr_printf(3, "NAME PLUGIN: Announcing DNS server (%s)\n", 
+-                      olsr_ip_to_string(&my_dns_server));
+-              to_packet = (struct name*)pos;
+-              to_packet->type = htons(NAME_FORWARDER);
+-              to_packet->len = htons(0);
+-              memcpy(&to_packet->ip, &my_dns_server, ipsize);
+-              pos += sizeof(struct name);
+-              i++;
+-      }
++
+       // names
+       for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
+       {
+-              olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
+-                      my_name->name, olsr_ip_to_string(&my_name->ip), my_name->len);
+-                      
+-              to_packet = (struct name*)pos;
+-              to_packet->type = htons(my_name->type);
+-              to_packet->len = htons(my_name->len);
+-              memcpy(&to_packet->ip, &my_name->ip, ipsize);
+-              pos += sizeof(struct name);
+-              strncpy(pos, my_name->name, my_name->len);
+-              pos += my_name->len;
+-              // padding to 4 byte boundaries
+-                for (k = my_name->len; (k & 3) != 0; k++)
+-                      *pos++ = '\0';
++        pos = create_packet( (struct name*) pos, my_name);
+               i++;
+       }
++      // forwarders
++      for (my_name = my_forwarders; my_name!=NULL; my_name = my_name->next)
++      {
++        pos = create_packet( (struct name*) pos, my_name);
++              i++;
++      }
++      // services
++      for (my_service = my_services; my_service!=NULL; my_service = my_service->next)
++      {
++        pos = create_packet( (struct name*) pos, my_service);
++              i++;
++      }
++    
++    // write the namemsg header with the number of announced entries and the protocol version
+       msg->nr_names = htons(i);
+       msg->version = htons(NAME_PROTOCOL_VERSION);
++
+       return pos - (char*)msg; //length
+ }
+ /**
+- * decapsulate a name message and update name_entries if necessary
++ * convert each of my to be announced name_entries into network
++ * compatible format
++ *
++ * return the length of the name packet
++ */
++char*  
++create_packet(struct name* to, struct name_entry *from)
++{
++    char *pos = (char*) to;
++    int k;
++    olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
++        from->name, olsr_ip_to_string(&from->ip), from->len);
++    to->type = htons(from->type);
++    to->len = htons(from->len);
++    memcpy(&to->ip, &from->ip, ipsize);
++    pos += sizeof(struct name);
++    strncpy(pos, from->name, from->len);
++    pos += from->len;
++    for (k = from->len; (k & 3) != 0; k++)
++        *pos++ = '\0';
++    return pos;
++}
++
++/**
++ * decapsulate a received name, service or forwarder and update the corresponding hash table if necessary
++ */
++void
++decap_namemsg(struct name *from_packet, struct name_entry **to, olsr_bool *this_table_changed )
++{
++      struct name_entry *tmp;
++      struct name_entry *already_saved_name_entries;
++    char *name = (char*)from_packet + sizeof(struct name);
++      olsr_printf(4, "\nNAME PLUGIN: decapsulating received name, service or forwarder \n");
++    int type_of_from_packet = ntohs(from_packet->type);
++    unsigned int len_of_name = ntohs(from_packet->len);
++    
++    // don't insert the received entry again, if it has already been inserted in the hash table. 
++    // Instead only the validity time is set in insert_new_name_in_list function, which calls this one
++    for (already_saved_name_entries = (*to); already_saved_name_entries != NULL ; already_saved_name_entries = already_saved_name_entries->next)
++    {
++        if ( (type_of_from_packet==NAME_HOST || type_of_from_packet==NAME_SERVICE) && strncmp(already_saved_name_entries->name, name, len_of_name) == 0 ) {
++            olsr_printf(4, "\nNAME PLUGIN: received name or service entry %s (%s) already in hash table\n", name, olsr_ip_to_string(&already_saved_name_entries->ip));
++            return;
++        } else  if (type_of_from_packet==NAME_FORWARDER && COMP_IP(&already_saved_name_entries->ip, &from_packet->ip) ) {
++            olsr_printf(4, "\nNAME PLUGIN: received forwarder entry %s (%s) already in hash table\n", name, olsr_ip_to_string(&already_saved_name_entries->ip));
++            return;
++        }
++    }
++
++    //XXX: should I check the from_packet->ip here? If so, why not also check the ip fro HOST and SERVICE?
++    if( (type_of_from_packet==NAME_HOST && !is_name_wellformed(name))  ||  (type_of_from_packet==NAME_SERVICE && !is_service_wellformed(name)) ) {
++        olsr_printf(4, "\nNAME PLUGIN: invalid name [%s] received, skipping.\n", name );
++        return;
++    }
++
++    //ignore all packets with a too long name
++    //or a spoofed len of its included name string
++    if (len_of_name > MAX_NAME || strlen(name) != len_of_name) {
++        olsr_printf(4, "\nNAME PLUGIN: from_packet->len %d > MAX_NAME %d or from_packet->len %d !0 strlen(name [%s] in packet)\n", 
++                len_of_name, MAX_NAME, len_of_name, name );
++        return;
++    }
++
++    //if not yet known entry 
++    tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");           
++    tmp->type = ntohs(from_packet->type);
++    tmp->len = len_of_name > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
++    tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
++    memcpy(&tmp->ip, &from_packet->ip, ipsize);
++    strncpy(tmp->name, name, tmp->len);
++    tmp->name[tmp->len] = '\0';
++
++    olsr_printf(3, "\nNAME PLUGIN: create new name/service/forwarder entry %s (%s) [len=%d] [type=%d] in linked list\n", 
++        tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
++
++    *this_table_changed = OLSR_TRUE;
++
++    // queue to front
++    tmp->next = *to;
++    *to = tmp;
++}
++
++
++/**
++ * unpack the received message and delegate to the decapsilation function for each
++ * name/service/forwarder entry in the message
+  */
+ void
+-decap_namemsg( struct namemsg *msg, int size, struct name_entry **to )
++update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
+ {
+       char *pos, *end_pos;
+-      struct name_entry *tmp;
+       struct name *from_packet; 
+       int i;
++
++      olsr_printf(3, "NAME PLUGIN: Received Message from %s\n", 
++              olsr_ip_to_string(originator));
+       
+-      olsr_printf(4, "NAME PLUGIN: decapsulating name msg (size %d)\n", size);
+-      
+-      if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
++    if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
+               olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
+               return;
+       }
+-      
+-      // for now ist easier to just delete everything, than
+-      // to update selectively
+-      free_name_entry_list(to);
+-      name_table_changed = OLSR_TRUE;
+-      
++
++
+       /* now add the names from the message */
+       pos = (char*)msg + sizeof(struct namemsg);
+-      end_pos = pos + size - sizeof(struct name*); // at least one struct name has to be left
+-      
++      end_pos = pos + msg_size - sizeof(struct name*); // at least one struct name has to be left
++
+       for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
+       {
+               from_packet = (struct name*)pos;
+-              
+-              tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");         
+-              tmp->type = ntohs(from_packet->type);
+-              tmp->len = ntohs(from_packet->len) > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
+-              tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
+-              memcpy(&tmp->ip, &from_packet->ip, ipsize);
++        
++        switch (ntohs(from_packet->type)) {
++            case NAME_HOST: 
++                insert_new_name_in_list(originator, list, from_packet, &name_table_changed, vtime); 
++                break;
++            case NAME_FORWARDER:
++                insert_new_name_in_list(originator, forwarder_list, from_packet, &forwarder_table_changed, vtime); 
++                break;
++            case NAME_SERVICE:
++                insert_new_name_in_list(originator, service_list, from_packet, &service_table_changed, vtime); 
++                break;
++            default:
++                olsr_printf(3, "NAME PLUGIN: Received Message of unknown type [%d] from (%s)\n", from_packet->type, olsr_ip_to_string(originator));
++                break;
++        }
+               pos += sizeof(struct name);
+-              strncpy(tmp->name, pos, tmp->len);
+-              tmp->name[tmp->len] = '\0';
+-
+-              olsr_printf(3, "NAME PLUGIN: New name %s (%s) %d %d\n", 
+-                      tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
+-
+-              // queue to front
+-              tmp->next = *to;
+-              *to = tmp;
+-
+-              // name + padding
+-              pos += 1 + ((tmp->len - 1) | 3);
+-      }
++              pos += 1 + (( ntohs(from_packet->len) - 1) | 3);
++    }
+       if (i!=0)
+-              olsr_printf(4, "NAME PLUGIN: Lost %d names due to length inconsistency\n", i);
++              olsr_printf(4, "NAME PLUGIN: Lost %d entries in received packet due to length inconsistency (%s)\n", i, olsr_ip_to_string(originator));
+ }
+ /**
+- * Update or register a new name entry
++ * insert all the new names,services and forwarders from a received packet into the
++ * corresponding entry for this ip in the corresponding hash table
+  */
+ void
+-update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
++insert_new_name_in_list(union olsr_ip_addr *originator, struct db_entry **this_list, struct name *from_packet, olsr_bool *this_table_changed, double vtime)
+ {
+       int hash;
+       struct db_entry *entry;
+-
+-      olsr_printf(3, "NAME PLUGIN: Received Name Message from %s\n", 
+-              olsr_ip_to_string(originator));
++    olsr_bool entry_found = OLSR_FALSE;
++    entry_found = OLSR_FALSE;
+       hash = olsr_hashing(originator);
+-      /* find the entry for originator */
+-      for (entry = list[hash]; entry != NULL; entry = entry->next)
+-      {
+-              if (memcmp(originator, &entry->originator, ipsize) == 0) {
+-                      // found
+-                      olsr_printf(4, "NAME PLUGIN: %s found\n", 
+-                              olsr_ip_to_string(originator));
+-              
+-                      decap_namemsg(msg, msg_size, &entry->names);
+-                      
+-                      olsr_get_timestamp(vtime * 1000, &entry->timer);
+-                      
+-                      return;
+-              }
+-      }
+-
+-      olsr_printf(3, "NAME PLUGIN: New entry %s\n", 
+-              olsr_ip_to_string(originator));
+-              
+-      /* insert a new entry */
+-      entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
+-      
+-      memcpy(&entry->originator, originator, ipsize);
+-      olsr_get_timestamp(vtime * 1000, &entry->timer);
+-      entry->names = NULL;
+-      // queue to front
+-      entry->next = list[hash];
+-      list[hash] = entry;
+-      
+-      decap_namemsg(msg, msg_size, &entry->names);
+-
+-      name_table_changed = OLSR_TRUE;
++            /* find the entry for originator, if there is already one */
++            for (entry = this_list[hash]; entry != NULL; entry = entry->next)
++            {
++                if (memcmp(originator, &entry->originator, ipsize) == 0) {
++                    // found
++                    olsr_printf(4, "NAME PLUGIN: found entry for (%s) in its hash table\n", olsr_ip_to_string(originator));
++                
++                    //delegate to function for parsing the packet and linking it to entry->names
++                    decap_namemsg(from_packet, &entry->names, this_table_changed);
++                    
++                    olsr_get_timestamp(vtime * 1000, &entry->timer);
++                   
++                    entry_found = OLSR_TRUE;
++                }
++            }
++            if (! entry_found)
++            {
++                olsr_printf(3, "NAME PLUGIN: create new db entry for ip (%s) in hash table\n", olsr_ip_to_string(originator));
++                    
++                /* insert a new entry */
++                entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
++                
++                memcpy(&entry->originator, originator, ipsize);
++                olsr_get_timestamp(vtime * 1000, &entry->timer);
++                entry->names = NULL;
++
++                // queue to front
++                entry->next = this_list[hash];
++                this_list[hash] = entry;
++                
++                //delegate to function for parsing the packet and linking it to entry->names
++                decap_namemsg(from_packet, &entry->names, this_table_changed);
++            }
+ }
+-
+ /**
+  * write names to a file in /etc/hosts compatible format
+  */
+@@ -650,8 +865,7 @@
+       
+       // write own names
+       for (name = my_names; name != NULL; name = name->next) {
+-              fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip),
+-                      name->name, my_suffix );
++        fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip), name->name, my_suffix );
+       }
+       
+       // write received names
+@@ -661,13 +875,11 @@
+               {
+                       for (name = entry->names; name != NULL; name = name->next) 
+                       {
+-                              if (name->type == NAME_HOST) {
+-                                      olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
+-                                      olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
+-                                      
+-                                      fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
+-                                      fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
+-                              }
++                olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
++                olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
++                
++                fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
++                fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
+                       }
+               }
+       }
+@@ -682,7 +894,70 @@
+ /**
+- * write upstream DNS servers to resolv.conf file
++ * write services to a file in the format:
++ * service  #originator ip
++ *
++ * since service has a special format
++ * each line will look similar to e.g.
++ * http://me.olsr:80|tcp|my little homepage
++ */
++void
++write_services_file()
++{
++      int hash;
++      struct name_entry *name;
++      struct db_entry *entry;
++      FILE* services_file;
++      time_t currtime;
++  
++  
++      if (!service_table_changed)
++              return;
++
++      olsr_printf(2, "NAME PLUGIN: writing services file\n");
++                    
++      services_file = fopen( my_services_file, "w" );
++      if (services_file == NULL) {
++              olsr_printf(2, "NAME PLUGIN: cant write services_file file\n");
++              return;
++      }
++      
++      fprintf(services_file, "### this file is overwritten regularly by olsrd\n");
++      fprintf(services_file, "### do not edit\n\n");
++
++      
++      // write own services
++      for (name = my_services; name != NULL; name = name->next) {
++        fprintf(services_file, "%s\t# my own service\n", name->name);
++      }
++      
++      // write received services
++      for (hash = 0; hash < HASHSIZE; hash++) 
++      {
++              for(entry = service_list[hash]; entry != NULL; entry = entry->next)
++              {
++                      for (name = entry->names; name != NULL; name = name->next) 
++                      {
++                olsr_printf(6, "%s\t",  name->name);
++                olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
++                
++                fprintf(services_file, "%s\t", name->name );
++                fprintf(services_file, "\t#%s\n", olsr_ip_to_string(&entry->originator));
++                      }
++              }
++      }
++
++      if (time(&currtime)) {
++              fprintf(services_file, "\n### written by olsrd at %s", ctime(&currtime));
++      }
++        
++      fclose(services_file);
++      service_table_changed = OLSR_FALSE;
++}
++
++/**
++ * write the 3 best upstream DNS servers to resolv.conf file
++ * best means the 3 with the best etx value in routing table
+  */
+ void
+ write_resolv_file()
+@@ -694,23 +969,17 @@
+       struct rt_entry *route, *tmp, *last;
+       FILE* resolv;
+       int i=0;
++      time_t currtime;
+       
+-      if (my_resolv_file[0] == '\0')
+-              return;
+-      
+-      if (!name_table_changed)
++      if (!forwarder_table_changed || my_forwarders != NULL || my_resolv_file[0] == '\0')
+               return;
+-      olsr_printf(2, "NAME PLUGIN: writing resolv file\n");
+-
+       for (hash = 0; hash < HASHSIZE; hash++) 
+       {
+-              for(entry = list[hash]; entry != NULL; entry = entry->next)
++              for(entry = forwarder_list[hash]; entry != NULL; entry = entry->next)
+               {
+                       for (name = entry->names; name != NULL; name = name->next) 
+                       {
+-                              if (name->type != NAME_FORWARDER)
+-                                      continue;
+                               
+                               /* find the nearest one */
+                               route = olsr_lookup_routing_table(&name->ip);
+@@ -762,18 +1031,25 @@
+               return;
+                
+       /* write to file */
++    olsr_printf(2, "NAME PLUGIN: try to write to resolv file\n");
+       resolv = fopen( my_resolv_file, "w" );
+       if (resolv == NULL) {
+               olsr_printf(2, "NAME PLUGIN: can't write resolv file\n");
+               return;
+       }
++      fprintf(resolv, "### this file is overwritten regularly by olsrd\n");
++      fprintf(resolv, "### do not edit\n\n");
+       i=0;
+       for (tmp=best_routes; tmp!=NULL && i<3; tmp=tmp->next) {
+               olsr_printf(6, "NAME PLUGIN: nameserver %s\n", olsr_ip_to_string(&tmp->rt_dst));
+               fprintf(resolv, "nameserver %s\n", olsr_ip_to_string(&tmp->rt_dst));
+               i++;
+       }
++      if (time(&currtime)) {
++              fprintf(resolv, "\n### written by olsrd at %s", ctime(&currtime));
++      }
+       fclose(resolv);
++      forwarder_table_changed = OLSR_FALSE;
+ }
+@@ -789,6 +1065,7 @@
+               to_delete = *tmp;
+               *tmp = (*tmp)->next;
+               free( to_delete->name );
++              to_delete->name = NULL;
+               free( to_delete );
+               to_delete = NULL;
+       }
+@@ -831,3 +1108,84 @@
+       }
+       return OLSR_FALSE;
+ }
++
++/** check if name has the right syntax, i.e. it must adhere to a special regex 
++ * stored in regex_t_name
++ * necessary to avaid names like "0.0.0.0 google.de\n etc"
++ */
++olsr_bool
++is_name_wellformed(char *name) {
++    return regexec(&regex_t_name, name, 1, &regmatch_t_name, 0) == 0 ;
++}
++
++
++/**
++ * check if the service is in the right syntax and also that the hostname 
++ * or ip whithin the service is allowed
++ */
++olsr_bool
++allowed_service(char *service_line)
++{
++    /* the call of is_service_wellformed generates the submatches stored in regmatch_t_service
++     * these are then used by allowed_hostname_or_ip_in_service
++     * see regexec(3) for more infos */
++    if (!is_service_wellformed(service_line)) {
++        return OLSR_FALSE;
++    } else if (!allowed_hostname_or_ip_in_service(service_line, &(regmatch_t_service[1]))) {
++        return OLSR_FALSE;
++    } 
++
++   return OLSR_TRUE;
++}
++
++olsr_bool
++allowed_hostname_or_ip_in_service(char *service_line, regmatch_t *hostname_or_ip_match) 
++{
++    char *hostname_or_ip;
++    struct in_addr ip;
++    union olsr_ip_addr olsr_ip;
++    struct name_entry *name;
++    if (hostname_or_ip_match->rm_so < 0 || hostname_or_ip_match->rm_eo < 0) {
++          return OLSR_FALSE;
++    } 
++
++    hostname_or_ip = strndup(&service_line[hostname_or_ip_match->rm_so], hostname_or_ip_match->rm_eo - hostname_or_ip_match->rm_so);
++    //hostname is one of the names, that I announce (i.e. one that i am allowed to announce)
++    for (name = my_names; name != NULL; name = name->next) {
++        if (strncmp(name->name, hostname_or_ip, name->len - strlen(my_suffix)) == 0 ) {
++            olsr_printf(4, "NAME PLUGIN: hostname %s in service %s is OK\n", hostname_or_ip, service_line);
++            free(hostname_or_ip);
++            hostname_or_ip = NULL;
++            return OLSR_TRUE;
++        }
++    }
++    
++    //ip in service-line is allowed 
++    if (inet_aton(hostname_or_ip, &ip)) {
++        olsr_ip.v4 = ip.s_addr;
++        if (allowed_ip(&olsr_ip)) {
++            olsr_printf(2, "NAME PLUGIN: ip %s in service %s is OK\n", olsr_ip_to_string(&olsr_ip), service_line);
++            free(hostname_or_ip);
++            hostname_or_ip = NULL;
++            return OLSR_TRUE;
++        }
++    }
++
++    olsr_printf(1, "NAME PLUGIN: ip or hostname %s in service %s is NOT allowed (does not belong to you)\n", hostname_or_ip, service_line);
++    free(hostname_or_ip);
++    hostname_or_ip = NULL;
++
++    return OLSR_FALSE;
++}
++
++/**
++ * check if the service matches the syntax 
++ * of "protocol://host:port/path|tcp_or_udp|a short description", 
++ * which is given in the regex regex_t_service
++ */
++olsr_bool
++is_service_wellformed(char *service_line)
++{
++    return regexec(&regex_t_service, service_line, pmatch_service, regmatch_t_service, 0) == 0;
++}
++
+diff -Nur olsrd-0.4.10.orig/lib/nameservice/src/nameservice.h olsrd-0.4.10/lib/nameservice/src/nameservice.h
+--- olsrd-0.4.10.orig/lib/nameservice/src/nameservice.h        2005-06-02 17:34:00.000000000 +0200
++++ olsrd-0.4.10/lib/nameservice/src/nameservice.h     2006-12-01 08:26:58.000000000 +0100
+@@ -39,6 +39,7 @@
+ #define _NAMESERVICE_PLUGIN
+ #include <sys/time.h>
++#include <regex.h>
+ #include "olsr_types.h"
+ #include "interfaces.h"
+@@ -51,19 +52,27 @@
+ #define PLUGIN_VERSION        "0.2"
+ #define PLUGIN_AUTHOR "Bruno Randolf"
++// useful to set for the freifunkfirmware to remove all
++// calls to olsr_printf by the empty statement ";"
++//#define olsr_printf(...) ;
+ #define MESSAGE_TYPE          130
+ #define PARSER_TYPE           MESSAGE_TYPE
+ #define EMISSION_INTERVAL     120 /* two minutes */
+-#define NAME_VALID_TIME               3600 /* one hour */
++#define NAME_VALID_TIME               1800 /* half one hour */
+ #define NAME_PROTOCOL_VERSION 1
+-#define MAX_NAME 255
++#define MAX_NAME 127
+ #define MAX_FILE 255
+-#define MAX_SUFFIX 255
+-
++#define MAX_SUFFIX 63
++/**
++ * a linked list of name_entry
++ * if type is NAME_HOST, name is a hostname and ip its IP addr
++ * if type is NAME_FORWARDER, then ip is a dns-server (and name is irrelevant)
++ * if type is NAME_SERVICE, then name is a service-line (and the ip is irrelevant)
++ */
+ struct name_entry
+ {
+       union olsr_ip_addr      ip;
+@@ -73,7 +82,17 @@
+       struct name_entry       *next;          /* linked list */
+ };
+-/* database entry */
++/* *
++ * linked list of db_entries for each originator with
++ * originator being its main_addr
++ * 
++ * names points to the name_entry with its hostname, dns-server or
++ * service-line entry
++ *
++ * all the db_entries are hashed in nameservice.c to avoid a too long list
++ * for many nodes in a net
++ *
++ * */
+ struct db_entry
+ {
+       union olsr_ip_addr      originator;     /* IP address of the node this entry describes */
+@@ -98,8 +117,26 @@
+ int
+ encap_namemsg(struct namemsg *);
++struct name_entry*
++add_name_to_list(struct name_entry *my_list, char *value, int type, struct in_addr *ip);
++
++struct name_entry*
++remove_nonvalid_names_from_list(struct name_entry *my_list, int type);
++
++void 
++free_all_list_entries(struct db_entry **this_db_list) ;
++
+ void
+-decap_namemsg(struct namemsg *, int, struct name_entry**);
++timeout_old_names(struct db_entry **this_list, olsr_bool *this_table_changed);
++
++void
++decap_namemsg(struct name *from_packet, struct name_entry **to, olsr_bool *this_table_changed );
++
++void
++insert_new_name_in_list(union olsr_ip_addr *originator, struct db_entry **this_list, struct name *from_packet, olsr_bool *this_table_changed, double vtime);
++
++olsr_bool
++allowed_hostname_or_ip_in_service(char *service_line, regmatch_t *hostname_or_ip);
+ void
+ update_name_entry(union olsr_ip_addr *, struct namemsg *, int, double);
+@@ -108,6 +145,9 @@
+ write_hosts_file(void);
+ void
++write_services_file(void);
++
++void
+ write_resolv_file(void);
+ int
+@@ -119,6 +159,18 @@
+ olsr_bool
+ allowed_ip(union olsr_ip_addr *addr);
++olsr_bool
++allowed_service(char *service_line);
++
++olsr_bool
++is_name_wellformed(char *service_line);
++
++olsr_bool
++is_service_wellformed(char *service_line);
++
++char*  
++create_packet(struct name *to, struct name_entry *from);
++
+ void
+ name_constructor(void);
+diff -Nur olsrd-0.4.10.orig/lib/nameservice/src/nameservice_msg.h olsrd-0.4.10/lib/nameservice/src/nameservice_msg.h
+--- olsrd-0.4.10.orig/lib/nameservice/src/nameservice_msg.h    2005-03-17 22:41:30.000000000 +0100
++++ olsrd-0.4.10/lib/nameservice/src/nameservice_msg.h 2006-12-01 08:26:58.000000000 +0100
+@@ -38,29 +38,34 @@
+ #ifndef _NAMESEVICE_MSG
+ #define _NAMESEVICE_MSG
+-
++/* type of the packet of name_entry */
+ typedef enum {
+       NAME_HOST = 0,
+       NAME_FORWARDER = 1,
+-      NAME_SERVICE = 2
++      NAME_SERVICE = 2,
+ } NAME_TYPE;
+-
++/**
++ * the name, forwarder or service entry as found in a packet within a
++ * message
++ **/
+ struct name
+ {
+       olsr_u16_t              type;
+       olsr_u16_t              len;    // length of the name
++    // the ip of the hostname, or the ip of the dns-server
++    // ip is irrelevant for services
+       union olsr_ip_addr      ip;
+       /*
+-       * name is written in plain text after this struct and padded to 4 byte
++       * name or service is written in plain text after this struct and padded to 4 byte
+        */
+ };
+ struct namemsg
+ {
+-      olsr_u16_t version;
+-      olsr_u16_t nr_names;   // number of following name messages
++      olsr_u16_t version;    // version number of the nameservice plugin
++      olsr_u16_t nr_names;   // number of following packets including names, forwarders or services
+       /*
+        * at least one struct name following
+        */
diff --git a/net/olsrd/patches/130-olsrd_fixes.patch b/net/olsrd/patches/130-olsrd_fixes.patch
deleted file mode 100644 (file)
index e806bed..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-diff -Nur olsrd-0.4.10.orig/src/defs.h olsrd-0.4.10/src/defs.h
---- olsrd-0.4.10.orig/src/defs.h       2006-01-01 16:59:02.000000000 +0100
-+++ olsrd-0.4.10/src/defs.h    2006-10-31 19:34:52.000000000 +0100
-@@ -68,10 +68,10 @@
- #define OLSRD_GLOBAL_CONF_FILE "/etc/" OLSRD_CONF_FILE_NAME
- #endif
--#define       HOPCNT_MAX              32      /* maximum hops number */
-+#define       HOPCNT_MAX              64      /* maximum hops number */
- #define       MAXMESSAGESIZE          1500    /* max broadcast size */
- #define UDP_IPV4_HDRSIZE        28
--#define UDP_IPV6_HDRSIZE        48
-+#define UDP_IPV6_HDRSIZE        62
- #define MAX_IFS                 16
- /* Debug helper macro */
-diff -Nur olsrd-0.4.10.orig/src/interfaces.h olsrd-0.4.10/src/interfaces.h
---- olsrd-0.4.10.orig/src/interfaces.h 2005-06-03 10:00:55.000000000 +0200
-+++ olsrd-0.4.10/src/interfaces.h      2006-10-31 19:44:52.000000000 +0100
-@@ -136,6 +136,8 @@
-   struct        vtimes valtimes;
-   struct        if_gen_property *gen_properties;/* Generic interface properties */
-+  
-+  int           ttl_index; /* index in TTL array for fish-eye */
-   struct      interface *int_next;
- };
-diff -Nur olsrd-0.4.10.orig/src/link_set.c olsrd-0.4.10/src/link_set.c
---- olsrd-0.4.10.orig/src/link_set.c   2005-11-17 05:25:44.000000000 +0100
-+++ olsrd-0.4.10/src/link_set.c        2006-10-31 19:31:19.000000000 +0100
-@@ -952,8 +952,9 @@
-   entry->loss_link_quality =
-     (float)(entry->total_packets - entry->lost_packets) /
--    (float)(entry->loss_window_size);
--
-+    (float)(entry->loss_window_size < (2 * 4) ? entry->loss_window_size: 
-+    4 * ((entry->loss_window_size / 4 - 1) * entry->total_packets + entry->loss_window_size) / entry->loss_window_size);
-+    
-   // multiply the calculated link quality with the user-specified multiplier
-   entry->loss_link_quality *= entry->loss_link_multiplier;
-diff -Nur olsrd-0.4.10.orig/src/lq_packet.c olsrd-0.4.10/src/lq_packet.c
---- olsrd-0.4.10.orig/src/lq_packet.c  2005-11-17 02:58:51.000000000 +0100
-+++ olsrd-0.4.10/src/lq_packet.c       2006-10-31 21:51:11.000000000 +0100
-@@ -149,9 +149,8 @@
-   int i;
-   struct neighbor_entry *walker;
-   struct link_entry *link;
--  static int ttl_list[] = { MAX_TTL, 3, 2, 1, 2, 1, 1, 3, 2, 1, 2, 1, 1, 0 };
--  static int ttl_index = 0;
--
-+  static int ttl_list[] = { 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, MAX_TTL-1, 0};
-+  
-   // remember that we have generated an LQ TC message; this is
-   // checked in net_output()
-@@ -167,10 +166,13 @@
-   if (olsr_cnf->lq_fish > 0)
-   {
--    if (ttl_list[ttl_index] == 0)
--      ttl_index = 0;
-+    // SVEN_OLA: Too lazy to find the different iface inits. This will do it too.
-+    if (outif->ttl_index >= sizeof(ttl_list) / sizeof(ttl_list[0])) outif->ttl_index = 0;
-+    
-+    if (ttl_list[outif->ttl_index] == 0)
-+      outif->ttl_index = 0;
--    lq_tc->comm.ttl = ttl_list[ttl_index++];
-+    lq_tc->comm.ttl = ttl_list[outif->ttl_index++];
-     OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
-   }
-diff -Nur olsrd-0.4.10.orig/src/olsr.c olsrd-0.4.10/src/olsr.c
---- olsrd-0.4.10.orig/src/olsr.c       2005-11-17 05:25:44.000000000 +0100
-+++ olsrd-0.4.10/src/olsr.c    2006-10-31 19:31:19.000000000 +0100
-@@ -68,6 +68,7 @@
- olsr_bool changes_topology;
- olsr_bool changes_neighborhood;
- olsr_bool changes_hna;
-+olsr_bool changes_force;
- /**
-  * Process changes functions
-@@ -142,6 +143,11 @@
-     OLSR_PRINTF(3, "CHANGES IN HNA\n")
- #endif
-   
-+  if(!changes_force &&
-+     2 <= olsr_cnf->lq_level &&
-+     0 >= olsr_cnf->lq_dlimit)
-+    return;
-+    
-   if(!changes_neighborhood &&
-      !changes_topology &&
-      !changes_hna)
-@@ -171,11 +177,6 @@
-           olsr_calculate_routing_table();
-           olsr_calculate_hna_routes();
-         }
--
--      else
--        {
--          olsr_calculate_lq_routing_table();
--        }
-     }
-   
-   else if (changes_topology)
-@@ -187,11 +188,6 @@
-           olsr_calculate_routing_table();
-           olsr_calculate_hna_routes();
-         }
--
--      else
--        {
--          olsr_calculate_lq_routing_table();
--        }
-     }
-   else if (changes_hna)
-@@ -202,11 +198,11 @@
-         {
-           olsr_calculate_hna_routes();
-         }
--
--      else
--        {
--          olsr_calculate_lq_routing_table();
--        }
-+    }
-+  
-+  if (olsr_cnf->lq_level >= 2)
-+    {
-+      olsr_calculate_lq_routing_table();
-     }
-   
-   if (olsr_cnf->debug_level > 0)
-@@ -239,6 +235,7 @@
-   changes_neighborhood = OLSR_FALSE;
-   changes_topology = OLSR_FALSE;
-   changes_hna = OLSR_FALSE;
-+  changes_force = OLSR_FALSE;
-   return;
-diff -Nur olsrd-0.4.10.orig/src/olsr.h olsrd-0.4.10/src/olsr.h
---- olsrd-0.4.10.orig/src/olsr.h       2005-05-29 14:47:45.000000000 +0200
-+++ olsrd-0.4.10/src/olsr.h    2006-10-31 19:31:19.000000000 +0100
-@@ -49,6 +49,7 @@
- extern olsr_bool changes_topology;
- extern olsr_bool changes_neighborhood;
- extern olsr_bool changes_hna;
-+extern olsr_bool changes_force;
- void
- register_pcf(int (*)(int, int, int));
-diff -Nur olsrd-0.4.10.orig/src/scheduler.c olsrd-0.4.10/src/scheduler.c
---- olsrd-0.4.10.orig/src/scheduler.c  2005-12-29 23:34:37.000000000 +0100
-+++ olsrd-0.4.10/src/scheduler.c       2006-10-31 19:31:19.000000000 +0100
-@@ -70,6 +70,7 @@
-   changes_neighborhood = OLSR_TRUE;
-   changes_topology = OLSR_TRUE;
-+  changes_force = OLSR_TRUE;
- }
- /**
-diff -Nur olsrd-0.4.10.orig/src/unix/ifnet.c olsrd-0.4.10/src/unix/ifnet.c
---- olsrd-0.4.10.orig/src/unix/ifnet.c 2005-12-29 19:37:16.000000000 +0100
-+++ olsrd-0.4.10/src/unix/ifnet.c      2006-10-31 21:44:59.000000000 +0100
-@@ -689,6 +689,17 @@
-   return 1;
- }
-+static char basename[32];
-+char* if_basename(char* name);
-+char* if_basename(char* name)
-+{
-+      char *p = strchr(name, ':');
-+      if (0 == p || p - name >= (int)(sizeof(basename) / sizeof(basename[0]) - 1)) return name;
-+      memcpy(basename, name, p - name);
-+      basename[p - name] = 0;
-+      return basename;
-+}
-+
- /**
-  * Initializes a interface described by iface,
-  * if it is set up and is of the correct type.
-@@ -832,10 +843,10 @@
-       }
-       
-       /* Deactivate IP spoof filter */
--      deactivate_spoof(ifr.ifr_name, iface->index, olsr_cnf->ip_version);
-+      deactivate_spoof(if_basename(ifr.ifr_name), iface->index, olsr_cnf->ip_version);
-       
-       /* Disable ICMP redirects */
--      disable_redirects(ifr.ifr_name, iface->index, olsr_cnf->ip_version);
-+      disable_redirects(if_basename(ifr.ifr_name), iface->index, olsr_cnf->ip_version);
-       
-     }
-   
-@@ -894,7 +907,7 @@
-   ifp->gen_properties = NULL;
-   ifp->int_name = olsr_malloc(strlen(ifr.ifr_name) + 1, "Interface update 3");
-       
--  strcpy(ifp->int_name, ifr.ifr_name);
-+  strcpy(ifp->int_name, if_basename(ifr.ifr_name));
-   /* Segfaults if using strncpy(IFNAMSIZ) why oh why?? */
-   ifp->int_next = ifnet;
-   ifnet = ifp;
diff --git a/net/olsrd/patches/140-olsrd-txtinfo.patch b/net/olsrd/patches/140-olsrd-txtinfo.patch
new file mode 100644 (file)
index 0000000..a7344ce
--- /dev/null
@@ -0,0 +1,853 @@
+diff -Nur olsrd-0.4.10.orig/lib/txtinfo/Makefile olsrd-0.4.10/lib/txtinfo/Makefile
+--- olsrd-0.4.10.orig/lib/txtinfo/Makefile     1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/txtinfo/Makefile  2006-12-01 08:26:58.000000000 +0100
+@@ -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: olsrd-txtinfo.patch,v 1.5 2006/12/04 08:33:46 sven-ola 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 -Nur olsrd-0.4.10.orig/lib/txtinfo/README_TXTINFO olsrd-0.4.10/lib/txtinfo/README_TXTINFO
+--- olsrd-0.4.10.orig/lib/txtinfo/README_TXTINFO       1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/txtinfo/README_TXTINFO    2006-12-01 08:26:58.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/txtinfo/src/olsrd_plugin.c olsrd-0.4.10/lib/txtinfo/src/olsrd_plugin.c
+--- olsrd-0.4.10.orig/lib/txtinfo/src/olsrd_plugin.c   1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/txtinfo/src/olsrd_plugin.c        2006-12-01 08:26:58.000000000 +0100
+@@ -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-txtinfo.patch,v 1.5 2006/12/04 08:33:46 sven-ola 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 -Nur olsrd-0.4.10.orig/lib/txtinfo/src/olsrd_txtinfo.c olsrd-0.4.10/lib/txtinfo/src/olsrd_txtinfo.c
+--- olsrd-0.4.10.orig/lib/txtinfo/src/olsrd_txtinfo.c  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/txtinfo/src/olsrd_txtinfo.c       2006-12-01 08:26:58.000000000 +0100
+@@ -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.patch,v 1.5 2006/12/04 08:33:46 sven-ola 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((union olsr_ip_addr *)&hna4->net),
++                        olsr_ip_to_string((union olsr_ip_addr *)&hna4->netmask),
++                              olsr_ip_to_string((union olsr_ip_addr *)&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((union olsr_ip_addr *)&hna6->net),
++                              hna6->prefix_len,
++                      olsr_ip_to_string((union olsr_ip_addr *)&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 -Nur olsrd-0.4.10.orig/lib/txtinfo/src/olsrd_txtinfo.h olsrd-0.4.10/lib/txtinfo/src/olsrd_txtinfo.h
+--- olsrd-0.4.10.orig/lib/txtinfo/src/olsrd_txtinfo.h  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/txtinfo/src/olsrd_txtinfo.h       2006-12-01 08:26:58.000000000 +0100
+@@ -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.patch,v 1.5 2006/12/04 08:33:46 sven-ola 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 -Nur olsrd-0.4.10.orig/lib/txtinfo/version-script.txt olsrd-0.4.10/lib/txtinfo/version-script.txt
+--- olsrd-0.4.10.orig/lib/txtinfo/version-script.txt   1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/txtinfo/version-script.txt        2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,10 @@
++VERS_1.0
++{
++  global:
++    olsrd_plugin_interface_version;
++    olsrd_plugin_register_param;
++    olsrd_plugin_init;
++
++  local:
++    *;
++};
diff --git a/net/olsrd/patches/140-olsrd_optimize.patch b/net/olsrd/patches/140-olsrd_optimize.patch
deleted file mode 100644 (file)
index ddea522..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-diff -Nur olsrd-0.4.10.orig/src/duplicate_set.c olsrd-0.4.10/src/duplicate_set.c
---- olsrd-0.4.10.orig/src/duplicate_set.c      2005-02-27 19:39:43.000000000 +0100
-+++ olsrd-0.4.10/src/duplicate_set.c   2006-11-12 09:33:49.000000000 +0100
-@@ -93,7 +93,7 @@
-   /* Hash the senders address */
--  hash = olsr_hashing(originator);
-+  hash = HASHMASK & seqno;
-   new_dup_entry = olsr_malloc(sizeof(struct dup_entry), "New dup entry");
-@@ -131,7 +131,7 @@
-   struct dup_entry *tmp_dup_table;
-   /* Hash the senders address */
--  hash = olsr_hashing(originator);
-+  hash = HASHMASK & seqno;
-   /* Check for entry */
-   for(tmp_dup_table = dup_set[hash].next;
-@@ -163,7 +163,7 @@
-   struct dup_entry *tmp_dup_table;
-   /* Hash the senders address */
--  hash = olsr_hashing(originator);
-+  hash = HASHMASK & seqno;
-   /* Check for entry */
-   for(tmp_dup_table = dup_set[hash].next;
-@@ -268,7 +268,7 @@
-   struct dup_iface *new_iface;
-   /* Hash the senders address */
--  hash = olsr_hashing(originator);
-+  hash = HASHMASK & seqno;
-   /* Check for entry */
-@@ -313,7 +313,7 @@
-   struct dup_entry *tmp_dup_table;
-   /* Hash the senders address */
--  hash = olsr_hashing(originator);
-+  hash = HASHMASK & seqno;
-   /* Check for entry */
-   for(tmp_dup_table = dup_set[hash].next;
-diff -Nur olsrd-0.4.10.orig/src/hashing.c olsrd-0.4.10/src/hashing.c
---- olsrd-0.4.10.orig/src/hashing.c    2005-02-20 19:52:18.000000000 +0100
-+++ olsrd-0.4.10/src/hashing.c 2006-11-12 09:33:49.000000000 +0100
-@@ -58,7 +58,7 @@
-   if(olsr_cnf->ip_version == AF_INET)
-     /* IPv4 */  
--    hash = (ntohl(address->v4));
-+    hash = address->v4x[0] ^ address->v4x[1] ^ address->v4x[2] ^ address->v4x[3];
-   else
-     {
-       /* IPv6 */
-diff -Nur olsrd-0.4.10.orig/src/hashing.h olsrd-0.4.10/src/hashing.h
---- olsrd-0.4.10.orig/src/hashing.h    2005-02-20 19:52:18.000000000 +0100
-+++ olsrd-0.4.10/src/hashing.h 2006-11-12 09:33:49.000000000 +0100
-@@ -43,7 +43,7 @@
- #ifndef _OLSR_HASHING
- #define _OLSR_HASHING
--#define       HASHSIZE        32
-+#define       HASHSIZE        128
- #define       HASHMASK        (HASHSIZE - 1)
- #include "olsr_types.h"
-diff -Nur olsrd-0.4.10.orig/src/lq_avl.c olsrd-0.4.10/src/lq_avl.c
---- olsrd-0.4.10.orig/src/lq_avl.c     2005-01-22 15:30:57.000000000 +0100
-+++ olsrd-0.4.10/src/lq_avl.c  2006-11-12 09:33:49.000000000 +0100
-@@ -40,6 +40,9 @@
-  */
- #include <stddef.h>
-+#ifndef DISABLE_SVEN_OLA
-+#include <time.h>
-+#endif
- #include "lq_avl.h"
-@@ -52,11 +55,33 @@
-   tree->comp = comp;
- }
-+#ifndef DISABLE_SVEN_OLA
-+static struct avl_node *avl_find_rec_ipv4(struct avl_node *node, void *key)
-+{
-+  if (*(unsigned int *)key < *(unsigned int *)node->key) {
-+    if (node->left != NULL) {
-+      return avl_find_rec_ipv4(node->left, key);
-+    }
-+  }
-+  else if (*(unsigned int *)key > *(unsigned int *)node->key) {
-+    if (node->right != NULL) {
-+      return avl_find_rec_ipv4(node->right, key);
-+    }
-+  }
-+  return node;
-+}
-+#endif
-+
- static struct avl_node *avl_find_rec(struct avl_node *node, void *key,
-                                      int (*comp)(void *, void *))
- {
-   int diff;
-+#ifndef DISABLE_SVEN_OLA
-+  if (0 == comp) {
-+    return avl_find_rec_ipv4(node, key);
-+  }
-+#endif
-   diff = (*comp)(key, node->key);
-   if (diff < 0)
-@@ -87,6 +112,13 @@
-   node = avl_find_rec(tree->root, key, tree->comp);
-+#ifndef DISABLE_SVEN_OLA
-+  if (0 == tree->comp) {
-+    if (0 != svenola_avl_comp_ipv4(node->key, key))
-+      return NULL;
-+  }
-+  else
-+#endif
-   if ((*tree->comp)(node->key, key) != 0)
-     return NULL;
-@@ -228,6 +260,12 @@
-   node = avl_find_rec(tree->root, new->key, tree->comp);
-+#ifndef DISABLE_SVEN_OLA
-+  if (0 == tree->comp) {
-+    diff = svenola_avl_comp_ipv4(new->key, node->key);
-+  }
-+  else
-+#endif
-   diff = (*tree->comp)(new->key, node->key);
-   if (diff == 0)
-diff -Nur olsrd-0.4.10.orig/src/lq_avl.h olsrd-0.4.10/src/lq_avl.h
---- olsrd-0.4.10.orig/src/lq_avl.h     2005-02-20 19:52:18.000000000 +0100
-+++ olsrd-0.4.10/src/lq_avl.h  2006-11-12 09:33:49.000000000 +0100
-@@ -62,4 +62,9 @@
- struct avl_node *avl_find(struct avl_tree *, void *);
- int avl_insert(struct avl_tree *, struct avl_node *);
-+#ifndef DISABLE_SVEN_OLA
-+#define svenola_avl_comp_ipv4(ip1, ip2) \
-+  (*(unsigned int *)ip1 == *(unsigned int *)ip2 ? 0 : \
-+  *(unsigned int *)ip1 < *(unsigned int *)ip2 ? -1 : +1)
-+#endif
- #endif
-diff -Nur olsrd-0.4.10.orig/src/lq_list.c olsrd-0.4.10/src/lq_list.c
---- olsrd-0.4.10.orig/src/lq_list.c    2004-12-04 18:06:57.000000000 +0100
-+++ olsrd-0.4.10/src/lq_list.c 2006-11-12 09:33:49.000000000 +0100
-@@ -48,6 +48,7 @@
-   list->tail = NULL;
- }
-+#ifdef DISABLE_SVEN_OLA
- struct list_node *list_get_head(struct list *list)
- {
-   return list->head;
-@@ -67,6 +68,7 @@
- {
-   return node->prev;
- }
-+#endif
- void list_add_head(struct list *list, struct list_node *node)
- {
-diff -Nur olsrd-0.4.10.orig/src/lq_list.h olsrd-0.4.10/src/lq_list.h
---- olsrd-0.4.10.orig/src/lq_list.h    2005-02-20 19:52:18.000000000 +0100
-+++ olsrd-0.4.10/src/lq_list.h 2006-11-12 09:33:49.000000000 +0100
-@@ -58,11 +58,18 @@
- void list_init(struct list *list);
-+#ifndef DISABLE_SVEN_OLA
-+#define list_get_head(node) (node)->head
-+#define list_get_tail(node) (node)->tail
-+#define list_get_next(node) (node)->next
-+#define list_get_prev(node) (node)->prev
-+#else
- struct list_node *list_get_head(struct list *list);
- struct list_node *list_get_tail(struct list *list);
- struct list_node *list_get_next(struct list_node *node);
- struct list_node *list_get_prev(struct list_node *node);
-+#endif
- void list_add_head(struct list *list, struct list_node *node);
- void list_add_tail(struct list *list, struct list_node *node);
-diff -Nur olsrd-0.4.10.orig/src/lq_route.c olsrd-0.4.10/src/lq_route.c
---- olsrd-0.4.10.orig/src/lq_route.c   2005-11-29 19:37:58.000000000 +0100
-+++ olsrd-0.4.10/src/lq_route.c        2006-11-12 09:34:46.000000000 +0100
-@@ -205,6 +205,16 @@
-   // add the vertex to the list, if it's not us
-+#ifndef DISABLE_SVEN_OLA
-+  if (0 == comp) {
-+    if (svenola_avl_comp_ipv4(&main_addr, node->key) != 0)
-+    {
-+      vert->node.data = vert;
-+      list_add_tail(vertex_list, &vert->node);
-+    }
-+  }
-+  else
-+#endif
-   if ((*comp)(&main_addr, node->key) != 0)
-   {
-     vert->node.data = vert;
-@@ -266,6 +276,154 @@
- }
- // XXX - bad complexity
-+#define SVEN_OPT
-+#undef SVEN_OPT_DBG
-+
-+/*
-+ * The function extract_best() is most expensive (>50% CPU in profiling).
-+ * It is called in two modes: while doing Dijkstra route calculation and
-+ * while searching for a direct route/hna. The latter can be optimized
-+ * because the stored verices do not change from call to call and it is
-+ * more sufficient to have them sorted/popped from a list rather than 
-+ * searching the complete list by every call. Sven-Ola@gmx.de, 11/2006
-+ */
-+ 
-+#ifdef SVEN_OPT
-+static struct dijk_vertex **etx_cache = 0;
-+static int etx_cache_count;
-+static int etx_cache_get;
-+static int etx_cache_saved = 0;
-+
-+static int etx_cache_compare(const void *a, const void *b)
-+{
-+  // Oh jeah. I love this macro assembler :)
-+  
-+  if ((*(struct dijk_vertex **)a)->path_etx > (*(struct dijk_vertex **)b)->path_etx) return 1;
-+  if ((*(struct dijk_vertex **)a)->path_etx < (*(struct dijk_vertex **)b)->path_etx) return -1;
-+  
-+  // This is for debugging only: etx==etx then compare pointers
-+  // to make it possible to compare to the original search algo.
-+  if (*(struct dijk_vertex **)a > *(struct dijk_vertex **)b) return 1;
-+  if (*(struct dijk_vertex **)a < *(struct dijk_vertex **)b) return -1;
-+  
-+  return 0;
-+}
-+
-+static struct dijk_vertex *extract_best_route(struct list *vertex_list)
-+{
-+#ifdef SVEN_OPT_DBG
-+  float best_etx = INFINITE_ETX + 1.0;
-+#endif
-+  struct list_node *node;
-+  struct dijk_vertex *vert;
-+  struct dijk_vertex *res = NULL;
-+
-+#ifdef SVEN_OPT_DBG
-+  node = list_get_head(vertex_list);
-+
-+  // loop through all vertices
-+  
-+  while (node != NULL)
-+  {
-+    vert = node->data;
-+
-+    // see whether the current vertex is better than what we have
-+
-+    if (!vert->done && vert->path_etx < best_etx)
-+    {
-+      best_etx = vert->path_etx;
-+      res = vert;
-+    }
-+    else if (!vert->done && vert->path_etx == best_etx && vert < res)
-+    {
-+      // Otherwise order is undefined if etx==etx and debug will complain
-+      best_etx = vert->path_etx;
-+      res = vert;
-+    }
-+
-+    node = list_get_next(node);
-+  }
-+#endif
-+  if (NULL == etx_cache)
-+  {
-+    int count = 0;
-+    node = list_get_head(vertex_list);
-+    while (node != NULL)
-+    {
-+      vert = node->data;
-+      if (!vert->done && vert->path_etx < INFINITE_ETX) count++;
-+      node = list_get_next(node);
-+    }
-+    if (0 < count)
-+    {
-+      etx_cache = olsr_malloc(sizeof(etx_cache[0]) * count, "ETX Cache");
-+#ifdef SVEN_OPT_DBG
-+      printf("count=%d, Malloc(%d)=%p\n", count, sizeof(etx_cache[0]) * count, etx_cache);
-+#endif
-+      node = list_get_head(vertex_list);
-+      etx_cache_count = 0;
-+      etx_cache_get = 0;
-+      while (node != NULL)
-+      {
-+        vert = node->data;
-+        if (!vert->done && vert->path_etx < INFINITE_ETX)
-+        {
-+          etx_cache[etx_cache_count] = vert;
-+          etx_cache_count++;
-+        }
-+        node = list_get_next(node);
-+      }
-+#ifdef SVEN_OPT_DBG
-+      printf("qsort(etx_cache_count=%d)\n", etx_cache_count);
-+#endif
-+      qsort(etx_cache, etx_cache_count, sizeof(etx_cache[0]), etx_cache_compare);
-+#ifdef SVEN_OPT_DBG
-+      if (0 < etx_cache_count)
-+      {
-+        int i = 0; 
-+        while(i < etx_cache_count && i < 10)
-+        {
-+          printf("%d: %p=%f\n", i, etx_cache[i], etx_cache[i]->path_etx);
-+          i++;
-+        }
-+      }
-+#endif
-+    }
-+  }
-+
-+#ifdef SVEN_OPT_DBG
-+  if (NULL != etx_cache)
-+  {
-+    struct dijk_vertex *rescache = NULL;
-+    if (etx_cache_get < etx_cache_count)
-+    {
-+      rescache = etx_cache[etx_cache_get++];
-+    }
-+    if (res != rescache)
-+    {
-+      printf("miss: etx_cache_get=%d, res=%p,%f != rescache=%p,%f\n",
-+        etx_cache_get, res, (NULL != res ? res->path_etx : -1), rescache, (NULL != rescache ? rescache->path_etx : -1));
-+    }
-+    else
-+    {
-+      etx_cache_saved++;
-+    }
-+  }
-+#else
-+  if (NULL != etx_cache && etx_cache_get < etx_cache_count)
-+  {
-+    res = etx_cache[etx_cache_get++];
-+  }
-+#endif
-+
-+  // if we've found a vertex, remove it from the set
-+
-+  if (res != NULL)
-+    res->done = OLSR_TRUE;
-+
-+  return res;
-+}
-+#endif // SVEN_OPT
- static struct dijk_vertex *extract_best(struct list *vertex_list)
- {
-@@ -371,7 +529,11 @@
-   struct interface *inter;
-   if (ipsize == 4)
-+#ifndef DISABLE_SVEN_OLA
-+    avl_comp = 0;
-+#else
-     avl_comp = avl_comp_ipv4;
-+#endif
-   else
-     avl_comp = avl_comp_ipv6;
-@@ -614,13 +776,27 @@
-   // add HNA routes - the set of unprocessed network nodes contains
-   // all reachable network nodes
-+#ifdef SVEN_OPT
-+#ifdef SVEN_OPT_DBG
-+  printf("free etx_cache, saved compares=%d, etx_cache=%p\n", etx_cache_saved, etx_cache);
-+  etx_cache_saved = 0;
-+#endif
-+  if (NULL != etx_cache) {
-+    free(etx_cache);
-+    etx_cache = NULL;
-+  }
-+#endif
-   for (;;)
-   {
-     // extract the network node with the best ETX and remove it
-     // from the set of unprocessed network nodes
-+#ifdef SVEN_OPT
-+    vert = extract_best_route(&vertex_list);
-+#else
-     vert = extract_best(&vertex_list);
-+#endif
-     // no more nodes left
-diff -Nur olsrd-0.4.10.orig/src/olsr_types.h olsrd-0.4.10/src/olsr_types.h
---- olsrd-0.4.10.orig/src/olsr_types.h 2005-05-15 14:57:24.000000000 +0200
-+++ olsrd-0.4.10/src/olsr_types.h      2006-11-12 09:33:49.000000000 +0100
-@@ -93,6 +93,7 @@
- union olsr_ip_addr
- {
-   olsr_u32_t v4;
-+  olsr_u8_t v4x[4];
-   struct in6_addr v6;
- };
diff --git a/net/olsrd/patches/150-hna_ip_fix.patch b/net/olsrd/patches/150-hna_ip_fix.patch
deleted file mode 100644 (file)
index 2f359a2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -ur olsrd.old/src/cfgparser/oparse.c olsrd.dev/src/cfgparser/oparse.c
---- olsrd.old/src/cfgparser/oparse.c   2006-01-01 17:15:57.000000000 +0100
-+++ olsrd.dev/src/cfgparser/oparse.c   2006-10-09 01:06:27.000000000 +0200
-@@ -1921,6 +1921,7 @@
-       return -1;
-     }
-   h->netmask.v4 = in.s_addr;
-+  h->net.v4 &= h->netmask.v4;
-   /* Queue */
-   h->next = cnf->hna4_entries;
-   cnf->hna4_entries = h;
diff --git a/net/olsrd/patches/150-olsrd-quagga.patch b/net/olsrd/patches/150-olsrd-quagga.patch
new file mode 100644 (file)
index 0000000..50d32dc
--- /dev/null
@@ -0,0 +1,3231 @@
+diff -Nur olsrd-0.4.10.orig/lib/quagga/ChangeLog olsrd-0.4.10/lib/quagga/ChangeLog
+--- olsrd-0.4.10.orig/lib/quagga/ChangeLog     1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/ChangeLog  2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/Makefile olsrd-0.4.10/lib/quagga/Makefile
+--- olsrd-0.4.10.orig/lib/quagga/Makefile      1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/Makefile   2006-12-02 10:56:37.000000000 +0100
+@@ -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 2005/05/26 16:09:25 br1 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 -Nur olsrd-0.4.10.orig/lib/quagga/quagga-0.98.6-olsr.diff olsrd-0.4.10/lib/quagga/quagga-0.98.6-olsr.diff
+--- olsrd-0.4.10.orig/lib/quagga/quagga-0.98.6-olsr.diff       1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/quagga-0.98.6-olsr.diff    2006-12-02 10:57:52.000000000 +0100
+@@ -0,0 +1,717 @@
++diff -Nur quagga-0.98.6.orig/bgpd/bgp_vty.c quagga-0.98.6/bgpd/bgp_vty.c
++--- quagga-0.98.6.orig/bgpd/bgp_vty.c 2006-03-30 18:12:25.000000000 +0200
+++++ quagga-0.98.6/bgpd/bgp_vty.c      2006-12-02 10:52:14.000000000 +0100
++@@ -7793,7 +7793,9 @@
++      return ZEBRA_ROUTE_STATIC;
++       else if (strncmp (str, "r", 1) == 0)
++      return ZEBRA_ROUTE_RIP;
++-      else if (strncmp (str, "o", 1) == 0)
+++      else if (strncmp (str, "ol", 2) == 0)
+++     return ZEBRA_ROUTE_OLSR;
+++      else if (strncmp (str, "os", 2) == 0)
++      return ZEBRA_ROUTE_OSPF;
++     }
++   if (afi == AFI_IP6)
++@@ -7806,20 +7808,23 @@
++      return ZEBRA_ROUTE_STATIC;
++       else if (strncmp (str, "r", 1) == 0)
++      return ZEBRA_ROUTE_RIPNG;
++-      else if (strncmp (str, "o", 1) == 0)
+++      else if (strncmp (str, "os", 2) == 0)
++      return ZEBRA_ROUTE_OSPF6;
+++      else if (strncmp (str, "ol", 2) == 0)
+++     return ZEBRA_ROUTE_OLSR;
++     }
++   return 0;
++ }
++ 
++ DEFUN (bgp_redistribute_ipv4,
++        bgp_redistribute_ipv4_cmd,
++-       "redistribute (connected|kernel|ospf|rip|static)",
+++       "redistribute (connected|kernel|ospf|rip|static|olsr)",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Static routes\n")
++ {
++   int type;
++@@ -7835,13 +7840,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv4_rmap,
++        bgp_redistribute_ipv4_rmap_cmd,
++-       "redistribute (connected|kernel|ospf|rip|static) route-map WORD",
+++       "redistribute (connected|kernel|ospf|rip|static|olsr) route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n")
++ {
++@@ -7860,13 +7866,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv4_metric,
++        bgp_redistribute_ipv4_metric_cmd,
++-       "redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295>",
+++       "redistribute (connected|kernel|ospf|rip|static|olsr) metric <0-4294967295>",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n")
++ {
++@@ -7887,13 +7894,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv4_rmap_metric,
++        bgp_redistribute_ipv4_rmap_metric_cmd,
++-       "redistribute (connected|kernel|ospf|rip|static) route-map WORD metric <0-4294967295>",
+++       "redistribute (connected|kernel|ospf|rip|static|olsr) route-map WORD metric <0-4294967295>",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n"
++        "Metric for redistributed routes\n"
++@@ -7917,13 +7925,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv4_metric_rmap,
++        bgp_redistribute_ipv4_metric_rmap_cmd,
++-       "redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295> route-map WORD",
+++       "redistribute (connected|kernel|ospf|rip|static|olsr) metric <0-4294967295> route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n"
++        "Route map reference\n"
++@@ -7947,14 +7956,16 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv4,
++        no_bgp_redistribute_ipv4_cmd,
++-       "no redistribute (connected|kernel|ospf|rip|static)",
+++       "no redistribute (connected|kernel|ospf|rip|static|olsr)",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++-       "Static routes\n")
+++       "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
+++       )
++ {
++   int type;
++ 
++@@ -7970,7 +7981,7 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv4_rmap,
++        no_bgp_redistribute_ipv4_rmap_cmd,
++-       "no redistribute (connected|kernel|ospf|rip|static) route-map WORD",
+++       "no redistribute (connected|kernel|ospf|rip|static|olsr) route-map WORD",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -7978,6 +7989,7 @@
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n")
++ {
++@@ -7996,7 +8008,7 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv4_metric,
++        no_bgp_redistribute_ipv4_metric_cmd,
++-       "no redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295>",
+++       "no redistribute (connected|kernel|ospf|rip|static|olsr) metric <0-4294967295>",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8004,6 +8016,7 @@
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n")
++ {
++@@ -8022,7 +8035,7 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
++        no_bgp_redistribute_ipv4_rmap_metric_cmd,
++-       "no redistribute (connected|kernel|ospf|rip|static) route-map WORD metric <0-4294967295>",
+++       "no redistribute (connected|kernel|ospf|rip|static|olsr) route-map WORD metric <0-4294967295>",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8030,6 +8043,7 @@
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n"
++        "Metric for redistributed routes\n"
++@@ -8051,7 +8065,7 @@
++ 
++ ALIAS (no_bgp_redistribute_ipv4_rmap_metric,
++        no_bgp_redistribute_ipv4_metric_rmap_cmd,
++-       "no redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295> route-map WORD",
+++       "no redistribute (connected|kernel|ospf|rip|static|olsr) metric <0-4294967295> route-map WORD",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8059,6 +8073,7 @@
++        "Open Shurtest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n"
++        "Route map reference\n"
++@@ -8067,13 +8082,15 @@
++ #ifdef HAVE_IPV6
++ DEFUN (bgp_redistribute_ipv6,
++        bgp_redistribute_ipv6_cmd,
++-       "redistribute (connected|kernel|ospf6|ripng|static)",
+++       "redistribute (connected|kernel|ospf6|ripng|static|olsr)",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++-       "Static routes\n")
+++       "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
+++       )
++ {
++   int type;
++ 
++@@ -8089,13 +8106,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv6_rmap,
++        bgp_redistribute_ipv6_rmap_cmd,
++-       "redistribute (connected|kernel|ospf6|ripng|static) route-map WORD",
+++       "redistribute (connected|kernel|ospf6|ripng|static|olsr) route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n")
++ {
++@@ -8114,13 +8132,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv6_metric,
++        bgp_redistribute_ipv6_metric_cmd,
++-       "redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295>",
+++       "redistribute (connected|kernel|ospf6|ripng|static|olsr) metric <0-4294967295>",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n")
++ {
++@@ -8141,13 +8160,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv6_rmap_metric,
++        bgp_redistribute_ipv6_rmap_metric_cmd,
++-       "redistribute (connected|kernel|ospf6|ripng|static) route-map WORD metric <0-4294967295>",
+++       "redistribute (connected|kernel|ospf6|ripng|static|ols) route-map WORD metric <0-4294967295>",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n"
++        "Metric for redistributed routes\n"
++@@ -8171,13 +8191,14 @@
++ 
++ DEFUN (bgp_redistribute_ipv6_metric_rmap,
++        bgp_redistribute_ipv6_metric_rmap_cmd,
++-       "redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295> route-map WORD",
+++       "redistribute (connected|kernel|ospf6|ripng|static|olsr) metric <0-4294967295> route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n"
++        "Route map reference\n"
++@@ -8201,14 +8222,16 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv6,
++        no_bgp_redistribute_ipv6_cmd,
++-       "no redistribute (connected|kernel|ospf6|ripng|static)",
+++       "no redistribute (connected|kernel|ospf6|ripng|static|olsr)",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++        "Kernel routes\n"
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++-       "Static routes\n")
+++       "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
+++      )
++ {
++   int type;
++ 
++@@ -8224,7 +8247,7 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv6_rmap,
++        no_bgp_redistribute_ipv6_rmap_cmd,
++-       "no redistribute (connected|kernel|ospf6|ripng|static) route-map WORD",
+++       "no redistribute (connected|kernel|ospf6|ripng|static|olsr) route-map WORD",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8232,6 +8255,7 @@
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n")
++ {
++@@ -8250,7 +8274,7 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv6_metric,
++        no_bgp_redistribute_ipv6_metric_cmd,
++-       "no redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295>",
+++       "no redistribute (connected|kernel|ospf6|ripng|static|olsr) metric <0-4294967295>",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8258,6 +8282,7 @@
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n")
++ {
++@@ -8276,7 +8301,7 @@
++ 
++ DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
++        no_bgp_redistribute_ipv6_rmap_metric_cmd,
++-       "no redistribute (connected|kernel|ospf6|ripng|static) route-map WORD metric <0-4294967295>",
+++       "no redistribute (connected|kernel|ospf6|ripng|static|olsr) route-map WORD metric <0-4294967295>",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8284,6 +8309,7 @@
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n"
++        "Metric for redistributed routes\n"
++@@ -8305,7 +8331,7 @@
++ 
++ ALIAS (no_bgp_redistribute_ipv6_rmap_metric,
++        no_bgp_redistribute_ipv6_metric_rmap_cmd,
++-       "no redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295> route-map WORD",
+++       "no redistribute (connected|kernel|ospf6|ripng|static|olsr) metric <0-4294967295> route-map WORD",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Connected\n"
++@@ -8313,6 +8339,7 @@
++        "Open Shurtest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
++        "Static routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "Default metric\n"
++        "Route map reference\n"
++@@ -8325,7 +8352,7 @@
++ {
++   int i;
++   const char *str[] = { "system", "kernel", "connected", "static", "rip",
++-               "ripng", "ospf", "ospf6", "isis", "bgp"};
+++               "ripng", "ospf", "ospf6", "isis", "bgp", "hsls", "olsr"};
++ 
++   /* Unicast redistribution only.  */
++   if (safi != SAFI_UNICAST)
++diff -Nur quagga-0.98.6.orig/lib/zebra.h quagga-0.98.6/lib/zebra.h
++--- quagga-0.98.6.orig/lib/zebra.h    2005-06-15 13:54:18.000000000 +0200
+++++ quagga-0.98.6/lib/zebra.h 2006-12-02 10:48:51.000000000 +0100
++@@ -378,7 +378,8 @@
++ #define ZEBRA_ROUTE_ISIS                 8
++ #define ZEBRA_ROUTE_BGP                  9
++ #define ZEBRA_ROUTE_HSLS              10
++-#define ZEBRA_ROUTE_MAX                  11
+++#define ZEBRA_ROUTE_OLSR              11
+++#define ZEBRA_ROUTE_MAX                  12
++ 
++ /* Zebra's family types. */
++ #define ZEBRA_FAMILY_IPV4                1
++diff -Nur quagga-0.98.6.orig/ospfd/ospf_vty.c quagga-0.98.6/ospfd/ospf_vty.c
++--- quagga-0.98.6.orig/ospfd/ospf_vty.c       2006-03-30 17:41:20.000000000 +0200
+++++ quagga-0.98.6/ospfd/ospf_vty.c    2006-12-02 10:48:51.000000000 +0100
++@@ -108,9 +108,11 @@
++     *source = ZEBRA_ROUTE_RIP;
++   else if (strncmp (str, "b", 1) == 0)
++     *source = ZEBRA_ROUTE_BGP;
+++  else if (strncmp (str, "ol", 2) == 0)
+++    *source = ZEBRA_ROUTE_OLSR;
++   else
++     return 0;
++-
+++  
++   return 1;
++ }
++ 
++@@ -5302,13 +5304,14 @@
++ \f
++ DEFUN (ospf_redistribute_source_metric_type,
++        ospf_redistribute_source_metric_type_routemap_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> metric-type (1|2) route-map WORD",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric <0-16777214> metric-type (1|2) route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "OSPF default metric\n"
++        "OSPF exterior metric type for redistributed routes\n"
++@@ -5346,13 +5349,14 @@
++ 
++ ALIAS (ospf_redistribute_source_metric_type,
++        ospf_redistribute_source_metric_type_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> metric-type (1|2)",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric <0-16777214> metric-type (1|2)",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "OSPF default metric\n"
++        "OSPF exterior metric type for redistributed routes\n"
++@@ -5368,18 +5372,20 @@
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "OSPF default metric\n")
++ 
++ DEFUN (ospf_redistribute_source_type_metric,
++        ospf_redistribute_source_type_metric_routemap_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric <0-16777214> route-map WORD",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric-type (1|2) metric <0-16777214> route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "OSPF exterior metric type for redistributed routes\n"
++        "Set OSPF External Type 1 metrics\n"
++        "Set OSPF External Type 2 metrics\n"
++@@ -5417,13 +5423,14 @@
++ 
++ ALIAS (ospf_redistribute_source_type_metric,
++        ospf_redistribute_source_type_metric_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric <0-16777214>",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric-type (1|2) metric <0-16777214>",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "OSPF exterior metric type for redistributed routes\n"
++        "Set OSPF External Type 1 metrics\n"
++        "Set OSPF External Type 2 metrics\n"
++@@ -5432,7 +5439,7 @@
++ 
++ ALIAS (ospf_redistribute_source_type_metric,
++        ospf_redistribute_source_type_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2)",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric-type (1|2)",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++@@ -5440,28 +5447,31 @@
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
++        "OSPF exterior metric type for redistributed routes\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Set OSPF External Type 1 metrics\n"
++        "Set OSPF External Type 2 metrics\n")
++ 
++ ALIAS (ospf_redistribute_source_type_metric,
++        ospf_redistribute_source_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp)",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr)",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++-       "Border Gateway Protocol (BGP)\n")
+++       "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n")
++ 
++ DEFUN (ospf_redistribute_source_metric_routemap,
++        ospf_redistribute_source_metric_routemap_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> route-map WORD",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric <0-16777214> route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Metric for redistributed routes\n"
++        "OSPF default metric\n"
++        "Route map reference\n"
++@@ -5490,13 +5500,14 @@
++ 
++ DEFUN (ospf_redistribute_source_type_routemap,
++        ospf_redistribute_source_type_routemap_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) route-map WORD",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) metric-type (1|2) route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "OSPF exterior metric type for redistributed routes\n"
++        "Set OSPF External Type 1 metrics\n"
++        "Set OSPF External Type 2 metrics\n"
++@@ -5526,13 +5537,14 @@
++ 
++ DEFUN (ospf_redistribute_source_routemap,
++        ospf_redistribute_source_routemap_cmd,
++-       "redistribute (kernel|connected|static|rip|bgp) route-map WORD",
+++       "redistribute (kernel|connected|static|rip|bgp|olsr) route-map WORD",
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++        "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Route map reference\n"
++        "Pointer to route-map entries\n")
++ {
++@@ -5553,14 +5565,16 @@
++ 
++ DEFUN (no_ospf_redistribute_source,
++        no_ospf_redistribute_source_cmd,
++-       "no redistribute (kernel|connected|static|rip|bgp)",
+++       "no redistribute (kernel|connected|static|rip|bgp|olsr)",
++        NO_STR
++        "Redistribute information from another routing protocol\n"
++        "Kernel routes\n"
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++-       "Border Gateway Protocol (BGP)\n")
+++       "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (olsr)\n"
+++       )
++ {
++   struct ospf *ospf = vty->index;
++   int source;
++@@ -5574,7 +5588,7 @@
++ 
++ DEFUN (ospf_distribute_list_out,
++        ospf_distribute_list_out_cmd,
++-       "distribute-list WORD out (kernel|connected|static|rip|bgp)",
+++       "distribute-list WORD out (kernel|connected|static|rip|bgp|olsr)",
++        "Filter networks in routing updates\n"
++        "Access-list name\n"
++        OUT_STR
++@@ -5582,7 +5596,8 @@
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++-       "Border Gateway Protocol (BGP)\n")
+++       "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n")
++ {
++   struct ospf *ospf = vty->index;
++   int source;
++@@ -5596,7 +5611,7 @@
++ 
++ DEFUN (no_ospf_distribute_list_out,
++        no_ospf_distribute_list_out_cmd,
++-       "no distribute-list WORD out (kernel|connected|static|rip|bgp)",
+++       "no distribute-list WORD out (kernel|connected|static|rip|bgp|olsr)",
++        NO_STR
++        "Filter networks in routing updates\n"
++        "Access-list name\n"
++@@ -5605,7 +5620,8 @@
++        "Connected\n"
++        "Static routes\n"
++        "Routing Information Protocol (RIP)\n"
++-       "Border Gateway Protocol (BGP)\n")
+++       "Border Gateway Protocol (BGP)\n"
+++       "Optimized Link State Routing (OLSR)\n")
++ {
++   struct ospf *ospf = vty->index;
++   int source;
++@@ -7121,7 +7137,8 @@
++ 
++ \f
++ const char *distribute_str[] = { "system", "kernel", "connected", "static",
++-                             "rip", "ripng", "ospf", "ospf6", "isis", "bgp"};
+++                             "rip", "ripng", "ospf", "ospf6", "isis", "bgp",
+++                             "hsls","olsr"};
++ int
++ config_write_ospf_redistribute (struct vty *vty, struct ospf *ospf)
++ {
++diff -Nur quagga-0.98.6.orig/zebra/zebra_vty.c quagga-0.98.6/zebra/zebra_vty.c
++--- quagga-0.98.6.orig/zebra/zebra_vty.c      2004-12-18 17:03:29.000000000 +0100
+++++ quagga-0.98.6/zebra/zebra_vty.c   2006-12-02 10:49:45.000000000 +0100
++@@ -53,6 +53,8 @@
++       return "isis";
++     case ZEBRA_ROUTE_BGP:
++       return "bgp";
+++    case ZEBRA_ROUTE_OLSR:
+++      return "olsr";
++     default:
++       return "unknown";
++     }
++@@ -84,6 +86,10 @@
++       return 'I';
++     case ZEBRA_ROUTE_BGP:
++       return 'B';
+++    case ZEBRA_ROUTE_HSLS:
+++      return 'H';
+++    case ZEBRA_ROUTE_OLSR:
+++      return 'L';
++     default:
++       return '?';
++     }
++@@ -755,8 +761,8 @@
++ }
++ 
++ #define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, " \
++-  "S - static, R - RIP, O - OSPF,%s       I - ISIS, B - BGP, " \
++-  "> - selected route, * - FIB route%s%s"
+++  "S - static, R - RIP, O - OSPF,%s       I - ISIS, B - BGP, H - HSLS, " \
+++  "L - OLSR, > - selected route, * - FIB route%s%s"
++ 
++ DEFUN (show_ip_route,
++        show_ip_route_cmd,
++@@ -874,7 +880,7 @@
++ 
++ DEFUN (show_ip_route_protocol,
++        show_ip_route_protocol_cmd,
++-       "show ip route (bgp|connected|isis|kernel|ospf|rip|static)",
+++       "show ip route (bgp|connected|isis|kernel|ospf|rip|olsr|static)",
++        SHOW_STR
++        IP_STR
++        "IP routing table\n"
++@@ -884,6 +890,7 @@
++        "Kernel\n"
++        "Open Shortest Path First (OSPF)\n"
++        "Routing Information Protocol (RIP)\n"
+++       "Optimized Link State Routing (OLSR)\n"
++        "Static routes\n")
++ {
++   int type;
++@@ -898,7 +905,7 @@
++     type = ZEBRA_ROUTE_CONNECT;
++   else if (strncmp (argv[0], "k", 1) ==0)
++     type = ZEBRA_ROUTE_KERNEL;
++-  else if (strncmp (argv[0], "o", 1) == 0)
+++  else if (strncmp (argv[0], "os", 2) == 0)
++     type = ZEBRA_ROUTE_OSPF;
++   else if (strncmp (argv[0], "i", 1) == 0)
++     type = ZEBRA_ROUTE_ISIS;
++@@ -906,6 +913,8 @@
++     type = ZEBRA_ROUTE_RIP;
++   else if (strncmp (argv[0], "s", 1) == 0)
++     type = ZEBRA_ROUTE_STATIC;
+++  else if (strncmp (argv[0], "ol", 2) == 0)
+++    type = ZEBRA_ROUTE_OLSR;
++   else 
++     {
++       vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
++@@ -1732,7 +1741,7 @@
++ 
++ DEFUN (show_ipv6_route_protocol,
++        show_ipv6_route_protocol_cmd,
++-       "show ipv6 route (bgp|connected|isis|kernel|ospf6|ripng|static)",
+++       "show ipv6 route (bgp|connected|isis|kernel|ospf6|ripng|olsr|static)",
++        SHOW_STR
++        IP_STR
++        "IP routing table\n"
++@@ -1742,6 +1751,7 @@
++        "Kernel\n"
++        "Open Shortest Path First (OSPFv3)\n"
++        "Routing Information Protocol (RIPng)\n"
+++       "Optimized Link State Routing (olsr)\n"
++        "Static routes\n")
++ {
++   int type;
++@@ -1756,7 +1766,7 @@
++     type = ZEBRA_ROUTE_CONNECT;
++   else if (strncmp (argv[0], "k", 1) ==0)
++     type = ZEBRA_ROUTE_KERNEL;
++-  else if (strncmp (argv[0], "o", 1) == 0)
+++  else if (strncmp (argv[0], "os", 2) == 0)
++     type = ZEBRA_ROUTE_OSPF6;
++   else if (strncmp (argv[0], "i", 1) == 0)
++     type = ZEBRA_ROUTE_ISIS;
++@@ -1764,7 +1774,9 @@
++     type = ZEBRA_ROUTE_RIPNG;
++   else if (strncmp (argv[0], "s", 1) == 0)
++     type = ZEBRA_ROUTE_STATIC;
++-  else 
+++  else if (strncmp (argv[0], "ol", 2) == 0)
+++     type = ZEBRA_ROUTE_OLSR;
+++  else
++     {
++       vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
++       return CMD_WARNING;
+diff -Nur olsrd-0.4.10.orig/lib/quagga/README olsrd-0.4.10/lib/quagga/README
+--- olsrd-0.4.10.orig/lib/quagga/README        1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/README     2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/src/olsrd_plugin.c olsrd-0.4.10/lib/quagga/src/olsrd_plugin.c
+--- olsrd-0.4.10.orig/lib/quagga/src/olsrd_plugin.c    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/src/olsrd_plugin.c 2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/src/quagga/zassert.h olsrd-0.4.10/lib/quagga/src/quagga/zassert.h
+--- olsrd-0.4.10.orig/lib/quagga/src/quagga/zassert.h  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/src/quagga/zassert.h       2006-12-02 10:56:37.000000000 +0100
+@@ -0,0 +1,27 @@
++/*
++ * $Id: zassert.h,v 1.2 2004/12/03 18:01:04 ajs 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 -Nur olsrd-0.4.10.orig/lib/quagga/src/quagga/zebra.h olsrd-0.4.10/lib/quagga/src/quagga/zebra.h
+--- olsrd-0.4.10.orig/lib/quagga/src/quagga/zebra.h    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/src/quagga/zebra.h 2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/src/quagga.c olsrd-0.4.10/lib/quagga/src/quagga.c
+--- olsrd-0.4.10.orig/lib/quagga/src/quagga.c  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/src/quagga.c       2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/src/quagga.h olsrd-0.4.10/lib/quagga/src/quagga.h
+--- olsrd-0.4.10.orig/lib/quagga/src/quagga.h  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/src/quagga.h       2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/test/foo.c olsrd-0.4.10/lib/quagga/test/foo.c
+--- olsrd-0.4.10.orig/lib/quagga/test/foo.c    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/test/foo.c 2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/test/foo.pl olsrd-0.4.10/lib/quagga/test/foo.pl
+--- olsrd-0.4.10.orig/lib/quagga/test/foo.pl   1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/test/foo.pl        2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/test/quagga.try1.c olsrd-0.4.10/lib/quagga/test/quagga.try1.c
+--- olsrd-0.4.10.orig/lib/quagga/test/quagga.try1.c    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/test/quagga.try1.c 2006-12-02 10:56:37.000000000 +0100
+@@ -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 -Nur olsrd-0.4.10.orig/lib/quagga/version-script.txt olsrd-0.4.10/lib/quagga/version-script.txt
+--- olsrd-0.4.10.orig/lib/quagga/version-script.txt    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/quagga/version-script.txt 2006-12-02 10:56:37.000000000 +0100
+@@ -0,0 +1,10 @@
++VERS_1.0
++{
++  global:
++    olsrd_plugin_interface_version;
++    olsrd_plugin_register_param;
++    olsrd_plugin_init;
++
++  local:
++    *;
++};
diff --git a/net/olsrd/patches/160-olsrd-quagga-routehandler.patch b/net/olsrd/patches/160-olsrd-quagga-routehandler.patch
new file mode 100644 (file)
index 0000000..f8a1201
--- /dev/null
@@ -0,0 +1,259 @@
+diff -Nur olsrd-0.4.10.orig/src/main.c olsrd-0.4.10/src/main.c
+--- olsrd-0.4.10.orig/src/main.c       2005-09-29 07:53:34.000000000 +0200
++++ olsrd-0.4.10/src/main.c    2006-12-01 09:10:15.000000000 +0100
+@@ -280,6 +280,9 @@
+   /* Initialize parser */
+   olsr_init_parser();
++  /* Initialize route-exporter */
++  olsr_init_export_route();
++
+   /* Initialize message sequencnumber */
+   init_msg_seqno();
+diff -Nur olsrd-0.4.10.orig/src/process_routes.c olsrd-0.4.10/src/process_routes.c
+--- olsrd-0.4.10.orig/src/process_routes.c     2005-05-30 15:13:38.000000000 +0200
++++ olsrd-0.4.10/src/process_routes.c  2006-12-01 09:10:15.000000000 +0100
+@@ -3,6 +3,9 @@
+  * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+  * All rights reserved.
+  *
++ * export_route_entry interface added by Immo 'FaUl Wehrenberg 
++ * <immo@chaostreff-dortmund.de>
++ *
+  * Redistribution and use in source and binary forms, with or without 
+  * modification, are permitted provided that the following conditions 
+  * are met:
+@@ -39,7 +42,6 @@
+  * $Id: process_routes.c,v 1.27 2005/05/30 13:13:38 kattemat Exp $
+  */
+-
+ #include "defs.h"
+ #include "olsr.h"
+ #include "log.h"
+@@ -51,10 +53,162 @@
+ #define strerror(x) StrError(x)
+ #endif
++struct export_route_entry
++{
++  olsr_u8_t type;       /* AF_INET/AF_INET6 */
++  int (*function)(struct rt_entry*);
++  struct export_route_entry *next;
++};
++
++
++static struct export_route_entry *add_routes;
++static struct export_route_entry *del_routes;
++
+ struct rt_entry old_routes[HASHSIZE];
+ struct rt_entry old_hna[HASHSIZE];
++void 
++olsr_addroute_add_function(int (*function)(struct rt_entry*), olsr_u8_t type) 
++{
++  struct export_route_entry *tmp;
++  tmp = olsr_malloc(sizeof *tmp, "olsr_addroute_add_function");
++  tmp->type = type;
++  tmp->function = function;
++  tmp->next = add_routes;
++  add_routes = tmp;
++}
++
++void 
++olsr_delroute_add_function(int (*function) (struct rt_entry*), olsr_u8_t type)
++{
++  struct export_route_entry *tmp;
++  tmp = olsr_malloc(sizeof *tmp, "olsr_delroute_add_function");
++  tmp->type = type;
++  tmp->function = function;
++  tmp->next = del_routes;
++  del_routes = tmp;
++}
++
++
++int 
++olsr_addroute_remove_function(int (*function) (struct rt_entry*), olsr_u8_t type)
++{
++  struct export_route_entry *tmp, *prev = NULL /* Make compiler happy */; 
++  tmp = add_routes;
++  while (tmp) 
++    {
++      if (function == tmp->function && type == tmp->type) 
++      {
++        if (tmp == add_routes) 
++          {
++            add_routes = add_routes->next;
++            free (tmp);
++            return 1;
++          }
++        else 
++          {
++            prev->next = tmp->next;
++            free (tmp);
++            return 1;
++          }
++      }
++      prev = tmp;
++      tmp = tmp->next;
++    }
++  return 0;
++}
++
++int
++olsr_delroute_remove_function(int (*function) (struct rt_entry*), olsr_u8_t type)
++{
++  struct export_route_entry *tmp, *prev = NULL /* Make compiler happy */;
++  tmp = del_routes;
++  while (tmp) 
++    {
++      if (function == tmp->function && type == tmp->type) 
++      {
++        if (tmp == del_routes) 
++          {
++            del_routes = del_routes->next;
++            free (tmp);
++            return 1;
++          }
++        else 
++          {
++            prev->next = tmp->next;
++            free (tmp);
++            return 1; 
++          }
++      }
++      prev = tmp;
++      tmp = tmp->next;
++    }
++  return 0;
++}
++
++void 
++olsr_init_export_route() 
++{
++  olsr_addroute_add_function(&olsr_ioctl_add_route, AF_INET);
++  olsr_addroute_add_function(&olsr_ioctl_add_route6, AF_INET6);
++  olsr_delroute_add_function(&olsr_ioctl_del_route, AF_INET);
++  olsr_delroute_add_function(&olsr_ioctl_del_route6, AF_INET6);
++}
++
++int
++olsr_export_add_route (struct rt_entry *e) 
++{
++  int retval = 0;
++  struct export_route_entry *tmp;
++  for (tmp = add_routes; tmp; tmp = tmp->next)
++    {
++      if (tmp->type == AF_INET)
++      retval = tmp->function(e);
++    }
++  return retval;
++}
++
++int
++olsr_export_add_route6 (struct rt_entry *e) 
++{
++  int retval = 0;
++  struct export_route_entry *tmp;
++  for (tmp = add_routes; tmp; tmp = tmp->next)
++    {
++      if (tmp->type == AF_INET6)
++      retval = tmp->function(e);
++    }
++  return retval;
++}
++
++int
++olsr_export_del_route (struct rt_entry *e) 
++{
++  int retval = 0;
++  struct export_route_entry *tmp;
++  for (tmp = del_routes; tmp; tmp = tmp->next)
++    {
++      if (tmp->type == AF_INET)
++      retval = tmp->function(e);
++    }
++  return retval;
++}
++
++int
++olsr_export_del_route6 (struct rt_entry *e) 
++{
++  int retval = 0;
++  struct export_route_entry *tmp;
++  for (tmp = del_routes; tmp; tmp = tmp->next)
++    {
++      if (tmp->type == AF_INET6)
++      retval = tmp->function(e);
++    }
++  return retval;
++}
++
++
+ int
+ olsr_init_old_table()
+@@ -348,9 +502,9 @@
+                   if(!olsr_cnf->host_emul)
+                     {
+                       if(olsr_cnf->ip_version == AF_INET)
+-                        error = olsr_ioctl_del_route(destination_ptr->destination);
++                        error = olsr_export_del_route(destination_ptr->destination);
+                       else
+-                        error = olsr_ioctl_del_route6(destination_ptr->destination);
++                        error = olsr_export_del_route6(destination_ptr->destination);
+                       
+                       if(error < 0)
+                         {
+@@ -436,9 +590,9 @@
+               if(!olsr_cnf->host_emul)
+                 {
+                   if(olsr_cnf->ip_version == AF_INET)
+-                    error=olsr_ioctl_add_route(destination_kernel->destination);
++                    error=olsr_export_add_route(destination_kernel->destination);
+                   else
+-                    error=olsr_ioctl_add_route6(destination_kernel->destination);
++                    error=olsr_export_add_route6(destination_kernel->destination);
+                   
+                   if(error < 0)
+                     {
+diff -Nur olsrd-0.4.10.orig/src/process_routes.h olsrd-0.4.10/src/process_routes.h
+--- olsrd-0.4.10.orig/src/process_routes.h     2005-05-29 14:47:45.000000000 +0200
++++ olsrd-0.4.10/src/process_routes.h  2006-12-01 09:10:15.000000000 +0100
+@@ -50,6 +50,34 @@
+ extern struct rt_entry old_routes[HASHSIZE];
+ extern struct rt_entry old_hna[HASHSIZE];
++void
++olsr_init_export_route(void);
++
++void
++olsr_addroute_add_function(int (*)(struct rt_entry*), olsr_u8_t);
++
++int
++olsr_addroute_remove_function(int (*)(struct rt_entry*), olsr_u8_t);
++
++void
++olsr_delroute_add_function(int (*)(struct rt_entry*), olsr_u8_t);
++
++int
++olsr_delroute_remove_function(int (*)(struct rt_entry*), olsr_u8_t);
++
++int
++olsr_export_add_route (struct rt_entry*); 
++
++int
++olsr_export_del_route (struct rt_entry*); 
++
++int
++olsr_export_add_route6 (struct rt_entry*); 
++
++int
++olsr_export_del_route6 (struct rt_entry*); 
++
++
+ int
+ olsr_init_old_table(void);
diff --git a/net/olsrd/patches/170-olsrd-bmf.patch b/net/olsrd/patches/170-olsrd-bmf.patch
new file mode 100644 (file)
index 0000000..1bec867
--- /dev/null
@@ -0,0 +1,3573 @@
+diff -Nur olsrd-0.4.10.orig/lib/bmf/Makefile olsrd-0.4.10/lib/bmf/Makefile
+--- olsrd-0.4.10.orig/lib/bmf/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/Makefile      2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,64 @@
++#
++# OLSR Basic Multicast Forwarding (BMF) plugin.
++# Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++# Written by Erik Tromp.
++# 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 Thales, BMF 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.
++#
++# $Id: Makefile,v 1.10 2005/05/25 13:50:22 br1 Exp $
++
++OLSRD_PLUGIN =        true
++PLUGIN_NAME = olsrd_bmf
++PLUGIN_VER =  1.1
++
++TOPDIR = ../..
++include $(TOPDIR)/Makefile.inc
++
++LIBS +=       -lpthread
++
++ifneq ($(OS),linux)
++
++default_target install clean: 
++      @echo "*** BMF Plugin only supported on Linux, sorry!"
++
++else
++
++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)
++
++endif
+\ Kein Zeilenumbruch am Dateiende.
+diff -Nur olsrd-0.4.10.orig/lib/bmf/PluginBmf.prj olsrd-0.4.10/lib/bmf/PluginBmf.prj
+--- olsrd-0.4.10.orig/lib/bmf/PluginBmf.prj    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/PluginBmf.prj 2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,83 @@
++#DO NOT EDIT THIS FILE!!!
++[APPTYPE@DEBUG]
++APPTYPE = 0
++[APPTYPE@RELEASE]
++APPTYPE = 0
++[COMPILE@DEBUG]
++COMPILEOPTION = -c -g
++[COMPILE@RELEASE]
++COMPILEOPTION = -c
++[CVS]
++INITDIR = $CVSROOT
++REMOTELOGIN = 0
++[DEBUG@DEBUG]
++EXEPOS = PluginSmf2
++WORKDIR = 
++[DEBUG@RELEASE]
++EXEPOS = PluginSmf2
++WORKDIR = 
++[DEPENDENCY]
++FILENAME = README_BMF.txt
++FILENAME = ../../olsrd.conf
++FILENAME = README_BMF
++FILENAME = version-script.txt
++FILENAME = README_SMF
++FILENAME = Makefile
++[GDBSERVER]
++ISGDBSERVER = 0
++[HEADER]
++FILENAME = src/Bmf.h
++FILENAME = src/PacketHistory.h
++FILENAME = src/Packet.h
++FILENAME = src/Address.h
++FILENAME = src/NetworkInterfaces.h
++FILENAME = src/DropList.h
++[LANTYPE@DEBUG]
++LANTYPE = 0
++[LANTYPE@RELEASE]
++LANTYPE = 0
++[LINK@DEBUG]
++LINKOPTION = -g -o PluginSmf2
++OUTPUT = PluginSmf2
++[LINK@RELEASE]
++LINKOPTION = -o PluginSmf2
++OUTPUT = PluginSmf2
++[MAIN]
++CONFIG = RELEASE,DEBUG
++DEFAULTCONFIG = DEBUG
++DEVTYPE = 0
++ONLINE = 1
++VERSION = 3.0
++WATCH = 
++[MAKE@DEBUG]
++CUSTOMMAKE = Makefile
++CUSTOMMAKEBUILDPARAM = 
++CUSTOMMAKECLEANPARAM = clean
++CUSTOMMAKEDIR = 
++CUSTOMSHELL = 
++MAKEFILE = Makefile_DEBUG.mk
++MANUALDEFAULT = 1
++REGENMAKEFILE = 1
++[MAKE@RELEASE]
++CUSTOMMAKE = Makefile
++CUSTOMMAKEBUILDPARAM = 
++CUSTOMMAKECLEANPARAM = clean
++CUSTOMMAKEDIR = 
++CUSTOMSHELL = 
++MAKEFILE = Makefile_DEBUG.mk
++MANUALDEFAULT = 1
++REGENMAKEFILE = 1
++[PRECOMPILE@DEBUG]
++ESQL_OPTION = -g
++PROC_OPTION = DEFINE=_PROC_ MODE=ORACLE LINES=true
++[PRECOMPILE@RELEASE]
++ESQL_OPTION = 
++PROC_OPTION = DEFINE=_PROC_ MODE=ORACLE
++[SOURCE]
++FILENAME = src/Bmf.c
++FILENAME = src/Packet.c
++FILENAME = src/PacketHistory.c
++FILENAME = src/DropList.c
++FILENAME = src/olsrd_plugin.c
++FILENAME = src/Address.c
++FILENAME = src/NetworkInterfaces.c
+diff -Nur olsrd-0.4.10.orig/lib/bmf/README_BMF.txt olsrd-0.4.10/lib/bmf/README_BMF.txt
+--- olsrd-0.4.10.orig/lib/bmf/README_BMF.txt   1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/README_BMF.txt        2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,233 @@
++BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD
++by Erik Tromp (erik.tromp@nl.thalesgroup.com)
++
++12 Jul 2006: Version 1.1
++* Major updates in code forwarding from and to non-OLSR enabled
++  network interfaces.
++* Debug level 9 gives a better indication of what happens to each
++  handled multicast/broadcast packet.
++* Can now deal with network interface removal ("ifdown eth1") and
++  addition ("ifup eth1").
++* CRC-calculation for duplicate detection is done over first 256
++  bytes in packet instead of over full packet length.
++* CRC calculated only on captured packets, and is subsequently
++  passed on in a special OLSR-BMF encapsulation header.
++* Deals correctly with fragmented packets
++
++27 Apr 2006: Version 1.0.1
++* First release.
++
++1. Introduction
++---------------
++
++The Basic Multicast Forwarding Plugin floods IP-multicast and
++IP-local-broadcast traffic over an OLSRD network. It uses the
++Multi-Point Relays (MPRs) as identified by the OLSR protocol
++to optimize the flooding of multicast and local broadcast packets
++to all the nodes in the network. To prevent broadcast storms, a
++history of packets is kept; only packets that have not been seen
++in the past 3-6 seconds are forwarded.
++
++In the IP header there is room for only two IP-addresses:
++* the destination IP address (in our case either a multicast
++  IP-address 224.0.0.0...239.255.255.255, or a local broadcast
++  address e.g. 192.168.1.255), and
++* the source IP address (the originator).
++
++For optimized flooding, however, we need more information. Let's
++assume we are the BMF process on one node. We will need to know which
++node forwarded the IP packet to us. Since OLSR keeps track of which
++nodes select our node as MPR (see the olsr_lookup_mprs_set function),
++we can determine if the node that forwarded the packet, has selected us as
++MPR. If so, we must also forward the packet, changing the 'forwarded-by'
++IP-address to that of us.
++
++Because we need more information than fits in a normal IP-header, the
++original packets are encapsulated into a new IP packet. Encapsulated
++packets are transported in UDP, port 50505. The source address of the
++encapsulation packet is set to the address of the forwarder instead of
++the originator. Of course, the payload of the encapsulation packet is
++the original IP packet.
++
++For local reception, each received encapsulated packets is unpacked
++and passed into a tuntap interface which is specially created for
++this purpose.
++
++Here is in short how the flooding works (see also the
++BmfEncapsulatedPacketReceived(...) function; details with respect to
++the forwarding towards non-OLSR enabled nodes are omitted):
++  
++  On all OLSR-enabled interfaces, setup reception of packets
++    on UDP port 50505.
++  Upon reception of such a packet:
++    If the received packet was sent by myself, drop it.
++    If the packet was recently seen, drop it.
++    Unpack the encapsulated packet and send a copy to myself via the
++      TunTap device.
++    If I am an MPR for the node that forwarded the packet to me,
++      forward the packet to all OLSR-enabled interfaces *including*
++      the interface on which it was received.
++
++As with all good things in life, it's so simple you could have
++thought of it yourself.
++
++
++2. How to build and install
++---------------------------
++
++Follow the instructions in the base directory README file under
++section II. - BUILDING AND RUNNING OLSRD. To be sure to install
++the BMF plugin, cd to the base directory and issue the follwing
++command at the shell prompt:
++
++  make install_all
++
++Next, turn on the possibility to create a tuntap device (see also
++/usr/src/linux/Documentation/networking/tuntap.txt)
++
++  mkdir /dev/net # if it doesn't exist already
++  mknod /dev/net/tun c 10 200
++  
++Set permissions, e.g.:
++  chmod 0700 /dev/net/tun
++     
++Edit the file /etc/olsrd.conf to load the BMF plugin. For example:
++
++  LoadPlugin "olsrd_bmf.so.1.1"
++  {
++    # No PlParam entries required for basic operation
++  }
++
++
++3. How to run
++-------------
++
++After building and installing OLSRD with the BMF plugin, run the
++olsrd deamon by entering at the shell prompt:
++  olsrd
++
++Look at the output; it should list the BMF plugin, e.g.:
++
++  ---------- Plugin loader ----------
++  Library: olsrd_bmf.so.1.1
++  OLSRD Basic Multicast Forwarding plugin 1.1 (Jul 12 2006 04:12:42)
++    (C) Thales Communications Huizen, Netherlands
++    Erik Tromp (erik.tromp@nl.thalesgroup.com)
++  Checking plugin interface version...  4 - OK
++  Trying to fetch plugin init function... OK
++  Trying to fetch param function... OK
++  Sending parameters...
++  "NonOlsrIf"/"eth0"... OK
++  Running plugin_init function...
++  OLSRD Basic Multicast Forwarding plugin: opened 6 sockets
++  ---------- LIBRARY LOADED ----------
++
++
++4. How to check if it works
++---------------------------
++
++To check that BMF is working, enter the following command on the
++command prompt:
++  
++  ping -I eth1 224.0.0.1
++    
++Replace eth1 with the name of any OLSR-enabled network interface.
++
++All OLSR-BMF nodes in the MANET should respond. For example:
++
++root@IsdbServer:~# ping -I eth1 224.0.0.1
++PING 224.0.0.1 (224.0.0.1) from 192.168.151.50 eth1: 56(84) bytes of data.
++64 bytes from 192.168.151.50: icmp_seq=1 ttl=64 time=0.511 ms
++64 bytes from 192.168.151.53: icmp_seq=1 ttl=64 time=4.67 ms (DUP!)
++64 bytes from 192.168.151.55: icmp_seq=1 ttl=63 time=10.7 ms (DUP!)
++64 bytes from 192.168.151.50: icmp_seq=2 ttl=64 time=0.076 ms
++64 bytes from 192.168.151.53: icmp_seq=2 ttl=64 time=1.23 ms (DUP!)
++64 bytes from 192.168.151.55: icmp_seq=2 ttl=63 time=1.23 ms (DUP!)
++64 bytes from 192.168.151.50: icmp_seq=3 ttl=64 time=0.059 ms
++64 bytes from 192.168.151.53: icmp_seq=3 ttl=64 time=2.94 ms (DUP!)
++64 bytes from 192.168.151.55: icmp_seq=3 ttl=63 time=5.62 ms (DUP!)
++64 bytes from 192.168.151.50: icmp_seq=4 ttl=64 time=0.158 ms
++64 bytes from 192.168.151.53: icmp_seq=4 ttl=64 time=1.14 ms (DUP!)
++64 bytes from 192.168.151.55: icmp_seq=4 ttl=63 time=1.16 ms (DUP!)
++
++
++5. Adding non-OLSR interfaces to the multicast flooding
++-------------------------------------------------------
++
++As a special feature, it is possible to have multicast and local-broadcast
++IP packets forwarded also on non-OLSR interfaces.
++
++If you have network interfaces on which OLSR is *not* running, but you *do*
++want to forward multicast and local-broadcast IP packets, specify these
++interfaces one by one as "NonOlsrIf" parameters in the BMF plugin section
++of /etc/olsrd.conf. For example:
++
++  LoadPlugin "olsrd_bmf.so.1.1"
++  {
++    # Non-OLSR interfaces to participate in the multicast flooding
++    PlParam     "NonOlsrIf"  "eth2"
++    PlParam     "NonOlsrIf"  "eth3"
++  }
++
++If an interface is listed both as NonOlsrIf for BMF, and in the
++Interfaces { ... } section of olsrd.conf, it will be seen by BMF
++as an OLSR-enabled interface.
++
++Note that when BMF receives or sends a packet via a non-OLSR interface,
++the TTL is decremented. TTL is NOT decremented on packets traveling
++within the OLSR-BMF MANET, since that is considered to be one (repaired)
++broadcast domain.
++
++Packets are not forwarded from one non-OLSR interface to another non-OLSR
++interface, only from non-OLSR interfaces to OLSR interfaces and vice versa.
++Packet forwarding between non-OLSR interfaces should be the result of
++other multicast routing protocols.
++  
++
++6. Testing in a lab environment
++-------------------------------
++
++Setup IP-tables to drop packets from nodes which are not
++direct (1-hop) neigbors. For example, to drop all packets from
++a host with MAC address 00:0C:29:28:0E:CC, enter at the shell prompt:
++
++  iptables -A INPUT -m mac --mac-source 00:0C:29:28:0E:CC -j DROP
++
++Edit the file /etc/olsrd.conf, and specify the MAC addresses of the nodes
++we do not want to see; even though packets from these nodes are dropped
++by iptables, they are still received on network interfaces which are in
++promiscuous mode. For example:
++
++  LoadPlugin "olsrd_bmf.so.1.1"
++  {
++    # Drop all packets received from the following MAC sources
++    PlParam     "DropMac"    "00:0C:29:C6:E2:61" # RemoteClient1
++    PlParam     "DropMac"    "00:0C:29:61:34:B7" # SimpleClient1
++    PlParam     "DropMac"    "00:0C:29:28:0E:CC" # SimpleClient2
++  }
++
++
++
++7. Common problems, FAQ
++-----------------------
++
++Question:
++On which platforms does BMF currently compile?
++
++Answer:
++Only on Linux. No compilation on Windows (yet). The oldest Linux
++kernel on which the BMF plugin was tested was version 2.4.18.
++
++
++Question:
++When starting OLSRD with the BMF plugin, I can see the following
++error message:
++
++OLSRD Basic Multicast Forwarding plugin: error opening /dev/net/tun: No such file or directory
++
++Wat to do?
++
++Answer:
++Turn on the possibility to create a tuntap device; see section 2 of this
++file.
++
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Address.c olsrd-0.4.10/lib/bmf/src/Address.c
+--- olsrd-0.4.10.orig/lib/bmf/src/Address.c    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Address.c 2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,194 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++ 
++/* -------------------------------------------------------------------------
++ * File       : Address.c
++ * Description: IP packet characterization functions
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++ 
++#include "Address.h"
++
++/* System includes */
++#include <assert.h> /* assert() */
++#include <netinet/ip.h> /* struct ip */
++#include <netinet/udp.h> /* struct udphdr */
++
++/* OLSRD includes */
++#include "defs.h" /* COMP_IP */
++
++/* Plugin includes */
++#include "Bmf.h" /* BMF_ENCAP_PORT */
++#include "NetworkInterfaces.h" /* TBmfInterface */
++
++/* -------------------------------------------------------------------------
++ * Function   : IsMulticast
++ * Description: Check if an IP address is a multicast address
++ * Input      : ipAddress
++ * Output     : none
++ * Return     : true (1) or false (0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int IsMulticast(union olsr_ip_addr* ipAddress)
++{
++  assert(ipAddress != NULL);
++
++  return (ntohl(ipAddress->v4) & 0xF0000000) == 0xE0000000;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : IsLocalBroadcast
++ * Description: Check if an IP address is a local broadcast address for a
++ *              given network interface
++ * Input      : destIp, ifFrom
++ * Output     : none
++ * Return     : true (1) or false (0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int IsLocalBroadcast(union olsr_ip_addr* destIp, struct TBmfInterface* ifFrom)
++{
++  struct sockaddr_in* sin;
++  
++  assert(destIp != NULL && ifFrom != NULL);
++
++  /* Cast down to correct sockaddr subtype */
++  sin = (struct sockaddr_in*)&(ifFrom->broadAddr);
++
++  return COMP_IP(&(sin->sin_addr.s_addr), destIp);
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : IsOlsrOrBmfPacket
++ * Description: Check if an ethernet packet is an OLSR packet or a BMF packet
++ * Input      : intf, ethPkt, len
++ * Output     : none
++ * Return     : true (1) or false (0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int IsOlsrOrBmfPacket(struct TBmfInterface* intf, unsigned char* ethPkt, size_t len)
++{
++  struct ip* ipData;
++  unsigned int ipHeaderLen;
++
++  assert(ethPkt != NULL);
++
++  /* Consider OLSR and BMF packets not to be local broadcast
++   * OLSR packets are UDP - port 698
++   * OLSR-BMF packets are UDP - port 50698
++   * OLSR-Autodetect probe packets are UDP - port 51698
++   * Fragments of the above packets are also not local broadcast */
++
++  ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET);
++  ipHeaderLen = ipData->ip_hl << 2;
++  if (len < IP_HDR_OFFSET + ipHeaderLen)
++  {
++    return 0;
++  }
++
++  if (ipData->ip_p != SOL_UDP)
++  {
++    return 0;
++  }
++
++  /* Check if the packet is a fragment */
++  if ((ntohs(ipData->ip_off) & IP_OFFMASK) != 0)
++  {
++    int i;
++    for (i = 0; i < FRAGMENT_HISTORY_SIZE; i++)
++    {
++      /* Quick-access pointer */
++      struct TFragmentHistory* entry = &intf->fragmentHistory[i];
++
++      /* Match */
++      if (entry->ipId == ntohs(ipData->ip_id) &&
++          entry->ipProto == ipData->ip_p &&
++          entry->ipSrc.s_addr == ntohl(ipData->ip_src.s_addr) &&
++          entry->ipDst.s_addr == ntohl(ipData->ip_dst.s_addr))
++      {
++        /* Found matching history entry, so packet is assumed to be a fragment
++         * of an earlier OLSR/OLSR-BMF/OLSR-Autodetect packet */
++
++        /* More fragments? If not, invalidate entry */
++        if (((ntohs(ipData->ip_off) & IP_MF) == 0))
++        {
++          memset(entry, 0, sizeof(struct TFragmentHistory));
++        }
++
++        return 1;
++      }
++    }
++
++    /* Matching history entry not found, so packet is not assumed to be a fragment
++     * of an earlier OLSR/OLSR-BMF/OLSR-Autodetect packet */
++    return 0;
++  }
++
++  /* The packet is the first (or only) fragment */
++
++  /* Check length first */
++  if (len < IP_HDR_OFFSET + ipHeaderLen + sizeof(struct udphdr ))
++  {
++    return 0;
++  }
++
++  /* Go into the UDP header and check port number */
++  struct udphdr* udpData = (struct udphdr*) (ethPkt + IP_HDR_OFFSET + ipHeaderLen);
++  u_int16_t port = ntohs(udpData->source);
++
++  if (port == OLSRPORT || port == BMF_ENCAP_PORT || port == 51698)
++      /* TODO define for 51698 */
++  {
++    /* If more fragments are expected, keep a record in the fragment history */
++    if ((ntohs(ipData->ip_off) & IP_MF) != 0)
++    {
++      /* Quick-access pointer */
++      struct TFragmentHistory* entry = &intf->fragmentHistory[intf->nextFragmentHistoryEntry];
++
++      /* Store in fragment history */
++      entry->ipId = ntohs(ipData->ip_id);
++      entry->ipProto = ipData->ip_p;
++      entry->ipSrc.s_addr = ntohl(ipData->ip_src.s_addr);
++      entry->ipDst.s_addr = ntohl(ipData->ip_dst.s_addr);
++
++      /* Advance to next entry */
++      intf->nextFragmentHistoryEntry++;
++      intf->nextFragmentHistoryEntry %= FRAGMENT_HISTORY_SIZE;
++    }
++    return 1;
++  }
++
++  return 0;
++}
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Address.h olsrd-0.4.10/lib/bmf/src/Address.h
+--- olsrd-0.4.10.orig/lib/bmf/src/Address.h    1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Address.h 2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,55 @@
++#ifndef _BMF_ADDRESS_H
++#define _BMF_ADDRESS_H
++
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : Address.h
++ * Description: IP packet characterization functions
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++#include "olsr_types.h" /* olsr_ip_addr */
++#include "interfaces.h" /* struct interface */
++
++struct TBmfInterface;
++
++int IsMulticast(union olsr_ip_addr* ipAddress);
++int IsLocalBroadcast(union olsr_ip_addr* destIp, struct TBmfInterface* ifFrom);
++int IsOlsrOrBmfPacket(struct TBmfInterface* intf, unsigned char* ethPkt, size_t len);
++
++#endif /* _BMF_ADDRESS_H */
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Bmf.c olsrd-0.4.10/lib/bmf/src/Bmf.c
+--- olsrd-0.4.10.orig/lib/bmf/src/Bmf.c        1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Bmf.c     2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,935 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : Bmf.c
++ * Description: Multicast forwarding functions
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++#define _MULTI_THREADED
++
++#include "Bmf.h"
++
++/* System includes */
++#include <stdio.h> /* NULL */
++#include <sys/types.h> /* ssize_t */
++#include <string.h> /* strerror() */
++#include <errno.h> /* errno */
++#include <assert.h> /* assert() */
++#include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */
++#include <pthread.h> /* pthread_t, pthread_create() */
++#include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
++#include <netinet/ip.h> /* struct ip */
++
++/* OLSRD includes */
++#include "defs.h" /* olsr_cnf */
++#include "olsr.h" /* olsr_printf */
++#include "scheduler.h" /* olsr_register_scheduler_event */
++#include "mid_set.h" /* mid_lookup_main_addr() */
++#include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */
++#include "link_set.h" /* get_best_link_to_neighbor() */
++
++/* Plugin includes */
++#include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
++#include "Address.h" /* IsMulticast(), IsLocalBroadcast() */
++#include "Packet.h" /* ETH_TYPE_OFFSET, IFHWADDRLEN etc. */
++#include "PacketHistory.h" /* InitPacketHistory() */
++#include "DropList.h" /* DropMac() */
++
++static pthread_t BmfThread;
++static int BmfThreadRunning = 0;
++
++
++/* -------------------------------------------------------------------------
++ * Function   : BmfPacketCaptured
++ * Description: Handle a captured raw IP packet
++ * Input      : intf - the network interface on which the packet was captured
++ *              buffer - space for the encapsulation header, followed by
++ *                the captured packet
++ *              len - the number of octets in the encapsulation header plus
++ *                captured packet
++ * Output     : none
++ * Return     : none
++ * Data Used  : BmfInterfaces
++ * Notes      : The packet is assumed to be captured on a socket of family
++ *              PF_PACKET and type SOCK_RAW.
++ * ------------------------------------------------------------------------- */
++static void BmfPacketCaptured(struct TBmfInterface* intf, unsigned char* buffer, ssize_t len)
++{
++  unsigned char* srcMac;
++  union olsr_ip_addr srcIp;
++  union olsr_ip_addr destIp;
++  union olsr_ip_addr* origIp;
++  struct sockaddr_in encapDest;
++  struct TBmfInterface* nextFwIntf;
++  int isFromOlsrIntf; /* Boolean indicating if packet captured on OLSR-enabled interface */
++  int iAmNotMpr;
++  unsigned char* ethPkt = buffer + ENCAP_HDR_LEN;
++  ssize_t ethPktLen = len - ENCAP_HDR_LEN;
++  struct ip* ipData;
++
++  /* Only forward IPv4 packets */
++  u_int16_t type;
++  memcpy(&type, ethPkt + ETH_TYPE_OFFSET, 2);
++  if (ntohs(type) != IPV4_TYPE)
++  {
++    return;
++  }
++
++  ipData = (struct ip*)(ethPkt + IP_HDR_OFFSET);
++
++  /* Only forward multicast or local broadcast packets */
++  COPY_IP(&destIp, &ipData->ip_dst);
++  if (! IsMulticast(&destIp) && ! IsLocalBroadcast(&destIp, intf))
++  {
++    return;
++  }
++
++  /* Discard OLSR packets (UDP port 698) and BMF encapsulated packets */
++  if (IsOlsrOrBmfPacket(intf, ethPkt, ethPktLen))
++  {
++    return;
++  }
++
++  COPY_IP(&srcIp, &ipData->ip_src);
++  olsr_printf(
++    9,
++    "%s: pkt of %d bytes incoming on \"%s\": %s->%s\n",
++    PLUGIN_NAME_SHORT,
++    ethPktLen,
++    intf->ifName,
++    olsr_ip_to_string(&srcIp),
++    olsr_ip_to_string(&destIp));
++
++  /* Apply drop list for testing purposes. */
++  srcMac = ethPkt + IFHWADDRLEN;
++  if (IsInDropList(srcMac))
++  {
++    olsr_printf(
++      9,
++      "%s: --> discarding: source MAC (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) found in drop list\n",
++      PLUGIN_NAME_SHORT,
++      srcMac, srcMac + 1, srcMac + 2, srcMac + 3, srcMac + 4, srcMac + 5);
++    return;
++  }
++
++  /* Lookup main address of source in the MID table of OLSR */
++  origIp = mid_lookup_main_addr(&srcIp);
++  if (origIp == NULL)
++  {
++    origIp = &srcIp;
++  }
++
++  /* Check if this packet is received on an OLSR-enabled interface */
++  isFromOlsrIntf = (intf->olsrIntf != NULL);
++
++  /* If this packet is captured on a non-OLSR interface, it will be forwarded
++   * only to OLSR interfaces, thereby crossing the boundary between the external
++   * network and the OLSR network. So decrease the TTL and re-calculate the IP header
++   * checksum. */
++  if (! isFromOlsrIntf)
++  {
++    DecreaseTtlAndUpdateHeaderChecksum(ethPkt);
++  }
++
++  /* If the resulting TTL is <= 0, this packet life has ended, so do not forward it */
++  if (GetIpTtl(ethPkt) <= 0)
++  {
++    olsr_printf(
++      9,
++      "%s: --> discarding: TTL=0\n",
++      PLUGIN_NAME_SHORT);
++    return;
++  }
++
++  /* Check if this packet was seen recently */
++  u_int32_t crc32 = PacketCrc32(ethPkt, ethPktLen);
++  if (CheckAndMarkRecentPacket(Hash16(crc32)))
++  {
++    olsr_printf(
++      9,
++      "%s: --> discarding: packet is duplicate\n",
++      PLUGIN_NAME_SHORT);
++    return;
++  }
++
++  /* Compose encapsulation header */
++  struct TEncapHeader* encapHdr = (struct TEncapHeader*) buffer;
++  memset (encapHdr, 0, ENCAP_HDR_LEN);
++  encapHdr->crc32 = htonl(crc32);
++
++  /* If this packet is captured on an OLSR interface from an OLSR neighbor,
++   * check with OLSR if I am MPR for that neighbor */
++  iAmNotMpr =
++    (isFromOlsrIntf /* captured on an OLSR interface */
++    && get_best_link_to_neighbor(origIp) != NULL /* from an OLSR neighbor */
++    && olsr_lookup_mprs_set(origIp) == NULL); /* but not selected as MPR */
++
++  memset(&encapDest, 0, sizeof(encapDest));
++  encapDest.sin_family = AF_INET;
++  encapDest.sin_port = htons(BMF_ENCAP_PORT);
++
++  /* Check with each interface what needs to be done on it */
++  nextFwIntf = BmfInterfaces;
++  while (nextFwIntf != NULL)
++  {
++    int isToOlsrIntf; /* Boolean indicating if forwarding interface is OLSR-enabled */
++
++    struct TBmfInterface* fwIntf = nextFwIntf;
++    nextFwIntf = fwIntf->next;
++
++    isToOlsrIntf = (fwIntf->olsrIntf != NULL);
++
++    /* The following if-else statement seems very complicated. Let's
++     * draw a Karnaugh-diagram of it for some clarification.
++     *
++     *                -------  isFromOlsrIntf 
++     *           --------      isToOlsrIntf
++     *       +---+---+---+---+
++     *       | 3 | 2 | 2 | 1 |
++     *       +---+---+---+---+
++     *     | | X | X | 4 | 1 |
++     *       +---+---+---+---+
++     * iAmNotMpr
++     *
++     * X = does not occur (iAmNotMpr = isFromOlsrIntf && ...)
++     * 1 = handled in first if-clause: if (isFromOlsrIntf && !isToOlsrIntf)...
++     * 2 = handled in second if-clause: if (isToOlsrIntf && !iAmNotMpr)...
++     * 3 = handled in third if-clause: if (!isFromOlsrIntf && !isToOlsrIntf)...
++     * 4 = handled in else-clause.
++     */
++
++    /* Forward from OLSR-interface to non-OLSR interface */
++    if (isFromOlsrIntf && !isToOlsrIntf)
++    {
++      struct TSaveTtl sttl;
++
++      /* Save IP header checksum and the TTL-value of the packet */ 
++      SaveTtlAndChecksum(ethPkt, &sttl);
++
++      /* Save IP header checksum and the TTL-value of the packet, then
++       * decrease the TTL by 1 before writing */
++      DecreaseTtlAndUpdateHeaderChecksum(ethPkt);
++
++      /* If the TTL is <= 0, do not forward this packet */
++      if (GetIpTtl(ethPkt) <= 0)
++      {
++        OLSR_PRINTF(
++          9,
++          "%s: --> not forwarding on \"%s\": TTL=0\n",
++          PLUGIN_NAME_SHORT,
++          fwIntf->ifName);
++      }
++      else
++      {
++        /* Change source MAC address to that of sending interface */
++        memcpy(ethPkt + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
++
++        int nBytesWritten = write(fwIntf->capturingSkfd, ethPkt, ethPktLen);
++        if (nBytesWritten != ethPktLen)
++        {
++          olsr_printf(
++            1,
++            "%s: write() error forwarding pkt for %s to \"%s\": %s\n",
++            PLUGIN_NAME,
++            olsr_ip_to_string(&destIp),
++            fwIntf->ifName,
++            strerror(errno));
++        }
++        else
++        {
++          OLSR_PRINTF(
++            9,
++            "%s: --> forwarded to \"%s\"\n",
++            PLUGIN_NAME_SHORT,
++            fwIntf->ifName);
++        }
++      }
++
++      /* Restore the IP header checksum and the TTL-value of the packet */
++      RestoreTtlAndChecksum(ethPkt, &sttl);
++
++    } /* if (isFromOlsrIntf && !isToOlsrIntf) */
++
++    /* Forward from any interface to OLSR interface. Packets from non-OLSR interfaces
++     * already had their TTL decreased. */
++    else /* !isFromOlsrIntf || isToOlsrIntf */
++    if (isToOlsrIntf && !iAmNotMpr)
++    {
++      int nBytesWritten;
++
++      /* Change encapsulated source MAC address to that of sending interface */
++      memcpy(ethPkt + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
++
++      /* Destination address is local broadcast */
++      encapDest.sin_addr.s_addr = ((struct sockaddr_in*)&fwIntf->olsrIntf->int_broadaddr)->sin_addr.s_addr;
++
++      nBytesWritten = sendto(
++        fwIntf->encapsulatingSkfd,
++        buffer,
++        len,
++        MSG_DONTROUTE,
++        (struct sockaddr*) &encapDest,
++        sizeof(encapDest));                   
++
++      if (nBytesWritten != len)
++      {
++        olsr_printf(
++          1,
++          "%s: sendto() error forwarding pkt for %s to \"%s\": %s\n",
++          PLUGIN_NAME,
++          olsr_ip_to_string(&destIp),
++          fwIntf->ifName,
++          strerror(errno));
++      }
++      else
++      {
++        OLSR_PRINTF(
++          9,
++          "%s: --> encapsulated and forwarded to \"%s\"\n",
++          PLUGIN_NAME_SHORT,
++          fwIntf->ifName);
++      } /* if (nBytesWritten != len) */
++    } /* else if (isToOlsrIntf && !iAmNotMpr) */
++
++    else /* (!isFromOlsrIntf || isToOlsrIntf) && (!isToOlsrIntf || iAmNotMpr) */
++    if (!isFromOlsrIntf && !isToOlsrIntf)
++    {
++      OLSR_PRINTF(
++        9,
++        "%s: --> not forwarding from \"%s\" to \"%s\": both non-OLSR interfaces\n",
++        PLUGIN_NAME_SHORT,
++        intf->ifName,
++        fwIntf->ifName);
++    }
++
++    else /* (!isFromOlsrIntf || isToOlsrIntf) && (!isToOlsrIntf || iAmNotMpr) && (isFromOlsrIntf || isToOlsrIntf) */
++    {
++      OLSR_PRINTF(
++        9,
++        "%s: --> not forwarding from \"%s\" to \"%s\": I am not selected as MPR by %s\n",
++        PLUGIN_NAME_SHORT,
++        intf->ifName,
++        fwIntf->ifName,
++        olsr_ip_to_string(&srcIp));
++    }
++  } /* while (nextFwIntf != NULL) */
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : BmfEncapsulatedPacketReceived
++ * Description: Handle a received BMF-encapsulated IP packet
++ * Input      : intf - the network interface on which the packet was received
++ *              fromIp - the IP node that forwarded the packet to us
++ *              buffer - the received encapsulated packet
++ *              len - the number of octets in the received encapsulated packet
++ * Output     : none
++ * Return     : none
++ * Data Used  : BmfInterfaces
++ * Notes      : The packet is assumed to be received on a socket of family
++ *              PF_INET and type SOCK_DGRAM (UDP).
++ * ------------------------------------------------------------------------- */
++static void BmfEncapsulatedPacketReceived(
++  struct TBmfInterface* intf, 
++  union olsr_ip_addr* fromIp,
++  unsigned char* buffer,
++  ssize_t len)
++{
++  union olsr_ip_addr* forwarder;
++  int nBytesToWrite;
++  unsigned char* bufferToWrite;
++  int nBytesWritten;
++  int iAmMpr;
++  struct sockaddr_in encapDest;
++  struct TBmfInterface* nextFwIntf;
++  struct ip* ipData;
++  unsigned char* ethPkt;
++  ssize_t ethPktLen;
++
++  /* Are we talking to ourselves? */
++  if (if_ifwithaddr(fromIp) != NULL)
++  {
++    return;
++  }
++
++  /* Encapsulated packet received on non-OLSR interface? Then discard */
++  if (intf->olsrIntf == NULL)
++  {
++    return;
++  }
++
++  /* Apply drop list? No, not needed: encapsulated packets are routed,
++   * so filtering should be done by adding a rule to the iptables FORWARD
++   * chain, e.g.:
++   * iptables -A FORWARD -m mac --mac-source 00:0C:29:28:0E:CC -j DROP */
++
++  ethPkt = buffer + ENCAP_HDR_LEN;
++  ethPktLen = len - ENCAP_HDR_LEN;
++
++  ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET);
++
++  OLSR_PRINTF(
++    9,
++    "%s: encapsulated pkt of %d bytes incoming on \"%s\": %s->",
++    PLUGIN_NAME_SHORT,
++    ethPktLen,
++    intf->ifName,
++    inet_ntoa(ipData->ip_src));
++  OLSR_PRINTF(
++    9,
++    "%s, forwarded by %s\n",
++    inet_ntoa(ipData->ip_dst), /* not possible to call inet_ntoa twice in same printf */
++    olsr_ip_to_string(fromIp));
++
++  /* Get encapsulation header */
++  struct TEncapHeader* encapHdr = (struct TEncapHeader*) buffer;
++
++  /* Check if this packet was seen recently */
++  if (CheckAndMarkRecentPacket(Hash16(ntohl(encapHdr->crc32))))
++  {
++    OLSR_PRINTF(
++      9,
++      "%s: --> discarding: packet is duplicate\n",
++      PLUGIN_NAME_SHORT);
++    return;
++  }
++
++  /* Unpack encapsulated packet and send a copy to myself via the EtherTunTap device */
++  bufferToWrite = ethPkt;
++  nBytesToWrite = ethPktLen;
++  if (TunOrTap == TT_TUN)
++  {
++    bufferToWrite += IP_HDR_OFFSET;
++    nBytesToWrite -= IP_HDR_OFFSET;
++  }
++  nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
++  if (nBytesWritten != nBytesToWrite)
++  {
++    olsr_printf(
++      1,
++      "%s: write() error forwarding encapsulated pkt to \"%s\": %s\n",
++      PLUGIN_NAME,
++      EtherTunTapIfName,
++      strerror(errno));
++  }
++  else
++  {
++    OLSR_PRINTF(
++      9,
++      "%s: --> unpacked and forwarded to \"%s\"\n",
++      PLUGIN_NAME_SHORT,
++      EtherTunTapIfName);
++  }
++
++  /* Lookup main address of forwarding node */
++  forwarder = mid_lookup_main_addr(fromIp);
++  if (forwarder == NULL)
++  {
++    forwarder = fromIp;
++  }
++
++  /* Check if I am MPR for the forwarder */
++  iAmMpr = (olsr_lookup_mprs_set(forwarder) != NULL);
++
++  memset(&encapDest, 0, sizeof(encapDest));
++  encapDest.sin_family = AF_INET;
++  encapDest.sin_port = htons(BMF_ENCAP_PORT);
++
++  nextFwIntf = BmfInterfaces;
++  while (nextFwIntf != NULL)
++  {
++    struct TBmfInterface* fwIntf = nextFwIntf;
++    nextFwIntf = fwIntf->next;
++
++    /* Forward from OLSR interface to non-OLSR interface: unpack encapsulated
++     * packet, decrease TTL and forward */
++    if (fwIntf->olsrIntf == NULL)
++    {
++      struct TSaveTtl sttl;
++
++      /* Save IP header checksum and the TTL-value of the packet, then 
++       * decrease the TTL by 1 before writing */
++      SaveTtlAndChecksum(ethPkt, &sttl);
++      DecreaseTtlAndUpdateHeaderChecksum(ethPkt);
++
++      /* If the TTL is <= 0, do not forward this packet */
++      if (GetIpTtl(ethPkt) <= 0)
++      {
++        OLSR_PRINTF(
++          9,
++          "%s: --> not forwarding on \"%s\": TTL=0\n",
++          PLUGIN_NAME_SHORT,
++          fwIntf->ifName);
++      }
++      else
++      {
++        nBytesWritten = write(fwIntf->capturingSkfd, ethPkt, ethPktLen);
++        if (nBytesWritten != ethPktLen)
++        {
++          olsr_printf(
++            1,
++            "%s: write() error forwarding unpacked encapsulated MC pkt to \"%s\": %s\n",
++            PLUGIN_NAME,
++            fwIntf->ifName,
++            strerror(errno));
++        }
++        else
++        {
++          OLSR_PRINTF(
++            9,
++            "%s: --> unpacked and forwarded to \"%s\"\n",
++            PLUGIN_NAME_SHORT,
++            fwIntf->ifName);
++        }
++      }
++
++      /* Restore the IP header checksum and the TTL-value of the packet */
++      RestoreTtlAndChecksum(ethPkt, &sttl);
++
++    } /* if (fwIntf->olsrIntf == NULL) */
++
++    /* Forward from OLSR interface to OLSR interface: forward the packet if this
++     * node is selected as MPR by the forwarding node */
++    else if (iAmMpr)
++    {
++      /* Change source MAC address to that of sending interface */
++      memcpy(buffer + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
++
++      /* Destination address is local broadcast */
++      encapDest.sin_addr.s_addr = ((struct sockaddr_in*)&fwIntf->olsrIntf->int_broadaddr)->sin_addr.s_addr;
++
++      nBytesWritten = sendto(
++        fwIntf->encapsulatingSkfd,
++        buffer,
++        len,
++        MSG_DONTROUTE,
++        (struct sockaddr*) &encapDest,
++        sizeof(encapDest));                   
++
++      if (nBytesWritten != len)
++      {
++        olsr_printf(
++          1,
++          "%s: sendto() error forwarding encapsulated pkt via \"%s\": %s\n",
++          PLUGIN_NAME,
++          fwIntf->ifName,
++          strerror(errno));
++      }
++      else
++      {
++        OLSR_PRINTF(
++          9,
++          "%s: --> forwarded to \"%s\"\n",
++          PLUGIN_NAME_SHORT,
++          fwIntf->ifName);
++      }
++    }  /* else if (iAmMpr) */
++    else /* fwIntf->olsrIntf != NULL && !iAmMpr */
++    {
++      /* fwIntf is an OLSR interface and I am not selected as MPR */
++      OLSR_PRINTF(
++        9,
++        "%s: --> not forwarding to \"%s\": I am not selected as MPR by %s\n",
++        PLUGIN_NAME_SHORT,
++        fwIntf->ifName,
++        olsr_ip_to_string(fromIp));
++    }
++  } /* while (nextFwIntf != NULL) */
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : DoBmf
++ * Description: Wait (blocking) for IP packets, then call the handler for each
++ *              received packet
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : BmfInterfaces
++ * ------------------------------------------------------------------------- */
++static void DoBmf(void)
++{
++#define BUFFER_MAX 2048
++  struct TBmfInterface* currIf;
++  int nFdBitsSet;
++
++  /* Compose set of socket file descriptors. 
++   * Keep the highest descriptor seen. */
++  int highestSkfd = -1;
++  fd_set input_set;
++  FD_ZERO(&input_set);
++
++  currIf = BmfInterfaces;
++  while (currIf != NULL)
++  {
++    FD_SET(currIf->capturingSkfd, &input_set);
++    if (currIf->capturingSkfd > highestSkfd)
++    {
++      highestSkfd = currIf->capturingSkfd;
++    }
++
++    if (currIf->encapsulatingSkfd >= 0)
++    {
++      FD_SET(currIf->encapsulatingSkfd, &input_set);
++      if (currIf->encapsulatingSkfd > highestSkfd)
++      {
++        highestSkfd = currIf->encapsulatingSkfd;
++      }
++    }
++
++    currIf = currIf->next;    
++  }
++
++  assert(highestSkfd >= 0);
++
++  /* Wait (blocking) for packets received on any of the sockets.
++   * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */
++  nFdBitsSet = select(highestSkfd + 1, &input_set, NULL, NULL, NULL);
++  if (nFdBitsSet < 0)
++  {
++    if (errno != EINTR)
++    {
++      olsr_printf(1, "%s: select() error: %s\n", PLUGIN_NAME, strerror(errno));
++    }
++    return;
++  }
++
++  if (nFdBitsSet == 0)
++  {
++    /* No packets waiting. This is unexpected; normally we would excpect select(...)
++     * to return only if at least one packet was received (so nFdBitsSet > 0), or
++     * if this thread received a signal (so nFdBitsSet < 0). */
++    return;
++  }
++
++  while (nFdBitsSet > 0)
++  {
++    struct TBmfInterface* nextIf = BmfInterfaces;
++    while (nextIf != NULL)
++    {
++      int skfd;
++      currIf = nextIf;
++      nextIf = currIf->next;
++
++      skfd = currIf->capturingSkfd;
++      if (FD_ISSET(skfd, &input_set))
++      {
++        unsigned char buffer[BUFFER_MAX];
++        struct sockaddr_ll pktAddr;
++        socklen_t addrLen;
++        int nBytes;
++        unsigned char* ethPkt = buffer + ENCAP_HDR_LEN;
++        struct ip* ipData;
++
++        /* A packet was captured. */
++
++        nFdBitsSet--;
++
++        memset(&pktAddr, 0, sizeof(struct sockaddr_ll));
++        addrLen = sizeof(pktAddr);
++
++        /* Receive the packet, leaving space for the BMF encap header */
++        nBytes = recvfrom(
++          skfd,
++          ethPkt,
++          BUFFER_MAX - ENCAP_HDR_LEN,
++          0,
++          (struct sockaddr*)&pktAddr,
++          &addrLen);
++        if (nBytes < 0)
++        {
++          olsr_printf(
++            1,
++            "%s: recvfrom() error on \"%s\": %s\n",
++            PLUGIN_NAME,
++            currIf->ifName,
++            strerror(errno));
++        }
++        else
++        {
++          /* Don't let BMF crash by sending too short packets */
++          int ipHeaderLen;
++          ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET);
++          ipHeaderLen = ipData->ip_hl << 2;
++          if (nBytes >= IP_HDR_OFFSET + ipHeaderLen)
++          {
++            if (pktAddr.sll_pkttype == PACKET_OUTGOING)
++            {
++              union olsr_ip_addr destIp;
++              COPY_IP(&destIp, &ipData->ip_dst);
++              if (IsMulticast(&destIp) || IsLocalBroadcast(&destIp, currIf))
++              {
++                if (! IsOlsrOrBmfPacket(currIf, ethPkt, nBytes))
++                {
++                  /* For outbound packets, just record the fact that the packet was
++                   * seen recently */
++                  u_int32_t crc32 = PacketCrc32(ethPkt, nBytes);
++                  MarkRecentPacket(Hash16(crc32));
++                }
++              }
++            }
++            else if (pktAddr.sll_pkttype == PACKET_MULTICAST ||
++                     pktAddr.sll_pkttype == PACKET_BROADCAST)
++            {
++              /* An inbound multicast or broadcast packet was captured */
++              BmfPacketCaptured(currIf, buffer, nBytes + ENCAP_HDR_LEN);
++            }
++          } /* if (nBytes >= IP_HDR_OFFSET + ipHeaderLen) */
++        } /* if (nBytes < 0) */
++      } /* if (FD_ISSET...) */
++
++      skfd = currIf->encapsulatingSkfd;
++      if (skfd >= 0 && (FD_ISSET(skfd, &input_set)))
++      {
++        unsigned char buffer[BUFFER_MAX];
++        struct sockaddr_in from;
++        socklen_t fromLen = sizeof(from);
++        int nBytes;
++        struct ip* ipData;
++
++        /* An encapsulated packet was received */
++
++        nFdBitsSet--;
++
++        nBytes = recvfrom(skfd, buffer, BUFFER_MAX, 0, (struct sockaddr*)&from, &fromLen);
++        if (nBytes < 0)
++        {
++          olsr_printf(
++            1,
++            "%s: recvfrom() error on \"%s\": %s\n",
++            PLUGIN_NAME,
++            currIf->ifName,
++            strerror(errno));
++        }
++        else
++        {
++          /* Don't let BMF crash by sending too short packets. */
++          int ipHeaderLen;
++          ipData = (struct ip *) (buffer + IP_HDR_OFFSET);
++          ipHeaderLen = ipData->ip_hl << 2;
++          if (nBytes >= IP_HDR_OFFSET + ipHeaderLen)
++          {
++            union olsr_ip_addr srcIp;
++            COPY_IP(&srcIp, &from.sin_addr.s_addr);
++            BmfEncapsulatedPacketReceived(currIf, &srcIp, buffer, nBytes);
++          }
++          else
++          {
++            olsr_printf(
++              1,
++              "%s: encapsulated packet too short (%d bytes) from %s on \"%s\"\n",
++              PLUGIN_NAME,
++              nBytes,
++              inet_ntoa(from.sin_addr),
++              currIf->ifName);
++          }
++        } /* if (nBytes < 0) */
++      } /* if (skfd >= 0 && (FD_ISSET...) */
++    } /* while (intf != NULL) */
++  } /* while (nFdBitsSet > 0) */
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : BmfSignalHandler
++ * Description: Dummy signal handler function
++ * Input      : signo - signal being handled
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++static void BmfSignalHandler(int signo)
++{
++  /* Dummy handler function */
++  return;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : BmfRun
++ * Description: Receiver thread function
++ * Input      : useless - not used
++ * Output     : none
++ * Return     : not used
++ * Data Used  : BmfThreadRunning
++ * Notes      : Another thread can gracefully stop this thread by writing a
++ *              '0' into global variable 'BmfThreadRunning' followed by sending
++ *              a SIGALRM signal.
++ * ------------------------------------------------------------------------- */
++static void* BmfRun(void* useless)
++{
++  /* Mask all signals except SIGALRM */
++  sigset_t blockedSigs;
++  sigfillset(&blockedSigs);
++  sigdelset(&blockedSigs, SIGALRM);
++  if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) < 0)
++  {
++    olsr_printf(1, "%s: pthread_sigmask() error: %s\n", PLUGIN_NAME, strerror(errno));
++  }
++
++  /* Set up the signal handler for the process: use SIGALRM to terminate
++   * the BMF thread. Only if a signal handler is specified, does a blocking
++   * system call return with errno set to EINTR; if a signal hander is not
++   * specified, any system call in which the thread may be waiting will not
++   * return. Note that the BMF thread is usually blocked in the select()
++   * function (see DoBmf()). */
++  if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR)
++  {
++    olsr_printf(1, "%s: signal() error: %s\n", PLUGIN_NAME, strerror(errno));
++  }
++
++  /* Call the thread function until flagged to exit */
++  while (BmfThreadRunning != 0)
++  {
++    DoBmf();
++  }
++
++  return NULL;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : InterfaceChange
++ * Description: Callback function passed to OLSRD for it to call whenever a
++ *              network interface has been added, removed or updated
++ * Input      : interf - the network interface to deal with
++ *              action - indicates if the specified network interface was
++ *              added, removed or updated.
++ * Output     : none
++ * Return     : always 0
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int InterfaceChange(struct interface* interf, int action)
++{
++  switch (action)
++  {
++  case (IFCHG_IF_ADD):
++    AddInterface(interf);
++    olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME, interf->int_name);
++    break;
++
++  case (IFCHG_IF_REMOVE):
++    CloseBmf();
++    InitBmf(interf);
++    olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME, interf->int_name);
++    break;
++
++  case (IFCHG_IF_UPDATE):
++    olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME, interf->int_name);
++    break;
++      
++  default:
++    break;
++  }
++  return 0;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : InitBmf
++ * Description: Initialize the BMF plugin
++ * Input      : skipThisIntf - specifies which network interface should not
++ *              be enabled for BMF. Pass NULL to indicate all.
++ * Output     : none
++ * Return     : fail (0) or success (1)
++ * Data Used  : BmfThreadRunning, BmfThread
++ * ------------------------------------------------------------------------- */
++int InitBmf(struct interface* skipThisIntf)
++{
++  if (CreateBmfNetworkInterfaces(skipThisIntf) < 0)
++  {
++    olsr_printf(1, "%s: Could not initialize any network interface!\n", PLUGIN_NAME);
++    /* Continue anyway; maybe an interface will be added later */
++  }
++
++  /* Start running the multicast packet processing thread */
++  BmfThreadRunning = 1;
++  if (pthread_create(&BmfThread, NULL, BmfRun, NULL) == 0)
++  {
++    return 1;
++  }
++  return 0;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CloseBmf
++ * Description: Close the BMF plugin and clean up
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : BmfThreadRunning, BmfThread
++ * ------------------------------------------------------------------------- */
++void CloseBmf()
++{
++  /* Signal BmfThread to exit */
++  BmfThreadRunning = 0;
++  if (pthread_kill(BmfThread, SIGALRM) < 0)
++  /* Strangely enough, all running threads receive the SIGALRM signal. But only the
++   * BMF thread is affected by this signal, having specified a handler for this
++   * signal in its thread entry function BmfRun(...). */
++  {
++    olsr_printf(1, "%s: pthread_kill() error: %s\n", PLUGIN_NAME, strerror(errno));
++  }
++
++  /* Wait for BmfThread to acknowledge */
++  if (pthread_join(BmfThread, NULL) < 0)
++  {
++    olsr_printf(1, "%s: pthread_join() error: %s\n", PLUGIN_NAME, strerror(errno));
++  }
++
++  /* Time to clean up */
++  CloseBmfNetworkInterfaces();
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : RegisterBmfParameter
++ * Description: Register a configuration parameter with the BMF process
++ * Input      : key - the parameter name: "DropMac" or "NonOlsrIf"
++ *              value - the parameter value
++ * Output     : none
++ * Return     : fatal error (<0), minor error (0) or success (>0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int RegisterBmfParameter(char* key, char* value)
++{
++  if (strcmp(key, "DropMac") == 0)
++  {
++    return DropMac(value);
++  }
++  else if (strcmp(key, "NonOlsrIf") == 0)
++  {
++    return AddNonOlsrBmfIf(value);
++  }
++
++  /* Key not recognized */
++  return 0;
++}
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Bmf.h olsrd-0.4.10/lib/bmf/src/Bmf.h
+--- olsrd-0.4.10.orig/lib/bmf/src/Bmf.h        1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Bmf.h     2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,64 @@
++#ifndef _BMF_BMF_H
++#define _BMF_BMF_H
++
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : Bmf.h
++ * Description: Multicast forwarding functions
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++/* BMF plugin data */
++#define PLUGIN_NAME "OLSRD Basic Multicast Forwarding plugin"
++#define PLUGIN_NAME_SHORT "OLSRD BMF"
++#define PLUGIN_VERSION "1.1 (" __DATE__ " " __TIME__ ")"
++#define PLUGIN_COPYRIGHT "  (C) Thales Communications Huizen, Netherlands"
++#define PLUGIN_AUTHOR "  Erik Tromp (erik.tromp@nl.thalesgroup.com)"
++#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
++
++/* UDP-Port on which multicast packets are encapsulated */
++#define BMF_ENCAP_PORT 50698
++
++struct interface;
++
++int InterfaceChange(struct interface* interf, int action);
++int InitBmf(struct interface* skipThisIntf);
++void CloseBmf(void);
++int RegisterBmfParameter(char* key, char* value);
++
++#endif /* _BMF_BMF_H */
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/DropList.c olsrd-0.4.10/lib/bmf/src/DropList.c
+--- olsrd-0.4.10.orig/lib/bmf/src/DropList.c   1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/DropList.c        2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,129 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : DropList.c
++ * Description: List of MAC addresses of hosts from which all packets are dropped.
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++
++#include "DropList.h"
++
++/* System includes */
++#include <assert.h> /* assert() */
++#include <stdio.h> /* NULL */
++#include <stdlib.h> /* malloc */
++#include <string.h> /* memcmp */
++
++/* OLSRD includes */
++#include "olsr.h" /* olsr_printf */
++
++/* Plugin includes */
++#include "Bmf.h" /* PLUGIN_NAME */
++#include "Packet.h" /* IFHWADDRLEN */
++
++static struct TMacAddress* DroppedMacAddresses = NULL;
++
++/* Register a MAC address in the drop list. 
++ */
++/* -------------------------------------------------------------------------
++ * Function   : DropMac
++ * Description: Register a MAC address in the drop list
++ * Input      : macStr - MAC address as string
++ * Output     : none
++ * Return     : success (1) or fail (0)
++ * Data Used  : DroppedMacAddresses
++ * Notes      : The registered MAC address will be matched to the source MAC 
++ *              address of incoming multicast packets. If matched, the multicast 
++ *              packet will be silently dropped. 
++ *              The drop list is needed only in lab environments, where hidden
++ *              nodes are simulated by using iptables with the
++ *              -m mac helper and --mac-source option (as in: 
++ *              "iptables -A INPUT -m mac --mac-source 00:0C:29:EE:C9:D0 -j DROP") 
++ *              The drop list is needed because network interfaces in promiscuous 
++ *              mode will still capture packets even if they are specified to 
++ *              be dropped by iptables.
++ * ------------------------------------------------------------------------- */
++int DropMac(const char* macStr)
++{
++  unsigned int mac[6];
++  int n;
++  struct TMacAddress* newMacAddress;
++  int i;
++
++  assert(macStr != NULL);
++
++  n = sscanf(macStr, "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
++  if (n != 6)
++  {
++    olsr_printf(1, "%s: Invalid Ethernet address '%s'\n", PLUGIN_NAME, macStr);
++    return 0;
++  }
++
++  newMacAddress = malloc(sizeof(struct TMacAddress));
++  for (i = 0; i < 6; i++)
++  {
++    newMacAddress->addr[i] = (unsigned char) mac[i];
++  }
++  newMacAddress->next = DroppedMacAddresses;
++  DroppedMacAddresses = newMacAddress;
++
++  return 1;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : IsInDropList
++ * Description: Check if a MAC address is in the drop list
++ * Input      : macAddress
++ * Output     : none
++ * Return     : true (1) or false (0)
++ * Data Used  : DroppedMacAddresses
++ * ------------------------------------------------------------------------- */
++int IsInDropList(const unsigned char* macAddress)
++{
++  struct TMacAddress* ma = DroppedMacAddresses;
++
++  assert(macAddress != NULL);
++
++  while (ma != NULL)
++  {
++    if (memcmp(ma->addr, macAddress, IFHWADDRLEN) == 0) return 1;
++    ma = ma->next;
++  }
++  return 0;
++}
++
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/DropList.h olsrd-0.4.10/lib/bmf/src/DropList.h
+--- olsrd-0.4.10.orig/lib/bmf/src/DropList.h   1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/DropList.h        2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,55 @@
++#ifndef _BMF_DROPLIST_H
++#define _BMF_DROPLIST_H
++
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : DropList.h
++ * Description: List of MAC addresses of hosts from which all packets are dropped.
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++struct TMacAddress
++{
++  unsigned char addr[6];
++  struct TMacAddress* next;
++};
++
++int DropMac(const char* macStr);
++int IsInDropList(const unsigned char* macAddress);
++
++#endif /* _BMF_DROPLIST_H */
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.c olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.c
+--- olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.c  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.c       2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,818 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : NetworkInterfaces.c
++ * Description: Functions to open and close sockets
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++#include "NetworkInterfaces.h"
++
++/* System includes */
++#include <syslog.h> /* syslog() */
++#include <string.h> /* strerror() */
++#include <errno.h> /* errno */
++#include <unistd.h> /* close() */
++#include <sys/ioctl.h> /* ioctl() */
++#include <fcntl.h> /* fcntl() */
++#include <assert.h> /* assert() */
++#include <net/if.h> /* socket(), ifreq, if_indextoname(), if_nametoindex() */
++#include <netinet/in.h> /* htons() */
++#include <linux/if_ether.h> /* ETH_P_ALL */
++#include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
++#include <linux/if_tun.h> /* IFF_TAP */
++
++/* OLSRD includes */
++#include "olsr.h" /* olsr_printf() */
++#include "defs.h" /* olsr_cnf */
++
++/* Plugin includes */
++#include "Packet.h" /* IFHWADDRLEN */
++#include "Bmf.h" /* PLUGIN_NAME */
++
++/* List of network interfaces used by BMF plugin */
++struct TBmfInterface* BmfInterfaces = NULL;
++
++/* File descriptor of EtherTunTap device */
++int EtherTunTapFd = -1;
++
++/* Network interface name of EtherTunTap device. If the name starts with "tun", an
++ * IP tunnel interface will be used. Otherwise, an EtherTap device will be used. */
++const char* EtherTunTapIfName = "tun0"; /* "tap0"; */
++
++/* If the network interface name starts with "tun", an IP tunnel interface will be
++ * used, and this variable will be set to TUN. Otherwise, an EtherTap device will
++ * be used, and this variable will be set to TAP. */
++enum TTunOrTap TunOrTap;
++
++/* -------------------------------------------------------------------------
++ * Function   : CreateCaptureSocket
++ * Description: Create socket for promiscuously capturing multicast IP traffic
++ * Input      : ifname - network interface (e.g. "eth0")
++ * Output     : none
++ * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
++ * Data Used  : none
++ * Notes      : The socket is a raw packet socket, bound to the specified
++ *              network interface
++ * ------------------------------------------------------------------------- */
++static int CreateCaptureSocket(const char* ifName)
++{
++  int ifIndex = if_nametoindex(ifName);
++  struct packet_mreq mreq;
++  struct ifreq req;
++  struct sockaddr_ll bindTo;
++
++  /* Open raw packet socket */
++  int skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
++  if (skfd < 0)
++  {
++    olsr_printf(1, "%s: socket(PF_PACKET) error: %s\n", PLUGIN_NAME, strerror(errno));
++    return -1;
++  }
++
++  /* Set interface to promiscuous mode */
++  memset(&mreq, 0, sizeof(struct packet_mreq));
++  mreq.mr_ifindex = ifIndex;
++  mreq.mr_type = PACKET_MR_PROMISC;
++  if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
++  {
++    olsr_printf(1, "%s: setsockopt(PACKET_MR_PROMISC) error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++
++  /* Get hardware (MAC) address */
++  memset(&req, 0, sizeof(struct ifreq));
++  strncpy(req.ifr_name, ifName, IFNAMSIZ);
++  if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
++  {
++    olsr_printf(1, "%s: error retrieving MAC address: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++   
++  /* Bind the socket to the specified interface */
++  memset(&bindTo, 0, sizeof(bindTo));
++  bindTo.sll_protocol = htons(ETH_P_ALL);
++  bindTo.sll_ifindex = ifIndex;
++  bindTo.sll_family = AF_PACKET;
++  memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
++  bindTo.sll_halen = IFHWADDRLEN;
++    
++  if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
++  {
++    olsr_printf(1, "%s: bind() error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++
++  /* Set socket to blocking operation */
++  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
++  {
++    olsr_printf(1, "%s: fcntl() error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++
++  return skfd;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CreateEncapsulateSocket
++ * Description: Create a socket for sending and receiving encapsulated
++ *              multicast packets
++ * Input      : ifname - network interface (e.g. "eth0")
++ * Output     : none
++ * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
++ * Data Used  : none
++ * Notes      : The socket is an UDP (datagram) over IP socket, bound to the
++ *              specified network interface
++ * ------------------------------------------------------------------------- */
++static int CreateEncapsulateSocket(const char* ifName)
++{
++  int on = 1;
++  struct sockaddr_in bindTo;
++
++  /* Open UDP-IP socket */
++  int skfd = socket(PF_INET, SOCK_DGRAM, 0);
++  if (skfd < 0)
++  {
++    olsr_printf(1, "%s: socket(PF_INET) error: %s\n", PLUGIN_NAME, strerror(errno));
++    return -1;
++  }
++
++  /* Enable sending to broadcast addresses */
++  if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
++  {
++    olsr_printf(1, "%s: setsockopt() error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++      
++  /* Bind to the specific network interfaces indicated by ifName. */
++  /* When using Kernel 2.6 this must happer prior to the port binding! */
++  if (setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
++  {
++    olsr_printf(1, "%s: setsockopt() error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++
++  /* Bind to port */
++  memset(&bindTo, 0, sizeof(bindTo));
++  bindTo.sin_family = AF_INET;
++  bindTo.sin_port = htons(BMF_ENCAP_PORT);
++  bindTo.sin_addr.s_addr = htonl(INADDR_ANY);
++      
++  if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0) 
++  {
++    olsr_printf(1, "%s: bind() error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++
++  /* Set socket to blocking operation */
++  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
++  {
++    olsr_printf(1, "%s: fcntl() error: %s\n", PLUGIN_NAME, strerror(errno));
++    close(skfd);
++    return -1;
++  }
++
++  return skfd;
++}
++
++/* To save the state of the IP spoof filter for the EtherTunTap device */
++static char EthTapSpoofState = '1';
++
++/* -------------------------------------------------------------------------
++ * Function   : DeactivateSpoofFilter
++ * Description: Deactivates the Linux anti-spoofing filter for the tuntap
++ *              interface
++ * Input      : tunTapName - name used for the tuntap interface (e.g. "tun0" or "tap1")
++ * Output     : none
++ * Return     : success (1) or fail (0)
++ * Data Used  : EthTapSpoofState
++ * Notes      : Saves the current filter state for later restoring
++ * ------------------------------------------------------------------------- */
++static int DeactivateSpoofFilter(const char* tunTapName)
++{
++  FILE* procSpoof;
++  char procFile[FILENAME_MAX];
++
++  assert(tunTapName != NULL);
++
++  /* Generate the procfile name */
++  sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", tunTapName);
++
++  procSpoof = fopen(procFile, "r");
++  if (procSpoof == NULL)
++  {
++    fprintf(
++      stderr,
++      "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
++      "Are you using the procfile filesystem?\n"
++      "Does your system support IPv4?\n"
++      "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
++      "filtering is disabled!\n\n",
++      procFile);
++      
++    sleep(3);
++    return 0;
++  }
++
++  EthTapSpoofState = fgetc(procSpoof);
++  fclose(procSpoof);
++
++  procSpoof = fopen(procFile, "w");
++  if (procSpoof == NULL)
++  {
++    fprintf(stderr, "Could not open %s for writing!\n", procFile);
++    fprintf(
++      stderr,
++      "I will continue (in 3 sec) - but you should manually ensure that IP"
++      " spoof filtering is disabled!\n\n");
++    sleep(3);
++    return 0;
++  }
++
++  syslog(LOG_INFO, "Writing \"0\" to %s", procFile);
++  fputs("0", procSpoof);
++
++  fclose(procSpoof);
++
++  return 1;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : RestoreSpoofFilter
++ * Description: Restores the Linux anti-spoofing filter setting for the tuntap
++ *              interface
++ * Input      : tunTapName - name used for the tuntap interface (e.g. "tun0" or "tap1")
++ * Output     : none
++ * Return     : none
++ * Data Used  : EthTapSpoofState
++ * ------------------------------------------------------------------------- */
++static void RestoreSpoofFilter(const char* tunTapName)
++{
++  FILE* procSpoof;
++  char procFile[FILENAME_MAX];
++
++  assert(tunTapName != NULL);
++
++  /* Generate the procfile name */
++  sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", tunTapName);
++
++  procSpoof = fopen(procFile, "w");
++  if (procSpoof == NULL)
++  {
++    fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procFile);
++  }
++  else
++  {
++    syslog(LOG_INFO, "Resetting %s to %c\n", procFile, EthTapSpoofState);
++
++    fputc(EthTapSpoofState, procSpoof);
++    fclose(procSpoof);
++  }
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CreateLocalEtherTunTap
++ * Description: Creates and brings up an EtherTunTap device
++ * Input      : none
++ * Output     : none
++ * Return     : success (0) or fail (<0)
++ * Data Used  : EtherTunTapIfName - name used for the tuntap interface (e.g.
++ *                "tun0" or "tap1")
++ * ------------------------------------------------------------------------- */
++static int CreateLocalEtherTunTap(void)
++{
++  static char* deviceName = "/dev/net/tun";
++  struct ifreq ifreq;
++  int etfd = open(deviceName, O_RDWR);
++  int skfd;
++  int ioctlres = 0;
++
++  if (etfd < 0)
++  {
++    olsr_printf(1, "%s: error opening %s: %s\n", PLUGIN_NAME, deviceName, strerror(errno));
++    return -1;
++  }
++
++  memset(&ifreq, 0, sizeof(ifreq));
++
++  /* Specify either the IFF_TAP flag for Ethernet frames, or the IFF_TUN flag for IP.
++   * Specify IFF_NO_PI for not receiving extra meta packet information. */
++  if (strncmp(EtherTunTapIfName, "tun", 3) == 0)
++  {
++    ifreq.ifr_flags = IFF_TUN;
++    TunOrTap = TT_TUN;
++  }
++  else
++  {
++    ifreq.ifr_flags = IFF_TAP;
++    TunOrTap = TT_TAP;
++  }
++  ifreq.ifr_flags |= IFF_NO_PI;
++
++  strcpy(ifreq.ifr_name, EtherTunTapIfName);
++  if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
++  {
++    olsr_printf(1, "%s: ioctl(TUNSETIFF) error on %s: %s\n", PLUGIN_NAME, deviceName, strerror(errno));
++    close(etfd);
++    return -1;
++  }
++
++  memset(&ifreq, 0, sizeof(ifreq));
++  strcpy(ifreq.ifr_name, EtherTunTapIfName);
++  ifreq.ifr_addr.sa_family = AF_INET;
++  skfd = socket(PF_INET, SOCK_DGRAM, 0);
++  if (skfd < 0)
++  {
++    olsr_printf(1, "%s: socket(PF_INET) error on %s: %s\n", PLUGIN_NAME, deviceName, strerror(errno));
++    close(etfd);
++    return -1;
++  }
++
++  if (ioctl(skfd, SIOCGIFADDR, &ifreq) < 0)
++  {
++    /* EtherTunTap interface does not yet have an IP address.
++     * Give it a dummy IP address "1.2.3.4". */
++    struct sockaddr_in *inaddr = (struct sockaddr_in *)&ifreq.ifr_addr;
++    inet_aton("1.2.3.4", &inaddr->sin_addr);
++    ioctlres = ioctl(skfd, SIOCSIFADDR, &ifreq);
++    if (ioctlres >= 0)
++    {
++      /* Bring EtherTunTap interface up (if not already) */
++      ioctlres = ioctl(skfd, SIOCGIFFLAGS, &ifreq);
++      if (ioctlres >= 0)
++      {
++        ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING);
++        ioctlres = ioctl(skfd, SIOCSIFFLAGS, &ifreq);
++      }
++    }
++
++    if (ioctlres < 0)
++    {
++      /* Any of the three above ioctl() calls failed */
++      olsr_printf(
++        1,
++        "%s: error bringing up EtherTunTap interface \"%s\": %s\n",
++        PLUGIN_NAME,
++        EtherTunTapIfName,
++        strerror(errno));
++
++      close(etfd);
++      close(skfd);
++      return -1;
++    } /* if (ioctlres < 0) */
++  } /* if (ioctl...) */
++
++  /* Set the multicast flag on the interface. TODO: Maybe also set
++   * IFF_ALLMULTI. */
++  memset(&ifreq, 0, sizeof(ifreq));
++  strcpy(ifreq.ifr_name, EtherTunTapIfName);
++  ioctlres = ioctl(skfd, SIOCGIFFLAGS, &ifreq);
++  if (ioctlres >= 0)
++  {
++    ifreq.ifr_flags |= IFF_MULTICAST;
++    ioctlres = ioctl(skfd, SIOCSIFFLAGS, &ifreq);
++  }
++  if (ioctlres < 0)
++  {
++    /* Any of the two above ioctl() calls failed */
++    olsr_printf(
++      1,
++      "%s: error setting multicast flag on EtherTunTap interface \"%s\": %s\n",
++      PLUGIN_NAME,
++      EtherTunTapIfName,
++      strerror(errno));
++    /* Continue anyway */
++  }
++  close(skfd);
++  
++  /* Deactivate IP spoof filter for EtherTunTap device */
++  DeactivateSpoofFilter(ifreq.ifr_name);
++
++  olsr_printf(9, "%s: opened \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
++
++  return etfd;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : IsNullMacAddress
++ * Description: Checks if a MAC address is all-zeroes
++ * Input      : mac - address to check
++ * Output     : none
++ * Return     : true (1) or false (0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++static int IsNullMacAddress(char* mac)
++{
++  int i;
++
++  assert(mac != NULL);
++
++  for (i = 0; i < IFHWADDRLEN; i++)
++  {
++    if (mac[i] != 0) return 0;
++  }
++  return 1;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CreateInterface
++ * Description: Create a new TBmfInterface object and adds it to the global
++ *              BmfInterfaces list
++ * Input      : ifName - name of the network interface (e.g. "eth0")
++ * Output     : none
++ * Return     : the number of opened sockets
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++static int CreateInterface(
++  const char* ifName,
++  struct interface* olsrIntf)
++{
++  int capturingSkfd;
++  int encapsulatingSkfd = -1;
++  struct ifreq ifr;
++  int nOpened = 0;
++  struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface));
++
++  assert(ifName != NULL);
++
++  if (newIf == NULL)
++  {
++    return 0;
++  }
++
++  if (olsrIntf != NULL)
++  {
++    /* On OLSR interfaces, create socket for encapsulating and forwarding 
++     * multicast packets */
++    encapsulatingSkfd = CreateEncapsulateSocket(ifName);
++    if (encapsulatingSkfd < 0)
++    {
++      free(newIf);
++      return 0;
++    }
++    nOpened++;
++  }
++
++  /* On all interfaces, create socket for capturing and sending multicast packets */
++  capturingSkfd = CreateCaptureSocket(ifName);
++  if (capturingSkfd < 0)
++  {
++    close(encapsulatingSkfd);
++    free(newIf);
++    return 0;
++  }
++  nOpened++;
++
++  /* Retrieve the MAC address */
++  memset(&ifr, 0, sizeof(struct ifreq));
++  strncpy(ifr.ifr_name, ifName, IFNAMSIZ); 
++  if (ioctl(capturingSkfd, SIOCGIFHWADDR, &ifr) < 0)
++  {
++    olsr_printf(
++      1,
++      "%s: ioctl(SIOCGIFHWADDR) error for device \"%s\": %s\n",
++      PLUGIN_NAME,
++      ifName,
++      strerror(errno));
++    close(capturingSkfd);
++    close(encapsulatingSkfd);
++    free(newIf);
++    return 0;
++  }
++
++  /* If null-interface, cancel the whole creation and return NULL */
++  if (IsNullMacAddress(ifr.ifr_hwaddr.sa_data))
++  {
++    close(capturingSkfd);
++    close(encapsulatingSkfd);
++    free(newIf);
++    return 0;
++  }
++
++  newIf->capturingSkfd = capturingSkfd;
++  newIf->encapsulatingSkfd = encapsulatingSkfd;
++  memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
++  memcpy(newIf->ifName, ifName, IFNAMSIZ);
++  newIf->olsrIntf = olsrIntf;
++  if (olsrIntf != NULL)
++  {
++    /* Copy broadcast address from OLSR interface */
++    newIf->broadAddr = olsrIntf->int_broadaddr;
++  }
++  else
++  {
++    /* Non-OLSR interface: retrieve the IP broadcast address */
++    memset(&ifr, 0, sizeof(struct ifreq));
++    strncpy(ifr.ifr_name, ifName, IFNAMSIZ); 
++    if (ioctl(capturingSkfd, SIOCGIFBRDADDR, &ifr) < 0) 
++    {
++      olsr_printf(
++        1,
++        "%s: ioctl(SIOCGIFBRDADDR) error for device \"%s\": %s\n",
++        PLUGIN_NAME,
++        ifName,
++        strerror(errno));
++
++      ((struct sockaddr_in*)&newIf->broadAddr)->sin_addr.s_addr = inet_addr("0.0.0.0");
++        }
++        else
++        {
++      newIf->broadAddr = ifr.ifr_broadaddr;
++    }
++  }
++
++  memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
++  newIf->nextFragmentHistoryEntry = 0;
++  
++  newIf->next = BmfInterfaces;
++  BmfInterfaces = newIf;
++
++  OLSR_PRINTF(
++    9,
++    "%s: opened %s interface \"%s\"\n",
++    PLUGIN_NAME_SHORT,
++    olsrIntf != NULL ? "OLSR" : "non-OLSR",
++    ifName);
++
++  return nOpened;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CreateBmfNetworkInterfaces
++ * Description: Create a list of TBmfInterface objects, one for each network
++ *              interface on which BMF runs
++ * Input      : skipThisIntf - network interface to skip, if seen
++ * Output     : none
++ * Return     : success (0) or fail (<0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
++{
++  int skfd;
++  struct ifconf ifc;
++  int numreqs = 30;
++  struct ifreq* ifr;
++  int n;
++  int nOpened = 0;
++
++  EtherTunTapFd = CreateLocalEtherTunTap();
++  if (EtherTunTapFd >=0)
++  {
++    nOpened++;
++  }
++
++  skfd = socket(PF_INET, SOCK_DGRAM, 0);
++  if (skfd < 0)
++  {
++    olsr_printf(
++      1,
++      "%s: no inet socket available to retrieve interface list: %s\n",
++      PLUGIN_NAME,
++      strerror(errno));
++    return -1;
++  }
++
++  /* Retrieve the network interface configuration list */
++  ifc.ifc_buf = NULL;
++  for (;;)
++  {
++    ifc.ifc_len = sizeof(struct ifreq) * numreqs;
++    ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
++
++    if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
++    {
++      olsr_printf(1, "%s: ioctl(SIOCGIFCONF) error: %s\n", PLUGIN_NAME, strerror(errno));
++
++      close(skfd);
++      free(ifc.ifc_buf);
++      return -1;
++    }
++    if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs)
++    {
++      /* Assume it overflowed; double the space and try again */
++      numreqs *= 2;
++      assert(numreqs < 1024);
++      continue; /* for (;;) */
++    }
++    break; /* for (;;) */
++  } /* for (;;) */
++
++  close(skfd);
++
++  /* For each item in the interface configuration list... */
++  ifr = ifc.ifc_req;
++  for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++)
++  {
++    struct interface* olsrIntf;
++
++    /* ...find the OLSR interface structure, if any */
++    union olsr_ip_addr ipAddr;
++    COPY_IP(&ipAddr, &((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr.s_addr);
++    olsrIntf = if_ifwithaddr(&ipAddr);
++
++    if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
++    {
++      continue; /* for (n = ...) */
++    }
++
++    if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
++    {
++      /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
++       * interface in the BMF plugin parameter list */
++      continue; /* for (n = ...) */
++    }
++
++    nOpened += CreateInterface(ifr->ifr_name, olsrIntf);
++
++  } /* for (n = ...) */
++
++  free(ifc.ifc_buf);
++  
++  if (BmfInterfaces == NULL)
++  {
++    olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
++    return -1;
++  }
++
++  olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
++
++  return 0;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : AddInterface
++ * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
++ *              network interfaces
++ * Input      : newIntf - network interface to add
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++void AddInterface(struct interface* newIntf)
++{
++  int nOpened;
++
++  assert(newIntf != NULL);
++
++  nOpened = CreateInterface(newIntf->int_name, newIntf);
++
++  olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CloseBmfNetworkInterfaces
++ * Description: Closes every socket on each network interface used by BMF
++ * Input      : newIntf - network interface to add
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * Notes      : Closes
++ *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
++ *              - for each BMF-enabled interface, the socket used for
++ *                capturing multicast packets
++ *              - for each OLSR-enabled interface, the socket used for
++ *                encapsulating packets
++ *              Also restores the network state to the situation before BMF
++ *              was started.
++ * ------------------------------------------------------------------------- */
++void CloseBmfNetworkInterfaces()
++{
++  int nClosed = 0;
++  
++  /* Close all opened sockets */
++  struct TBmfInterface* nextBmfIf = BmfInterfaces;
++  while (nextBmfIf != NULL)
++  {
++    struct TBmfInterface* bmfIf = nextBmfIf;
++    nextBmfIf = bmfIf->next;
++
++    if (bmfIf->capturingSkfd >= 0)
++    {
++      close(bmfIf->capturingSkfd);
++      nClosed++;
++    }
++    if (bmfIf->encapsulatingSkfd >= 0) 
++    {
++      close(bmfIf->encapsulatingSkfd);
++      nClosed++;
++    }
++
++    OLSR_PRINTF(
++      9,
++      "%s: closed %s interface \"%s\"\n", 
++      PLUGIN_NAME_SHORT,
++      bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
++      bmfIf->ifName);
++
++    free(bmfIf);
++  }
++  
++  if (EtherTunTapFd >= 0)
++  {
++    /* Restore IP spoof filter for EtherTunTap device */
++    RestoreSpoofFilter(EtherTunTapIfName);
++
++    close(EtherTunTapFd);
++    nClosed++;
++
++    OLSR_PRINTF(9, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
++  }
++
++  BmfInterfaces = NULL;
++
++  olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME, nClosed);
++}
++
++#define MAX_NON_OLSR_IFS 10
++static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
++static int nNonOlsrIfs = 0;
++
++/* -------------------------------------------------------------------------
++ * Function   : AddNonOlsrBmfIf
++ * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
++ *              network interfaces
++ * Input      : ifName - network interface (e.g. "eth0")
++ * Output     : none
++ * Return     : success (1) or fail (0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int AddNonOlsrBmfIf(const char* ifName)
++{
++  assert(ifName != NULL);
++
++  if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
++  {
++    olsr_printf(
++      1,
++      "%s: too many non-OLSR interfaces specified, maximum is %d\n",
++      PLUGIN_NAME,
++      MAX_NON_OLSR_IFS);
++    return 0;
++  }
++
++  strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ);
++  nNonOlsrIfs++;
++  return 1;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : IsNonOlsrBmfIf
++ * Description: Checks if a network interface is OLSR-enabled
++ * Input      : ifName - network interface (e.g. "eth0")
++ * Output     : none
++ * Return     : true (1) or false (0)
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int IsNonOlsrBmfIf(const char* ifName)
++{
++  int i;
++
++  assert(ifName != NULL);
++
++  for (i = 0; i < nNonOlsrIfs; i++)
++  {
++    if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
++  }
++  return 0;
++}
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.h olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.h
+--- olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.h  1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.h       2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,106 @@
++#ifndef _BMF_NETWORKINTERFACES_H
++#define _BMF_NETWORKINTERFACES_H
++
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : NetworkInterfaces.h
++ * Description: Functions to open and close sockets
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++/* System includes */
++#include <netinet/in.h> /* struct in_addr */
++
++/* Plugin includes */
++#include "Packet.h" /* IFHWADDRLEN */
++
++
++struct TBmfInterface
++{
++  /* File descriptor of raw packet socket, used for capturing multicast packets */
++  int capturingSkfd;
++
++  /* File descriptor of UDP (datagram) socket for encapsulated multicast packets. 
++   * Only used for OLSR-enabled interfaces; set to -1 if interface is not OLSR-enabled. */
++  int encapsulatingSkfd;
++
++  unsigned char macAddr[IFHWADDRLEN];
++
++  char ifName[IFNAMSIZ];
++
++  /* OLSRs idea of this network interface. NULL if this interface is not
++   * OLSR-enabled. */
++  struct interface* olsrIntf;
++
++  /* Kernels index of this network interface */
++  int ifIndex;
++
++  /* Broadcast address of this network interface */
++  struct sockaddr broadAddr;
++
++  #define FRAGMENT_HISTORY_SIZE 10
++  struct TFragmentHistory
++  {
++    u_int16_t ipId;
++    u_int8_t ipProto;
++    struct in_addr ipSrc;
++    struct in_addr ipDst;
++  } fragmentHistory [FRAGMENT_HISTORY_SIZE];
++
++  int nextFragmentHistoryEntry;
++
++  /* Next element in list */
++  struct TBmfInterface* next; 
++};
++
++extern struct TBmfInterface* BmfInterfaces;
++
++extern int EtherTunTapFd;
++
++extern const char* EtherTunTapIfName;
++
++enum TTunOrTap { TT_TUN = 0, TT_TAP };
++extern enum TTunOrTap TunOrTap;
++
++int CreateBmfNetworkInterfaces(struct interface* skipThisIntf);
++void AddInterface(struct interface* newIntf);
++void CloseBmfNetworkInterfaces(void);
++int AddNonOlsrBmfIf(const char* ifName);
++int IsNonOlsrBmfIf(const char* ifName);
++
++#endif /* _BMF_NETWORKINTERFACES_H */
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/olsrd_plugin.c olsrd-0.4.10/lib/bmf/src/olsrd_plugin.c
+--- olsrd-0.4.10.orig/lib/bmf/src/olsrd_plugin.c       1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/olsrd_plugin.c    2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,166 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : olsrd_plugin.c
++ * Description: Interface to the OLSRD plugin system
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++/* System includes */
++#include <assert.h> /* assert() */
++#include <stdio.h>
++
++/* OLSRD includes */
++#include "olsrd_plugin.h"
++#include "defs.h" /* olsr_u8_t, olsr_cnf */
++#include "scheduler.h" /* olsr_register_scheduler_event */
++
++/* BMF includes */
++#include "Bmf.h" /* InitBmf(), CloseBmf(), RegisterBmfParameter() */
++#include "PacketHistory.h" /* InitPacketHistory() */
++
++static void __attribute__ ((constructor)) my_init(void);
++static void __attribute__ ((destructor)) my_fini(void);
++
++void olsr_plugin_exit(void);
++
++/* -------------------------------------------------------------------------
++ * Function   : olsrd_plugin_interface_version
++ * Description: Plugin interface version
++ * Input      : none
++ * Output     : none
++ * Return     : BMF plugin interface version number
++ * Data Used  : none
++ * Notes      : Called by main OLSRD (olsr_load_dl) to check plugin interface
++ *              version
++ * ------------------------------------------------------------------------- */
++int olsrd_plugin_interface_version()
++{
++  return OLSRD_PLUGIN_INTERFACE_VERSION;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : olsrd_plugin_init
++ * Description: Plugin initialisation
++ * Input      : none
++ * Output     : none
++ * Return     : fail (0) or success (1)
++ * Data Used  : olsr_cnf
++ * Notes      : Called by main OLSRD (init_olsr_plugin) to initialize plugin
++ * ------------------------------------------------------------------------- */
++int olsrd_plugin_init()
++{
++  /* Check validity */
++  if (olsr_cnf->ip_version != AF_INET)
++  {
++    fprintf(stderr, PLUGIN_NAME ": This plugin only supports IPv4!\n");
++    return 0;
++  }
++
++  /* Clear the packet history */
++  InitPacketHistory();
++
++  /* Register ifchange function */
++  add_ifchgf(&InterfaceChange);
++
++  /* Register the duplicate registration pruning process */
++  olsr_register_scheduler_event(&PrunePacketHistory, NULL, 3.0, 2.0, NULL);
++
++  return InitBmf(NULL);
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : olsr_plugin_exit
++ * Description: Plugin cleanup
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * Notes      : Called by my_fini() at unload of shared object
++ * ------------------------------------------------------------------------- */
++void olsr_plugin_exit()
++{
++  CloseBmf();
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : olsrd_plugin_register_param
++ * Description: Register parameters from config file
++ * Input      : key - the parameter name
++ *              value - the parameter value
++ * Output     : none
++ * Return     : fatal error (<0), minor error (0) or success (>0)
++ * Data Used  : none
++ * Notes      : Called by main OLSR (init_olsr_plugin) for all plugin parameters
++ * ------------------------------------------------------------------------- */
++int olsrd_plugin_register_param(char* key, char* value)
++{
++  assert(key != NULL && value != NULL);
++
++  return RegisterBmfParameter(key, value);
++}
++ 
++/* -------------------------------------------------------------------------
++ * Function   : my_init
++ * Description: Plugin constructor
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * Notes      : Called at load of shared object
++ * ------------------------------------------------------------------------- */
++static void my_init()
++{
++  /* Print plugin info to stdout */
++  printf("%s\n", MOD_DESC);
++
++  return;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : my_fini
++ * Description: Plugin destructor
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * Notes      : Called at unload of shared object
++ * ------------------------------------------------------------------------- */
++static void my_fini()
++{
++  olsr_plugin_exit();
++}
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Packet.c olsrd-0.4.10/lib/bmf/src/Packet.c
+--- olsrd-0.4.10.orig/lib/bmf/src/Packet.c     1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Packet.c  2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,133 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : Packet.c
++ * Description: BMF and IP packet processing functions
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++#include "Packet.h"
++
++/* System includes */
++#include <assert.h> /* assert() */
++#include <sys/types.h> /* u_int32_t */
++#include <netinet/in.h> /* ntohs(), htons() */
++#include <linux/ip.h>
++
++/* -------------------------------------------------------------------------
++ * Function   : GetIpTtl
++ * Description: Retrieve the TTL (Time To Live) value from the IP header of
++ *              the passed ethernet-IP packet
++ * Input      : buffer - the ethernet-IP packet
++ * Output     : none
++ * Return     : TTL value
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++int GetIpTtl(unsigned char* buffer)
++{
++  struct iphdr* iph;
++
++  assert(buffer != NULL);
++
++  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
++  return iph->ttl;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : SaveTtlAndChecksum
++ * Description: Save the TTL (Time To Live) value and IP checksum as found in
++ *              the IP header of the passed ethernet-IP packet
++ * Input      : buffer - the ethernet-IP packet
++ * Output     : sttl - the TTL and checksum values
++ * Return     : none
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++void SaveTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl)
++{
++  struct iphdr* iph;
++
++  assert(buffer != NULL && sttl != NULL);
++
++  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
++  sttl->ttl = iph->ttl;
++  sttl->check = ntohs(iph->check);
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : RestoreTtlAndChecksum
++ * Description: Restore the TTL (Time To Live) value and IP checksum in
++ *              the IP header of the passed ethernet-IP packet
++ * Input      : buffer - the ethernet-IP packet
++ *              sttl - the TTL and checksum values
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++void RestoreTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl)
++{
++  struct iphdr* iph;
++
++  assert(buffer != NULL && sttl != NULL);
++
++  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
++  iph->ttl = sttl->ttl;
++  iph->check = htons(sttl->check);
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : DecreaseTtlAndUpdateHeaderChecksum
++ * Description: For an IP packet, decrement the TTL value and update the IP header
++ *              checksum accordingly.
++ * Input      : buffer - the ethernet-IP packet
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * Notes      : See also RFC1141
++ * ------------------------------------------------------------------------- */
++void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* buffer)
++{
++  struct iphdr* iph;
++  u_int32_t sum;
++
++  assert(buffer != NULL);
++
++  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
++
++  iph->ttl--; /* decrement ttl */
++  sum = ntohs(iph->check) + 0x100; /* increment checksum high byte */
++  iph->check = htons(sum + (sum>>16)); /* add carry */
++}
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Packet.h olsrd-0.4.10/lib/bmf/src/Packet.h
+--- olsrd-0.4.10.orig/lib/bmf/src/Packet.h     1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Packet.h  2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,85 @@
++#ifndef _BMF_PACKET_H
++#define _BMF_PACKET_H
++
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : Packet.h
++ * Description: BMF and IP packet processing functions
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++/* System includes */
++#include <net/if.h> /* IFNAMSIZ, IFHWADDRLEN */
++#include <sys/types.h> /* u_int8_t, u_int16_t */
++
++/* Offsets and sizes into IP-ethernet packets */
++#define IPV4_ADDR_SIZE 4
++#define ETH_TYPE_OFFSET (2*IFHWADDRLEN)
++#define ETH_TYPE_LEN 2
++#define IP_HDR_OFFSET (ETH_TYPE_OFFSET + ETH_TYPE_LEN)
++#define IPV4_OFFSET_SRCIP 12
++#define IPV4_OFFSET_DSTIP (IPV4_OFFSET_SRCIP + IPV4_ADDR_SIZE)
++
++#define IPV4_TYPE 0x0800
++
++/* BMF-encapsulated packets are Ethernet-IP-UDP packets, which start
++ * with a 16-bytes BMF header (struct TEncapHeader), followed by the
++ * encapsulated Ethernet-IP packet itself */
++
++struct TEncapHeader
++{
++  u_int32_t crc32;
++  u_int32_t futureExpansion1;
++  u_int32_t futureExpansion2;
++  u_int32_t futureExpansion3;
++} __attribute__((__packed__));
++
++#define       ENCAP_HDR_LEN sizeof(struct TEncapHeader)
++
++struct TSaveTtl
++{
++  u_int8_t ttl;
++  u_int16_t check;
++} __attribute__((__packed__));
++
++int GetIpTtl(unsigned char* buffer);
++void SaveTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl);
++void RestoreTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl);
++void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* buffer);
++
++#endif /* _BMF_PACKET_H */
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.c olsrd-0.4.10/lib/bmf/src/PacketHistory.c
+--- olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.c      1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/PacketHistory.c   2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,293 @@
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : PacketHistory.c
++ * Description: Functions for keeping and accessing the history of processed
++ *              multicast IP packets.
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++#include "PacketHistory.h"
++
++/* System includes */
++#include <assert.h> /* assert() */
++#include <sys/types.h> /* u_int16_t, u_int32_t */
++#include <string.h> /* memset */
++
++/* OLSRD includes */
++#include "olsr.h" /* olsr_printf */
++
++/* Plugin includes */
++#include "Packet.h"
++
++static u_int32_t PacketHistory[HISTORY_TABLE_SIZE];
++
++#define CRC_UPTO_NBYTES 256
++
++/* -------------------------------------------------------------------------
++ * Function   : CalcCrcCcitt
++ * Description: Calculate 16-bits CRC according to CRC-CCITT specification
++ * Input      : buffer - the bytes to calculate the CRC value over
++ *              len - the number of bytes to calculate the CRC value over
++ * Output     : none
++ * Return     : CRC-16 value
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++static u_int16_t CalcCrcCcitt(unsigned char* buffer, ssize_t len)
++{
++  /* Initial value of 0xFFFF should be 0x1D0F according to
++   * www.joegeluso.com/software/articles/ccitt.htm */
++  u_int16_t crc = 0xFFFF; 
++  int i;
++
++  assert(buffer != NULL);
++
++  for (i = 0; i < len; i++)
++  {
++    crc  = (unsigned char)(crc >> 8) | (crc << 8);
++    crc ^= buffer[i];
++    crc ^= (unsigned char)(crc & 0xff) >> 4;
++    crc ^= (crc << 8) << 4;
++    crc ^= ((crc & 0xff) << 4) << 1;
++  }
++  return crc;
++}
++
++
++/* -------------------------------------------------------------------------
++ * Function   : GenerateCrc32Table
++ * Description: Generate the table of CRC remainders for all possible bytes,
++ *              according to CRC-32-IEEE 802.3
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++#define CRC32_POLYNOMIAL 0xedb88320UL /* bit-inverse of 0x04c11db7UL */
++
++static unsigned long CrcTable[256];
++
++static void GenerateCrc32Table(void)
++{
++  int i, j;
++  u_int32_t crc;
++  for (i = 0; i < 256; i++)
++  {
++    crc = (u_int32_t) i;
++    for (j = 0; j < 8; j++)
++    {
++      if (crc & 1)
++      {
++        crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
++      }
++      else
++      {
++        crc = (crc >> 1);
++      }
++    }
++    CrcTable[i] = crc;
++  }
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CalcCrc32
++ * Description: Calculate CRC-32 according to CRC-32-IEEE 802.3
++ * Input      : buffer - the bytes to calculate the CRC value over
++ *              len - the number of bytes to calculate the CRC value over
++ * Output     : none
++ * Return     : CRC-32 value
++ * Data Used  : none
++ * ------------------------------------------------------------------------- */
++static u_int32_t CalcCrc32(unsigned char* buffer, ssize_t len)
++{
++  int i, j;
++  u_int32_t crc = 0xffffffffUL;
++  for (i = 0; i < len; i++)
++  {
++    /* Skip IP header checksum; we want to avoid as much as possible
++     * calculating a checksum over data containing a checksum */
++  //  if (i >= 12 && i < 14) continue;
++
++    j = ((int) (crc & 0xFF) ^ *buffer++);
++    crc = (crc >> 8) ^ CrcTable[j];
++  }
++  return crc ^ 0xffffffffUL;
++}
++
++/*  */
++/* -------------------------------------------------------------------------
++ * Function   : PacketCrc32
++ * Description: Calculates the CRC-32 value for an Ethernet packet
++ * Input      : ethPkt - the Ethernet packet
++ *              len - the number of octets in the Ethernet packet
++ * Output     : none
++ * Return     : 32-bits hash value
++ * Data Used  : none
++ * Notes      : The source and destination MAC address are not taken into account
++ *              in the CRC calculation.
++ * ------------------------------------------------------------------------- */
++u_int32_t PacketCrc32(unsigned char* ethPkt, ssize_t len)
++{
++  assert(ethPkt != NULL);
++  assert(len > ETH_TYPE_OFFSET);
++
++  /* Start CRC calculation at ethertype; skip source and destination MAC 
++   * addresses. Clip number of bytes over which CRC is calculated to prevent
++   * long packets from possibly claiming too much CPU resources. */
++  ssize_t nCrcBytes = len - ETH_TYPE_OFFSET;
++  if (nCrcBytes > CRC_UPTO_NBYTES)
++  {
++    nCrcBytes = CRC_UPTO_NBYTES;
++  }
++  return CalcCrc32(ethPkt + ETH_TYPE_OFFSET, nCrcBytes);
++}
++
++/* Calculates a 16-bit hash value from a 32-bit hash value */
++u_int16_t Hash16(u_int32_t hash32)
++{
++  return ((hash32 >> 16) + hash32) & 0xFFFFU;
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : InitPacketHistory
++ * Description: Initialize the packet history table and CRC-32 table
++ * Input      : none
++ * Output     : none
++ * Return     : none
++ * Data Used  : PacketHistory
++ * ------------------------------------------------------------------------- */
++void InitPacketHistory()
++{
++  memset(PacketHistory, 0, sizeof(PacketHistory));
++  GenerateCrc32Table();
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : MarkRecentPacket
++ * Description: Record the fact that this packet was seen recently
++ * Input      : hash16
++ * Output     : none
++ * Return     : none
++ * Data Used  : PacketHistory
++ * ------------------------------------------------------------------------- */
++void MarkRecentPacket(u_int16_t hash16)
++{
++  u_int32_t index;
++  uint offset;
++
++  index = hash16 / NPACKETS_PER_ENTRY;
++  assert(index < HISTORY_TABLE_SIZE);
++
++  offset = (hash16 % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET;
++  assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET);
++
++  /* Mark as "seen recently" */
++  PacketHistory[index] = PacketHistory[index] | (0x3u << offset);
++}
++
++/* -------------------------------------------------------------------------
++ * Function   : CheckAndMarkRecentPacket
++ * Description: Check if this packet was seen recently, then record the fact
++ *              that this packet was seen recently.
++ * Input      : hash16
++ * Output     : none
++ * Return     : not recently seen (0), recently seen (1)
++ * Data Used  : PacketHistory
++ * ------------------------------------------------------------------------- */
++int CheckAndMarkRecentPacket(u_int16_t hash16)
++{
++  u_int32_t index;
++  uint offset;
++  u_int32_t bitMask;
++  int result;
++
++  index = hash16 / NPACKETS_PER_ENTRY;
++  assert(index < HISTORY_TABLE_SIZE);
++
++  offset =  (hash16 % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET;
++  assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET);
++
++  bitMask = 0x1u << offset;
++  result = ((PacketHistory[index] & bitMask) == bitMask);
++  
++  /* Always mark as "seen recently" */
++  PacketHistory[index] = PacketHistory[index] | (0x3u << offset);
++
++  return result;
++}
++  
++/* -------------------------------------------------------------------------
++ * Function   : PrunePacketHistory
++ * Description: Prune the packet history table.
++ * Input      : useless - not used
++ * Output     : none
++ * Return     : none
++ * Data Used  : PacketHistory
++ * ------------------------------------------------------------------------- */
++void PrunePacketHistory(void* useless)
++{
++  uint i;
++  for (i = 0; i < HISTORY_TABLE_SIZE; i++)
++  {
++    if (PacketHistory[i] > 0)
++    {
++      uint j;
++      for (j = 0; j < NPACKETS_PER_ENTRY; j++)
++      {
++        uint offset = j * NBITS_PER_PACKET;
++
++        u_int32_t bitMask = 0x3u << offset;
++        u_int32_t bitsSeenRecenty = 0x3u << offset;
++        u_int32_t bitsTimingOut = 0x1u << offset;
++
++        /* 10 should never occur */
++        assert ((PacketHistory[i] & bitMask) != (0x2u << offset));
++        
++        if ((PacketHistory[i] & bitMask) == bitsSeenRecenty)
++        {
++          /* 11 -> 01 */
++          PacketHistory[i] &= ~bitMask | bitsTimingOut;
++        }
++        else if ((PacketHistory[i] & bitMask) == bitsTimingOut)
++        {
++          /* 01 -> 00 */
++          PacketHistory[i] &= ~bitMask;
++        }
++      } /* for (j = ...) */
++    } /* if (PacketHistory[i] > 0) */
++  } /* for (i = ...) */
++}
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.h olsrd-0.4.10/lib/bmf/src/PacketHistory.h
+--- olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.h      1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/PacketHistory.h   2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,67 @@
++#ifndef _BMF_PACKETHISTORY_H
++#define _BMF_PACKETHISTORY_H
++
++/*
++ * OLSR Basic Multicast Forwarding (BMF) plugin.
++ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.
++ * Written by Erik Tromp.
++ * 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 Thales, BMF 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.
++ */
++
++/* -------------------------------------------------------------------------
++ * File       : PacketHistory.h
++ * Description: Functions for keeping and accessing the history of processed
++ *              multicast IP packets.
++ * Created    : 29 Jun 2006
++ *
++ * $Id$ 
++ *
++ * $Log$
++ * ------------------------------------------------------------------------- */
++
++#include <sys/types.h> /* ssize_t */
++
++/* 2 bits per seen packet: 
++ * 11 = "seen recently",
++ * 01 = "timing out"
++ * 00 = "not seen recently"
++ * Note that 10 is unused */
++#define NBITS_PER_PACKET 2
++#define NBITS_IN_UINT16 (sizeof(u_int16_t) * 8)
++#define NBITS_IN_UINT32 (sizeof(u_int32_t) * 8)
++#define NPACKETS_PER_ENTRY (NBITS_IN_UINT32 / NBITS_PER_PACKET)
++#define HISTORY_TABLE_SIZE ((1 << NBITS_IN_UINT16) / NPACKETS_PER_ENTRY)
++
++void InitPacketHistory(void);
++u_int32_t PacketCrc32(unsigned char* ethPkt, ssize_t len);
++u_int16_t Hash16(u_int32_t hash32);
++void MarkRecentPacket(u_int16_t hash16);
++int CheckAndMarkRecentPacket(u_int16_t hash16);
++void PrunePacketHistory(void*);
++
++#endif /* _BMF_PACKETHISTORY_H */
+diff -Nur olsrd-0.4.10.orig/lib/bmf/version-script.txt olsrd-0.4.10/lib/bmf/version-script.txt
+--- olsrd-0.4.10.orig/lib/bmf/version-script.txt       1970-01-01 01:00:00.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/version-script.txt    2006-12-01 08:26:58.000000000 +0100
+@@ -0,0 +1,10 @@
++VERS_1.0
++{
++  global:
++    olsrd_plugin_interface_version;
++    olsrd_plugin_register_param;
++    olsrd_plugin_init;
++
++  local:
++    *;
++};
+diff -Nur olsrd-0.4.10.orig/Makefile olsrd-0.4.10/Makefile
+--- olsrd-0.4.10.orig/Makefile 2006-12-01 08:26:58.000000000 +0100
++++ olsrd-0.4.10/Makefile      2006-12-01 08:26:58.000000000 +0100
+@@ -164,5 +164,10 @@
+               $(MAKE) -C lib/pgraph 
+               $(MAKE) -C lib/pgraph install 
++bmf:
++              $(MAKE) -C lib/bmf clean
++              $(MAKE) -C lib/bmf 
++              $(MAKE) -C lib/bmf install 
++
+ build_all:    cfgparser olsrd libs
+ install_all:  install install_libs
diff --git a/net/olsrd/patches/180-olsrd-bmf-fixes.patch b/net/olsrd/patches/180-olsrd-bmf-fixes.patch
new file mode 100644 (file)
index 0000000..4ff1627
--- /dev/null
@@ -0,0 +1,336 @@
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Bmf.c olsrd-0.4.10/lib/bmf/src/Bmf.c
+--- olsrd-0.4.10.orig/lib/bmf/src/Bmf.c        2006-11-29 12:45:19.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Bmf.c     2006-11-29 12:47:49.000000000 +0100
+@@ -114,7 +114,15 @@
+   /* Only forward multicast or local broadcast packets */
+   COPY_IP(&destIp, &ipData->ip_dst);
+-  if (! IsMulticast(&destIp) && ! IsLocalBroadcast(&destIp, intf))
++  if (! IsMulticast(&destIp)
++#ifdef SVEN_OLA_DISABLED
++     /* 
++      * Sven-Ola@gmx.de: In a bigger mesh, there are a lot of
++      * accidential bcast sources.  Disabled to save bandwidth 
++      */
++     && ! IsLocalBroadcast(&destIp, intf)
++#endif
++  )
+   {
+     return;
+   }
+@@ -128,9 +136,10 @@
+   COPY_IP(&srcIp, &ipData->ip_src);
+   olsr_printf(
+     9,
+-    "%s: pkt of %d bytes incoming on \"%s\": %s->%s\n",
++    "%s: pkt of %d bytes ttl=%d incoming on \"%s\": %s->%s\n",
+     PLUGIN_NAME_SHORT,
+     ethPktLen,
++    GetIpTtl(ethPkt),
+     intf->ifName,
+     olsr_ip_to_string(&srcIp),
+     olsr_ip_to_string(&destIp));
+@@ -191,6 +200,7 @@
+   struct TEncapHeader* encapHdr = (struct TEncapHeader*) buffer;
+   memset (encapHdr, 0, ENCAP_HDR_LEN);
+   encapHdr->crc32 = htonl(crc32);
++  encapHdr->encapttl = GetIpTtl(ethPkt);
+   /* If this packet is captured on an OLSR interface from an OLSR neighbor,
+    * check with OLSR if I am MPR for that neighbor */
+@@ -248,7 +258,7 @@
+       /* If the TTL is <= 0, do not forward this packet */
+       if (GetIpTtl(ethPkt) <= 0)
+       {
+-        OLSR_PRINTF(
++        olsr_printf(
+           9,
+           "%s: --> not forwarding on \"%s\": TTL=0\n",
+           PLUGIN_NAME_SHORT,
+@@ -272,10 +282,11 @@
+         }
+         else
+         {
+-          OLSR_PRINTF(
++          olsr_printf(
+             9,
+-            "%s: --> forwarded to \"%s\"\n",
++            "%s: --> forwarded(capt) ttl=%d to \"%s\"\n",
+             PLUGIN_NAME_SHORT,
++            GetIpTtl(ethPkt),
+             fwIntf->ifName);
+         }
+       }
+@@ -291,6 +302,7 @@
+     if (isToOlsrIntf && !iAmNotMpr)
+     {
+       int nBytesWritten;
++      unsigned char ttl;
+       /* Change encapsulated source MAC address to that of sending interface */
+       memcpy(ethPkt + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
+@@ -298,6 +310,10 @@
+       /* Destination address is local broadcast */
+       encapDest.sin_addr.s_addr = ((struct sockaddr_in*)&fwIntf->olsrIntf->int_broadaddr)->sin_addr.s_addr;
++      /* SVEN_OLA: Normal TTL of this socket will be 64 if unset */
++      ttl = GetIpTtl(ethPkt);
++      if (0 <= (nBytesWritten = setsockopt(fwIntf->encapsulatingSkfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))))
++
+       nBytesWritten = sendto(
+         fwIntf->encapsulatingSkfd,
+         buffer,
+@@ -306,6 +322,18 @@
+         (struct sockaddr*) &encapDest,
+         sizeof(encapDest));                   
++      /*
++       * Sven-Ola@gmx.de: Very primitive testing of forward error correction
++       */
++      if (nBytesWritten == len)
++        nBytesWritten = sendto(
++          fwIntf->encapsulatingSkfd,
++          buffer,
++          len,
++          MSG_DONTROUTE,
++          (struct sockaddr*) &encapDest,
++          sizeof(encapDest));
++
+       if (nBytesWritten != len)
+       {
+         olsr_printf(
+@@ -318,10 +346,11 @@
+       }
+       else
+       {
+-        OLSR_PRINTF(
++        olsr_printf(
+           9,
+-          "%s: --> encapsulated and forwarded to \"%s\"\n",
++          "%s: --> encapsulated and forwarded ttl=%d to \"%s\"\n",
+           PLUGIN_NAME_SHORT,
++          GetIpTtl(ethPkt),
+           fwIntf->ifName);
+       } /* if (nBytesWritten != len) */
+     } /* else if (isToOlsrIntf && !iAmNotMpr) */
+@@ -329,7 +358,7 @@
+     else /* (!isFromOlsrIntf || isToOlsrIntf) && (!isToOlsrIntf || iAmNotMpr) */
+     if (!isFromOlsrIntf && !isToOlsrIntf)
+     {
+-      OLSR_PRINTF(
++      olsr_printf(
+         9,
+         "%s: --> not forwarding from \"%s\" to \"%s\": both non-OLSR interfaces\n",
+         PLUGIN_NAME_SHORT,
+@@ -339,7 +368,7 @@
+     else /* (!isFromOlsrIntf || isToOlsrIntf) && (!isToOlsrIntf || iAmNotMpr) && (isFromOlsrIntf || isToOlsrIntf) */
+     {
+-      OLSR_PRINTF(
++      olsr_printf(
+         9,
+         "%s: --> not forwarding from \"%s\" to \"%s\": I am not selected as MPR by %s\n",
+         PLUGIN_NAME_SHORT,
+@@ -402,17 +431,21 @@
+   ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET);
+-  OLSR_PRINTF(
++  olsr_printf(
+     9,
+-    "%s: encapsulated pkt of %d bytes incoming on \"%s\": %s->",
++    "%s: encapsulated pkt of %d bytes ttl=%d incoming on \"%s\": %s->",
+     PLUGIN_NAME_SHORT,
+     ethPktLen,
++    GetIpTtl(ethPkt),
+     intf->ifName,
+     inet_ntoa(ipData->ip_src));
+-  OLSR_PRINTF(
++  olsr_printf(
+     9,
+-    "%s, forwarded by %s\n",
+-    inet_ntoa(ipData->ip_dst), /* not possible to call inet_ntoa twice in same printf */
++    "%s, ",
++    inet_ntoa(ipData->ip_dst)); /* not possible to call inet_ntoa twice in same printf */
++  olsr_printf(
++    9,
++    "forwarded by %s\n",
+     olsr_ip_to_string(fromIp));
+   /* Get encapsulation header */
+@@ -421,7 +454,7 @@
+   /* Check if this packet was seen recently */
+   if (CheckAndMarkRecentPacket(Hash16(ntohl(encapHdr->crc32))))
+   {
+-    OLSR_PRINTF(
++    olsr_printf(
+       9,
+       "%s: --> discarding: packet is duplicate\n",
+       PLUGIN_NAME_SHORT);
+@@ -448,12 +481,28 @@
+   }
+   else
+   {
+-    OLSR_PRINTF(
++    olsr_printf(
+       9,
+-      "%s: --> unpacked and forwarded to \"%s\"\n",
++      "%s: --> unpacked and forwarded ttl=%d to \"%s\"\n",
+       PLUGIN_NAME_SHORT,
++      GetIpTtl(ethPkt),
+       EtherTunTapIfName);
+   }
++  
++  /*
++   * Sven-Ola@gmx.de: The original implemenation make a wave
++   * through the complete mesh for every packet. Packets are
++   * discarded if any device has seen it (most bad case). We
++   * Want some "local" distribution mode, so I've added some
++   * hopcounter here - derived from the original ttl
++   */
++  if (0 == encapHdr->encapttl || 0 == --encapHdr->encapttl) {
++    olsr_printf(
++      9,
++      "%s: --> dicarding encapsulated: TTL=0\n",
++      PLUGIN_NAME_SHORT);
++    return;
++  }
+   /* Lookup main address of forwarding node */
+   forwarder = mid_lookup_main_addr(fromIp);
+@@ -489,7 +538,7 @@
+       /* If the TTL is <= 0, do not forward this packet */
+       if (GetIpTtl(ethPkt) <= 0)
+       {
+-        OLSR_PRINTF(
++        olsr_printf(
+           9,
+           "%s: --> not forwarding on \"%s\": TTL=0\n",
+           PLUGIN_NAME_SHORT,
+@@ -509,10 +558,12 @@
+         }
+         else
+         {
+-          OLSR_PRINTF(
++          olsr_printf(
+             9,
+-            "%s: --> unpacked and forwarded to \"%s\"\n",
++            "%s: --> unpacked and forwarded ttl=%d, sttl=%d to \"%s\"\n",
+             PLUGIN_NAME_SHORT,
++            GetIpTtl(ethPkt),
++            sttl.ttl,
+             fwIntf->ifName);
+         }
+       }
+@@ -551,17 +602,18 @@
+       }
+       else
+       {
+-        OLSR_PRINTF(
++        olsr_printf(
+           9,
+-          "%s: --> forwarded to \"%s\"\n",
++          "%s: --> forwarded(encrec) ttl=%d to \"%s\"\n",
+           PLUGIN_NAME_SHORT,
++          GetIpTtl(ethPkt),
+           fwIntf->ifName);
+       }
+     }  /* else if (iAmMpr) */
+     else /* fwIntf->olsrIntf != NULL && !iAmMpr */
+     {
+       /* fwIntf is an OLSR interface and I am not selected as MPR */
+-      OLSR_PRINTF(
++      olsr_printf(
+         9,
+         "%s: --> not forwarding to \"%s\": I am not selected as MPR by %s\n",
+         PLUGIN_NAME_SHORT,
+@@ -690,7 +742,15 @@
+             {
+               union olsr_ip_addr destIp;
+               COPY_IP(&destIp, &ipData->ip_dst);
+-              if (IsMulticast(&destIp) || IsLocalBroadcast(&destIp, currIf))
++              if (IsMulticast(&destIp)
++#ifdef SVEN_OLA_DISABLED
++                 /* 
++                  * Sven-Ola@gmx.de: In a bigger mesh, there are a lot of
++                  * accidential bcast sources.  Disabled to save bandwidth 
++                  */
++                 || IsLocalBroadcast(&destIp, currIf)
++#endif
++              )
+               {
+                 if (! IsOlsrOrBmfPacket(currIf, ethPkt, nBytes))
+                 {
+@@ -701,8 +761,15 @@
+                 }
+               }
+             }
+-            else if (pktAddr.sll_pkttype == PACKET_MULTICAST ||
+-                     pktAddr.sll_pkttype == PACKET_BROADCAST)
++            else if (pktAddr.sll_pkttype == PACKET_MULTICAST
++#ifdef SVEN_OLA_DISABLED
++                 /* 
++                  * Sven-Ola@gmx.de: In a bigger mesh, there are a lot of
++                  * accidential bcast sources.  Disabled to save bandwidth 
++                  */
++                 || pktAddr.sll_pkttype == PACKET_BROADCAST
++#endif
++            )
+             {
+               /* An inbound multicast or broadcast packet was captured */
+               BmfPacketCaptured(currIf, buffer, nBytes + ENCAP_HDR_LEN);
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.c olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.c
+--- olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.c  2006-11-29 12:45:19.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.c       2006-11-29 12:47:49.000000000 +0100
+@@ -568,7 +568,7 @@
+   newIf->next = BmfInterfaces;
+   BmfInterfaces = newIf;
+-  OLSR_PRINTF(
++  olsr_printf(
+     9,
+     "%s: opened %s interface \"%s\"\n",
+     PLUGIN_NAME_SHORT,
+@@ -738,7 +738,7 @@
+       nClosed++;
+     }
+-    OLSR_PRINTF(
++    olsr_printf(
+       9,
+       "%s: closed %s interface \"%s\"\n", 
+       PLUGIN_NAME_SHORT,
+@@ -756,7 +756,7 @@
+     close(EtherTunTapFd);
+     nClosed++;
+-    OLSR_PRINTF(9, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
++    olsr_printf(9, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
+   }
+   BmfInterfaces = NULL;
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Packet.c olsrd-0.4.10/lib/bmf/src/Packet.c
+--- olsrd-0.4.10.orig/lib/bmf/src/Packet.c     2006-11-29 12:45:19.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Packet.c  2006-11-29 12:50:35.000000000 +0100
+@@ -46,6 +46,8 @@
+ #include <assert.h> /* assert() */
+ #include <sys/types.h> /* u_int32_t */
+ #include <netinet/in.h> /* ntohs(), htons() */
++/* Fixes (k)ubuntu linux-kernel-headers package */
++#include <asm/byteorder.h>
+ #include <linux/ip.h>
+ /* -------------------------------------------------------------------------
+diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Packet.h olsrd-0.4.10/lib/bmf/src/Packet.h
+--- olsrd-0.4.10.orig/lib/bmf/src/Packet.h     2006-11-29 12:45:19.000000000 +0100
++++ olsrd-0.4.10/lib/bmf/src/Packet.h  2006-11-29 12:47:49.000000000 +0100
+@@ -66,7 +66,8 @@
+   u_int32_t crc32;
+   u_int32_t futureExpansion1;
+   u_int32_t futureExpansion2;
+-  u_int32_t futureExpansion3;
++  u_int8_t futureExpansion3[3];
++  u_int8_t encapttl;
+ } __attribute__((__packed__));
+ #define       ENCAP_HDR_LEN sizeof(struct TEncapHeader)
diff --git a/net/olsrd/patches/190-olsrd-optimize.patch b/net/olsrd/patches/190-olsrd-optimize.patch
new file mode 100644 (file)
index 0000000..ddea522
--- /dev/null
@@ -0,0 +1,426 @@
+diff -Nur olsrd-0.4.10.orig/src/duplicate_set.c olsrd-0.4.10/src/duplicate_set.c
+--- olsrd-0.4.10.orig/src/duplicate_set.c      2005-02-27 19:39:43.000000000 +0100
++++ olsrd-0.4.10/src/duplicate_set.c   2006-11-12 09:33:49.000000000 +0100
+@@ -93,7 +93,7 @@
+   /* Hash the senders address */
+-  hash = olsr_hashing(originator);
++  hash = HASHMASK & seqno;
+   new_dup_entry = olsr_malloc(sizeof(struct dup_entry), "New dup entry");
+@@ -131,7 +131,7 @@
+   struct dup_entry *tmp_dup_table;
+   /* Hash the senders address */
+-  hash = olsr_hashing(originator);
++  hash = HASHMASK & seqno;
+   /* Check for entry */
+   for(tmp_dup_table = dup_set[hash].next;
+@@ -163,7 +163,7 @@
+   struct dup_entry *tmp_dup_table;
+   /* Hash the senders address */
+-  hash = olsr_hashing(originator);
++  hash = HASHMASK & seqno;
+   /* Check for entry */
+   for(tmp_dup_table = dup_set[hash].next;
+@@ -268,7 +268,7 @@
+   struct dup_iface *new_iface;
+   /* Hash the senders address */
+-  hash = olsr_hashing(originator);
++  hash = HASHMASK & seqno;
+   /* Check for entry */
+@@ -313,7 +313,7 @@
+   struct dup_entry *tmp_dup_table;
+   /* Hash the senders address */
+-  hash = olsr_hashing(originator);
++  hash = HASHMASK & seqno;
+   /* Check for entry */
+   for(tmp_dup_table = dup_set[hash].next;
+diff -Nur olsrd-0.4.10.orig/src/hashing.c olsrd-0.4.10/src/hashing.c
+--- olsrd-0.4.10.orig/src/hashing.c    2005-02-20 19:52:18.000000000 +0100
++++ olsrd-0.4.10/src/hashing.c 2006-11-12 09:33:49.000000000 +0100
+@@ -58,7 +58,7 @@
+   if(olsr_cnf->ip_version == AF_INET)
+     /* IPv4 */  
+-    hash = (ntohl(address->v4));
++    hash = address->v4x[0] ^ address->v4x[1] ^ address->v4x[2] ^ address->v4x[3];
+   else
+     {
+       /* IPv6 */
+diff -Nur olsrd-0.4.10.orig/src/hashing.h olsrd-0.4.10/src/hashing.h
+--- olsrd-0.4.10.orig/src/hashing.h    2005-02-20 19:52:18.000000000 +0100
++++ olsrd-0.4.10/src/hashing.h 2006-11-12 09:33:49.000000000 +0100
+@@ -43,7 +43,7 @@
+ #ifndef _OLSR_HASHING
+ #define _OLSR_HASHING
+-#define       HASHSIZE        32
++#define       HASHSIZE        128
+ #define       HASHMASK        (HASHSIZE - 1)
+ #include "olsr_types.h"
+diff -Nur olsrd-0.4.10.orig/src/lq_avl.c olsrd-0.4.10/src/lq_avl.c
+--- olsrd-0.4.10.orig/src/lq_avl.c     2005-01-22 15:30:57.000000000 +0100
++++ olsrd-0.4.10/src/lq_avl.c  2006-11-12 09:33:49.000000000 +0100
+@@ -40,6 +40,9 @@
+  */
+ #include <stddef.h>
++#ifndef DISABLE_SVEN_OLA
++#include <time.h>
++#endif
+ #include "lq_avl.h"
+@@ -52,11 +55,33 @@
+   tree->comp = comp;
+ }
++#ifndef DISABLE_SVEN_OLA
++static struct avl_node *avl_find_rec_ipv4(struct avl_node *node, void *key)
++{
++  if (*(unsigned int *)key < *(unsigned int *)node->key) {
++    if (node->left != NULL) {
++      return avl_find_rec_ipv4(node->left, key);
++    }
++  }
++  else if (*(unsigned int *)key > *(unsigned int *)node->key) {
++    if (node->right != NULL) {
++      return avl_find_rec_ipv4(node->right, key);
++    }
++  }
++  return node;
++}
++#endif
++
+ static struct avl_node *avl_find_rec(struct avl_node *node, void *key,
+                                      int (*comp)(void *, void *))
+ {
+   int diff;
++#ifndef DISABLE_SVEN_OLA
++  if (0 == comp) {
++    return avl_find_rec_ipv4(node, key);
++  }
++#endif
+   diff = (*comp)(key, node->key);
+   if (diff < 0)
+@@ -87,6 +112,13 @@
+   node = avl_find_rec(tree->root, key, tree->comp);
++#ifndef DISABLE_SVEN_OLA
++  if (0 == tree->comp) {
++    if (0 != svenola_avl_comp_ipv4(node->key, key))
++      return NULL;
++  }
++  else
++#endif
+   if ((*tree->comp)(node->key, key) != 0)
+     return NULL;
+@@ -228,6 +260,12 @@
+   node = avl_find_rec(tree->root, new->key, tree->comp);
++#ifndef DISABLE_SVEN_OLA
++  if (0 == tree->comp) {
++    diff = svenola_avl_comp_ipv4(new->key, node->key);
++  }
++  else
++#endif
+   diff = (*tree->comp)(new->key, node->key);
+   if (diff == 0)
+diff -Nur olsrd-0.4.10.orig/src/lq_avl.h olsrd-0.4.10/src/lq_avl.h
+--- olsrd-0.4.10.orig/src/lq_avl.h     2005-02-20 19:52:18.000000000 +0100
++++ olsrd-0.4.10/src/lq_avl.h  2006-11-12 09:33:49.000000000 +0100
+@@ -62,4 +62,9 @@
+ struct avl_node *avl_find(struct avl_tree *, void *);
+ int avl_insert(struct avl_tree *, struct avl_node *);
++#ifndef DISABLE_SVEN_OLA
++#define svenola_avl_comp_ipv4(ip1, ip2) \
++  (*(unsigned int *)ip1 == *(unsigned int *)ip2 ? 0 : \
++  *(unsigned int *)ip1 < *(unsigned int *)ip2 ? -1 : +1)
++#endif
+ #endif
+diff -Nur olsrd-0.4.10.orig/src/lq_list.c olsrd-0.4.10/src/lq_list.c
+--- olsrd-0.4.10.orig/src/lq_list.c    2004-12-04 18:06:57.000000000 +0100
++++ olsrd-0.4.10/src/lq_list.c 2006-11-12 09:33:49.000000000 +0100
+@@ -48,6 +48,7 @@
+   list->tail = NULL;
+ }
++#ifdef DISABLE_SVEN_OLA
+ struct list_node *list_get_head(struct list *list)
+ {
+   return list->head;
+@@ -67,6 +68,7 @@
+ {
+   return node->prev;
+ }
++#endif
+ void list_add_head(struct list *list, struct list_node *node)
+ {
+diff -Nur olsrd-0.4.10.orig/src/lq_list.h olsrd-0.4.10/src/lq_list.h
+--- olsrd-0.4.10.orig/src/lq_list.h    2005-02-20 19:52:18.000000000 +0100
++++ olsrd-0.4.10/src/lq_list.h 2006-11-12 09:33:49.000000000 +0100
+@@ -58,11 +58,18 @@
+ void list_init(struct list *list);
++#ifndef DISABLE_SVEN_OLA
++#define list_get_head(node) (node)->head
++#define list_get_tail(node) (node)->tail
++#define list_get_next(node) (node)->next
++#define list_get_prev(node) (node)->prev
++#else
+ struct list_node *list_get_head(struct list *list);
+ struct list_node *list_get_tail(struct list *list);
+ struct list_node *list_get_next(struct list_node *node);
+ struct list_node *list_get_prev(struct list_node *node);
++#endif
+ void list_add_head(struct list *list, struct list_node *node);
+ void list_add_tail(struct list *list, struct list_node *node);
+diff -Nur olsrd-0.4.10.orig/src/lq_route.c olsrd-0.4.10/src/lq_route.c
+--- olsrd-0.4.10.orig/src/lq_route.c   2005-11-29 19:37:58.000000000 +0100
++++ olsrd-0.4.10/src/lq_route.c        2006-11-12 09:34:46.000000000 +0100
+@@ -205,6 +205,16 @@
+   // add the vertex to the list, if it's not us
++#ifndef DISABLE_SVEN_OLA
++  if (0 == comp) {
++    if (svenola_avl_comp_ipv4(&main_addr, node->key) != 0)
++    {
++      vert->node.data = vert;
++      list_add_tail(vertex_list, &vert->node);
++    }
++  }
++  else
++#endif
+   if ((*comp)(&main_addr, node->key) != 0)
+   {
+     vert->node.data = vert;
+@@ -266,6 +276,154 @@
+ }
+ // XXX - bad complexity
++#define SVEN_OPT
++#undef SVEN_OPT_DBG
++
++/*
++ * The function extract_best() is most expensive (>50% CPU in profiling).
++ * It is called in two modes: while doing Dijkstra route calculation and
++ * while searching for a direct route/hna. The latter can be optimized
++ * because the stored verices do not change from call to call and it is
++ * more sufficient to have them sorted/popped from a list rather than 
++ * searching the complete list by every call. Sven-Ola@gmx.de, 11/2006
++ */
++ 
++#ifdef SVEN_OPT
++static struct dijk_vertex **etx_cache = 0;
++static int etx_cache_count;
++static int etx_cache_get;
++static int etx_cache_saved = 0;
++
++static int etx_cache_compare(const void *a, const void *b)
++{
++  // Oh jeah. I love this macro assembler :)
++  
++  if ((*(struct dijk_vertex **)a)->path_etx > (*(struct dijk_vertex **)b)->path_etx) return 1;
++  if ((*(struct dijk_vertex **)a)->path_etx < (*(struct dijk_vertex **)b)->path_etx) return -1;
++  
++  // This is for debugging only: etx==etx then compare pointers
++  // to make it possible to compare to the original search algo.
++  if (*(struct dijk_vertex **)a > *(struct dijk_vertex **)b) return 1;
++  if (*(struct dijk_vertex **)a < *(struct dijk_vertex **)b) return -1;
++  
++  return 0;
++}
++
++static struct dijk_vertex *extract_best_route(struct list *vertex_list)
++{
++#ifdef SVEN_OPT_DBG
++  float best_etx = INFINITE_ETX + 1.0;
++#endif
++  struct list_node *node;
++  struct dijk_vertex *vert;
++  struct dijk_vertex *res = NULL;
++
++#ifdef SVEN_OPT_DBG
++  node = list_get_head(vertex_list);
++
++  // loop through all vertices
++  
++  while (node != NULL)
++  {
++    vert = node->data;
++
++    // see whether the current vertex is better than what we have
++
++    if (!vert->done && vert->path_etx < best_etx)
++    {
++      best_etx = vert->path_etx;
++      res = vert;
++    }
++    else if (!vert->done && vert->path_etx == best_etx && vert < res)
++    {
++      // Otherwise order is undefined if etx==etx and debug will complain
++      best_etx = vert->path_etx;
++      res = vert;
++    }
++
++    node = list_get_next(node);
++  }
++#endif
++  if (NULL == etx_cache)
++  {
++    int count = 0;
++    node = list_get_head(vertex_list);
++    while (node != NULL)
++    {
++      vert = node->data;
++      if (!vert->done && vert->path_etx < INFINITE_ETX) count++;
++      node = list_get_next(node);
++    }
++    if (0 < count)
++    {
++      etx_cache = olsr_malloc(sizeof(etx_cache[0]) * count, "ETX Cache");
++#ifdef SVEN_OPT_DBG
++      printf("count=%d, Malloc(%d)=%p\n", count, sizeof(etx_cache[0]) * count, etx_cache);
++#endif
++      node = list_get_head(vertex_list);
++      etx_cache_count = 0;
++      etx_cache_get = 0;
++      while (node != NULL)
++      {
++        vert = node->data;
++        if (!vert->done && vert->path_etx < INFINITE_ETX)
++        {
++          etx_cache[etx_cache_count] = vert;
++          etx_cache_count++;
++        }
++        node = list_get_next(node);
++      }
++#ifdef SVEN_OPT_DBG
++      printf("qsort(etx_cache_count=%d)\n", etx_cache_count);
++#endif
++      qsort(etx_cache, etx_cache_count, sizeof(etx_cache[0]), etx_cache_compare);
++#ifdef SVEN_OPT_DBG
++      if (0 < etx_cache_count)
++      {
++        int i = 0; 
++        while(i < etx_cache_count && i < 10)
++        {
++          printf("%d: %p=%f\n", i, etx_cache[i], etx_cache[i]->path_etx);
++          i++;
++        }
++      }
++#endif
++    }
++  }
++
++#ifdef SVEN_OPT_DBG
++  if (NULL != etx_cache)
++  {
++    struct dijk_vertex *rescache = NULL;
++    if (etx_cache_get < etx_cache_count)
++    {
++      rescache = etx_cache[etx_cache_get++];
++    }
++    if (res != rescache)
++    {
++      printf("miss: etx_cache_get=%d, res=%p,%f != rescache=%p,%f\n",
++        etx_cache_get, res, (NULL != res ? res->path_etx : -1), rescache, (NULL != rescache ? rescache->path_etx : -1));
++    }
++    else
++    {
++      etx_cache_saved++;
++    }
++  }
++#else
++  if (NULL != etx_cache && etx_cache_get < etx_cache_count)
++  {
++    res = etx_cache[etx_cache_get++];
++  }
++#endif
++
++  // if we've found a vertex, remove it from the set
++
++  if (res != NULL)
++    res->done = OLSR_TRUE;
++
++  return res;
++}
++#endif // SVEN_OPT
+ static struct dijk_vertex *extract_best(struct list *vertex_list)
+ {
+@@ -371,7 +529,11 @@
+   struct interface *inter;
+   if (ipsize == 4)
++#ifndef DISABLE_SVEN_OLA
++    avl_comp = 0;
++#else
+     avl_comp = avl_comp_ipv4;
++#endif
+   else
+     avl_comp = avl_comp_ipv6;
+@@ -614,13 +776,27 @@
+   // add HNA routes - the set of unprocessed network nodes contains
+   // all reachable network nodes
++#ifdef SVEN_OPT
++#ifdef SVEN_OPT_DBG
++  printf("free etx_cache, saved compares=%d, etx_cache=%p\n", etx_cache_saved, etx_cache);
++  etx_cache_saved = 0;
++#endif
++  if (NULL != etx_cache) {
++    free(etx_cache);
++    etx_cache = NULL;
++  }
++#endif
+   for (;;)
+   {
+     // extract the network node with the best ETX and remove it
+     // from the set of unprocessed network nodes
++#ifdef SVEN_OPT
++    vert = extract_best_route(&vertex_list);
++#else
+     vert = extract_best(&vertex_list);
++#endif
+     // no more nodes left
+diff -Nur olsrd-0.4.10.orig/src/olsr_types.h olsrd-0.4.10/src/olsr_types.h
+--- olsrd-0.4.10.orig/src/olsr_types.h 2005-05-15 14:57:24.000000000 +0200
++++ olsrd-0.4.10/src/olsr_types.h      2006-11-12 09:33:49.000000000 +0100
+@@ -93,6 +93,7 @@
+ union olsr_ip_addr
+ {
+   olsr_u32_t v4;
++  olsr_u8_t v4x[4];
+   struct in6_addr v6;
+ };
diff --git a/net/olsrd/patches/200-olsrd-fixes-eric.patch b/net/olsrd/patches/200-olsrd-fixes-eric.patch
new file mode 100644 (file)
index 0000000..95bb06d
--- /dev/null
@@ -0,0 +1,1284 @@
+diff -Naur olsrd-0.4.10/files/olsrd.conf.default.lq olsrd-0.4.10-patched/files/olsrd.conf.default.lq
+--- olsrd-0.4.10/files/olsrd.conf.default.lq   2005-03-31 20:35:23.000000000 +0200
++++ olsrd-0.4.10-patched/files/olsrd.conf.default.lq   2006-11-16 13:22:26.000000000 +0100
+@@ -259,6 +259,7 @@
+     # HNA validity time
+     HnaValidityTime   30.0
++
+     # When multiple links exist between hosts
+     # the weight of interface is used to determine
+     # the link to use. Normally the weight is
+@@ -266,9 +267,29 @@
+     # on the characteristics of the interface,
+     # but here you can specify a fixed value.
+     # Olsrd will choose links with the lowest value.
+-
++    # Note:
++    # Interface weight is used only when LinkQualityLevel is 0.
++    # For any other value of LinkQualityLevel, the interface ETX
++    # value is used instead.
+     # Weight 0
++    # If a certain route should be preferred 
++    # or ignored by the mesh, the Link Quality 
++    # value of a node can be multiplied with a factor 
++    # entered here. In the example the route 
++    # using 192.168.0.1 would rather be ignored.
++    # A multiplier of 0.5 will result in a small
++    # (bad) LinkQuality value and a high (bad)
++    # ETX value.
++    # Note:
++    # Link quality multiplier is used only when
++    # LinkQualityLevel is > 0.
++
++    # LinkQualityMult 192.168.0.1 0.5
++
++    # This multiplier applies to all other nodes 
++    # LinkQualityMult default 0.8
++
+ }
+diff -Naur olsrd-0.4.10/files/olsrd.conf.default.lq-fisheye olsrd-0.4.10-patched/files/olsrd.conf.default.lq-fisheye
+--- olsrd-0.4.10/files/olsrd.conf.default.lq-fisheye   2005-12-17 08:30:34.000000000 +0100
++++ olsrd-0.4.10-patched/files/olsrd.conf.default.lq-fisheye   2006-11-16 13:24:18.000000000 +0100
+@@ -267,6 +267,7 @@
+     # HNA validity time
+     HnaValidityTime   100.0
++
+     # When multiple links exist between hosts
+     # the weight of interface is used to determine
+     # the link to use. Normally the weight is
+@@ -274,7 +275,10 @@
+     # on the characteristics of the interface,
+     # but here you can specify a fixed value.
+     # Olsrd will choose links with the lowest value.
+-
++    # Note:
++    # Interface weight is used only when LinkQualityLevel is set to 0.
++    # For any other value of LinkQualityLevel, the interface ETX
++    # value is used instead.
+     # Weight 0
+@@ -286,13 +290,14 @@
+     # A multiplier of 0.5 will result in a small
+     # (bad) LinkQuality value and a high (bad)
+     # ETX value.
++    # Note:
++    # Link quality multiplier is used only when
++    # LinkQualityLevel is > 0.
+     # LinkQualityMult 192.168.0.1 0.5
+     # This multiplier applies to all other nodes 
+     # LinkQualityMult default 0.8
+- 
+-
+ }
+diff -Naur olsrd-0.4.10/files/olsrd.conf.default.rfc olsrd-0.4.10-patched/files/olsrd.conf.default.rfc
+--- olsrd-0.4.10/files/olsrd.conf.default.rfc  2005-06-04 17:34:05.000000000 +0200
++++ olsrd-0.4.10-patched/files/olsrd.conf.default.rfc  2006-11-16 13:23:02.000000000 +0100
+@@ -254,6 +254,7 @@
+     # HNA validity time
+     # HnaValidityTime         15.0
++
+     # When multiple links exist between hosts
+     # the weight of interface is used to determine
+     # the link to use. Normally the weight is
+@@ -261,9 +262,29 @@
+     # on the characteristics of the interface,
+     # but here you can specify a fixed value.
+     # Olsrd will choose links with the lowest value.
+-
++    # Note:
++    # Interface weight is used only when LinkQualityLevel is set to 0.
++    # For any other value of LinkQualityLevel, the interface ETX
++    # value is used instead.
+     # Weight 0
++    # If a certain route should be preferred 
++    # or ignored by the mesh, the Link Quality 
++    # value of a node can be multiplied with a factor 
++    # entered here. In the example the route 
++    # using 192.168.0.1 would rather be ignored.
++    # A multiplier of 0.5 will result in a small
++    # (bad) LinkQuality value and a high (bad)
++    # ETX value.
++    # Note:
++    # Link quality multiplier is used only when
++    # LinkQualityLevel is > 0.
++
++    # LinkQualityMult 192.168.0.1 0.5
++
++    # This multiplier applies to all other nodes 
++    # LinkQualityMult default 0.8
++
+ }
+diff -Naur olsrd-0.4.10/lib/httpinfo/src/html.h olsrd-0.4.10-patched/lib/httpinfo/src/html.h
+--- olsrd-0.4.10/lib/httpinfo/src/html.h       2005-03-14 22:28:15.000000000 +0100
++++ olsrd-0.4.10-patched/lib/httpinfo/src/html.h       2006-09-14 13:11:02.000000000 +0200
+@@ -48,7 +48,7 @@
+ static const char *httpinfo_css[] =
+ {
+-  "A {text-decoration: none}\n",
++  "#A {text-decoration: none}\n",
+   "TH{text-align: left}\n",
+   "H1, H3, TD, TH {font-family: Helvetica; font-size: 80%%}\n",
+   "h2\n {\nfont-family: Helvetica;\n font-size: 14px;text-align: center;\n",
+diff -Naur olsrd-0.4.10/lib/httpinfo/src/olsrd_httpinfo.c olsrd-0.4.10-patched/lib/httpinfo/src/olsrd_httpinfo.c
+--- olsrd-0.4.10/lib/httpinfo/src/olsrd_httpinfo.c     2005-12-22 16:06:52.000000000 +0100
++++ olsrd-0.4.10-patched/lib/httpinfo/src/olsrd_httpinfo.c     2006-11-24 12:53:25.000000000 +0100
+@@ -713,7 +713,10 @@
+   size += sprintf(&buf[size], "<h2>OLSR routes in kernel</h2>\n");
+-  size += sprintf(&buf[size], "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Destination</th><th>Gateway</th><th>Metric</th><th>ETX</th><th>Interface</th><th>Type</th></tr>\n");
++  size += sprintf(&buf[size], "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Destination</th><th>Gateway</th><th>Metric</th>");
++  if (olsr_cnf->lq_level > 0)
++    size += sprintf(&buf[size], "<th>ETX</th>");
++  size += sprintf(&buf[size], "<th>Interface</th><th>Type</th></tr>\n");
+   /* Neighbors */
+   for(index = 0;index < HASHSIZE;index++)
+@@ -722,12 +725,23 @@
+         routes != &routingtable[index];
+         routes = routes->next)
+       {
+-        size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td><td>%d</td><td>%.2f</td><td>%s</td><td>HOST</td></tr>\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);
++        size += sprintf(&buf[size],
++                         "<tr><td><a href=\"http://%s:%d/all\">%s</a></td>"
++                         "<td><a href=\"http://%s:%d/all\">%s</a></td>"
++                         "<td>%d</td>",
++                         olsr_ip_to_string(&routes->rt_dst),
++                         http_port,
++                         olsr_ip_to_string(&routes->rt_dst),
++                         olsr_ip_to_string(&routes->rt_router),
++                         http_port,
++                         olsr_ip_to_string(&routes->rt_router),
++                         routes->rt_metric);
++          if (olsr_cnf->lq_level > 0)
++          size += sprintf(&buf[size], "<td>%.2f</td>", routes->rt_etx);
++        size += sprintf(&buf[size],
++                         "<td>%s</td>"
++                         "<td>HOST</td></tr>\n",
++                         routes->rt_if->int_name);
+       }
+     }
+@@ -738,11 +752,21 @@
+         routes != &hna_routes[index];
+         routes = routes->next)
+       {
+-        size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>HNA</td></tr>\n",
+-                        olsr_ip_to_string(&routes->rt_dst),
+-                        olsr_ip_to_string(&routes->rt_router),
+-                        routes->rt_metric,
+-                        routes->rt_if->int_name);
++        size += sprintf(&buf[size],
++                         "<tr><td>%s</td>"
++                         "<td><a href=\"http://%s:%d/all\">%s</a></td>"
++                         "<td>%d</td>",
++                         olsr_ip_to_string(&routes->rt_dst),
++                         olsr_ip_to_string(&routes->rt_router),
++                         http_port,
++                         olsr_ip_to_string(&routes->rt_router),
++                         routes->rt_metric);
++          if (olsr_cnf->lq_level > 0)
++          size += sprintf(&buf[size], "<td>%.2f</td>", routes->rt_etx);
++        size += sprintf(&buf[size],
++                         "<td>%s</td>"
++                         "<td>HNA</td></tr>\n",
++                         routes->rt_if->int_name);
+       }
+     }
+@@ -816,17 +840,24 @@
+     
+     size += sprintf(&buf[size], "</tr>\n<tr>\n");
+-    size += sprintf(&buf[size], "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
+-      
+-    size += sprintf(&buf[size], "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
+-    size += sprintf(&buf[size], "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
++    if (olsr_cnf->lq_level == 0)
++      {
++        size += sprintf(&buf[size], "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
++      if (olsr_cnf->use_hysteresis)
++          {
++            size += sprintf(&buf[size], "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
++            size += sprintf(&buf[size], "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
++          }
++      }
+     size += sprintf(&buf[size], "</tr>\n<tr>\n");
+-    size += sprintf(&buf[size], "<td>LQ extention: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
+-    size += sprintf(&buf[size], "<td>LQ level: %d</td>\n", olsr_cnf->lq_level);
+-    size += sprintf(&buf[size], "<td>LQ winsize: %d</td>\n", olsr_cnf->lq_wsize);
+-    size += sprintf(&buf[size], "<td></td>\n");
++    size += sprintf(&buf[size], "<td>LQ extension: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
++    if (olsr_cnf->lq_level)
++      {
++        size += sprintf(&buf[size], "<td>LQ level: %d</td>\n", olsr_cnf->lq_level);
++        size += sprintf(&buf[size], "<td>LQ winsize: %d</td>\n", olsr_cnf->lq_wsize);
++      }
+     size += sprintf(&buf[size], "</tr></table>\n");
+@@ -868,7 +899,6 @@
+           size += sprintf(&buf[size], "<td>WLAN: %s</td>\n", rifs->is_wireless ? "Yes" : "No");
+           size += sprintf(&buf[size], "<td>STATUS: UP</td></tr>\n");
+         }         
+-
+       }
+     size += sprintf(&buf[size], "</table>\n");
+@@ -950,21 +980,39 @@
+   int size = 0, index, thop_cnt;
+   size += sprintf(&buf[size], "<h2>Links</h2>\n");
+-  size += sprintf(&buf[size], "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Local IP</th><th>remote IP</th><th>Hysteresis</th><th>LinkQuality</th><th>lost</th><th>total</th><th>NLQ</th><th>ETX</th></tr>\n");
++  size += sprintf(&buf[size], "<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Local IP</th><th>remote IP</th><th>Hysteresis</th>\n");
++  if (olsr_cnf->lq_level > 0)
++    size += sprintf(&buf[size], "<th>LinkQuality</th><th>lost</th><th>total</th><th>NLQ</th><th>ETX</th>\n");
++  size += sprintf(&buf[size], "</tr>\n");
+   /* Link set */
+   link = link_set;
+     while(link)
+       {
+-      size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td><td>%0.2f</td><td>%0.2f</td><td>%d</td><td>%d</td><td>%0.2f</td><td>%0.2f</td></tr>\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);
++      size += sprintf(&buf[size],
++                       "<tr><td>%s</td>"
++                       "<td><a href=\"http://%s:%d/all\">%s</a></td>"
++                       "<td>%0.2f</td>",
++                       olsr_ip_to_string(&link->local_iface_addr),
++                       olsr_ip_to_string(&link->neighbor_iface_addr),
++                       http_port,
++                       olsr_ip_to_string(&link->neighbor_iface_addr),
++                       link->L_link_quality);
++        if (olsr_cnf->lq_level > 0)
++          {
++          size += sprintf(&buf[size],
++                           "<td>%0.2f</td>"
++                           "<td>%d</td>"
++                           "<td>%d</td>"
++                           "<td>%0.2f</td>"
++                           "<td>%0.2f</td></tr>\n",
++                           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);
++          }
++      size += sprintf(&buf[size], "</tr>\n");
+       link = link->next;
+       }
+@@ -981,7 +1029,13 @@
+         neigh = neigh->next)
+       {
+         size += sprintf(&buf[size], 
+-                        "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%d</td>", 
++                        "<tr><td><a href=\"http://%s:%d/all\">%s</a></td>"
++                        "<td>%s</td>"
++                        "<td>%s</td>"
++                        "<td>%s</td>"
++                        "<td>%d</td>", 
++                        olsr_ip_to_string(&neigh->neighbor_main_addr),
++                          http_port,
+                         olsr_ip_to_string(&neigh->neighbor_main_addr),
+                         (neigh->status == SYM) ? "YES" : "NO",
+                         neigh->is_mpr ? "YES" : "NO",
+@@ -1021,7 +1075,10 @@
+   struct topo_dst *dst_entry;
+-  size += sprintf(&buf[size], "<h2>Topology entries</h2>\n<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Destination IP</th><th>Last hop IP</th><th>LQ</th><th>ILQ</th><th>ETX</th></tr>\n");
++  size += sprintf(&buf[size], "<h2>Topology entries</h2>\n<table width=\"100%%\" BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=center><tr><th>Destination IP</th><th>Last hop IP</th>");
++  if (olsr_cnf->lq_level > 0)
++    size += sprintf(&buf[size], "<th>LQ</th><th>ILQ</th><th>ETX</th>");
++  size += sprintf(&buf[size], "</tr>\n");
+   /* Topology */  
+@@ -1035,12 +1092,26 @@
+         dst_entry = entry->destinations.next;
+         while(dst_entry != &entry->destinations)
+           {
+-            size += sprintf(&buf[size], "<tr><td>%s</td><td>%s</td><td>%0.2f</td><td>%0.2f</td><td>%0.2f</td></tr>\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);
++            size += sprintf(&buf[size],
++                             "<tr><td><a href=\"http://%s:%d/all\">%s</a></td>"
++                             "<td><a href=\"http://%s:%d/all\">%s</a></td>",
++                             olsr_ip_to_string(&dst_entry->T_dest_addr),
++                             http_port,
++                             olsr_ip_to_string(&dst_entry->T_dest_addr),
++                             olsr_ip_to_string(&entry->T_last_addr), 
++                             http_port,
++                             olsr_ip_to_string(&entry->T_last_addr));
++              if (olsr_cnf->lq_level > 0)
++                {
++                size += sprintf(&buf[size],
++                                 "<td>%0.2f</td>"
++                                 "<td>%0.2f</td>"
++                                 "<td>%0.2f</td>\n",
++                                 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);
++                }
++            size += sprintf(&buf[size], "</tr>\n");
+             dst_entry = dst_entry->next;
+           }
+@@ -1083,7 +1154,9 @@
+                             olsr_ip_to_string(&tmp_net->A_network_addr));
+             size += sprintf(&buf[size], "<td>%s</td>",
+                             olsr_netmask_to_string(&tmp_net->A_netmask));
+-            size += sprintf(&buf[size], "<td>%s</td></tr>\n",
++            size += sprintf(&buf[size], "<td><a href=\"http://%s:%d/all\">%s</a></td></tr>\n",
++                              olsr_ip_to_string(&tmp_hna->A_gateway_addr),
++                              http_port,
+                               olsr_ip_to_string(&tmp_hna->A_gateway_addr));
+             tmp_net = tmp_net->next;
+           }
+@@ -1101,7 +1174,7 @@
+ int
+ build_mid_body(char *buf, olsr_u32_t bufsize)
+ {
+-  int size = 0;
++  int size = 0, mid_cnt;
+   olsr_u8_t index;
+   struct mid_entry *entry;
+   struct mid_address *alias;
+@@ -1114,18 +1187,21 @@
+       entry = mid_set[index].next;
+       while(entry != &mid_set[index])
+       {
+-        size += sprintf(&buf[size], "<tr><td>%s</td>\n", olsr_ip_to_string(&entry->main_addr));
++        size += sprintf(&buf[size], "<tr><td><a href=\"http://%s:%d/all\">%s</a></td>\n",
++                        olsr_ip_to_string(&entry->main_addr),
++                          http_port,
++                        olsr_ip_to_string(&entry->main_addr));
+         size += sprintf(&buf[size], "<td><select>\n<option>IP ADDRESS</option>\n");
+         alias = entry->aliases;
++        mid_cnt = 0;
+         while(alias)
+           {
+             size += sprintf(&buf[size], "<option>%s</option>\n", olsr_ip_to_string(&alias->alias));
++            mid_cnt ++;
+             alias = alias->next_alias;
+           }
+-        size += sprintf(&buf[size], "</select>\n");
+-
+-        size += sprintf(&buf[size], "</tr>\n");
++        size += sprintf(&buf[size], "</select> (%d)</td></tr>\n", mid_cnt);
+         entry = entry->next;
+       }
+     }
+diff -Naur olsrd-0.4.10/lib/httpinfo/src/olsrd_plugin.c olsrd-0.4.10-patched/lib/httpinfo/src/olsrd_plugin.c
+--- olsrd-0.4.10/lib/httpinfo/src/olsrd_plugin.c       2005-05-29 14:47:41.000000000 +0200
++++ olsrd-0.4.10-patched/lib/httpinfo/src/olsrd_plugin.c       2006-09-18 03:03:50.000000000 +0200
+@@ -51,6 +51,8 @@
+ #include <stdlib.h>
+ #include "olsrd_httpinfo.h"
++int http_port = 0;
++
+ static void __attribute__ ((constructor)) 
+ my_init(void);
+diff -Naur olsrd-0.4.10/lib/httpinfo/src/olsrd_plugin.h olsrd-0.4.10-patched/lib/httpinfo/src/olsrd_plugin.h
+--- olsrd-0.4.10/lib/httpinfo/src/olsrd_plugin.h       2005-05-29 14:47:41.000000000 +0200
++++ olsrd-0.4.10-patched/lib/httpinfo/src/olsrd_plugin.h       2006-09-18 03:03:38.000000000 +0200
+@@ -71,7 +71,7 @@
+ #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+ #define PLUGIN_INTERFACE_VERSION 4
+-int http_port;
++extern int http_port;
+ /* Allowed hosts stuff */
+diff -Naur olsrd-0.4.10/src/cfgparser/cfgfile_gen.c olsrd-0.4.10-patched/src/cfgparser/cfgfile_gen.c
+--- olsrd-0.4.10/src/cfgparser/cfgfile_gen.c   2005-12-30 03:24:00.000000000 +0100
++++ olsrd-0.4.10-patched/src/cfgparser/cfgfile_gen.c   2006-11-16 13:54:04.000000000 +0100
+@@ -311,7 +311,17 @@
+               }
+           }
+-        fprintf(fd, "    # When multiple links exist between hosts\n    # the weight of interface is used to determine\n    # the link to use. Normally the weight is\n    # automatically calculated by olsrd based\n    # on the characteristics of the interface,\n    # but here you can specify a fixed value.\n    # Olsrd will choose links with the lowest value.\n");
++         fprintf(fd, "    # When multiple links exist between hosts\n");
++         fprintf(fd, "    # the weight of interface is used to determine\n");
++         fprintf(fd, "    # the link to use. Normally the weight is\n");
++         fprintf(fd, "    # automatically calculated by olsrd based\n");
++         fprintf(fd, "    # on the characteristics of the interface,\n");
++         fprintf(fd, "    # but here you can specify a fixed value.\n");
++         fprintf(fd, "    # Olsrd will choose links with the lowest value.\n");
++         fprintf(fd, "    # Note:\n");
++         fprintf(fd, "    # Interface weight is used only when LinkQualityLevel is 0.\n");
++         fprintf(fd, "    # For any other value of LinkQualityLevel, the interface ETX\n");
++         fprintf(fd, "    # value is used instead.\n\n");
+         if(in->cnf->weight.fixed)
+           {
+             fprintf(fd, "    Weight\t %d\n\n", in->cnf->weight.value);
+@@ -615,9 +625,19 @@
+           }
+         if(first)
+-          WRITE_TO_BUF("    # When multiple links exist between hosts\n    # the weight of interface is used to determine\n    # the link to use. Normally the weight is\n")
+-          if(first)
+-            WRITE_TO_BUF("    # automatically calculated by olsrd based\n    # on the characteristics of the interface,\n    # but here you can specify a fixed value.\n    # Olsrd will choose links with the lowest value.\n")
++          {
++             WRITE_TO_BUF("    # When multiple links exist between hosts\n");
++             WRITE_TO_BUF("    # the weight of interface is used to determine\n");
++             WRITE_TO_BUF("    # the link to use. Normally the weight is\n")
++             WRITE_TO_BUF("    # automatically calculated by olsrd based\n");
++             WRITE_TO_BUF("    # on the characteristics of the interface,\n");
++             WRITE_TO_BUF("    # but here you can specify a fixed value.\n");
++             WRITE_TO_BUF("    # Olsrd will choose links with the lowest value.\n")
++             WRITE_TO_BUF("    # Note:\n");
++             WRITE_TO_BUF("    # Interface weight is used only when LinkQualityLevel is 0.\n");
++             WRITE_TO_BUF("    # For any other value of LinkQualityLevel, the interface ETX\n");
++             WRITE_TO_BUF("    # value is used instead.\n\n");
++            }
+         if(in->cnf->weight.fixed)
+           {
+             WRITE_TO_BUF("    Weight\t %d\n\n", in->cnf->weight.value)
+diff -Naur olsrd-0.4.10/src/defs.h olsrd-0.4.10-patched/src/defs.h
+--- olsrd-0.4.10/src/defs.h    2006-01-01 16:59:02.000000000 +0100
++++ olsrd-0.4.10-patched/src/defs.h    2006-09-13 15:24:48.000000000 +0200
+@@ -72,7 +72,7 @@
+ #define       MAXMESSAGESIZE          1500    /* max broadcast size */
+ #define UDP_IPV4_HDRSIZE        28
+ #define UDP_IPV6_HDRSIZE        48
+-#define MAX_IFS                 16
++#define MAX_IFS                 32
+ /* Debug helper macro */
+ #ifdef DEBUG
+diff -Naur olsrd-0.4.10/src/link_set.c olsrd-0.4.10-patched/src/link_set.c
+--- olsrd-0.4.10/src/link_set.c        2005-11-17 05:25:44.000000000 +0100
++++ olsrd-0.4.10-patched/src/link_set.c        2006-11-16 13:49:17.000000000 +0100
+@@ -263,7 +263,7 @@
+     if (!COMP_IP(&walker->neighbor->neighbor_main_addr, main_addr))
+       continue;
+-    // handle the non-LQ case
++    // handle the non-LQ, RFC-compliant case
+     if (olsr_cnf->lq_level == 0)
+     {
+@@ -297,7 +297,7 @@
+       }
+     }
+-    // handle the LQ case
++    // handle the LQ, non-RFC compliant case
+     else
+     {
+@@ -402,7 +402,8 @@
+   while(tmp_link_set)
+     {
+       if(COMP_IP(remote, &tmp_link_set->neighbor_iface_addr) &&
+-       COMP_IP(local, &tmp_link_set->local_iface_addr))
++         COMP_IP(local, &tmp_link_set->local_iface_addr) &&
++         COMP_IP(remote_main, &tmp_link_set->neighbor->neighbor_main_addr))
+       return tmp_link_set;
+       tmp_link_set = tmp_link_set->next;
+     }
+@@ -501,7 +502,12 @@
+   /* Copy the main address - make sure this is done every time
+    * as neighbors might change main address */
+-  COPY_IP(&neighbor->neighbor_main_addr, remote_main);
++  /* Erik Tromp - OOPS! Don't do this! Neighbor entries are hashed through their
++   * neighbor_main_addr field, and when that field is changed, their position
++   * in the hash table is no longer correct, so that the function
++   * olsr_lookup_neighbor_table() can no longer find the neighbor
++   * entry. */
++  /*COPY_IP(&neighbor->neighbor_main_addr, remote_main);*/
+   neighbor->linkcount++;
+@@ -516,9 +522,14 @@
+        * We'll go for one that is hopefully long
+        * enough in most cases. 10 seconds
+        */
+-      OLSR_PRINTF(1, "Adding MID alias main %s ", olsr_ip_to_string(remote_main))
+-      OLSR_PRINTF(1, "-> %s based on HELLO\n\n", olsr_ip_to_string(remote))
+-      insert_mid_alias(remote_main, remote, MID_ALIAS_HACK_VTIME);
++    /* Erik Tromp - commented out. It is not RFC-compliant. Also, MID aliases
++     * that are not explicitly declared by a node will be removed as soon as
++     * the olsr_prune_aliases(...) function is called.
++     *
++     * OLSR_PRINTF(1, "Adding MID alias main %s ", olsr_ip_to_string(remote_main))
++     * OLSR_PRINTF(1, "-> %s based on HELLO\n\n", olsr_ip_to_string(remote))
++     * insert_mid_alias(remote_main, remote, MID_ALIAS_HACK_VTIME);
++     */
+     }
+   return link_set;
+diff -Naur olsrd-0.4.10/src/linux/net.h olsrd-0.4.10-patched/src/linux/net.h
+--- olsrd-0.4.10/src/linux/net.h       2005-08-28 21:30:30.000000000 +0200
++++ olsrd-0.4.10-patched/src/linux/net.h       2006-09-18 01:09:50.000000000 +0200
+@@ -55,8 +55,7 @@
+ #include <syslog.h>
+ #include <netinet/in.h>
+ #include "../olsr_protocol.h"
+-
+-#define MAXIFS                  8 /* Maximum number of network interfaces */
++#include "../defs.h" /* MAX_IFS */ 
+ /* Redirect proc entry */
+ #define REDIRECT_PROC "/proc/sys/net/ipv4/conf/%s/send_redirects"
+@@ -77,7 +76,7 @@
+   struct nic_state *next;
+ };
+-struct nic_state nic_states[MAXIFS];
++struct nic_state nic_states[MAX_IFS];
+ extern int
+diff -Naur olsrd-0.4.10/src/local_hna_set.c olsrd-0.4.10-patched/src/local_hna_set.c
+--- olsrd-0.4.10/src/local_hna_set.c   2005-02-27 19:39:43.000000000 +0100
++++ olsrd-0.4.10-patched/src/local_hna_set.c   2006-09-20 09:55:20.000000000 +0200
+@@ -129,6 +129,45 @@
+   return 0;
+ }
++struct hna4_entry *
++find_local_hna4_entry(union olsr_ip_addr *net, olsr_u32_t mask)
++{
++  struct hna4_entry *h4 = olsr_cnf->hna4_entries;
++
++  while(h4)
++    {
++      if((net->v4 == h4->net.v4) && 
++       (mask == h4->netmask.v4))
++      {
++        return h4;
++      }
++      h4 = h4->next;
++    }
++
++  return NULL;
++}
++
++
++
++struct hna6_entry *
++find_local_hna6_entry(union olsr_ip_addr *net, olsr_u16_t prefix_len)
++{
++  struct hna6_entry *h6 = olsr_cnf->hna6_entries;
++
++  while(h6)
++    {
++      if((memcmp(net, &h6->net, ipsize) == 0) && 
++       (prefix_len == h6->prefix_len))
++      {
++        return h6;
++      }
++      h6 = h6->next;
++    }
++
++  return NULL;
++}
++
++
+ int
+diff -Naur olsrd-0.4.10/src/local_hna_set.h olsrd-0.4.10-patched/src/local_hna_set.h
+--- olsrd-0.4.10/src/local_hna_set.h   2005-02-20 19:52:18.000000000 +0100
++++ olsrd-0.4.10-patched/src/local_hna_set.h   2006-09-20 09:55:42.000000000 +0200
+@@ -58,6 +58,12 @@
+ int
+ remove_local_hna6_entry(union olsr_ip_addr *, olsr_u16_t);
++struct hna4_entry *
++find_local_hna4_entry(union olsr_ip_addr *net, olsr_u32_t mask);
++
++struct hna6_entry *
++find_local_hna6_entry(union olsr_ip_addr *net, olsr_u16_t prefix_len);
++
+ int
+ check_inet_gw(void);
+diff -Naur olsrd-0.4.10/src/lq_mpr.c olsrd-0.4.10-patched/src/lq_mpr.c
+--- olsrd-0.4.10/src/lq_mpr.c  2005-11-29 19:37:58.000000000 +0100
++++ olsrd-0.4.10-patched/src/lq_mpr.c  2006-11-16 15:18:33.000000000 +0100
+@@ -51,7 +51,7 @@
+   struct neighbor_list_entry *walker;
+   int i, k;
+   struct neighbor_entry *neigh;
+-  double best;
++  double best, best_1hop;
+   olsr_bool mpr_changes = OLSR_FALSE;
+   struct link_entry *link;
+@@ -90,6 +90,8 @@
+            neigh2 != &two_hop_neighbortable[i];
+            neigh2 = neigh2->next)
+         {
++          best_1hop = -1.0;
++
+           // check whether this 2-hop neighbour is also a neighbour
+           neigh = olsr_lookup_neighbor_table(&neigh2->neighbor_2_addr);
+@@ -110,14 +112,14 @@
+             if(!link)
+               continue;
+-              best = link->loss_link_quality * link->neigh_link_quality;
++              best_1hop = link->loss_link_quality * link->neigh_link_quality;
+               // see wether we find a better route via an MPR
+               for (walker = neigh2->neighbor_2_nblist.next;
+                    walker != &neigh2->neighbor_2_nblist;
+                    walker = walker->next)
+-                if (walker->path_link_quality > best)
++                if (walker->path_link_quality > best_1hop)
+                   break;
+               // we've reached the end of the list, so we haven't found
+@@ -157,7 +159,10 @@
+                     best = walker->path_link_quality;
+                   }
+-              if (neigh != NULL)
++              // Found a 1-hop neighbor that we haven't previously selected.
++              // Use it as MPR only when the 2-hop path through it is better than
++              // any existing 1-hop path.
++              if ((neigh != NULL) && (best > best_1hop))
+                 {
+                   neigh->is_mpr = OLSR_TRUE;
+                   neigh->skip = OLSR_TRUE;
+diff -Naur olsrd-0.4.10/src/mid_set.c olsrd-0.4.10-patched/src/mid_set.c
+--- olsrd-0.4.10/src/mid_set.c 2005-05-29 14:47:45.000000000 +0200
++++ olsrd-0.4.10-patched/src/mid_set.c 2006-11-13 14:29:14.000000000 +0100
+@@ -46,6 +46,7 @@
+ #include "scheduler.h"
+ #include "neighbor_table.h"
+ #include "link_set.h"
++#include "packet.h" /* struct mid_alias */
+ struct mid_entry mid_set[HASHSIZE];
+@@ -99,6 +100,7 @@
+   struct mid_entry *tmp;
+   struct mid_address *tmp_adr;
+   olsr_u32_t hash, alias_hash;
++  union olsr_ip_addr *registered_m_addr;
+   hash = olsr_hashing(m_addr);
+   alias_hash = olsr_hashing(&alias->alias);
+@@ -110,8 +112,16 @@
+     {
+       if(COMP_IP(&tmp->main_addr, m_addr))
+       break;
++     }
++
++  /* Check if alias is already registered with m_addr */
++  registered_m_addr = mid_lookup_main_addr(&alias->alias);
++  if (registered_m_addr != NULL && COMP_IP(registered_m_addr, m_addr))
++    {
++      /* Alias is already registered with main address. Nothing to do here. */
++      return;
+     }
+-       
++
+   /*If the address was registered*/ 
+   if(tmp != &mid_set[hash])
+     {
+@@ -312,7 +322,7 @@
+       /*find match*/
+       if(COMP_IP(&tmp_list->main_addr, adr))
+       {
+-        //printf("Updating timer for node %s\n",ip_to_string(&tmp_list->main_addr));
++        // printf("MID: Updating timer for node %s\n", olsr_ip_to_string(&tmp_list->main_addr));
+         tmp_list->ass_timer = GET_TIMESTAMP(vtime*1000);
+         return 1;
+@@ -322,6 +332,91 @@
+ }
++/**
++ *Remove aliases from 'entry' which are not listed in 'declared_aliases'.
++ *
++ *@param entry the MID entry
++ *@param declared_aliases the list of declared aliases for the MID entry
++ *
++ *@return nada
++ */
++void
++olsr_prune_aliases(union olsr_ip_addr *m_addr, struct mid_alias *declared_aliases)
++{
++  struct mid_entry *entry;
++  olsr_u32_t hash;
++  struct mid_address *registered_aliases;
++  struct mid_address *previous_alias;
++  struct mid_alias *save_declared_aliases = declared_aliases;
++
++  hash = olsr_hashing(m_addr);
++
++  /* Check for registered entry */
++  for(entry = mid_set[hash].next;
++      entry != &mid_set[hash];
++      entry = entry->next)
++    {
++      if(COMP_IP(&entry->main_addr, m_addr))
++      break;
++    }
++  if(entry == &mid_set[hash])
++    {
++      /* MID entry not found, nothing to prune here */
++      return;
++    }
++
++  registered_aliases = entry->aliases;
++  previous_alias = NULL;
++
++  while(registered_aliases != 0)
++    {
++      struct mid_address *current_alias = registered_aliases;
++      registered_aliases = registered_aliases->next_alias;
++
++      declared_aliases = save_declared_aliases;
++
++      /* Go through the list of declared aliases to find the matching current alias */
++      while(declared_aliases != 0 &&
++            ! COMP_IP(&current_alias->alias, &declared_aliases->alias_addr))
++        {
++          declared_aliases = declared_aliases->next;
++        }
++
++      if (declared_aliases == 0)
++        {
++          /* Current alias not found in list of declared aliases: free current alias */
++          OLSR_PRINTF(1, "MID remove: (%s, ", olsr_ip_to_string(&entry->main_addr))
++          OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&current_alias->alias))
++
++          /* Update linked list as seen by 'entry' */
++          if (previous_alias != NULL)
++            {
++              previous_alias->next_alias = current_alias->next_alias;
++            }
++          else
++            {
++              entry->aliases = current_alias->next_alias;
++            }
++
++          /* Remove from hash table */
++          DEQUEUE_ELEM(current_alias);
++ 
++          free(current_alias);
++
++          /*
++           *Recalculate topology
++           */
++          changes_neighborhood = OLSR_TRUE;
++          changes_topology = OLSR_TRUE;
++        }
++      else
++        {
++          previous_alias = current_alias;
++        }
++    }
++}
++
++
+ /**
+  *Find timed out entries and delete them
+diff -Naur olsrd-0.4.10/src/mid_set.h olsrd-0.4.10-patched/src/mid_set.h
+--- olsrd-0.4.10/src/mid_set.h 2005-05-29 14:47:45.000000000 +0200
++++ olsrd-0.4.10-patched/src/mid_set.h 2006-11-08 13:35:44.000000000 +0100
+@@ -73,6 +73,7 @@
+ extern struct mid_entry mid_set[HASHSIZE];
+ extern struct mid_address reverse_mid_set[HASHSIZE];
++struct mid_alias;
+ int
+ olsr_init_mid_set(void);
+@@ -95,6 +96,9 @@
+ void
+ olsr_time_out_mid_set(void *);
++void
++olsr_prune_aliases(union olsr_ip_addr *m_addr, struct mid_alias *declared_aliases);
++
+ int
+ olsr_update_mid_table(union olsr_ip_addr *, float);
+diff -Naur olsrd-0.4.10/src/olsr.c olsrd-0.4.10-patched/src/olsr.c
+--- olsrd-0.4.10/src/olsr.c    2005-11-17 05:25:44.000000000 +0100
++++ olsrd-0.4.10-patched/src/olsr.c    2006-11-09 14:12:24.000000000 +0100
+@@ -217,13 +217,17 @@
+         
+           if (olsr_cnf->debug_level > 3)
+             {
+-              olsr_print_duplicate_table();
++              if (olsr_cnf->debug_level > 8)
++                {
++                  olsr_print_duplicate_table();
++                }
+               olsr_print_hna_set();
+             }
+         }
+       
+       olsr_print_link_set();
+       olsr_print_neighbor_table();
++      olsr_print_two_hop_neighbor_table();
+       olsr_print_tc_table();
+     }
+diff -Naur olsrd-0.4.10/src/process_package.c olsrd-0.4.10-patched/src/process_package.c
+--- olsrd-0.4.10/src/process_package.c 2005-11-29 19:38:40.000000000 +0100
++++ olsrd-0.4.10-patched/src/process_package.c 2006-11-24 12:19:33.000000000 +0100
+@@ -52,6 +52,7 @@
+ #include "parser.h"
+ #include "duplicate_set.h"
+ #include "rebuild_packet.h"
++#include "local_hna_set.h"
+ /**
+@@ -406,6 +407,8 @@
+       tmp_adr = tmp_adr->next;
+     } 
+   
++  olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
++
+  forward:  
+   olsr_forward_message(m, 
+                      &message.mid_origaddr, 
+@@ -470,8 +473,13 @@
+   while(hna_tmp)
+     {
+-      olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime); 
+-      
++      /* Don't add an HNA entry that we are advertising ourselves. */
++      if (!find_local_hna4_entry(&hna_tmp->net, hna_tmp->netmask.v4) &&
++          !find_local_hna6_entry(&hna_tmp->net, hna_tmp->netmask.v6))
++        {
++          olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime);
++        } 
++
+       hna_tmp = hna_tmp->next;
+     }
+@@ -494,7 +502,7 @@
+ /**
+  *Processes an list of neighbors from an incoming HELLO message.
+- *@param neighbor the neighbor who sendt the message.
++ *@param neighbor the neighbor who sent the message.
+  *@param message the HELLO message
+  *@return nada
+  */
+@@ -539,6 +547,31 @@
+               /* Updating the holding time for this neighbor */
+               two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
+               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
++
++              // For link quality OLSR, reset the path link quality here.
++              // The path link quality will be calculated in the second pass, below.
++              // Keep the saved_path_link_quality for reference.
++
++              if (olsr_cnf->lq_level > 0)
++                {
++                  // loop through the one-hop neighbors that see this
++                  // 'two_hop_neighbor'
++
++                  struct neighbor_list_entry *walker;
++
++                  for (walker = two_hop_neighbor->neighbor_2_nblist.next;
++                       walker != &two_hop_neighbor->neighbor_2_nblist;
++                       walker = walker->next)
++                    {
++                      // have we found the one-hop neighbor that sent the
++                      // HELLO message that we're current processing?
++
++                      if (walker->neighbor == neighbor)
++                        {
++                          walker->path_link_quality = 0.0;
++                        }
++                    }
++                }
+             }
+           else
+             {
+@@ -586,19 +619,48 @@
+                                               (float)message->vtime); 
+                 }
+             }
++        }
++    }
+-          if (olsr_cnf->lq_level > 0)
++  // Separate, second and third pass for link quality OLSR
++
++  if (olsr_cnf->lq_level > 0)
++    {
++      struct link_entry *link =
++        get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
++
++      if(!link)
++      return;
++
++      // Second pass for link quality OLSR: calculate the best 2-hop
++      // path costs to all the 2-hop neighbors indicated in the
++      // HELLO message. Since the same 2-hop neighbor may be listed
++      // more than once in the same HELLO message (each at a possibly
++      // different quality) we want to select only the best one, not just
++      // the last one listed in the HELLO message.
++
++      for(message_neighbors = message->neighbors;
++          message_neighbors != NULL;
++          message_neighbors = message_neighbors->next)
++        {
++          if(if_ifwithaddr(&message_neighbors->address) != NULL)
++            continue;
++
++          if(((message_neighbors->status == SYM_NEIGH) ||
++              (message_neighbors->status == MPR_NEIGH)))
+             {
+-            struct neighbor_list_entry *walker;
+-            struct link_entry *link;
++              struct neighbor_list_entry *walker;
++              struct neighbor_2_entry *two_hop_neighbor;
++              struct neighbor_2_list_entry *two_hop_neighbor_yet =
++                olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
+-              link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
++              if(!two_hop_neighbor_yet)
++                continue;
+-            if(!link)
+-              continue;
++              two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
+               // loop through the one-hop neighbors that see this
+-              // two hop neighbour
++              // 'two_hop_neighbor'
+               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
+                    walker != &two_hop_neighbor->neighbor_2_nblist;
+@@ -609,14 +671,7 @@
+                   if (walker->neighbor == neighbor)
+                     {
+-                      double saved_lq, rel_lq;
+-
+-                      // saved previous total link quality
+-
+-                      saved_lq = walker->saved_path_link_quality;
+-
+-                      if (saved_lq == 0.0)
+-                        saved_lq = -1.0;
++                      double new_second_hop_link_quality, new_path_link_quality;
+                       // path link quality = link quality between us
+                       // and our one-hop neighbor x link quality between
+@@ -633,18 +688,75 @@
+                       // the link quality between the 1-hop neighbour and the
+                       // 2-hop neighbour
+-                      walker->second_hop_link_quality =
++                      new_second_hop_link_quality = 
+                         message_neighbors->link_quality *
+                         message_neighbors->neigh_link_quality;
+                       // the total quality for the route
+                       // "us --- 1-hop --- 2-hop"
+-                      walker->path_link_quality =
+-                        walker->second_hop_link_quality *
++                      new_path_link_quality =
++                        new_second_hop_link_quality *
+                         link->loss_link_quality * link->neigh_link_quality;
+-                      // if the link quality has changed by more than 10
++                      // Only copy the link quality if it is better than what we have
++                      // for this 2-hop neighbor
++                      if (new_path_link_quality > walker->path_link_quality)
++                        {
++                          walker->second_hop_link_quality = new_second_hop_link_quality;
++                          walker->path_link_quality = new_path_link_quality;
++                        }
++                    }
++                }
++            }
++        }
++
++      // Third pass for link quality OLSR: check if the 2-hop path qualities have
++      // actually changed. If so, signal this through the 'changes_neighborhood'
++      // and 'changes_topology' booleans. Keep a 'saved_path_link_quality' for
++      // later reference.
++      for(message_neighbors = message->neighbors;
++          message_neighbors != NULL;
++          message_neighbors = message_neighbors->next)
++        {
++          if(if_ifwithaddr(&message_neighbors->address) != NULL)
++            continue;
++
++          if(((message_neighbors->status == SYM_NEIGH) ||
++              (message_neighbors->status == MPR_NEIGH)))
++            {
++              struct neighbor_list_entry *walker;
++              struct neighbor_2_entry *two_hop_neighbor;
++              struct neighbor_2_list_entry *two_hop_neighbor_yet =
++                olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
++
++              if(!two_hop_neighbor_yet)
++                continue;
++
++              two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
++
++              // loop through the one-hop neighbors that see this
++              // 'two_hop_neighbor'
++
++              for (walker = two_hop_neighbor->neighbor_2_nblist.next;
++                   walker != &two_hop_neighbor->neighbor_2_nblist;
++                   walker = walker->next)
++                {
++                  // have we found the one-hop neighbor that sent the
++                  // HELLO message that we're current processing?
++
++                  if (walker->neighbor == neighbor)
++                    {
++                      double saved_lq, rel_lq;
++
++                      // saved previous total link quality
++
++                      saved_lq = walker->saved_path_link_quality;
++
++                      if (saved_lq == 0.0)
++                        saved_lq = -1.0;
++
++                      // if the link cost has changed by more than 10
+                       // percent, signal
+                       rel_lq = walker->path_link_quality / saved_lq;
+diff -Naur olsrd-0.4.10/src/routing_table.c olsrd-0.4.10-patched/src/routing_table.c
+--- olsrd-0.4.10/src/routing_table.c   2005-11-17 00:55:54.000000000 +0100
++++ olsrd-0.4.10-patched/src/routing_table.c   2006-11-26 12:08:12.004604584 +0100
+@@ -65,10 +65,10 @@
+ olsr_fill_routing_table_with_two_hop_neighbors(void);
+ static struct rt_entry *
+-olsr_check_for_higher_hopcount(struct rt_entry *, struct hna_net *, olsr_u16_t);
++olsr_check_for_higher_quality(struct rt_entry *, struct hna_net *, float);
+ struct rt_entry *
+-olsr_check_for_lower_hopcount(struct rt_entry *, struct hna_net *, olsr_u16_t);
++olsr_check_for_lower_quality(struct rt_entry *, struct hna_net *, float);
+ static olsr_bool
+ two_hop_neighbor_reachable(struct neighbor_2_list_entry *);
+@@ -212,7 +212,12 @@
+   new_route_entry->rt_if = iface;
+   new_route_entry->rt_metric = metric;
+-  new_route_entry->rt_etx = etx;
++  if (etx< 0.0)
++    /* non-LQ case */
++    new_route_entry->rt_etx = (float)metric;
++  else
++    /* LQ case */
++    new_route_entry->rt_etx = etx;
+   
+   if(COMP_IP(dst, router))
+     /* Not GW */
+@@ -289,7 +294,7 @@
+                                                   &link->neighbor_iface_addr,
+                                                   iface,
+                                                   1,
+-                                                  0);
++                                                  -1.0);
+                       }
+                   }
+             
+@@ -404,7 +409,7 @@
+                                                     &link->neighbor_iface_addr,
+                                                     iface,
+                                                     2,
+-                                                    0);
++                                                    -1.0);
+                         
+                         if(new_route_entry != NULL)
+                           {
+@@ -501,7 +506,7 @@
+                                                     &list_destination_n->destination->rt_router, 
+                                                     list_destination_n->destination->rt_if,
+                                                     list_destination_n->destination->rt_metric+1,
+-                                                    0);
++                                                    -1.0);
+                         if(destination_n_1->destination != NULL)
+                           {
+                             destination_n_1->next=list_destination_n_1;
+@@ -549,17 +554,17 @@
+ /**
+- *Check for a entry with a higher hopcount than
++ *Check for an entry with a higher quality (lower etx) than
+  *a given value in a routing table
+  *
+  *@param routes the routingtable to look in
+  *@param net the network entry to look for
+- *@param metric the metric to check for
++ *@param etx the metric to check for
+  *
+- *@return the localted entry if found. NULL if not
++ *@return the located entry if found. NULL if not
+  */
+ static struct rt_entry *
+-olsr_check_for_higher_hopcount(struct rt_entry *routes, struct hna_net *net, olsr_u16_t metric)
++olsr_check_for_higher_quality(struct rt_entry *routes, struct hna_net *net, float etx)
+ {
+   int index;
+@@ -574,8 +579,8 @@
+         if(COMP_IP(&tmp_routes->rt_dst, &net->A_network_addr) &&
+            (memcmp(&tmp_routes->rt_mask, &net->A_netmask, netmask_size) == 0))
+           {
+-            /* Found a entry */
+-            if(tmp_routes->rt_metric > metric)
++            /* Found an entry */
++            if(tmp_routes->rt_etx < etx)
+               return tmp_routes;
+             else
+               return NULL;
+@@ -589,17 +594,17 @@
+ /**
+- *Check for a entry with a lower or equal hopcount than
++ *Check for an entry with a lower or equal quality (higher or equal etx) than
+  *a given value in a routing table
+  *
+  *@param routes the routingtable to look in
+  *@param net the network entry to look for
+- *@param metric the metric to check for
++ *@param etx the metric to check for
+  *
+- *@return the localted entry if found. NULL if not
++ *@return the located entry if found. NULL if not
+  */
+ struct rt_entry *
+-olsr_check_for_lower_hopcount(struct rt_entry *routes, struct hna_net *net, olsr_u16_t metric)
++olsr_check_for_lower_quality(struct rt_entry *routes, struct hna_net *net, float etx)
+ {
+   int index;
+@@ -614,8 +619,8 @@
+         if(COMP_IP(&tmp_routes->rt_dst, &net->A_network_addr) &&
+            (memcmp(&tmp_routes->rt_mask, &net->A_netmask, netmask_size) == 0))
+           {
+-            /* Found a entry */
+-            if(tmp_routes->rt_metric <= metric)
++            /* Found an entry */
++            if(tmp_routes->rt_etx >= etx)
+               return tmp_routes;
+             else
+               return NULL;
+@@ -672,13 +677,13 @@
+               }
+             /* If there exists a better or equal entry - skip */
+-            if(olsr_check_for_lower_hopcount(hna_routes, tmp_net, tmp_rt->rt_metric) != NULL)
++            if(olsr_check_for_higher_quality(hna_routes, tmp_net, tmp_rt->rt_etx) != NULL)
+               {
+                 continue;
+               }
+-            /* If we find an entry with higher hopcount we just edit it */
+-            if((new_rt = olsr_check_for_higher_hopcount(hna_routes, tmp_net, tmp_rt->rt_metric)) != NULL)
++            /* If we find an entry with lower quality we just edit it */
++            if((new_rt = olsr_check_for_lower_quality(hna_routes, tmp_net, tmp_rt->rt_etx)) != NULL)
+               {
+                 /* Fill struct */
+                 /* Net */
+@@ -687,6 +692,7 @@
+                 /* Gateway */
+                 COPY_IP(&new_rt->rt_router, &tmp_rt->rt_router);
+                 /* Metric */
++                new_rt->rt_etx = tmp_rt->rt_etx;
+                 new_rt->rt_metric = tmp_rt->rt_metric;
+                 /* Flags */
+                 new_rt->rt_flags = RTF_UP | RTF_GATEWAY;
+@@ -707,6 +713,7 @@
+                 /* Gateway */
+                 COPY_IP(&new_rt->rt_router, &tmp_rt->rt_router);
+                 /* Metric */
++                new_rt->rt_etx = tmp_rt->rt_etx;
+                 new_rt->rt_metric = tmp_rt->rt_metric;
+                 /* Flags */
+                 new_rt->rt_flags = RTF_UP | RTF_GATEWAY;
+diff -Naur olsrd-0.4.10/src/unix/ifnet.c olsrd-0.4.10-patched/src/unix/ifnet.c
+--- olsrd-0.4.10/src/unix/ifnet.c      2005-12-29 19:37:16.000000000 +0100
++++ olsrd-0.4.10-patched/src/unix/ifnet.c      2006-11-16 13:14:42.000000000 +0100
+@@ -308,9 +308,11 @@
+         OLSR_PRINTF(1, "IPv4 address changed for %s\n", ifr.ifr_name)
+         OLSR_PRINTF(1, "\tOld:%s\n", sockaddr_to_string(&ifp->int_addr))
+         OLSR_PRINTF(1, "\tNew:%s\n", sockaddr_to_string(&ifr.ifr_addr))
++
++          ifp->int_addr = ifr.ifr_addr;
+         
+         if(memcmp(&main_addr, 
+-                  &((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr, 
++                  &ifp->ip_addr, 
+                   ipsize) == 0)
+           {
+             OLSR_PRINTF(1, "New main address: %s\n", sockaddr_to_string(&ifr.ifr_addr))
+@@ -320,7 +322,6 @@
+                    ipsize);
+           }
+-        ifp->int_addr = ifr.ifr_addr;
+         memcpy(&ifp->ip_addr, 
+                &((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr, 
+                ipsize);
+@@ -845,7 +846,6 @@
+   ifs.if_index = if_nametoindex(ifr.ifr_name);
+   
+   /* Set interface metric */
+-  /* Set interface metric */
+   if(iface->cnf->weight.fixed)
+     ifs.int_metric = iface->cnf->weight.value;
+   else
diff --git a/net/olsrd/patches/210-olsrd-fixes-sven-ola.patch b/net/olsrd/patches/210-olsrd-fixes-sven-ola.patch
new file mode 100644 (file)
index 0000000..4232df5
--- /dev/null
@@ -0,0 +1,212 @@
+diff -Nur olsrd-0.4.10.orig/src/defs.h olsrd-0.4.10/src/defs.h
+--- olsrd-0.4.10.orig/src/defs.h       2006-11-28 21:17:27.000000000 +0100
++++ olsrd-0.4.10/src/defs.h    2006-11-28 21:18:46.000000000 +0100
+@@ -68,10 +68,10 @@
+ #define OLSRD_GLOBAL_CONF_FILE "/etc/" OLSRD_CONF_FILE_NAME
+ #endif
+-#define       HOPCNT_MAX              32      /* maximum hops number */
++#define       HOPCNT_MAX              64      /* maximum hops number */
+ #define       MAXMESSAGESIZE          1500    /* max broadcast size */
+ #define UDP_IPV4_HDRSIZE        28
+-#define UDP_IPV6_HDRSIZE        48
++#define UDP_IPV6_HDRSIZE        62
+ #define MAX_IFS                 32
+ /* Debug helper macro */
+diff -Nur olsrd-0.4.10.orig/src/interfaces.h olsrd-0.4.10/src/interfaces.h
+--- olsrd-0.4.10.orig/src/interfaces.h 2005-06-03 10:00:55.000000000 +0200
++++ olsrd-0.4.10/src/interfaces.h      2006-11-28 21:18:01.000000000 +0100
+@@ -136,6 +136,8 @@
+   struct        vtimes valtimes;
+   struct        if_gen_property *gen_properties;/* Generic interface properties */
++  
++  int           ttl_index; /* index in TTL array for fish-eye */
+   struct      interface *int_next;
+ };
+diff -Nur olsrd-0.4.10.orig/src/link_set.c olsrd-0.4.10/src/link_set.c
+--- olsrd-0.4.10.orig/src/link_set.c   2006-11-28 21:17:27.000000000 +0100
++++ olsrd-0.4.10/src/link_set.c        2006-11-28 21:18:01.000000000 +0100
+@@ -963,8 +963,9 @@
+   entry->loss_link_quality =
+     (float)(entry->total_packets - entry->lost_packets) /
+-    (float)(entry->loss_window_size);
+-
++    (float)(entry->loss_window_size < (2 * 4) ? entry->loss_window_size: 
++    4 * ((entry->loss_window_size / 4 - 1) * entry->total_packets + entry->loss_window_size) / entry->loss_window_size);
++    
+   // multiply the calculated link quality with the user-specified multiplier
+   entry->loss_link_quality *= entry->loss_link_multiplier;
+diff -Nur olsrd-0.4.10.orig/src/lq_packet.c olsrd-0.4.10/src/lq_packet.c
+--- olsrd-0.4.10.orig/src/lq_packet.c  2005-11-17 02:58:51.000000000 +0100
++++ olsrd-0.4.10/src/lq_packet.c       2006-11-28 21:18:01.000000000 +0100
+@@ -149,9 +149,8 @@
+   int i;
+   struct neighbor_entry *walker;
+   struct link_entry *link;
+-  static int ttl_list[] = { MAX_TTL, 3, 2, 1, 2, 1, 1, 3, 2, 1, 2, 1, 1, 0 };
+-  static int ttl_index = 0;
+-
++  static int ttl_list[] = { 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, MAX_TTL-1, 0};
++  
+   // remember that we have generated an LQ TC message; this is
+   // checked in net_output()
+@@ -167,10 +166,13 @@
+   if (olsr_cnf->lq_fish > 0)
+   {
+-    if (ttl_list[ttl_index] == 0)
+-      ttl_index = 0;
++    // SVEN_OLA: Too lazy to find the different iface inits. This will do it too.
++    if (outif->ttl_index >= sizeof(ttl_list) / sizeof(ttl_list[0])) outif->ttl_index = 0;
++    
++    if (ttl_list[outif->ttl_index] == 0)
++      outif->ttl_index = 0;
+-    lq_tc->comm.ttl = ttl_list[ttl_index++];
++    lq_tc->comm.ttl = ttl_list[outif->ttl_index++];
+     OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
+   }
+diff -Nur olsrd-0.4.10.orig/src/olsr.c olsrd-0.4.10/src/olsr.c
+--- olsrd-0.4.10.orig/src/olsr.c       2006-11-28 21:17:27.000000000 +0100
++++ olsrd-0.4.10/src/olsr.c    2006-11-28 21:18:01.000000000 +0100
+@@ -68,6 +68,7 @@
+ olsr_bool changes_topology;
+ olsr_bool changes_neighborhood;
+ olsr_bool changes_hna;
++olsr_bool changes_force;
+ /**
+  * Process changes functions
+@@ -142,6 +143,11 @@
+     OLSR_PRINTF(3, "CHANGES IN HNA\n")
+ #endif
+   
++  if(!changes_force &&
++     2 <= olsr_cnf->lq_level &&
++     0 >= olsr_cnf->lq_dlimit)
++    return;
++    
+   if(!changes_neighborhood &&
+      !changes_topology &&
+      !changes_hna)
+@@ -171,11 +177,6 @@
+           olsr_calculate_routing_table();
+           olsr_calculate_hna_routes();
+         }
+-
+-      else
+-        {
+-          olsr_calculate_lq_routing_table();
+-        }
+     }
+   
+   else if (changes_topology)
+@@ -187,11 +188,6 @@
+           olsr_calculate_routing_table();
+           olsr_calculate_hna_routes();
+         }
+-
+-      else
+-        {
+-          olsr_calculate_lq_routing_table();
+-        }
+     }
+   else if (changes_hna)
+@@ -202,11 +198,11 @@
+         {
+           olsr_calculate_hna_routes();
+         }
+-
+-      else
+-        {
+-          olsr_calculate_lq_routing_table();
+-        }
++    }
++  
++  if (olsr_cnf->lq_level >= 2)
++    {
++      olsr_calculate_lq_routing_table();
+     }
+   
+   if (olsr_cnf->debug_level > 0)
+@@ -243,6 +239,7 @@
+   changes_neighborhood = OLSR_FALSE;
+   changes_topology = OLSR_FALSE;
+   changes_hna = OLSR_FALSE;
++  changes_force = OLSR_FALSE;
+   return;
+diff -Nur olsrd-0.4.10.orig/src/olsr.h olsrd-0.4.10/src/olsr.h
+--- olsrd-0.4.10.orig/src/olsr.h       2005-05-29 14:47:45.000000000 +0200
++++ olsrd-0.4.10/src/olsr.h    2006-11-28 21:18:01.000000000 +0100
+@@ -49,6 +49,7 @@
+ extern olsr_bool changes_topology;
+ extern olsr_bool changes_neighborhood;
+ extern olsr_bool changes_hna;
++extern olsr_bool changes_force;
+ void
+ register_pcf(int (*)(int, int, int));
+diff -Nur olsrd-0.4.10.orig/src/scheduler.c olsrd-0.4.10/src/scheduler.c
+--- olsrd-0.4.10.orig/src/scheduler.c  2005-12-29 23:34:37.000000000 +0100
++++ olsrd-0.4.10/src/scheduler.c       2006-11-28 21:18:01.000000000 +0100
+@@ -70,6 +70,7 @@
+   changes_neighborhood = OLSR_TRUE;
+   changes_topology = OLSR_TRUE;
++  changes_force = OLSR_TRUE;
+ }
+ /**
+diff -Nur olsrd-0.4.10.orig/src/unix/ifnet.c olsrd-0.4.10/src/unix/ifnet.c
+--- olsrd-0.4.10.orig/src/unix/ifnet.c 2006-11-28 21:17:27.000000000 +0100
++++ olsrd-0.4.10/src/unix/ifnet.c      2006-11-28 21:18:01.000000000 +0100
+@@ -690,6 +690,17 @@
+   return 1;
+ }
++static char basename[32];
++char* if_basename(char* name);
++char* if_basename(char* name)
++{
++      char *p = strchr(name, ':');
++      if (0 == p || p - name >= (int)(sizeof(basename) / sizeof(basename[0]) - 1)) return name;
++      memcpy(basename, name, p - name);
++      basename[p - name] = 0;
++      return basename;
++}
++
+ /**
+  * Initializes a interface described by iface,
+  * if it is set up and is of the correct type.
+@@ -833,10 +844,10 @@
+       }
+       
+       /* Deactivate IP spoof filter */
+-      deactivate_spoof(ifr.ifr_name, iface->index, olsr_cnf->ip_version);
++      deactivate_spoof(if_basename(ifr.ifr_name), iface->index, olsr_cnf->ip_version);
+       
+       /* Disable ICMP redirects */
+-      disable_redirects(ifr.ifr_name, iface->index, olsr_cnf->ip_version);
++      disable_redirects(if_basename(ifr.ifr_name), iface->index, olsr_cnf->ip_version);
+       
+     }
+   
+@@ -894,7 +905,7 @@
+   ifp->gen_properties = NULL;
+   ifp->int_name = olsr_malloc(strlen(ifr.ifr_name) + 1, "Interface update 3");
+       
+-  strcpy(ifp->int_name, ifr.ifr_name);
++  strcpy(ifp->int_name, if_basename(ifr.ifr_name));
+   /* Segfaults if using strncpy(IFNAMSIZ) why oh why?? */
+   ifp->int_next = ifnet;
+   ifnet = ifp;
diff --git a/net/olsrd/patches/220-olsrd-fixes-jhay-bsd.patch b/net/olsrd/patches/220-olsrd-fixes-jhay-bsd.patch
new file mode 100644 (file)
index 0000000..4bb3d07
--- /dev/null
@@ -0,0 +1,425 @@
+diff -Nur olsrd-0.4.10.orig/src/bsd/kernel_routes.c olsrd-0.4.10/src/bsd/kernel_routes.c
+--- olsrd-0.4.10.orig/src/bsd/kernel_routes.c  2005-02-27 11:43:38.000000000 +0100
++++ olsrd-0.4.10/src/bsd/kernel_routes.c       2006-12-12 08:59:26.000000000 +0100
+@@ -170,12 +170,103 @@
+   return add_del_route(dest, 0);
+ }
+-int olsr_ioctl_add_route6(struct rt_entry *dest)
++static int add_del_route6(struct rt_entry *dest, int add)
+ {
++  struct rt_msghdr *rtm;
++  unsigned char buff[512];
++  unsigned char *walker;
++  struct sockaddr_in6 sin6;
++  struct sockaddr_dl sdl;
++  int step, step_dl;
++  int len;
++  char Str1[40], Str2[40];
++
++  inet_ntop(AF_INET6, &dest->rt_dst.v6, Str1, 40);
++  inet_ntop(AF_INET6, &dest->rt_router.v6, Str2, 40);
++
++  OLSR_PRINTF(1, "%s IPv6 route to %s/%d via %s.\n",
++    (add != 0) ? "Adding" : "Removing", Str1, dest->rt_mask.v6, Str2)
++
++  memset(buff, 0, sizeof (buff));
++  memset(&sin6, 0, sizeof (sin6));
++  memset(&sdl, 0, sizeof (sdl));
++
++  sin6.sin6_len = sizeof (sin6);
++  sin6.sin6_family = AF_INET6;
++  sdl.sdl_len = sizeof (sdl);
++  sdl.sdl_family = AF_LINK;
++
++  step = 1 + ((sizeof (struct sockaddr_in6) - 1) | 3);
++  step_dl = 1 + ((sizeof (struct sockaddr_dl) - 1) | 3);
++
++  rtm = (struct rt_msghdr *)buff;
++  rtm->rtm_version = RTM_VERSION;
++  rtm->rtm_type = (add != 0) ? RTM_ADD : RTM_DELETE;
++  rtm->rtm_index = 0;
++  rtm->rtm_flags = dest->rt_flags;
++  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
++  rtm->rtm_seq = ++seq;
++
++  walker = buff + sizeof (struct rt_msghdr);
++
++  memcpy(&sin6.sin6_addr.s6_addr, &dest->rt_dst.v6, sizeof(struct in6_addr));
++
++  memcpy(walker, &sin6, sizeof (sin6));
++  walker += step;
++
++  if ((rtm->rtm_flags & RTF_GATEWAY) != 0)
++  {
++    memcpy(&sin6.sin6_addr.s6_addr, &dest->rt_router.v6, sizeof(struct in6_addr));
++
++    memcpy(walker, &sin6, sizeof (sin6));
++    walker += step;
++  }
++
++  // the host is directly reachable, so add the output interface's address
++
++  else
++  {
++    memcpy(&sin6.sin6_addr.s6_addr, &dest->rt_if->int6_addr.sin6_addr.s6_addr,
++      sizeof(struct in6_addr));
++
++    memcpy(walker, &sin6, sizeof (sin6));
++    walker += step;
++    rtm->rtm_flags |= RTF_LLINFO;
++  }
++
++  if ((rtm->rtm_flags & RTF_HOST) == 0)
++  {
++    olsr_prefix_to_netmask((union olsr_ip_addr *)&sin6.sin6_addr, dest->rt_mask.v6);
++    memcpy(walker, &sin6, sizeof (sin6));
++    walker += step;
++    rtm->rtm_addrs |= RTA_NETMASK;
++  }
++
++  if ((rtm->rtm_flags & RTF_GATEWAY) != 0)
++  {
++    strcpy(&sdl.sdl_data[0], dest->rt_if->int_name);
++    sdl.sdl_nlen = (u_char)strlen(dest->rt_if->int_name);
++    memcpy(walker, &sdl, sizeof (sdl));
++    walker += step_dl;
++    rtm->rtm_addrs |= RTA_IFP;
++  }
++
++  rtm->rtm_msglen = (unsigned short)(walker - buff);
++
++  len = write(rts, buff, rtm->rtm_msglen);
++
++  if (len < rtm->rtm_msglen)
++    fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
++
+   return 0;
+ }
++int olsr_ioctl_add_route6(struct rt_entry *dest)
++{
++  return add_del_route6(dest, 1);
++}
++
+ int olsr_ioctl_del_route6(struct rt_entry *dest)
+ {
+-  return 0;
++  return add_del_route6(dest, 0);
+ }
+diff -Nur olsrd-0.4.10.orig/src/bsd/net.c olsrd-0.4.10/src/bsd/net.c
+--- olsrd-0.4.10.orig/src/bsd/net.c    2005-08-28 21:30:29.000000000 +0200
++++ olsrd-0.4.10/src/bsd/net.c 2006-12-12 08:59:30.000000000 +0100
+@@ -61,8 +61,10 @@
+ #endif
+ #ifdef __FreeBSD__
++#include <ifaddrs.h>
+ #include <net/if_var.h>
+ #include <net/ethernet.h>
++#include <netinet/in_var.h>
+ #ifndef FBSD_NO_80211
+ #include <net80211/ieee80211.h>
+ #include <net80211/ieee80211_ioctl.h>
+@@ -71,8 +73,8 @@
+ #endif
+ #endif
+-#ifdef SPOOF
+ #include <net/if_dl.h>
++#ifdef SPOOF
+ #include <libnet.h>
+ #endif /* SPOOF */
+@@ -172,6 +174,17 @@
+     name = "net.inet6.icmp6.rediraccept";
+   ignore_redir = set_sysctl_int(name, 0);
++#elif defined __FreeBSD__
++  if (olsr_cnf->ip_version == AF_INET)
++  {
++    name = "net.inet.icmp.drop_redirect";
++    ignore_redir = set_sysctl_int(name, 1);
++  }
++  else
++  {
++    name = "net.inet6.icmp6.rediraccept";
++    ignore_redir = set_sysctl_int(name, 0);
++  }
+ #else
+   if (olsr_cnf->ip_version == AF_INET)
+     name = "net.inet.icmp.drop_redirect";
+@@ -243,6 +256,12 @@
+   else
+     name = "net.inet6.icmp6.rediraccept";
++#elif defined __FreeBSD__
++  if (olsr_cnf->ip_version == AF_INET)
++    name = "net.inet.icmp.drop_redirect";
++
++  else
++    name = "net.inet6.icmp6.rediraccept";
+ #else
+   if (olsr_cnf->ip_version == AF_INET)
+     name = "net.inet.icmp.drop_redirect";
+@@ -335,7 +354,6 @@
+       return (-1);
+     }
+-#ifdef SPOOF
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEPORT failed");
+@@ -347,7 +365,6 @@
+       perror("IP_RECVIF failed");
+       return (-1);
+     }
+-#endif /* SPOOF */
+   for (on = bufspace; ; on -= 1024) 
+     {
+@@ -406,6 +423,18 @@
+       return (-1);
+     }
++  if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) 
++    {
++      perror("SO_REUSEPORT failed");
++      return (-1);
++    }
++
++  if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0)
++    {
++      perror("IPV6_RECVPKTINFO failed");
++      return (-1);
++    }
++
+   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
+     {
+       perror("bind");
+@@ -425,31 +454,16 @@
+ int
+ join_mcast(struct interface *ifs, int sock)
+ {
+-  /* See linux/in6.h */
++  /* See netinet6/in6.h */
+   struct ipv6_mreq mcastreq;
+   COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
+   mcastreq.ipv6mr_interface = ifs->if_index;
+-#if 0
+   OLSR_PRINTF(3, "Interface %s joining multicast %s...",      ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr))
+-  /* Send multicast */
+-  if(setsockopt(sock, 
+-              IPPROTO_IPV6, 
+-              IPV6_ADD_MEMBERSHIP, 
+-              (char *)&mcastreq, 
+-              sizeof(struct ipv6_mreq)) 
+-     < 0)
+-    {
+-      perror("Join multicast");
+-      return -1;
+-    }
+-#else
+-#warning implement IPV6_ADD_MEMBERSHIP
+-#endif
+-  /* Old libc fix */
++  /* rfc 3493 */
+ #ifdef IPV6_JOIN_GROUP
+   /* Join reciever group */
+   if(setsockopt(sock, 
+@@ -458,8 +472,8 @@
+               (char *)&mcastreq, 
+               sizeof(struct ipv6_mreq)) 
+      < 0)
+-#else
+-  /* Join reciever group */
++#else /* rfc 2133, obsoleted */
++  /* Join receiver group */
+   if(setsockopt(sock, 
+               IPPROTO_IPV6, 
+               IPV6_ADD_MEMBERSHIP, 
+@@ -494,6 +508,70 @@
+ int get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
+ {
++  struct ifaddrs *ifap, *ifa;
++  const struct sockaddr_in6 *sin6 = NULL;
++  struct in6_ifreq ifr6;
++  int found = 0;
++  int s6;
++  u_int32_t flags6;
++
++  if (getifaddrs(&ifap) != 0)
++    {
++      OLSR_PRINTF(3, "get_ipv6_address: getifaddrs() failed.\n")
++      return 0;
++    }
++
++  for (ifa = ifap; ifa; ifa = ifa->ifa_next)
++    {
++      if (ifa->ifa_addr->sa_family == AF_INET6 &&
++          strcmp(ifa->ifa_name, ifname) == 0)
++        {
++        sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
++        if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
++          continue;
++        strncpy(ifr6.ifr_name, ifname, sizeof(ifname));
++        if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
++          {
++            OLSR_PRINTF(3, "socket(AF_INET6,SOCK_DGRAM)");
++            break;
++          }
++        ifr6.ifr_addr = *sin6;
++        if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0)
++          {
++            OLSR_PRINTF(3, "ioctl(SIOCGIFAFLAG_IN6)");
++            close(s6);
++            break;
++          }
++        close(s6);
++        flags6 = ifr6.ifr_ifru.ifru_flags6;
++        if ((flags6 & IN6_IFF_ANYCAST) != 0)
++          continue;
++        if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
++          {
++            if (scope_in)
++              {
++                memcpy(&saddr6->sin6_addr, &sin6->sin6_addr,
++                       sizeof(struct in6_addr));
++                found = 1;
++                break;
++              }
++          }
++        else
++          {
++            if (scope_in == 0)
++              {
++                memcpy(&saddr6->sin6_addr, &sin6->sin6_addr,
++                       sizeof(struct in6_addr));
++                found = 1;
++                break;
++              }
++          }
++      }
++    }
++  freeifaddrs(ifap);
++  if (found)
++    return 1;
++
+   return 0;
+ }
+@@ -621,16 +699,19 @@
+             struct sockaddr *from,
+             socklen_t *fromlen)
+ {
+-#if SPOOF
+   struct msghdr mhdr;
+   struct iovec iov;
+   struct cmsghdr *cm;
+   struct sockaddr_dl *sdl;
+   struct sockaddr_in *sin = (struct sockaddr_in *) from; //XXX
++  struct sockaddr_in6 *sin6;
++  struct in6_addr *iaddr6;
++  struct in6_pktinfo *pkti;
++  struct interface *ifc;
++  char addrstr[INET6_ADDRSTRLEN];
++  char iname[IFNAMSIZ];
+   unsigned char chdr[4096];
+   int count;
+-  struct interface *ifc;
+-  char iname[32];
+   bzero(&mhdr, sizeof(mhdr));
+   bzero(&iov, sizeof(iov));
+@@ -653,35 +734,45 @@
+   /* this needs to get communicated back to caller */
+   *fromlen = mhdr.msg_namelen;
+-
+-  cm = (struct cmsghdr *) chdr;
+-  sdl = (struct sockaddr_dl *) CMSG_DATA (cm);
+-  bzero (iname, sizeof (iname));
+-  memcpy (iname, sdl->sdl_data, sdl->sdl_nlen);
++  if (olsr_cnf->ip_version == AF_INET6)
++    {
++      for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&mhdr); cm;
++         cm = (struct cmsghdr *)CMSG_NXTHDR(&mhdr, cm))
++      {
++        if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
++          {
++            pkti = (struct in6_pktinfo *) CMSG_DATA(cm);
++            iaddr6 = &pkti->ipi6_addr;
++            if_indextoname(pkti->ipi6_ifindex, iname);
++          }
++      }
++    }
++  else
++    {
++      cm = (struct cmsghdr *) chdr;
++      sdl = (struct sockaddr_dl *) CMSG_DATA (cm);
++      bzero (iname, sizeof (iname));
++      memcpy (iname, sdl->sdl_data, sdl->sdl_nlen);
++    }
+   ifc = if_ifwithsock (s);
++  sin6 = (struct sockaddr_in6 *)from;
++  OLSR_PRINTF (4, "%d bytes from %s, socket associated %s really received on %s\n",
++             count,
++             (olsr_cnf->ip_version == AF_INET6) ?
++               inet_ntop(AF_INET6, (char *)&sin6->sin6_addr, addrstr,
++                                   INET6_ADDRSTRLEN):
++               inet_ntoa (sin->sin_addr),
++             ifc->int_name,
++             iname);
++
+   if (strcmp (ifc->int_name, iname) != 0)
+     {
+       return (0);
+     }
+-  OLSR_PRINTF (2, "%d bytes from %s, socket associated %s really received on %s\n",
+-             count,
+-             inet_ntoa (sin->sin_addr),
+-             ifc->int_name,
+-             iname);
+-
+   return (count);
+-
+-#else /* SPOOF */
+-  return recvfrom(s, 
+-                buf, 
+-                len, 
+-                0, 
+-                from, 
+-                fromlen);
+-#endif /* SPOOF */
+ }
+ /**
+diff -Nur olsrd-0.4.10.orig/src/net_olsr.c olsrd-0.4.10/src/net_olsr.c
+--- olsrd-0.4.10.orig/src/net_olsr.c   2005-12-29 19:37:16.000000000 +0100
++++ olsrd-0.4.10/src/net_olsr.c        2006-12-12 08:59:35.000000000 +0100
+@@ -526,7 +526,7 @@
+   for(;p > 0; p -= 8)
+     {
+-      adr->v6.s6_addr[i] = (p < 8) ? 0xff ^ (0xff << p) : 0xff;
++      adr->v6.s6_addr[i] = (p < 8) ? 0xff ^ (0xff >> p) : 0xff;
+       i++;
+     }
+@@ -564,7 +564,7 @@
+       {
+         for(tmp = adr->v6.s6_addr[i];
+             tmp > 0;
+-            tmp = tmp >> 1)
++            tmp = (tmp << 1) & 0xff)
+           prefix++;
+       }
+     }
diff --git a/net/olsrd/patches/230-olsrd-fixes-backport.patch b/net/olsrd/patches/230-olsrd-fixes-backport.patch
new file mode 100644 (file)
index 0000000..92616df
--- /dev/null
@@ -0,0 +1,306 @@
+diff -Nur olsrd-0.4.10.orig/lib/dot_draw/src/olsrd_dot_draw.c olsrd-0.4.10/lib/dot_draw/src/olsrd_dot_draw.c
+--- olsrd-0.4.10.orig/lib/dot_draw/src/olsrd_dot_draw.c        2005-12-30 03:23:59.000000000 +0100
++++ olsrd-0.4.10/lib/dot_draw/src/olsrd_dot_draw.c     2006-12-01 20:23:37.000000000 +0100
+@@ -136,6 +136,8 @@
+   /* Register the "ProcessChanges" function */
+   register_pcf(&pcf_event);
++  plugin_ipc_init();
++
+   return 1;
+ }
+@@ -237,6 +239,7 @@
+       /* Register with olsrd */
++      printf("Adding socket with olsrd\n");
+       add_olsr_socket(ipc_socket, &ipc_action);
+       ipc_socket_up = 1;
+     }
+diff -Nur olsrd-0.4.10.orig/lib/httpinfo/src/olsrd_httpinfo.c olsrd-0.4.10/lib/httpinfo/src/olsrd_httpinfo.c
+--- olsrd-0.4.10.orig/lib/httpinfo/src/olsrd_httpinfo.c        2006-12-01 20:20:31.000000000 +0100
++++ olsrd-0.4.10/lib/httpinfo/src/olsrd_httpinfo.c     2006-12-01 20:23:37.000000000 +0100
+@@ -297,6 +297,7 @@
+   if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
+     {
+       olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
++      close(s);
+       return -1;
+     }
+       
+@@ -304,6 +305,7 @@
+   if (listen(s, 1) == -1) 
+     {
+       olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
++      close(s);
+       return -1;
+     }
+diff -Nur olsrd-0.4.10.orig/lib/secure/src/olsrd_secure.c olsrd-0.4.10/lib/secure/src/olsrd_secure.c
+--- olsrd-0.4.10.orig/lib/secure/src/olsrd_secure.c    2005-11-19 09:37:23.000000000 +0100
++++ olsrd-0.4.10/lib/secure/src/olsrd_secure.c 2006-12-01 20:23:37.000000000 +0100
+@@ -952,7 +952,7 @@
+   else
+     {
+       /* Check configuration timeout */
+-      if(!TIMED_OUT(&entry->conftime))
++      if(!TIMED_OUT(entry->conftime))
+       {
+         /* If registered - do not accept! */
+         olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
+@@ -1205,7 +1205,7 @@
+       while(tmp_list != &timestamps[index])
+       {
+         /*Check if the entry is timed out*/
+-        if((TIMED_OUT(&tmp_list->valtime)) && (TIMED_OUT(&tmp_list->conftime)))
++        if((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime)))
+           {
+             entry_to_delete = tmp_list;
+             tmp_list = tmp_list->next;
+diff -Nur olsrd-0.4.10.orig/make/Makefile.linux olsrd-0.4.10/make/Makefile.linux
+--- olsrd-0.4.10.orig/make/Makefile.linux      2005-11-19 09:43:51.000000000 +0100
++++ olsrd-0.4.10/make/Makefile.linux   2006-12-01 20:23:37.000000000 +0100
+@@ -3,7 +3,11 @@
+ #
+ INSTALL_PREFIX ?=
++ifeq ($(shell arch),x86_64)
++LIBDIR =      $(INSTALL_PREFIX)/usr/lib64
++else
+ LIBDIR =      $(INSTALL_PREFIX)/usr/lib
++endif
+ SRCS +=       $(wildcard src/linux/*.c) $(wildcard src/unix/*.c)
+ HDRS +=               $(wildcard src/linux/*.h) $(wildcard src/unix/*.h)
+diff -Nur olsrd-0.4.10.orig/make/Makefile.osx olsrd-0.4.10/make/Makefile.osx
+--- olsrd-0.4.10.orig/make/Makefile.osx        2005-12-29 20:48:43.000000000 +0100
++++ olsrd-0.4.10/make/Makefile.osx     2006-12-01 20:23:37.000000000 +0100
+@@ -2,6 +2,10 @@
+ # MAC OSX SPECIFIC CONFIGURATION
+ #
++# don't strip executables and bundles for now until we figure out the proper way
++# to do it (flags).
++STRIP = \#
++
+ INSTALL_PREFIX ?=
+ LIBDIR =      $(INSTALL_PREFIX)/usr/lib
+@@ -12,12 +16,10 @@
+ LIBS =                
+ PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
+-INSTALL_LIB = install -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME); \
+-              /sbin/ldconfig
++INSTALL_LIB = install -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME)
+ ifdef OLSRD_PLUGIN
+-CFLAGS +=     -fPIC
+-LDFLAGS =     -fPIC -dynamiclib -single_module -flat_namespace -undefined suppress
++LDFLAGS = -bundle -flat_namespace -undefined suppress
+ else
+ LDFLAGS = -dynamic
+ endif
+diff -Nur olsrd-0.4.10.orig/Makefile olsrd-0.4.10/Makefile
+--- olsrd-0.4.10.orig/Makefile 2006-12-01 20:20:31.000000000 +0100
++++ olsrd-0.4.10/Makefile      2006-12-01 20:23:37.000000000 +0100
+@@ -171,3 +171,4 @@
+ build_all:    cfgparser olsrd libs
+ install_all:  install install_libs
++clean_all:      uberclean clean_libs
+diff -Nur olsrd-0.4.10.orig/src/bsd/net.c olsrd-0.4.10/src/bsd/net.c
+--- olsrd-0.4.10.orig/src/bsd/net.c    2005-08-28 21:30:29.000000000 +0200
++++ olsrd-0.4.10/src/bsd/net.c 2006-12-01 20:23:37.000000000 +0100
+@@ -290,6 +290,7 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEADDR failed");
++      close(sock);
+       return (-1);
+     }
+   /* connect to PORT on HOST */
+@@ -298,6 +299,7 @@
+       printf("FAILED\n");
+       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+       printf("connection refused\n");
++      close(sock);
+       return (-1);
+     }
+@@ -332,6 +334,7 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEADDR failed");
++      close(sock);
+       return (-1);
+     }
+@@ -339,12 +342,14 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEPORT failed");
++      close(sock);
+       return (-1);
+     }
+   if (setsockopt(sock, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0) 
+     {
+       perror("IP_RECVIF failed");
++      close(sock);
+       return (-1);
+     }
+ #endif /* SPOOF */
+@@ -403,6 +408,7 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEADDR failed");
++      close(sock);
+       return (-1);
+     }
+diff -Nur olsrd-0.4.10.orig/src/linux/net.c olsrd-0.4.10/src/linux/net.c
+--- olsrd-0.4.10.orig/src/linux/net.c  2005-09-17 22:48:50.000000000 +0200
++++ olsrd-0.4.10/src/linux/net.c       2006-12-01 20:23:37.000000000 +0100
+@@ -434,6 +434,7 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEADDR failed");
++      close(sock);
+       return (-1);
+     }
+   /* connect to PORT on HOST */
+@@ -442,6 +443,7 @@
+       printf("FAILED\n");
+       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+       printf("connection refused\n");
++      close(sock);
+       return (-1);
+     }
+@@ -487,6 +489,7 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEADDR failed");
++      close(sock);
+       return (-1);
+     }
+@@ -520,6 +523,7 @@
+     {
+       fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
+       syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
++      close(sock);
+       return -1;
+     }
+@@ -606,6 +610,7 @@
+   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+     {
+       perror("SO_REUSEADDR failed");
++      close(sock);
+       return (-1);
+     }
+@@ -619,6 +624,7 @@
+     {
+       fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
+       syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
++      close(sock);
+       return -1;
+     }
+diff -Nur olsrd-0.4.10.orig/src/main.c olsrd-0.4.10/src/main.c
+--- olsrd-0.4.10.orig/src/main.c       2006-12-01 20:20:31.000000000 +0100
++++ olsrd-0.4.10/src/main.c    2006-12-01 20:23:54.000000000 +0100
+@@ -118,7 +118,7 @@
+   system_tick_divider = 1000/sysconf(_SC_CLK_TCK);
+   /* Check if user is root */
+-  if(getuid() || getgid())
++  if(geteuid())
+     {
+       fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
+       exit(EXIT_FAILURE);
+@@ -395,6 +395,7 @@
+   signal(SIGHUP, olsr_reconfigure);  
+   signal(SIGINT, olsr_shutdown);  
+   signal(SIGTERM, olsr_shutdown);  
++  signal(SIGPIPE, SIG_IGN);
+ #endif
+   /* Register socket poll event */
+@@ -535,6 +536,7 @@
+   fprintf(stderr, "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n");
+   fprintf(stderr, "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n");
+   fprintf(stderr, "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>] \n"); 
++  fprintf(stderr, "  [-lql <LQ level>] [-lqw <LQ winsize>]\n"); 
+ }
+@@ -635,6 +637,42 @@
+         memcpy(&ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(olsr_u32_t));  
+         continue;
+       }
++
++      /*
++       * Set LQ level
++       */
++      if (strcmp(*argv, "-lql") == 0) 
++      {
++        int tmp_lq_level;
++        NEXT_ARG;
++          CHECK_ARGC;
++        
++        /* Sanity checking is done later */
++        sscanf(*argv, "%d", &tmp_lq_level);
++        olsr_cnf->lq_level = tmp_lq_level;
++        continue;
++      }
++
++      /*
++       * Set LQ winsize
++       */
++      if (strcmp(*argv, "-lqw") == 0) 
++      {
++        int tmp_lq_wsize;
++        NEXT_ARG;
++          CHECK_ARGC;
++        
++        sscanf(*argv, "%d", &tmp_lq_wsize);
++
++        if(tmp_lq_wsize < MIN_LQ_WSIZE || tmp_lq_wsize > MAX_LQ_WSIZE)
++          {
++            printf("LQ winsize %d not allowed. Range [%d-%d]\n", 
++                   tmp_lq_wsize, MIN_LQ_WSIZE, MAX_LQ_WSIZE);
++            olsr_exit(__func__, EXIT_FAILURE);
++          }
++        olsr_cnf->lq_wsize = tmp_lq_wsize;
++        continue;
++      }
+       
+       /*
+        * Enable additional debugging information to be logged.
+diff -Nur olsrd-0.4.10.orig/src/scheduler.c olsrd-0.4.10/src/scheduler.c
+--- olsrd-0.4.10.orig/src/scheduler.c  2006-12-01 20:20:31.000000000 +0100
++++ olsrd-0.4.10/src/scheduler.c       2006-12-01 20:23:37.000000000 +0100
+@@ -330,6 +330,7 @@
+           {
+             prev->next = entry->next;
+           }
++          free(entry);
+         return 1;
+       }
+diff -Nur olsrd-0.4.10.orig/src/win32/net.c olsrd-0.4.10/src/win32/net.c
+--- olsrd-0.4.10.orig/src/win32/net.c  2005-05-30 15:50:27.000000000 +0200
++++ olsrd-0.4.10/src/win32/net.c       2006-12-01 20:23:37.000000000 +0100
+@@ -87,6 +87,7 @@
+       printf("FAILED\n");
+       fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+       printf("connection refused\n");
++      closesocket(sock);
+       return (-1);
+     }
diff --git a/net/olsrd/patches/240-olsrd-fixes-routedel.patch b/net/olsrd/patches/240-olsrd-fixes-routedel.patch
new file mode 100644 (file)
index 0000000..ae61bab
--- /dev/null
@@ -0,0 +1,137 @@
+diff -Nur olsrd-0.4.10.orig/src/link_set.c olsrd-0.4.10/src/link_set.c
+--- olsrd-0.4.10.orig/src/link_set.c   2006-12-01 09:04:56.000000000 +0100
++++ olsrd-0.4.10/src/link_set.c        2006-12-01 09:06:22.000000000 +0100
+@@ -381,6 +381,69 @@
+ }
+ /**
++ *Delete all interface link entries
++ *
++ *@param interface ip address
++ */
++
++void
++del_if_link_entries(union olsr_ip_addr *int_addr)
++{
++  struct link_entry *tmp_link_set, *last_link_entry;
++
++  if(link_set == NULL)
++    return;
++
++  tmp_link_set = link_set;
++  last_link_entry = NULL;
++
++  while(tmp_link_set)
++    {
++
++      if(COMP_IP(int_addr, &tmp_link_set->local_iface_addr))
++        {
++          if(last_link_entry != NULL)
++            {
++              last_link_entry->next = tmp_link_set->next;
++
++              /* Delete neighbor entry */
++              if(tmp_link_set->neighbor->linkcount == 1)
++                olsr_delete_neighbor_table(&tmp_link_set->neighbor->neighbor_main_addr);
++              else
++                tmp_link_set->neighbor->linkcount--;
++
++              //olsr_delete_neighbor_if_no_link(&tmp_link_set->neighbor->neighbor_main_addr);
++              changes_neighborhood = OLSR_TRUE;
++
++              free(tmp_link_set);
++              tmp_link_set = last_link_entry;
++            }
++          else
++            {
++              link_set = tmp_link_set->next; /* CHANGED */
++
++              /* Delete neighbor entry */
++              if(tmp_link_set->neighbor->linkcount == 1)
++                olsr_delete_neighbor_table(&tmp_link_set->neighbor->neighbor_main_addr);
++              else
++                tmp_link_set->neighbor->linkcount--;
++
++              changes_neighborhood = OLSR_TRUE;
++
++              free(tmp_link_set);
++              tmp_link_set = link_set;
++              continue;
++            }
++        }
++
++      last_link_entry = tmp_link_set;
++      tmp_link_set = tmp_link_set->next;
++    }
++
++  return;
++}
++
++/**
+  *Nothing mysterious here.
+  *Adding a new link entry to the link set.
+  *
+diff -Nur olsrd-0.4.10.orig/src/link_set.h olsrd-0.4.10/src/link_set.h
+--- olsrd-0.4.10.orig/src/link_set.h   2005-10-23 22:58:14.000000000 +0200
++++ olsrd-0.4.10/src/link_set.h        2006-12-01 09:06:22.000000000 +0100
+@@ -116,6 +116,9 @@
+ void
+ olsr_init_link_set(void);
++void
++del_if_link_entries(union olsr_ip_addr *);
++
+ struct link_entry *
+ get_best_link_to_neighbor(union olsr_ip_addr *);
+diff -Nur olsrd-0.4.10.orig/src/linux/kernel_routes.c olsrd-0.4.10/src/linux/kernel_routes.c
+--- olsrd-0.4.10.orig/src/linux/kernel_routes.c        2005-02-27 19:39:43.000000000 +0100
++++ olsrd-0.4.10/src/linux/kernel_routes.c     2006-12-01 09:06:22.000000000 +0100
+@@ -244,9 +244,8 @@
+   inet_ntop(AF_INET, &destination->rt_mask.v4, mask_str, 16);
+   inet_ntop(AF_INET, &destination->rt_router.v4, router_str, 16);
+-  OLSR_PRINTF(1, "(ioctl)Deleting route with metric %d to %s/%s via %s/%s.\n",
+-              destination->rt_metric, dst_str, mask_str, router_str,
+-              destination->rt_if->int_name)
++  OLSR_PRINTF(1, "(ioctl)Deleting route with metric %d to %s/%s via %s.\n",
++              destination->rt_metric, dst_str, mask_str, router_str)
+   
+   memset(&kernel_route,0,sizeof(struct rtentry));
+diff -Nur olsrd-0.4.10.orig/src/lq_packet.c olsrd-0.4.10/src/lq_packet.c
+--- olsrd-0.4.10.orig/src/lq_packet.c  2006-12-01 09:04:56.000000000 +0100
++++ olsrd-0.4.10/src/lq_packet.c       2006-12-01 09:06:22.000000000 +0100
+@@ -225,8 +225,10 @@
+           link = get_best_link_to_neighbor(&neigh->main);
+-          neigh->link_quality = link->loss_link_quality;
+-          neigh->neigh_link_quality = link->neigh_link_quality;
++          if (link) {
++            neigh->link_quality = link->loss_link_quality;
++            neigh->neigh_link_quality = link->neigh_link_quality;
++          }
+           // queue the neighbour entry
+diff -Nur olsrd-0.4.10.orig/src/unix/ifnet.c olsrd-0.4.10/src/unix/ifnet.c
+--- olsrd-0.4.10.orig/src/unix/ifnet.c 2006-12-01 09:04:56.000000000 +0100
++++ olsrd-0.4.10/src/unix/ifnet.c      2006-12-01 09:06:22.000000000 +0100
+@@ -56,6 +56,7 @@
+ #include "mantissa.h"
+ #include "lq_packet.h"
+ #include "log.h"
++#include "link_set.h"
+ #include <signal.h>
+ #include <sys/types.h>
+ #include <net/if.h>
+@@ -393,6 +394,8 @@
+   OLSR_PRINTF(1, "Removing interface %s\n", iface->name)
+   olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name);
++  del_if_link_entries(&ifp->ip_addr);
++
+   /*
+    *Call possible ifchange functions registered by plugins  
+    */
diff --git a/net/olsrd/patches/250-olsrd-cpu-overload.patch b/net/olsrd/patches/250-olsrd-cpu-overload.patch
new file mode 100644 (file)
index 0000000..b76ef91
--- /dev/null
@@ -0,0 +1,36 @@
+diff -Nur olsrd-0.4.10.orig/src/parser.c olsrd-0.4.10/src/parser.c
+--- olsrd-0.4.10.orig/src/parser.c     2005-11-19 09:49:44.000000000 +0100
++++ olsrd-0.4.10/src/parser.c  2006-12-04 09:12:40.000000000 +0100
+@@ -61,6 +61,14 @@
+ #define strerror(x) StrError(x)
+ #endif
++/* Sven-Ola: On very slow devices used in huge networks
++ * the amount of lq_tc messages is so high, that the 
++ * recv() loop never ends. This is a small hack to end
++ * the loop in this cases
++ */
++ 
++unsigned int cpu_overload_exit = 0;
++
+ struct parse_function_entry *parse_functions;
+ static char inbuf[MAXMESSAGESIZE+1];
+@@ -347,9 +355,16 @@
+   int cc;
+   struct interface *olsr_in_if;
+   union olsr_ip_addr from_addr;
+-
++  cpu_overload_exit = 0;
++  
+   for (;;) 
+     {
++      if (32 < ++cpu_overload_exit)
++      {
++        OLSR_PRINTF(1, "CPU overload detected, ending olsr_input() loop\n")
++              break;
++      }
++      
+       fromlen = sizeof(struct sockaddr_storage);
+       cc = olsr_recvfrom(fd, 
diff --git a/net/olsrd/patches/260-olsrd-secure_key_path.patch b/net/olsrd/patches/260-olsrd-secure_key_path.patch
new file mode 100644 (file)
index 0000000..7be25c0
--- /dev/null
@@ -0,0 +1,12 @@
+diff -Nur olsrd-0.4.10.orig/lib/secure/src/olsrd_secure.h olsrd-0.4.10/lib/secure/src/olsrd_secure.h
+--- olsrd-0.4.10.orig/lib/secure/src/olsrd_secure.h    2005-11-19 09:30:45.000000000 +0100
++++ olsrd-0.4.10/lib/secure/src/olsrd_secure.h 2006-12-01 08:50:41.000000000 +0100
+@@ -46,7 +46,7 @@
+ #include "hashing.h"
+-#define KEYFILE "/root/.olsr/olsrd_secure_key"
++#define KEYFILE "/etc/olsrd.d/olsrd_secure_key"
+ /* Schemes */
+ #define ONE_CHECKSUM          1
diff --git a/net/olsrd/patches/270-olsrd-hna_ip_fix.patch b/net/olsrd/patches/270-olsrd-hna_ip_fix.patch
new file mode 100644 (file)
index 0000000..f7f1140
--- /dev/null
@@ -0,0 +1,22 @@
+diff -Nur olsrd-0.4.10.orig/src/cfgparser/oparse.c olsrd-0.4.10/src/cfgparser/oparse.c
+--- olsrd-0.4.10.orig/src/cfgparser/oparse.c   2006-01-01 17:15:57.000000000 +0100
++++ olsrd-0.4.10/src/cfgparser/oparse.c        2006-12-01 08:21:39.000000000 +0100
+@@ -1921,6 +1921,7 @@
+       return -1;
+     }
+   h->netmask.v4 = in.s_addr;
++  h->net.v4 &= h->netmask.v4;
+   /* Queue */
+   h->next = cnf->hna4_entries;
+   cnf->hna4_entries = h;
+diff -Nur olsrd-0.4.10.orig/src/cfgparser/oparse.y olsrd-0.4.10/src/cfgparser/oparse.y
+--- olsrd-0.4.10.orig/src/cfgparser/oparse.y   2005-11-17 05:25:44.000000000 +0100
++++ olsrd-0.4.10/src/cfgparser/oparse.y        2006-12-01 08:23:05.000000000 +0100
+@@ -701,6 +701,7 @@
+       return -1;
+     }
+   h->netmask.v4 = in.s_addr;
++  h->net.v4 &= h->netmask.v4;
+   /* Queue */
+   h->next = cnf->hna4_entries;
+   cnf->hna4_entries = h;