--- /dev/null
+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)
+
--- /dev/null
+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
+++ /dev/null
-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
--- /dev/null
+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(®ex_t_name, regex_name , REG_EXTENDED)) != 0)
++ {
++ /* #2: call regerror() if regcomp failed
++ * commented out, because only for debuggin needed
++ *
++ int errmsgsz = regerror(ret, ®ex_t_name, NULL, 0);
++ char *errmsg = malloc(errmsgsz);
++ regerror(ret, ®ex_t_name, errmsg, errmsgsz);
++ fprintf(stderr, "regcomp: %s", errmsg);
++ free(errmsg);
++ regfree(®ex_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(®ex_t_service, regex_service , REG_EXTENDED )) != 0)
++ {
++ /* #2: call regerror() if regcomp failed
++ * commented out, because only for debuggin needed
++ *
++ int errmsgsz = regerror(ret, ®ex_t_service, NULL, 0);
++ char *errmsg = malloc(errmsgsz);
++ regerror(ret, ®ex_t_service, errmsg, errmsgsz);
++ fprintf(stderr, "regcomp: %s", errmsg);
++ free(errmsg);
++ regfree(®ex_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(®ex_t_name);
++ regfree(®ex_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(®ex_t_name, name, 1, ®match_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(®ex_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
+ */
+++ /dev/null
-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;
--- /dev/null
+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:
++ *;
++};
+++ /dev/null
-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;
- };
-
+++ /dev/null
-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;
--- /dev/null
+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:
++ *;
++};
--- /dev/null
+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);
+
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+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;
+ };
+
--- /dev/null
+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(¤t_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(¤t_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
--- /dev/null
+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;
--- /dev/null
+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++;
+ }
+ }
--- /dev/null
+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 != ×tamps[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);
+ }
+
--- /dev/null
+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
+ */
--- /dev/null
+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,
--- /dev/null
+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
--- /dev/null
+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;