diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/CHANGELOG ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/CHANGELOG
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/CHANGELOG	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/CHANGELOG	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,1626 @@
+This file states changes as of version 0.2.4:
+
+0.5.6 ---------------------------------------------------------------------
+
+PATCHES from Hannes Gredler <hannes@gredler.at>:
+- add small valgrind howto
+- remove the per tc_edge timer
+- add some basic infrastructure for cookies
+  cookies are used to track usage of timer and memory resources
+- add a lightweight memory manager to reduce malloc() churn.
+- eliminate data field from avl_node and list_node and
+  replace this via inline recasts
+- add indentation dotfile for future code cleanup
+- refactor the timer implementation, get rid of timeout functions
+  all manipulations done in constant time.
+- use calloc rather than malloc for lazy callers
+- log RIB add/del transactions only if there is an actual route change
+- fix to to always insert a HNA Net when receiving a HNA refresh
+- fix delete all routes if the last IP address is gone
+
+PATCHES and BUGFIXES from Henning Rogge <rogge@fgan.de>
+- Bugfix for fragmented TC sequence numbers
+- eliminate second timer for edge garbage collection (aka border code).
+- fix SPF bug
+- fix for jitter calculation
+- refactor linkset code
+- add netsimpcap, a network simulation device
+- parser refactoring
+- fix for possible overflow in fpm plugin
+
+PATCHES and BUGFIXES from Sven-Ola Tuecke <sven-ola@gmx.de>:
+- add a fixed-point math implementation, which saves
+  a great deal of CPU on embedded devices
+- fix for Link quality dijkstra limit
+
+PATCHES and BUGFIXES from Aaron Kaplan <aaron@lo-res.org>:
+- fix openbsd warnings / compile errors about sprintf strcpy
+
+BUGFIX from Erik Tromp <erik_tromp@hotmail.com>:
+- update in bmf due to new flags field in tc_edge_entry
+
+PATCH from Clemens Hopfer <datacop@inode.at>:
+- dot_draw plugin: close the connection after graph output.
+
+PATCH from Joe Gio <joezgio@gmail.com>:
+- track if AC power is connected/disconnected
+
+PATCH from Hagen Paul Pfeifer <hagen@jauu.net>:
+- import jenkins hash for good hash calculations
+
+PATCH from Andres Ambrois <andresambrois@gmail.com>:
+- nameservice plugin: add parameters for SIGHUPing other daemons, or calling scripts
+
+PATCH from Markus Kittenberger <Markus.Kittenberger@gmx.at>:
+- txtinfo plugin: add more http options
+
+0.5.5 ---------------------------------------------------------------------
+
+BUGFIX from Andreas Jacobs <andjac@kawo1.rwth-aachen.de>:
+- calculate correct sleeptime
+
+BUGFIX from Dario Borriello <dario_bodj@hotmail.com>:
+- do not update LQ if not configured
+
+BUGFIX from Jo-Philipp Wich <freifunk@wwsnet.net:
+- fix olsr_ip_to_string() buffer quirk
+- fix txtinfo format quirks in HNA table
+- name-service plugin - write MID entries to hosts file
+- avoid infinite loop in the message parser
+
+PATCH by John Hay <jhay@meraka.org.za>:
+- compile clean on FreeBSD
+- bugfix: do not account for IP headers when building MID6 messages
+
+PATCHES from Henning Rogge <rogge@fgan.de>:
+- join LQ and non-LQ Hello execution paths
+
+PATCHES from otti <otti@wirdorange.org>:
+- rttable-default: configures a new policy routing table for the default route
+
+BUGFIXES and PATCHES by Sven-Ola Tuecke <mail2news@commando.de>:
+- Windows Vista: add interface metric to SPF computed metric
+- lqtc-seqno: Optimize check for old seqno numbers in LQTC messages
+- lqnatthresh: maintain an advantage for the current (NAT) inet gw
+- fisheye-startup: Changed to MAX_TTL for the first 32 LQTCs
+- Added and removed files necessary for win32 compile
+- Fix for hg: do not remove anything in .hg with 'make uberclean'
+- 104-olsrd-verysmallfix
+- 105-fix-lq-buffer-quirks
+- 106-fix-seqnocheck
+- 110-bmf-v152
+- 121-olsrd-fib-metric-approx
+- 133-fix-lqneigh
+- 136-optimize-invalidip-check
+- 138-optimize-message-generation
+
+BUGFIX from Lorenz Shori <lorenz.schori@gmx.ch>:
+- Mac OSX compile fixes
+
+BUGFIXES and PATCHES by Hannes Gredler <hannes@gredler.at>
+- fix not deleted tc entry.
+- avoid setting routes with an invalid/impossible netmask.
+- refactoring of TC parsing to kill another pile of malloc()/free()s
+  saving (again) code and especially run.time performance.
+- RIB Refactoring, Part 2:
+  - avoid the periodical rib-tree insertion
+  - add a FOR_ALL_HNA_RT_ENTRIES() macro for the snmp folks
+    (or any parties who want to walk HNA entries).
+  - add an olsr_cnf option 'flat_fib_metrics' which defaults to TRUE.
+- fix broken prefix insertion (regression of the RIB refactoring)
+- squelsh compiler warnings on Mac OSX
+
+PATCH by John Hay <jhay@meraka.org.za>:
+- also printout our own HNAs in the dotdraw plugin.
+
+PATCH by Patrick McCarty <mccartyp@gmail.com>:
+- fixed compile errors in the BSD port
+
+PATCHES by Sven-Ola Tuecke <mail2news@commando.de>:
+- 102-olsrd-cvs-fixes.patch: use different buffers in the same printf()
+- 103-olsrd-rt-exportroute-cleanup.patch: avoid a malloc()ed list of functions
+- 132-save-the-fish.patch: really save the fish and avoid to forward invalid
+  messages from older olsrd versions
+- 135-georss-map-for-nameservice.patch: fixes and extensions for the namesaervice plugin
+- 138-olsrd-fixdotdraw.patch: fix the dot_draw plugin
+(all to be found on http://download-master.berlin.freifunk.net/sven-ola/nylon/packages/olsrd/files/)
+- Replaced "which" with a /bin/sh script snippet
+
+PATCHES and CLEANUPS by Bernd Petrovitsch <bernd@firmix.at>
+- Jens Nachtigall <nachtigall@web.de> suggested (and reminded) to use
+  olsrd.conf.default.lq as the default installed one.
+  It makes much more sense as - to the best of my(bernd's) knowledge - all
+  larger networks uses the LQ extensions. And new customers should better
+  be pushed in that direction.
+- with the help of Patrick McCarty <mccartyp@gmail.com>, we got olsr to build
+  on OpenBSD again:
+  * OpenBSD'd `sed` is pretty conservative and doesn't understand 's|re|sub|'.
+    So we fall back to the old 's/re/sub/' and quote all '/' and '.' correctly
+    (which was the main reason to use '|').
+    And while I'm at it: Remove the useless $(CCACHE) from the $(CC) for
+    dependency generation and beautify (read: "$(strip)") $(CPPFLAGS).
+  * OpenBSD needs an explicit "#include <sys/types.h>" before
+    "#include <netinet/in.h>".
+- fixed lib/secure/src/md5.h: This was broken as it had
+  "typedef unsigned long int UINT4;". "unsigned long int" is 8 bytes on x86_64.
+  We are using now the standardized types from <inttypes.h>.
+- fixed warnings and improved lib/secure/src/md5.c:
+  * we are using memcpy() and memset() instead of the open-coded loops as
+    suggested 
+  * const'ified
+  * added function prototypes for static functions
+  * moved static functions to the top so that their declaration is before
+    their use to allow gcc to inline if only used once.
+  It remains ugly - God knows why there are that so many useless
+  type-casts.
+- Some minor and trivial cleanup: Added two functions to calculate the ETX
+  value from a struct tc_edge_entry and a struct link_entry, respectively.
+  And use them everywhere.
+- added http://meshcube.org/nylon/utils/olsr-topology-view.pl into
+  lib/httpinfo/misc as suggested by Jens Nachtigall <nachtigall@web.de>
+- Killed "struct olsrd_config *cnf" in src/cfgparser/olsrd_conf.h and replaced
+  it's usage with "olsr_cnf" from src/defs.h.
+  Serious cleanup: olsrd_get_default_cnf() does no longer initialize the global
+  "cnf" variable" but uses a local one which is returned as before. And
+  olsrd_parse_cnf() does no longer return the global variable it is working on.
+- Merged "struct hna4_entry" and "struct hna6_entry" into
+  "struct local_hna_entry" (as "struct hna_entry" is a different thing)
+  Both have almost the same data (IP address + netmask/prefix) so we use
+  the quite new "struct olsr_ip_prefix" to store it.
+  Also merged the "hna4" and "hna6" pointer in "struct olsr_config" -
+  look at the global "olsr_cnf->ip_version".
+- added a olsr_ip_prefix_to_string() function
+- .h file cleanup: def.h does not longer include net_olsr.h because it 
+  doesn't needs it.
+- more type safety: the macros COPY_IP() and COMP_IP are gone and replaced
+  with "=" or similar "normal" C operations. There are also now the inline
+  functions ip4cmp() and ip4equal() to work on "struct in_addr", ip6cmp()
+  and ip6equal() to work on "struct in6_addr" and ipcmp() and ip6equal()
+  to work on "union olsr_ip_addr".
+  Most (or even more precise: almost all) uses of COPY_IP() and COMP_IP()
+  are in "if (olsr_cnf->ip_version) { ... } else { ... }" anyway to
+  there is no reson to copy an IPv4 address effectively with
+  "memcpy(&dst, &src, 4)" or compare with memcmp(&a, &b, 4)" wher the
+  always "4" is stored in a variable inhibiting compiler optimization.
+  There is also the deprecated function genipcopy() mimicking the old
+  typeless COPY_IP() macro for the last few places where a cleanup is
+  needed anyways.
+  There also lots of old macros left over (commented out of course) until
+  we are confident that everything works. And then I will kill them too.
+- Fixed the misleading definition of "v4" in "struct olsr_ip_addr" fom
+  "olsr_u32_t" (in network-byteorder!) to "struct in_addr". Lots of
+  temporary variables to call inet_ntoa()/inet_ptoa() vanished .....
+- We have now ip4_to_string(), ip6_to_string() and olsr_ip_to_string()
+  to print a "struct in_addr", "struct in6_addr" and "union olsr_ip_addr"
+  into a string buffer.
+- cleanup: olsr_ip_to_string() and similar non-reentrant functions now must
+  get a target buffer. To ease that, there is the "struct ipaddr_str"
+  which is large enough for all of them (read: for an IPv6 address). This
+  also removes the cyclic buffer there.
+  All of these function return a "const char *" which can be directly used
+  for printf(3) and friends.
+- const'ified more functions
+- converted the source to UTF-8.
+- "struct sig_msg" uses an olsr_u8_t for a byte array (and not "char")
+- force the few inline function to always be inlined.
+- #ifdef the body of the olsr_print_hna_set() and olsr_print_neighbor_table()
+  if nothing is done
+- declare "int_addr", "int_netmask" and "int_broadaddr" in "struct interface"
+  as "struct sockaddr_in" since it is that what we actually want there (and
+  it is similar to the IPv6 code).
+- updated the olsrd.conf.default.lq-fisheye to the Debian-deliverd version
+  after recent discussions olsr-dev@olsr.org
+- use "inline_avl_comp_ipv4()" in "avl_comp_ipv4()"
+- clean up the routes on more signals. Basically we want to do this on all
+  signals which terminate the program.
+- killed a superflous global buffer in src/main.c
+- made inline functions from avl_walk_{first,last,next,prev} and created
+  "const" versions of it. inline_avl_comp_ipv4() is now also an inline function
+  (and not a macro)
+- created a typedef's for various function pointers - much easier to read.
+- cleanup: compare tree->comp (adn other pointers)) to NULL (and not 0)
+- killed superflous "return"s at the end of void functions
+- const'ified more parameters in many more functions in the .h and
+  .c files
+- init-functions with constant or ignored return values are "void"
+- created a typedef fro the callback in "struct export_route_entry"
+  and using it!
+- moved the initialization of the {add,chg,del}_kernel_list variables
+  into process_routes.c. So they are now "static" there.
+- olsr_export_{add,del}_route{,6} are now static in process_routes.c
+  since they are not used elsewhere.
+- olsr_addroute_add_function() and olsr_deldroute_add_function() were
+  almost identical - made one function out of it.
+  Same for olsr_addroute_del_function() and olsr_deldroute_del_function().
+- fixed the sort order in avl_comp_ipv4_prefix(): We compare now the IPv4
+  values in host byte order (and not network byte order). So the route
+  list in the e.g. httpinfo plugin is now nicely sorted.
+- fixed and improved the `gcc-warnings` script:
+  * support older gcc's (as on Debian/Sarge) as they have slightly different
+    error messages
+  * removed superflous lines
+  * replaced the call of `sed` with shell built-in features fixing syntax
+    errors on Debian/Sarge
+  * set all locale-relevant variables to "C" (just to be sure)
+- consolidated ip{4,6,}{cmp,equal}: all are nwo inline functions using only
+  the minimal necessary operations. Thanks to Hannes Gredler
+  <hannes@gedler.at> and Sven-Ola Tuecke <mail2news@commando.de> for pointing
+  that out and suggesting the `inline`, respectively.
+  use ip{4,}cmp in lq_avl.[ch] to resue the code. inline_avl_comp_ipv4
+  is superflous now (and replaced by ip4cmp) and use the global MIN and MAX
+  macro instead of AVLMIN and AVLMAX
+- killed netmasks from the IPv4 part of the code and use the prefixlen there
+  (similar to thte IPv6 part). Manymore details on
+  http://lists.olsr.org/pipermail/olsr-dev/2007-November/001464.html
+- removed the superflous "open_ipc" field from the "struct olsrd_config" as
+  it contains only the equivalent of "olsr_cnf->debug_level > 1".
+- inspired by Sven-Ola Tuecke: avoid a bash'ism (i.e. "OPTS="${OPTS//$opt}") in
+  gcc-warnings and ld-warnings. But we do not replace it with `sed` (since it
+  costs a fork(2) and an exec(3)) but also with shell code which doesn't use
+  any external program.
+- added configuration file support for "flat fib metrics".
+
+0.5.4 ---------------------------------------------------------------------
+
+QUAGGA by Immo 'FaUl' Wehrenberg <immo.olsr@do.bundessicherheitsministerium.de>
+- updated to svn version 33
+
+BMF PLUGIN  by Erik Tromp <erik_tromp@hotmail.com>
+- updated to 1.5.1
+- updated to latest plugin interfaces changes and killed warnings (by Bernd
+  Petrovitsch <bernd@firmix.at>)
+
+PATCH by Hannes Gredler <hannes@gredler.at> which rewrites the route handling.
+To quote him:
+----  snip  ----
+change list:
+- get rid of separate routing tables for HNA and per-node routes, everything is
+  now unified in an AVL routing tree (&routingtree)
+
+- introduce walking macros (OLSR_FOR_ALL_RT_ENTRIES()) that hide the internal
+  structure of the RIB for making life of the plugin authors easier.
+
+- get rid of different SPF implementations for LQ and non-LQ code paths. a
+  non-LQ edge is simply substituted with a cost of 1.0
+
+- get rid of host masks - a new data type olsr_prefix is introduced which is
+  basically an ip address plus a prefix length.
+
+  do not install the metric in the kernel FIB - for the kernel its pointless
+  if the route gets installed with a metric of N or M.
+
+  we do not need to update the kernel FIB if we have hop count only changes
+  (for example if there is a reroute action further downstream)
+
+  the only things which triggers a kernel FIB route update is a next hop
+  change (a next hop is neighboring gateway router plus an interface).
+
+  all OLSR routes are installed with a metric of 2
+
+- separate between rt_entry and rt_path - the former is a route installed in the
+  kernel with an next hop. the latter is a candidate for best path selection
+  after SPF calculation has been done. in the rt_entry we keep a pointer to the
+  best_path and also to the next hop that was installed in the kernel FIB.
+
+  we always keep all originator of a route, if a route originator goes away we
+  can easy recompute the best path for the route.
+
+  the next hop in the rt_entry gets only updated upon a successful route_add
+  call - that way we always remember what next hop to delete.
+
+  stray routes should be history now.
+
+- tweak the linked list toolkit to operate on circular lists.
+
+- get rid of malloc calls for building the kernel update list. the list node is
+  now embedded in the rt_entry.
+
+- introduce three queues (add/chg/del) for kernel updates.
+
+- for neighbor route dependency tracking the neighbor routes are queued first or
+  last (depending on which queue you work on)
+
+- rework all the plugins which directly manipulate rt entries.
+
+- rework the plugins that read from the routing table (most notably nameserver,
+  httpinfo and quagga plugin)
+
+- lots of comments that explains the intentions and purpose of this code-piece.
+
+non RT related stuff:
+- use a list rather than a tree for storing the post-SPF results, which further
+  improves the raw-SPF runtime.
+
+- add display of SPF runtime (masked behind #ifdef SPF_PROFILING)
+
+- http://gredler.at/download/olsrd/neighbor_routes3.diff: This updates the own
+  IP address (read: the main address) after changes (e.g. on
+  `ifup wlan0; sleep 1; ifdown wlan0`) and kills the
+  olsr_fill_routing_table_with_neighbors() function.
+----  snip  ----
+And Sven-Ola Tuecke <mail2news@commando.de> fixed an instability issue on interface
+up/down operations (see 102-olsrd-rt-refactoring-fixes.patch below) and a missing
+initialization.
+
+PATCH by Hannes Gredler <hannes@gredler.at> which "consolidates
+the link-state database and the spf-calculation in order
+to calculate routes more efficiently".
+To quote him (more):
+----  snip  ----
+- use the link-state (tc) database for SPF calculations rather than
+  replicating the notion of vertices and edges for a SPF run.
+  this heavily reduces malloc() calls and shrinks the total CPU
+  load of the route calculation path between 60%-80%.
+----  snip  ----
+
+PATCHES by Sven-Ola Tuecke <mail2news@commando.de> to be found on from
+http://download-master.berlin.freifunk.net/sven-ola/nylon/packages/olsrd/files/
+- 102-olsrd-rt-refactoring-fixes.patch
+  Because you changed a lot of basics: It's time to handle a general
+  flaw in the routing system. Plase take a look at chk_if_changed(). This
+  will free() any "struct interface" pointer without warning at any time.
+  This is why it's possile to SEGV olsrd with a simple "ifdown xxx".
+  The patch replaces the (maybe) invalid pointer with an index reference
+  "iif_index". You can always ask the OS for a name. Please note, that I do
+  not have a working BSD toolchain, so I've placed an #error in the IPv6
+  BSD-part where the author/porter has started to hack something funny.
+
+- 110-olsrd-double-wlancard-neigh-hack.patch:
+  This is a hack for Nodes having to wifi cards with the same channel,
+  bssid, IP-Range etc. If two nodes can see each other by means of two
+  possible links (here: two wifi cards with equal config), a bug is  triggered
+  with the Neigh-is-SYM detections. This small little hack prevents this.
+
+- 112-olsrd-nameservice-fixemptyname.patch:
+  This is an addon to my lat/lon stuff which will prevent olsrd from
+  running (oops?) if no hostname is given and the nameservice plugin
+  is loaded.
+
+- 113-olsrd-dyngwplain-pluginvers5.patch:
+  This updates the dyngwplain plugin to the new Plugin Iface
+
+- 140-olsrd-arprefreshed.patch:
+  This is a new one. Opens a packet socket and listen to UDP(698), extract
+  the sender MAC and refreshes the ARP cache whith that. Should speedup
+  especially in cases, if you initially try to use a longer routing path which
+  normally triggers a "ARP-Lookup-Chain".
+- 106-olsrd-nameserviceparams.patch:
+  This patch converts more plugins to the new interface version.
+- 104-olsrd-policy-routing.patch
+  Reworked this one to discard GPL helper functions. Also checked IPv6 and
+  re-included the IPC hookup. The patch adds a "RtTable [number]" for
+  /etc/olsrd.conf which is simply the Linux
+  policy routing table to use. Defaults to 254 (== main).
+  This patch was modified/clenaed up by <bernd@firmix.at> to use "#if"
+  instead of "#ifdef" as it's more robust against typos.
+- 110-olsrd-fixpacketprint.patch, 112-olsrd-nameservice-fixemptyname.patch,
+  113-olsrd-txtinfo-fixhttpget.patch, 114-olsrd-timeoutlimit.patch,
+  115-olsrd-nameserviceparamfix.patch and
+  116-olsrd-fix-pluginparam-addons.patch fixing the compilation warning
+  on 64bit and lots of other improvements.
+- "Save the fish" patch: Avoid forwarding of packets with too low TTL. This
+  kills lots of packet forwarding storms.
+  NB: The oneliner was applied by hand by BP and formatted to look (in BPs O)
+  more readable.
+
+PATCH by Arnd Hannemann <hannemann@i4.informatik.rwth-aachen.de>
+olsr_makefile_make_use_of_exename.patch
+- This patch makes sure that the EXENAME variable of Makefile.inc is used
+  in Makefile.
+
+PATCHES by John Hay <jhay@meraka.org.za>
+- update to new FreeBSD WLAN API
+- do not require /bin/bash, use /bin/sh
+- Fixed alignment so that olsrd runs on FreeBSD/arm
+- allow more interface in an IPv6 subnet on FreeBSD
+- use PREFIX and DESTDIR as all the other Makefile.$OS also for FreeBSD
+- make txtinfo plugin work with IPv6
+
+PATCH by Andreas Jacobs <jacobs@i4.informatik.rwth-aachen.de>
+- fix the loss link quality calculation for "windows size % 4 != 0"
+
+PATCH by Acinonyx <acinonyxs@yahoo.gr>
+- Bug fix: include $(TOPDIR)/Makefile.inc at the begin in the Quagga plugin
+
+PATCH by David Cornejo <dcornejo@gmail.com>
+- fixed an "+=" of an uninitialized variable (detected with/by the
+  scan.coverty.com).
+
+BUG reported by Aaron Kaplan <aaron@lo-res.org>
+- BSD-xargs doesn't know "-r".
+
+PATCHES and CLEANUPS by Bernd Petrovitsch <bernd@firmix.at>
+- Made a function from the ME_TO_DOUBLE() macro (in src/mantissa.h).
+  This saves code throughout the code even on i386 and will even more
+  on architectures without floating point units and "-msoft-float".
+- And the mathemathics in src/mantissa.h is reformulated to minimize
+  floating point operations to save CPU power - especially on embedded
+  devices.
+- I rewrote the half of src/lq_packet.[ch] which deals with incoming
+  packets. This was triggered with performance output of gcc produced
+  by Sven-Ola Tuecke at CCCamp07.
+  This kills *lots* of (more than) superflous malloc()s and the same
+  number of (free()s). And it also kills some code and copying around of
+  data.
+- Make it compile without warning with flex-2.5.33 (to be found on Fedora 7
+  and Gentoo in Sep-2007) again.
+
+- converted the dyn_gw plugin to plugin interface version 5 (which leaves
+  the quagga plugion as the last with the old one).
+- paving the way to activate -Wshadow, much more to do
+- const-ify parameters here and there
+- use NULL for pointers (and not "0")
+- Killed "extern" declarations in (not generated) .c files
+
+- Based on a patch by Gianni Costanzi <gianni.costanzi@gmail.com> (so credits
+  and thanks have to go there):
+  added OS_CFLAG_PTHREAD Makefile variable since gcc (on Linux) requests this
+  in the manual page.
+  Changes/additions:
+  - I added definitions to all OS-specific Makefile.$OS with the value similar
+    to the value in OS_LIB_PTHREAD (either empty or "-pthread").
+  - The variable is added to CPPFLAGS (and not CFLAGS) since CPPFLAGS is used
+    for all cpp and gcc calls (and gcc's man page indicates that it sets
+    variables for both of them).
+
+0.5.3 ---------------------------------------------------------------------
+
+URGENT BUG FIX
+Ignacio GarcÃ­a PÃ©rez <iggarpe@terra.es> found a serious bug in the dot-draw
+plugin and identified it's source.
+
+BUG FIX
+The bmf plugin wanted to kill a not-started thread and this causes a segmentation
+violation. This happens if the old plugin interface support is not compiled in
+and one uses - or more asccurate: wants to use - the bmf plugin which uses that
+ATM. Thanks to Cedric Krier <ced@ced.homedns.org> for reporting this.
+
+DEPENDENCIES FIXED
+The dependencies (*.d files) are now properly generated and used. And they also
+dependen on the Makefile in the current directory and the Makefile.inc so that
+changes there also lead to new compilation.
+Remember: We support "ccache" so install it to save lot of meaningless recompiles
+if nothing (as seen by the real C compiler, i.e. after the C preprocessor) has
+changed.
+
+BUILD FIX
+Linux/IA64 and Linux/HPPA also need "-fPIC".
+
+CLEANUPS
+- olsr_switch does no longer generate warnings
+- olsr_switch is also built with "build_all" and cleaned with "uberclean"
+- More "const" all over the place.
+- More "static" for local functions and variables.
+- Killed an unnecessary "static" variable.
+
+0.5.2 ---------------------------------------------------------------------
+
+URGENT BUG FIX
+Sven-Ola Tuecke found a serious bug of the class "show stopper" and sent a patch.
+
+PLUGIN CLEANUP
+Plugins handle parameters quite individually (case-sensitive vs case-insensitive,
+different parsing functions for the same values, etc.). Plugin Interface version 5
+now exports a table of { parameter-name, parsing-function, addr-of-storage } and
+it's size. Common functions should be shared.
+
+0.5.1 ---------------------------------------------------------------------
+
+MISC
+Upgrade to olsr-bmf 1.5 from Erik Tromp <erik_tromp@hotmail.com>
+
+latitude/longitude support is now in the nameservice plugin done by
+Sven-Ola Tuecke <mail2news@commando.de>
+
+added the spf refactoring patch from  Hannes Gredler <hannes@gredler.at> which
+saves a noteworthy amount of CPU time. To quote him:
+----  snip  ----
+1. use of an AVL tree as a min-heap implementation
+
+   as a means for efficient sorting.
+   (the etx metric is used as the key in the candidate tree)
+
+2. next-hop propagation
+
+   rather than tracking the previous node in olsr_relax()
+   i have changed that model and pre-populate all one-hop neighbors
+   with their own IP adress as 'next-hop' and pull that
+   pointer up once new paths are explored.
+
+   as a result no walker for counting hops and extracting next-hops
+   is required - it turns out at this is slighly more efficient
+   than the existing behaviour (even with the cache applied).
+----  snip  ----
+
+CLEANUPS
+* moved a only locally needed hack from "union olsr_ip_addr" into the only place
+  where it is needed in hashing.c
+
+0.5.0 ---------------------------------------------------------------------
+
+APPLIED PATCHES FROM FREIFUNK-FIRMWARE
+libsmake, dyngwplain, nameservices+services, tzxtinfo, quagga, quagga-routehandler,
+optimize, fixes from Eric Tromp and Sven-Ola Tuecke, CPU-optimize, secure key, HNA-IP
+
+CLEANUPS
+removed hardcoded limit on the number of interfaces (at least in the Unix part)
+made Makefile targets much more consistent
+
+MISC
+put Bmf-1.3 plugin into it
+
+FreeBSD IPv6 SUPPORT
+
+Patch from John Hay applied.
+
+BUGFIXES
+
+0.4.10 --------------------------------------------------------------------
+
+OLSR NETWORK SIMULATOR
+
+An application called olsr_switch(sorry for the nameclash with the win32
+GUI) has been added. If olsrd is ran using the -hint option it can now
+connect to olsr_switch and be part of a virtual network. This means
+that multiple instances can be ran at the same host! The olsr_switch
+application allows the user to define link variables on all viritual
+links in the network, creating all possible topologies. Read more in
+the readme file.
+
+EXPERIMENTAL FISH EYE ALGORITHM
+
+An experimental algorithm for TTL settings on TC messages has
+been added. Read more in the corresponding README file.
+
+OPENBSD SUPPORT
+
+olsrd now also compiles on OpenBSD systems. Thanks a lot to Holger
+Mauermann for the patches!
+
+BUILDSYSTEM REWRITE
+
+Bruno has rewritten the make system. OS detection is now done
+automagically and the general design is much improved.
+
+IP ADDRESS VALIDATION
+
+Olsrd now maintains a set of IP addresses that is considered
+invalid. Checks against this set is done on all received
+OLSR packets announced originator addresses. The dataset can
+be updated dynamically.
+
+PLUGIN INTERFACE
+
+Updated interface version to 3 and added more noticeable warning
+for version missmatch.
+
+MATH LIB DEPENDENCY
+
+The dependency on the math lib came from the use of pow(3) in the
+mantissa/exponent calculation. The calls to pow in this long forgotten
+code, was very unnessecarry. The pow calls are replaced with bitwise
+shifts and -lm is no longer needed.
+
+ICMP REDIRECTS ON LINUX
+
+On Linux systems "0" is now also written to the all/send_redirects
+procfile and not only the pr. interface ones. Hopefully this resolves
+problems reported with systems still sending ICMP redirects.
+
+BUGFIXES
+
+- Fixed init of IPv6 addrtype variable. It used to be uninitialized,
+  causing it to default to site-local and have some weird side-effects.
+- Fixed crash when changing IPv6 address at run-time
+- Fixed a bug that prevented setting willingness 0 in the configfile
+- Fixed bad handling of missing command line arguments
+- Did various updates to prevent assertion when a neighbor
+  has changed IP and sends HELLO before its olsrd precess has detected
+  the change.
+- Fixed return value check on times(2) calls in the scheduler
+- Fixed bug(s) that could cause crash when an interface was brought
+  down while olsrd was running.
+- Removed the silent (read: unchecked) hard limit of 16 interfaces.
+- Compiles now cleanly on 64bit (e.g. x86_64).
+
+0.4.9 ---------------------------------------------------------------------
+
+OPTIMIZATIONS
+
+The MID database is now also indexed by alias addresses. this makes
+look-ups of main addresses based on alias addresses _much_ faster.
+The mid_lookup_main_addr function alone has gone from >30% of the
+total CPU time used by olsrd to <1%.
+PLUGIN DEVELOPERS: datatypes for MID entries has been changed.
+
+Routing table calculation in the LQ case now uses balanced binary
+trees instead of linked lists, which makes look-ups much faster.
+
+The debug output function olsr_printf() is not used by olsrd
+internals any more. Instead the macro OLSR_PRINTF is to be used.
+This macro does debug level testing _before_ doing any function
+calls(both printf itself and parameters to printf). This is a much
+more optimized way of doing debug output. In addition olsrd can
+be built without any debug output code if doing 'make NODEBUG=1'.
+
+TIMEOUT OF DATASETS
+
+Validity times for dataset entries are now set using the clock_t type
+(used to be struct timeval). This data is now fetched from the times(2)
+function instead of gettimeofday(2). This prevents possible problems
+if the system time is changed.
+PLUGIN DEVELOPERS: Note that datatypes for close to all dataset entries
+(link, neighbor, mid, hna, tc etc.) has been changed!!
+
+CONFIGURATION FILE
+
+Multiple interfaces can now use the same interface configuration block.
+Example:
+Interface "if0" "if1" "if2"
+{
+	.....
+}
+
+Interface configurations now also support the "Weight" directive. When
+olsrd finds multiple links to a neighbor it will choose the link
+going via the interface with the lowest weight. Olsrd normally
+sets this weight dynamically based on interface characteristics,
+but if the user wishes to set a fixed weight in a interface(or
+a group of interfaces), this directive is now available.
+
+Moreover, interface configurations now support the "LinkQualityMult"
+directive. It takes an IP address and a multiplier as arguments.
+
+Example:
+
+Interface "if0"
+{
+  [...]
+
+  LinkQualityMult 192.168.0.1 0.7
+  LinkQualityMult default 0.5
+
+  [...]
+}
+
+The idea is to make certain links via the configured interface
+artificially worse or better than they really are. The first parameter
+specifies the IP address of a neighbour interface. The second
+parameter is the multiplier to be applied to the link to the specified
+neighbour interface.
+
+After we have derived the link quality from the packet loss among the
+packets received from the specified neighbour interface, we multiply
+the link quality by the given multiplier. So, the multiplier changes
+the LQ value that we use when determining the ETX, which is 1 / (LQ *
+NLQ).
+
+If "default" is given as the IP address then the multiplier applies to
+all links via the configured interface. Note, however, that olsrd only
+assigns one multiplier to each link. It does so in the following way.
+
+* If there is a "LinkQualityMult" line that matches the IP address of
+  the link's neighbour interface, then use the multiplier in this
+  line.
+
+* If there isn't any matching line, then look for a "default" line. If
+  there is a "default" line, then use the multiplier in this "default"
+  line.
+
+* Otherwise use 1.0, i.e. do not modify the LQ value at all.
+
+Hence, a line with an IP address has priority over a "default" line.
+
+In the above example, the LQ value of the link between the local
+interface if0 and the neighbour interface 192.168.0.1 would be
+multiplied by 0.7. All other links between the local interface if0 and
+a neighbour interface would be multiplied by 0.5.
+
+IPV6 SOCKETS
+
+The socket option IPV6_V6ONLY is now set on IPv6 sockets in linux.
+This means that olsrd will no longer receive IPv4 traffic when
+running in IPv6 mode.
+This should enable users to actually run one olsrd instance using
+IPv6 and one using IPv4 at the same time :)
+
+PLUGINS
+
+The httpinfo, dyn_gw and dot_draw plugins now all include olsrd
+headerfiles directly. A plugin should define OLSR_PLUGIN before
+including olsrd headers. Doing things this way removed the
+redundant datatype definitions that has so often caused trouble
+when things has been updated in olsrd.
+
+NETBSD SUPPORT
+
+olsrd now also compiles on NetBSD systems. Use 'make OS=nbsd' to
+build. This port is not very well tested and feedback is greatly
+appreciated.
+
+EXPERIMENTAL MULTI-INTERFACE CODE FOR FREEBSD
+
+Experimental code using libnet can be compiled in allowing multiple
+interfaces to be used in FreeBSD.  You enable this by compiling using
+OS=fbsd-ll.  You must have libnet-devel installed for this to work
+(/usr/ports/net/libnet-devel).
+
+OTHER UPDATES
+
+- WLAN devices are now detected in FreeBSD
+- First specified interfaces IP is used as main address.
+- Broadcastflag is not checked on interface if fixed broadcast is
+  set in config.
+- Removed Linux link layer code as this was not really in use.
+- Added -nofork command line option
+
+BUGFIXES
+
+- Link sensing now works according to announced vtime from
+  neighbors. Previously links going symmetric->asymmetric
+  were not necessarily detected until the holding time expired.
+- A bug in route addition/removal that could lead to routes
+  using GWs being added before the actual route to the GW
+  was set up, has been fixed.
+- A bug in the interface selection in route calculation has been
+  fixed. New routes are no longer added prior to deleting old ones,
+  since this caused trouble.
+- A bug in the IPv6 multicast address configuration has been fixed.
+  This caused olsrd not to work with global IPv6 addresses.
+- A bug in the IPv6 prefix-from IPaddr function has been fixed. This
+  bug caused HNA prefixes to always be calculated to 0.
+- If a 2-hop neighbor is also a 1-hop neighbor, a bug made olsrd
+  prefer a bad direct link to a better link via an MPR.
+- If a link or interface lookup failed, olsrd crashed.
+- Fixed a crash in the LQ packet generation code based on a
+  signed/unsigned integer comparison.
+
+
+0.4.8 ---------------------------------------------------------------------
+
+LICENSE CHANGE
+
+Olsrd is now distributed under a BSD style license. We believe olsrd will
+be better off using this license as it opens up for commercial players
+to use olsrd freely in their products. In the end this will lead to
+this kind of users doing serious testing and bug fixing of olsrd.
+
+ETX-LIKE LINK QUALITY DETECTION
+
+We can now determine the packet loss on a link by looking at the serial
+numbers of the OLSR messages received from a neighbor. This tells us how
+many packets get through from our neighbor to us. We use a new extended
+kind of HELLO messages (LQ_HELLO messages, LQ = link quality) to broadcast
+the link quality that we have determined on our end of the link to our
+neighbors. So do our neighbors, and we as well as they end up with an
+idea of how good the link is in both directions. From the LQ_HELLOs we
+also learn the link quality between our neighbors and our two-hop neigh-
+bors. In this way we can select those neighbors as MPRs that have the
+best links to our two-hop neighbors. To distribute the link quality
+throughout the network, we use a new extended version of TC messages
+(LQ_TC messages). They contain the qualities at both ends of each of our
+links. Nodes can then run Dijkstra's algorithm to find a path between
+themselves and other nodes that minimizes the packet loss.
+
+If the newly introduced "LinkQualityLevel" is set to zero in the
+configuration file, link quality is not used and the daemon behaves as
+before, i.e. as specified by the OLSR RFC. If this parameter is set
+to 1, LQ_HELLOs and LQ_TCs are used instead of HELLOs and TCs, link
+quality is measured and MPRs are selected based on the link qualities.
+If this parameter is set to 2, the routing table is additionally
+calculated based on the link qualities.
+
+Setting "LinkQualityLevel" to a non-zero value BREAKS COMPATIBILITY. You
+will then not be able to participate in RFC-conformant OLSR networks
+any longer. This is because we use LQ_HELLOs and LQ_TCs instead of HELLOs
+and TCs in this case.
+
+It's best practice to set "LinkQualityLevel" to the same value on all
+nodes in a network.
+
+When determining the quality of a link olsrd only considers a given
+number of most recent OLSR packets received from its neighbors. By
+default, olsrd looks at the 10 most recent OLSR packets. This can be
+changed via the "LinkQualityWinSize" configuration option. Values
+between 3 and 128 are legal.
+
+NEW CONFIGFILE PARSER/FORMAT/SCHEME
+
+A whole new config file syntax and parser is introduced with this
+release. The parser is generated using flex and bison and it is
+designed to be very modular. The parser can be compiled as either
+a standalone binary, a shared library or as part of olsrd. This way
+other applications can parse and generate olsrd configuration files
+only by linking to the dynamic library.
+In the new configfile options can be set pr. interface, plugin
+parameters can be set, more IPC options can be set...and more.
+The syntax is documented in the olsrd.conf(5) manual page found
+in the files/ directory.
+Olsrd internals now uses a single struct, as returned by the config
+parser, for all configuration in runtime. this means that updating
+values in this struct will dynamically update olsrd operation. It
+also means that all configuration is now kept in one place instead
+of spread all across the place.
+
+FREEBSD AND MAC OSX PORT
+
+This version offers an initial port of olsrd to FreeBSD and Mac OS
+X. Like the Windows port it currently does not support IPv6. As this
+is a very first try at supporting FreeBSD and Mac OS X, this port is
+probably not as reliable as the Linux version. We'd greatly appreciate
+feedback and bug reports. To compile you need GNU make. Then simply
+run "gmake OS=fbsd" to build the executable.
+
+NEW MAKEFILE(S)
+
+The makefiles used to build olsrd have been rewritten and now includes
+dependency file generation using makedep.
+
+DEBUG OUTPUT
+
+Tables are now only printed if changes occur, so there are no longer
+any periodical output when using a debuglevel >0. A "heartbeat" is
+now printed to STDOUT(if it is a terminal) in the form of a rotating
+line to show that olsrd is actually operating.
+Adding "ClearScreen yes" to the configuration file clears the screen
+each time before the debug output shows updated information. This
+makes the debug output easier to read in many cases. "ClearScreen no"
+is the default, if no "ClearScreen" directive is given in the
+configuration file.
+
+PLUGIN INTERFACE
+
+There are some changes in the plugin interface. It is now at
+version 2. Plugin specific parameters from the configfile
+using the PlParam option, will now be passed on to plugins.
+To receive such parameters a plugin must implement a function:
+int
+register_olsr_param(char *key, char *value)
+to which parameter pairs will be passed.
+
+NO MORE THREADS
+
+Olsrd no longer uses any thread library on its operation. Everything
+now happens in the main thread allowing for use of olsrd on platforms
+with no thread library.
+
+ACPI SUPPORT IN WILLINGNESS CALCULATION(LINUX)
+
+The willingness calculation for Linux, now also supports the more
+modern ACPI proc interface in addition to APM. This is not well
+tested and feedback is appreciated!
+
+IPC OPTIONS
+
+Various options regarding IPC connections can now be set in the
+configfile. The options are max connections, allowed unicast
+hosts and allowed net-ranges.
+
+CODE REWRITES
+
+Much of the message generation and net output code is rewritten.
+Sending of partial messages should now work 100%. Also TC, MID
+and HNA messages are now cached for a random amount of time
+before transmitted - this often leads to the situation where these
+messages are sent together with an HELLO message, which is highly
+desirable since it saves network resources.
+PLUGIN DEVELOPERS must note that the buffers and size variables
+used in net output is no longer directly accessible!
+
+NET OUTPUT CODE REWRITTEN
+
+Every interface now has one outputbuffer registered. This allows
+messages to be "cached" as explained above, so that multiple
+messages are stacked together.
+Also the outputbuffer and size are no longer accessible directly,
+an API is available to plugins(and olsr code).
+
+OS DEPENDENT NETWORK INTERFACE
+
+The OS dependent network functions are now defined in net_os.h
+instead of being mixed up with internal network functions
+in net.h.
+
+BUGFIXES
+
+A bug that caused the announced ANSN sequence number to never stop
+being increased when a change in the MPR selector set was detected
+has been fixed. Another TC related bug that caused timed out TC
+entries not to be deleted from the routing table in certain cases
+has also been fixed. These bugs could cause unstable routes.
+A bug that in many cases caused the wrong routes to be deleted
+when using IPv6 has been fixed.
+
+
+0.4.7 ---------------------------------------------------------------------
+
+NATIVE WINDOWS GUI AND INSTALLER
+
+We now have a native Windows GUI. The GTK+ version is no longer
+supported on Windows. The new native GUI is pretty compact as it does
+not require the GTK+ runtime DLLs. In addition to monitoring olsrds
+state the GUI offers an easy way for novice users to configure
+olsrd. It's pretty self-explanatory. Have a look at README-WIN32.txt
+for details. The Windows version now also comes with an installer
+based on the freely available Nullsoft Scriptable Install System
+(NSIS). Looks like the Windows port is becoming more and more
+Windows-ish. :-)
+
+WIRELESS INTERFACE DETECTION ON WINDOWS
+
+Like the Linux version the Windows port is now able to tell WLAN
+interfaces from wired interfaces. We can now, for example, set
+different HELLO intervals for WLAN interfaces and wired interfaces,
+respectively.
+
+ROUTE UPDATES
+
+The order of updates of calculated routes is swapped. Now new routes
+are added prior to deleting old ones. This could fix issues where
+in some very very few cases one could experiment loss of routes.
+
+BUGFIXES
+
+There were quite some bugs in IPv6 operation in 0.4.6. These are
+the bugs that were fixed:
+- HNA message parsing did not work.
+- Some IPv6 addresses were printed as IPv4 addresses in the
+  debug output.
+- The '-dispin' option now works again.
+- A filedescriptor leak in the IPv6 interface detection caused
+  olsrd to crash.
+
+
+0.4.6 ---------------------------------------------------------------------
+
+WINDOWS PORT!
+
+Read the README-WIN32.txt file!
+
+DYNAMIC NETWORK INTERFACE UPDATES
+
+Network interfaces can now be updated and removed/added at
+runtime. Olsrd will check all interfaces specified in the config
+file or on the command-line, every 5 seconds. If updates
+occur, olsrd will register this and update the necessary data.
+If interfaces are removed or added, olsrd will detect this
+and configure the interfaces. If an interface is removed
+olsrd will continue to check the interface, so if say, a PCMCIA
+card is removed and later on reinserted(and given the same name),
+olsrd will detect this and start running on it again.
+
+Note that olsrd will now run even if no interfaces are detected.
+
+ROUTE CALCULATION UPDATE
+
+All 1 hop neighbor addresses that are not directly reachable trough
+a symmetric link in the link set will now be added with a GW in the
+routing table. this GW will be an interface address from a registered
+symmetric link to the neighbor.
+
+MID UPDATE
+
+Alias addresses are now registered in the link set processing
+if available. This is not to pretty(since the vtime has to
+be a mere guess) but it gives faster initial route updates.
+If a HELLO is received(at initial registration) from an IP
+that is not the same as the one set as main address in the
+received HELLO header, then the IP from which the HELLO was
+received will be registered as an alias of the main address
+set in the HELLO header. The default vtime is set to 15 secs.
+
+CODE RESTRUCTURING
+
+All OS dependent interface configuration code is now located in
+OS/ifnet.c(that would be linux/ifnet.c if using GNU/Linux).
+The functions are available trough the headerfile src/ifnet.h
+
+CODE CLEANUPS
+
+- Some timer issues fixed
+- Got rid of the global socket descriptors
+- Updated indexing of network interfaces
+- Introduced a global socket to use for ioctl calls(ioctl_s)
+- Removed upper limit for interfaces to use
+- Point-to-point interfaces are now allowed
+- The main select(2) loop now uses a timeout
+- A small bugfix in the select fd-set update code
+- Some bugfixes in the configuration file parsing
+- stdout/stderr are now set to not be buffered
+- A bugfix in the MID generation regarding seq. numbering
+
+PLUGIN INTERFCAE
+
+A new set of functions that are called whenever a change in the
+interface configuration(update, addition, removal) is made is
+introduced.
+These functions are added and removed very much like the ptf
+functions. Available trough the functions add_ifchgf and del_ifchgf.
+
+OBS OBS OBS!!! PLUGIN DEVELOPERS READ THIS!!!!
+
+The interface struct(declared in interfaces.h) has changed.
+Plugin developers must update plugins that uses the interface
+struct!
+
+The headerfile olsr_plugin_io.h which contains the plugin interface
+commands now contains a revision list where all changes are
+stated.
+
+
+0.4.5 ---------------------------------------------------------------------
+
+PLUGIN: SECURE OLSR
+
+A plugin that generates and checks message signatures is added.
+Check lib/secure
+
+PLUGIN: TOPOLOGY GRAPH
+
+A plugin that generates output of the topology in the dot format
+is added. See lib/dot_draw
+
+OPTIMIZATIONS
+
+Some optimizations done that should cause fewer route recalculations.
+
+BUGFIXES
+
+Some bugs reported by Takafumi Tanaka fixed.
+
+RESTORATION OF NETWORK SETTINGS
+
+Network settings like disabling of ICMP redirects and spoof filter, are
+now restored at exit by olsrd.
+
+RFC COMPLIANCE FIX
+
+Nodes would in certain scenarios retransmit messages originating for
+themselves. This was a RFC incompliance. Reported by Ingmar Baumgart.
+
+NON-WLAN TIMERS
+
+No longer setting the HELLO interval of non-wlan interfaces as a multiplier
+of the wlan interval. The interval is set seperatly now.
+Due to this there are some updates in the configfile imperatives.
+
+CODE CLEANUPS
+
+Some new macros introduced for table insertion and removal and IP
+copying and comparison.
+
+FRONT END BUGFIXES
+
+IPv6 bugfixes in the GUI.
+
+
+0.4.4 ---------------------------------------------------------------------
+
+ROUTE CALCULATION
+
+Routes are no longer added via neighbors declaring a willingness
+of WILL_NEVER.
+
+LINK SENSING AND ROUTE CALCULATION
+
+Link sensing and route calculation has been updated to handle
+multiple links between hosts in a sane way.
+
+IP SPOOF FILTERING
+
+IP spoof filtering is disabled on the interfaces which olsrd runs.
+These settings are not restored!
+
+ICMP REDIRECTS
+
+ICMP redirect message generation is disabled on the interfaces
+which olsrd runs.
+These settings are not restored!
+
+CONFIGFILE OPTIONS FOR MID AND HNA ADDED
+
+Options to set the MID and HNA emission intervals and
+validity time in the configfile added.
+
+IPv6 ADDRESS SCOPE
+
+Option to set what IPv6 address type(scope) to use in the
+configfile added. It can be set to either global or site-local.
+
+IPv6 MULTICAST
+
+Options to set site-local and global multicast addresses
+in the configfile added.
+
+EMISSION INTERVAL FUNCTION
+
+Functions to set emission intervals at runtime added.
+
+LINK LAYER NOTIFICATIONS
+
+If started with the -llinfo switch olsrd will collect and display
+link-layer information on neighbors. This is no longer limited to
+one interface. But no action is taken based on this info - and
+there is a upper limit of 8 neighbors from which this info can
+be collected pr. interface. This limitation is inherited from the
+WLAN drivers and is not something imposed by the olsrd code!
+
+IPv6 HNA MESSAGE FORMAT
+
+IPv6 HNA messages now contains 128-bit netmask instead of prefix.
+
+PLUGIN FUNCTIONS
+
+Added "packet transform functions" which allow plugins to alter all
+outgoing OLSR traffic.
+
+RESTRUCTURING
+
+Moved most headers out of OS dependent directories. The tunneling
+and link-layer notification interface is not yet separated from
+the /linux directory.
+
+MANUALPAGE
+
+A manpage(olsrd(8)) describing olsrd has been created. It is installed
+when using 'make install'.
+
+
+0.4.3 ---------------------------------------------------------------------
+
+PLUGIN SUPPORT
+
+Olsrd now supports runtime-loadable plugins! A couple of example plugins
+are located in the lib/ directory. Read the README files in the various
+plugin directories for more info. A directive to load plugins have been
+added to the configfile as well.
+Documentation of the plugin interface can be fount at http://www.olsr.org.
+
+The plugin interface is designed to be extendable. But it should _always_
+be backwards compatible with the interface used in this release!
+
+LINK-LAYER NOTIFICATION
+
+Some preliminary link-layer notification code has been added. Link quality
+can be written to stdout if olsrd is started with the -llinfo switch.
+No action is currently taken based on this info. And info will only
+be retrieved from the interface named "eth1".
+This code is not usable for users as of yet!
+
+MPR UPDATES
+
+Neighbors with willingness set to WILL_ALWAYS is now always added. The
+MPR selection is optimized as described in RFC3626 section 8.3.1
+point 5.
+
+MPR BUGS
+
+There was a couple of bugs in the MPR selection code. All fixed.
+
+LINUX 2.6 BUG
+
+Users could not run olsrd on multiple interfaces using the Linux 2.6 kernel
+series. This is now fixed.
+
+MINOR BUGS
+
+One small bug in link hysteresis initialization and one in HNA route
+deletion.
+
+MESSAGE-SEQUENCENUMBER INCOMPLIANCE
+
+Message-seqnos was implemented on a pr. messagetype and pr. interface
+basis. This is not RFC3626 compliant and has been updates. All messages
+and interfaces now uses a global seuencenumber.
+
+RANDOM SEQUENCENUMBERS
+
+Sequencenumbers are now initialized using a random value.
+
+DAEMON MODE
+
+Fixes for running olsrd in daemon mode(debug 0).
+
+OPTIMIZATIONS
+
+Optimizations based on profiling implemented.
+
+SANITATION
+
+Message size is checked for every message before passing it to the
+appropriate message parsing function. If the size is bigger than the
+remaining size of the olsr packet then the message is discarded.
+
+GUI FRONT-END
+
+Some minor modifications done to the gui.
+
+INTERNAL CHANGES
+
+Lots of changes in handling of registration and unregistration of
+scheduler, socketparser, parser and local hna set.
+Some restructuring and movement of functions.
+
+
+0.4.2 ---------------------------------------------------------------------
+
+No public release
+
+0.4.1 ---------------------------------------------------------------------
+
+No public release
+
+0.4.0 ---------------------------------------------------------------------
+
+LINK HYSTERESIS
+
+Link hysteresis as described in the RFC added.
+
+TC REDUNDANCY
+
+TC redundancy as described in the RFC added
+
+MPR REDUNDANCY
+
+MPR redundancy as described in the RFC added
+
+SCHEDULER REWRITE
+
+The scheduler has been rewritten to register scheduled
+events(function pointers) dynamically.
+
+PARSER REWRITE
+
+The parser has been rewritten to register parse functions
+on a pr. messagetype dynamically
+
+MALLOC WRAPPER
+
+A wrapper for the malloc(3) syscal has been introduced.
+olsr_malloc(size_t, const char *) should ALWAYS be used.
+
+CODE RESTRUCTURING
+
+Lots of restructuring in headerfiles.
+Linux spesific code moved to subdirectory linux/
+FreeBSD code to be put in freebsd/
+LOTS of code restructured due to the rexrite of the scheduler
+and parser.
+
+MPR CALCULATION
+
+Optimizing the MPR set as suggested in the RFC section
+8.3.1 point 5 added.
+
+BUGFIXES
+
+Some bugs in MPR selection fixed.
+
+
+0.3.8 ---------------------------------------------------------------------
+
+CODE REWRITES
+
+HNA code completely rewritten!
+The old code was really bad! Now it is much cleaner implemented and
+should work fine.
+One- and two-hop neighbor list structures rewritten. They now use
+the same hashed double-linked lists as the rest of the information
+sets use.
+
+CODE RESTRUCTURING
+
+Some code restructuring which resulted in the new files: timer.h,
+mantissa.c, mantissa.h, hashing.c, hashing.h, linux/net.c
+linux/net.h, linux/kernel_routes.c, linux/kernel_routes.h and some
+renamed files
+
+BUG FIXES
+
+The bug causing errormessages on exit is fixed.
+The bug that caused initial HNA routes in the GUI to display a hopcount
+of 0 fixed.
+IPv6 HNA netmasks were all added as /128. It's fixed now.
+
+IPv6
+
+Turns out sitelocal address had to be preferred to avoid IPv6 header
+messing up link-sensing. Bug fixed
+
+
+0.3.7 ---------------------------------------------------------------------
+
+CODE REWRITES
+
+The entire TC set and MPR selector set code rewritten. Hashing and
+double linked lists added to the MID code.
+Lots of HNA code has been rewritten as well.
+
+HNA bugfix
+
+When a node lost connectivity to a HNA GW all HNA entries to that gw
+was deleted. This has been fixed - and HNA entries only gets deleted
+on timeout now.
+Other HNA bugs have been fixed as well. But the whole HNA implementation
+needs a rewrite!
+
+Holdingtime BUGfix
+
+There was a bug that caused holdingtime not to be properly recalculated
+when using non-default emission intervals.
+
+Forwarding and symmetric neighbors
+
+Seems I had misread the RFC on what a 1-hop symmetric neighbor is.
+Now the link-set is checked when a check for a symmetric neighbor
+is done. Not the 1 hop neighbor set as it used to be. This way
+the hack when receiving MID messages could be removed.
+
+IPv6
+
+Global addresses are now preferred. Sitelocal addresses are only used
+if no global addresses are found. There have been problems where
+the address set in the IP header of IPv6 packets do not match the
+address chosen by OLSR.
+
+GUI - 0.2.5
+
+The GUI is finally updated! It can now handle piggybacked messages
+and link sensing HELLO message format.
+
+
+0.3.6 ---------------------------------------------------------------------
+
+HNA support using IPv6
+
+HNA now works using IPv6 as well! Just add the network address and
+prefix in the HNA6 section in the configfile. The IPv6 HNA packets differ
+some from the IPv4 as they don't send the netmask but the prefix.
+
+
+NEW FILENAME FOR THE BINARY AND CONFIG FILE
+
+They are now called olsrd and olsrd.conf. I figured I'd use the olsrd
+name before somebody else started using it ;-)
+
+
+Config file
+
+New options: DEBUG, HNA6 and IPC-CONNECT added to config file.
+
+
+Output
+
+A printf-wrapper has been introduced - debug level output handling
+is much more uniform now.
+The daemon should run fine in detached mode now(DEBUG 0)
+
+GUI front-end
+
+The GUI front-end can now connect and disconnect at any time while the
+daemon is running, if started using the -ipc switch or with IPC set to
+'yes' in the configfile.
+
+
+BUGS
+
+A small HNA bug fixed.
+
+
+0.3.5 ---------------------------------------------------------------------
+
+Forwarding jitter
+
+Forwarding jitter added. Messages are piggybacked if they arrive(and are to
+be forwarded) while there is data to be forwarded buffered.
+Added some bugfixes to support parsing of piggybacked messages as well.
+
+Route calculation
+
+Fixed route calculation so that 2 hop neighbors are added. This smooths
+changes from 1 hop to 2 hop neighbor out. The old way one had to wait for
+a TC before the 2 hop neighbors were added.
+
+2 hop neighbor set
+
+All neighbors received in HELLO messages are added to the two hop
+neighborhood. This helps smoothing out the 1-to-2 hop transition as well.
+
+MID calculation
+
+MID calculation had to be updated due to the registering of two hop neighbors
+that are already one hop neighbors. They should not be considered when calculating
+two hop coverage.
+
+Optimizations
+
+Deletion of possible one hop neighbors registered on non main-addresses when
+first registering MID info from a node removed. This can not occur due
+to the fact that registering of neighbor nodes are done on main addresses
+from link-sensing
+Option to not forward messages on wired links on which they arrived removed.
+This is no longer usable to any degree when adding support for piggybacking
+of forwarded messages is to be implemented.
+
+Cleanups
+
+Some unused parameters and commandline options were removed.
+
+
+
+0.3.3 ---------------------------------------------------------------------
+
+TC MESSAGEING
+
+Added sending of empty TC messages if all MPR selectors are removed. Empty
+TC messages are sent for a TC_HOLD_TIME period as described in section
+9.3 in the RFC.
+
+HNA
+
+Fixed HNA route calculations for IPv6. I forgot to upgrade this in 0.3.2
+
+OPTIONS
+
+-hnaint and -midint command line optionas added to set the interval
+of HNA and MID generation.
+
+FORWARDING
+
+As an optimization messages have not been forwarded on the received interface
+if this is registered as a non-WLAN interface. This causes problems for
+people using Ethernet-to-WLAN adapters. This optimization is now turned
+off by default. It can be activated using the -nofwlan option.
+
+BUGS
+
+THERE ARE SOME NASTY BUGS IN 0.3.2!
+Fixed a bug that caused 2 hop neighbors not to time out.
+Fixed a bug that caused a 1 hop neighbor timeout not to recalculate
+the routing table.
+Fixed a small memleak in the MID set
+Fixed some smaller bugs.
+
+IPv6 functioning is not well tested in this release.
+
+0.3.2 ---------------------------------------------------------------------
+
+HNA
+
+Updated HNA to be RFC compliant. This means that all received HNA tuples
+are registered and only the subset of unique entries(net/netmask) with
+the smallest hopcount is inserted into the routing table.
+
+Config file
+
+User can specify configfile name using the -f switch.
+
+Bugs
+
+Fixed a link-sensing bug that caused problems when using MID nodes.
+
+0.3.1 ---------------------------------------------------------------------
+
+MPR calculation
+
+MPR calculation is now based on the willingness announced by nodes.
+
+Neighbor set
+
+The neighbor set does not have timeouts on entries any more. Creation
+and deletion of neighbor entries is done from the link-set as suggested
+in the RFC.
+
+Cleanups
+
+Gotten rid of a lot of code that became more or less obsolete due to
+all the changes introduced in 0.3.0.
+
+Bugs
+
+Fixed a nasty bug concerning the sequence numbering of TC packets.
+Fixed some bugs regarding MPR calculation - and probably introduced
+a whole new species when implementing the willingness-based calculation ;-)
+
+
+0.3.0 ---------------------------------------------------------------------
+
+Due to the extensive amount of updates this release is versioned 0.3.0
+
+Duplicate table and forwarding
+
+The duplicate table functionality is totally rewritten in 100% RFC
+compliance. The forward algorithm specified in the RFC is implemented
+this meant rewriting much of the packet processing code. The daemon
+also forwards unknown packettypes now.
+
+Link sensing and neighbor processing
+
+Link sensing and neighbor processing was done in the same operation in the
+old code. Link sensing is now a mechanism of its own which is 100% RFC
+compliant. Neighbor processing and HELLO generation has been partly
+rewritten to be RFC compliant. Neighbors are now registered as either
+SYN or NOT_SYM. The NOT_NEIGH, SYM_NEIGH and MPR_NEIGH values are only
+used when building HELLO messages. Links are in one of the following states:
+UNSPEC_LINK, ASYM_LINK or SYM_LINK.
+HELLO messages now advertise link status of neighbors on the interface
+the message is transmitted.
+
+Willingness
+
+A node now dynamically calculates willingness based on powersource and
+possibly battery power. If the node is AC powered it announces a willingness
+of 6. If batterypowered the willingness is calculated as:
+P / 26
+Where P is percentage of power left.
+
+Configuration file
+
+The daemon now tries to read its configuration from the file /etc/uolsrd.conf
+A "standard" configuration file is installed when doing 'make install'.
+This file should be edited to fit your needs.
+Command-line options can still be used to override the configuration form
+the file(ore if no config file is present).
+The -f switch can also be used to specify a configuration file.
+
+Willingness
+
+If AdvancedPowerManagemant(APM) is supported on your system the willingness
+of the node is dynamically calculated based upon the powerstatus of the node.
+MPR calculation based upon willingness is not done as of yet.
+
+TC ANSN
+
+A bugs in the TC processing fixed.
+
+HNA
+
+Some serious HNA bugs fixed. These bugs caused a node to always choos the
+gateway with the larges hopcout :) More seriously - a bug caused looping
+of HNA messages in certain scenarios.
+
+Package sequence numbers
+
+These were added. Not much use as of now - but they're there(as specified
+in the RFC).
+
+Broadcast address
+
+Users can now specify the broadcast address to use. Useful if one wishes to
+use the 255.255.255.255 broadcast.
+
+
+
+0.2.5 ---------------------------------------------------------------------
+
+Htime and Vtime
+
+Htime and Vtime processing and handling added. Holding times used to be
+a static value for all nodes. Now every node can signal its vlidity time
+to others.
+To achieve this mantissa/exponent calculation functionality was added.
+Messages now include Vtime(and Htime in HELLO) values in mantissa/exponent
+format instead of just zero. These values are as stated above, used as holding
+time for nodes.
+the GUI should be upgraded as well...
+
+Jitter
+
+The use of jitter in message generation intervals vere fixed.
+
+
+0.2.4 ---------------------------------------------------------------------
+
+Seqno bugs
+
+Some bugs concerning sequence numbers in HELLO and MID message handling
+was fixed. Newly registered nodes in the neighbor and MID sets were
+initialized with a seqno of 0. When using a "wraparound" sequencenumber
+check(as defined in olsr_protocol.h) this can produce errors if a new
+node joins a network where existing nodes has seqnos >0x00FF.
+
+IPv6 related bugs
+
+Some checks and copying of node addresses where done using sizeof(u_olsr32_t)
+which is 32 bits. This caused only the 32 firs bits of IPv6 addresses to
+be copied and checked.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/LICENCE ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/LICENCE
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/LICENCE	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/LICENCE	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,19 @@
+SRC +=	$(wildcard ./src/*.c)
+
+OBJS = $(SRC:.c=.o)
+
+CC = gcc
+CFLAGS = -c -g -Wall -Werror -I./src
+LFLAGS = -g -Wall 
+BUILDLIBS = -L/usr/lib -lpcap -Wl
+
+.c.o:
+	${CC} ${CFLAGS} -o $@ $^
+
+netsimpcap:	${OBJS}
+	${CC} -o ./bin/$@ ${LFLAGS} ${BUILDLIBS} ${OBJS}
+
+clean:
+	rm -f ${OBJS} ./bin/netsimpcap
+
+all: netsimpcap
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/sampleconf.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/sampleconf.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/sampleconf.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/sampleconf.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,11 @@
+0 1 0.8
+
+1 2 0.9
+
+2 3 0.8
+
+3 4 0.7
+
+4 5 0.9
+
+5 0 0.95
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/config.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/config.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/config.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/config.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,107 @@
+/*
+ * NetsimPcap - a userspace network bridge with simulated packet loss
+ *             Copyright 2008 H. Rogge (rogge@fgan.de)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "debug.h"
+
+/*
+ * stripString
+ * 
+ * this function strips leading and trailing whitespaces from a string
+ * 
+ * @param string to strip
+ * @return stripped string
+ */
+char *
+stripString (char *str)
+{
+
+  /* strip left whitespaces */
+  while (*str == ' ' || *str == '\t') {
+    str++;
+  }
+	
+  /* strip right whitespaces */
+  int i = strlen(str);
+  while (--i >= 0) {
+    if(str[i]==' ' || str[i]=='\r' || str[i]=='\n' || str[i]=='\t') {
+      str[i] = 0;
+      break;
+    }
+  }
+	
+  return str;
+}
+
+/*
+ * readConnectionMatrix
+ * 
+ * This function reads the network settings and place them in the
+ * connection matrix (float array with size "len" x "len".
+ * 
+ * @param pointer to begin of connection matrix
+ * @param pointer to filename
+ * @param number of elements in each connection matrix line
+ * @return 0 if function was successfull, 1 if an error happened
+ */
+int
+readConnectionMatrix (float *connectionMatrix, char *filename, int len)
+{
+  FILE *file = fopen(filename, "r");
+  if (!file) {
+    return 1;
+  }
+	
+  char buffer[1024];
+  while (fgets(buffer, 1024, file)) {
+    int from, to;
+    float propability;
+    
+    char *line = stripString(buffer);
+    DPRINT("%s\n", line);
+		
+    if (line[0] == '#' || line[0] == 0) {
+      continue;
+    }
+		
+    if(sscanf(line, "%d %d %f", &from, &to, &propability) != 3) {
+      continue;
+    }
+		
+    if (from < 0 || from >= len || to < 0 || to >= len || from == to) {
+      continue;
+    }
+		
+    connectionMatrix[GRID(from, to, len)] = propability;
+    if (connectionMatrix[GRID(to, from, len)] == 0) {
+      connectionMatrix[GRID(to, from, len)] = propability;
+    }
+  }
+  fclose(file);
+  return 0;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/config.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/config.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/config.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/config.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,32 @@
+/*
+ * NetsimPcap - a userspace network bridge with simulated packet loss
+ *             Copyright 2008 H. Rogge (rogge@fgan.de)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONFIG_H_
+    
+#define CONFIG_H_
+
+#define GRID(x,y,width) ((x) + (y) * (width))
+
+int readConnectionMatrix(float *connectionMatrix, char *filename, int len);
+#endif /*CONFIG_H_*/
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/debug.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/debug.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/debug.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/debug.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * NetsimPcap - a userspace network bridge with simulated packet loss
+ *             Copyright 2008 H. Rogge (rogge@fgan.de)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WLAN_DEBUG_H
+#define WLAN_DEBUG_H
+
+#define DPRINT(...)		if(debugMode) { printf(__VA_ARGS__); }
+
+#define DHEXDUMP(purpose, data,length)	if (debugMode) {	\
+		int i;										\
+		printf("Hexdump: %s\n", purpose);						\
+		for (i=0; i<length; i++) {					\
+			if ((i & 31) == 0)	printf("%04x: ", i);\
+			printf("%02x", ((int)data[i])  & 255);	\
+			if ((i & 3) == 3) printf(" ");			\
+			if ((i & 31) == 31) printf("\n");		\
+		}											\
+		printf("\n\n");								\
+	}
+
+extern int debugMode;
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/netsimpcap.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/netsimpcap.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/netsimpcap.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/netsimpcap.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,397 @@
+/*
+ * NetsimPcap - a userspace network bridge with simulated packet loss
+ *             Copyright 2008 H. Rogge (rogge@fgan.de)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pcap.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/if_tun.h>
+#include <net/if_arp.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "config.h"
+#include "network_tap.h"
+
+int debugMode = 0;
+
+int running;
+
+pcap_t* devices[128];
+int deviceFD[128];
+int deviceCount;
+
+int tapFD;
+
+u_int32_t *connBC;
+u_int32_t *connUni;
+
+u_int8_t buffer[65536];
+u_int8_t mac_bc[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * signalHandler
+ * 
+ * This handler stops the mainloop when the programm is send a signal
+ * to stop
+ */
+static void
+signalHandler (int signo __attribute__((unused)))
+{
+  running = 0;
+}
+
+/*
+ * calculateConnections
+ * 
+ * @param pointer to user defined connection matrix
+ * @param number of elements in a matrix line
+ * @param 1 if matrix contains drop-propabilities
+ */
+void
+calculateConnections (float *connMatrix, int socketcount, int drop)
+{
+
+  /* calculating unicast/broadcast matrix */
+  connUni = malloc(sizeof(u_int32_t) * socketcount * socketcount);
+  memset(connUni, 0, sizeof(u_int32_t) * socketcount * socketcount);
+  connBC = malloc(sizeof(u_int32_t) * socketcount * socketcount);
+  memset(connBC, 0, sizeof(u_int32_t) * socketcount * socketcount);
+  
+  float broadcast, unicast;
+  int i, j;
+  for (j=0; j<socketcount; j++) {
+    for (i=0; i<socketcount; i++) {
+      float prop = connMatrix[GRID(i, j, socketcount)];
+      if (drop) {
+        prop = 1.0 - prop;
+      }
+      broadcast = prop;
+      
+      /* IEEE 802.11 do (normally) up to 4 retransmissions for unicast.
+       * A unicast package is only lost if all of this 5 transmissions
+       * are lost.
+       */      
+      prop = 1 - prop;
+      unicast = (1 - prop)*(1 + prop + prop*prop + prop*prop*prop + prop*prop*prop*prop);
+      
+      connBC[GRID(i, j, socketcount)] = (1<<24) * broadcast;
+      connUni[GRID(i, j, socketcount)] = (1<<24) * unicast;
+    }
+  }
+  
+  if (debugMode) {
+    printf("Connection matrix for unicast:\n");
+    for (j=0; j<socketcount; j++) {
+      for (i=0; i<socketcount; i++) {
+        if (i>0) {
+          printf(" ");
+        }
+        
+        printf("%1.2f", (float)connBC[GRID(i,j, socketcount)] / (float)(1<<24));
+      }
+      printf("\n");
+    }
+    printf("\nConnectionmatrix for broadcast:\n");
+    for (j=0; j<socketcount; j++) {
+      for (i=0; i<socketcount; i++) {
+        if (i>0) {
+          printf(" ");
+        }
+        
+        printf("%1.2f", (float)connUni[GRID(i,j, socketcount)] / (float)(1<<24));
+      }
+      printf("\n");
+    }
+  }
+}
+
+/*
+ * tap_callback
+ * 
+ * This function is called every times a package is received through the
+ * (optional) tap device. It retransmits the package to all connected devices.
+ */
+void
+tap_callback (void)
+{
+  int len, i;
+  
+  len = read(tapFD, buffer, sizeof(buffer));
+  if (len > 0) {
+    for (i=0; i<deviceCount; i++) {
+      pcap_inject(devices[i], buffer, len);
+    }
+  }
+}
+
+/*
+ * capture_callback
+ * 
+ * This function is called for every package received through libpcap on
+ * one of the connected devices. It retransmit the package to the other
+ * devices (loss propability is defined in connection matrix) and always
+ * to the tap device (if active)
+ * 
+ * See libpcap documentation for parameters
+ */
+void
+capture_callback (u_char *args, const struct pcap_pkthdr* hdr, const u_char* packet)
+{
+  int *index = (int *)args;
+  int unicast = memcmp(packet, mac_bc, 6) != 0;
+  
+  int i, len;
+  
+  len = hdr->len;
+  memcpy(buffer, packet, len);
+  
+  if (tapFD != -1) {
+    int send = 0;
+    while (send < len) {
+      int t = write(tapFD, &buffer[send], len - send);
+      if (t == -1) {
+        printf("Error while sending to tap device!\n");
+        break;
+      }
+      send += t;
+    }
+  }
+  
+  for (i=0; i<deviceCount; i++) {
+    u_int32_t prop;
+    if (unicast) {
+      prop = connUni[GRID(*index, i, deviceCount)];
+    } else {
+      prop = connBC[GRID(*index, i, deviceCount)];
+    }
+    
+    if (prop == 0 || prop < (rand() % (1<<24))) {
+      continue;
+    }
+    
+    pcap_inject(devices[i], buffer, len);
+  }
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+  int dropPropability = 0;
+  char *connectionFile= NULL;
+  int deviceIndex = -1;
+  int hubMode = 0;
+  
+  MacAddress mac;
+  char *tapname = NULL;
+  
+  if (argc==1 || (argc == 2 && strcmp(argv[1], "--help")==0)) {
+    printf("%s: [-con <connectionfile>] [-hub] [-debug]"
+        " [-tap <devname> <mac>] [-drop] -dev <dev1> <dev2> <dev3>...\n", argv[0]);
+    return 0;
+  }
+  
+  deviceCount = 0;
+  tapFD = -1;
+  
+  for (i=1; i<argc; i++) {
+    if (strcmp(argv[i], "-con")==0 && i < argc-1) {
+      connectionFile = argv[i+1];
+      i++;
+    }
+    if (strcmp(argv[i], "-drop")==0) {
+      dropPropability = 1;
+    }
+    if (strcmp(argv[i], "-dev")==0) {
+      deviceIndex = ++i;
+      while (i < argc && argv[i][0] != '-') {
+        i++;
+        deviceCount++;
+      }
+      i--; /* to cancel the i++ in the for loop */
+    }
+    if (strcmp(argv[i], "-hub")==0) {
+      hubMode = 1;
+    }
+    if (strcmp(argv[i], "-tap")==0 && i < argc-2) {
+      tapname = argv[++i];
+      readMac(argv[++i], &mac);
+    }
+    if (strcmp(argv[i], "-debug")==0) {
+      debugMode = 1;
+    }
+  }
+  
+  if (hubMode == 1 && connectionFile != NULL) {
+    printf("Error, you cannot set matrix file in hub mode.\n");
+    return 1;
+  }
+  
+  if (connectionFile == NULL && hubMode == 0) {
+    printf("Error, netsim needs a matrix file for connections if not running in hub mode.\n");
+    return 1;
+  }
+  
+  if (deviceIndex < 0) {
+    printf("Error, you must specify the devices the programm connects to.\n");
+    return 1;
+  }
+  
+  if (deviceCount < 2) {
+    printf("Error, you need to bind at least two devices to the bridge.\n");
+    return 1;
+  }
+  
+  if (tapname) {
+    tapFD = createTap(tapname, &mac);
+    if (tapFD==-1) {
+      printf("Error, cannot open tap device '%s'\n", tapname);
+      return 1;
+    }
+    
+  }
+  running = 1;
+  
+  float *connMatrix = malloc(sizeof(float) * deviceCount * deviceCount);
+  if (!connMatrix) {
+    printf("Error, not enough memory for mac buffer!");
+    if (tapFD != -1)    closeTap(tapFD);
+    return 1;
+  }
+  
+  if (hubMode) {
+    int x,y;
+
+    /*
+     * In hub mode the any-to-any loss factor is 1.0, which
+     * means we can skip reading a matrix file.
+     */
+    for (y=0; y<deviceCount; y++) {
+      for (x=0; x<deviceCount; x++) {
+        if (x != y) {
+          connMatrix[GRID(x,y,deviceCount)] = 1.0;
+        }
+      }
+    }
+  } else {
+    if (readConnectionMatrix(connMatrix, connectionFile, deviceCount)) {
+      printf("Error while reading matrix file\n");
+      free(connMatrix);
+      if (tapFD != -1)    closeTap(tapFD);
+      return 1;
+    }
+  }
+  calculateConnections(connMatrix, deviceCount, dropPropability);
+  free(connMatrix);
+
+  char errbuf[PCAP_ERRBUF_SIZE];
+  int maxDeviceFD = 0;
+  
+  if (tapFD != -1) {
+    maxDeviceFD = tapFD;
+  }
+  for (i=0; i<deviceCount; i++) {
+    devices[i] = pcap_open_live(argv[i + deviceIndex], BUFSIZ, 0, -1, errbuf);
+    deviceFD[i] = -1;
+    if (devices[i] == NULL) {
+      printf("Error, cannot open pcap for device '%s'.\n", argv[i + deviceIndex]);
+      running = 0;
+    } else {
+      deviceFD[i] = pcap_fileno(devices[i]);
+      if (deviceFD[i] > maxDeviceFD) {
+        maxDeviceFD = deviceFD[i];
+      }
+    }
+  }
+  
+  /* activate signal handling */
+  signal(SIGABRT, &signalHandler);
+  signal(SIGTERM, &signalHandler);
+  signal(SIGQUIT, &signalHandler);
+  signal(SIGINT, &signalHandler);
+  
+  while (running) {
+    fd_set socketSet;
+    int socketsReady;
+    struct timeval timeout;
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+    
+    FD_ZERO(&socketSet);
+    for (i=0; i<deviceCount; i++) {
+      FD_SET(deviceFD[i], &socketSet);
+    }
+    if (tapFD != -1) {
+      FD_SET(tapFD, &socketSet);
+    }
+    
+    socketsReady = select(maxDeviceFD+1, &socketSet, (fd_set *) 0, (fd_set *) 0, &timeout);
+    if (socketsReady <= 0) {
+      break;
+    }
+    
+    for (i=0; i<deviceCount; i++) {
+      if (FD_ISSET(deviceFD[i], &socketSet)) {
+        int error = pcap_dispatch(devices[i], -1, capture_callback, (u_char *)&i);
+        
+        if (error == -1) {
+          printf("Error during pcap_dispatch for device %s\n", argv[i + deviceIndex]);
+          running = 0;
+          break;
+        }
+      }
+    }
+    if (tapFD != -1 && FD_ISSET(tapFD, &socketSet)) {
+      tap_callback();
+    }
+  }
+  
+  for (i=0; i<deviceCount; i++) {
+    if (devices[i] != NULL) {
+      pcap_close(devices[i]);
+    }
+  }
+  free(connUni);
+  free(connBC);
+  
+  if (tapFD != -1)    closeTap(tapFD);
+  return 0;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,228 @@
+/*
+ * NetsimPcap - a userspace network bridge with simulated packet loss
+ *             Copyright 2008 H. Rogge (rogge@fgan.de)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/if_tun.h>
+#include <net/if_arp.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "config.h"
+#include "debug.h"
+#include "network_tap.h"
+
+char macBroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * This function translates a mac address from string
+ * to binary format.
+ * 
+ * @param pointer to source string
+ * @param pointer to target mac adresee
+ * @return 0 if successful, 1 for an error
+ */
+int
+readMac (char *value, MacAddress *target)
+{
+  char buffer[13];
+  int index = 0;
+  
+  memset(buffer, 0, sizeof(buffer));
+  
+  char c;
+  while ((c = *value++)) {
+    switch (c) {
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case 'a':
+    case 'A':
+    case 'b':
+    case 'B':
+    case 'c':
+    case 'C':
+    case 'd':
+    case 'D':
+    case 'e':
+    case 'E':
+    case 'f':
+    case 'F':
+      if (index > 11) {
+        return 1;
+      }
+      buffer[index++] = c;
+      break;
+    default:
+      break;
+    }
+  }
+  
+  if(index < 12) {
+    return 1;
+  }
+  
+  for (index = 5; index >= 0; index--) {
+    buffer[index*2+2] = 0;
+    
+    int value;
+    sscanf(&buffer[index], "%x", &value);
+    target->mac[index] = (char) value;
+  }
+  return 0;
+}
+
+/*
+ * closeTap
+ * 
+ * This function close a tap device
+ * 
+ * @param file destriptor of the tap device
+ */
+void
+closeTap (int fd)
+{
+  close(fd);
+}
+
+/*
+ * createTap
+ * 
+ * This function creates a tap device, sets a mac address
+ * and the broadcast address and activates the device
+ * 
+ * @param pointer to device name
+ * @param pointer to mac address
+ * @return file descriptor of tap device, -1 if an error
+ * happened
+ */
+int
+createTap (char *name, MacAddress *mac)
+{
+  static const char deviceName[] = "/dev/net/tun";
+  int etfd;
+  struct ifreq ifreq;
+	
+  int ioctlSkfd;
+  int ioctlres;
+	
+  etfd = open(deviceName, O_RDWR);
+  if (etfd < 0) {
+    printf("Cannot open tap device!\n");
+    return -1;
+  }
+	
+  memset(&ifreq, 0, sizeof(ifreq));
+  strncpy(ifreq.ifr_name, name, IFNAMSIZ - 1);
+  ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+	
+	
+  /*
+   * Specify the IFF_TAP flag for Ethernet packets.
+   * Specify IFF_NO_PI for not receiving extra meta packet information.
+   */
+  ifreq.ifr_flags = IFF_TAP;
+  ifreq.ifr_flags |= IFF_NO_PI;
+	
+  if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0) {
+    close(etfd);
+    printf("Cannot set tun device type!\n");
+    return -1;
+  }
+	
+  memset(&ifreq, 0, sizeof(ifreq));
+  strncpy(ifreq.ifr_name, name, IFNAMSIZ - 1);
+  ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+  ifreq.ifr_addr.sa_family = AF_INET;
+	
+  ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (ioctlSkfd < 0) {
+    close(etfd);
+    printf("Cannot open configuration socket!\n");
+    return -1;
+  }
+	
+  /* Set hardware address */
+  ifreq.ifr_addr.sa_family = ARPHRD_ETHER;
+  memcpy(ifreq.ifr_addr.sa_data, mac, 6);
+  ioctlres = ioctl(ioctlSkfd, SIOCSIFHWADDR, &ifreq);
+  if (ioctlres >= 0) {
+    /* Set hardware broadcast */
+    memcpy(ifreq.ifr_addr.sa_data, macBroadcast, 6);
+    ioctlres = ioctl(ioctlSkfd, SIOCSIFHWBROADCAST, &ifreq);
+    if (ioctlres >= 0) {
+      /* Bring EtherTunTap interface up (if not already) */
+      ifreq.ifr_addr.sa_family = AF_INET;
+      ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
+      if (ioctlres >= 0) {
+        ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
+        ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
+      }
+    }
+  }
+  if (ioctlres < 0) {
+    printf("Configuration of tun device failed! (%d %s)\n", errno, strerror(errno));
+    close(etfd);
+    close(ioctlSkfd);
+    return -1;
+  }
+	
+	
+  /* Set the multicast flag on the interface */
+  memset(&ifreq, 0, sizeof(ifreq));
+  strncpy(ifreq.ifr_name, name, IFNAMSIZ - 1);
+  ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+	
+  ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
+  if (ioctlres >= 0) {
+    ifreq.ifr_flags |= IFF_MULTICAST;
+    ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
+  }
+	
+  close(ioctlSkfd);
+  return etfd;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/netsimpcap/src/network_tap.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * NetsimPcap - a userspace network bridge with simulated packet loss
+ *             Copyright 2008 H. Rogge (rogge@fgan.de)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETWORK_H_
+#define NETWORK_H_
+
+#include <linux/types.h>
+
+typedef struct MacAddress {
+  char mac[6];
+} MacAddress;
+
+int readMac(char *value, MacAddress *target);
+void closeTap(int fd);
+int createTap(char *name, MacAddress *mac);
+
+#endif /*NETWORK_H_*/
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/README ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/README
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/contrib/README	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/contrib/README	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1 @@
+This folder contains contributed projects.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/features.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/features.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/features.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/features.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,37 @@
+Features supported by the different versions of olsrd.
+
+    X   supported
+    !   support planned
+    -   support not planned
+    ?   unsure
+
+                                   Linux  Windows  FreeBSD  OSX
+
+IPv6                                 X       !        !      !
+
+automatically enable IP              X       X        X      X 
+forwarding
+
+automatically disable ICMP           X       !        X      X 
+redirect messages
+
+automatically disable                X       ?        ?      ?
+anti-spoofing
+
+use 255.255.255.255 as broadcast     X       ?        X      !
+address on a single interface
+
+use 255.255.255.255 as broadcast     X       ?        X      !
+address on multiple interfaces
+
+use the same subnet broadcast        X       -        X      -
+address on multiple interfaces
+
+initially delete default routes      X       !        !      !
+
+recognize WLAN interfaces            X       X        X      !
+
+willingness based on                 X       X        ?      ?
+battery power
+
+TOS                                  X       -        -      -
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.8.gz and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.8.gz sind verschieden.
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.5.gz and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.5.gz sind verschieden.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.default.lq ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.default.lq
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.default.lq	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.default.lq	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,317 @@
+#
+# olsr.org OLSR daemon config file
+#
+# Lines starting with a # are discarded
+#
+# This file was shipped with olsrd 0.X.X
+#
+
+# This file is an example of a typical
+# configuration for a mostly static
+# network(regarding mobility) using
+# the LQ extention
+
+# Debug level(0-9)
+# If set to 0 the daemon runs in the background
+
+DebugLevel	2
+
+# IP version to use (4 or 6)
+
+IpVersion	4
+
+# FIBMetric ("flat", "correct", or "approx")
+
+FIBMetric "flat"
+
+# Clear the screen each time the internal state changes
+
+ClearScreen     yes
+
+# HNA IPv4 routes
+# syntax: netaddr netmask
+# Example Internet gateway:
+# 0.0.0.0 0.0.0.0
+
+Hna4
+{
+#   Internet gateway:
+#   0.0.0.0      0.0.0.0
+#   more entries can be added:
+#   192.168.1.0  255.255.255.0
+}
+
+# HNA IPv6 routes
+# syntax: netaddr prefix
+# Example Internet gateway:
+Hna6
+{
+#   Internet gateway:
+#   ::              0
+#   more entries can be added:
+#   fec0:2200:106:: 48
+}
+
+
+# Should olsrd keep on running even if there are
+# no interfaces available? This is a good idea
+# for a PCMCIA/USB hotswap environment.
+# "yes" OR "no"
+
+AllowNoInt	yes
+
+# TOS(type of service) value for
+# the IP header of control traffic.
+# If not set it will default to 16
+
+#TosValue	16
+
+# The fixed willingness to use(0-7)
+# If not set willingness will be calculated
+# dynamically based on battery/power status
+# if such information is available
+
+#Willingness    	4
+
+# Allow processes like the GUI front-end
+# to connect to the daemon.
+
+IpcConnect
+{
+     # Determines how many simultaneously
+     # IPC connections that will be allowed
+     # Setting this to 0 disables IPC
+
+     MaxConnections  0
+
+     # By default only 127.0.0.1 is allowed
+     # to connect. Here allowed hosts can
+     # be added
+
+     Host            127.0.0.1
+     #Host            10.0.0.5
+
+     # You can also specify entire net-ranges 
+     # that are allowed to connect. Multiple
+     # entries are allowed
+
+     #Net             192.168.1.0 255.255.255.0     
+}
+
+# Wether to use hysteresis or not
+# Hysteresis adds more robustness to the
+# link sensing but delays neighbor registration.
+# Used by default. 'yes' or 'no'
+
+UseHysteresis	no
+
+# Hysteresis parameters
+# Do not alter these unless you know 
+# what you are doing!
+# Set to auto by default. Allowed
+# values are floating point values
+# in the interval 0,1
+# THR_LOW must always be lower than
+# THR_HIGH.
+
+#HystScaling	0.50
+#HystThrHigh	0.80
+#HystThrLow	0.30
+
+
+# Link quality level
+# 0 = do not use link quality
+# 1 = use link quality for MPR selection
+# 2 = use link quality for MPR selection and routing
+# Defaults to 0
+
+LinkQualityLevel	2
+
+# Link quality aging factor
+# Defaults to 0.1, smaller values mean faster reaction to changing links
+
+#LinkQualityAging 0.1 
+
+# Link quality algorithm
+# Defaults to "etx_fpm" for fixpoint based etx algorithm
+
+#LinkQualityAlgorithm    "etx_fpm"
+
+# Polling rate in seconds(float). 
+# Default value 0.05 sec
+
+Pollrate	0.05
+
+# Interval to poll network interfaces for configuration 
+# changes. Defaults to 2.5 seconds
+
+NicChgsPollInt  3.0
+
+# TC redundancy
+# Specifies how much neighbor info should
+# be sent in TC messages
+# Possible values are:
+# 0 - only send MPR selectors
+# 1 - send MPR selectors and MPRs
+# 2 - send all neighbors
+#
+# defaults to 0
+
+TcRedundancy	2
+
+
+#
+# MPR coverage
+# Specifies how many MPRs a node should
+# try select to reach every 2 hop neighbor
+#
+# Can be set to any integer >0
+#
+# defaults to 1
+
+MprCoverage	3
+
+
+# Olsrd plugins to load
+# This must be the absolute path to the file
+# or the loader will use the following scheme:
+# - Try the paths in the LD_LIBRARY_PATH 
+#   environment variable.
+# - The list of libraries cached in /etc/ld.so.cache
+# - /lib, followed by /usr/lib
+
+# Example plugin entry with parameters:
+
+#LoadPlugin "olsrd_dyn_gw.so.0.3"
+#{
+    # Here parameters are set to be sent to the
+    # plugin. Theese are on the form "key" "value".
+    # Parameters ofcause, differs from plugin to plugin.
+    # Consult the documentation of your plugin for details.
+
+    # Example: dyn_gw params
+
+    # how often to check for Internet connectivity
+    # defaults to 5 secs
+#   PlParam     "Interval"   "40"
+    
+    # if one or more IPv4 addresses are given, do a ping on these in
+    # descending order to validate that there is not only an entry in
+    # routing table, but also a real internet connection. If any of
+    # these addresses could be pinged successfully, the test was
+    # succesful, i.e. if the ping on the 1st address was successful,the
+    # 2nd won't be pinged
+#   PlParam     "Ping"       "141.1.1.1"
+#   PlParam     "Ping"       "194.25.2.129"
+#}
+
+
+
+# Interfaces and their rules
+# Omitted options will be set to the
+# default values. Multiple interfaces
+# can be specified in the same block
+# and multiple blocks can be set.
+
+# !!CHANGE THE INTERFACE LABEL(s) TO MATCH YOUR INTERFACE(s)!!
+# (eg. wlan0 or eth1):
+
+Interface "XXX" "YYY"
+{
+    # Olsrd can autodetect changes in NIC
+    # configurations(IP address changes etc.). 
+    # This is Enabled by default and the interval
+    # to poll for changes on is defined by 
+    # NicChgsPollInt.
+    # This polling can be disabled pr. NIC by setting
+    # AutoDetectChanges to no.
+
+    # AutoDetectChanges            yes
+
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    # Ip4Broadcast		255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    # Ip6AddrType		site-local
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+
+    # Ip6MulticastSite		ff05::11
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+
+    # Ip6MulticastGlobal	ff0e::1
+
+
+    # Emission intervals.
+    # If not defined, RFC proposed values will
+    # be used in most cases.
+
+    # Hello interval in seconds(float)
+    HelloInterval    2.0
+
+    # HELLO validity time
+    HelloValidityTime	20.0
+
+    # TC interval in seconds(float)
+    TcInterval        5.0
+
+    # TC validity time
+    TcValidityTime	30.0
+
+    # MID interval in seconds(float)
+    MidInterval	5.0
+
+    # MID validity time
+    MidValidityTime	30.0
+
+    # HNA interval in seconds(float)
+    HnaInterval	5.0
+
+    # 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
+    # automatically calculated by olsrd based
+    # 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 -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.default.lq-fisheye ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.default.lq-fisheye
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.default.lq-fisheye	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.default.lq-fisheye	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,343 @@
+#
+# olsr.org OLSR daemon config file
+#
+# Lines starting with a # are discarded
+#
+# This file was shipped with olsrd 0.5.4
+#
+
+# This file is an example of a typical
+# configuration for a mostly static
+# network(regarding mobility) using
+# the LQ extention
+
+# Debug level(0-9)
+# If set to 0 the daemon runs in the background
+
+DebugLevel	0
+
+# IP version to use (4 or 6)
+
+IpVersion	4
+
+# FIBMetric ("flat", "correct", or "approx")
+
+FIBMetric "flat"
+
+# Interfaces and their rules
+# Omitted options will be set to the
+# default values. Multiple interfaces
+# can be specified in the same block
+# and multiple blocks can be set.
+
+# !!CHANGE THE INTERFACE LABEL(s) TO MATCH YOUR INTERFACE(s)!!
+# (eg. wlan0 or eth1):
+# 
+# this is (in most cases) the only configuration you need to change
+
+#Interface "eth1" "eth0" "wlan0" "wlan1" "ath0" "ath1"
+Interface "eth1"
+{
+
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    # Ip4Broadcast		255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    # Ip6AddrType		site-local
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+
+    # Ip6MulticastSite		ff05::11
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+
+    # Ip6MulticastGlobal	ff0e::1
+
+
+    # Emission intervals.
+    # If not defined, RFC proposed values will
+    # be used in most cases.
+
+    # Hello interval in seconds(float)
+    HelloInterval    6.0
+
+    # HELLO validity time
+    HelloValidityTime	600.0
+
+
+    # TC interval in seconds(float) 0.5 is only viable when
+    # LinkQualityFishEye is enabled. Otherwise larger networks would
+    # suffocate from a massive protocol overhead of TC-messages
+
+    TcInterval        0.5
+
+    # TC validity time
+    TcValidityTime	300.0
+
+    # MID interval in seconds(float)
+    MidInterval		10.0
+
+    # MID validity time
+    MidValidityTime	300.0
+
+    # HNA interval in seconds(float)
+    HnaInterval		10.0
+
+    # HNA validity time
+    HnaValidityTime 	300.0
+
+    # When multiple links exist between hosts
+    # the weight of interface is used to determine
+    # the link to use. Normally the weight is
+    # automatically calculated by olsrd based
+    # on the characteristics of the interface,
+    # but here you can specify a fixed value.
+    # Olsrd will choose links with the lowest value.
+
+    # 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.
+
+    # LinkQualityMult 192.168.0.1 0.5
+
+    # This multiplier applies to all other nodes 
+    # LinkQualityMult default 0.8
+}
+
+
+# Fisheye mechanism for TC messages 0=off, 1=on
+
+LinkQualityFishEye 1
+
+
+# ignore topology information from nodes further than 3 hops away
+#
+# update topology information every 3.0 seconds
+# (on slower embedded hardware with more than 100 nodes use something like 9 sec)
+# 
+LinkQualityDijkstraLimit 3 3.0
+
+# Clear the screen each time the internal state changes
+
+ClearScreen     yes
+
+# HNA IPv4 routes
+# syntax: netaddr netmask
+# Example Internet gateway:
+# 0.0.0.0 0.0.0.0
+
+Hna4
+{
+#   Internet gateway:
+#   0.0.0.0      0.0.0.0
+#   more entries can be added:
+#   192.168.1.0  255.255.255.0
+}
+
+# HNA IPv6 routes
+# syntax: netaddr prefix
+# Example Internet gateway:
+Hna6
+{
+#   Internet gateway:
+#   ::              0
+#   more entries can be added:
+#   fec0:2200:106:: 48
+}
+
+
+# Should olsrd keep on running even if there are
+# no interfaces available? This is a good idea
+# for a PCMCIA/USB hotswap environment.
+# "yes" OR "no"
+
+AllowNoInt	yes
+
+# TOS(type of service) value for
+# the IP header of control traffic.
+# If not set it will default to 16
+
+#TosValue	16
+
+# The fixed willingness to use(0-7)
+# If not set willingness will be calculated
+# dynamically based on battery/power status
+# if such information is available
+
+Willingness    	7
+
+# Allow processes like the GUI front-end
+# to connect to the daemon.
+
+IpcConnect
+{
+     # Determines how many simultaneously
+     # IPC connections that will be allowed
+     # Setting this to 0 disables IPC
+
+     MaxConnections  0
+
+     # By default only 127.0.0.1 is allowed
+     # to connect. Here allowed hosts can
+     # be added
+
+     Host            127.0.0.1
+     #Host            10.0.0.5
+
+     # You can also specify entire net-ranges 
+     # that are allowed to connect. Multiple
+     # entries are allowed
+
+     #Net             192.168.1.0 255.255.255.0     
+}
+
+# Wether to use hysteresis or not
+# Hysteresis adds more robustness to the
+# link sensing but delays neighbor registration.
+# Used by default. 'yes' or 'no'
+# Do not use hysteresis with ETX!
+
+UseHysteresis	no
+
+# Hysteresis parameters
+# Do not alter these unless you know 
+# what you are doing!
+# Set to auto by default. Allowed
+# values are floating point values
+# in the interval 0,1
+# THR_LOW must always be lower than
+# THR_HIGH.
+
+#HystScaling	0.50
+#HystThrHigh	0.80
+#HystThrLow	0.30
+
+
+# Link quality level
+# 0 = do not use link quality
+# 1 = use link quality for MPR selection
+# 2 = use link quality for MPR selection and routing
+# Defaults to 0
+
+LinkQualityLevel	2
+
+# Link quality aging factor
+# Defaults to 0.1, smaller values mean faster reaction to changing links
+
+#LinkQualityAging 0.1 
+
+# Link quality algorithm
+# Defaults to "etx_fpm" for fixpoint based etx algorithm
+
+#LinkQualityAlgorithm    "etx_fpm"
+
+# Polling rate in seconds(float). 
+# Default value 0.05 sec
+
+Pollrate	0.1
+
+
+# TC redundancy
+# Specifies how much neighbor info should
+# be sent in TC messages
+# Possible values are:
+# 0 - only send MPR selectors
+# 1 - send MPR selectors and MPRs
+# 2 - send all neighbors
+#
+# defaults to 0
+
+TcRedundancy	2
+
+
+#
+# MPR coverage
+# Specifies how many MPRs a node should
+# try select to reach every 2 hop neighbor
+#
+# Can be set to any integer >0
+#
+# defaults to 1
+
+MprCoverage	5
+
+
+# Olsrd plugins to load
+# This must be the absolute path to the file
+# or the loader will use the following scheme:
+# - Try the paths in the LD_LIBRARY_PATH 
+#   environment variable.
+# - The list of libraries cached in /etc/ld.so.cache
+# - /lib, followed by /usr/lib
+
+# Configuration examples for plugins:
+# see /usr/share/doc/olsrd-plugins/ for some for documentation
+
+#LoadPlugin "olsrd_httpinfo.so.0.1"
+#{
+#	# defaults to 1978
+#	PlParam     "Port"   "8080"
+#	# if you dont set these, the default is to listen only on the loopback device
+#	#PlParam "Host"   "80.23.53.22"
+#	#PlParam "Net"    "10.0.0.0 255.0.0.0"
+#	#PlParam "Net" "0.0.0.0 0.0.0.0"
+#}
+
+# useful if your machine has an uplink
+#LoadPlugin "olsrd_dyn_gw.so.0.4"
+#{
+    # Here parameters are set to be sent to the
+    # plugin. Theese are on the form "key" "value".
+    # Parameters ofcause, differs from plugin to plugin.
+    # Consult the documentation of your plugin for details.
+
+    # Example: dyn_gw params
+
+    # how often to check for Internet connectivity
+    # defaults to 5 secs
+#   PlParam     "Interval"   "40"
+    
+    # if one or more IPv4 addresses are given, do a ping on these in
+    # descending order to validate that there is not only an entry in
+    # routing table, but also a real internet connection. If any of
+    # these addresses could be pinged successfully, the test was
+    # succesful, i.e. if the ping on the 1st address was successful,the
+    # 2nd won't be pinged
+#   PlParam     "Ping"       "141.1.1.1"
+#   PlParam     "Ping"       "194.25.2.129"
+#}
+
+#LoadPlugin "olsrd_nameservice.so.0.2"
+#{
+        #PlParam "name" "xxx"
+        #PlParam "a.b.c.d" "xxx-eth"
+        #PlParam "a.b.c.e" "xxx-bbb"
+        #PlParam "a.b.c.f" "xxx-olsr"
+        #PlParam "suffix" ".olsr"
+#}
+
+#LoadPlugin "olsrd_dot_draw.so.0.3"
+#{
+        # accept connection from IP:
+        # default 127.0.0.1 (localhost)	
+        #PlParam     "accept" "192.168.0.5"
+        #PlParam     "port" "2004"
+#}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.default.rfc ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.default.rfc
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.default.rfc	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.default.rfc	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,306 @@
+#
+# olsr.org OLSR daemon config file
+#
+# Lines starting with a # are discarded
+#
+# This file was shipped with olsrd 0.X.X
+#
+
+# Debug level(0-9)
+# If set to 0 the daemon runs in the background
+
+DebugLevel	1
+
+# IP version to use (4 or 6)
+
+IpVersion	4
+
+# FIBMetric ("flat", "correct", or "approx")
+
+FIBMetric "flat"
+
+# Clear the screen each time the internal state changes
+
+ClearScreen     yes
+
+# HNA IPv4 routes
+# syntax: netaddr netmask
+# Example Internet gateway:
+# 0.0.0.0 0.0.0.0
+
+Hna4
+{
+#   Internet gateway:
+#   0.0.0.0      0.0.0.0
+#   more entries can be added:
+#   192.168.1.0  255.255.255.0
+}
+
+# HNA IPv6 routes
+# syntax: netaddr prefix
+# Example Internet gateway:
+Hna6
+{
+#   Internet gateway:
+#   ::              0
+#   more entries can be added:
+#   fec0:2200:106:: 48
+}
+
+
+# Should olsrd keep on running even if there are
+# no interfaces available? This is a good idea
+# for a PCMCIA/USB hotswap environment.
+# "yes" OR "no"
+
+AllowNoInt	yes
+
+# TOS(type of service) value for
+# the IP header of control traffic.
+# If not set it will default to 16
+
+#TosValue	16
+
+# The fixed willingness to use(0-7)
+# If not set willingness will be calculated
+# dynamically based on battery/power status
+# if such information is available
+
+#Willingness    	4
+
+# Allow processes like the GUI front-end
+# to connect to the daemon.
+
+IpcConnect
+{
+     # Determines how many simultaneously
+     # IPC connections that will be allowed
+     # Setting this to 0 disables IPC
+
+     MaxConnections  0
+
+     # By default only 127.0.0.1 is allowed
+     # to connect. Here allowed hosts can
+     # be added
+
+     Host            127.0.0.1
+     #Host            10.0.0.5
+
+     # You can also specify entire net-ranges 
+     # that are allowed to connect. Multiple
+     # entries are allowed
+
+     #Net             192.168.1.0 255.255.255.0     
+}
+
+# Whether to use hysteresis or not
+# Hysteresis adds more robustness to the
+# link sensing but delays neighbor registration.
+# Used by default. 'yes' or 'no'
+
+UseHysteresis	yes
+
+# Hysteresis parameters
+# Do not alter these unless you know 
+# what you are doing!
+# Set to auto by default. Allowed
+# values are floating point values
+# in the interval 0,1
+# THR_LOW must always be lower than
+# THR_HIGH.
+
+HystScaling	0.50
+HystThrHigh	0.80
+HystThrLow	0.30
+
+
+# Link quality level
+# 0 = do not use link quality
+# 1 = use link quality for MPR selection
+# 2 = use link quality for MPR selection and routing
+# Defaults to 0
+
+#LinkQualityLevel	0
+
+# Link quality aging factor
+# Defaults to 0.05, smaller values mean larger LQ window size
+# LinkQualityAging 0.1 
+
+# Polling rate in seconds(float). 
+# Default value 0.05 sec
+
+Pollrate	0.05
+
+# Interval to poll network interfaces for configuration 
+# changes. Defaults to 2.5 seconds
+
+NicChgsPollInt  3.0
+
+# TC redundancy
+# Specifies how much neighbor info should
+# be sent in TC messages
+# Possible values are:
+# 0 - only send MPR selectors
+# 1 - send MPR selectors and MPRs
+# 2 - send all neighbors
+#
+# defaults to 0
+
+#TcRedundancy	0
+
+
+#
+# MPR coverage
+# Specifies how many MPRs a node should
+# try select to reach every 2 hop neighbor
+#
+# Can be set to any integer >0
+#
+# defaults to 1
+
+#MprCoverage	1
+
+
+# Olsrd plugins to load
+# This must be the absolute path to the file
+# or the loader will use the following scheme:
+# - Try the paths in the LD_LIBRARY_PATH 
+#   environment variable.
+# - The list of libraries cached in /etc/ld.so.cache
+# - /lib, followed by /usr/lib
+
+# Example plugin entry with parameters:
+
+#LoadPlugin "olsrd_dyn_gw.so.0.3"
+#{
+    # Here parameters are set to be sent to the
+    # plugin. Theese are on the form "key" "value".
+    # Parameters ofcause, differs from plugin to plugin.
+    # Consult the documentation of your plugin for details.
+
+    # Example: dyn_gw params
+
+    # how often to check for Internet connectivity
+    # defaults to 5 secs
+#   PlParam     "Interval"   "40"
+    
+    # if one or more IPv4 addresses are given, do a ping on these in
+    # descending order to validate that there is not only an entry in
+    # routing table, but also a real internet connection. If any of
+    # these addresses could be pinged successfully, the test was
+    # succesful, i.e. if the ping on the 1st address was successful,the
+    # 2nd won't be pinged
+#   PlParam     "Ping"       "141.1.1.1"
+#   PlParam     "Ping"       "194.25.2.129"
+#}
+
+
+
+# Interfaces and their rules
+# Omitted options will be set to the
+# default values. Multiple interfaces
+# can be specified in the same block
+# and multiple blocks can be set.
+
+# !!CHANGE THE INTERFACE LABEL(s) TO MATCH YOUR INTERFACE(s)!!
+# (eg. wlan0 or eth1):
+
+Interface "XXX" "YYY"
+{
+    # Olsrd can autodetect changes in NIC
+    # configurations(IP address changes etc.). 
+    # This is Enabled by default and the interval
+    # to poll for changes on is defined by 
+    # NicChgsPollInt.
+    # This polling can be disabled pr. NIC by setting
+    # AutoDetectChanges to no.
+
+    # AutoDetectChanges            yes
+
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    # Ip4Broadcast		255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    # Ip6AddrType		site-local
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+
+    # Ip6MulticastSite		ff05::11
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+
+    # Ip6MulticastGlobal	ff0e::1
+
+
+    # Emission intervals.
+    # If not defined, RFC proposed values will
+    # be used in most cases.
+
+    # Hello interval in seconds(float)
+    # HelloInterval    2.0
+
+    # HELLO validity time
+    # HelloValidityTime	6.0
+
+    # TC interval in seconds(float)
+    # TcInterval        5.0
+
+    # TC validity time
+    # TcValidityTime	15.0
+
+    # MID interval in seconds(float)
+    # MidInterval	5.0
+
+    # MID validity time
+    # MidValidityTime	15.0
+
+    # HNA interval in seconds(float)
+    # HnaInterval	5.0
+
+    # 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
+    # automatically calculated by olsrd based
+    # 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 -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.win32.lq ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.win32.lq
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.win32.lq	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.win32.lq	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,158 @@
+#
+# olsr.org configuration file
+#
+# This configuration file should be copied to the Windows
+# directory. It is then used when you run olsrd.exe directly, i.e.
+# without the GUI. If you use the GUI, then you do not need this
+# file. In this case look at Default.olsr instead.
+#
+#
+
+#
+# Periodically print the internal state, including information on
+# route calculation
+#
+
+DebugLevel		2
+
+#
+# Don't clear the screen each time the internal state changes
+#
+
+ClearScreen		no
+
+#
+# Enable the link quality extensions?
+#
+# 0 - no
+# 1 - yes, use link quality for MPR selection
+# 2 - yes, use link quality for MPR selection and routing
+#
+
+LinkQualityLevel	2
+
+# Link quality aging factor
+# Defaults to 0.05, smaller values mean larger LQ window size
+LinkQualityAging 0.1 
+
+#
+# Do not use hysteresis
+#
+
+UseHysteresis		no
+
+#
+# If using hysteresis, use "smooth" parameters
+#
+
+HystScaling		0.1
+HystThrHigh		0.8
+HystThrLow		0.3
+
+#
+# The pollrate used by the scheduler
+#
+
+Pollrate		0.1
+
+# Interval to poll network interfaces for configuration 
+# changes. Defaults to 2.5 seconds
+
+NicChgsPollInt  3.0
+
+#
+# Which neighbours should be advertised via TC messages?
+#
+# 0 - only advertise our MPR selectors
+# 1 - advertise our MPR selectors and our MPRs
+# 2 - advertise all neighbors
+#
+
+TcRedundancy		2
+
+#
+# Specifies by how many MPRs each two-hop neighbour should be covered
+#
+
+MprCoverage		3
+
+#
+# Load the dot draw plugin
+#
+
+#LoadPlugin		"olsrd_dot_draw.dll"
+#{
+#}
+
+#
+# Load the name service plugin
+#
+
+#LoadPlugin		"olsrd_nameservice.dll"
+#{
+#	PlParam	"name"	"thomas"
+#}
+
+#
+# Load the HTTP info plugin
+#
+
+LoadPlugin		"olsrd_httpinfo.dll"
+{
+	PlParam	"Net"	"0.0.0.0 0.0.0.0"
+}
+
+#
+# IPv4 HNAs - syntax: netaddr netmask
+#
+
+Hna4
+{
+#	0.0.0.0 0.0.0.0
+}
+
+#
+# Interfaces - use "olsrd.exe -int" to obtain a list of you interfaces
+# and then change "if99" to the name of your WLAN interface
+#
+
+Interface "if99"
+{
+        # Olsrd can autodetect changes in NIC
+        # configurations(IP address changes etc.). 
+        # This is Enabled by default and the interval
+        # to poll for changes on is defined by 
+        # NicChgsPollInt.
+        # This polling can be disabled pr. NIC by setting
+        # AutoDetectChanges to no.
+
+        # AutoDetectChanges            yes
+
+	#
+	# HELLO interval and validity time in seconds (float)
+	#
+
+	HelloInterval		2.0
+	HelloValidityTime	20.0
+
+	#
+	# TC interval and validity time in seconds (float)
+	#
+
+	TcInterval		5.0
+	TcValidityTime		30.0
+
+	#
+	# MID interval and validity time in seconds (float)
+	#
+
+	MidInterval		5.0
+	MidValidityTime		30.0
+
+	#
+	# HNA interval and validity time in seconds (float)
+	#
+
+	HnaInterval		5.0
+	HnaValidityTime 	30.0
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.win32.rfc ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.win32.rfc
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsrd.conf.win32.rfc	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsrd.conf.win32.rfc	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,158 @@
+#
+# olsr.org configuration file
+#
+# This configuration file should be copied to the Windows
+# directory. It is then used when you run olsrd.exe directly, i.e.
+# without the GUI. If you use the GUI, then you do not need this
+# file. In this case look at Default.olsr instead.
+#
+#
+
+#
+# Periodically print the internal state, including information on
+# route calculation
+#
+
+DebugLevel		2
+
+#
+# Don't clear the screen each time the internal state changes
+#
+
+ClearScreen		no
+
+#
+# Enable the link quality extensions?
+#
+# 0 - no
+# 1 - yes, use link quality for MPR selection
+# 2 - yes, use link quality for MPR selection and routing
+#
+
+LinkQualityLevel	0
+
+# Link quality aging factor
+# Defaults to 0.05, smaller values mean larger LQ window size
+LinkQualityAging 0.1 
+
+#
+# Do not use hysteresis
+#
+
+UseHysteresis		no
+
+#
+# If using hysteresis, use the RFC parameters
+#
+
+HystScaling		0.5
+HystThrHigh		0.8
+HystThrLow		0.3
+
+#
+# The pollrate used by the scheduler
+#
+
+Pollrate		0.1
+
+# Interval to poll network interfaces for configuration 
+# changes. Defaults to 2.5 seconds
+
+NicChgsPollInt  3.0
+
+#
+# Which neighbours should be advertised via TC messages?
+#
+# 0 - only advertise our MPR selectors
+# 1 - advertise our MPR selectors and our MPRs
+# 2 - advertise all neighbors
+#
+
+TcRedundancy		0
+
+#
+# Specifies by how many MPRs each two-hop neighbour should be covered
+#
+
+MprCoverage		1
+
+#
+# Load the dot draw plugin
+#
+
+#LoadPlugin		"olsrd_dot_draw.dll"
+#{
+#}
+
+#
+# Load the name service plugin
+#
+
+#LoadPlugin		"olsrd_nameservice.dll"
+#{
+#	PlParam	"name"	"thomas"
+#}
+
+#
+# Load the HTTP info plugin
+#
+
+LoadPlugin		"olsrd_httpinfo.dll"
+{
+	PlParam	"Net"	"0.0.0.0 0.0.0.0"
+}
+
+#
+# IPv4 HNAs - syntax: netaddr netmask
+#
+
+Hna4
+{
+#	0.0.0.0 0.0.0.0
+}
+
+#
+# Interfaces - use "olsrd.exe -int" to obtain a list of you interfaces
+# and then change "if99" to the name of your WLAN interface
+#
+
+Interface "if99"
+{
+        # Olsrd can autodetect changes in NIC
+        # configurations(IP address changes etc.). 
+        # This is Enabled by default and the interval
+        # to poll for changes on is defined by 
+        # NicChgsPollInt.
+        # This polling can be disabled pr. NIC by setting
+        # AutoDetectChanges to no.
+
+        # AutoDetectChanges            yes
+
+	#
+	# HELLO interval and validity time in seconds (float)
+	#
+
+	HelloInterval		2.0
+	HelloValidityTime	6.0
+
+	#
+	# TC interval and validity time in seconds (float)
+	#
+
+	TcInterval		5.0
+	TcValidityTime		15.0
+
+	#
+	# MID interval and validity time in seconds (float)
+	#
+
+	MidInterval		5.0
+	MidValidityTime		15.0
+
+	#
+	# HNA interval and validity time in seconds (float)
+	#
+
+	HnaInterval		5.0
+	HnaValidityTime 	15.0
+}
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/files/olsr_switch.8.gz and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/files/olsr_switch.8.gz sind verschieden.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gcc-warnings ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gcc-warnings
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gcc-warnings	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gcc-warnings	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# We expect warning options for gcc as arguments and return the ones which are
+# accepted by the given gcc.
+#
+
+set -ue
+#set -vx
+
+# make sure we do not use some locale ....
+export LANG=C LC_ALL=C LC_COLLATE=C LC_CTYPE=C LC_MESSAGES=C LC_NUMERIC=C
+
+OPTS=""
+for param; do
+    case "$param" in
+    -[fWm]?*) OPTS="$OPTS $param";;
+    *)        echo "Ignoring $param" >&2
+    esac
+done
+
+testcompile() {
+    $CC $OPTS -x c -o /dev/null - 2>&1 <<- EOF
+       int main(void) {
+           return 0;
+       }
+EOF
+}
+
+parsetest() {
+    while read error; do 
+        case "$error" in
+        *:\ unrecognized\ *option\ \"*)
+            opt="${error#*\"}"
+            opt="${opt%\"*}"
+            ;;
+        *:\ unrecognized\ *option\ \`*)
+            opt="${error#*\`}"
+            opt="${opt%\'*}"
+            ;;
+        *) continue
+            ;;
+       esac
+       # if we come here, we have in $opt the option to remove. and
+       # we remove all instances. And we save agoinst leading "-"
+       NEW_OPTS=""
+       for o in $OPTS; do
+           case "$o" in
+               $opt) : echo "Removed $o" >&2;;
+               *)    NEW_OPTS="$NEW_OPTS $o";;
+           esac
+       done
+       OPTS="$NEW_OPTS"
+    done
+    echo $OPTS
+}
+
+testcompile | parsetest
+
+exit 0
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/CHANGELOG ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/CHANGELOG
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/CHANGELOG	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/CHANGELOG	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,39 @@
+CHANGELOG AS OF 0.2.2
+
+0.2.6 -------------------------------------------------
+
+Minor updates
+
+UPDATES
+Some simple code rewrites and bugfixes.
+Route deletion using IPv6 should work now.
+
+
+0.2.5 -------------------------------------------------
+
+Lots of updates.
+
+REWRITES
+
+Rewritten queuing structure.
+Route information is removed from main tab.
+
+PIGGYBACKING
+
+The front-end now supports piggybacked messages.
+
+
+0.2.2 -------------------------------------------------
+
+HELLO PARSING ERROR
+
+The parsing of HELLO messages didnt handle grous of neighbors
+bigger than 1 if there existed more than one group. This because
+the implementation did not check for several IP addresses but
+just incremented the struct-array index. A kindof ugly hack fixed
+this.
+
+MESSAGE RECIEVING
+
+Recieving of messages not complete - fixed. One could risk just recieving
+half a message the way it used to be implemented.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,19 @@
+CC ?=	gcc
+
+CFLAGS += -Wall `pkg-config --cflags gtk+-2.0`
+LFLAGS= `pkg-config --libs gtk+-2.0`
+
+OBJS=	src/main.o src/interface.o src/callbacks.o src/ipc.o \
+	src/packet.o src/nodes.o src/routes.o
+
+all:	olsrd-gui
+
+olsrd-gui:	$(OBJS)
+	$(CC) $(LFLAGS) -o $@ $(OBJS)
+
+clean:
+	rm -f $(OBJS)
+
+install:
+	mkdir -p ${DESTDIR}/usr/bin
+	cp ./olsrd-gui ${DESTDIR}/usr/bin/
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,275 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "common.h"
+#include "interface.h"
+
+
+
+
+void selection_made( GtkWidget      *clist,
+                     gint            row,
+                     gint            column,
+		     GdkEventButton *event,
+                     gpointer        data )
+{
+    gchar *ip, *hops, *gw, *dev;
+    const gchar text[100];
+    /* Get the text that is stored in the selected row and column
+     * which was clicked in. We will receive it as a pointer in the
+     * argument text.
+     */
+    gtk_clist_get_text(GTK_CLIST(clist), row, 0, &ip);
+    gtk_clist_get_text(GTK_CLIST(clist), row, 1, &gw);
+    gtk_clist_get_text(GTK_CLIST(clist), row, 2, &hops);
+    gtk_clist_get_text(GTK_CLIST(clist), row, 3, &dev);
+
+    /* Just prints some information about the selected row */
+    sprintf((char *)&text[0], "IP:%s\nGATEWAY:%s\nHOPCOUNT:%s\nINTERFACE:%s\n",
+	    ip, gw, hops, dev);
+
+    //gtk_text_buffer_set_text (textBuffer, text, -1);
+
+    //gtk_text_view_set_buffer((GtkTextView *)text1, textBuffer);
+
+    //gtk_widget_show (text1);
+
+
+    return;
+}
+
+
+
+
+
+
+
+void
+node_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data)
+{
+
+  gchar *text;
+  struct node *host;
+  struct mid *mids;
+  struct mpr *mprs;
+  struct hna *hnas;
+  int i;
+  gchar *tmpshit[1] = {""};
+
+  /*
+   *Clear the lists
+   */
+  gtk_clist_clear(GTK_CLIST(mid_list));
+  gtk_clist_clear(GTK_CLIST(mpr_list));
+  gtk_clist_clear(GTK_CLIST(hna_list));
+  i = 0;
+
+  /*
+   *Get th IP address
+   */
+  gtk_clist_get_text(GTK_CLIST(node_list), row, 0, &text);
+
+  /* Get the node */
+  if(strncmp(text, "local", sizeof("local")) == 0)
+    host = find_node_t(&main_addr);
+  else
+    host = find_node(text);
+
+
+
+  if(host)
+    {
+      /* Timeout the registered MPRs for this node */
+      time_out_mprs(&host->addr);
+
+      /* Get mpr pointer AFTER timeout....(another waisted hour...) */ 
+      mprs = host->mpr.next;
+      mids = host->mid.next;
+      hnas = host->hna.next;
+
+      while (mids != &host->mid)
+	{
+	  gtk_clist_append(GTK_CLIST(mid_list), tmpshit);
+	  gtk_clist_set_text(GTK_CLIST(mid_list), i, 0, ip_to_string(&mids->alias));
+	  i++;
+	  mids = mids->next;
+	}
+
+      i = 0;
+
+
+      while (mprs != &host->mpr)
+	{
+	  //printf("ADDING MPR : %s\n", ip_to_string(&mprs->addr));fflush(stdout);
+	  gtk_clist_append(GTK_CLIST(mpr_list), tmpshit);
+	  gtk_clist_set_text(GTK_CLIST(mpr_list), i, 0, ip_to_string(&mprs->addr));
+	  i++;
+	  mprs = mprs->next;
+	}
+      i = 0;
+
+      while (hnas != &host->hna)
+	{
+	  gtk_clist_append(GTK_CLIST(hna_list), tmpshit);
+	  gtk_clist_set_text(GTK_CLIST(hna_list), i, 0, ip_to_string(&hnas->net));
+	  i++;
+	  hnas = hnas->next;
+	}
+
+    }
+  else
+    {
+      printf("Could not find info about %s!\n", text);
+    }
+
+
+}
+
+
+
+
+void
+packet_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data)
+{
+  /* Fetch the packet from the cache */
+  union olsr_message *pack;
+  char *packet;
+  int y, x;
+  short size;
+  char *content[4];
+  int mem_size = 10;
+
+  content[0] = (char *)malloc(mem_size);
+  content[1] = (char *)malloc(mem_size);
+  content[2] = (char *)malloc(mem_size);
+  content[3] = (char *)malloc(mem_size);
+
+
+  pack = get_packet(row);
+  packet = (char *)pack;
+
+  //printf("Got the packet at row %d...\n", row);
+
+  gtk_clist_clear(GTK_CLIST(packet_content_list));
+
+  size = ntohs(pack->v4.olsr_msgsize);
+  
+  for(y = 0; y < size;y += 4)
+    {
+
+      for(x = 0; x < 4; x++)
+	{
+	  if(display_dec)
+	    sprintf(content[x], "%03i", (u_char) packet[y+x]); /* Decimal format */
+	  else
+	    sprintf(content[x], "%02x", (u_char) packet[y+x]); /* Hex format */	    
+	}
+
+      gtk_clist_append(GTK_CLIST(packet_content_list), content);
+    }
+
+  free(content[0]);
+  free(content[1]);
+  free(content[2]);
+  free(content[3]);
+
+}
+
+
+
+
+void
+column_clicked_callback(GtkWidget *list,gint column)
+{
+
+  //printf("You pressed %d\n",column);
+
+}
+
+
+/*
+ *Connect button callback
+ */
+void 
+connect_callback( GtkWidget *widget,
+		  gpointer   data )
+{
+  ipc_connect();
+}
+
+
+
+/*
+ *Packet button callback
+ */
+void 
+packet_callback( GtkWidget *widget,
+		  gpointer   data )
+{
+  if(freeze_packets)
+    {
+      freeze_packets = 0;
+      gtk_button_set_label(GTK_BUTTON(packet_button), "Freeze packets");
+    }
+  else
+    {
+      freeze_packets = 1;
+      gtk_button_set_label(GTK_BUTTON(packet_button), "Grab packets");
+    }
+}
+
+
+
+/*
+ *Packet display button callback
+ */
+void 
+packet_disp_callback( GtkWidget *widget,
+		  gpointer   data )
+{
+  if(display_dec)
+    {
+      display_dec = 0;
+      gtk_button_set_label(GTK_BUTTON(packet_disp_button), "Display decimal");
+    }
+  else
+    {
+      display_dec = 1;
+      gtk_button_set_label(GTK_BUTTON(packet_disp_button), "Display hex");
+    }
+}
+
+
+
+void
+gui_shutdown(GtkObject *object, gpointer user_data)
+{
+  printf("Shutting down...\n");
+
+  if(ipc_close() < 0)
+    printf("Could not close socket!\n");
+
+  printf("BYE-BYE!\n");
+  exit(0);
+
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/callbacks.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1 @@
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/common.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/common.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/common.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/common.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,229 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ *Andreas TÃ¸nmnesen
+ */
+
+#ifndef _OLSRD_FORNTEND_COMMON
+#define _OLSRD_FORNTEND_COMMON
+
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+
+//#include "interface.h"
+#include "callbacks.h"
+//#include "types.h"
+#include "olsr_protocol.h"
+
+#define olsrd_version "olsr.org GUI 0.2.7" 
+#define IPC_INTERVAL 500 //interval for IPC read timeout
+#define MAXPACKS 20
+#define BUFFSIZE 512
+
+
+extern int connected;
+extern struct timeval hold_time_nodes; /* Timeout for all nodes */
+extern struct timeval now;
+
+
+/* Our address */
+union olsr_ip_addr main_addr;
+union olsr_ip_addr null_addr;
+
+int ipversion;
+int ipsize;
+char ipv6_buf[100];      /* buffer for IPv6 inet_htop */
+
+int nodes_timeout;
+
+int freeze_packets;
+int display_dec;
+extern int timeouts;
+
+/*
+ *Node info
+ */
+
+
+struct mid
+{
+  union olsr_ip_addr alias;
+  struct mid *next;
+  struct mid *prev;
+};
+
+struct hna
+{
+  union olsr_ip_addr net;
+  union olsr_ip_addr mask;
+  struct hna *next;
+  struct hna *prev;
+};
+
+struct mpr
+{
+  union olsr_ip_addr addr;
+  struct timeval timer;
+  struct mpr *next;
+  struct mpr *prev;
+};
+
+
+struct node
+{
+  union olsr_ip_addr addr;
+  union olsr_ip_addr gw_addr;
+  int hopcount;
+  int display;
+  char dev[5];
+  struct mid mid;
+  struct hna hna;
+  struct mpr mpr;
+  struct timeval timer;
+  struct node *next;
+  struct node *prev;
+};
+
+
+
+
+
+
+/*
+ *Interface public
+ */
+
+
+GtkWidget * 
+create_main_window (void);
+
+
+void
+packet_list_add(char *, char *, char *);
+
+void
+route_list_add(char *, char *, char *, char *);
+
+int
+route_list_del(char *);
+
+void
+route_list_update(char *);
+
+
+void
+set_net_info(gchar *, int);
+
+void
+set_net_info_offline();
+
+void
+update_nodes_list(struct node *);
+
+int
+remove_nodes_list(union olsr_ip_addr *);
+
+/*
+ *IPC public
+ */
+int
+ipc_connect();
+
+int
+ipc_close();
+
+int
+ipc_read();
+
+int
+ipc_send();
+
+
+char *
+ip_to_string(union olsr_ip_addr *);
+
+int
+gui_itoa(int, char *);
+
+
+/*
+ *Packet.c public
+ */
+
+int
+add_packet_to_buffer(union olsr_message *, int);
+
+
+union olsr_message *
+get_packet(int);
+
+
+
+/*
+ *Nodes.c public
+ */
+
+
+
+void
+init_nodes();
+
+struct node *
+find_node(char *);
+
+struct node *
+find_node_t(union olsr_ip_addr *);
+
+int
+update_timer_node(union olsr_ip_addr *, olsr_u8_t);
+
+int
+add_hna_node(union olsr_ip_addr *, union olsr_ip_addr *, union olsr_ip_addr *, olsr_u8_t);
+
+int
+add_mid_node(union olsr_ip_addr *, union olsr_ip_addr *, olsr_u8_t);
+
+void
+init_timer(olsr_u32_t, struct timeval *);
+
+gint
+time_out_nodes(gpointer);
+
+int
+add_node(union olsr_ip_addr *, olsr_u8_t);
+
+int
+add_mpr(union olsr_ip_addr *, union olsr_ip_addr *, struct timeval *);
+
+int
+update_timer_mpr(union olsr_ip_addr *, union olsr_ip_addr *, olsr_u8_t);
+
+int
+time_out_mprs(union olsr_ip_addr *);
+
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/interface.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/interface.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/interface.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/interface.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,1284 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#include "common.h"
+#include "interface.h"
+#include "pixmaps.h"
+
+/* Global widgets */
+/* GtkWidget *text1; */
+
+GdkBitmap *mask;
+
+int packet_list_size = 0;
+int route_list_size = 0;
+int node_list_size = 0;
+
+GtkWidget *main_window;
+
+GtkWidget*
+create_main_window (void)
+{
+  GtkWidget *notebook1;
+  GtkWidget *frame3;
+  GtkWidget *frame4;
+  GtkWidget *hbox1;
+  GtkWidget *vbox1;
+  GtkWidget *scrolledwindow1;
+  GtkWidget *node_label1;
+  GtkWidget *node_label2;
+  GtkWidget *node_label3;
+  GtkWidget *node_label4;
+  GtkWidget *node_label7;
+  GtkWidget *node_label8;
+  GtkWidget *node_label9;
+  GtkWidget *mid_frame;
+  GtkWidget *mpr_frame;
+  GtkWidget *hna_frame;
+  GtkWidget *mid_scrolledwindow;
+  GtkWidget *mpr_scrolledwindow;
+  GtkWidget *hna_scrolledwindow;
+  GtkWidget *Main;
+  GtkWidget *label_routes;
+  GtkWidget *hbox2;
+  GtkWidget *frame2;
+  GtkWidget *scrolledwindow4;
+  GtkWidget *label17;
+  GtkWidget *label18;
+  GtkWidget *label19;
+  GtkWidget *scrolledwindow3;
+  GtkWidget *label13;
+  GtkWidget *label14;
+  GtkWidget *label15;
+  GtkWidget *label16;
+  GtkWidget *label_packets;
+  //GtkWidget *empty_notebook_page2;
+  GtkWidget *label3;
+  GtkWidget *net_vbox;
+  GtkWidget *pack_vbox;
+  GtkWidget *pack_disp_vbox;
+  GtkWidget *disp_frame;
+  GtkWidget *route_frame;
+  GtkWidget *route_stats_frame;
+  GtkWidget *route_scrolledwindow;
+  GtkWidget *route_label1;
+  GtkWidget *route_label2;
+  GtkWidget *route_label3;
+  GtkWidget *route_label4;
+  GtkWidget *route_hbox1;
+
+  GtkWidget *traffic_label;
+
+  GtkWidget *settings_label;
+  GtkWidget *settings_hbox1;
+
+  GtkWidget *about_hbox1;
+  GtkWidget *about_label;
+
+  GtkWidget *empty1;
+
+  GdkPixmap *unik_logo_gdk;
+  GtkWidget *unik_logo;
+
+  /*
+   *The main window
+   */
+
+  main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_object_set_data (GTK_OBJECT (main_window), "main_window", main_window);
+  gtk_window_set_title (GTK_WINDOW (main_window), (olsrd_version));
+  gtk_window_set_default_size(GTK_WINDOW (main_window), 600, 550);
+  gtk_signal_connect(GTK_OBJECT(main_window),
+		     "destroy",
+		     GTK_SIGNAL_FUNC(gui_shutdown),
+		     //GTK_SIGNAL_FUNC(gtk_main_quit),
+		     NULL);
+  gtk_window_set_position(GTK_WINDOW(main_window), GTK_WIN_POS_CENTER); /* Position window in center */
+  gtk_window_set_policy(GTK_WINDOW(main_window), FALSE, TRUE, TRUE); /* No user-resizing */
+
+  /*
+   *Initialize the pixmaps
+   */
+  unik_logo_gdk = gdk_pixmap_colormap_create_from_xpm_d (NULL, gtk_widget_get_colormap(main_window), &mask, NULL, (gchar **)logo_xpm);
+
+  unik_logo = gtk_pixmap_new(unik_logo_gdk, mask);
+
+  /*
+   *The notebook
+   */
+
+  notebook1 = gtk_notebook_new ();
+  gtk_widget_ref (notebook1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "notebook1", notebook1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (notebook1);
+  gtk_container_add (GTK_CONTAINER (main_window), notebook1);
+
+
+
+  /*
+   *The first vbox
+   */
+  vbox1 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_ref (vbox1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "vbox1", vbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox1);
+  //gtk_box_pack_start (GTK_BOX (hbox1), vbox1, TRUE, TRUE, 1);
+  gtk_container_add (GTK_CONTAINER (notebook1), vbox1);
+
+
+
+
+  /*
+   *The nodes frame
+   */
+  frame3 = gtk_frame_new ("Registered nodes:");
+  gtk_widget_ref (frame3);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "frame3", frame3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame3);
+  gtk_box_pack_start (GTK_BOX (vbox1), frame3, TRUE, TRUE, 0);
+  gtk_widget_set_size_request(frame3, -1, 300);
+  gtk_container_set_border_width (GTK_CONTAINER (frame3), 1);
+
+
+
+
+  /*
+   *The scrolled window to contain the node list
+   */
+
+  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (scrolledwindow1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "scrolledwindow1", scrolledwindow1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (scrolledwindow1);
+  gtk_container_add (GTK_CONTAINER (frame3), scrolledwindow1);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+  //gtk_box_pack_start (GTK_BOX (frame3), scrolledwindow1, TRUE, TRUE, 0);
+  //gtk_widget_set_usize (scrolledwindow1, -2, 332);
+
+  /*
+   *The node list
+   */
+  
+  node_list = gtk_clist_new (7);
+  gtk_widget_ref (node_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "node_list", node_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_list);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow1), node_list);
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 0, 150); /* IP */
+  //gtk_clist_set_column_justification(GTK_CLIST(node_list), 0, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 1, 150); /* gateway */
+  //gtk_clist_set_column_justification(GTK_CLIST(node_list), 1, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 2, 50); /* hopcount */
+  gtk_clist_set_column_justification(GTK_CLIST(node_list), 2, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 3, 80); /* dev */
+  gtk_clist_set_column_justification(GTK_CLIST(node_list), 3, GTK_JUSTIFY_CENTER);
+
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 4, 70); /* timer */
+  gtk_clist_set_column_justification(GTK_CLIST(node_list), 4, GTK_JUSTIFY_CENTER);
+  //gtk_clist_set_column_width (GTK_CLIST (node_list), 7, 100); /* last about */
+  //gtk_clist_set_column_justification(GTK_CLIST(node_list), 7, GTK_JUSTIFY_CENTER);
+
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 5, 40); /* MID */
+  gtk_clist_set_column_justification(GTK_CLIST(node_list), 5, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (node_list), 6, 40); /* HNA */
+  gtk_clist_set_column_justification(GTK_CLIST(node_list), 6, GTK_JUSTIFY_CENTER);
+
+  gtk_clist_column_titles_show (GTK_CLIST (node_list));
+
+  /*
+   *Row selection callback
+   */
+  gtk_signal_connect(GTK_OBJECT(node_list), "select_row",
+		     GTK_SIGNAL_FUNC(selection_made),
+		     NULL);
+
+  /*
+   *Column selection callback
+   */
+  gtk_signal_connect(GTK_OBJECT(node_list),
+		     "click_column",
+		     GTK_SIGNAL_FUNC(column_clicked_callback),
+		     NULL);
+
+  node_label1 = gtk_label_new ("Dest");
+  gtk_widget_ref (node_label1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "IP", node_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label1);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 0, node_label1);
+
+  node_label2 = gtk_label_new ("Gateway");
+  gtk_widget_ref (node_label2);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "hops", node_label2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label2);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 1, node_label2);
+
+  node_label3 = gtk_label_new ("Metric");
+  gtk_widget_ref (node_label3);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "info", node_label3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label3);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 2, node_label3);
+
+  node_label4 = gtk_label_new ("Device");
+  gtk_widget_ref (node_label4);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "Device", node_label4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label4);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 3, node_label4);
+
+
+  node_label7 = gtk_label_new ("Timer");
+  gtk_widget_ref (node_label7);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "LMF", node_label7,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label7);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 4, node_label7);
+
+  /*
+  node_label8 = gtk_label_new ("LMA");
+  gtk_widget_ref (node_label8);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "LMA", node_label8,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label8);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 7, node_label8);
+  */
+
+  node_label8 = gtk_label_new ("MID");
+  gtk_widget_ref (node_label8);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "MID", node_label8,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label8);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 5, node_label8);
+
+  node_label9 = gtk_label_new ("HNA");
+  gtk_widget_ref (node_label9);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "HNA", node_label9,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (node_label9);
+  gtk_clist_set_column_widget (GTK_CLIST (node_list), 6, node_label9);
+
+
+
+  gtk_clist_column_titles_active(GTK_CLIST (node_list));
+
+
+  gtk_widget_show_now(node_list);
+
+
+
+  /*
+   *Row selection callback
+   */
+  gtk_signal_connect(GTK_OBJECT(node_list), "select_row",
+		     GTK_SIGNAL_FUNC(node_selection),
+		     NULL);
+
+
+
+
+
+  /*
+   *The first hbox
+   */
+  hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_ref (hbox1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "hbox1", hbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox1);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
+  //gtk_container_add (GTK_CONTAINER (notebook1), hbox1);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox1), 4);
+  gtk_widget_set_size_request(hbox1, -1, 200);
+
+
+
+  /*
+   *The net-info frame
+   */
+  frame4 = gtk_frame_new ("Info:");
+  gtk_widget_ref (frame4);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "frame4", frame4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame4);
+  gtk_box_pack_start (GTK_BOX (hbox1), frame4, TRUE, TRUE, 0);
+  //gtk_widget_set_size_request(frame4, 200, -1);
+  gtk_container_set_border_width (GTK_CONTAINER (frame4), 1);
+
+
+  /*
+   *The net-info hbox
+   */
+  net_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_ref (net_vbox);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "net_vbox", net_vbox,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (net_vbox);
+  gtk_container_add (GTK_CONTAINER (frame4), net_vbox);
+
+
+  /*
+   *The net-info label field
+   */
+  net_label = gtk_label_new(NULL);
+  gtk_widget_ref (net_label);
+  gtk_misc_set_alignment((GtkMisc *)net_label, 0, 0);
+  //gtk_label_set_justify((GtkLabel *)net_label,GTK_JUSTIFY_LEFT);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "net_label", net_label,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  //set_net_info("Not connected...");
+  gtk_widget_show (net_label);
+  gtk_box_pack_start (GTK_BOX (net_vbox), net_label, TRUE, TRUE, 0);
+
+  //gtk_container_add (GTK_CONTAINER (frame4), net_label);
+
+  /*
+   *The connect button
+   */
+
+  connect_button = gtk_button_new_with_label ("Connect to host");
+  gtk_widget_ref (connect_button);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "connect_button", connect_button,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  /* Connect the "clicked" signal of the button to our callback */
+  gtk_signal_connect (GTK_OBJECT (connect_button), "clicked",
+		      GTK_SIGNAL_FUNC (connect_callback), NULL);
+  gtk_widget_show (connect_button);
+  gtk_box_pack_start (GTK_BOX (net_vbox), connect_button, FALSE, FALSE, 1);
+  gtk_container_set_border_width (GTK_CONTAINER (connect_button), 5);
+
+
+
+  /*
+   *The node MPR info frame
+   */
+  mpr_frame = gtk_frame_new ("MPR:");
+  gtk_widget_ref (mpr_frame);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "mpr_frame", mpr_frame,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (mpr_frame);
+  gtk_box_pack_start (GTK_BOX (hbox1), mpr_frame, FALSE, FALSE, 0);
+  //gtk_widget_set_size_request(mid_frame, 125, -1);
+  gtk_container_set_border_width (GTK_CONTAINER (mpr_frame), 1);
+
+  /*
+   *The scrolledwindow to contain the MPR node info
+   */
+  mpr_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (mpr_scrolledwindow);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "mpr_scrolledwindow", mpr_scrolledwindow,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  gtk_widget_show (mpr_scrolledwindow);
+  gtk_container_add (GTK_CONTAINER (mpr_frame), mpr_scrolledwindow);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mpr_scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_container_set_border_width (GTK_CONTAINER (mpr_scrolledwindow), 3);
+
+
+  /*
+   *The node MID info frame
+   */
+  mid_frame = gtk_frame_new ("MID:");
+  gtk_widget_ref (mid_frame);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "mid_frame", mid_frame,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (mid_frame);
+  gtk_box_pack_start (GTK_BOX (hbox1), mid_frame, FALSE, FALSE, 0);
+  //gtk_widget_set_size_request(mid_frame, 125, -1);
+  gtk_container_set_border_width (GTK_CONTAINER (mid_frame), 1);
+
+  /*
+   *The scrolledwindow to contain the MID node info
+   */
+  mid_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (mid_scrolledwindow);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "mid_scrolledwindow", mid_scrolledwindow,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  gtk_widget_show (mid_scrolledwindow);
+  gtk_container_add (GTK_CONTAINER (mid_frame), mid_scrolledwindow);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mid_scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_container_set_border_width (GTK_CONTAINER (mid_scrolledwindow), 3);
+
+
+
+  /*
+   *The MPR list
+   */
+  mpr_list = gtk_clist_new (1);
+  gtk_widget_ref (mpr_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "mpr_list", mpr_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (mpr_list);
+  gtk_container_add (GTK_CONTAINER (mpr_scrolledwindow), mpr_list);
+  gtk_clist_set_column_width (GTK_CLIST (mpr_list), 0, 120); /* IP */
+  gtk_clist_column_titles_hide (GTK_CLIST (mpr_list));
+
+
+  /*
+   *The MID list
+   */
+  mid_list = gtk_clist_new (1);
+  gtk_widget_ref (mid_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "mid_list", mid_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (mid_list);
+  gtk_container_add (GTK_CONTAINER (mid_scrolledwindow), mid_list);
+  gtk_clist_set_column_width (GTK_CLIST (mid_list), 0, 120); /* IP */
+  gtk_clist_column_titles_hide (GTK_CLIST (mid_list));
+
+
+
+
+  /*
+   *The node HNA info frame
+   */
+  hna_frame = gtk_frame_new ("HNA:");
+  gtk_widget_ref (hna_frame);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "hna_frame", hna_frame,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hna_frame);
+  gtk_box_pack_start (GTK_BOX (hbox1), hna_frame, FALSE, FALSE, 0);
+  //gtk_widget_set_size_request(mid_frame, 125, -1);
+  gtk_container_set_border_width (GTK_CONTAINER (hna_frame), 1);
+
+
+
+  /*
+   *The HNA scrolled window
+   */
+  hna_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (hna_scrolledwindow);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "hna_scrolledwindow", hna_scrolledwindow,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  gtk_widget_show (hna_scrolledwindow);
+  gtk_container_add (GTK_CONTAINER (hna_frame), hna_scrolledwindow);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (hna_scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_container_set_border_width (GTK_CONTAINER (hna_scrolledwindow), 3);
+
+
+  /*
+   *The HNA list
+   */
+  hna_list = gtk_clist_new (1);
+  gtk_widget_ref (hna_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "hna_list", hna_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hna_list);
+  gtk_container_add (GTK_CONTAINER (hna_scrolledwindow), hna_list);
+  gtk_clist_set_column_width (GTK_CLIST (hna_list), 0, 120); /* IP */
+  gtk_clist_column_titles_hide (GTK_CLIST (hna_list));
+
+
+
+
+
+  /*
+   *The "main" notebook page
+   */
+  Main = gtk_label_new ("Main");
+  gtk_widget_ref (Main);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "Main", Main,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (Main);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), Main);
+
+
+
+  /*
+   *The main hbox of the Packet page
+   */
+
+  hbox2 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_ref (hbox2);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "hbox2", hbox2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (hbox2);
+  gtk_container_add (GTK_CONTAINER (notebook1), hbox2);
+
+
+  /*
+   *The packet hbox
+   */
+  pack_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_ref (pack_vbox);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "pack_vbox", pack_vbox,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (pack_vbox);
+  gtk_box_pack_start (GTK_BOX (hbox2), pack_vbox, TRUE, TRUE, 0);
+
+
+
+  /*
+   *The packet frame
+   */
+
+  frame2 = gtk_frame_new ("Packet");
+  gtk_widget_ref (frame2);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "frame2", frame2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (frame2);
+  gtk_box_pack_start (GTK_BOX (pack_vbox), frame2, TRUE, TRUE, 0); /* Do not expand */
+
+
+  /*
+   *Packet list scrolled window
+   */
+  scrolledwindow4 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (scrolledwindow4);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "scrolledwindow4", scrolledwindow4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  gtk_widget_show (scrolledwindow4);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow4), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+  gtk_container_add (GTK_CONTAINER (frame2), scrolledwindow4);
+
+
+
+
+
+  /*
+   *The packet list
+   */
+
+  packet_list = gtk_clist_new (3);
+  gtk_widget_ref (packet_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "packet_list", packet_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (packet_list);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow4), packet_list);
+  gtk_clist_set_column_width (GTK_CLIST (packet_list), 0, 80); /* Type */
+  gtk_clist_set_column_width (GTK_CLIST (packet_list), 1, 150); /* Origin IP */
+  gtk_clist_set_column_width (GTK_CLIST (packet_list), 2, 20); /* size */
+  gtk_clist_column_titles_show (GTK_CLIST (packet_list));
+
+  label17 = gtk_label_new ("Type");
+  gtk_widget_ref (label17);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label17", label17,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label17);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_list), 0, label17);
+
+  label18 = gtk_label_new ("Origin");
+  gtk_widget_ref (label18);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label18", label18,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label18);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_list), 1, label18);
+
+  label19 = gtk_label_new ("Size");
+  gtk_widget_ref (label19);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label19", label19,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label19);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_list), 2, label19);
+
+
+
+  /*
+   *Row selection callback
+   */
+  gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
+		     GTK_SIGNAL_FUNC(packet_selection),
+		     NULL);
+
+
+
+  /*
+   *The packet button
+   */
+
+  packet_button = gtk_button_new_with_label ("Grab packets");
+  gtk_widget_ref (packet_button);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "packet_button", packet_button,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  /* Connect the "clicked" signal of the button to our callback */
+  gtk_signal_connect (GTK_OBJECT (packet_button), "clicked",
+		      GTK_SIGNAL_FUNC (packet_callback), NULL);
+  gtk_widget_show (packet_button);
+  gtk_box_pack_start (GTK_BOX (pack_vbox), packet_button, FALSE, FALSE, 5);
+
+
+
+
+
+
+  /*
+   *The packet disp hbox
+   */
+  pack_disp_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_ref (pack_disp_vbox);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "pack_disp_vbox", pack_disp_vbox,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (pack_disp_vbox);
+  gtk_box_pack_start (GTK_BOX (hbox2), pack_disp_vbox, TRUE, TRUE, 0);
+
+
+
+
+  /*
+   *The packet disp frame
+   */
+
+  disp_frame = gtk_frame_new ("Packet content");
+  gtk_widget_ref (disp_frame);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "disp_frame", disp_frame,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (disp_frame);
+  gtk_box_pack_start (GTK_BOX (pack_disp_vbox), disp_frame, TRUE, TRUE, 0); /* Do not expand */
+
+
+
+  /*
+   *Scrolled window for the packet display
+   *list
+   */
+
+  scrolledwindow3 = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (scrolledwindow3);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "scrolledwindow3", scrolledwindow3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (scrolledwindow3);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow3), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+  gtk_container_add (GTK_CONTAINER (disp_frame), scrolledwindow3);
+
+  //gtk_box_pack_start (GTK_BOX (disp_frame), scrolledwindow3, TRUE, TRUE, 0);
+
+
+  /*
+   *The packet display list
+   */
+  packet_content_list = gtk_clist_new (4);
+  gtk_widget_ref (packet_content_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "packet_content_list", packet_content_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+
+  gtk_widget_show (packet_content_list);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow3), packet_content_list);
+  gtk_clist_set_column_width (GTK_CLIST (packet_content_list), 0, 70); /* 0-7 */
+  gtk_clist_set_column_justification(GTK_CLIST (packet_content_list), 0, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (packet_content_list), 1, 70); /* 8-15 */
+  gtk_clist_set_column_justification(GTK_CLIST (packet_content_list), 1, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (packet_content_list), 2, 70); /* 16-23 */
+  gtk_clist_set_column_justification(GTK_CLIST (packet_content_list), 2, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (packet_content_list), 3, 70); /* 24-31 */
+  gtk_clist_set_column_justification(GTK_CLIST (packet_content_list), 3, GTK_JUSTIFY_CENTER);
+  gtk_clist_column_titles_show (GTK_CLIST (packet_content_list));
+
+  label13 = gtk_label_new ("0 - 7");
+  gtk_widget_ref (label13);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label13", label13,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label13);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_content_list), 0, label13);
+
+  label14 = gtk_label_new ("8 - 15");
+  gtk_widget_ref (label14);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label14", label14,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label14);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_content_list), 1, label14);
+
+  label15 = gtk_label_new ("16 - 23");
+  gtk_widget_ref (label15);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label15", label15,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label15);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_content_list), 2, label15);
+
+  label16 = gtk_label_new ("24 - 31");
+  gtk_widget_ref (label16);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label16", label16,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label16);
+  gtk_clist_set_column_widget (GTK_CLIST (packet_content_list), 3, label16);
+
+  //gtk_clist_set_selection_mode(GTK_CLIST (packet_content_list), GTK_SELECTION_NONE); /* no selections */
+
+
+
+  /*
+   *The packet button
+   */
+
+  packet_disp_button = gtk_button_new_with_label ("Display hex");
+  gtk_widget_ref (packet_disp_button);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "packet_disp_button", packet_disp_button,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  /* Connect the "clicked" signal of the button to our callback */
+  gtk_signal_connect (GTK_OBJECT (packet_disp_button), "clicked",
+		      GTK_SIGNAL_FUNC (packet_disp_callback), NULL);
+  gtk_widget_show (packet_disp_button);
+  gtk_box_pack_start (GTK_BOX (pack_disp_vbox), packet_disp_button, FALSE, FALSE, 5);
+
+
+  /*
+   *The "packets" notebook
+   */
+
+  label_packets = gtk_label_new ("Packets");
+  gtk_widget_ref (label_packets);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label_packets", label_packets,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label_packets);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label_packets);
+
+
+
+
+
+
+  /*
+   *The route hbox
+   */
+  route_hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_ref (route_hbox1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_hbox1", route_hbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_hbox1);
+  //gtk_box_pack_start (GTK_BOX (hbox1), vbox1, TRUE, TRUE, 1);
+  gtk_container_add (GTK_CONTAINER (notebook1), route_hbox1);
+
+
+
+
+  /*
+   *The routes frame
+   */
+
+  route_frame = gtk_frame_new ("OLSR routes in kernel:");
+  gtk_widget_ref (route_frame);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_frame", route_frame,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_frame);
+
+  //gtk_container_add (GTK_CONTAINER (notebook1), route_frame);
+  gtk_widget_set_size_request(route_frame, 200, -1);
+  gtk_box_pack_start (GTK_BOX (route_hbox1), route_frame, TRUE, TRUE, 0); /* Do not expand */
+
+
+
+  /*
+   *Scrolled window for the packet display
+   *list
+   */
+
+  route_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_ref (route_scrolledwindow);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_scrolledwindow", route_scrolledwindow,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_scrolledwindow);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (route_scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+  gtk_container_add (GTK_CONTAINER (route_frame), route_scrolledwindow);
+
+  //gtk_box_pack_start (GTK_BOX (route_frame), scrolledwindow3, TRUE, TRUE, 0);
+
+
+  /*
+   *The routes display list
+   */
+  route_list = gtk_clist_new (4);
+  gtk_widget_ref (route_list);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_list", route_list,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  gtk_widget_show (route_list);
+  gtk_container_add (GTK_CONTAINER (route_scrolledwindow), route_list);
+  gtk_clist_set_column_width (GTK_CLIST (route_list), 0, 120); /* dest */
+  //gtk_clist_set_column_justification(GTK_CLIST (route_list), 0, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (route_list), 1, 120); /* gw */
+  //gtk_clist_set_column_justification(GTK_CLIST (route_list), 1, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (route_list), 2, 50); /* weight */
+  gtk_clist_set_column_justification(GTK_CLIST (route_list), 2, GTK_JUSTIFY_CENTER);
+  gtk_clist_set_column_width (GTK_CLIST (route_list), 3, 70); /* interface */
+  gtk_clist_set_column_justification(GTK_CLIST (route_list), 3, GTK_JUSTIFY_CENTER);
+  gtk_clist_column_titles_show (GTK_CLIST (route_list));
+
+  route_label1 = gtk_label_new ("Destination");
+  gtk_widget_ref (route_label1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_label1", route_label1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_label1);
+  gtk_clist_set_column_widget (GTK_CLIST (route_list), 0, route_label1);
+
+  route_label2 = gtk_label_new ("Gateway");
+  gtk_widget_ref (route_label2);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_label2", route_label2,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_label2);
+  gtk_clist_set_column_widget (GTK_CLIST (route_list), 1, route_label2);
+
+  route_label3 = gtk_label_new ("Weight");
+  gtk_widget_ref (route_label3);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_label3", route_label3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_label3);
+  gtk_clist_set_column_widget (GTK_CLIST (route_list), 2, route_label3);
+
+  route_label4 = gtk_label_new ("Interface");
+  gtk_widget_ref (route_label4);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_label4", route_label4,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_label4);
+  gtk_clist_set_column_widget (GTK_CLIST (route_list), 3, route_label4);
+
+  //gtk_clist_set_selection_mode(GTK_CLIST (route_list), GTK_SELECTION_NONE); /* no selections */
+
+
+
+  /*
+   *The routes stats frame
+   */
+
+  route_stats_frame = gtk_frame_new ("Stats:");
+  gtk_widget_ref (route_stats_frame);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "route_stats_frame", route_stats_frame,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (route_stats_frame);
+
+  //gtk_container_add (GTK_CONTAINER (notebook1), route_frame);
+  gtk_box_pack_start (GTK_BOX (route_hbox1), route_stats_frame, TRUE, TRUE, 1);
+
+
+
+
+
+  /*
+   *The "routes" notebook
+   */
+  label_routes = gtk_label_new ("Routes");
+  gtk_widget_ref (label_routes);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "label_routes", label_routes,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label_routes);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 2), label_routes);
+
+
+
+
+  empty1 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (empty1);
+  gtk_container_add (GTK_CONTAINER (notebook1), empty1);
+
+
+
+
+
+
+
+  /*
+   *The "traffic" notebook
+   */
+  traffic_label = gtk_label_new ("Traffic");
+  gtk_widget_ref (traffic_label);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "traffic_label", traffic_label,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (traffic_label);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 3), traffic_label);
+  
+
+
+
+
+  /*
+   *The settings hbox
+   */
+  settings_hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_ref (settings_hbox1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "settings_hbox1", settings_hbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (settings_hbox1);
+  //gtk_box_pack_start (GTK_BOX (hbox1), vbox1, TRUE, TRUE, 1);
+  gtk_container_add (GTK_CONTAINER (notebook1), settings_hbox1);
+
+
+
+  /*
+   *The settings-info label field
+   */
+  info_label = gtk_label_new(NULL);
+  gtk_widget_ref (info_label);
+  gtk_misc_set_alignment((GtkMisc *)info_label, 0, 0);
+  //gtk_label_set_justify((GtkLabel *)net_label,GTK_JUSTIFY_LEFT);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "info_label", info_label,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  //set_net_info("Not connected...");
+  gtk_widget_show (info_label);
+  gtk_box_pack_start (GTK_BOX (settings_hbox1), info_label, TRUE, TRUE, 0);
+
+
+  /*
+   *The "settings" notebook
+   */
+  settings_label = gtk_label_new ("Settings");
+  gtk_widget_ref (settings_label);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "settings_label", settings_label,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (settings_label);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 4), settings_label);
+
+
+
+
+
+
+
+  /*
+   *The "about" hbox
+   */
+  about_hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_ref (about_hbox1);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "about_hbox1", about_hbox1,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (about_hbox1);
+  //gtk_box_pack_start (GTK_BOX (hbox1), vbox1, TRUE, TRUE, 1);
+  gtk_container_add (GTK_CONTAINER (notebook1), about_hbox1);
+  gtk_container_set_border_width (GTK_CONTAINER (about_hbox1), 10);
+
+
+  /*
+   *The about label field
+   */
+  about_label = gtk_label_new(NULL);
+  gtk_widget_ref (about_label);
+  gtk_misc_set_alignment((GtkMisc *)about_label, 0, 0);
+  gtk_label_set_justify((GtkLabel *)about_label,GTK_JUSTIFY_CENTER);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "about_label", about_label,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  //set_net_info("Not connected...");
+  gtk_widget_show (about_label);
+  gtk_box_pack_start (GTK_BOX (about_hbox1), unik_logo, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (about_hbox1), about_label, TRUE, TRUE, 0);
+  gtk_widget_show (unik_logo);
+
+
+  gtk_label_set_text((GtkLabel *)about_label, "OLSRD-GUI by Andreas Tonnesen (andreto@ifi.uio.no)");
+
+
+  /*
+   *The "about" notebook
+   */
+  label3 = gtk_label_new ("About");
+  gtk_widget_ref (label3);
+  gtk_object_set_data_full (GTK_OBJECT (main_window), "About", label3,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (label3);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 5), label3);
+
+
+
+  return main_window;
+
+}
+
+
+
+
+/*
+ *Add a node to the node list
+ */
+void
+route_list_add(char *dest, char *gw, char *metric, char *dev)
+{
+  gchar *tmp[4] = {dest, gw, dev, metric};
+  route_list_size++;
+
+  gtk_clist_freeze(GTK_CLIST(route_list));
+
+  gtk_clist_append(GTK_CLIST(route_list), tmp);
+
+  gtk_clist_thaw(GTK_CLIST(route_list));
+
+}
+
+
+/*
+ *Update the entyr with IP 'addr'
+ */
+void
+route_list_update(char *addr)
+{
+
+}
+
+
+/*
+ *Delete a node from the node list
+ */
+int
+route_list_del(char *dest)
+{
+  int i = 0;
+  char *ip;
+
+  gtk_clist_freeze(GTK_CLIST(route_list));
+
+  for(i = 0; i < route_list_size; i++)
+    {
+      gtk_clist_get_text(GTK_CLIST(route_list), i, 0, (gchar **) &ip);
+      if(strcmp(dest, ip) == 0)
+	{
+	  //printf("Found %d\n", i);
+	  gtk_clist_remove(GTK_CLIST(route_list), i);
+	  route_list_size--;
+	  gtk_clist_thaw(GTK_CLIST(route_list));
+	  return 1;
+	}
+    }
+
+  gtk_clist_thaw(GTK_CLIST(route_list));
+  return 0;  
+}
+
+
+
+/*
+ *Remove a node from the list
+ */
+int
+remove_nodes_list(union olsr_ip_addr *node)
+{
+  char *ip;
+  char *in_ip = ip_to_string(node);
+  int i;
+
+  for(i = 0; i < node_list_size; i++)
+    {
+      gtk_clist_get_text(GTK_CLIST(node_list), i, 0, (gchar **) &ip);
+      if(strcmp(in_ip, ip) == 0)
+	{
+	  //printf("Found entry!\n");
+	  gtk_clist_remove(GTK_CLIST(node_list), i);
+	  node_list_size--;
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+
+
+
+/*
+ *If the node passed as a parameter exists then
+ *update it. If not add it to the list
+ */
+void
+update_nodes_list(struct node *node)
+{
+  int i = 0;
+  char *ip;
+  int found = 0;
+  char *dest;
+  char *tmp[9] = {"","","","","","","","",""};
+  char timer[20];
+  struct tm *time_st;
+  char itoa_buf[10];
+
+  if(memcmp(&node->addr, &main_addr, ipsize) == 0)
+    dest = "local";
+  else
+    dest = ip_to_string(&node->addr);
+
+  gtk_clist_freeze(GTK_CLIST(node_list));
+
+  while((i < node_list_size) && !found)
+    {
+      gtk_clist_get_text(GTK_CLIST(node_list), i, 0, (gchar **) &ip);
+      if(strcmp(dest, ip) == 0)
+	found = 1;
+      i++;
+    }
+
+  /* Update node */
+  if(found)
+    {
+      i--; /* Go backt to the right row */
+      //printf("Updating %s\n\n", ip_to_string(&node->addr));
+      /* don't update main addr */
+      /* Gateway */
+      if(memcmp(&node->addr, &main_addr, ipsize) != 0)
+	{
+	  if(memcmp(&node->gw_addr, &null_addr, ipsize) != 0)
+	    gtk_clist_set_text(GTK_CLIST(node_list), i, 1, ip_to_string(&node->gw_addr));
+	  /* Weigth */
+	  if(node->hopcount != 0)
+	    {
+	      gui_itoa(node->hopcount, itoa_buf);
+	      gtk_clist_set_text(GTK_CLIST(node_list), i, 2, itoa_buf);
+	    }
+	  /* Device */
+	  gtk_clist_set_text(GTK_CLIST(node_list), i, 3, &node->dev[0]);
+	}
+
+
+      /* Timer */
+      if(node->timer.tv_usec)
+      {
+	memset(&timer[0], 0, 20);
+	time_st = localtime((time_t *)&node->timer.tv_sec);
+	sprintf(&timer[0], "%02d:%02d:%02d", time_st->tm_hour, time_st->tm_min, time_st->tm_sec);
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 4, &timer[0]);
+      }
+
+
+      /* MID */
+      if(node->mid.next != &node->mid)
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 5, "yes");
+      else
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 5, "no");
+      /* HNA */
+      if(node->hna.next != &node->hna)
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 6, "yes");
+      else
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 6, "no");
+		
+    }
+  /* Add new node */
+  else
+    {
+      i = node_list_size;
+      /* Create entry */
+      gtk_clist_insert(GTK_CLIST(node_list), i, tmp);
+      /* Main address */
+      gtk_clist_set_text(GTK_CLIST(node_list), i, 0, dest);
+      if(memcmp(&node->addr, &main_addr, ipsize) == 0)
+	{
+	  if(memcmp(&node->gw_addr, &null_addr, ipsize) != 0)
+	    gtk_clist_set_text(GTK_CLIST(node_list), i, 1, ip_to_string(&node->gw_addr));
+	  /* Weigth */
+	  if(node->hopcount != 0)
+	    {
+	      gui_itoa(node->hopcount, itoa_buf);
+	      gtk_clist_set_text(GTK_CLIST(node_list), i, 2, itoa_buf);
+	    }
+	  /* Device */
+	  gtk_clist_set_text(GTK_CLIST(node_list), i, 3, &node->dev[0]);
+	}
+
+      /* MID */
+      if(node->mid.next != &node->mid)
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 5, "yes");
+      else
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 5, "no");
+      /* HNA */
+      if(node->hna.next != &node->hna)
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 6, "yes");
+      else
+	gtk_clist_set_text(GTK_CLIST(node_list), i, 6, "no");
+
+      node_list_size++;
+    }
+
+  gtk_clist_thaw(GTK_CLIST(node_list));
+
+
+}
+
+
+
+
+/*
+ *Add a packet to the packet list
+ */
+void
+packet_list_add(char *type, char *from, char *length)
+{
+  gchar *nfo[3] = {type, from, length};
+
+  //if(!freeze_packets)
+    //{
+      if(packet_list_size >= MAXPACKS)
+	gtk_clist_remove(GTK_CLIST(packet_list), MAXPACKS-1);
+      else
+	packet_list_size++;
+
+      gtk_clist_prepend(GTK_CLIST(packet_list), nfo );
+
+      //}
+
+}
+
+
+
+
+
+
+
+
+void
+set_net_info(gchar *info, int disp_button)
+{
+  gchar title[255];
+
+  memset(&title[0], 0, 255);
+  gtk_label_set_text((GtkLabel *)info_label, info); 
+  gtk_label_set_text((GtkLabel *)net_label, "Connected"); 
+
+  strcat(title, olsrd_version);
+  strcat(title, " - ");
+  strcat(title, ip_to_string(&main_addr));
+
+  gtk_window_set_title (GTK_WINDOW (main_window), title);
+
+  if(disp_button)
+    gtk_widget_show(connect_button);
+  else 
+    gtk_widget_hide(connect_button);
+}
+
+
+
+void
+set_net_info_offline()
+{
+  gtk_label_set_text((GtkLabel *)net_label, "Connection refused...");
+  gtk_widget_show(connect_button);
+}
+
+void
+set_net_info_connecting()
+{
+  gtk_label_set_text((GtkLabel *)net_label, "Connecting...");  
+}
+
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/interface.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/interface.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/interface.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/interface.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,93 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+
+GtkWidget *net_label;
+GtkWidget *info_label;
+GtkTextBuffer *textBuffer;
+GtkWidget *connect_button;
+GtkWidget *packet_list;
+GtkWidget *packet_content_list;
+GtkWidget *packet_button;
+GtkWidget *packet_disp_button;
+GtkWidget *node_list;
+GtkWidget *mid_list;
+GtkWidget *mpr_list;
+GtkWidget *hna_list;
+GtkWidget *route_list;
+
+
+void
+fill_clist(GtkCList *);
+
+
+void selection_made( GtkWidget      *clist,
+                     gint            row,
+                     gint            column,
+		     GdkEventButton *event,
+                     gpointer        data );
+
+
+void
+set_net_info_connecting();
+
+void
+column_clicked_callback(GtkWidget *,gint);
+
+
+void 
+connect_callback( GtkWidget *widget,
+		  gpointer   data );
+
+void 
+packet_callback( GtkWidget *widget,
+		  gpointer   data );
+
+void 
+packet_disp_callback( GtkWidget *widget,
+		  gpointer   data );
+
+
+void
+packet_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data);
+
+
+void
+node_selection(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data);
+
+
+void
+gui_shutdown(GtkObject *, gpointer);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/ipc.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/ipc.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/ipc.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/ipc.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,721 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "common.h"
+#include "ipc.h"
+#include "packet.h"
+#include "routes.h"
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+#undef errno
+#define errno WSAGetLastError()
+#undef strerror
+#define strerror(x) StrError(x)
+#define perror(x) WinSockPError(x)
+#endif
+
+int ipc_socket = 0;
+
+int
+ipc_close()
+{
+
+  if(close(ipc_socket))
+    return 1;
+  
+  return 0;
+}
+
+
+
+int
+ipc_connect(struct sockaddr_in *pin)
+{
+#ifdef WIN32
+  int On = 1;
+  unsigned long Len;
+#else
+  int flags;
+#endif
+
+  connected = 0;
+
+  if(!ipc_socket)
+    if((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+      {
+	perror("socket");
+	exit(1);
+      }
+
+  printf("Attempting connect...");
+
+  /* connect to PORT on HOST */
+  if (connect(ipc_socket,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
+    {
+      fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+      set_net_info_offline();
+      printf("connection refused\n");
+    }
+  else 
+    {
+      set_net_info("Connected!", FALSE);
+      printf("Connected!!\n");
+
+      /* Setting socket non-blocking */  
+      
+#ifdef WIN32
+      if (WSAIoctl(ipc_socket, FIONBIO, &On, sizeof (On), NULL, 0, &Len,
+                   NULL, NULL) < 0)
+        {
+          fprintf(stderr, "Error while making socket non-blocking!\n");
+          exit(1);
+        }
+#else
+      if ((flags = fcntl(ipc_socket, F_GETFL, 0)) < 0)
+	{
+	  fprintf(stderr,"Error getting socket flags!\n");
+	  exit(1);
+	}
+      
+      
+      if (fcntl(ipc_socket, F_SETFL, flags | O_NONBLOCK) < 0)
+	{
+	  fprintf(stderr,"Error setting socket flags!\n");
+	  exit(1);
+	}
+#endif      
+      connected = 1;
+      
+      return 1;
+    }
+  
+  return 0;
+
+}
+
+
+int
+ipc_read()
+{
+  //int x, i;
+  int bytes, tmp_len;
+  char *tmp;
+  union olsr_message *msg;
+  union 
+  {
+    char	buf[BUFFSIZE+1];
+    union	olsr_message olsr_msg;
+  } inbuf;
+  //char buf[BUFFSIZE+1];
+
+  //printf(".");fflush(stdout);
+  memset(&inbuf, 0, sizeof(BUFFSIZE+1));
+  //buf[0] = '\0';
+
+  if(connected)
+    {
+      bytes = recv(ipc_socket, (char *)&inbuf, BUFFSIZE, 0);
+      if (bytes == 0)
+        {
+          shutdown(ipc_socket, SHUT_RDWR);
+	  set_net_info("Disconnected from server...", TRUE);
+          connected = 0;
+	  close(ipc_socket);
+        }
+     
+      if(bytes > 0)
+	{
+	   
+	  tmp = (char *) &inbuf.olsr_msg;
+	
+	  /*    
+	  x = 0;
+	  printf("\n\t");
+	  for(i = 0; i < bytes;i++)
+	    {
+	      if(x == 4)
+		{
+		  x = 0;
+		  printf("\n\t");
+		}
+	      x++;
+	      printf(" %03i", (u_char) tmp[i]);
+	    }
+	  
+	  printf("\n\nBytes read: %d - msg_size: %d\n", bytes, ntohs(inbuf.olsr.v4.olsr_packlen));
+	  */
+	  
+	  msg = &inbuf.olsr_msg;
+
+	  /* There can be(there probably are!) several packets in the buffer */
+
+	  /* Should be the same for v4 and v6 */
+	  if(ntohs(inbuf.olsr_msg.v4.olsr_msgsize) < bytes)
+	    {
+	      //printf("chomping...\n");
+	      while(ntohs(msg->v4.olsr_msgsize) < bytes)
+		{
+		  ipc_evaluate_message(msg);
+
+		  tmp_len = ntohs(msg->v4.olsr_msgsize);
+		  msg = (union olsr_message *) &tmp[tmp_len];
+		  tmp = &tmp[tmp_len];
+		  if(tmp_len == 0)
+		    break;
+		  bytes = bytes - tmp_len;
+
+		  tmp_len = ntohs(msg->v4.olsr_msgsize);
+
+		  //printf("%d/%d ", tmp_len, bytes);
+		  /* Copy to start of buffer */
+		  if(tmp_len > bytes)
+		    {
+		      /* Copy the buffer */
+		      //printf("READING END OF MESSAGE. %d bytes\n", tmp_len-bytes);
+		      //printf("\tCopying %d bytes\n", bytes);
+		      memcpy(&inbuf, tmp, bytes);
+		      //printf("\tRecieving %d bytes to buffer[%d]\n", tmp_len-bytes, bytes);
+		      bytes = recv(ipc_socket, (char *)&inbuf.buf[bytes], tmp_len-bytes, 0);
+		      //printf("\tBytes: %d Size: %d\n", bytes, ntohs(msgs->v4.olsr_packlen));
+		      tmp = (char *)&inbuf.olsr_msg;
+		      msg = (union olsr_message *) tmp;
+		    }
+		}
+	      //printf("\n");
+	    }
+	  
+	  /* Only one (or the last) message */
+	  ipc_evaluate_message(msg);
+
+	}
+
+    }
+
+
+
+  return 1;
+}
+
+
+
+
+int
+ipc_send()
+{
+
+
+  return 1;
+}
+
+
+
+
+
+int
+ipc_evaluate_message(union olsr_message *olsr_in)
+{
+  int ipc_pack = 0;
+  olsr_u8_t type;
+  int msgsize;
+  char itoa_buf[10];
+  olsr_u8_t vtime;
+  union olsr_ip_addr *originator;
+
+  /* Find size, vtime, originator and type - same for IPv4 and 6 */
+  type = olsr_in->v4.olsr_msgtype;
+  msgsize = ntohs(olsr_in->v4.olsr_msgsize);
+  vtime = olsr_in->v4.olsr_vtime;
+  originator = (union olsr_ip_addr *)&olsr_in->v4.originator;
+
+  gui_itoa(msgsize, itoa_buf);
+
+  switch(type)
+    {
+    case HELLO_MESSAGE:
+      //printf("Recieved HELLO packet\n");
+      if(!freeze_packets)
+	packet_list_add("HELLO", ip_to_string(originator), itoa_buf);
+
+      if(ipversion == AF_INET)
+	{
+	  process_hello(msgsize, vtime, originator, (union hello_message *)&olsr_in->v4.message.hello);
+	}
+      else
+	{
+	  process_hello(msgsize, vtime, originator, (union hello_message *)&olsr_in->v6.message.hello);
+	}
+      break;
+
+    case TC_MESSAGE:
+      if(!freeze_packets)
+	packet_list_add("TC", ip_to_string(originator), itoa_buf);
+      
+      if(ipversion == AF_INET)
+	{
+	  process_tc(msgsize, vtime, originator, (union tc_message *)&olsr_in->v4.message.tc);
+	  //printf("Recieved TC packet from %s\n", ip_to_string(&m->olsr_tc->tc_origaddr));
+	}
+      else
+	{
+	  process_tc(msgsize, vtime, originator, (union tc_message *)&olsr_in->v6.message.tc);
+	  //printf("Recieved TC packet from %s\n", ip_to_string(&m->olsr_tc->tc_origaddr));
+	}
+      break;
+
+    case MID_MESSAGE:
+      if(!freeze_packets)
+	packet_list_add("MID", ip_to_string(originator), itoa_buf);
+      if(ipversion == AF_INET)
+	{
+	  process_mid(msgsize, vtime, originator, (union mid_message *)&olsr_in->v4.message.mid);
+	  //printf("Recieved MID packet from %s\n", ip_to_string(&m->olsr_mid->mid_origaddr));
+	}
+      else
+	{
+	  process_mid(msgsize, vtime, originator, (union mid_message *)&olsr_in->v6.message.mid);
+	  //printf("Recieved MID packet from %s\n", ip_to_string(&m->olsr_mid->mid_origaddr));
+	}
+      
+      break;
+
+    case HNA_MESSAGE:
+
+      if(!freeze_packets)
+	packet_list_add("HNA", ip_to_string(originator), itoa_buf);
+      if(ipversion == AF_INET)
+	{
+	  process_hna(msgsize, vtime, originator, (union hna_message *)&olsr_in->v4.message.hna);
+	  //printf("Recieved HNA packet\n");
+	}
+      else
+	{
+	  process_hna(msgsize, vtime, originator, (union hna_message *)&olsr_in->v6.message.hna);
+	  //printf("Recieved HNA packet\n");
+	}
+      
+      break;
+
+    case IPC_MESSAGE:
+      //printf("Recieved IPC packet\n");
+      ipc_pack = 1; /* Don't add to buffer */
+      ipc_eval_route_packet((struct routemsg *) olsr_in);      
+      break;
+    case IPC_NET:
+      //printf("Recieved IPC packet\n");
+      ipc_pack = 1; /* Don't add to buffer */
+      ipc_eval_net_info((struct netmsg *) olsr_in);      
+      break;
+    default:
+      if(!freeze_packets)
+	{
+	  char unk_label[8];
+	  sprintf(unk_label, "%d", type);
+	  packet_list_add(unk_label, ip_to_string(originator), itoa_buf);
+	}
+	printf("Unknown packet type %d\n", type);
+      
+    }
+  
+  if(!freeze_packets && !ipc_pack)
+    {
+	  add_packet_to_buffer(olsr_in, msgsize);
+    }
+
+
+  return 1;
+}
+
+
+
+int
+ipc_eval_net_info(struct netmsg *msg)
+{
+  char info[256];
+  printf("Evaluating NET info...\n");
+
+  /*
+  printf("\tMain address: %s\n", ip_to_string(&msg->main_addr));
+  printf("\tMid adresses: %d\n", msg->mids);
+  printf("\tHna adresses: %d\n", msg->hnas);
+  printf("\tHELLO interval: %f\n", (float)(ntohs(msg->hello_int)));
+  printf("\tHELLO LAN interval: %f\n", (float)(ntohs(msg->hello_lan_int)));
+  printf("\tTC interval: %d\n", ntohs(msg->tc_int));
+  printf("\tNeighbor hold time: %d\n", ntohs(msg->neigh_hold));
+  printf("\tTopology hold: %d\n", ntohs(msg->topology_hold));
+  */
+  if(msg->ipv6 == 0)
+    {
+      ipversion = AF_INET;
+      ipsize = sizeof(struct in_addr);
+      sprintf(&info[0],"IP version 4\nMain address: %s\nMid addresses: %d\nHna addresses: %d\nHELLO interval: %d\nHELLO LAN interval: %d\nTC interval: %d\nNeighbor hold time: %d\nTopology hold: %d\n", ip_to_string(&msg->main_addr), msg->mids, msg->hnas, ntohs(msg->hello_int), ntohs(msg->hello_lan_int), ntohs(msg->tc_int), ntohs(msg->neigh_hold), ntohs(msg->topology_hold));
+   }
+  else
+    {
+      ipversion = AF_INET6;
+      ipsize = sizeof(struct in6_addr);
+      sprintf(&info[0],"IP version 6\nMain address: %s\nMid addresses: %d\nHna addresses: %d\nHELLO interval: %d\nHELLO LAN interval: %d\nTC interval: %d\nNeighbor hold time: %d\nTopology hold: %d\n", ip_to_string(&msg->main_addr), msg->mids, msg->hnas, ntohs(msg->hello_int), ntohs(msg->hello_lan_int), ntohs(msg->tc_int), ntohs(msg->neigh_hold), ntohs(msg->topology_hold));
+    }
+
+
+
+  memcpy(&main_addr, &msg->main_addr, ipsize);
+
+  set_net_info(&info[0], 0);
+
+
+  return 0;
+}
+
+
+int
+ipc_eval_route_packet(struct routemsg *msg)
+{
+  struct route_entry rt_ent;
+  char dev[5];
+  char gw[16];
+  char itoa_buf[10];
+  dev[4] = '\0';
+  memset(&gw[0], 0, 16);
+
+  printf("Processing route packet\n"); 
+
+  memset(rt_ent.if_name, 0, MAX_IF_NAMESIZ);
+  
+  /* Fill struct */
+  
+  memcpy(&rt_ent.gw, &msg->gateway_addr, ipsize);
+  memcpy(&rt_ent.dst, &msg->target_addr, ipsize);
+  memcpy(rt_ent.if_name, msg->device, 4);
+  rt_ent.hopcnt = msg->metric;
+
+  if(msg->add)
+    {
+      memcpy(&dev[0], &msg->device[0], 4);
+
+      /*Add node to node list */
+      memcpy(&gw[0], ip_to_string(&msg->gateway_addr), 16);
+
+      gui_itoa(msg->metric, itoa_buf);
+
+      route_list_add(ip_to_string(&msg->target_addr),
+		     gw,
+		     dev,
+		     itoa_buf);
+
+      printf("\tRoute to %s(hc %d) added\n", ip_to_string(&msg->target_addr), rt_ent.hopcnt);
+
+      /*
+      printf("\tRoute to %s added\n", ip_to_string(&msg->target_addr));
+      printf("\tGateway %s\n", gw);
+      printf("\tInterface %s\n", msg->device);
+      printf("\tMetric %d\n", msg->metric);
+      */
+    }
+  else
+    {
+
+      if(route_list_del(ip_to_string(&msg->target_addr)) < 1)
+	printf("COULD NOT FIND ROUTE TO DELETE!\n\n");
+
+      printf("\tRoute to %s deleted\n", ip_to_string(&msg->target_addr));
+    }
+  return 1;
+}
+
+
+
+
+int
+process_hello(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union hello_message *m)
+{
+  struct hellinfo *neigh;
+  struct hellinfo6 *neigh6;
+  int i;
+  int nsize;
+  int type, link;
+
+
+  printf("Processing HELLO from %s size = %d\n", ip_to_string(originator), size);
+
+
+  if(!update_timer_node(originator, vtime))
+    add_node(originator, vtime);
+
+  /* Add neighbors if any */
+  size = size - 4 - 8 - ipsize; /* size of neighbors(size - olsrheder- helloheader) */
+
+  if(!size)
+    return 0;
+
+
+  /* Get the neighbortype-blocks start */
+  neigh = m->v4.hell_info;
+  neigh6 = m->v6.hell_info;
+
+  //printf("HELLO Size: %d\n", size);
+
+  while(size > 0)
+    {
+
+      //printf("\tNEIGH: 0x%x\n", (int)neigh);
+      if(ipversion == AF_INET)
+	{
+	  nsize = ntohs(neigh->size);
+	  type = EXTRACT_STATUS(ntohs(neigh->link_code));
+	  link = EXTRACT_LINK(ntohs(neigh->link_code));
+	  //printf("TYPE: %d\n", neigh->link_code);
+	}
+      else
+	{
+	  nsize = ntohs(neigh6->size);
+	  type = EXTRACT_STATUS(ntohs(neigh6->link_code));
+	  link = EXTRACT_LINK(ntohs(neigh6->link_code));
+	}
+
+
+      size -= nsize;
+
+      nsize = nsize - 4; /* - hellinfo header */
+      //printf("Size left: %d Current hellinfo: %d\n", size, nsize);
+      i = 0;
+      while(nsize > 0)
+	{
+	  //printf("Adding neighbor %s...\n", ip_to_string((union olsr_ip_addr *)&neigh->neigh_addr[i]));
+	  /*
+	   if(MPR)
+	  update_timer_mpr((union olsr_ip_addr *)&mprsinfo->addr, originator);
+	  */
+	  
+	  if(ipversion == AF_INET) /* Update MPRs */
+	    {
+	      if(type == MPR_NEIGH)
+		{
+		  //printf("MPR from HELLO\n");
+		  update_timer_mpr((union olsr_ip_addr *)&neigh->neigh_addr[i], originator, vtime);
+		}
+	      add_node((union olsr_ip_addr *)&neigh->neigh_addr[i++], vtime);
+	    }
+	  else
+	    {
+	      if(type == MPR_NEIGH) /* Update MPRs */
+		{
+		  //printf("MPR from HELLO\n");
+		  update_timer_mpr((union olsr_ip_addr *)&neigh6->neigh_addr[i], originator, vtime);
+		}
+	      add_node((union olsr_ip_addr *)&neigh6->neigh_addr[i++], vtime);
+	    }
+
+	  nsize = nsize - ipsize;
+	  //printf("Nsize: %d\n", nsize);
+	}
+ 
+      neigh = (struct hellinfo *) &neigh->neigh_addr[i];
+      neigh6 = (struct hellinfo6 *) &neigh6->neigh_addr[i];
+
+      
+    }
+  //printf("DONE\n");
+
+  return 0;
+}
+
+
+
+
+int
+process_tc(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union tc_message *m)
+{
+
+  struct neigh_info *mprsinfo;
+  struct neigh_info6 *mprsinfo6;
+
+  printf("Processing TC from %s size = %d\n", ip_to_string(originator), size);
+
+  /* Updating timer */
+  if(!update_timer_node(originator, vtime))
+    add_node(originator, vtime);
+
+  /* Calculate size of the mprsinfo */
+  size = size - 4 - 8 - ipsize;
+
+  //printf("TC Size: %d\n", size);
+
+  if(ipversion == AF_INET)
+    mprsinfo =  &m->v4.neigh[0];
+  else
+    mprsinfo6 =  &m->v6.neigh[0];
+
+
+  while(size > 0)
+    {
+      if(ipversion == AF_INET)
+	{
+	  //printf("\tprocessing TC: %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo->addr));
+	  add_node((union olsr_ip_addr *)&mprsinfo->addr, vtime);
+	  update_timer_mpr((union olsr_ip_addr *)&mprsinfo->addr, originator, vtime);
+	  mprsinfo++;
+	}
+      else
+	{
+	  //printf("\tprocessing TC: %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo6->addr));
+	  //printf("TC: add node %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo6->addr));
+	  add_node((union olsr_ip_addr *)&mprsinfo6->addr, vtime);
+	  update_timer_mpr((union olsr_ip_addr *)&mprsinfo6->addr, originator, vtime);
+	  mprsinfo6++;
+	}
+      size = size - ipsize;
+      //printf("\tsize: %d\n", size);
+    }
+  //printf("DONE\n");
+
+  return 0;
+}
+
+
+
+int
+process_mid(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union mid_message *m)
+{
+  struct midaddr *midaddr;
+  struct midaddr6 *midaddr6;
+
+
+  printf("Processing MID from %s size = %d\n", ip_to_string(originator), size);
+
+  /* Calculate size of the midinfo */
+  size = size - 4 - 4 - ipsize;
+
+  if(ipversion == AF_INET)
+    midaddr =  &m->v4.mid_addr[0];
+  else
+    midaddr6 =  &m->v6.mid_addr[0];
+
+  //printf("MID size: %d\n", size);
+
+  while(size > 0)
+    {
+      if(ipversion == AF_INET)
+	{
+	  //printf("MID: add node %s\n", ip_to_string((union olsr_ip_addr *)&midaddr->addr));
+	  add_mid_node(originator, (union olsr_ip_addr *)&midaddr->addr, vtime);
+	  midaddr++;
+	}
+      else
+	{
+	  add_mid_node(originator, (union olsr_ip_addr *)&midaddr6->addr, vtime);
+	  //printf("MID: add node %s\n", ip_to_string((union olsr_ip_addr *)&midaddr6->addr));
+	  midaddr6++;
+	}
+      size = size - ipsize;
+    }
+
+  //printf("DONE\n");
+  return 0;
+}
+
+
+
+
+int
+process_hna(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union hna_message *m)
+{
+
+
+  printf("Processing HNA size = %d\n", size);
+  struct hnapair *hnapairs;
+  struct hnapair6 *hnapairs6;
+
+  /* Calculate size of the hnainfo */
+  size = size - 4 - 4 - ipsize;
+
+  if(ipversion == AF_INET)
+    hnapairs =  &m->v4.hna_net[0];
+  else
+    hnapairs6 =  &m->v6.hna_net[0];
+
+
+  while(size > 0)
+    {
+      if(ipversion == AF_INET)
+	{
+	  //printf("\tHNA:%s\n", ip_to_string((union olsr_ip_addr *)&hnapairs->addr));
+	  add_hna_node(originator, (union olsr_ip_addr *)&hnapairs->addr, (union olsr_ip_addr *)&hnapairs->netmask, vtime);
+	  hnapairs++;
+	}
+      else
+	{
+	  add_hna_node(originator, (union olsr_ip_addr *)&hnapairs6->addr, (union olsr_ip_addr *)&hnapairs6->netmask, vtime);
+	  hnapairs6++;
+	}
+
+      size = size - ipsize - ipsize;
+    }
+
+
+  return 0;
+}
+
+
+
+
+
+
+char *
+ip_to_string(union olsr_ip_addr *addr)
+{
+  char *ret;
+  struct in_addr in;
+  
+  if(ipversion == AF_INET)
+    {
+      in.s_addr=addr->v4;
+      ret = inet_ntoa(in);
+    }
+  else
+    {
+      /* IPv6 */
+      ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
+    }
+
+  return ret;
+
+}
+
+
+
+
+int
+gui_itoa(int i, char *buf)
+{
+  char tmp[10];
+
+  if(sprintf(buf, "%hd", i))
+  {
+      /* This shitty string needs to be converted to UTF-8 */
+    strcpy(tmp, g_locale_to_utf8(buf, -1, NULL, NULL, NULL));
+    strcpy(buf, tmp);
+    return 1;
+    //return ret;
+  }
+  return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/ipc.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/ipc.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/ipc.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/ipc.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,105 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "olsr_protocol.h"
+#include "packet.h"
+
+#define IPC_PORT 1212
+#define	IPC_MESSAGE 11    /* IPC to front-end telling of route changes */
+#define IPC_NET 12       /* IPC to front end net-info */
+
+
+//int ipc_socket;
+int connected;
+
+
+/*
+ *AND:
+ *IPC message sent to the front-end
+ *at every route update. Both delete
+ *and add
+ */
+
+struct routemsg 
+{
+  olsr_u8_t      msgtype;
+  olsr_u16_t     size;
+  olsr_u8_t      metric;
+  olsr_u8_t      add;
+  union olsr_ip_addr target_addr;
+  union olsr_ip_addr gateway_addr;
+  char           device[4];
+};
+
+
+struct netmsg
+{
+  olsr_u8_t      msgtype;
+  olsr_u16_t     size;
+  olsr_u8_t      mids; /* No. of extra interfaces */
+  olsr_u8_t      hnas; /* No. of HNA nets */
+  olsr_u8_t      unused1;
+  olsr_u16_t     hello_int;
+  olsr_u16_t     hello_lan_int;
+  olsr_u16_t     tc_int;
+  olsr_u16_t     neigh_hold;
+  olsr_u16_t     topology_hold;
+  olsr_u8_t      ipv6;
+  union olsr_ip_addr   main_addr;
+};
+
+/*
+ *Private functions
+ */
+
+int
+ipc_get_socket();
+
+int
+ipc_evaluate_message(union olsr_message *);
+
+int
+ipc_eval_route_packet(struct routemsg *);
+
+int
+ipc_eval_net_info(struct netmsg *);
+
+int
+process_hello(int, olsr_u8_t, union olsr_ip_addr *, union hello_message *);
+
+int
+process_tc(int, olsr_u8_t, union olsr_ip_addr *, union tc_message *);
+
+int
+process_mid(int, olsr_u8_t, union olsr_ip_addr *, union mid_message *);
+
+int
+process_hna(int, olsr_u8_t, union olsr_ip_addr *, union hna_message *);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/main.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/main.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/main.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/main.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,146 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "common.h"
+#include "main.h"
+#include "ipc.h"
+
+int
+main (int argc, char *argv[])
+{
+  struct hostent *hp;
+  struct in_addr in;
+  struct sockaddr_in pin;
+
+#ifdef WIN32
+  WSADATA WsaData;
+#endif
+  GtkWidget *main_window;
+
+#ifdef WIN32
+  if (WSAStartup(0x0202, &WsaData))
+    {
+      fprintf(stderr, "Could not initialize WinSock.\n");
+      exit(1);
+    }
+#endif
+
+  
+  /* Get IP */
+  if ((hp = gethostbyname(argc > 1 ? argv[1] : "localhost")) == 0) 
+    {
+      fprintf(stderr, "Not a valid host \"%s\"\n", argv[1]);
+      exit(1);
+    }
+  
+  in.s_addr=((struct in_addr *)(hp->h_addr))->s_addr;
+  printf("Address: %s\n", inet_ntoa(in));
+  
+  /* fill in the socket structure with host information */
+  memset(&pin, 0, sizeof(pin));
+  pin.sin_family = AF_INET;
+  pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
+  pin.sin_port = htons(IPC_PORT);
+  
+  gtk_init (&argc, &argv);
+
+  init_nodes();
+
+  freeze_packets = 1;
+  display_dec = 1;
+
+  /* "Failsafe" values */
+  ipversion = AF_INET;
+  ipsize = sizeof(struct in_addr);
+
+  main_window = create_main_window ();
+  gtk_widget_show (main_window);
+
+  printf("Done building GUI\n");
+
+  memset(&main_addr, 0, sizeof(union olsr_ip_addr));
+  memset(&null_addr, 0, sizeof(union olsr_ip_addr));
+
+  /* Terminate signal */
+  signal(SIGINT, shutdown_);  
+
+  /* Init node timeout */
+  nodes_timeout = NEIGHB_HOLD_TIME_NW;
+  init_timer((olsr_u32_t) (nodes_timeout * 1000), &hold_time_nodes);
+
+  ipc_connect(&pin);
+
+  add_timeouts();
+
+  gtk_main ();
+  return 0;
+}
+
+
+
+/*
+ *Timeouts
+ */
+
+int
+add_timeouts()
+{
+
+  /*
+   *Check socket for messages every IPC_INTERVAL
+   *milliseconds
+   */
+  gtk_timeout_add(IPC_INTERVAL, ipc_timeout, NULL);
+
+
+  /*
+   *Time out nodes
+   */
+  timeouts = 5; /* Wait 5 times befor starting timing out nodes */
+  gtk_timeout_add(TOP_HOLD_TIME, time_out_nodes, NULL);
+
+
+ return 1;
+}
+
+
+
+gint ipc_timeout(gpointer data)
+{
+
+  ipc_read();
+  return 1;
+}
+
+
+
+void
+shutdown_(int signal)
+{
+  printf("Cleaning up...\n");
+
+  if(ipc_close() < 0)
+    printf("Could not close socket!\n");
+
+  printf("BYE-BYE!\n");
+  exit(signal);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/main.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/main.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/main.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/main.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,37 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <signal.h>
+
+int timeouts;
+
+
+int
+add_timeouts();
+
+
+gint
+ipc_timeout(gpointer);
+
+
+void
+shutdown_(int);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/nodes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/nodes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/nodes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/nodes.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,739 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "common.h"
+#include "nodes.h"
+#include <math.h>
+
+
+void
+init_nodes()
+{
+
+  nodes.next = &nodes;
+  nodes.prev = &nodes;
+}
+
+/*
+ *Insert a new node in the list
+ *NB! The list is NOT checked for duplicates!!
+ */
+struct node *
+insert_node(struct node *n, olsr_u8_t vtime)
+{
+  struct node *new_node;
+
+  printf("Inserting node %s\n", ip_to_string((union olsr_ip_addr *)&n->addr));
+
+  if((new_node = malloc(sizeof(struct node))) == 0)
+    {
+      fprintf(stderr, "OUT OF MEMORY!\n");
+      exit(1);
+    }
+
+  memcpy(new_node, n, sizeof(struct node));
+  
+  /* queue */
+  nodes.next->prev = new_node;
+  new_node->next = nodes.next;
+  nodes.next = new_node;
+  new_node->prev = &nodes;
+
+  new_node->hna.next = &new_node->hna;
+  new_node->hna.prev = &new_node->hna;
+  new_node->mid.next = &new_node->mid;
+  new_node->mid.prev = &new_node->mid;
+  new_node->mpr.next = &new_node->mpr;
+  new_node->mpr.prev = &new_node->mpr;
+
+
+  update_timer_node(&n->addr, vtime);
+
+  return new_node;
+}
+
+
+/**
+ *Add a new node to the set
+ */
+int
+add_node(union olsr_ip_addr *node, olsr_u8_t vtime)
+{
+  struct node new;
+  struct node *tmp_nodes;
+  struct timeval tmp_timer;
+  double dbl_time;
+  olsr_u32_t time_value;
+  struct mid *tmp_mid;
+
+  dbl_time = me_to_double(vtime);
+  time_value = (olsr_u32_t) dbl_time*1000;
+
+  tmp_timer.tv_sec = time_value/1000;
+  tmp_timer.tv_usec = (time_value-(tmp_timer.tv_sec*1000)) * 1000;   
+
+  /* Check if node exists */
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  //printf("updating timer for node %s\n", ip_to_string(node));
+	  //printf("Updatimng timer for: %s\n", ip_to_string(node));
+	  //printf("Secs: %d, usecs: %d\n", (int)tmp_timer.tv_sec, (int)tmp_timer.tv_usec);
+	  gettimeofday(&now, (struct timezone *)NULL);
+	  timeradd(&now, &tmp_timer, &tmp_nodes->timer);
+	  return 0; 
+	}
+      /* Check MID */
+      for(tmp_mid = tmp_nodes->mid.next;
+	  tmp_mid != &tmp_nodes->mid;
+	  tmp_mid = tmp_mid->next)
+	{
+	  if(memcmp(&tmp_mid->alias, node, ipsize) == 0)
+	    {
+	      //printf("updating timer for node %s\n", ip_to_string(node));
+	      //printf("Updatimng timer for (MID): %s\n", ip_to_string(&tmp_nodes->addr));
+	      //printf("Secs: %d, usecs: %d\n", (int)tmp_timer.tv_sec, (int)tmp_timer.tv_usec);
+	      gettimeofday(&now, (struct timezone *)NULL);
+	      timeradd(&now, &tmp_timer, &tmp_nodes->timer);
+	      return 0; 
+	    }
+	}
+    }
+
+  /* New node */
+  memset(&new, 0, sizeof(struct node));
+  memcpy(&new.addr, node, ipsize);
+  new.display = 1;
+  printf("1:");
+  insert_node(&new, vtime);
+  update_nodes_list(&new);
+ 
+  return 1;
+}
+
+
+int
+update_timer_node(union olsr_ip_addr *node, olsr_u8_t vtime)
+{
+  struct node *tmp_nodes;
+  struct timeval tmp_timer;
+  double dbl_time;
+  olsr_u32_t time_value;
+
+  dbl_time = me_to_double(vtime);
+  time_value = (olsr_u32_t) dbl_time*1000;
+
+  tmp_timer.tv_sec = time_value/1000;
+  tmp_timer.tv_usec = (time_value-(tmp_timer.tv_sec*1000)) * 1000;   
+
+  //printf("Updatimng timer for: %s\n", ip_to_string(node));
+  //printf("Secs: %d, usecs: %d\n", (int)tmp_timer.tv_sec, (int)tmp_timer.tv_usec);
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  //printf("updating timer for node %s\n", ip_to_string(node));
+	  gettimeofday(&now, (struct timezone *)NULL);
+	  timeradd(&now, &tmp_timer, &tmp_nodes->timer);
+	  if(tmp_nodes->display)
+	    update_nodes_list(tmp_nodes);
+	  return 1; 
+	}
+    }
+  
+  return 0;
+}
+
+
+/**
+ *Updates the hold time for the mpr 'mpr' registered on
+ *the node 'node'. Adds the mpr to the node if not already
+ *registered.
+ *@param node the node that has chosen the MPR
+ *@param mpr the MPR chosen by the node
+ *@return 0 if node was added, 1 if not
+ */
+int
+update_timer_mpr(union olsr_ip_addr *node, union olsr_ip_addr *mpr, olsr_u8_t vtime)
+{
+  struct node *tmp_nodes;
+  struct mpr *tmp_mpr;
+  struct timeval tmp_timer;
+  double dbl_time;
+  olsr_u32_t time_value;
+
+  dbl_time = me_to_double(vtime);
+  time_value = (olsr_u32_t) dbl_time*1000;
+
+  tmp_timer.tv_sec = time_value/1000;
+  tmp_timer.tv_usec = (time_value-(tmp_timer.tv_sec*1000)) * 1000;   
+
+  //printf("Updatimng MPR timer for: %s\n", ip_to_string(node));
+  //printf("Secs: %d, usecs: %d\n", (int)tmp_timer.tv_sec, (int)tmp_timer.tv_usec);
+
+  //printf("Updatimng timer for: %s\n", ip_to_string(node));
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  for(tmp_mpr = tmp_nodes->mpr.next;
+	      tmp_mpr != &tmp_nodes->mpr;
+	      tmp_mpr = tmp_mpr->next)
+	    {
+	      if(memcmp(&tmp_mpr->addr, mpr, ipsize) == 0)
+		{
+		  //printf("updating timer for MPR %s ", ip_to_string(mpr));
+		  //printf("node %s\n", ip_to_string(node));
+		  gettimeofday(&now, (struct timezone *)NULL);
+		  timeradd(&now, &tmp_timer, &tmp_mpr->timer);
+		  return 1; 
+		}
+	    }
+	  /* Only add if parent is added */
+	  add_mpr(node, mpr, &tmp_timer);
+	  return 0;
+	}
+    }
+
+  return 0;
+}
+
+
+
+
+int
+add_mid_node(union olsr_ip_addr *node, union olsr_ip_addr *alias, olsr_u8_t vtime)
+{
+
+  struct node *tmp_nodes;
+  struct mid *tmp_mid;
+  struct node new, *inserted;
+
+  //printf("MID_add: %s\n", ip_to_string(alias));
+
+  //update_timer_node(node, vtime);
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  for(tmp_mid = tmp_nodes->mid.next;
+	      tmp_mid != &tmp_nodes->mid;
+	      tmp_mid = tmp_mid->next)
+	    {
+	      if(memcmp(&tmp_mid->alias, alias, ipsize) == 0)
+		return 0;
+	    }
+
+	  /* we didn't find the address */
+	  printf("(1)NEW MID %s ", ip_to_string(alias));
+	  printf("ADDED FOR %s\n", ip_to_string(node));
+	  if((tmp_mid = malloc(sizeof(struct mid))) == 0)
+	    {
+	      fprintf(stderr, "OUT OF MEMORY\n");
+	      exit(1);
+	    }
+
+	  memcpy(&tmp_mid->alias, alias, ipsize);
+
+	  tmp_nodes->mid.next->prev = tmp_mid;
+	  tmp_mid->next = tmp_nodes->mid.next;
+	  tmp_nodes->mid.next = tmp_mid;
+	  tmp_mid->prev = &tmp_nodes->mid;
+
+	  remove_node_addr(alias); // Remove if already registered as a node
+	  
+	  update_nodes_list(tmp_nodes);
+	  return 1; 
+
+	}
+    }
+
+
+
+  /*New node */
+
+  printf("ADDING NEW NODE %s FROM MID...\n", ip_to_string(node));
+  /* We don't know wery much... */
+  memset(&new, 0, sizeof(struct node));
+  memcpy(&new.addr, node, ipsize);
+  inserted = insert_node(&new, vtime);
+
+  if((tmp_mid = malloc(sizeof(struct mid))) == 0)
+    {
+      fprintf(stderr, "OUT OF MEMORY!\n");
+      exit(1);
+    }
+
+  memcpy(&tmp_mid->alias, alias, ipsize);
+
+  tmp_mid->next = &inserted->mid;
+  tmp_mid->prev = &inserted->mid;
+  inserted->mid.next = tmp_mid;
+  inserted->mid.prev = tmp_mid;
+
+  update_nodes_list(inserted);
+
+  return 2;
+}
+
+
+int
+add_hna_node(union olsr_ip_addr *node, union olsr_ip_addr *net, union olsr_ip_addr *mask, olsr_u8_t vtime)
+{
+
+  struct node *tmp_nodes;
+  struct hna *tmp_hna;
+  struct node new, *inserted;
+
+  //printf("HNA: %s\n", ip_to_string(&net));
+
+  update_timer_node(node, vtime);
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  for(tmp_hna = tmp_nodes->hna.next;
+	      tmp_hna != &tmp_nodes->hna;
+	      tmp_hna = tmp_hna->next)
+	    {
+	      if((memcmp(&tmp_hna->net, net, ipsize) == 0) && (memcmp(&tmp_hna->mask, mask, ipsize) == 0))
+		return 0;
+	    }
+
+	  //printf("NEW HNA ADDED FOR %s ", ip_to_string(node));
+	  //printf("net: %s \n", ip_to_string(&net));
+	  /* we didn't find the address */
+	  if((tmp_hna = malloc(sizeof(struct hna))) == 0)
+	    {
+	      fprintf(stderr, "OUT OF MEMORY\n");
+	      exit(1);
+	    }
+
+	  memcpy(&tmp_hna->net, net, ipsize);
+	  memcpy(&tmp_hna->mask, mask, ipsize);
+
+	  /* queue */
+	  tmp_nodes->hna.next->prev = tmp_hna;
+	  tmp_hna->next = tmp_nodes->hna.next;
+	  tmp_nodes->hna.next = tmp_hna;
+	  tmp_hna->prev = &tmp_nodes->hna;
+	  
+	  update_nodes_list(tmp_nodes);
+	  return 1; 
+	}
+    }
+
+
+
+  printf("ADDING NEW NODE %s FROM HNA...\n", ip_to_string(node));
+  /* We don't know wery much... */
+  memset(&new, 0, sizeof(struct node));
+  memcpy(&new.addr, node, ipsize);
+  inserted = insert_node(&new, vtime);
+
+  if((tmp_hna = malloc(sizeof(struct hna))) == 0)
+    {
+      fprintf(stderr, "OUT OF MEMORY!\n");
+      exit(1);
+    }
+
+  memcpy(&tmp_hna->net, net, ipsize);
+  memcpy(&tmp_hna->mask, mask, ipsize);
+
+  tmp_hna->next = &inserted->hna;
+  tmp_hna->prev = &inserted->hna;
+  inserted->hna.next = tmp_hna;
+  inserted->hna.prev = tmp_hna;
+
+  update_nodes_list(inserted);
+
+  return 2;
+}
+
+
+/**
+ *Add the MPR mpr to the node nodes selected MPRs.
+ *Nodes are NOT added if they are not yet registered!
+ *
+ *@param node the node that has chosen an MPR
+ *@param mpr the MPR choosen by node
+ *@return negative if node already registered or node not found
+ */
+int
+add_mpr(union olsr_ip_addr *node, union olsr_ip_addr *mpr, struct timeval *tmp_timer)
+{
+
+  struct node *tmp_nodes;
+  struct mpr *mprs;
+  struct mpr *tmp_mpr;
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  for(mprs = tmp_nodes->mpr.next;
+	      mprs != &tmp_nodes->mpr;
+	      mprs = mprs->next)
+	    {
+	      if(memcmp(&mprs->addr, mpr, ipsize) == 0)
+		  return 0;
+	    }
+
+	  //printf("Adding MPR %s to ", ip_to_string(mpr));
+	  //printf("%s\n", ip_to_string(node));
+	  /* Add mpr */
+
+	  if((tmp_mpr = malloc(sizeof(struct mpr))) == 0)
+	    {
+	      fprintf(stderr, "OUT OF MEMORY\n");
+	      exit(1);
+	    }
+
+	  memcpy(&tmp_mpr->addr, mpr, ipsize);
+
+	  gettimeofday(&now, (struct timezone *)NULL);
+	  timeradd(&now, tmp_timer, &tmp_mpr->timer);
+
+	  /* queue */
+	  tmp_nodes->mpr.next->prev = tmp_mpr;
+	  tmp_mpr->next = tmp_nodes->mpr.next;
+	  tmp_nodes->mpr.next = tmp_mpr;
+	  tmp_mpr->prev = &tmp_nodes->mpr;
+
+	  update_nodes_list(tmp_nodes);
+	  return 1; 
+
+	}
+    }
+
+  return 1;
+}
+
+
+
+
+int
+remove_node(struct node *node)
+{
+  struct hna *tmp_hna, *tmp_hna2;
+  struct mid *tmp_mid, *tmp_mid2;
+  struct mpr *tmp_mpr, *tmp_mpr2;
+
+  printf("Remove node %s\n", ip_to_string(&node->addr));
+
+
+  tmp_hna = node->hna.next;
+  while(tmp_hna != &node->hna)
+    {
+      tmp_hna2 = tmp_hna;
+      tmp_hna = tmp_hna->next;
+      free(tmp_hna2);
+    }
+  tmp_mpr = node->mpr.next;
+  while(tmp_mpr != &node->mpr)
+    {
+      tmp_mpr2 = tmp_mpr;
+      tmp_mpr = tmp_mpr->next;
+      free(tmp_mpr2);
+    }
+  tmp_mid = node->mid.next;
+  while(tmp_mid != &node->mid)
+    {
+      tmp_mid2 = tmp_mid;
+      tmp_mid = tmp_mid->next;
+      free(tmp_mid2);
+    }
+  
+  /* Gemove form GUI */
+  remove_nodes_list(&node->addr);
+  
+  /* Dequeue */
+  node->prev->next = node->next;
+  node->next->prev = node->prev;
+  
+  free(node);
+
+  return 1;  
+}
+
+
+
+
+
+
+/*
+ * Remove based on address
+ */
+
+int
+remove_node_addr(union olsr_ip_addr *node)
+{
+  struct node *tmp_nodes;
+  struct hna *tmp_hna, *tmp_hna2;
+  struct mid *tmp_mid, *tmp_mid2;
+  struct mpr *tmp_mpr, *tmp_mpr2;
+
+  printf("Remove node %s\n", ip_to_string(node));
+
+
+  tmp_nodes = nodes.next;
+
+  while(tmp_nodes != &nodes)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  printf("(2)Deleting node %s\n", ip_to_string((union olsr_ip_addr *)&tmp_nodes->addr));
+
+	  tmp_hna = tmp_nodes->hna.next;
+	  while(tmp_hna != &tmp_nodes->hna)
+	    {
+	      tmp_hna2 = tmp_hna;
+	      tmp_hna = tmp_hna->next;
+	      free(tmp_hna2);
+	    }
+	  tmp_mpr = tmp_nodes->mpr.next;
+	  while(tmp_mpr != &tmp_nodes->mpr)
+	    {
+	      tmp_mpr2 = tmp_mpr;
+	      tmp_mpr = tmp_mpr->next;
+	      free(tmp_mpr2);
+	    }
+	  tmp_mid = tmp_nodes->mid.next;
+	  while(tmp_mid != &tmp_nodes->mid)
+	    {
+	      tmp_mid2 = tmp_mid;
+	      tmp_mid = tmp_mid->next;
+	      free(tmp_mid2);
+	    }
+
+	  /* Gemove form GUI */
+	  remove_nodes_list(&tmp_nodes->addr);
+
+	  /* Dequeue */
+	  tmp_nodes->prev->next = tmp_nodes->next;
+	  tmp_nodes->next->prev = tmp_nodes->prev;
+
+	  free(tmp_nodes);
+
+	  return 1;
+	}
+
+      tmp_nodes = tmp_nodes->next;
+    }
+
+  return 0;
+}
+
+
+
+
+struct node *
+find_node(char *ip)
+{
+  struct node *tmp_nodes;
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(strcmp(ip_to_string((union olsr_ip_addr *)&tmp_nodes->addr), ip) == 0)
+	return tmp_nodes;
+    }
+
+  return NULL;
+}
+
+
+struct node *
+find_node_t(union olsr_ip_addr *ip)
+{
+  struct node *tmp_nodes;
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, ip, ipsize) == 0)
+	return tmp_nodes;
+    }
+
+
+  return 0;
+}
+
+
+/*
+ *Remove timed out nodes
+ */
+gint
+time_out_nodes(gpointer data)
+{
+  struct node *tmp_nodes;
+  struct node *node_to_delete;
+
+  /* Wait before starting timing out */
+  if(timeouts)
+    {
+      timeouts--;
+      //printf("Waiting...\n");
+      return 1;
+    }
+
+  //printf("Timing out nodes...\n");
+  gettimeofday(&now, (struct timezone *)NULL);
+
+  tmp_nodes = nodes.next;
+
+  while(tmp_nodes != &nodes)
+    {
+      //printf("%s: %6d < %6d\n", ip_to_string(&tmp_nodes->addr), tmp_nodes->timer.tv_sec, now.tv_sec);
+      if(timercmp(&tmp_nodes->timer,&now,<))
+	{
+	  printf("Node %s timed out...\n", ip_to_string((union olsr_ip_addr *)&tmp_nodes->addr));
+	  node_to_delete = tmp_nodes;
+
+	  tmp_nodes = tmp_nodes->next;
+
+	  remove_nodes_list(&node_to_delete->addr);
+	  remove_node(node_to_delete);
+	} 
+      else
+	tmp_nodes = tmp_nodes->next;
+    }
+
+  return 1;
+}
+
+
+
+/**
+ *Timeout MPRs for a given node. Only called when user
+ *is to see the registered MPRs of the node.
+ *@param node the node whom MPRs should be timed out
+ *@return negative if node not found
+ */
+int
+time_out_mprs(union olsr_ip_addr *node)
+{
+
+  struct node *tmp_nodes;
+  struct mpr *mpr_to_delete;
+  struct mpr *tmp_mpr;
+
+  gettimeofday(&now, (struct timezone *)NULL);
+
+
+  /* W A R N I N G !
+   *
+   * THIS ALGORITHM HAS NOT BEEN TESTED PROPERLY!!!!!!
+   * -Andreas
+   */
+
+  for(tmp_nodes = nodes.next;
+      tmp_nodes != &nodes;
+      tmp_nodes = tmp_nodes->next)
+    {
+      if(memcmp(&tmp_nodes->addr, node, ipsize) == 0)
+	{
+	  tmp_mpr = tmp_nodes->mpr.next;
+	 
+	  while(tmp_mpr != &tmp_nodes->mpr)
+	    {
+	      if(timercmp(&tmp_mpr->timer,&now,<))
+		{
+		  printf("MPR %s OF NODE ", ip_to_string((union olsr_ip_addr *)&tmp_mpr->addr));
+		  printf("%s TIMIED OUT ", ip_to_string((union olsr_ip_addr *)&tmp_nodes->addr));fflush(stdout);
+
+		  mpr_to_delete = tmp_mpr;
+		  tmp_mpr = tmp_mpr->next;
+
+		  /* Dequeue */
+		  mpr_to_delete->next->prev = mpr_to_delete->prev;
+		  mpr_to_delete->prev->next = mpr_to_delete->next;
+		  /* Delete */
+		  free(mpr_to_delete);
+		}
+	      else
+		tmp_mpr = tmp_mpr->next;
+	    }
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+
+
+void
+init_timer(olsr_u32_t time_value, struct timeval *hold_timer)
+{ 
+  olsr_u16_t  time_value_sec=0;
+  olsr_u16_t  time_value_msec=0;
+
+  time_value_sec=time_value/1000;
+  time_value_msec=time_value-(time_value_sec*1000);
+
+  hold_timer->tv_sec=time_value_sec;
+  hold_timer->tv_usec=time_value_msec*1000; 
+  
+}
+
+
+/**
+ *Function that converts a mantissa/exponent 8bit value back
+ *to double as described in RFC3626:
+ *
+ * value = C*(1+a/16)*2^b [in seconds]
+ *
+ *  where a is the integer represented by the four highest bits of the
+ *  field and b the integer represented by the four lowest bits of the
+ *  field.
+ *
+ *@param me the 8 bit mantissa/exponen value
+ *
+ *@return a double value
+ */
+double
+me_to_double(olsr_u8_t me)
+{
+  int a = me>>4;
+  int b = me - a*16;
+  return (double)(VTIME_SCALE_FACTOR*(1+(double)a/16)*(double)pow(2,b));
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/nodes.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/nodes.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/nodes.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/nodes.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ *Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ *Node information
+ */
+
+#include <sys/time.h>
+//#include <time.h>
+
+
+struct timeval now;
+struct timeval hold_time_nodes; /* Timeout for all nodes */
+
+/* The node list */
+struct node nodes;
+
+
+struct node *
+insert_node(struct node *, olsr_u8_t);
+
+
+int
+remove_node(struct node *);
+
+int
+remove_node_addr(union olsr_ip_addr *);
+
+double
+me_to_double(olsr_u8_t);
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/olsr.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/olsr.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/olsr.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/olsr.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,25 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "common.h"
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/olsr_protocol.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/olsr_protocol.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/olsr_protocol.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/olsr_protocol.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,437 @@
+/*
+ * OLSR ad-hoc routing table management protocol
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of the UniK OLSR daemon.
+ *
+ * The UniK OLSR daemon is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The UniK OLSR daemon 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 the UniK OLSR daemon; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ *Values and packet formats as proposed in RFC3626 and misc. values and
+ *data structures used by the UniK olsr daemon.
+ */
+
+#ifndef _PROTOCOLS_OLSR_H
+#define	_PROTOCOLS_OLSR_H
+
+/* Port for OLSR to use */
+
+#define OLSRPORT       698
+
+/* Default IPv6 multicast address */
+
+#define OLSR_IPV6_MULTICAST_ADDR "ff05::15"
+
+/* types */
+#include <sys/types.h>
+
+#ifdef WIN32
+typedef unsigned char   olsr_u8_t;
+typedef unsigned short  olsr_u16_t;
+typedef unsigned int    olsr_u32_t;
+typedef char            olsr_8_t;
+typedef short           olsr_16_t;
+typedef int             olsr_32_t;
+#else
+typedef u_int8_t        olsr_u8_t;
+typedef u_int16_t       olsr_u16_t;
+typedef u_int32_t       olsr_u32_t;
+typedef int8_t          olsr_8_t;
+typedef int16_t         olsr_16_t;
+typedef int32_t         olsr_32_t;
+#endif
+
+/* IPv6 address format in6_addr */
+#include <netinet/in.h>
+
+union olsr_ip_addr
+{
+  olsr_u32_t v4;
+  struct in6_addr v6;
+};
+
+
+/*
+ *Emission Intervals
+ */
+
+#define HELLO_INTERVAL        2
+#define HELLO_INTERVAL_NW     HELLO_INTERVAL * 2
+#define REFRESH_INTERVAL      2
+#define TC_INTERVAL           5
+#define MID_INTERVAL          TC_INTERVAL
+#define HNA_INTERVAL          TC_INTERVAL
+
+/*
+ *Holding Time
+ */
+
+#define NEIGHB_HOLD_TIME      3 * REFRESH_INTERVAL
+/*extra: time to delete for non-wireless interfaces */
+#define NEIGHB_HOLD_TIME_NW   NEIGHB_HOLD_TIME * 2
+#define TOP_HOLD_TIME         3 * TC_INTERVAL
+#define DUP_HOLD_TIME         30
+#define MID_HOLD_TIME         3 * MID_INTERVAL
+#define HNA_HOLD_TIME         3 * HNA_INTERVAL
+
+/*
+ * Scaling factor
+ */
+
+#define VTIME_SCALE_FACTOR    0.0625
+
+/*
+ *Message Types
+ */
+
+#define HELLO_MESSAGE         1
+#define TC_MESSAGE            2
+#define MID_MESSAGE           3
+#define HNA_MESSAGE           4
+#define MAX_MESSAGE           4
+
+/*
+ *Link Types
+ */
+
+#define UNSPEC_LINK           0
+#define ASYM_LINK             1
+#define SYM_LINK              2
+#define LOST_LINK             3
+#define MAX_LINK              3
+
+/*
+ *Neighbor Types
+ */
+
+#define NOT_NEIGH             0
+#define SYM_NEIGH             1
+#define MPR_NEIGH             2
+#define MAX_NEIGH             2
+
+/*
+ *Neighbor status
+ */
+
+#define NOT_SYM               0
+#define SYM                   1
+
+/*
+ *Link Hysteresis
+ */
+
+#define HYST_THRESHOLD_HIGH   0.8
+#define HYST_THRESHOLD_LOW    0.3
+#define HYST_SCALING          0.5
+
+/*
+ *Willingness
+ */
+
+#define WILL_NEVER            0
+#define WILL_LOW              1
+#define WILL_DEFAULT          3
+#define WILL_HIGH             6
+#define WILL_ALWAYS           7
+
+/*
+ *Misc. Constants
+ */
+
+#define TC_REDUNDANCY         0
+#define MPR_COVERAGE          1
+#define MAXJITTER             HELLO_INTERVAL / 4
+#define MAX_TTL               0xff
+
+/*
+ *Sequence numbering
+ */
+
+/* Seqnos are 16 bit values */
+
+#define MAXVALUE 0xFFFF
+
+/* Macro for checking seqnos "wraparound" */
+#define SEQNO_GREATER_THAN(s1, s2)                \
+        (((s1 > s2) && (s1 - s2 <= (MAXVALUE/2))) \
+     || ((s2 > s1) && (s2 - s1 > (MAXVALUE/2))))
+
+
+
+/*
+ * Macros for creating and extracting the neighbor 
+ * and link type information from 8bit link_code
+ * data as passed in HELLO messages
+ */
+
+#define CREATE_LINK_CODE(status, link) (link | (status<<2))
+
+#define EXTRACT_STATUS(link_code) ((link_code & 0xC)>>2)
+
+#define EXTRACT_LINK(link_code) (link_code & 0x3)
+
+
+/***********************************************
+ *           OLSR packet definitions           *
+ ***********************************************/
+
+
+/*
+ *The HELLO message
+ */
+
+/*
+ *Hello info
+ */
+struct hellinfo 
+{
+  olsr_u8_t   link_code;
+  olsr_u8_t   reserved;
+  olsr_u16_t  size;
+  olsr_u32_t  neigh_addr[1]; /* neighbor IP address(es) */
+};
+
+struct hellomsg 
+{
+  olsr_u16_t      reserved;
+  olsr_u8_t       htime;
+  olsr_u8_t       willingness;
+  struct hellinfo hell_info[1];
+};
+
+/*
+ *IPv6
+ */
+
+struct hellinfo6
+{
+  olsr_u8_t       link_code;
+  olsr_u8_t       reserved;
+  olsr_u16_t      size;
+  struct in6_addr neigh_addr[1]; /* neighbor IP address(es) */
+};
+
+struct hellomsg6
+{
+  olsr_u16_t         reserved;
+  olsr_u8_t          htime;
+  olsr_u8_t          willingness;
+  struct hellinfo6 hell_info[1];
+};
+
+
+
+
+
+/*
+ * Topology Control packet
+ */
+
+struct neigh_info
+{
+  olsr_u32_t       addr;
+};
+
+
+struct olsr_tcmsg 
+{
+  olsr_u16_t        ansn;
+  olsr_u16_t        reserved;
+  struct neigh_info neigh[1];
+};
+
+
+/*
+ *IPv6
+ */
+
+struct neigh_info6
+{
+  struct in6_addr      addr;
+};
+
+
+struct olsr_tcmsg6
+{
+  olsr_u16_t           ansn;
+  olsr_u16_t           reserved;
+  struct neigh_info6 neigh[1];
+};
+
+
+
+
+
+/*
+ *Multiple Interface Declaration message
+ */
+
+/* 
+ * Defined as s struct for further expansion 
+ * For example: do we want to tell what type of interface
+ * is associated whit each address?
+ */
+struct midaddr
+{
+  olsr_u32_t addr;
+};
+
+
+struct midmsg 
+{
+  struct midaddr mid_addr[1];
+};
+
+
+/*
+ *IPv6
+ */
+struct midaddr6
+{
+  struct in6_addr addr;
+};
+
+
+struct midmsg6
+{
+  struct midaddr6 mid_addr[1];
+};
+
+
+
+
+
+
+/*
+ * Host and Network Association message
+ */
+struct hnapair
+{
+  olsr_u32_t   addr;
+  olsr_u32_t   netmask;
+};
+
+struct hnamsg
+{
+  struct hnapair hna_net[1];
+};
+
+/*
+ *IPv6
+ */
+
+struct hnapair6
+{
+  struct in6_addr   addr;
+  struct in6_addr   netmask;
+};
+
+struct hnamsg6
+{
+  struct hnapair6 hna_net[1];
+};
+
+
+
+
+
+/*
+ * OLSR message (several can exist in one OLSR packet)
+ */
+
+struct olsrmsg
+{
+  olsr_u8_t     olsr_msgtype;
+  olsr_u8_t     olsr_vtime;
+  olsr_u16_t    olsr_msgsize;
+  olsr_u32_t    originator;
+  olsr_u8_t     ttl;
+  olsr_u8_t     hopcnt;
+  olsr_u16_t    seqno;
+
+  union 
+  {
+    struct hellomsg hello;
+    struct olsr_tcmsg    tc;
+    struct hnamsg   hna;
+    struct midmsg   mid;
+  } message;
+
+};
+
+/*
+ *IPv6
+ */
+
+struct olsrmsg6
+{
+  olsr_u8_t        olsr_msgtype;
+  olsr_u8_t        olsr_vtime;
+  olsr_u16_t       olsr_msgsize;
+  struct in6_addr  originator;
+  olsr_u8_t        ttl;
+  olsr_u8_t        hopcnt;
+  olsr_u16_t       seqno;
+
+  union 
+  {
+    struct hellomsg6 hello;
+    struct olsr_tcmsg6    tc;
+    struct hnamsg6   hna;
+    struct midmsg6   mid;
+  } message;
+
+};
+
+
+
+/*
+ * Generic OLSR packet
+ */
+
+struct olsr 
+{
+  olsr_u16_t	  olsr_packlen;		/* packet length */
+  olsr_u16_t	  olsr_seqno;
+  struct olsrmsg  olsr_msg[1];          /* variable messages */
+};
+
+
+struct olsr6
+{
+  olsr_u16_t	    olsr_packlen;        /* packet length */
+  olsr_u16_t	    olsr_seqno;
+  struct olsrmsg6   olsr_msg[1];         /* variable messages */
+};
+
+
+/* IPv4 <-> IPv6 compability */
+
+union olsr_message
+{
+  struct olsrmsg v4;
+  struct olsrmsg6 v6;
+};
+
+union olsr_packet
+{
+  struct olsr v4;
+  struct olsr6 v6;
+};
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/packet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/packet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/packet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/packet.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,126 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ *Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ *The list of cached packets
+ *
+ */
+
+#include "common.h"
+#include "packet.h"
+
+struct packnode *packets = NULL;
+int no_packets = 0;
+
+/*
+ *Add the contets of a packet to
+ *the cached packets
+ */
+int
+add_packet_to_buffer(union olsr_message *p, int size)
+{
+  struct packnode *tmp;
+  /* Should be the same for v4 and v6 */
+
+
+  /* If this is the first packet */
+  if(!packets)
+    {
+      //printf("Adding first packet\n");
+      packets = malloc(sizeof(struct packnode));
+      packets->packet = malloc(size);
+      memcpy(packets->packet, p, size);
+      packets->next = NULL;
+      no_packets++;
+      return 1;
+    }
+  else
+    {
+      /* If the buffer is not full */
+      if(no_packets < MAXPACKS)
+	{
+	  //printf("Buffer not filled yet..\n");
+	  tmp = packets;
+	  packets = malloc(sizeof(struct packnode));
+	  packets->packet = malloc(size);
+	  memcpy(packets->packet, p, size);
+	  packets->next = tmp;
+	  no_packets++;
+	  return 1;
+	}
+      /* If buffer is full */
+      else
+	{
+	  //printf("Buffer full - deleting...\n");
+	  tmp = packets;
+	  /* Find second last packet */
+	  while(tmp->next->next)
+	    {
+	      tmp = tmp->next;
+	    }
+	  /* Delete last packet */
+	  free(tmp->next->packet);
+	  free(tmp->next);
+	  tmp->next = NULL;
+
+	  /*Add the new packet */
+	  tmp = packets;
+	  packets = malloc(sizeof(struct packnode));
+	  packets->packet = malloc(size);
+	  memcpy(packets->packet, p, size);
+	  packets->next = tmp;
+	  return 1;
+	}
+
+    }
+  return 0;
+}
+
+
+
+/*
+ *Get the packet with index 'index'
+ */
+union olsr_message *
+get_packet(int index)
+{
+  int i = 0;
+  struct packnode *tmp;
+
+  if(index>MAXPACKS)
+    return 0;
+
+  if(index == 0)
+    return packets->packet;
+
+  tmp = packets;
+
+  while(i != index)
+    {
+      tmp = tmp->next;
+      i++;
+    }
+  return tmp->packet;
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/packet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/packet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/packet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/packet.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,76 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ *Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ *The list of cached packets
+ *
+ */
+
+#ifndef _PACKET_H
+#define _PACKET_H
+
+struct packnode
+{
+  union olsr_message *packet;
+  struct packnode *next;
+};
+
+
+
+/*
+ * Unions for IPv4 <-> IPv6 compability
+ */
+
+union hello_message
+{
+  struct hellomsg v4;
+  struct hellomsg6 v6;
+};
+
+
+union tc_message
+{
+  struct olsr_tcmsg v4;
+  struct olsr_tcmsg6 v6;
+};
+
+
+union mid_message
+{
+  struct midmsg v4;
+  struct midmsg6 v6;
+};
+
+
+
+union hna_message
+{
+  struct hnamsg v4;
+  struct hnamsg6 v6;
+};
+
+
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps/logo.xpm ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps/logo.xpm
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps/logo.xpm	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps/logo.xpm	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,2446 @@
+/* XPM */
+static char * logo_xpm[] = {
+"87 103 2340 2",
+"  	c #FFFFFF",
+". 	c #FBFBFB",
+"+ 	c #F8F8F8",
+"@ 	c #F4F4F4",
+"# 	c #F2F2F2",
+"$ 	c #FEFEFE",
+"% 	c #F5F5F5",
+"& 	c #FCFCFC",
+"* 	c #FAFAFA",
+"= 	c #F6F6F6",
+"- 	c #EAEAEA",
+"; 	c #CDCDCD",
+"> 	c #6F6F6F",
+", 	c #777777",
+"' 	c #343434",
+") 	c #040404",
+"! 	c #020202",
+"~ 	c #000000",
+"{ 	c #161616",
+"] 	c #545454",
+"^ 	c #727272",
+"/ 	c #AFAFAF",
+"( 	c #E6E6E6",
+"_ 	c #FDFDFD",
+": 	c #F0F0F0",
+"< 	c #F3F3F3",
+"[ 	c #D0D0D0",
+"} 	c #7F7F7F",
+"| 	c #2A2A2A",
+"1 	c #0A0A0A",
+"2 	c #030303",
+"3 	c #010101",
+"4 	c #050505",
+"5 	c #202020",
+"6 	c #7D7D7D",
+"7 	c #E1E1E1",
+"8 	c #EFEFEF",
+"9 	c #F7F7F7",
+"0 	c #929292",
+"a 	c #0D0D0D",
+"b 	c #111111",
+"c 	c #080808",
+"d 	c #060606",
+"e 	c #0B0B0B",
+"f 	c #1E1E1E",
+"g 	c #0E0E0E",
+"h 	c #313131",
+"i 	c #ADADAD",
+"j 	c #E3E3E3",
+"k 	c #DCDCDC",
+"l 	c #2B2B2B",
+"m 	c #070707",
+"n 	c #0C0C0C",
+"o 	c #D9D9D9",
+"p 	c #2D2D2D",
+"q 	c #353535",
+"r 	c #D4D4D4",
+"s 	c #F9F9F9",
+"t 	c #676767",
+"u 	c #565656",
+"v 	c #C3C3C3",
+"w 	c #171717",
+"x 	c #141414",
+"y 	c #303030",
+"z 	c #090909",
+"A 	c #A5A5A5",
+"B 	c #F1F1F1",
+"C 	c #4A4A4A",
+"D 	c #131313",
+"E 	c #292929",
+"F 	c #595959",
+"G 	c #5F5F5F",
+"H 	c #2F2F2F",
+"I 	c #272727",
+"J 	c #D2D2D2",
+"K 	c #252525",
+"L 	c #5B5B5B",
+"M 	c #454545",
+"N 	c #1D1D1D",
+"O 	c #A8A8A8",
+"P 	c #444444",
+"Q 	c #121212",
+"R 	c #181818",
+"S 	c #717171",
+"T 	c #0F0F0F",
+"U 	c #C8C8C8",
+"V 	c #3C3C3C",
+"W 	c #828282",
+"X 	c #101010",
+"Y 	c #3E3E3E",
+"Z 	c #373737",
+"` 	c #848484",
+" .	c #5C5C5C",
+"..	c #484848",
+"+.	c #1A1A1A",
+"@.	c #747474",
+"#.	c #242424",
+"$.	c #434343",
+"%.	c #858585",
+"&.	c #6B6B6B",
+"*.	c #494949",
+"=.	c #474747",
+"-.	c #B7B7B7",
+";.	c #B4B4B4",
+">.	c #6D6D6D",
+",.	c #B9B9B9",
+"'.	c #B0B0B0",
+").	c #ABABAB",
+"!.	c #838383",
+"~.	c #4E4E4E",
+"{.	c #CFCFCF",
+"].	c #414141",
+"^.	c #C0C2C1",
+"/.	c #BEC0BF",
+"(.	c #C1C1C1",
+"_.	c #C5C5C5",
+":.	c #4B4A4F",
+"<.	c #56555B",
+"[.	c #010009",
+"}.	c #0B0715",
+"|.	c #01000B",
+"1.	c #04010C",
+"2.	c #010007",
+"3.	c #17161B",
+"4.	c #848683",
+"5.	c #C7CCC5",
+"6.	c #E0E6DC",
+"7.	c #E8EEE2",
+"8.	c #E5E5E5",
+"9.	c #B5B5B5",
+"0.	c #393939",
+"a.	c #ACACAC",
+"b.	c #C8C9CD",
+"c.	c #F1F2F6",
+"d.	c #EAEBED",
+"e.	c #DDDFDC",
+"f.	c #C2C4BF",
+"g.	c #282A25",
+"h.	c #000200",
+"i.	c #040000",
+"j.	c #050000",
+"k.	c #0E0A07",
+"l.	c #2E2A29",
+"m.	c #B4B0AF",
+"n.	c #FBF7F6",
+"o.	c #FAF6F5",
+"p.	c #EDE9E8",
+"q.	c #E2E2E2",
+"r.	c #707070",
+"s.	c #323232",
+"t.	c #F4F3F9",
+"u.	c #E6E7EC",
+"v.	c #959698",
+"w.	c #D0D2CF",
+"x.	c #F5FAF3",
+"y.	c #7A8074",
+"z.	c #0C1303",
+"A.	c #000900",
+"B.	c #030100",
+"C.	c #050200",
+"D.	c #090600",
+"E.	c #797471",
+"F.	c #DDD7D7",
+"G.	c #E3DADF",
+"H.	c #6F656D",
+"I.	c #3E343D",
+"J.	c #212121",
+"K.	c #EDEDED",
+"L.	c #C7C7C7",
+"M.	c #878787",
+"N.	c #DBDBDB",
+"O.	c #9FA1A0",
+"P.	c #303231",
+"Q.	c #08090B",
+"R.	c #515256",
+"S.	c #AEB2B5",
+"T.	c #ADB1B0",
+"U.	c #0A0F0B",
+"V.	c #080C0D",
+"W.	c #000102",
+"X.	c #000002",
+"Y.	c #88888A",
+"Z.	c #D7D7D9",
+"`.	c #636164",
+" +	c #030002",
+".+	c #030004",
+"++	c #808080",
+"@+	c #E8E8E8",
+"#+	c #2A2E20",
+"$+	c #000300",
+"%+	c #73727A",
+"&+	c #797785",
+"*+	c #FFFCFF",
+"=+	c #080413",
+"-+	c #130F1E",
+";+	c #000212",
+">+	c #00010F",
+",+	c #010713",
+"'+	c #737A82",
+")+	c #CED3D6",
+"!+	c #030905",
+"~+	c #0F160F",
+"{+	c #868686",
+"]+	c #EEEEEE",
+"^+	c #0B1403",
+"/+	c #000500",
+"(+	c #101211",
+"_+	c #413E47",
+":+	c #8D8592",
+"<+	c #E2D6E4",
+"[+	c #1C0F19",
+"}+	c #0A0002",
+"|+	c #000004",
+"1+	c #19181D",
+"2+	c #666867",
+"3+	c #A4A9A5",
+"4+	c #000400",
+"5+	c #696969",
+"6+	c #475148",
+"7+	c #060D06",
+"8+	c #0D0707",
+"9+	c #433834",
+"0+	c #C9B7A9",
+"a+	c #412D14",
+"b+	c #342000",
+"c+	c #3D2D09",
+"d+	c #544524",
+"e+	c #160800",
+"f+	c #4A3F2B",
+"g+	c #857D70",
+"h+	c #100B05",
+"i+	c #010000",
+"j+	c #939393",
+"k+	c #8D9798",
+"l+	c #000202",
+"m+	c #060000",
+"n+	c #0D0100",
+"o+	c #AF9C72",
+"p+	c #917B3F",
+"q+	c #A68E46",
+"r+	c #A98E41",
+"s+	c #9E833E",
+"t+	c #9F864E",
+"u+	c #5A441B",
+"v+	c #BDAB95",
+"w+	c #0D0000",
+"x+	c #16070E",
+"y+	c #0B000C",
+"z+	c #FDF7F7",
+"A+	c #FFFEFF",
+"B+	c #FEFFFF",
+"C+	c #FCFFFF",
+"D+	c #EFF5F5",
+"E+	c #070B0C",
+"F+	c #060709",
+"G+	c #100F14",
+"H+	c #E7EEF4",
+"I+	c #4D4D4F",
+"J+	c #0A0000",
+"K+	c #270A04",
+"L+	c #835A44",
+"M+	c #CC9D67",
+"N+	c #B0801E",
+"O+	c #FFD956",
+"P+	c #EBC548",
+"Q+	c #C79929",
+"R+	c #C38D2D",
+"S+	c #E9B059",
+"T+	c #EDB86C",
+"U+	c #A57B3F",
+"V+	c #462806",
+"W+	c #110000",
+"X+	c #0F0006",
+"Y+	c #746E72",
+"Z+	c #F2F6F5",
+"`+	c #FAFEFD",
+" @	c #383236",
+".@	c #080004",
+"+@	c #120411",
+"@@	c #040009",
+"#@	c #737373",
+"$@	c #FFFEFD",
+"%@	c #F8F6F7",
+"&@	c #070508",
+"*@	c #807585",
+"=@	c #E0D3CA",
+"-@	c #49360B",
+";@	c #B79A56",
+">@	c #E7C16C",
+",@	c #C69836",
+"'@	c #FFDA67",
+")@	c #E0AF2E",
+"!@	c #FFD06A",
+"~@	c #F4C166",
+"{@	c #EDB966",
+"]@	c #F6C370",
+"^@	c #FFD37A",
+"/@	c #F0CD73",
+"(@	c #C9AE5D",
+"_@	c #A8914B",
+":@	c #96753F",
+"<@	c #FAE2B6",
+"[@	c #E9DEC2",
+"}@	c #403933",
+"|@	c #0B0310",
+"1@	c #0F0B19",
+"2@	c #000104",
+"3@	c #000A00",
+"4@	c #F9F7F8",
+"5@	c #EFF3F2",
+"6@	c #252726",
+"7@	c #020001",
+"8@	c #030000",
+"9@	c #210303",
+"0@	c #BC9F75",
+"a@	c #D8BA58",
+"b@	c #EBCA3F",
+"c@	c #EDC42C",
+"d@	c #FFE04F",
+"e@	c #E4B029",
+"f@	c #FFD455",
+"g@	c #F3BB4A",
+"h@	c #F9C361",
+"i@	c #FBCB77",
+"j@	c #F9D07E",
+"k@	c #FCDA80",
+"l@	c #FFE180",
+"m@	c #FFDE7D",
+"n@	c #F6D377",
+"o@	c #FAC952",
+"p@	c #E9BF5B",
+"q@	c #B59656",
+"r@	c #1E0800",
+"s@	c #060007",
+"t@	c #0A0D1C",
+"u@	c #000600",
+"v@	c #000C00",
+"w@	c #5E5E5E",
+"x@	c #FEFAFB",
+"y@	c #FBFDFC",
+"z@	c #FCFEFB",
+"A@	c #FBFDFA",
+"B@	c #686765",
+"C@	c #0E0906",
+"D@	c #0B0301",
+"E@	c #5F3401",
+"F@	c #E4BB63",
+"G@	c #F1C73F",
+"H@	c #FFD730",
+"I@	c #F4C41C",
+"J@	c #F6C028",
+"K@	c #F0B831",
+"L@	c #FFD053",
+"M@	c #F7BF2C",
+"N@	c #F7C447",
+"O@	c #FBD373",
+"P@	c #FFE191",
+"Q@	c #FCDF93",
+"R@	c #F6D286",
+"S@	c #F7CB82",
+"T@	c #FFCE8C",
+"U@	c #FDCA4A",
+"V@	c #EDBA44",
+"W@	c #F8CC6D",
+"X@	c #A58650",
+"Y@	c #000007",
+"Z@	c #050F0E",
+"`@	c #3B3B3B",
+" #	c #FCFAFD",
+".#	c #FCFEFD",
+"+#	c #FEFFFD",
+"@#	c #F4F5F0",
+"##	c #7A7772",
+"$#	c #100805",
+"%#	c #322924",
+"&#	c #EFBF53",
+"*#	c #F3C343",
+"=#	c #FFCF3C",
+"-#	c #F5BF27",
+";#	c #FEC536",
+">#	c #FFCF4F",
+",#	c #F8BC42",
+"'#	c #FCC247",
+")#	c #FFCE48",
+"!#	c #FFCD5F",
+"~#	c #FCD47F",
+"{#	c #FADC96",
+"]#	c #FBDC99",
+"^#	c #FBD58C",
+"/#	c #FFD089",
+"(#	c #FFCF8C",
+"_#	c #FED271",
+":#	c #FCC95C",
+"<#	c #F7C554",
+"[#	c #E4BF67",
+"}#	c #503F14",
+"|#	c #0C0612",
+"1#	c #0F020C",
+"2#	c #D8D8D8",
+"3#	c #F5F5F7",
+"4#	c #FAFCF9",
+"5#	c #F6F5F0",
+"6#	c #6C6761",
+"7#	c #070000",
+"8#	c #50433D",
+"9#	c #F5C849",
+"0#	c #EEBE38",
+"a#	c #FDC93F",
+"b#	c #F3BA37",
+"c#	c #FFC34E",
+"d#	c #FFC555",
+"e#	c #FFD05C",
+"f#	c #F3BD41",
+"g#	c #FCC36C",
+"h#	c #FFCD85",
+"i#	c #FFD196",
+"j#	c #F4CE90",
+"k#	c #F6D284",
+"l#	c #FFDB7B",
+"m#	c #FFD168",
+"n#	c #F5BF55",
+"o#	c #E7BE6E",
+"p#	c #D8A53A",
+"q#	c #D69C1F",
+"r#	c #E6BB52",
+"s#	c #7D6831",
+"t#	c #0F0013",
+"u#	c #0F000C",
+"v#	c #9A9A9A",
+"w#	c #F7F7F9",
+"x#	c #FAFBF6",
+"y#	c #FBFAF5",
+"z#	c #908981",
+"A#	c #080000",
+"B#	c #3C2D26",
+"C#	c #CFA245",
+"D#	c #EBBD4E",
+"E#	c #FFD353",
+"F#	c #F9C740",
+"G#	c #FAC545",
+"H#	c #F7C147",
+"I#	c #F4C144",
+"J#	c #F7C645",
+"K#	c #F7C773",
+"L#	c #FFD187",
+"M#	c #FFD593",
+"N#	c #FED287",
+"O#	c #FACF71",
+"P#	c #F5CB5B",
+"Q#	c #EBBC48",
+"R#	c #DDAB3A",
+"S#	c #C99D30",
+"T#	c #F9BD3B",
+"U#	c #FFD14D",
+"V#	c #F2BC58",
+"W#	c #3E2800",
+"X#	c #110D1C",
+"Y#	c #FAFCFB",
+"Z#	c #FFFFFB",
+"`#	c #FFFCF5",
+" $	c #D2CBC3",
+".$	c #160500",
+"+$	c #AC7C4B",
+"@$	c #D5A855",
+"#$	c #D5A92E",
+"$$	c #EABE29",
+"%$	c #FCCF36",
+"&$	c #FDCF3E",
+"*$	c #EBBD34",
+"=$	c #FFD752",
+"-$	c #FBD75D",
+";$	c #F3CB5C",
+">$	c #F4C867",
+",$	c #F9CB6B",
+"'$	c #EDBD57",
+")$	c #D2A33B",
+"!$	c #CC9B3C",
+"~$	c #D8A651",
+"{$	c #F8C52E",
+"]$	c #FFBE24",
+"^$	c #EA980E",
+"/$	c #DA9C47",
+"($	c #1C0700",
+"_$	c #00020B",
+":$	c #27291B",
+"<$	c #D6D6D6",
+"[$	c #361500",
+"}$	c #D8B453",
+"|$	c #E4BA42",
+"1$	c #C68D24",
+"2$	c #C6823B",
+"3$	c #E09866",
+"4$	c #EDA96A",
+"5$	c #F4B764",
+"6$	c #F3B85C",
+"7$	c #E7AF5A",
+"8$	c #D2A250",
+"9$	c #C19745",
+"0$	c #C09539",
+"a$	c #D4A136",
+"b$	c #F1B739",
+"c$	c #FFC73C",
+"d$	c #F3B019",
+"e$	c #D19519",
+"f$	c #CEA053",
+"g$	c #C7A889",
+"h$	c #0E040D",
+"i$	c #0E0B12",
+"j$	c #2F2D2E",
+"k$	c #4B4B4B",
+"l$	c #575757",
+"m$	c #D3D3D3",
+"n$	c #7E4E5C",
+"o$	c #D39E72",
+"p$	c #D69A2A",
+"q$	c #FCBA28",
+"r$	c #FFC23D",
+"s$	c #CB9326",
+"t$	c #956F0E",
+"u$	c #99811F",
+"v$	c #937D31",
+"w$	c #A4842D",
+"x$	c #C5942D",
+"y$	c #EEA932",
+"z$	c #FFB936",
+"A$	c #FFB82F",
+"B$	c #FCA61B",
+"C$	c #E9960A",
+"D$	c #C08D31",
+"E$	c #E1B56C",
+"F$	c #DABB8F",
+"G$	c #C2B1A1",
+"H$	c #000100",
+"I$	c #121710",
+"J$	c #898989",
+"K$	c #797979",
+"L$	c #3A3A3A",
+"M$	c #9C9C9C",
+"N$	c #735C90",
+"O$	c #E3C2BB",
+"P$	c #DBA954",
+"Q$	c #D5920D",
+"R$	c #E6A00D",
+"S$	c #F9BA2F",
+"T$	c #F1C33C",
+"U$	c #E6C63D",
+"V$	c #D5BB5A",
+"W$	c #EABF4C",
+"X$	c #FFBE32",
+"Y$	c #FFB518",
+"Z$	c #FFA409",
+"`$	c #F5950D",
+" %	c #DB8B1C",
+".%	c #CC872A",
+"+%	c #C9AE99",
+"@%	c #DEC8BA",
+"#%	c #D5CBC2",
+"$%	c #C1C1BF",
+"%%	c #000302",
+"&%	c #101A19",
+"*%	c #091308",
+"=%	c #909090",
+"-%	c #333333",
+";%	c #546B73",
+">%	c #C4CEC3",
+",%	c #CEC29A",
+"'%	c #D2AE72",
+")%	c #D59848",
+"!%	c #DC8D24",
+"~%	c #EA9305",
+"{%	c #FEA600",
+"]%	c #F9A416",
+"^%	c #FCA20D",
+"/%	c #F89B00",
+"(%	c #E78D00",
+"_%	c #D2860C",
+":%	c #CC9543",
+"<%	c #D6B68F",
+"[%	c #E3D1C3",
+"}%	c #DBD0E1",
+"|%	c #CCC6D4",
+"1%	c #CBCBD3",
+"2%	c #CDD2D5",
+"3%	c #27302F",
+"4%	c #000502",
+"5%	c #070B0A",
+"6%	c #383838",
+"7%	c #A0A0A0",
+"8%	c #E7E7E7",
+"9%	c #7A8273",
+"0%	c #C1CDC1",
+"a%	c #B9C4BE",
+"b%	c #CCCBC6",
+"c%	c #CFB6A0",
+"d%	c #CE9359",
+"e%	c #DD851B",
+"f%	c #FB9004",
+"g%	c #FF9106",
+"h%	c #EF8E0B",
+"i%	c #DA8F1C",
+"j%	c #C9963D",
+"k%	c #C2A36C",
+"l%	c #C2B3A0",
+"m%	c #C3C0C9",
+"n%	c #C6C7E3",
+"o%	c #DCDAE7",
+"p%	c #E7E7EF",
+"q%	c #F6F8F5",
+"r%	c #B8BAB7",
+"s%	c #1C171D",
+"t%	c #040007",
+"u%	c #363636",
+"v%	c #757575",
+"w%	c #151515",
+"x%	c #653F4A",
+"y%	c #C9B2BC",
+"z%	c #C5C4CA",
+"A%	c #BDC9C7",
+"B%	c #BEC9B8",
+"C%	c #D8CEAA",
+"D%	c #D9B581",
+"E%	c #C28C50",
+"F%	c #D2994C",
+"G%	c #D0A060",
+"H%	c #CCAD7F",
+"I%	c #CABBA4",
+"J%	c #D0CBC5",
+"K%	c #DED9DD",
+"L%	c #EEE4ED",
+"M%	c #F8EBF5",
+"N%	c #F9FAF5",
+"O%	c #FFFFFA",
+"P%	c #FFFEFB",
+"Q%	c #767074",
+"R%	c #040005",
+"S%	c #100513",
+"T%	c #E0C8D6",
+"U%	c #FFF7FF",
+"V%	c #DFD5DD",
+"W%	c #CCCDC8",
+"X%	c #B9C0B0",
+"Y%	c #B8C1AE",
+"Z%	c #C7CDC1",
+"`%	c #CFD4CE",
+" &	c #C0C4B6",
+".&	c #C8C9C1",
+"+&	c #D1CDCC",
+"@&	c #D5CCD1",
+"#&	c #D6CDD2",
+"$&	c #E1D8D9",
+"%&	c #F4EFEB",
+"&&	c #FFFFF6",
+"*&	c #FCFFF8",
+"=&	c #FEFFFA",
+"-&	c #F4F6F3",
+";&	c #F1F1F3",
+">&	c #EAEAEC",
+",&	c #121315",
+"'&	c #0A0B0D",
+")&	c #1C1C1C",
+"!&	c #DADADA",
+"~&	c #E9E9E9",
+"{&	c #8B8B8B",
+"]&	c #D9FFEA",
+"^&	c #F1FFFF",
+"/&	c #D6D4DF",
+"(&	c #E2D0DE",
+"_&	c #DCC9CF",
+":&	c #CAC4C4",
+"<&	c #BCC8C8",
+"[&	c #B0C9CD",
+"}&	c #B2D0DB",
+"|&	c #BDCBD4",
+"1&	c #D2CBD2",
+"2&	c #ECD6D9",
+"3&	c #FEE9E8",
+"4&	c #FFFBF7",
+"5&	c #F3FFFE",
+"6&	c #E6FFFF",
+"7&	c #EDF4ED",
+"8&	c #FBFFFF",
+"9&	c #F9FDFF",
+"0&	c #EAF4F5",
+"a&	c #95A299",
+"b&	c #000700",
+"c&	c #6E6E6E",
+"d&	c #2C2C2C",
+"e&	c #DDDDDD",
+"f&	c #D1D1D1",
+"g&	c #D5D5D5",
+"h&	c #EBEBEB",
+"i&	c #B3B3B3",
+"j&	c #C0C0C0",
+"k&	c #404040",
+"l&	c #E0E0E0",
+"m&	c #505050",
+"n&	c #767676",
+"o&	c #888888",
+"p&	c #A1A1A1",
+"q&	c #959595",
+"r&	c #1B1B1B",
+"s&	c #CBCBCB",
+"t&	c #3D3D3D",
+"u&	c #5A5A5A",
+"v&	c #555555",
+"w&	c #ECECEC",
+"x&	c #969696",
+"y&	c #BBBBBB",
+"z&	c #222222",
+"A&	c #464646",
+"B&	c #7C7C7C",
+"C&	c #B8B8B8",
+"D&	c #262626",
+"E&	c #9F9F9F",
+"F&	c #BFBFBF",
+"G&	c #BABABA",
+"H&	c #C6C6C6",
+"I&	c #DFDFDF",
+"J&	c #CCCCCC",
+"K&	c #515151",
+"L&	c #B6B6B6",
+"M&	c #D7D7D7",
+"N&	c #C4C4C4",
+"O&	c #C2C2C2",
+"P&	c #4C4C4C",
+"Q&	c #CACACA",
+"R&	c #BCBCBC",
+"S&	c #535353",
+"T&	c #949494",
+"U&	c #AAAAAA",
+"V&	c #424242",
+"W&	c #CECECE",
+"X&	c #636363",
+"Y&	c #6A6A6A",
+"Z&	c #4F4F4F",
+"`&	c #DEDEDE",
+" *	c #BEBEBE",
+".*	c #BDBDBD",
+"+*	c #191919",
+"@*	c #3F3F3F",
+"#*	c #232323",
+"$*	c #2E2E2E",
+"%*	c #1F1F1F",
+"&*	c #5D5D5D",
+"**	c #282828",
+"=*	c #A9A9A9",
+"-*	c #4D4D4D",
+";*	c #525252",
+">*	c #E4E4E4",
+",*	c #FDF8F2",
+"'*	c #FFFBFF",
+")*	c #F1F0F6",
+"!*	c #F3F6FF",
+"~*	c #101920",
+"{*	c #021013",
+"]*	c #00090B",
+"^*	c #0A0603",
+"/*	c #7D7874",
+"(*	c #100B07",
+"_*	c #050100",
+":*	c #555452",
+"<*	c #F6F7F9",
+"[*	c #F5FEEB",
+"}*	c #FCFBFF",
+"|*	c #FFFAFF",
+"1*	c #FFF8FF",
+"2*	c #EBEAF2",
+"3*	c #6E716A",
+"4*	c #FDFBFC",
+"5*	c #CFCECC",
+"6*	c #030200",
+"7*	c #050402",
+"8*	c #71706E",
+"9*	c #373634",
+"0*	c #0A0907",
+"a*	c #62615F",
+"b*	c #FFFDFF",
+"c*	c #FFFBF8",
+"d*	c #A6A2A1",
+"e*	c #0E080A",
+"f*	c #F9FBFF",
+"g*	c #FAFBFF",
+"h*	c #F9F9F7",
+"i*	c #FFFFF8",
+"j*	c #8C887F",
+"k*	c #0B0400",
+"l*	c #16070C",
+"m*	c #050608",
+"n*	c #7C7D7F",
+"o*	c #454648",
+"p*	c #090A0C",
+"q*	c #FEFDFB",
+"r*	c #F3F2F0",
+"s*	c #FFF3FF",
+"t*	c #FEFEF4",
+"u*	c #F9FEEA",
+"v*	c #FEFFEF",
+"w*	c #C1B6BE",
+"x*	c #0A000B",
+"y*	c #A2A2A2",
+"z*	c #F8FAF7",
+"A*	c #ECF2E8",
+"B*	c #323730",
+"C*	c #000009",
+"D*	c #010010",
+"E*	c #353A3E",
+"F*	c #7F8488",
+"G*	c #B3B4B6",
+"H*	c #FFFFFD",
+"I*	c #F7FFFC",
+"J*	c #F2FDF7",
+"K*	c #F4F8F7",
+"L*	c #CBC6CC",
+"M*	c #150915",
+"N*	c #050706",
+"O*	c #030504",
+"P*	c #9EA09F",
+"Q*	c #FFFDFD",
+"R*	c #F9FBF6",
+"S*	c #EDF6F1",
+"T*	c #212F2F",
+"U*	c #00060E",
+"V*	c #000515",
+"W*	c #000017",
+"X*	c #080705",
+"Y*	c #090D10",
+"Z*	c #7E8387",
+"`*	c #2C3135",
+" =	c #D8D9DB",
+".=	c #FCFBF9",
+"+=	c #FDF8F4",
+"@=	c #F5F9FA",
+"#=	c #F8FFFF",
+"$=	c #F4FDFF",
+"%=	c #EFF8FF",
+"&=	c #C4C8C9",
+"*=	c #262922",
+"==	c #010302",
+"-=	c #060807",
+";=	c #070908",
+">=	c #A8AAA9",
+",=	c #FFFCF6",
+"'=	c #FBF6F2",
+")=	c #F5F7F4",
+"!=	c #F9FFFF",
+"~=	c #515B5C",
+"{=	c #000603",
+"]=	c #0A0F09",
+"^=	c #090A04",
+"/=	c #141311",
+"(=	c #1C2023",
+"_=	c #6A6F73",
+":=	c #CBCCCE",
+"<=	c #F0EBE7",
+"[=	c #F5FFF3",
+"}=	c #ECF3EC",
+"|=	c #FBFCFF",
+"1=	c #959C95",
+"2=	c #081406",
+"3=	c #020605",
+"4=	c #000403",
+"5=	c #131716",
+"6=	c #CACECD",
+"7=	c #FBFCF7",
+"8=	c #F7F8FA",
+"9=	c #FBFBFD",
+"0=	c #898079",
+"a=	c #1B0A00",
+"b=	c #513505",
+"c=	c #583600",
+"d=	c #200900",
+"e=	c #1D0D00",
+"f=	c #323639",
+"g=	c #A4A5A7",
+"h=	c #F7F6F4",
+"i=	c #FFFEFA",
+"j=	c #FFFBE2",
+"k=	c #FFE8C4",
+"l=	c #FFF4D0",
+"m=	c #FBEBD2",
+"n=	c #656259",
+"o=	c #090D0C",
+"p=	c #0E1211",
+"q=	c #010504",
+"r=	c #1E2221",
+"s=	c #F3FDF2",
+"t=	c #FEF4F5",
+"u=	c #CAB09F",
+"v=	c #774B1A",
+"w=	c #E5AB57",
+"x=	c #F6B247",
+"y=	c #BD9F87",
+"z=	c #38210F",
+"A=	c #1F1209",
+"B=	c #05090C",
+"C=	c #28292B",
+"D=	c #CECDCB",
+"E=	c #FDF9F6",
+"F=	c #F6F5FF",
+"G=	c #FFFBF2",
+"H=	c #FFE1AD",
+"I=	c #D0A757",
+"J=	c #D2A959",
+"K=	c #D5B783",
+"L=	c #40332A",
+"M=	c #010012",
+"N=	c #232927",
+"O=	c #242A28",
+"P=	c #000301",
+"Q=	c #050B09",
+"R=	c #1B211F",
+"S=	c #F9FFFD",
+"T=	c #F2F8F6",
+"U=	c #FCFFEF",
+"V=	c #F9FAF4",
+"W=	c #FBEEFF",
+"X=	c #FFF2FF",
+"Y=	c #FDFFF1",
+"Z=	c #EEEAC7",
+"`=	c #D5B642",
+" -	c #E5A802",
+".-	c #FFB018",
+"+-	c #FFAA32",
+"@-	c #FFBF40",
+"#-	c #DFAB55",
+"$-	c #482B0B",
+"%-	c #060203",
+"&-	c #010A11",
+"*-	c #030D0F",
+"=-	c #645961",
+"--	c #FFF5E8",
+";-	c #FFEBEF",
+">-	c #CD9A25",
+",-	c #F19B00",
+"'-	c #FF920C",
+")-	c #FFA72C",
+"!-	c #5B3003",
+"~-	c #020200",
+"{-	c #01000D",
+"]-	c #02000D",
+"^-	c #03000B",
+"/-	c #030005",
+"(-	c #040006",
+"_-	c #05020D",
+":-	c #00000C",
+"<-	c #090005",
+"[-	c #39280E",
+"}-	c #1D0000",
+"|-	c #9E7B99",
+"1-	c #F7FFE5",
+"2-	c #FEFFF9",
+"3-	c #F6FCFC",
+"4-	c #F2FBF8",
+"5-	c #F6FBFE",
+"6-	c #FEFDFF",
+"7-	c #F8FDFF",
+"8-	c #EFFDFD",
+"9-	c #F5FEF9",
+"0-	c #F8FCFF",
+"a-	c #FAF0E4",
+"b-	c #F3CD8C",
+"c-	c #EEAA2B",
+"d-	c #F9A608",
+"e-	c #FFB122",
+"f-	c #FCB340",
+"g-	c #FFBD40",
+"h-	c #E8B343",
+"i-	c #D7B764",
+"j-	c #3B2C03",
+"k-	c #00000B",
+"l-	c #07060B",
+"m-	c #FFF7F2",
+"n-	c #FEE3DC",
+"o-	c #D5A92C",
+"p-	c #FFB120",
+"q-	c #FFA32F",
+"r-	c #ECA124",
+"s-	c #573603",
+"t-	c #060910",
+"u-	c #030102",
+"v-	c #020100",
+"w-	c #0A0D06",
+"x-	c #0A021A",
+"y-	c #120007",
+"z-	c #A78B4C",
+"A-	c #A88521",
+"B-	c #BE9955",
+"C-	c #FFF4DA",
+"D-	c #F9F3E5",
+"E-	c #FDFEF8",
+"F-	c #F2FFFF",
+"G-	c #F3FBFF",
+"H-	c #FFFFF1",
+"I-	c #FCFFE9",
+"J-	c #FBFFF1",
+"K-	c #FBF9EA",
+"L-	c #FAD79D",
+"M-	c #FAB246",
+"N-	c #FFA41A",
+"O-	c #FFA817",
+"P-	c #FEB12D",
+"Q-	c #F2BB47",
+"R-	c #F2AF2D",
+"S-	c #FFD144",
+"T-	c #F4C843",
+"U-	c #CAA84F",
+"V-	c #462E12",
+"W-	c #131416",
+"X-	c #FAF5F9",
+"Y-	c #EFDBC2",
+"Z-	c #DDB82C",
+"`-	c #FEB535",
+" ;	c #FFAB4E",
+".;	c #E6AA25",
+"+;	c #684F0C",
+"@;	c #040410",
+"#;	c #080901",
+"$;	c #010200",
+"%;	c #030400",
+"&;	c #060700",
+"*;	c #030009",
+"=;	c #160611",
+"-;	c #745630",
+";;	c #F6CD4D",
+">;	c #F8C416",
+",;	c #E9B428",
+"';	c #DCB568",
+");	c #FFEEC5",
+"!;	c #FDFEF9",
+"~;	c #EDFFFF",
+"{;	c #FCFEFF",
+"];	c #FFF0D6",
+"^;	c #F6DE9E",
+"/;	c #EED789",
+"(;	c #F9DB9B",
+"_;	c #FFE4BA",
+":;	c #F0E1C2",
+"<;	c #FCDD9A",
+"[;	c #F5BD4C",
+"};	c #F6A319",
+"|;	c #FFAB20",
+"1;	c #FFB32E",
+"2;	c #F8B435",
+"3;	c #F2C341",
+"4;	c #FFBF2D",
+"5;	c #FFCC37",
+"6;	c #F7BA2E",
+"7;	c #F4BE51",
+"8;	c #C09453",
+"9;	c #140000",
+"0;	c #030C13",
+"a;	c #FBF2F5",
+"b;	c #F1DBAC",
+"c;	c #ECC627",
+"d;	c #F3A831",
+"e;	c #FFAC59",
+"f;	c #FBC531",
+"g;	c #9D8324",
+"h;	c #241512",
+"i;	c #040402",
+"j;	c #000005",
+"k;	c #050912",
+"l;	c #0B0007",
+"m;	c #604A25",
+"n;	c #DDB949",
+"o;	c #FFC81F",
+"p;	c #F9AD01",
+"q;	c #FFB82E",
+"r;	c #CE952A",
+"s;	c #FEDA7A",
+"t;	c #FCFDF7",
+"u;	c #FCFDF8",
+"v;	c #F0FFFD",
+"w;	c #FFF9F0",
+"x;	c #FFE1C1",
+"y;	c #F8BE75",
+"z;	c #E3A834",
+"A;	c #E4A621",
+"B;	c #F2A62E",
+"C;	c #FFA33E",
+"D;	c #EEAB43",
+"E;	c #F8B334",
+"F;	c #EFA915",
+"G;	c #ECA612",
+"H;	c #FDBA37",
+"I;	c #FEC045",
+"J;	c #F7BE39",
+"K;	c #FCC834",
+"L;	c #FFC924",
+"M;	c #FFBD33",
+"N;	c #FFC95A",
+"O;	c #F7B046",
+"P;	c #EFB94F",
+"Q;	c #9D7D30",
+"R;	c #0B0000",
+"S;	c #040025",
+"T;	c #F6EBE5",
+"U;	c #F2D59D",
+"V;	c #FDCE28",
+"W;	c #FBAD31",
+"X;	c #FFAF58",
+"Y;	c #FFD233",
+"Z;	c #DCB63B",
+"`;	c #805E31",
+" >	c #0D0805",
+".>	c #151014",
+"+>	c #0A0815",
+"@>	c #000010",
+"#>	c #0D0B18",
+"$>	c #171216",
+"%>	c #0B0603",
+"&>	c #6D5121",
+"*>	c #D1B258",
+"=>	c #F3C742",
+"->	c #FEB825",
+";>	c #FFAF21",
+">>	c #FFB631",
+",>	c #F4B035",
+"'>	c #EEBC4B",
+")>	c #FBFCF6",
+"!>	c #FEFEFC",
+"~>	c #F9FCF1",
+"{>	c #FBDEB6",
+"]>	c #F7B561",
+"^>	c #EF9D20",
+"/>	c #EE9E0B",
+"(>	c #F7A60C",
+"_>	c #FFA20A",
+":>	c #FF9602",
+"<>	c #FDA408",
+"[>	c #FFAD10",
+"}>	c #FFB119",
+"|>	c #F7BA2C",
+"1>	c #F4C746",
+"2>	c #F2C94B",
+"3>	c #F7C33B",
+"4>	c #FFC22E",
+"5>	c #F5C11F",
+"6>	c #FFC247",
+"7>	c #FFB959",
+"8>	c #FFCD60",
+"9>	c #F3B931",
+"0>	c #FFD863",
+"a>	c #5C4018",
+"b>	c #0D0013",
+"c>	c #E1DBCB",
+"d>	c #E2C394",
+"e>	c #FCCA2D",
+"f>	c #FFBF3A",
+"g>	c #FFB451",
+"h>	c #FDC625",
+"i>	c #F9C83D",
+"j>	c #E3AE52",
+"k>	c #8B7150",
+"l>	c #2C1400",
+"m>	c #0F0000",
+"n>	c #1E0D05",
+"o>	c #221109",
+"p>	c #371F05",
+"q>	c #957B5A",
+"r>	c #DEB537",
+"s>	c #F4C84D",
+"t>	c #FDC75A",
+"u>	c #FFB650",
+"v>	c #FFBB39",
+"w>	c #FFBC1D",
+"x>	c #EAA71B",
+"y>	c #FABD64",
+"z>	c #FAFBF5",
+"A>	c #FFF6E6",
+"B>	c #F1C480",
+"C>	c #ED9E1B",
+"D>	c #FBA303",
+"E>	c #FFB61E",
+"F>	c #FFBC30",
+"G>	c #FFB827",
+"H>	c #FFB718",
+"I>	c #FFC123",
+"J>	c #FFBA29",
+"K>	c #FFBD3A",
+"L>	c #FFC546",
+"M>	c #F8C63F",
+"N>	c #F3C83D",
+"O>	c #FEC43E",
+"P>	c #FFB93B",
+"Q>	c #FECB3C",
+"R>	c #FDC145",
+"S>	c #FFBC49",
+"T>	c #FFBE3B",
+"U>	c #FFD13C",
+"V>	c #D8A927",
+"W>	c #B48C44",
+"X>	c #340E00",
+"Y>	c #C8D1BE",
+"Z>	c #D4BEA7",
+"`>	c #F0C43D",
+" ,	c #FFC93C",
+".,	c #FAB84A",
+"+,	c #F5C32C",
+"@,	c #FAC73A",
+"#,	c #FFCA45",
+"$,	c #F9C160",
+"%,	c #E0AD54",
+"&,	c #AF8136",
+"*,	c #855918",
+"=,	c #895D1C",
+"-,	c #B7893E",
+";,	c #E8B55C",
+">,	c #FFC867",
+",,	c #FFC947",
+"',	c #ECB429",
+"),	c #FFD25A",
+"!,	c #F9BB56",
+"~,	c #FBB836",
+"{,	c #FFBD14",
+"],	c #DB9E07",
+"^,	c #FFC366",
+"/,	c #FDFDFB",
+"(,	c #FFF1DF",
+"_,	c #EEBB62",
+":,	c #ED9E00",
+"<,	c #FFB202",
+"[,	c #FFC234",
+"},	c #E6B745",
+"|,	c #E7B739",
+"1,	c #FFCA32",
+"2,	c #EACD41",
+"3,	c #F0B83F",
+"4,	c #FFB64C",
+"5,	c #FFBE48",
+"6,	c #FCBB2B",
+"7,	c #FAC42C",
+"8,	c #FFC846",
+"9,	c #FFBA50",
+"0,	c #F9C74E",
+"a,	c #FCC745",
+"b,	c #FEC635",
+"c,	c #F9BE22",
+"d,	c #FFC831",
+"e,	c #FFD050",
+"f,	c #EBBA5D",
+"g,	c #B68945",
+"h,	c #6C6C6C",
+"i,	c #BCD3C1",
+"j,	c #D9CBC8",
+"k,	c #EBC653",
+"l,	c #FCC93A",
+"m,	c #F4BF4D",
+"n,	c #FFD64B",
+"o,	c #F9C83F",
+"p,	c #F7C025",
+"q,	c #FFBE27",
+"r,	c #FFBB2F",
+"s,	c #F6B537",
+"t,	c #EEB13E",
+"u,	c #EFB23F",
+"v,	c #F8B739",
+"w,	c #FFB92D",
+"x,	c #FFBA23",
+"y,	c #FFB15C",
+"z,	c #FFC736",
+"A,	c #EEC21B",
+"B,	c #F4C43C",
+"C,	c #F5BE40",
+"D,	c #F1B61E",
+"E,	c #FFCA2F",
+"F,	c #EAB033",
+"G,	c #FCF4F1",
+"H,	c #EBC982",
+"I,	c #E6A407",
+"J,	c #FFAC0C",
+"K,	c #FFB141",
+"L,	c #F5BB2C",
+"M,	c #FCCD27",
+"N,	c #F8BC4A",
+"O,	c #FDC53E",
+"P,	c #FFC740",
+"Q,	c #FEC63B",
+"R,	c #FDC53A",
+"S,	c #FCC43D",
+"T,	c #FBC23F",
+"U,	c #FBC143",
+"V,	c #6B4D31",
+"W,	c #1C0200",
+"X,	c #08000B",
+"Y,	c #03030F",
+"Z,	c #020300",
+"`,	c #C7CBCA",
+" '	c #E8D5C4",
+".'	c #E7BF5F",
+"+'	c #EEB727",
+"@'	c #FFC750",
+"#'	c #F1B539",
+"$'	c #FFCC3B",
+"%'	c #FCC149",
+"&'	c #FDBF38",
+"*'	c #FCBE37",
+"='	c #FBBD36",
+"-'	c #FABC35",
+";'	c #F9C33F",
+">'	c #FAC43E",
+",'	c #FEC33B",
+"''	c #FFBF37",
+")'	c #FCBA30",
+"!'	c #FAB52C",
+"~'	c #F7B227",
+"{'	c #F0DB8A",
+"]'	c #FDEDC9",
+"^'	c #F3FFFF",
+"/'	c #F9FFF3",
+"('	c #FFFAF7",
+"_'	c #F2D091",
+":'	c #EBA915",
+"<'	c #FFAE10",
+"['	c #FFB340",
+"}'	c #F7BC30",
+"|'	c #FFCD2C",
+"1'	c #FBBF4D",
+"2'	c #FDC43F",
+"3'	c #FFC641",
+"4'	c #FEC63D",
+"5'	c #FDC53C",
+"6'	c #FCC33E",
+"7'	c #FBC241",
+"8'	c #FBC144",
+"9'	c #D9B463",
+"0'	c #6C4C1B",
+"a'	c #2C160B",
+"b'	c #160C14",
+"c'	c #0F110C",
+"d'	c #AEAEAE",
+"e'	c #CACDD2",
+"f'	c #D4BEB3",
+"g'	c #E3B85C",
+"h'	c #FFC63B",
+"i'	c #FFC04C",
+"j'	c #FFC448",
+"k'	c #FFC837",
+"l'	c #F8BE43",
+"m'	c #FFC13A",
+"n'	c #FEC23D",
+"o'	c #FFBF39",
+"p'	c #FEBC34",
+"q'	c #FCB82F",
+"r'	c #FBB62D",
+"s'	c #E6C954",
+"t'	c #FBE2A0",
+"u'	c #FFF9F2",
+"v'	c #F5FCFF",
+"w'	c #F7FEF6",
+"x'	c #F9D9AA",
+"y'	c #EEAE2A",
+"z'	c #FEAD13",
+"A'	c #FFB43E",
+"B'	c #F7BC34",
+"C'	c #FFCD30",
+"D'	c #FEC04F",
+"E'	c #FDC441",
+"F'	c #FFC645",
+"G'	c #FFC643",
+"H'	c #FEC63F",
+"I'	c #FCC340",
+"J'	c #FBC146",
+"K'	c #D0A445",
+"L'	c #624219",
+"M'	c #020700",
+"N'	c #DADCE9",
+"O'	c #826A68",
+"P'	c #A0711F",
+"Q'	c #FCBD3A",
+"R'	c #FFBA4E",
+"S'	c #FFC54C",
+"T'	c #F1B928",
+"U'	c #FFC94C",
+"V'	c #FFC33E",
+"W'	c #FCC640",
+"X'	c #FEC039",
+"Y'	c #FEBE38",
+"Z'	c #FFBD35",
+"`'	c #E7BE24",
+" )	c #F9D26B",
+".)	c #FFE7BF",
+"+)	c #FFF0EC",
+"@)	c #FAFFF8",
+"#)	c #FCFFFB",
+"$)	c #FBFFFB",
+"%)	c #FDE0C0",
+"&)	c #EFB03F",
+"*)	c #F9A912",
+"=)	c #FFB437",
+"-)	c #F5B934",
+";)	c #FDC731",
+">)	c #FEC14E",
+",)	c #FDC443",
+"')	c #FEC544",
+"))	c #FEC542",
+"!)	c #FEC540",
+"~)	c #FCC342",
+"{)	c #FCC245",
+"])	c #F8B61A",
+"^)	c #FFD34E",
+"/)	c #B68F32",
+"()	c #3B2400",
+"_)	c #130709",
+":)	c #0E0719",
+"<)	c #030106",
+"[)	c #0D0D01",
+"})	c #9E9FB1",
+"|)	c #2C1215",
+"1)	c #8D590E",
+"2)	c #F5B136",
+"3)	c #FCB14B",
+"4)	c #FFBF4A",
+"5)	c #FFCE50",
+"6)	c #FFC43F",
+"7)	c #FCC23C",
+"8)	c #FDC13C",
+"9)	c #FFC13C",
+"0)	c #FFC13D",
+"a)	c #FFC23E",
+"b)	c #FBC326",
+"c)	c #FAC446",
+"d)	c #F6CA73",
+"e)	c #F7D89F",
+"f)	c #FFF0C7",
+"g)	c #FFFFE8",
+"h)	c #F7FFF8",
+"i)	c #FFE9D8",
+"j)	c #F4B558",
+"k)	c #F5AA11",
+"l)	c #FEB62E",
+"m)	c #F6BA35",
+"n)	c #FCC632",
+"o)	c #FFC249",
+"p)	c #FCC244",
+"q)	c #FFC039",
+"r)	c #FFBF2A",
+"s)	c #F8C73E",
+"t)	c #B28B3E",
+"u)	c #3B191A",
+"v)	c #0D001B",
+"w)	c #0C0111",
+"x)	c #010300",
+"y)	c #252638",
+"z)	c #D49B54",
+"A)	c #FEB640",
+"B)	c #F8A545",
+"C)	c #FFBD4E",
+"D)	c #FFC838",
+"E)	c #FABF41",
+"F)	c #FEC43F",
+"G)	c #FFC841",
+"H)	c #FDC33E",
+"I)	c #FFC33F",
+"J)	c #FFC541",
+"K)	c #FFC642",
+"L)	c #FFC543",
+"M)	c #FFC03D",
+"N)	c #F4BF3D",
+"O)	c #F1C950",
+"P)	c #F9E07C",
+"Q)	c #FFF5B9",
+"R)	c #FFFAEE",
+"S)	c #F2FFF3",
+"T)	c #FFF2ED",
+"U)	c #F6BB6D",
+"V)	c #F6AD12",
+"W)	c #FFBB28",
+"X)	c #F9BE34",
+"Y)	c #FEC633",
+"Z)	c #FDC345",
+"`)	c #FFC851",
+" !	c #F1B01E",
+".!	c #FEBF26",
+"+!	c #F4B84A",
+"@!	c #905833",
+"#!	c #2A0109",
+"$!	c #151400",
+"%!	c #EDB36A",
+"&!	c #FFB13E",
+"*!	c #FFA84B",
+"=!	c #FFB647",
+"-!	c #FFC334",
+";!	c #F6BB3D",
+">!	c #FFC741",
+",!	c #FFC640",
+"'!	c #FEC341",
+")!	c #FFC442",
+"!!	c #FFC545",
+"~!	c #FFC646",
+"{!	c #FFC251",
+"]!	c #FFC341",
+"^!	c #FFC531",
+"/!	c #F2CA46",
+"(!	c #F4D67C",
+"_!	c #FBE9BB",
+":!	c #EDFFEE",
+"<!	c #FFF7F9",
+"[!	c #F9BE7A",
+"}!	c #F2AE0D",
+"|!	c #FFBE21",
+"1!	c #FAC031",
+"2!	c #FCC431",
+"3!	c #FFC53F",
+"4!	c #FDC638",
+"5!	c #FDC636",
+"6!	c #FAC845",
+"7!	c #FFC742",
+"8!	c #FFB32C",
+"9!	c #FFB333",
+"0!	c #F1A93D",
+"a!	c #8E5E16",
+"b!	c #5D482D",
+"c!	c #928D91",
+"d!	c #0B0F10",
+"e!	c #1A0000",
+"f!	c #D3984C",
+"g!	c #F7A631",
+"h!	c #FFAB50",
+"i!	c #FFB145",
+"j!	c #F2B527",
+"k!	c #FEC345",
+"l!	c #FFC540",
+"m!	c #FEC446",
+"n!	c #FDC647",
+"o!	c #FAC24B",
+"p!	c #FFC434",
+"q!	c #F9BE3C",
+"r!	c #F1C354",
+"s!	c #F2D376",
+"t!	c #E7FFE6",
+"u!	c #FFF7FA",
+"v!	c #F7BD7D",
+"w!	c #F0AC09",
+"x!	c #FEBD19",
+"y!	c #F8BE2E",
+"z!	c #F9C12C",
+"A!	c #FFC439",
+"B!	c #FDC635",
+"C!	c #E7C42C",
+"D!	c #FEC449",
+"E!	c #FFB245",
+"F!	c #FFAD25",
+"G!	c #FFB40C",
+"H!	c #D8A71A",
+"I!	c #CAB37D",
+"J!	c #ECE3FE",
+"K!	c #2D1105",
+"L!	c #DA9D4D",
+"M!	c #FAA632",
+"N!	c #FFA449",
+"O!	c #FFBD51",
+"P!	c #F3B427",
+"Q!	c #FFC744",
+"R!	c #FFC63E",
+"S!	c #FCC546",
+"T!	c #FBC445",
+"U!	c #FBC446",
+"V!	c #F7C942",
+"W!	c #FBC53E",
+"X!	c #FFC23F",
+"Y!	c #FFC047",
+"Z!	c #F9C04D",
+"`!	c #EDC844",
+" ~	c #F4F9FF",
+".~	c #FFFDAD",
+"+~	c #EDC41E",
+"@~	c #ECA900",
+"#~	c #FFB411",
+"$~	c #FFBB18",
+"%~	c #FFC728",
+"&~	c #F3BA2D",
+"*~	c #FFC327",
+"=~	c #FFC325",
+"-~	c #FFC324",
+";~	c #FFC422",
+">~	c #FFC420",
+",~	c #FFC41E",
+"'~	c #FEC422",
+")~	c #FEC424",
+"!~	c #FCC425",
+"~~	c #FDC528",
+"{~	c #FCC628",
+"]~	c #FCC52A",
+"^~	c #FFCC3C",
+"/~	c #F2B934",
+"(~	c #F5B937",
+"_~	c #FEB31A",
+":~	c #DB9211",
+"<~	c #CC9048",
+"[~	c #D9A790",
+"}~	c #ECF6FF",
+"|~	c #F7F4EF",
+"1~	c #EFFAEC",
+"2~	c #FEFFFB",
+"3~	c #8F8F8F",
+"4~	c #070311",
+"5~	c #643F13",
+"6~	c #E69641",
+"7~	c #FF9D48",
+"8~	c #FFA949",
+"9~	c #F6B130",
+"0~	c #FEC339",
+"a~	c #F8BA41",
+"b~	c #F7C030",
+"c~	c #FFC840",
+"d~	c #FDBD3F",
+"e~	c #FFBB40",
+"f~	c #FFC64E",
+"g~	c #FFC753",
+"h~	c #FFC745",
+"i~	c #FEC230",
+"j~	c #F7BE26",
+"k~	c #F7C332",
+"l~	c #FACC54",
+"m~	c #FBCF76",
+"n~	c #FBF4FF",
+"o~	c #F9E296",
+"p~	c #E2AF15",
+"q~	c #F2A904",
+"r~	c #FFB618",
+"s~	c #FBB80F",
+"t~	c #FFC519",
+"u~	c #F8C120",
+"v~	c #FEC41B",
+"w~	c #FEC41A",
+"x~	c #FFC219",
+"y~	c #FDC319",
+"z~	c #FDC31A",
+"A~	c #FCC31A",
+"B~	c #FDC41D",
+"C~	c #FBC41F",
+"D~	c #FBC421",
+"E~	c #F6C123",
+"F~	c #FFCE3E",
+"G~	c #F2AC19",
+"H~	c #FFB219",
+"I~	c #FFBE35",
+"J~	c #D6953B",
+"K~	c #8D5524",
+"L~	c #7B7E83",
+"M~	c #ECECEE",
+"N~	c #FAFFFA",
+"O~	c #FBFFF8",
+"P~	c #F6EEF9",
+"Q~	c #05000A",
+"R~	c #71481A",
+"S~	c #E6963F",
+"T~	c #FC9641",
+"U~	c #FFA647",
+"V~	c #F5B031",
+"W~	c #F9B840",
+"X~	c #FFCB48",
+"Y~	c #FFC441",
+"Z~	c #FBBF3D",
+"`~	c #FCC141",
+" {	c #FFCA49",
+".{	c #FFCB4A",
+"+{	c #FBC443",
+"@{	c #F3BC3B",
+"#{	c #F3B52E",
+"${	c #FFC53B",
+"%{	c #FFCF42",
+"&{	c #FDC942",
+"*{	c #EEBF4D",
+"={	c #F0C871",
+"-{	c #FFE0A7",
+";{	c #FFECE5",
+">{	c #E9C46C",
+",{	c #DF9F0A",
+"'{	c #FEAB11",
+"){	c #FFB41A",
+"!{	c #F7B403",
+"~{	c #FDC403",
+"{{	c #FBC50B",
+"]{	c #FEC111",
+"^{	c #FEC110",
+"/{	c #FEC10E",
+"({	c #FEC20C",
+"_{	c #FDC00D",
+":{	c #FDC210",
+"<{	c #FCC312",
+"[{	c #FCC314",
+"}{	c #FBC314",
+"|{	c #FCC415",
+"1{	c #FAC515",
+"2{	c #FFCC2B",
+"3{	c #FFC32D",
+"4{	c #F8B119",
+"5{	c #FFB113",
+"6{	c #FFB622",
+"7{	c #E59D25",
+"8{	c #B47518",
+"9{	c #0D0500",
+"0{	c #736D71",
+"a{	c #C9C6D1",
+"b{	c #E2E3E7",
+"c{	c #F3F8F2",
+"d{	c #FFFAFE",
+"e{	c #787878",
+"f{	c #0D0007",
+"g{	c #8B5F2E",
+"h{	c #ED9C43",
+"i{	c #F9953F",
+"j{	c #FFAB4A",
+"k{	c #F9B538",
+"l{	c #F9BE36",
+"m{	c #FFBE46",
+"n{	c #FFBF44",
+"o{	c #FFC143",
+"p{	c #FDC240",
+"q{	c #F6C63E",
+"r{	c #F3C83E",
+"s{	c #F3CA3E",
+"t{	c #FFC636",
+"u{	c #FCC23A",
+"v{	c #EFBB41",
+"w{	c #E5B755",
+"x{	c #E8C37D",
+"y{	c #F5DCB3",
+"z{	c #FFF4E2",
+"A{	c #FFDD9E",
+"B{	c #E5B137",
+"C{	c #EAA100",
+"D{	c #FFAF13",
+"E{	c #FFB015",
+"F{	c #F8B400",
+"G{	c #FBC200",
+"H{	c #F9C000",
+"I{	c #FABD03",
+"J{	c #FBBE04",
+"K{	c #FBBE03",
+"L{	c #FBBE01",
+"M{	c #FCC000",
+"N{	c #FEBE05",
+"O{	c #FDC006",
+"P{	c #FDC107",
+"Q{	c #FDC308",
+"R{	c #FDC30A",
+"S{	c #FEC40B",
+"T{	c #FFC90A",
+"U{	c #F5C00E",
+"V{	c #F9C01B",
+"W{	c #FFC121",
+"X{	c #FFB312",
+"Y{	c #F8A001",
+"Z{	c #F5A311",
+"`{	c #FFB731",
+" ]	c #4C3513",
+".]	c #151026",
+"+]	c #5A5F63",
+"@]	c #C5CAC3",
+"#]	c #D6D6D8",
+"$]	c #F9F6FD",
+"%]	c #F2F3EE",
+"&]	c #170104",
+"*]	c #A87643",
+"=]	c #F39F45",
+"-]	c #F6943D",
+";]	c #FFAD4D",
+">]	c #F9B93D",
+",]	c #F8BD35",
+"']	c #FFC24A",
+")]	c #F8BB3C",
+"!]	c #FEBF3E",
+"~]	c #FFC23B",
+"{]	c #FCBE35",
+"]]	c #F9BF37",
+"^]	c #FFCC45",
+"/]	c #F5BD42",
+"(]	c #E8B447",
+"_]	c #DBAD58",
+":]	c #DFBC82",
+"<]	c #F4DDBD",
+"[]	c #FFF9ED",
+"}]	c #F3C44E",
+"|]	c #E6AB09",
+"1]	c #FAAA00",
+"2]	c #FFAE0B",
+"3]	c #FFAA0B",
+"4]	c #FCB600",
+"5]	c #FEC000",
+"6]	c #FBBB04",
+"7]	c #FBBA00",
+"8]	c #FCBB00",
+"9]	c #FDBC00",
+"0]	c #FDBD00",
+"a]	c #FEBE00",
+"b]	c #FFBB00",
+"c]	c #FEBD01",
+"d]	c #FEBF02",
+"e]	c #FFC003",
+"f]	c #FEC202",
+"g]	c #FFC303",
+"h]	c #FAC307",
+"i]	c #FAC10F",
+"j]	c #FFBE12",
+"k]	c #FFB60E",
+"l]	c #FFAF09",
+"m]	c #FDA704",
+"n]	c #EFA101",
+"o]	c #956F2E",
+"p]	c #000305",
+"q]	c #060900",
+"r]	c #0C040F",
+"s]	c #494351",
+"t]	c #3B3E35",
+"u]	c #585858",
+"v]	c #240405",
+"w]	c #B9824A",
+"x]	c #F09B40",
+"y]	c #F1913A",
+"z]	c #F9A94A",
+"A]	c #F3B53A",
+"B]	c #F3B732",
+"C]	c #FFBE47",
+"D]	c #FFCC42",
+"E]	c #FFBF38",
+"F]	c #FFC342",
+"G]	c #FFC045",
+"H]	c #FDB441",
+"I]	c #F1A93A",
+"J]	c #C99B50",
+"K]	c #DBB274",
+"L]	c #F2D1A4",
+"M]	c #FFE9D1",
+"N]	c #FFF9EF",
+"O]	c #F6FFFF",
+"P]	c #E5AD26",
+"Q]	c #E7A300",
+"R]	c #FFAA00",
+"S]	c #FFA303",
+"T]	c #FBA407",
+"U]	c #FFB600",
+"V]	c #FAB600",
+"W]	c #FDB410",
+"X]	c #FBB400",
+"Y]	c #FCB501",
+"Z]	c #FDB700",
+"`]	c #FEB800",
+" ^	c #FFB900",
+".^	c #FEBA00",
+"+^	c #FEBD00",
+"@^	c #FEBF00",
+"#^	c #FFBC02",
+"$^	c #FFC207",
+"%^	c #F9C205",
+"&^	c #F9BB04",
+"*^	c #FFB709",
+"=^	c #FFB20A",
+"-^	c #FEA700",
+";^	c #EB9A00",
+">^	c #BD8C26",
+",^	c #000019",
+"'^	c #000804",
+")^	c #07000B",
+"!^	c #191126",
+"~^	c #39100C",
+"{^	c #C78B4F",
+"]^	c #ED983B",
+"^^	c #F5973F",
+"/^	c #F5A94B",
+"(^	c #F1B73C",
+"_^	c #F4BA35",
+":^	c #FFBC48",
+"<^	c #FAC63C",
+"[^	c #FFC340",
+"}^	c #FFBE44",
+"|^	c #FEB64A",
+"1^	c #F4AB4F",
+"2^	c #E6A154",
+"3^	c #DF9C56",
+"4^	c #DCBDA1",
+"5^	c #F2D8C1",
+"6^	c #FFF3E5",
+"7^	c #FFFDF6",
+"8^	c #F7FDF9",
+"9^	c #F6FFF9",
+"0^	c #E4A43A",
+"a^	c #E79C0D",
+"b^	c #F89F03",
+"c^	c #F39406",
+"d^	c #F49F08",
+"e^	c #F8AF00",
+"f^	c #EBA100",
+"g^	c #FCAA16",
+"h^	c #F6AB00",
+"i^	c #F7AC01",
+"j^	c #F8AE01",
+"k^	c #F8AE00",
+"l^	c #F9AF00",
+"m^	c #FAB000",
+"n^	c #FBB000",
+"o^	c #FBB200",
+"p^	c #FCB300",
+"q^	c #FBB500",
+"r^	c #FCB800",
+"s^	c #FDB900",
+"t^	c #FFB80D",
+"u^	c #FCBC03",
+"v^	c #F6C000",
+"w^	c #F8BF00",
+"x^	c #FDB400",
+"y^	c #FDA702",
+"z^	c #FEA805",
+"A^	c #FFB00C",
+"B^	c #D79D17",
+"C^	c #361100",
+"D^	c #000F05",
+"E^	c #08000E",
+"F^	c #070016",
+"G^	c #051000",
+"H^	c #4F1E17",
+"I^	c #D08E51",
+"J^	c #EC9536",
+"K^	c #FBA047",
+"L^	c #F4A94C",
+"M^	c #EFB73C",
+"N^	c #F8BE39",
+"O^	c #FFBB47",
+"P^	c #F3B637",
+"Q^	c #FDBD42",
+"R^	c #FFBE4D",
+"S^	c #F3B351",
+"T^	c #E0A557",
+"U^	c #D7A870",
+"V^	c #DFBB97",
+"W^	c #EDCFB7",
+"X^	c #FFF9F5",
+"Y^	c #FFFDF7",
+"Z^	c #FDFCF7",
+"`^	c #F7F9F4",
+" /	c #F5FAF4",
+"./	c #F9FEF8",
+"+/	c #FDFFFA",
+"@/	c #EEA65E",
+"#/	c #E9982C",
+"$/	c #F09312",
+"%/	c #E7880A",
+"&/	c #F19A0C",
+"*/	c #EEA400",
+"=/	c #D98D00",
+"-/	c #F7A013",
+";/	c #EFA200",
+">/	c #F0A300",
+",/	c #F1A400",
+"'/	c #F2A500",
+")/	c #F3A700",
+"!/	c #F4A800",
+"~/	c #F8AC00",
+"{/	c #F9AD00",
+"]/	c #FAAF00",
+"^/	c #FAB100",
+"//	c #FBB700",
+"(/	c #FEAA09",
+"_/	c #FEBC06",
+":/	c #F7C100",
+"</	c #EEB900",
+"[/	c #F8B300",
+"}/	c #FFB30F",
+"|/	c #FEAA0C",
+"1/	c #E99900",
+"2/	c #DFA007",
+"3/	c #562E0B",
+"4/	c #010017",
+"5/	c #050900",
+"6/	c #15031B",
+"7/	c #040015",
+"8/	c #57221A",
+"9/	c #CF8B4C",
+"0/	c #E58E2D",
+"a/	c #FAA147",
+"b/	c #EEA547",
+"c/	c #EAB239",
+"d/	c #F6BC37",
+"e/	c #FEB542",
+"f/	c #FFBE4F",
+"g/	c #FBB347",
+"h/	c #E9A544",
+"i/	c #DA9F51",
+"j/	c #D6AB74",
+"k/	c #E2CBAC",
+"l/	c #F6F2E9",
+"m/	c #F9FFFB",
+"n/	c #F7FFF9",
+"o/	c #F9FFF8",
+"p/	c #FFF8E6",
+"q/	c #F6E6CC",
+"r/	c #E5D0A5",
+"s/	c #D7BB7A",
+"t/	c #D0AC54",
+"u/	c #CCA234",
+"v/	c #C9991B",
+"w/	c #C5930C",
+"x/	c #F38E00",
+"y/	c #EF8C00",
+"z/	c #EB8B00",
+"A/	c #EC9100",
+"B/	c #F19800",
+"C/	c #F29D04",
+"D/	c #F09D01",
+"E/	c #EB9B00",
+"F/	c #FDA600",
+"G/	c #F6A400",
+"H/	c #F3A800",
+"I/	c #F5B00D",
+"J/	c #F3B114",
+"K/	c #F0AE12",
+"L/	c #F2AD11",
+"M/	c #F7B113",
+"N/	c #F9B000",
+"O/	c #FFB506",
+"P/	c #FEB308",
+"Q/	c #FCAD00",
+"R/	c #FFAE01",
+"S/	c #FFA408",
+"T/	c #FD960B",
+"U/	c #D89417",
+"V/	c #2D0200",
+"W/	c #020023",
+"X/	c #110015",
+"Y/	c #0D031E",
+"Z/	c #472D20",
+"`/	c #B77F4E",
+" (	c #E18C32",
+".(	c #F59F32",
+"+(	c #EBA63E",
+"@(	c #F1B553",
+"#(	c #F5AB42",
+"$(	c #FFAC38",
+"%(	c #FFB734",
+"&(	c #FCB839",
+"*(	c #F2BB3D",
+"=(	c #EFBB45",
+"-(	c #F2B948",
+";(	c #F8B54A",
+">(	c #FCB34C",
+",(	c #FFAF49",
+"'(	c #DE903B",
+")(	c #C49253",
+"!(	c #DBC5A0",
+"~(	c #F8F3E0",
+"{(	c #F9FAF2",
+"](	c #F5F6EE",
+"^(	c #FBF8EF",
+"/(	c #FFF8FB",
+"((	c #FFF9F3",
+"_(	c #FFF9EA",
+":(	c #FFF6DB",
+"<(	c #FFECC6",
+"[(	c #FFDDAF",
+"}(	c #F6D19D",
+"|(	c #DBBE78",
+"1(	c #D5B165",
+"2(	c #CD9F47",
+"3(	c #CE932B",
+"4(	c #DA9017",
+"5(	c #E99109",
+"6(	c #F59200",
+"7(	c #FB9400",
+"8(	c #FC9610",
+"9(	c #F59107",
+"0(	c #F19200",
+"a(	c #F59D00",
+"b(	c #F7A600",
+"c(	c #F5AA00",
+"d(	c #F3AE00",
+"e(	c #F5B200",
+"f(	c #F8B200",
+"g(	c #F9B105",
+"h(	c #FAAE0A",
+"i(	c #FBAE0A",
+"j(	c #FEB005",
+"k(	c #FFAE06",
+"l(	c #FEA408",
+"m(	c #F79808",
+"n(	c #C68916",
+"o(	c #290200",
+"p(	c #040021",
+"q(	c #09190F",
+"r(	c #08000C",
+"s(	c #090018",
+"t(	c #202B1B",
+"u(	c #1F0000",
+"v(	c #B7734C",
+"w(	c #FA994A",
+"x(	c #F79532",
+"y(	c #DC8E2C",
+"z(	c #ECAC4A",
+"A(	c #F8B447",
+"B(	c #FFB139",
+"C(	c #FAB33F",
+"D(	c #FEB944",
+"E(	c #FFC048",
+"F(	c #FFC149",
+"G(	c #FFBC47",
+"H(	c #FBB243",
+"I(	c #F9A741",
+"J(	c #F7A13E",
+"K(	c #D6873C",
+"L(	c #DA9A5C",
+"M(	c #E9BF97",
+"N(	c #F9E7D3",
+"O(	c #FBFBFF",
+"P(	c #FDFCFF",
+"Q(	c #FFF2FC",
+"R(	c #F5FFFD",
+"S(	c #F9FFF0",
+"T(	c #F2EBCE",
+"U(	c #EBD3A3",
+"V(	c #E7BC78",
+"W(	c #E0A24D",
+"X(	c #D78C27",
+"Y(	c #D07E12",
+"Z(	c #ED9108",
+"`(	c #EC8D00",
+" _	c #F18D00",
+"._	c #FC9500",
+"+_	c #FF9C00",
+"@_	c #FA9E00",
+"#_	c #EF9B00",
+"$_	c #E89A00",
+"%_	c #F2A107",
+"&_	c #F8A50B",
+"*_	c #F9A706",
+"=_	c #F3A100",
+"-_	c #EE9B00",
+";_	c #EB9703",
+">_	c #C39130",
+",_	c #301003",
+"'_	c #323F38",
+")_	c #797C67",
+"!_	c #B6AAB8",
+"~_	c #C0B8CD",
+"{_	c #DDE5D8",
+"]_	c #754946",
+"^_	c #BA7053",
+"/_	c #D76F32",
+"(_	c #F58635",
+"__	c #F1953E",
+":_	c #E59C3E",
+"<_	c #E39F34",
+"[_	c #F4AC34",
+"}_	c #F8B95A",
+"|_	c #F1B04A",
+"1_	c #EEA63A",
+"2_	c #F1A130",
+"3_	c #F6A033",
+"4_	c #F39A36",
+"5_	c #EA8F36",
+"6_	c #E08333",
+"7_	c #C9956E",
+"8_	c #ECC3A5",
+"9_	c #FFF0E3",
+"0_	c #FFFCFD",
+"a_	c #FEFEFF",
+"b_	c #FFF9FF",
+"c_	c #FFFFF3",
+"d_	c #FEFFF4",
+"e_	c #F8FBF0",
+"f_	c #F1F6EF",
+"g_	c #F1F7F3",
+"h_	c #F5FBFB",
+"i_	c #F7FFFF",
+"j_	c #F0F0F2",
+"k_	c #F5F3F4",
+"l_	c #FFFAF6",
+"m_	c #FFFDF3",
+"n_	c #FFFDEC",
+"o_	c #FFF4DC",
+"p_	c #F9E6C8",
+"q_	c #F0DBBC",
+"r_	c #D29B36",
+"s_	c #D6962A",
+"t_	c #E29219",
+"u_	c #EE920D",
+"v_	c #F69208",
+"w_	c #F79309",
+"x_	c #F2940E",
+"y_	c #F09511",
+"z_	c #F9A700",
+"A_	c #F6A000",
+"B_	c #F79D09",
+"C_	c #FCA00F",
+"D_	c #F89F07",
+"E_	c #ED9A00",
+"F_	c #EC9E08",
+"G_	c #F3A819",
+"H_	c #BE9A50",
+"I_	c #C2AAA0",
+"J_	c #DFDCF1",
+"K_	c #F4F8E9",
+"L_	c #FEF7FF",
+"M_	c #EDE7F5",
+"N_	c #FFE3E0",
+"O_	c #D9A08C",
+"P_	c #B85D30",
+"Q_	c #E3793B",
+"R_	c #FF9B56",
+"S_	c #EB9242",
+"T_	c #E59234",
+"U_	c #F8A73C",
+"V_	c #E7A14B",
+"W_	c #F0A349",
+"X_	c #F9A543",
+"Y_	c #FC9F3F",
+"Z_	c #F3953B",
+"`_	c #E58D43",
+" :	c #D9894E",
+".:	c #D18758",
+"+:	c #EFD8CA",
+"@:	c #FFEFE8",
+"#:	c #FCFCFF",
+"$:	c #F5F7FF",
+"%:	c #FDFDFF",
+"&:	c #FFF5FD",
+"*:	c #FEFFF3",
+"=:	c #FBFFF4",
+"-:	c #F9FFF4",
+";:	c #F9FCFF",
+">:	c #F4FBFF",
+",:	c #F2F9FF",
+"':	c #FFF8F5",
+"):	c #F9DECB",
+"!:	c #E1B588",
+"~:	c #CC8F3F",
+"{:	c #C77A0E",
+"]:	c #D28000",
+"^:	c #E79300",
+"/:	c #F6A106",
+"(:	c #E69300",
+"_:	c #E89000",
+"::	c #EF8F07",
+"<:	c #F2920A",
+"[:	c #E99002",
+"}:	c #E19104",
+"|:	c #E9A422",
+"1:	c #F9BB44",
+"2:	c #FFEEBF",
+"3:	c #FFFBF4",
+"4:	c #F6FCF2",
+"5:	c #F0D6C7",
+"6:	c #C98E70",
+"7:	c #C06B42",
+"8:	c #D2713E",
+"9:	c #DB793C",
+"0:	c #EE8D46",
+"a:	c #EE8D3E",
+"b:	c #E38837",
+"c:	c #EF9340",
+"d:	c #F39744",
+"e:	c #E2883C",
+"f:	c #C87839",
+"g:	c #C38258",
+"h:	c #DAAA93",
+"i:	c #F7CFC3",
+"j:	c #FFFDF8",
+"k:	c #F7FBFC",
+"l:	c #F3F8FC",
+"m:	c #F4F9FD",
+"n:	c #FDFEFF",
+"o:	c #FFF5FF",
+"p:	c #FFF6FF",
+"q:	c #FFFDFE",
+"r:	c #F7FDFF",
+"s:	c #F7FAFF",
+"t:	c #F7F7FF",
+"u:	c #FBF9FE",
+"v:	c #FFFDFB",
+"w:	c #FFFFEF",
+"x:	c #FFF2CC",
+"y:	c #FFD79A",
+"z:	c #ECB563",
+"A:	c #D39331",
+"B:	c #C07C11",
+"C:	c #D89115",
+"D:	c #DF931B",
+"E:	c #E99620",
+"F:	c #EB971D",
+"G:	c #E4991C",
+"H:	c #E2A634",
+"I:	c #F0C368",
+"J:	c #FFDC95",
+"K:	c #FFFBE3",
+"L:	c #FCF9FF",
+"M:	c #FCFDFF",
+"N:	c #F2F7F1",
+"O:	c #F8FDF9",
+"P:	c #E7F3F1",
+"Q:	c #F5F5ED",
+"R:	c #E9D2C2",
+"S:	c #CC9A81",
+"T:	c #C9805D",
+"U:	c #CE774A",
+"V:	c #E98B58",
+"W:	c #DA7A47",
+"X:	c #EB8441",
+"Y:	c #E2803F",
+"Z:	c #D67D43",
+"`:	c #C98151",
+" <	c #CA9374",
+".<	c #D9B8A7",
+"+<	c #F4E2DE",
+"@<	c #F5FBF9",
+"#<	c #FDFAFF",
+"$<	c #FBF8FF",
+"%<	c #FEF9FF",
+"&<	c #F4FEFF",
+"*<	c #FFFCF4",
+"=<	c #FFFBF1",
+"-<	c #F8FFF0",
+";<	c #F7FFF1",
+"><	c #F3FEF0",
+",<	c #F2F8EC",
+"'<	c #FAF4E4",
+")<	c #FFEDD5",
+"!<	c #FFDCBC",
+"~<	c #F7C9A5",
+"{<	c #E1B15D",
+"]<	c #EDB761",
+"^<	c #F5B85B",
+"/<	c #F3B850",
+"(<	c #F0C159",
+"_<	c #F6D785",
+":<	c #FFF0C5",
+"<<	c #F3F4EF",
+"[<	c #FDFCFA",
+"}<	c #F8E6DA",
+"|<	c #F9D1B8",
+"1<	c #DFA482",
+"2<	c #E6A07E",
+"3<	c #CE8564",
+"4<	c #D8774C",
+"5<	c #D47F58",
+"6<	c #DA977A",
+"7<	c #F0C1AF",
+"8<	c #FFEDE4",
+"9<	c #FFFCFA",
+"0<	c #FCFCFA",
+"a<	c #FAFAF8",
+"                                                . +   @     # $ % & *   = - ; > , ' ) ! ~ ~ { ] ^ / ( * _ = @ _   @   . +   .                                                 ",
+"                                                    _   *     :     < [ } | 1 2 ! ~ 3 4 4 3 ~ ! ~ ~ 5 6 7       8     @   _                                                   ",
+"                                                    <   .     $ % 9 0 a ~ b ~ ~ ~ c d ~ ~ c e 3 ~ f g ~ h i @ 9 +     %   _   $                                               ",
+"                                                .   & *     j   k l ~ g ~ ~ 1 e m ) ! ! ~ ~ ~ 3 4 ~ ~ 1 m n > @   % $   9   . $                                               ",
+"                                                *     *   * . o p d ) ~ 4 m ~ ~ ~ ~ ~ 4 d ~ ~ ~ ~ ) 4 ) ~ ~ e q r   s   =   *                                                 ",
+"                                                    *   = %   t 4 ~ c ! ~ ! c n m c 2 ~ ~ 2 c m m c ~ ~ ! 4 4 a u   @     *                                                   ",
+"                                                  $     # + v w ~ x ~ ~ a m ~ ~ ~ 2 m 3 ~ ) ~ ~ g y q w ~ ~ ~ ! z A %     +                                                   ",
+"                                                  %   B s   C 4 ~ ~ 3 D ~ ~ w ~ ~ ~ ~ ~ 3 ! ) m E F G H n 4 ) ! c I s   @     .                                               ",
+"                                                          J 1 2 c ~ 2 ~ ~ 2 c ~ ~ 3 ! ~ ~ d 4 ~ K L L M N ~ 4 ) 3 ~ / + .   s                                                 ",
+"                                                . _ s +   O ! ~ ~ ~ ~ 2 d ~ ~ ! 1 ~ ~ ~ ~ ~ ~ ) P C Q n R a ~ ~ 1 ~ I j _     =                                               ",
+"                                                .   . +   S 2 ~ 4 D ~ ~ ~ e ! ~ ~ ~ ~ 2 4 4 d c T 1 ~ x ~ ~ ~ n ~ 2 ~ U   =   .                                               ",
+"                                                      &   V 4 ! ~ ~ ~ 4 e ~ ~ 2 ~ 4 c ~ ~ ! ~ ~ ) Q ~ ) ~ g ~ ~ ~ ~ Q W . %                                                   ",
+"                                                _   $ . _ X ! ~ ! ~ a z ~ ~ ) 3 ) 4 ) ~ ~ ~ ! 4 ~ T 3 ~ ~ 2 ~ T z ~ b Y B & _ $                                               ",
+"                                                $ $ $ _ . ~ ! ~ 3 ~ d D g g e ~ 4 ~ ~ z 4 ~ ~ d 2 Z `  .z m X ~ 3 ~ ~ ..&     *                                               ",
+"                                                  &     & ~ ) ! ~ ~ +.L @.l ~ ~ ! 3 ~ ~ 3 1 R #.$.~ P %.&.g ~ n ~ ) 3 *.@ &   $                                               ",
+"                                                  9     * ~ ! ~ =.-.;.S &...z ! ~ T 1 ~ { >.i ,.'.).@.| !.~.~ ) c ~ ~ T {.+ _ _                                               ",
+"                                                    .   8 ~ ) ].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.: 8.9.0 q 0.b ~ 3 ~ ~ ! r $ $                                                 ",
+"                                                & +   *   b D a.b.c.d.e.f.g.h.h.i.j.k.l.m.n.o.p.      q.r.1 ~ ~ 3 ~ ~ ! r $ $                                                 ",
+"                                                  &   < s ~ s.{.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.> K.  L.b ~ n 3 ~ ~ ! r $ $                                                 ",
+"                                                    s   * ! M.N.O.P.Q.R.S.T.U.h.V.W.X.Y.Z.`. +.+1 ++U   < K 3 ~ 3 ~ ~ ! r $ $                                                 ",
+"                                                    +   & ~ M.@+#+$+X.%+&+*+=+-+;+>+,+'+)+h.!+~+z {+, ]+s 0.m 4 3 ~ ~ ! r $ $                                                 ",
+"                                                      #   ~ s.@ ^+/+(+_+:+<+[+}+|+1+X.2+3+$+$+4+! 5+>.    Z ~ ) 3 ~ ~ ! r $ $                                                 ",
+"                                                +     s   z D q.6+7+~ 8+9+0+a+b+c+d+e+f+g+h+i+i+~ y j+9 L.a ~ 2 3 ~ ~ ! r $ $                                                 ",
+"                                                $   s   . ~ ) W k+l+x m+n+o+p+q+r+s+t+u+v+w+x+y+4 x o + i 4 T ~ 3 ~ ~ ! r $ $                                                 ",
+"                                                z+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+`+ @.@+@@@~ z ~ ~ #@  &                                                 ",
+"                                                $@%@B+Z+C+X.X.&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@1@2@3@2 d ~ ~ >   s                                                 ",
+"                                                A+4@B+5@C+6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@! ~ ~ ~ w@                                                    ",
+"                                                x@A+y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@w+Y@Z@u@~ ~ ~ ~ `@.                                                   ",
+"                                                 #  .#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#:#<#[#}#i.|#1#~ 1 ~ d Q 2#& s                                               ",
+"                                                A+3#B+4#5#6#7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#m+t#u#~ 4 ~ c ~ v#*                                                 ",
+"                                                A+w#B+x#y#z#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#|+X#}+n ~ 3 m ~ ..:                                                 ",
+"                                                A+  Y#Z#`# $J+.$+$@$#$$$%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($;+_$:$E ~ X c ~ ) k s                                               ",
+"                                                $ $ .   9 <$) 4 [$}$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$w+h$i$j$#@k$N ! ~ 3 l$& @   *   s   *                                 ",
+"                                                  *   $ . m$z ! n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$m+|+H$I$@.J$K$L$n ~ E M$    . &   @   s                               ",
+"                                                  8   B % ^ z ~ N$O$P$Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%@%#%$%%%&%4+*%V W =%].m ~ 3 -%% B   9       _                               ",
+"                                                  < 9 _ ).m ~ 1 ;%>%,%'%)%!%~%{%]%^%/%(%_%:%<%[%}%|%1%2%3%4%5%H$~ 6%=.b ~ ) ~ ) 7%*     +                                     ",
+"                                                %   < 8%-%3 ~ e 9%0%a%b%c%d%e%f%g%h%i%j%k%l%m%n%o%p%d.q%r%i+s%t%~ c e ~ ~ g ~ 2 u%= s     8   *                               ",
+"                                                s     v%~ w%~ ~ x%y%z%A%B%C%D%E%F%G%H%I%J%K%L%M%N%Z#O%O%P%Q%R%S%4 ~ ~ ~ ) d ~ c z 0   %     9                                 ",
+"                                                  9 v x ~ z ~ | T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&-&# ;&>&,&'&3 ~ 3 ~ ~ ~ ~ 4 c )&!&]+*   ~&                                ",
+"                                                9 . P Q ) 3 ! {&]&^&/&(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&8&9&8&0&a&b&~ ~ d ~ ~ d ~ ~ 3 ~ c&  + s   &                               ",
+"                                  @ @   $ 9   _   W ~ ~ T 3 d&@+s $ _ : e&f&f&g&g&N.8.: + _     .       + & h&X n ~ ~ n ~ ~ m 2 ~ m ) i&  #   $   _ &                         ",
+"                                =     _ =   8   ;.R 2 a ~ x j&& * _ $ s B h&- h&8 < + $       $ * & $   .     c&~ 4 2 ~ ~ z c ~ ) ~ c k&l&  9 &           $ _ $               ",
+"                                %         % 9 ]+m&2 c ) ~ $.* $ _ $         _ * + * & _ _ . s 9   _     . _   [ 4 n ! ~ 4 ~ ~ e z 4 2 2 n&  + $ _         _ _ $               ",
+"                                &   . &   B   o&~ D ~ ~ x p&9   $ _ _ _ $ _ . s                   .   & + . $ * u%n ~ 4 a ! ~ 2 ~ g ~ ~ d q&s 9 . $ $ & _     $               ",
+"                                .     B +   U a ~ 4 ~ ) K ~&  s & _ & . s s . _     _ & & $     s *   + *   # s L z ~ ! a d&r&~ ~ ~ c ! ~ 5 s&      & s &     &               ",
+"                                    %     % t&~ b ~ c 3 u&_   .                   $ _ & . * * * $     _ &   ~&( o&1 ~ ) ~ +.| #.D ~ ~ z X 2 v&8       & $     *               ",
+"                                  * w&  ]+++~ X ~ ~ ~ 3 x&w&-     & * * . 9 : ~&B = &       $ . +   8 % - K.k 2#y&z&~ d ~ ~ T A&| e ~ ~ ~ d ~ B&w&.           &               ",
+"                                9   & < C&4 e ~ d ~ 3 D&E&F&G&g&@ K.( 8.( e&s&y&H&[ I&K.@ @ 8 h&!&j J&e&; [ J g&r M 4 ~ m e ~ X K&p J.~ 3 4 c g r ]+    _                     ",
+"                $ $               s   ~&r&2 ~ 3 ~ 2 n *.M$a.a.J s @ 8%I&<$j&L&(.{.k ~&: % + < - M&M&<$J J&L.N&O&_.i ~ ! 1 ! ~ ~ b A&P&~ ! 1 ~ ) d&  ]+  +   &                 ",
+"                $ $           $   . $ K$a ~ ~ ! ) ~ ) &.L&r 8%. & _ * s < k ; r w&@ . & $   & = . < ( M&Q&(.y&C&R&R&u&~ ~ ~ m c ~ p S&L$c ~ ~ 2 e T&  _   +                   ",
+"                $ $         $ $ s   G&w ~ ~ ~ ~ m ~ I i&8.+   & .         B j @+$     $ $     &   $ * % K.I&{.v i&(.U&D&3 2 ! 3 ~ n V&&.r&~ 2 ~ ~ z&e&s   9   $               ",
+"                $         $ _ _ =   P&) ~ ~ n ~ c ~ r.-   $   8 _   . .   = : + _ _ & * * & $ $ + *         # ( W&_.G&, 3 e ~ ~ c ~ +.X&k&! c ~ ~ ~ ^ + &   & .               ",
+"                $       $ _ & &   R&) T ~ ) d 2 ) g -.%   +         . s   & s   $ _ _ $   $       $ s * $     & _ N.N&;.g ~ c ~ g ~ 2 Y Y&Q d ~ 4 4 X I&    s _               ",
+"                $       $ _ . . & Z&~ c ~ X ~ z ) ~.K._   & &   _   $ $     * $           $ & $     & . _ $ _ .   B B `&l$~ D ~ 2 ~ d z&++D&~ d ~ X ~ v#  s                   ",
+"                      $ _ & . *  *m d 4 ~ z&~ d J.;.        9 * *   $ _     * *   _ $     & * & . _         _ * * s   s .*+*2 ~ ~ ! m T , @*~ 4 ~ c ~ t&h&*                   ",
+"                      $ _ & . * v%~ ~ b ~ y b ~ *.  s % @       $   _ *     $     . &     _ _       $ * + s $     * * _ + L$~ g ~ ) ~ ~ X&S&~ ~ ) ~ e ~ O&  $ *               ",
+"                    *   s =   h&c z ~ b #*K ~ d {.8   & 9     &                                                 s   $ . < , ~ ~ ) ~ 4 ! V&u&2 ~ ~ ~ 2 ) L _ * *               ",
+"                    &     &   0 ~ 2 2 3 R e ~ F ~&*   _ .     .                                                   & s   . y&z 4 3 ~ ) 4 @*G z 4 ) ~ ~ ~ $** 9                 ",
+"                          & = s.~ 3 g z %*! Q .*    $ & $     _                                                   9 _   # ~&3 ~ ~ 2 3 4 u%&*1 d 2 ~ 3 ~ 2 j =                 ",
+"                *     * . s .*m c 3 z p **z M @   & + .                                                           s     @+w&c ~ ~ m ~ 2 d&K&2 ~ ~ ~ ) 4 ~ =*. .               ",
+"                *     9   $ > ! ) ~ ~ -*D 2 ++    * *     & $                                                   9 _   & = 8 ' 3 ~ d ~ 3 d&V&3 ~ ~ ~ ! a ~ F   s               ",
+"                    9 .   # d&~ ~ ! g ;*~ ~ C&  $ $       & _                                                       & =   = ] ~ ~ 2 ~ 3 u%q ) 2 3 ~ ~ m ! r&  &               ",
+"                    9 _   R&z ~ ~ m $*`@~ { >*  _       $ $ $ _                                                     _ 9   * u ~ 2 ~ ! ! ].I ) ) ) ~ ~ ~ ) n                   ",
+"                      & ]+++~ ~ ~ ) $.5 n ' 9 * * _ _ s .     .                                                   &     _   S&e 1 ~ d 3 =.+.~ ~ ! ~ 2 3 c R s $               ",
+"                ,*P%'*)*!*~*{*]*^*i./*(*_*:*  <*                                                                [*=&}*|*1*2*3*/+e ~ ) ~ =.m d ~ ~ ~ ~ d ) d G&$               ",
+"                    4*A+5*6*i+i+i+7*8*9*0*a*]+                                                                  b*$@c*Z#Z#P%d*e*~ ~ e 1 6%~ ! d m 4 ! 2 3 3 ).&               ",
+"                f*g*h*i*j*k*A#l*X.m*n*o*p*5+q*r*                                                                s*|*t*u*v*&&w*x*m b b X J.~ ~ z ! ~ ) ~ ~ 3 y*                ",
+"                b*A+z*A*B*X.C*D*2@2@E*F*2@G*H*c*                                                                |*b*C+I*J*K*L*M*~ ! ~ 1 w ! ~ ~ H$H$N*H$H$O*P*B+$             ",
+"                '*Q*R*S*T*U*V*W*X*~ Y*Z*`* =.=+=                                                                =&@=#=$=$=%=&=*=%*L$t&$.D&2 ~ ~ H$==-=H$H$;=>=y@_ $ $         ",
+"                ,='=)=!=~={=]=^=J+m+/=(=_=:=H*<=                                                                [=}=g**+b*|=1=2=b ~ ~ d **-%**c H$3=H$H$4=5=6=C+_ _ _ $       ",
+"                &&7=8=9=0=a=b=c=d=e=m+~ f=g=h=i=                                                                #=&&j=k=l=m=n=%%~ 4 1 4 ~ ~ D&s.o=p=H$q=4=r=5@C+& & _ $       ",
+"                s=!=B+t=u=v=w=x=y=z=A=i+B=C=D=E=                                                                F=G=H=I=J=K=L=M=d ! ! ~ 4 ~ Q ~ N=O=P=Q=h.R=S=T=. & _ _ $     ",
+"U%&&U=V=W=X='*Y=l=$@!=Z=`= -.-+-@-#-$-%-&-*-X.=-@   B   _ . &             $ $ $                         _ $ $ & --;->-,-'-)-!-~-{-]-^-/-(-_-]-:-h.:-<-[-}-|-1*1-2-=&Z#H*H*    ",
+"}*3-4-5-6-b*7-8-9-0-a-b-c-d-e-f-g-h-i-j-8@k-l-~-0.H&  K.  s   _           $ $ $                 $     $ _     & m-n-o-p-q-r-s-t-u-i+i+8@8@v-6*u-w-x-y-z-A-B-C-D-E-=&Z#H*H*    ",
+"F-G-9&  H-I-J-8&F-K-L-M-N-O-P-Q-R-S-T-U-V-.@W-/+~ w%s&      *               $ $                 _     $ $     & X-Y-Z-`- ;.;+;@;#;H$H$$;%;H$H$&;*;=;-;;;>;,;';);E-!;=&H*H*    ",
+"~;{;|*];^;/;(;_;:;<;[;};|;1;2;3;4;5;6;7;8;9;8@0;4 ~ 5 9._   * *                                 &     $ $     * a;b;c;d;e;f;g;h;i;X.j;k;k;j;X.~ l;m;n;o;p;q;r;s;t;u;=&H*H*    ",
+"v;w;x;y;z;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;d ~ ~ N c&@   s                                 _     _     $ + T;U;V;W;X;Y;Z;`; >.>+>@>@>#>$>%>&>*>=>->;>>>,>'>)>7=!;!>H*    ",
+"~>{>]>^>/>(>_>:><>[>}>|>1>2>3>4>5>6>7>8>9>0>a>b>~ n ~ ~ a F     $ $                             $     _     & % c>d>e>f>g>h>i>j>k>l>m>n>o>m>p>q>r>s>t>u>v>w>x>y>z>7=u;!>H*    ",
+"A>B>C>D>E>F>G>H>I>J>K>L>M>N>O>P>Q>R>S>T>U>V>W>X>4 m a ~ X 1 &*@ $ $ $                                 _     . # Y>Z>`> ,.,+,@,#,$,%,&,*,=,-,;,>,,,',),!,~,{,],^,V=x#u;/,H*    ",
+"(,_,:,<,[,},|,1,2,3,4,5,6,7,8,9,0,a,b,c,d,e,f,g,b ~ 3 Q ~ ~ Q h,$ $ $                                 $     * : i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,V=x#7=/,!>    ",
+"G,H,I,J,K,L,M,N,O,O,O,O,O,O,O,O,P,P,Q,R,R,S,T,U,V,W,R;X,Y,Y@==Z,&.  : .   $                       s & _       = `, '.'+'@'#'$'%'&'*'='-'-'='*'&';'>'O>,''')'!'~'{']'*+#=^'/'&&",
+"('_':'<'['}'|'1'2'2'2'2'2'2'2'2'3'P,4'5'5'6'7'8'9'0'a'b'X.4+c'X.g d'  .   & s                   *     s $ $ + s e'f'g'h'i'j'k'l'm'm'&'&'&'&'m'm'>'6'O>n'o'p'q'r's't'u'*+v'w'i*",
+"Z#x'y'z'A'B'C'D'E'E'E'E'E'E'E'E'F'G'H'O,2'I'U,J'a#K'L'R;i+M'H$~ 2 P   _ %     +                 @   = $   % _ 9 N'O'P'Q'R'S'T'U'V'V'n'n'n'n'V'V'W'2'O>n'X'Y'Z'p'`' ).)+)n.@)#)",
+"$)%)&)*)=)-);)>),),),),),),),),)')))!)2'2'~){)'#])^)/)()_):)<)[)2 k&# 8.    h&                    K.  % <   K.  })|)1)2)3)4)T'5)6)6)V'V'V'V'6)6)3'!)O>7)8)9)0)a)b)c)d)e)f)g)C+",
+"h)i)j)k)l)m)n)o)E'E'E'E'E'E'E'E'')))O,O,2'E'p)'#q)r)s)t)u)v)w)x)3 -*.   & $ _                           8 *   _.y)9;z)A)B)C)D)E)F)F)F)F)F)F)F)F)G)P,F)H)H)I)J)K)L)M)N)O)P)Q)R)",
+"S)T)U)V)W)X)Y)F'O,O,O,O,O,O,O,O,2'O,5'R,5'2',)Z)`) !.!+!@!#!w+$!y -.  9     #                   .   B     & {.-%_$9;%!&!*!=!-!;!H)H)F)F)F)F)H)H)>!,!F)F)'!)!!!~!{!]!^!7,/!(!_!",
+":!<![!}!|!1!2!3!R,R,R,R,R,R,R,R,5'R,4!5!4!R,2'E'6!7!8!9!0!a!b!c!y&j $ _ %     %                   I&  9 < !&s.~ d!e!f!g!h!i!j!k!I'E'))))))))E'I',!,!l!!)E'')m!n!o!K)D)p!q!r!s!",
+"t!u!v!w!x!y!z!A!4!4!4!4!4!4!4!4!4!5!B!B!B!4!5'O,C!D!E!F!G!H!I!J!  < s     %                     %   # $ Q&y ~ 1 h.K!L!M!N!O!P!k!I'E'G'Q!Q!G'E'I'R!,!l!))')S!T!U!V!W!X!Y!C)Z!`!",
+" ~.~+~@~#~$~%~&~*~=~=~-~-~;~;~>~,~>~'~)~!~~~{~]~^~/~(~[,_~:~<~[~}~C+|~H*$)1~2~|*& _ $       & s s   % 3~x ~ b ~ 4~5~6~7~8~9~0~a~E'))))G'G'))))E'b~R,c~J)d~e~Y!f~g~h~i~j~k~l~m~",
+"n~o~p~q~r~s~t~u~>~,~,~v~v~w~w~w~x~y~z~A~B~C~D~D~E~F~0~G~H~I~J~K~L~M~A+s N~O~H*P~      s @ =     $ !&v&~ 1 ~ ~ +*Q~R~S~T~U~V~X)W~E'))))G'G'))))E'X~Y~Z~`~ {.{+{@{#{${%{&{*{={-{",
+";{>{,{'{){!{~{{{]{]{^{^{/{({({({_{_{:{:{<{[{}{|{1{2{3{4{5{6{7{8{9{0{a{b{#)c{  d{  + @ _     9 ( e{f ~ c ~ 2 X ~ f{g{h{i{j{k{l{m{E'E'))))))))E'E'n{o{o{p{>'q{r{s{t{u{v{w{x{y{z{",
+"A{B{C{D{E{F{G{H{I{I{J{K{L{L{M{M{N{N{O{P{P{Q{R{S{T{U{V{W{X{Y{Z{`{ ]R;.]+]@]#]$]%]  . & _ ~&d'F +.2 ~ 2 1 ~ ~ ! ~ &]*]=]-];]>],]']I'E'))))))))E'I')]!]6)~]{]]]H'^]/](]_]:]<][]  ",
+"}]|]1]2]3]4]5]6]7]7]7]8]9]9]0]a]b]9]c]d]e]f]f]g]M{h]i]j]k]l]m]n]o]9;W*p]q]r]s]t]u]K&P s.5 X d 3 ~ +*) ~ d 3 ~ 1 v]w]x]y]z]A]B]C]I'I'E'))))E'I'I'D]R,{]E]F]G]H]I]J]K]L]M]N]+#O]",
+"P]Q]R]S]T]U]V]W]X]X]Y]Z]Z]`] ^ ^Z]Z]`].^9]+^@^@^#^$^%^&^*^=^-^;^>^e!,^'^$+)^!^4+~ ~ ~ 3 ~ ~ ~ ~ ) ~ ~ g ~ ! a ~ ~^{^]^^^/^(^_^:^I'I'E'E'E'E'I'I'<^4'[^}^|^1^2^3^4^5^6^7^!;8^9^",
+"0^a^b^c^d^e^f^g^h^h^i^j^k^l^m^m^n^o^p^q^4]r^s^.^t^u^v^w^x^y^z^A^B^C^W*D^4+E^F^G^X c ~ ~ ! ) ~ ~ z 2 ~ 3 ~ ~ ~ 4 H^I^J^K^L^M^N^O^T,I'I'E'E'I'I'T,P^Q^R^S^T^U^V^W^X^Y^Z^`^ /./+/",
+"@/#/$/%/&/*/=/-/;/;/>/,/'/'/)/!/~/{/]/^/o^q^////(/_/:/</[/}/|/1/2/3/4/b&5/6/7/u@~ ~ 4 ! ~ ~ ~ m ~ ~ ~ ~ 3 4 ) 2 8/9/0/a/b/c/d/e/T,I'I'E'E'I'I'T,f/g/h/i/j/k/l/!=8=S=m/n/o/H*b*",
+"p/q/r/s/t/u/v/w/x/y/z/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/{/Q/R/S/T/U/V/W/u@4+X/Y/u@~ d z 3 ~ ) 2 ~ 4 ~ ~ ) ) ~ ~ ) Z/`/ (.(+(@(#($(>>%(&(*(=(-(;(>(,('()(!(~({(](^(              ",
+"1*/(((_(:(<([(}(|(1(2(3(4(5(6(7(8(9(0(a(b(c(d(e(f(g(h(i(j(k(l(m(n(o(p(q(5/r(s(t(s.z&r&L$n&7%x&v%H l $*-%| x ) 3 u(v(w(x(y(z(A(B(C(D(E(F(G(H(I(J(K(L(M(N(O%B+A+b*              ",
+"O(O(P(*+'*'*U%Q(R(S(T(U(V(W(X(Y(Z(`( _._+_@_#_$_h^'/%_&_*_=_-_;_>_,_W*'_)_!_~_{__     _ . _ . % $ & _ $ ]+f&,./ ]_^_/_(___:_<_[_}_|_1_2_3_4_5_6_7_8_9_0_a_6-b*b_              ",
+"c_d_e_f_g_h_i_!=j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z_A_B_C_D_E_F_G_H_I_J_!=K_L_M_=&]++ $ * 9 s _   * * $     * < < N_O_P_Q_R_S_T_U_V_W_X_Y_Z_`_ :.:+:@:0_#:$:%:*+&:              ",
+"c_c_c_c_*:=:-:-:|*'**+b*6-;:>:,:':):!:~:{:]:^:/:(:_:::<:[:}:|:1:2:3:*+8&4:  b*H*    $ _       9 * + s & $       O%5:6:7:8:9:0:a:b:c:d:e:f:g:h:i:j:/,k:l:m:n:$@P%              ",
+"o:p:1**+q:q*t;z>r:s:$:t:u:q:P%v:^'8&w:x:y:z:A:B:C:D:E:F:G:H:I:J:K:,=L:M:N:O:* *+s _     & &               & s + P:Q:R:S:T:U:V:W:X:Y:Z:`: <.<+<b*@<@<S=C++#7=Z^i*              ",
+"b*b*b*#<$<%<*+b*&<i_!=C+H*i**<=<-<;<><,<'<)<!<~<{<]<^</<(<_<:<H-./<<4*A+8&w'Z#*+  $ 9 &       _ @ 9 * &         C+C+[<}<|<1<2<3<4<5<6<7<8<9<  D+m:0-B+  H*0<a<Y#              "};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/pixmaps.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,23 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pixmaps/logo.xpm"
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/routes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/routes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/routes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/routes.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,77 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*
+ * Route entries are registered
+ * separatly from the node set
+ *
+ * This set is not used for anything in particular
+ * intended for future use
+ */
+
+#include "routes.h"
+
+
+int
+init_route_entries()
+{
+  route_count = 0;
+
+  route_set.next = &route_set;
+  route_set.prev = &route_set;
+
+  return 1;
+}
+
+
+int
+add_route_entry(struct route_entry *entry)
+{
+  struct route_entry *new_entry;
+
+  if((new_entry = malloc(sizeof(struct route_entry))) == 0)
+    {
+      fprintf(stderr, "OUT OF MEMORY!\n");
+      exit(1);
+    }
+
+  /* queue */
+  new_entry->next = route_set.next;
+  route_set.next->prev = new_entry;
+  route_set.next = new_entry;
+  new_entry->prev = &route_set;
+
+  route_count++;
+
+  return 1;
+
+}
+
+int
+del_route_entry(struct route_entry *entry)
+{
+
+  route_count--;
+
+  return 1;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/routes.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/routes.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/linux-gtk/src/routes.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/linux-gtk/src/routes.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,67 @@
+/*
+ * OLSR ad-hoc routing table management protocol GUI front-end
+ * Copyright (C) 2003 Andreas TÃ¸nnesen (andreto@ifi.uio.no)
+ *
+ * This file is part of olsr.org.
+ *
+ * uolsrGUI is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * uolsrGUI 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 olsr.org; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*
+ * Route entries are registered
+ * separatly from the node set
+ *
+ * This set is not used for anything in particular
+ * intended for future use
+ */
+
+#ifndef _OLSRD_FRONTEND_ROUTE
+#define _OLSRD_FRONTEND_ROUTE
+
+#include "common.h"
+
+#define MAX_IF_NAMESIZ  10
+
+struct route_entry
+{
+  union olsr_ip_addr gw;
+  union olsr_ip_addr dst;
+  olsr_u16_t         hopcnt;
+  char               if_name[MAX_IF_NAMESIZ];
+  struct route_entry *next;
+  struct route_entry *prev;
+};
+
+/* List */
+struct route_entry route_set;
+
+/* Counter */
+olsr_u32_t route_count;
+
+/* Functions */
+
+int
+init_route_entries();
+
+int
+add_route_entry(struct route_entry *);
+
+int
+del_route_entry(struct route_entry *);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Inst/installer.nsi ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Inst/installer.nsi
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Inst/installer.nsi	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Inst/installer.nsi	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,195 @@
+;
+;  The olsr.org Optimized Link-State Routing daemon (olsrd)
+;  Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+;  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.
+;
+;
+
+Name olsr.org
+OutFile ..\..\..\olsr-setup.exe
+BrandingText "www.olsr.org"
+InstallDir $PROGRAMFILES\olsr.org
+LicenseData ..\..\..\license.txt
+XPStyle on
+
+Page license
+Page components
+Page directory
+Page instfiles
+
+UninstPage uninstConfirm
+UninstPage instfiles
+
+Function .onInit
+        MessageBox MB_YESNO "This will install olsr.org 0.5.6-rc6-247f41fa940a on your computer. Continue?" IDYES NoAbort
+        Abort
+NoAbort:
+FunctionEnd
+
+InstType "ETX Configuration (recommended)"
+InstType "RFC Configuration"
+
+Section "Program Files"
+
+        SectionIn 1 2 RO
+
+        SetOutPath $INSTDIR
+
+        File ..\Main\release\Switch.exe
+        File ..\Shim\release\Shim.exe
+        File ..\..\..\olsrd.exe
+        File ..\..\..\src\cfgparser\olsrd_cfgparser.dll
+        File /oname=README.txt ..\..\..\README
+        File /oname=README-LQ.html ..\..\..\README-Link-Quality.html
+        File /oname=README-Fish-Eye.txt ..\..\..\README-Link-Quality-Fish-Eye.txt
+        File ..\..\..\README-Olsr-Switch.html
+        File linux-manual.txt
+        File ..\Main\RFC-Default.olsr
+        File ..\Main\LQ-Default.olsr
+        File ..\..\..\lib\dot_draw\olsrd_dot_draw.dll
+        File ..\..\..\lib\httpinfo\olsrd_httpinfo.dll
+        File ..\..\..\lib\mini\olsrd_mini.dll
+        File ..\..\..\lib\pgraph\olsrd_pgraph.dll
+        File ..\..\..\lib\secure\olsrd_secure.dll
+        File ..\..\..\lib\txtinfo\olsrd_txtinfo.dll
+
+        WriteRegStr HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\olsr.org DisplayName olsr.org
+        WriteRegStr HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\olsr.org UninstallString $INSTDIR\uninstall.exe
+
+        WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\olsr.org NoModify 1
+        WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\olsr.org NoRepair 1
+
+        WriteUninstaller $INSTDIR\uninstall.exe
+
+SectionEnd
+
+Section "ETX Configuration"
+
+        SectionIn 1 RO
+
+        File ..\..\..\gui\win32\Main\RFC-Default.olsr
+        File ..\..\..\gui\win32\Main\LQ-Default.olsr
+        File /oname=Default.olsr ..\..\..\gui\win32\Main\LQ-Default.olsr
+
+SectionEnd
+
+Section "RFC Configuration"
+
+        SectionIn 2 RO
+
+        File ..\..\..\gui\win32\Main\RFC-Default.olsr
+        File ..\..\..\gui\win32\Main\LQ-Default.olsr
+        File /oname=Default.olsr ..\..\..\gui\win32\Main\RFC-Default.olsr
+
+SectionEnd
+
+Section "Start Menu Shortcuts"
+
+        SectionIn 1 2
+
+        CreateDirectory $SMPROGRAMS\olsr.org
+
+        CreateShortCut "$SMPROGRAMS\olsr.org\OLSR Switch.lnk" $INSTDIR\Switch.exe "" $INSTDIR\Switch.exe 0
+        CreateShortCut $SMPROGRAMS\olsr.org\README.lnk $INSTDIR\README.txt
+        CreateShortCut $SMPROGRAMS\olsr.org\README-LQ.lnk $INSTDIR\README-LQ.html
+        CreateShortCut $SMPROGRAMS\olsr.org\Uninstall.lnk $INSTDIR\uninstall.exe "" $INSTDIR\uninstall.exe 0
+
+SectionEnd
+
+Section "Desktop Shortcut"
+
+        SectionIn 1 2
+
+        CreateShortCut "$DESKTOP\OLSR Switch.lnk" $INSTDIR\Switch.exe "" $INSTDIR\Switch.exe 0
+
+SectionEnd
+
+Section "File Association (*.olsr)"
+
+        SectionIn 1 2
+
+        WriteRegStr HKCR .olsr "" OlsrOrgConfigFile
+
+        WriteRegStr HKCR OlsrOrgConfigFile "" "olsr.org Configuration File"
+
+        WriteRegStr HKCR OlsrOrgConfigFile\shell "" open
+        WriteRegStr HKCR OlsrOrgConfigFile\DefaultIcon "" $INSTDIR\Switch.exe,0
+        WriteRegStr HKCR OlsrOrgConfigFile\shell\open\command "" '$INSTDIR\Switch.exe "%1"'
+
+SectionEnd
+
+Section "Uninstall"
+
+        DeleteRegKey HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\olsr.org
+
+        DeleteRegKey HKCR .olsr
+        DeleteRegKey HKCR OlsrOrgConfigFile
+
+        Delete $INSTDIR\Switch.exe
+        Delete $INSTDIR\Shim.exe
+        Delete $INSTDIR\olsrd.exe
+        Delete $INSTDIR\olsr_switch.exe
+	Delete $INSTDIR\olsrd_cfgparser.dll
+        Delete $INSTDIR\README.txt
+        Delete $INSTDIR\README-LQ.html
+        Delete $INSTDIR\README-Fish-Eye.txt
+        Delete $INSTDIR\README-Olsr-Switch.html
+        Delete $INSTDIR\linux-manual.txt
+        Delete $INSTDIR\Default.olsr
+        Delete $INSTDIR\RFC-Default.olsr
+        Delete $INSTDIR\LQ-Default.olsr
+	Delete $INSTDIR\olsrd.conf.rfc
+	Delete $INSTDIR\olsrd.conf.lq
+        Delete $INSTDIR\olsrd_dot_draw.dll
+        Delete $INSTDIR\olsrd_httpinfo.dll
+        Delete $INSTDIR\olsrd_mini.dll
+        Delete $INSTDIR\olsrd_pgraph.dll
+        Delete $INSTDIR\olsrd_secure.dll
+        Delete $INSTDIR\olsrd_txtinfo.dll
+        Delete $INSTDIR\uninstall.exe
+
+        RMDir $INSTDIR
+
+        Delete "$SMPROGRAMS\olsr.org\OLSR Switch.lnk"
+        Delete $SMPROGRAMS\olsr.org\README.lnk
+        Delete $SMPROGRAMS\olsr.org\README-LQ.lnk
+        Delete $SMPROGRAMS\olsr.org\Uninstall.lnk
+
+        RMDir $SMPROGRAMS\olsr.org
+
+        Delete "$DESKTOP\OLSR Switch.lnk"
+
+SectionEnd
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Inst/linux-manual.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Inst/linux-manual.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Inst/linux-manual.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Inst/linux-manual.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,134 @@
+olsrd(8)                                                              olsrd(8)
+
+
+
+NAME
+       olsrd - Optimized Link State Routing protocol daemon
+
+SYNOPSIS
+       olsrd  [  -i   interface1  [interface2  ...]  ] [ -f  configfile ] [ -d
+       debuglevel ] [ -ipv6 ] [ -ipc ] [ -dispin ] [ -dispout ]  [  -tnl  ]  [
+       -bcast  broadcastaddress ] [ -delgw ] [ -hint  HELLO interval for wire-
+       less interfaces ] [ -tcint  TC interval ] [ -midint  MID interval  ]  [
+       -hnaint   HNA  interval  ] [ -hhold  HELLO validity time ] [ -thold  TC
+       validity time ] [ -tos  TOS value ] [ -nhint  HELLO interval non WLAN ]
+       [ -nhhold  HELLO validity time non WLAN ] [ -T  scheduler poll rate ]
+
+
+
+DESCRIPTION
+       olsrd is an implementation of the Optimized Link State Routing protocol
+       for  Mobile  Ad-Hoc  networks(MANET).  The  protocol  is  described  in
+       RFC3626.  It is designed to be run as a standalone server process - but
+       as it is still in an experimental stage most users will prefer  running
+       it with some debug output which is directed to STDOUT.
+
+
+       This  manual page only lists the command line arguments. For details of
+       the configuration file see the comments  included  in  /etc/olsrd.conf.
+       Note  that  none  of these options need to be set at the command line -
+       all these options and others can be set in the configuration file.
+
+
+       The homepage of olsrd is http://www.olsr.org
+
+
+OPTIONS
+       -i interface1 ... interfaceN
+                   This option specifies  on  what  network  interfaces  olsrd
+                   should  run.  These interfaces cannot be aliased interfaces
+                   such as eth0:1.
+
+       -f configfile
+                   This option overrides the default configuration  file  path
+                   used by olsrd - /etc/olsrd.conf
+
+       -d debuglevel
+                   This option specifies the amount of debug information olsrd
+                   should write to STDOUT. If set to 0 olsrd will run  in  the
+                   background.
+
+       -ipv6       This  option  instructs  olsrd to use the Internet Protocol
+                   version 6. The default is version 4.
+
+       -ipc        This option allows the GUI front-end created fro  olsrd  to
+                   connect to olsrd at runtime.
+
+       -dispin     This option, when set, causes olsrd to display all incoming
+                   packet data on STDOUT. When using IPv4  the  data  is  dis-
+                   played  in decimal format, when using IPv6 the data is dis-
+                   played in hexadecimal format.
+
+       -dispout    This option, when set, causes olsrd to display all outgoing
+                   packet  data  on  STDOUT.  When using IPv4 the data is dis-
+                   played in decimal format, when using IPv6 the data is  dis-
+                   played in hexadecimal format.
+
+       -tnl        When  this  option is set olsrd will use IP-in-IP tunneling
+                   to Internet gateways. This is very experimental code and it
+                   should not be used as of yet.
+
+       -delgw      If  this option is set olsrd will remove any default routes
+                   set prior to adding an Internet route based on  OLSR  rout-
+                   ing.
+
+       -bcast broadcastaddress
+                   This option specifies what IPv4 broadcastaddress to use for
+                   OLSR control traffic. The only value that  currently  makes
+                   sense   when   setting   broadcast   address  mannually  is
+                   255.255.255.255.  The default action is to use  the  broad-
+                   castaddres  that  the  network  interface  is preconfigured
+                   with(per interface).
+
+       -hint seconds
+                   This value sets the interval on which HELLO messages should
+                   be  generated.  The value is a floating point number repre-
+                   senting seconds.
+
+       -nhint seconds
+                   This value sets the interval on which HELLO messages should
+                   be  generated  on  interfaces  that  are not detected to be
+                   wireless.  The value is a floating point number  represent-
+                   ing seconds.
+
+       -tcint seconds
+                   This value sets the interval on which TC messages should be
+                   generated. The value is a floating point number  represent-
+                   ing seconds.
+
+       -midint seconds
+                   This  value  sets the interval on which MID messages should
+                   be generated. The value is a floating point  number  repre-
+                   senting seconds.
+
+       -hnaint seconds
+                   This  value  sets the interval on which HNA messages should
+                   be generated. The value is a floating point  number  repre-
+                   senting seconds.
+
+       -hhold multiplier
+                   This  option  sets  the  announced HELLO validity time as a
+                   multiplier of the HELLO interval.
+
+       -nhhold multiplier
+                   This option sets the announced HELLO validity time on  non-
+                   WLAN interfaces, as a multiplier of the HELLO interval.
+
+       -thold multiplier
+                   This option sets the announced TC validity time as a multi-
+                   plier of the TC interval.
+
+       -tos TOS-value
+                   This option sets the type of service value that  should  be
+                   set in the OLSR control traffic packet IP headers.
+
+       -T seconds  This  option  sets  the polling intervall of the scheduler.
+                   The default is 0.1 seconds. This option should only be con-
+                   sidered if running with really low emission intervals.
+
+
+
+       FILES  /etc/olsrd.conf
+
+SEE ALSO
+       iwconfig(8) route(8).
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,291 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "FrontendDlg.h"
+#include "TrayIcon.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+BEGIN_MESSAGE_MAP(CFrontendApp, CWinApp)
+	//{{AFX_MSG_MAP(CFrontendApp)
+	//}}AFX_MSG
+	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+CFrontendApp::CFrontendApp()
+{
+}
+
+CFrontendApp theApp;
+
+static int SetEnableRedirKey(unsigned long New)
+{
+	HKEY Key;
+	unsigned long Type;
+	unsigned long Len;
+	unsigned long Old;
+	
+	if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+		"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+		0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
+		return -1;
+	
+	Len = sizeof (Old);
+	
+	if (::RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
+		(unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
+		Type != REG_DWORD)
+		Old = 1;
+	
+	if (::RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
+		(unsigned char *)&New, sizeof (New)))
+	{
+		::RegCloseKey(Key);
+		return -1;
+	}
+	
+	::RegCloseKey(Key);
+	return Old;
+}
+
+BOOL CFrontendApp::InitInstance()
+{
+	int Res;
+
+	CCommandLineInfo CmdLineInfo;
+	ParseCommandLine(CmdLineInfo);
+
+	CFrontendDlg dlg;
+
+	tray_icon = new TrayIcon( dlg, AfxGetInstanceHandle() );
+
+	dlg.ConfigFile = CmdLineInfo.m_strFileName;
+
+	m_pMainWnd = &dlg;
+
+	Res = SetEnableRedirKey(0);
+
+	if (Res == 1)
+	{
+		Res = AfxMessageBox("- WARNING -\n\n"
+			"The OLSR software has just switched off the processing of incoming ICMP "
+			" redirect messages in your registry.\n\n"
+			" Please REBOOT your computer for this change to take effect.\n\n"
+			" Do you want to allow the OLSR software to reboot your computer now?\n\n"
+			" (Please say \"Yes\".)", MB_YESNO | MB_ICONEXCLAMATION);
+
+		if (Res == IDYES)
+		{
+			HANDLE Proc;
+			HMODULE Lib;
+			BOOL (*Open)(HANDLE, DWORD, HANDLE *);
+			BOOL (*Lookup)(char *, char *, LUID *);
+			BOOL (*Adjust)(HANDLE, BOOL, TOKEN_PRIVILEGES *, DWORD,
+				TOKEN_PRIVILEGES *, DWORD *);
+			HANDLE Token;
+
+			Proc = ::GetCurrentProcess();
+
+			Lib = ::LoadLibrary("advapi32.dll");
+
+			if (Lib != NULL)
+			{
+				Open = (BOOL (*)(HANDLE, DWORD, HANDLE *))
+					::GetProcAddress(Lib, "OpenProcessToken");
+
+				Lookup = (BOOL (*)(char *, char *, LUID *))
+					::GetProcAddress(Lib, "LookupPrivilegeValueA");
+
+				Adjust = (BOOL (*)(HANDLE, BOOL, TOKEN_PRIVILEGES *, DWORD,
+					TOKEN_PRIVILEGES *, DWORD *))
+					::GetProcAddress(Lib, "AdjustTokenPrivileges");
+
+				if (Open != NULL && Lookup != NULL && Adjust != NULL)
+				{
+					struct
+					{
+						DWORD Count;
+						LUID_AND_ATTRIBUTES Priv;
+					}
+					TokPriv;
+
+					Proc = ::GetCurrentProcess();
+
+					if (!Open(Proc, TOKEN_ALL_ACCESS, &Token))
+						AfxMessageBox("OpenProcessToken() failed.");
+
+					else if (!Lookup("", "SeShutdownPrivilege", &TokPriv.Priv.Luid))
+						AfxMessageBox("LookupPrivilegeValue() failed.");
+
+					else
+					{
+						TokPriv.Count = 1;
+						TokPriv.Priv.Attributes = SE_PRIVILEGE_ENABLED;
+
+						if (!Adjust(Token, FALSE, (TOKEN_PRIVILEGES *)&TokPriv,
+							0, NULL, NULL))
+							AfxMessageBox("AdjustTokenPrivilege() failed.");
+					}
+				}
+
+				::FreeLibrary(Lib);
+			}
+
+			::ExitWindowsEx(EWX_REBOOT, 0);
+			::TerminateProcess(Proc, 0);
+		}
+	}
+
+	RedirectStdHandles();
+
+	dlg.DoModal();
+
+	return FALSE;
+}
+
+unsigned int CFrontendApp::RedirectThreadFunc(void)
+{
+	char Buff[1000];
+	int Len;
+	int Left, Right;
+	CString Line;
+	CString Int;
+
+	while (::ReadFile(OutRead, Buff, sizeof (Buff) - 1, (unsigned long *)&Len, NULL))
+	{
+		if (Len == 0)
+			break;
+
+		Left = 0;
+
+		for (Right = 0; Right < Len; Right++)
+		{
+			if (Buff[Right] != 13)
+				Buff[Left++] = Buff[Right];
+		}
+
+		Len = Left;
+
+		Left = 0;
+
+		for (Right = 0; Right < Len; Right++)
+		{
+			if (Buff[Right] == 10)
+			{
+				Buff[Right] = 0;
+				Line += (Buff + Left);
+
+				AfxMessageBox(Line);
+
+				Line.Empty();
+
+				Left = Right + 1;
+			}
+		}
+
+		Buff[Right] = 0;
+		Line += (Buff + Left);
+	}
+
+	AfxEndThread(0);
+	return 0;
+}
+
+static unsigned int RedirectThreadStub(void *Arg)
+{
+	class CFrontendApp *This;
+
+	This = (class CFrontendApp *)Arg;
+
+	return This->RedirectThreadFunc();
+}
+
+struct IoInfo
+{
+	HANDLE Hand;
+	unsigned char Attr;
+	char Buff;
+#if defined _MT
+	int Flag;
+	CRITICAL_SECTION Lock;
+#endif
+};
+
+extern "C" struct IoInfo *__pioinfo[];
+
+int CFrontendApp::RedirectStdHandles(void)
+{
+	SECURITY_ATTRIBUTES SecAttr;
+	HANDLE OutWrite;
+	struct IoInfo *Info;
+
+	SecAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
+	SecAttr.lpSecurityDescriptor = NULL;
+	SecAttr.bInheritHandle = TRUE;
+
+	if (!::CreatePipe(&OutRead, &OutWrite, &SecAttr, 0))
+	{
+		AfxMessageBox("Cannot create stdout pipe.");
+		return -1;
+	}
+
+	AfxBeginThread(RedirectThreadStub, (void *)this);
+
+	Info = __pioinfo[0];
+
+	// Info[1].Hand = OutWrite;
+	// Info[1].Attr = 0x89; // FOPEN | FTEXT | FPIPE;
+
+	Info[2].Hand = OutWrite;
+	Info[2].Attr = 0x89;
+
+	// stdout->_file = 1;
+	stderr->_file = 2;
+
+	win32_stdio_hack((unsigned int)OutWrite);
+
+	return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,1008 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "FrontendDlg.h"
+#include "TrayIcon.h"
+
+#include "Ipc.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+CFrontendDlg::CFrontendDlg(CWnd* pParent)
+	: CDialog(CFrontendDlg::IDD, pParent)
+{
+	//{{AFX_DATA_INIT(CFrontendDlg)
+	//}}AFX_DATA_INIT
+
+	Event = CreateEvent(NULL, FALSE, FALSE, "TheOlsrdShimEvent");
+
+	LogThread = NULL;
+	NetThread = NULL;
+}
+
+void CFrontendDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CFrontendDlg)
+	DDX_Control(pDX, IDC_BUTTON2, m_StopButton);
+	DDX_Control(pDX, IDC_BUTTON1, m_StartButton);
+	DDX_Control(pDX, IDC_TAB1, m_TabCtrl);
+	//}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CFrontendDlg, CDialog)
+	//{{AFX_MSG_MAP(CFrontendDlg)
+	ON_BN_CLICKED(IDC_BUTTON1, OnStartButton)
+	ON_BN_CLICKED(IDC_BUTTON2, OnStopButton)
+	ON_BN_CLICKED(IDC_BUTTON3, OnExitButton)
+	ON_BN_CLICKED(IDOK, OnOK)
+	ON_BN_CLICKED(IDCANCEL, OnCancel)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+#if 0
+static void HexDump(unsigned char *Mem, int Len)
+{
+	char Buff[10000];
+	int i, k;
+	char *Walker = Buff;
+
+	for (i = 0; i < Len; i += k)
+	{
+		Walker += sprintf(Walker, "%08x:", i);
+
+		for (k = 0; i + k < Len && k < 16; k++)
+			Walker += sprintf(Walker, " %02x", Mem[i + k]);
+
+		while (k < 16)
+		{
+			Walker += sprintf(Walker, "   ");
+			k++;
+		}
+
+		Walker += sprintf(Walker, " ");
+
+		for (k = 0; i + k < Len && k < 16; k++)
+			if (Mem[i + k] < 32 || Mem[i + k] > 126)
+				Walker += sprintf(Walker, ".");
+
+			else
+				Walker += sprintf(Walker, "%c", Mem[i + k]);
+
+		Walker += sprintf(Walker, "\r\n");
+	}
+
+	::MessageBox(NULL, Buff, "HEXDUMP", MB_OK);
+}
+#endif
+
+// XXX - pretty inefficient
+
+void CFrontendDlg::Timeout(void)
+{
+	POSITION Pos, Pos2;
+	class NodeEntry Entry;
+	class MprEntry MprEntry;
+	class MidEntry MidEntry;
+	class HnaEntry HnaEntry;
+
+Restart0:
+	Pos = NodeList.GetHeadPosition();
+
+	while (Pos != NULL)
+	{
+		Entry = NodeList.GetAt(Pos);
+
+		if (Entry.Timeout < Now)
+		{
+			NodeList.RemoveAt(Pos);
+			goto Restart0;
+		}
+
+Restart1:
+		Pos2 = Entry.MprList.GetHeadPosition();
+
+		while (Pos2 != NULL)
+		{
+			MprEntry = Entry.MprList.GetAt(Pos2);
+
+			if (MprEntry.Timeout < Now)
+			{
+				Entry.MprList.RemoveAt(Pos2);
+				goto Restart1;
+			}
+
+			Entry.MprList.GetNext(Pos2);
+		}
+
+Restart2:
+		Pos2 = Entry.MidList.GetHeadPosition();
+
+		while (Pos2 != NULL)
+		{
+			MidEntry = Entry.MidList.GetAt(Pos2);
+
+			if (MidEntry.Timeout < Now)
+			{
+				Entry.MidList.RemoveAt(Pos2);
+				goto Restart2;
+			}
+
+			Entry.MidList.GetNext(Pos2);
+		}
+
+Restart3:
+		Pos2 = Entry.HnaList.GetHeadPosition();
+
+		while (Pos2 != NULL)
+		{
+			HnaEntry = Entry.HnaList.GetAt(Pos2);
+
+			if (HnaEntry.Timeout < Now)
+			{
+				Entry.HnaList.RemoveAt(Pos2);
+				goto Restart3;
+			}
+
+			Entry.HnaList.GetNext(Pos2);
+		}
+
+		NodeList.GetNext(Pos);
+	}
+
+	if( NodeList.IsEmpty() )
+		TrayIcon::getInstance()->setStatus( TrayIcon::ON, "No nodes found" );
+	else
+		TrayIcon::getInstance()->setStatus( TrayIcon::CONNECTED, "Nodes available" );
+
+	m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
+}
+
+unsigned int VTimeToInt(unsigned int VTime)
+{
+	return ((0x10 | ((VTime & 0xf0) >> 4)) << (VTime & 0x0f)) >> 8;
+}
+
+void CFrontendDlg::AddMpr(unsigned int MprAddr, unsigned int NodeAddr,
+						  unsigned int VTime)
+{
+	class NodeEntry NewEntry;
+	POSITION Pos;
+	unsigned __int64 Timeout;
+
+	Timeout = Now +
+		(unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
+
+	AddNode(NodeAddr, VTime);
+	AddNode(MprAddr, VTime);
+
+	NewEntry.Addr = NodeAddr;
+
+	Pos = NodeList.Find(NewEntry);
+
+	if (Pos == NULL)
+		return;
+
+	class NodeEntry &OldEntry = NodeList.GetAt(Pos);
+
+	OldEntry.AddMpr(MprAddr, Timeout);
+
+	m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
+}
+
+void CFrontendDlg::AddMid(unsigned int IntAddr, unsigned int NodeAddr,
+						  unsigned int VTime)
+{
+	class NodeEntry NewEntry;
+	POSITION Pos;
+	unsigned __int64 Timeout;
+
+	Timeout = Now +
+		(unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
+
+	AddNode(NodeAddr, VTime);
+
+	NewEntry.Addr = NodeAddr;
+
+	Pos = NodeList.Find(NewEntry);
+
+	if (Pos == NULL)
+		return;
+
+	class NodeEntry &OldEntry = NodeList.GetAt(Pos);
+
+	OldEntry.AddMid(IntAddr, Timeout);
+
+	m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
+}
+
+void CFrontendDlg::AddHna(unsigned int NetAddr, unsigned int NetMask,
+						  unsigned int NodeAddr, unsigned int VTime)
+{
+	class NodeEntry NewEntry;
+	POSITION Pos;
+	unsigned __int64 Timeout;
+
+	Timeout = Now +
+		(unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
+
+	AddNode(NodeAddr, VTime);
+
+	NewEntry.Addr = NodeAddr;
+
+	Pos = NodeList.Find(NewEntry);
+
+	if (Pos == NULL)
+		return;
+
+	class NodeEntry &OldEntry = NodeList.GetAt(Pos);
+
+	OldEntry.AddHna(NetAddr, NetMask, Timeout);
+
+	m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
+}
+
+void CFrontendDlg::AddNode(unsigned int NodeAddr, unsigned int VTime)
+{
+	class NodeEntry NewEntry;
+	POSITION Pos;
+	unsigned __int64 Timeout;
+
+	if (NodeAddr == LocalHost)
+		return;
+
+	Timeout = Now +
+		(unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
+
+	NewEntry.Addr = NodeAddr;
+
+	Pos = NodeList.Find(NewEntry);
+
+	if (Pos != NULL)
+	{
+		class NodeEntry &OldEntry = NodeList.GetAt(Pos);
+		OldEntry.Timeout = Timeout;
+	}
+
+	else
+	{
+		NewEntry.Timeout = Timeout;
+		NodeList.AddTail(NewEntry);
+	}
+
+	m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
+}
+
+void CFrontendDlg::HandleOlsrTc(struct OlsrTc *Msg, int UseLq)
+{
+	int Size;
+	unsigned int *Addr;
+
+	Msg->Header.SeqNo = ::ntohs(Msg->Header.SeqNo);
+	Msg->Ansn = ::ntohs(Msg->Ansn);
+
+	AddNode(Msg->Header.Orig, Msg->Header.VTime);
+
+	Size = Msg->Header.Size;
+
+	Size -= sizeof (struct OlsrTc);
+
+	Addr = (unsigned int *)(Msg + 1);
+
+	while (Size > 0)
+	{
+		Size -= 4;
+
+		AddMpr(*Addr, Msg->Header.Orig, Msg->Header.VTime);
+
+		Addr++;
+
+		if (UseLq != 0)
+		{
+			Size -= 4;
+			Addr++;
+		}
+
+	}
+}
+
+void CFrontendDlg::HandleOlsrMid(struct OlsrHeader *Msg)
+{
+	int Size;
+	unsigned int *Addr;
+
+	Msg->SeqNo = ::ntohs(Msg->SeqNo);
+
+	AddNode(Msg->Orig, Msg->VTime);
+
+	Size = Msg->Size;
+
+	Size -= sizeof (struct OlsrHeader);
+
+	Addr = (unsigned int *)(Msg + 1);
+
+	while (Size > 0)
+	{
+		Size -= 4;
+
+		AddMid(*Addr, Msg->Orig, Msg->VTime);
+
+		Addr++;
+	}
+}
+
+void CFrontendDlg::HandleOlsrHna(struct OlsrHeader *Msg)
+{
+	int Size;
+	unsigned int *Addr;
+
+	Msg->SeqNo = ::ntohs(Msg->SeqNo);
+
+	AddNode(Msg->Orig, Msg->VTime);
+
+	Size = Msg->Size;
+
+	Size -= sizeof (struct OlsrHeader);
+
+	Addr = (unsigned int *)(Msg + 1);
+
+	while (Size > 0)
+	{
+		Size -= 8;
+
+		AddHna(Addr[0], Addr[1], Msg->Orig, Msg->VTime);
+
+		Addr += 2;
+	}
+}
+
+void CFrontendDlg::HandleOlsrHello(struct OlsrHello *Msg, int UseLq)
+{
+	int Size, LinkSize;
+	struct OlsrHelloLink *Link;
+	unsigned int *Addr;
+
+	Msg->Header.SeqNo = ::ntohs(Msg->Header.SeqNo);
+
+	AddNode(Msg->Header.Orig, Msg->Header.VTime);
+
+	Size = Msg->Header.Size;
+
+	Size -= sizeof (struct OlsrHello);
+
+	Link = (struct OlsrHelloLink *)(Msg + 1);
+
+	while (Size > 0)
+	{
+		Link->Size = ::ntohs(Link->Size);
+
+		LinkSize = Link->Size;
+
+		Size -= LinkSize;
+
+		LinkSize -= sizeof (struct OlsrHelloLink);
+
+		Addr = (unsigned int *)(Link + 1);
+
+		while (LinkSize > 0)
+		{
+			LinkSize -= 4;
+
+			AddNode(*Addr, Msg->Header.VTime);
+
+			if ((Link->LinkCode & 0x0c) == 0x08)
+				AddMpr(*Addr, Msg->Header.Orig, Msg->Header.VTime);
+
+			Addr++;
+
+			if (UseLq != 0)
+			{
+				LinkSize -= 4;
+				Addr++;
+			}
+		}
+
+		Link = (struct OlsrHelloLink *)Addr;
+	}
+}
+
+void CFrontendDlg::HandleIpcRoute(struct IpcRoute *Msg)
+{
+	if (Msg->Header.Size != sizeof (struct IpcRoute))
+		return;
+
+	if (Msg->Add == 0)
+		m_TabCtrl.m_Dialog4.DeleteRoute(Msg->Dest.v4);
+
+	else
+		m_TabCtrl.m_Dialog4.AddRoute(Msg->Dest.v4, Msg->Gate.v4, Msg->Metric,
+		Msg->Int);
+}
+
+void CFrontendDlg::HandleIpcConfig(struct IpcConfig *Msg)
+{
+	if (Msg->Header.Size != sizeof (struct IpcConfig))
+		return;
+
+	Msg->HelloInt = ::ntohs(Msg->HelloInt);
+	Msg->WiredHelloInt = ::ntohs(Msg->WiredHelloInt);
+	Msg->TcInt = ::ntohs(Msg->TcInt);
+
+	Msg->HelloHold = ::ntohs(Msg->HelloHold);
+	Msg->TcHold = ::ntohs(Msg->TcHold);
+
+	LocalHost = Msg->MainAddr.v4;
+}
+
+static int FullRead(SOCKET SockHand, char *Buff, int Len)
+{
+	int Res;
+
+	do
+	{
+		Res = ::recv(SockHand, Buff, Len, 0);
+
+		if (Res <= 0)
+			return -1;
+
+		Len -= Res;
+		Buff += Res;
+	}
+	while (Len > 0);
+
+	return 0;
+}
+
+// XXX - we should have access to olsrd's internal data structures instead
+
+unsigned int CFrontendDlg::NetThreadFunc(void)
+{
+	struct IpcHeader Header;
+	int Res;
+	char *Msg;
+
+	for (;;)
+	{
+		Res = FullRead(SockHand, (char *)&Header, sizeof (struct IpcHeader));
+
+		if (Res < 0)
+			break;
+
+		Header.Size = ntohs(Header.Size);
+
+		Msg = new char [Header.Size];
+
+		::memcpy(Msg, &Header, sizeof (struct IpcHeader));
+
+		Res = FullRead(SockHand, Msg + sizeof (struct IpcHeader),
+			Header.Size - sizeof (struct IpcHeader));
+
+		if (Res < 0)
+			break;
+
+		SYSTEMTIME SysTime;
+		FILETIME FileTime;
+
+		::GetSystemTime(&SysTime);
+		::SystemTimeToFileTime(&SysTime, &FileTime);
+
+		Now = *(unsigned __int64 *)&FileTime;
+
+		switch (Header.Type)
+		{
+		case MSG_TYPE_IPC_ROUTE:
+			HandleIpcRoute((struct IpcRoute *)Msg);
+			break;
+
+		case MSG_TYPE_IPC_CONFIG:
+			HandleIpcConfig((struct IpcConfig *)Msg);
+			break;
+
+		case MSG_TYPE_OLSR_HELLO:
+			HandleOlsrHello((struct OlsrHello *)Msg, 0);
+			break;
+
+		case MSG_TYPE_OLSR_TC:
+			HandleOlsrTc((struct OlsrTc *)Msg, 0);
+			break;
+
+		case MSG_TYPE_OLSR_MID:
+			HandleOlsrMid((struct OlsrHeader *)Msg);
+			break;
+
+		case MSG_TYPE_OLSR_HNA:
+			HandleOlsrHna((struct OlsrHeader *)Msg);
+			break;
+
+		case MSG_TYPE_OLSR_LQ_HELLO:
+			HandleOlsrHello((struct OlsrHello *)Msg, 1);
+			break;
+
+		case MSG_TYPE_OLSR_LQ_TC:
+			HandleOlsrTc((struct OlsrTc *)Msg, 1);
+			break;
+		}
+
+		delete[] Msg;
+
+		// XXX - nodes are only timed out while messages keep coming in
+
+		Timeout();
+	}
+
+	AfxEndThread(0);
+	return 0;
+}
+
+unsigned int CFrontendDlg::LogThreadFunc(void)
+{
+	char Buff[1000];
+	int Len;
+	int Left, Right;
+	CString Line;
+	CString Int;
+
+	while (::ReadFile(OutRead, Buff, sizeof (Buff) - 1, (unsigned long *)&Len, NULL))
+	{
+		if (Len == 0)
+			break;
+
+		Left = 0;
+
+		for (Right = 0; Right < Len; Right++)
+		{
+			if (Buff[Right] != 13)
+				Buff[Left++] = Buff[Right];
+		}
+
+		Len = Left;
+
+		Left = 0;
+
+		for (Right = 0; Right < Len; Right++)
+		{
+			if (Buff[Right] == 10)
+			{
+				Buff[Right] = 0;
+				Line += (Buff + Left);
+
+				if (PipeMode == PIPE_MODE_RUN)
+					m_TabCtrl.m_Dialog1.AddOutputLine(Line);
+
+				else if (Line.GetLength() > 8 && Line[0] == 'i' && Line[1] == 'f')
+				{
+					Int = Line.Mid(0, 4);
+					Int.MakeUpper();
+
+					Interfaces.Add(Int);
+					IsWlan.Add(Line.Mid(6, 1));
+					Addresses.Add(Line.Mid(8));
+				}
+
+				Line.Empty();
+
+				Left = Right + 1;
+			}
+		}
+
+		Buff[Right] = 0;
+		Line += (Buff + Left);
+	}
+
+	if (PipeMode == PIPE_MODE_RUN)
+	{
+		m_StopButton.EnableWindow(FALSE);
+		m_StartButton.EnableWindow(TRUE);
+	}
+
+	AfxEndThread(0);
+	return 0;
+}
+
+static unsigned int LogThreadStub(void *Arg)
+{
+	class CFrontendDlg *This;
+
+	This = (class CFrontendDlg *)Arg;
+
+	return This->LogThreadFunc();
+}
+
+static unsigned int NetThreadStub(void *Arg)
+{
+	class CFrontendDlg *This;
+
+	This = (class CFrontendDlg *)Arg;
+
+	return This->NetThreadFunc();
+}
+
+int CFrontendDlg::ExecutePipe(const char *CmdLine, HANDLE *InWrite,
+							  HANDLE *OutRead, HANDLE *ShimProc)
+{
+	SECURITY_ATTRIBUTES SecAttr;
+	HANDLE OutWrite, OutReadTmp;
+	HANDLE ErrWrite;
+	HANDLE InRead, InWriteTmp;
+	HANDLE Proc;
+	STARTUPINFO StartupInfo;
+	PROCESS_INFORMATION ProcessInfo;
+
+	SecAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
+	SecAttr.lpSecurityDescriptor = NULL;
+	SecAttr.bInheritHandle = TRUE;
+
+	Proc = ::GetCurrentProcess();
+
+	if (!::CreatePipe(&OutReadTmp, &OutWrite, &SecAttr, 0))
+	{
+		AfxMessageBox("Cannot create stdout pipe.");
+		return -1;
+	}
+
+	if (!::DuplicateHandle(Proc, OutReadTmp, Proc, OutRead,
+		0, FALSE, DUPLICATE_SAME_ACCESS))
+	{
+		AfxMessageBox("Cannot duplicate temporary stdout read handle.");
+		return -1;
+	}
+
+	if (!::CloseHandle(OutReadTmp))
+	{
+		AfxMessageBox("Cannot close temporary stdout read handle.");
+		return -1;
+	}
+
+	if (!::CreatePipe(&InRead, &InWriteTmp, &SecAttr, 0))
+	{
+		AfxMessageBox("Cannot create stdin pipe.");
+		return -1;
+	}
+
+	if (!::DuplicateHandle(Proc, InWriteTmp, Proc, InWrite,
+		0, FALSE, DUPLICATE_SAME_ACCESS))
+	{
+		AfxMessageBox("Cannot duplicate temporary stdin write handle.");
+		return -1;
+	}
+
+	if (!::CloseHandle(InWriteTmp))
+	{
+		AfxMessageBox("Cannot close temporary stdin write handle.");
+		return -1;
+	}
+
+	if (!::DuplicateHandle(Proc, OutWrite, Proc, &ErrWrite,
+		0, TRUE, DUPLICATE_SAME_ACCESS))
+	{
+		AfxMessageBox("Cannot duplicate stdout write handle for stderr.");
+		return -1;
+	}
+
+	::memset(&StartupInfo, 0, sizeof (STARTUPINFO));
+
+	StartupInfo.cb = sizeof (STARTUPINFO);
+
+	StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+
+	StartupInfo.hStdInput = InRead;
+	StartupInfo.hStdOutput = OutWrite;
+	StartupInfo.hStdError = ErrWrite;
+
+	StartupInfo.wShowWindow = SW_HIDE;
+
+	if (!::CreateProcess(NULL, (char *)CmdLine, NULL, NULL, TRUE,
+		0, NULL, NULL, &StartupInfo, &ProcessInfo))
+	{
+		AfxMessageBox("Cannot create OLSR server process.");
+		return -1;
+	}
+
+	if (!::CloseHandle(InRead))
+	{
+		AfxMessageBox("Cannot close stdin read handle.");
+		return -1;
+	}
+
+	if (!::CloseHandle(OutWrite))
+	{
+		AfxMessageBox("Cannot close stdout write handle.");
+		return -1;
+	}
+
+	if (!::CloseHandle(ErrWrite))
+	{
+		AfxMessageBox("Cannot close stderr write handle.");
+		return -1;
+	}
+
+	*ShimProc = ProcessInfo.hProcess;
+
+	return 0;
+}
+
+int CFrontendDlg::GetInterfaces()
+{
+	char GuiPath[MAX_PATH];
+	CString CmdLine;
+	CWinThread *IntThread;
+
+	::GetModuleFileName(NULL, GuiPath, MAX_PATH);
+
+	CmdLine = GuiPath;
+	CmdLine = CmdLine.Mid(0, CmdLine.ReverseFind('\\')) + "\\olsrd.exe -int";
+
+	if (ExecutePipe((const char *)CmdLine, &InWrite, &OutRead, &ShimProc) < 0)
+	{
+		AfxMessageBox("Cannot execute '" + CmdLine + "'.");
+		return -1;
+	}
+
+	PipeMode = PIPE_MODE_INT;
+
+	IntThread = AfxBeginThread(LogThreadStub, (void *)this);
+
+	::WaitForSingleObject((HANDLE)(*IntThread), INFINITE);
+
+	return 0;
+}
+
+int CFrontendDlg::StartOlsrd()
+{
+	WSADATA WsaData;
+	CString CmdLine;
+	char Path[MAX_PATH];
+	char TempPath[MAX_PATH];
+	int Try;
+
+	m_TabCtrl.m_Dialog3.ClearNodeInfo();
+	m_TabCtrl.m_Dialog4.ClearRoutes();
+
+	if (WSAStartup(0x0202, &WsaData))
+	{
+		AfxMessageBox("Cannot initialize WinSock library.");
+		return -1;
+	}
+
+	::GetModuleFileName(NULL, Path, MAX_PATH);
+
+	CmdLine = Path;
+	CmdLine = CmdLine.Mid(0, CmdLine.ReverseFind('\\')) + "\\Shim.exe";
+
+	::GetTempPath(MAX_PATH - 16, Path);
+	::GetTempFileName(Path, "GNU", 0, TempPath);
+
+	StoredTempFile = TempPath;
+
+	if (m_TabCtrl.m_Dialog2.SaveConfigFile(StoredTempFile, 0) < 0)
+	{
+		AfxMessageBox("Cannot save temporary configuration file '" + 
+			StoredTempFile + "'.");
+		return -1;
+	}
+
+	CmdLine += " -f " + StoredTempFile;
+
+	if (ExecutePipe((const char *)CmdLine, &InWrite, &OutRead, &ShimProc) < 0)
+	{
+		AfxMessageBox("Cannot execute '" + CmdLine + "'.");
+		return -1;
+	}
+
+	PipeMode = PIPE_MODE_RUN;
+
+	LogThread = AfxBeginThread(LogThreadStub, (void *)this);
+
+	struct sockaddr_in Addr;
+
+	Addr.sin_family = AF_INET;
+	Addr.sin_port = ::htons(1212);
+	Addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
+
+	SockHand = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+	if (SockHand < 0)
+	{
+		AfxMessageBox("Cannot create IPC socket.");
+
+		::SetEvent(Event);
+		::WaitForSingleObject((HANDLE)LogThread, INFINITE);
+
+		LogThread = NULL;
+
+		return -1;
+	}
+
+	for (Try = 0; Try < 5; Try++)
+	{
+		if (::connect(SockHand, (struct sockaddr *)&Addr,
+			sizeof (struct sockaddr_in)) >= 0)
+			break;
+
+		::Sleep(500);
+	}
+
+	if (Try == 10)
+	{
+		AfxMessageBox("Cannot connect to IPC port.");
+
+		::SetEvent(Event);
+		::WaitForSingleObject((HANDLE)LogThread, INFINITE);
+
+		::closesocket(SockHand);
+
+		LogThread = NULL;
+
+		return -1;
+	}
+
+	NetThread = AfxBeginThread(NetThreadStub, (void *)this);
+
+	return 0;
+}
+
+int CFrontendDlg::StopOlsrd()
+{
+	if (LogThread == NULL && NetThread == NULL)
+		return 0;
+
+	TrayIcon::getInstance()->setStatus( TrayIcon::OFF, "Off" );
+
+	::SetEvent(Event);
+
+	::WaitForSingleObject((HANDLE)LogThread, INFINITE);
+	::WaitForSingleObject((HANDLE)NetThread, INFINITE);
+
+	LogThread = NULL;
+	NetThread = NULL;
+
+	::DeleteFile(StoredTempFile);
+
+	return 0;
+}
+
+BOOL CFrontendDlg::OnInitDialog()
+{
+	HICON Small, Large;
+
+	CDialog::OnInitDialog();
+
+	Small = (HICON)::LoadImage(AfxGetApp()->m_hInstance,
+		MAKEINTRESOURCE(IDI_ICON1),
+		IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
+		GetSystemMetrics(SM_CYSMICON), 0);
+
+	Large = (HICON)::LoadImage(AfxGetApp()->m_hInstance,
+		MAKEINTRESOURCE(IDI_ICON1),
+		IMAGE_ICON, GetSystemMetrics(SM_CXICON),
+		GetSystemMetrics(SM_CYICON), 0);
+
+	SetIcon(Small, FALSE);
+	SetIcon(Large, TRUE);
+
+	GetInterfaces();
+
+	m_TabCtrl.InsertItem(0, "Settings");
+	m_TabCtrl.InsertItem(1, "Output");
+	m_TabCtrl.InsertItem(2, "Nodes");
+	m_TabCtrl.InsertItem(3, "Routes");
+
+	m_TabCtrl.InitTabDialogs(&Interfaces, &Addresses, &IsWlan);
+
+	m_StopButton.EnableWindow(FALSE);
+
+	if (!ConfigFile.IsEmpty())
+	{
+		if (m_TabCtrl.m_Dialog2.OpenConfigFile(ConfigFile) < 0)
+			AfxMessageBox("Cannot open configuration file '" + ConfigFile + "'.");
+
+		else
+		{
+			OnStartButton();
+
+			m_TabCtrl.SetCurSel(1);
+			m_TabCtrl.DisplayTabDialog();
+		}
+	}
+
+	return TRUE;
+}
+
+void CFrontendDlg::OnOK()
+{
+}
+
+void CFrontendDlg::OnCancel()
+{
+	OnExitButton();
+}
+
+void CFrontendDlg::OnStartButton() 
+{
+	m_StartButton.EnableWindow(FALSE);
+
+	m_TabCtrl.m_Dialog1.SetFrozen(1);
+
+	if (StartOlsrd() < 0)
+	{
+		m_TabCtrl.m_Dialog1.SetFrozen(0);
+		m_TabCtrl.m_Dialog1.AddOutputLine("");
+
+		AfxMessageBox("Cannot start OLSR server.");
+
+		m_StartButton.EnableWindow(TRUE);
+
+		return;
+	}
+
+	m_TabCtrl.m_Dialog1.HandleStart();
+
+	m_StopButton.EnableWindow(TRUE);
+}
+
+void CFrontendDlg::OnStopButton() 
+{
+	if (StopOlsrd() < 0)
+		return;
+
+	m_TabCtrl.m_Dialog1.HandleStop();
+
+	m_StopButton.EnableWindow(FALSE);
+	m_StartButton.EnableWindow(TRUE);
+}
+
+void CFrontendDlg::OnExitButton()
+{
+	delete TrayIcon::getInstance();
+
+	if (StopOlsrd() < 0)
+		return;
+
+	m_TabCtrl.m_Dialog3.ClearNodeInfo();
+	m_TabCtrl.m_Dialog4.ClearRoutes();
+
+	DestroyWindow();
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/FrontendDlg.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,137 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_FRONTENDDLG_H__7D68FBC0_7448_479B_81F0_3FBBDE291395__INCLUDED_)
+#define AFX_FRONTENDDLG_H__7D68FBC0_7448_479B_81F0_3FBBDE291395__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "MyTabCtrl.h"
+#include "NodeEntry.h"
+
+#define PIPE_MODE_RUN 0
+#define PIPE_MODE_INT 1
+
+class CFrontendDlg : public CDialog
+{
+public:
+	CFrontendDlg(CWnd* pParent = NULL);
+
+	//{{AFX_DATA(CFrontendDlg)
+	enum { IDD = IDD_FRONTEND_DIALOG };
+	CButton m_StopButton;
+	CButton m_StartButton;
+	MyTabCtrl m_TabCtrl;
+	//}}AFX_DATA
+
+	unsigned int LogThreadFunc(void);
+	unsigned int NetThreadFunc(void);
+
+	CString ConfigFile;
+protected:
+
+	//{{AFX_VIRTUAL(CFrontendDlg)
+	virtual void DoDataExchange(CDataExchange* pDX);
+	//}}AFX_VIRTUAL
+
+public:
+	//{{AFX_MSG(CFrontendDlg)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnOK();
+	afx_msg void OnCancel();
+	afx_msg void OnStartButton();
+	afx_msg void OnStopButton();
+	afx_msg void OnExitButton();
+	//}}AFX_MSG
+
+protected:
+	DECLARE_MESSAGE_MAP()
+
+	int StartOlsrd(void);
+	int StopOlsrd(void);
+
+	int GetInterfaces(void);
+
+	HANDLE Event;
+
+	CString StoredTempFile;
+
+	SOCKET SockHand;
+
+	int PipeMode;
+	int ExecutePipe(const char *, HANDLE *, HANDLE *, HANDLE *);
+
+	CWinThread *LogThread;
+	CWinThread *NetThread;
+
+	CStringArray Interfaces;
+	CStringArray Addresses;
+	CStringArray IsWlan;
+
+	HANDLE OutRead, InWrite;
+	HANDLE ShimProc;
+
+	void HandleIpcRoute(struct IpcRoute *);
+	void HandleIpcConfig(struct IpcConfig *);
+	void HandleOlsrHello(struct OlsrHello *, int);
+	void HandleOlsrTc(struct OlsrTc *, int);
+	void HandleOlsrMid(struct OlsrHeader *);
+	void HandleOlsrHna(struct OlsrHeader *);
+
+	void AddNode(unsigned int, unsigned int);
+	void AddMpr(unsigned int, unsigned int, unsigned int);
+	void AddMid(unsigned int, unsigned int, unsigned int);
+	void AddHna(unsigned int, unsigned int, unsigned int, unsigned int);
+
+	CList<class NodeEntry, class NodeEntry &> NodeList;
+
+	void Timeout(void);
+
+	unsigned __int64 Now;
+
+	unsigned int LocalHost;
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.dsp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.dsp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.dsp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.dsp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,251 @@
+# Microsoft Developer Studio Project File - Name="Frontend" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Frontend - Win32 Debug
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE 
+!MESSAGE NMAKE /f "Frontend.mak".
+!MESSAGE 
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE 
+!MESSAGE NMAKE /f "Frontend.mak" CFG="Frontend - Win32 Debug"
+!MESSAGE 
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE 
+!MESSAGE "Frontend - Win32 Release" (basierend auf  "Win32 (x86) Application")
+!MESSAGE "Frontend - Win32 Debug" (basierend auf  "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Frontend - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\..\src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 olsrd_cfgparser.lib ws2_32.lib iphlpapi.lib /nologo /subsystem:windows /machine:I386 /out:"Release/Switch.exe"
+
+!ELSEIF  "$(CFG)" == "Frontend - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\..\src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX"stdafx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 olsrd_cfgparser.lib ws2_32.lib iphlpapi.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Switch.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Frontend - Win32 Release"
+# Name "Frontend - Win32 Debug"
+# Begin Group "Quellcodedateien"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Frontend.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Frontend.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\FrontendDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\HnaEntry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MidEntry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MprEntry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog1.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog3.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyEdit.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyTabCtrl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NodeEntry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TrayIcon.cpp
+# End Source File
+# End Group
+# Begin Group "Header-Dateien"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Frontend.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\FrontendDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\HnaEntry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ipc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MidEntry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MprEntry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog1.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog3.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog4.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyEdit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyTabCtrl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\NodeEntry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\src\olsr_cfg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\src\olsr_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TrayIcon.h
+# End Source File
+# End Group
+# Begin Group "Ressourcendateien"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\Frontend.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Frontend.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Tray1.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Tray2.ico
+# End Source File
+# End Group
+# End Target
+# End Project
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,80 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_FRONTEND_H__8033A41F_6FDC_4054_A582_AB7B6AC5EEAE__INCLUDED_)
+#define AFX_FRONTEND_H__8033A41F_6FDC_4054_A582_AB7B6AC5EEAE__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#ifndef __AFXWIN_H__
+	#error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h"
+
+class TrayIcon;
+
+class CFrontendApp : public CWinApp
+{
+public:
+	CFrontendApp();
+
+	int RedirectStdHandles(void);
+	unsigned int RedirectThreadFunc(void);
+
+	HANDLE OutRead;
+	TrayIcon* tray_icon;
+
+	//{{AFX_VIRTUAL(CFrontendApp)
+	public:
+	virtual BOOL InitInstance();
+	//}}AFX_VIRTUAL
+
+	//{{AFX_MSG(CFrontendApp)
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.rc ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.rc
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Frontend.rc	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Frontend.rc	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,323 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Englisch (USA) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+    "#ifdef _WIN32\r\n"
+    "LANGUAGE 9, 1\r\n"
+    "#pragma code_page(1252)\r\n"
+    "#endif //_WIN32\r\n"
+    "#include ""res\\Frontend.rc2""  // non-Microsoft Visual C++ edited resources\r\n"
+    "#include ""afxres.rc""         // Standard components\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_FRONTEND_DIALOG DIALOGEX 0, 0, 399, 289
+STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | 
+    WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "olsr.org Switch 0.5.6-rc6-247f41fa940a"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+    CONTROL         "Tab1",IDC_TAB1,"SysTabControl32",0x0,7,7,383,256
+    PUSHBUTTON      "Start",IDC_BUTTON1,228,268,50,14
+    PUSHBUTTON      "Stop",IDC_BUTTON2,284,268,50,14
+    PUSHBUTTON      "Exit",IDC_BUTTON3,340,268,50,14
+END
+
+IDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 377, 240
+STYLE WS_CHILD | WS_VISIBLE
+FONT 8, "MS Sans Serif"
+BEGIN
+    EDITTEXT        IDC_EDIT1,7,25,363,208,ES_MULTILINE | ES_READONLY | 
+                    ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
+    PUSHBUTTON      "Freeze",IDC_BUTTON3,152,7,50,14
+    PUSHBUTTON      "Continue",IDC_BUTTON2,208,7,50,14
+    PUSHBUTTON      "Save",IDC_BUTTON4,264,7,50,14
+    PUSHBUTTON      "Clear",IDC_BUTTON1,320,7,50,14
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE  0, 0, 377, 240
+STYLE WS_CHILD | WS_VISIBLE
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "List1",IDC_LIST1,"SysListView32",LVS_LIST | WS_BORDER | 
+                    WS_TABSTOP,7,19,103,76
+    CONTROL         "Slider2",IDC_SLIDER2,"msctls_trackbar32",TBS_AUTOTICKS | 
+                    TBS_BOTH | WS_TABSTOP,8,116,87,26
+    EDITTEXT        IDC_EDIT7,55,153,26,12,ES_RIGHT
+    CONTROL         "Enable IP version 6",IDC_CHECK3,"Button",
+                    BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,171,93,10
+    CONTROL         "Offer Internet connection",IDC_CHECK2,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,7,187,93,10
+    EDITTEXT        IDC_EDIT1,189,7,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT2,305,7,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT3,189,23,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT9,305,23,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT4,189,39,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT10,305,39,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT5,189,55,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT6,305,55,26,12,ES_RIGHT
+    COMBOBOX        IDC_COMBO1,189,76,26,41,CBS_DROPDOWNLIST | CBS_SORT | 
+                    WS_VSCROLL | WS_TABSTOP
+    EDITTEXT        IDC_EDIT15,305,77,26,12,ES_RIGHT | ES_NUMBER
+    CONTROL         "Enable hysteresis",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,134,101,74,10
+    EDITTEXT        IDC_EDIT12,189,115,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT13,305,115,26,12,ES_RIGHT
+    EDITTEXT        IDC_EDIT11,189,131,26,12,ES_RIGHT
+    CONTROL         "Enable ETX link quality",IDC_CHECK4,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,132,155,92,10
+    CONTROL         "for MPR selection only",IDC_RADIO1,"Button",
+                    BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,132,171,87,10
+    CONTROL         "for MPR selection and routing",IDC_RADIO2,"Button",
+                    BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,132,187,109,
+                    10
+    EDITTEXT        IDC_EDIT14,305,169,26,12,ES_RIGHT | ES_NUMBER | 
+                    WS_DISABLED
+    PUSHBUTTON      "Open",IDC_BUTTON4,210,219,50,14
+    PUSHBUTTON      "Save",IDC_BUTTON5,265,219,50,14
+    PUSHBUTTON      "Reset",IDC_BUTTON1,320,219,50,14
+    LTEXT           "Interface list",IDC_STATIC,7,8,39,8
+    LTEXT           "Debug level",IDC_STATIC,7,105,39,8
+    RTEXT           "HELLO interval:",IDC_STATIC,132,9,51,8
+    RTEXT           "HELLO hold:",IDC_STATIC,247,9,42,8
+    RTEXT           "MID interval:",IDC_STATIC,132,25,41,8
+    RTEXT           "MID hold:",IDC_STATIC,247,25,32,8
+    RTEXT           "HNA interval:",IDC_STATIC,132,41,43,8
+    RTEXT           "HNA hold:",IDC_STATIC,247,41,34,8
+    RTEXT           "TC interval:",IDC_STATIC,132,57,37,8
+    RTEXT           "TC hold:",IDC_STATIC,247,57,28,8
+    RTEXT           "TC redundancy:",IDC_STATIC,132,79,52,8
+    RTEXT           "MPR coverage:",IDC_STATIC,247,79,51,8
+    LTEXT           "sec",IDC_STATIC,219,9,12,8
+    LTEXT           "sec",IDC_STATIC,335,9,12,8
+    LTEXT           "sec",IDC_STATIC,219,25,12,8
+    LTEXT           "sec",IDC_STATIC,335,25,12,8
+    LTEXT           "sec",IDC_STATIC,219,41,12,8
+    LTEXT           "sec",IDC_STATIC,335,41,12,8
+    LTEXT           "sec",IDC_STATIC,219,57,12,8
+    LTEXT           "sec",IDC_STATIC,335,57,12,8
+    RTEXT           "Poll interval:",IDC_STATIC,7,155,39,8
+    LTEXT           "sec",IDC_STATIC,85,155,12,8
+    CTEXT           "0",IDC_TEXT1,96,123,11,8
+    RTEXT           "Low mark:",IDC_STATIC,132,117,34,8
+    RTEXT           "Scaling:",IDC_STATIC,132,133,26,8
+    RTEXT           "High mark:",IDC_STATIC,247,117,35,8
+    RTEXT           "Window size:",IDC_STATIC,247,171,43,8
+    CONTROL         "Enable Fish Eye",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,249,187,92,10
+END
+
+IDD_DIALOG3 DIALOG DISCARDABLE  0, 0, 377, 240
+STYLE WS_CHILD | WS_VISIBLE
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "List1",IDC_LIST1,"SysListView32",LVS_REPORT | 
+                    LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,18,239,215
+    CONTROL         "List4",IDC_LIST4,"SysListView32",LVS_REPORT | 
+                    LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,255,18,115,66
+    CONTROL         "List4",IDC_LIST5,"SysListView32",LVS_REPORT | 
+                    LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,255,92,115,66
+    CONTROL         "List4",IDC_LIST6,"SysListView32",LVS_REPORT | 
+                    LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,255,167,115,66
+    LTEXT           "Node list",IDC_STATIC,7,7,32,8
+    LTEXT           "Node information",IDC_STATIC,257,7,59,8
+END
+
+IDD_DIALOG4 DIALOG DISCARDABLE  0, 0, 377, 240
+STYLE WS_CHILD | WS_VISIBLE
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "List1",IDC_LIST1,"SysListView32",LVS_REPORT | WS_BORDER | 
+                    WS_TABSTOP,7,18,363,215
+    LTEXT           "Routing table",IDC_STATIC,7,7,48,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO MOVEABLE PURE 
+BEGIN
+    IDD_FRONTEND_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 390
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 282
+    END
+
+    IDD_DIALOG1, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 370
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 233
+    END
+
+    IDD_DIALOG2, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 370
+        TOPMARGIN, 6
+        BOTTOMMARGIN, 233
+    END
+
+    IDD_DIALOG3, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 370
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 233
+    END
+
+    IDD_DIALOG4, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 370
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 233
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1               ICON    DISCARDABLE     "res\\Frontend.ico"
+IDI_ICON3               ICON    DISCARDABLE     "res\\Tray2.ico"
+IDI_ICON2               ICON    DISCARDABLE     "res\\Tray1.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_TRAYMENU MENU DISCARDABLE 
+BEGIN
+    POPUP "IDR_TRAYMENU"
+    BEGIN
+        MENUITEM "Start",                       IDM_START
+        MENUITEM "Stop",                        IDM_STOP
+        POPUP "Show"
+        BEGIN
+            MENUITEM "Window",                      IDM_WINDOW
+            MENUITEM "Settings",                    IDM_SETTINGS
+            MENUITEM "Output",                      IDM_OUTPUT
+        END
+        MENUITEM "Exit",                        IDM_EXIT
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_DIALOG2 DLGINIT
+BEGIN
+    IDC_COMBO1, 0x403, 2, 0
+0x0030, 
+    IDC_COMBO1, 0x403, 2, 0
+0x0031, 
+    IDC_COMBO1, 0x403, 2, 0
+0x0032, 
+    0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 24
+//
+
+1                       24      DISCARDABLE     "trustInfo.manifest"
+#endif    // Englisch (USA) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\Frontend.rc2"  // non-Microsoft Visual C++ edited resources
+#include "afxres.rc"         // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/gnome-shutdown.png and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/gnome-shutdown.png sind verschieden.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/HnaEntry.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/HnaEntry.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/HnaEntry.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/HnaEntry.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,56 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "HnaEntry.h"
+
+class HnaEntry &HnaEntry::operator=(class HnaEntry &Src)
+{
+	Addr = Src.Addr;
+	Mask = Src.Mask;
+	Timeout = Src.Timeout;
+
+	return *this;
+}
+
+BOOL HnaEntry::operator==(const class HnaEntry &Comp) const
+{
+	return Addr == Comp.Addr && Mask == Comp.Mask;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/HnaEntry.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/HnaEntry.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/HnaEntry.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/HnaEntry.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,55 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_HNAENTRY_H
+#define TL_HNAENTRY_H
+
+class HnaEntry
+{
+public:
+	unsigned int Addr;
+	unsigned int Mask;
+	unsigned __int64 Timeout;
+
+	class HnaEntry &HnaEntry::operator=(class HnaEntry &);
+	BOOL HnaEntry::operator==(const class HnaEntry &) const;
+};
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Ipc.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Ipc.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Ipc.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Ipc.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,135 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_IPC_H
+#define TL_IPC_H
+
+#define MSG_TYPE_OLSR_HELLO 1
+#define MSG_TYPE_OLSR_TC 2
+#define MSG_TYPE_OLSR_MID 3
+#define MSG_TYPE_OLSR_HNA 4
+#define MSG_TYPE_OLSR_LQ_HELLO 201
+#define MSG_TYPE_OLSR_LQ_TC 202
+
+#define MSG_TYPE_IPC_ROUTE 11
+#define MSG_TYPE_IPC_CONFIG 12
+
+#pragma pack(push, BeforeIpcMessages, 1)
+
+struct OlsrHeader
+{
+	unsigned char Type;
+	unsigned char VTime;
+	unsigned short Size;
+	unsigned int Orig;
+	unsigned char Ttl;
+	unsigned char Hops;
+	unsigned short SeqNo;
+};
+
+struct OlsrHello
+{
+	struct OlsrHeader Header;
+
+	unsigned short Reserved;
+	unsigned char HTime;
+	unsigned char Will;
+};
+
+struct OlsrHelloLink
+{
+	unsigned char LinkCode;
+	unsigned char Reserved;
+	unsigned short Size;
+};
+
+struct OlsrTc
+{
+	struct OlsrHeader Header;
+
+	unsigned short Ansn;
+	unsigned short Reserved;
+};
+
+union IpcIpAddr
+{
+	unsigned int v4;
+	unsigned char v6[16];
+};
+
+struct IpcHeader
+{
+	unsigned char Type;
+	unsigned char Reserved;
+	unsigned short Size;
+};
+
+struct IpcRoute
+{
+	struct IpcHeader Header;
+	
+	unsigned char Metric;
+	unsigned char Add;
+	unsigned char Reserved[2];
+	union IpcIpAddr Dest;
+	union IpcIpAddr Gate;
+	char Int[4];
+};
+
+struct IpcConfig
+{
+	struct IpcHeader Header;
+
+	unsigned char NumMid;
+	unsigned char NumHna;
+	unsigned char Reserved1[2];
+	unsigned short HelloInt;
+	unsigned short WiredHelloInt;
+	unsigned short TcInt;
+	unsigned short HelloHold;
+	unsigned short TcHold;
+	unsigned char Ipv6;
+	unsigned char Reserved2;
+	IpcIpAddr MainAddr;
+};
+
+#pragma pack (pop, BeforeIpcMessages)
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/LQ-Default.olsr ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/LQ-Default.olsr
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/LQ-Default.olsr	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/LQ-Default.olsr	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,202 @@
+#
+# Default configuration for the GUI
+#
+
+# Debug level(0-9)
+# If set to 0 the daemon runs in the background
+
+DebugLevel	0
+
+# IP version to use (4 or 6)
+
+IpVersion	4
+
+# FIBMetric ("flat" or "correct")
+
+FIBMetric	"flat"
+
+# HNA IPv4 routes
+# syntax: netaddr/prefix
+
+Hna4 {
+}
+
+# Should olsrd keep on running even if there are
+# no interfaces available? This is a good idea
+# for a PCMCIA/USB hotswap environment.
+# "yes" OR "no"
+
+AllowNoInt	yes
+
+# TOS(type of service) to use. Default is 16
+
+TosValue	16
+
+# Policy Routing Table to use. Default is 254
+
+RtTable		254
+
+# The fixed willingness to use(0-7)
+# If not set willingness will be calculated
+# dynammically based on battery/power status
+
+#Willingness	4
+
+# Allow processes like the GUI front-end
+# to connect to the daemon.
+
+IpcConnect {
+    MaxConnections	1
+    Host		127.0.0.1
+    Net			192.168.1.0/24
+}
+
+# Hysteresis adds more robustness to the
+# link sensing.
+# Used by default. 'yes' or 'no'
+
+UseHysteresis	no
+
+# Hysteresis parameters
+# Do not alter these unless you know 
+# what you are doing!
+# Set to auto by default. Allowed
+# values are floating point values
+# in the interval 0,1
+# THR_LOW must always be lower than
+# THR_HIGH!!
+
+#HystScaling	0.50
+#HystThrHigh	0.80
+#HystThrLow	0.30
+
+# Polling rate in seconds(float).
+# Auto uses default value 0.05 sec
+
+Pollrate	0.05
+# Interval to poll network interfaces for configuration
+# changes. Defaults to 2.5 seconds
+NicChgsPollInt	2.50
+# TC redundancy
+# Specifies how much neighbor info should
+# be sent in TC messages
+# Possible values are:
+# 0 - only send MPR selectors
+# 1 - send MPR selectors and MPRs
+# 2 - send all neighbors
+#
+# defaults to 0
+
+TcRedundancy	2
+
+# MPR coverage
+# Specifies how many MPRs a node should
+# try select to reach every 2 hop neighbor
+# Can be set to any integer >0
+# defaults to 1
+
+MprCoverage	7
+
+# Link quality level
+# 0 = do not use link quality
+# 1 = use link quality for MPR selection
+# 2 = use link quality for MPR selection and routing
+
+LinkQualityLevel	2
+
+# Fish Eye algorithm
+# 0 = do not use fish eye
+# 1 = use fish eye
+
+LinkQualityFishEye	1
+
+# Link quality window size
+
+LinkQualityWinSize	100
+
+# Clear screen when printing debug output?
+
+ClearScreen	no
+
+# Olsrd plugins to load
+# This must be the absolute path to the file
+# or the loader will use the following scheme:
+# - Try the paths in the LD_LIBRARY_PATH 
+#   environment variable.
+# - The list of libraries cached in /etc/ld.so.cache
+# - /lib, followed by /usr/lib
+
+LoadPlugin "olsrd_txtinfo.dll" {
+    PlParam "Accept"	"127.0.0.1"
+}
+LoadPlugin "olsrd_dot_draw.dll" {
+    PlParam "Accept"	"127.0.0.1"
+}
+LoadPlugin "olsrd_httpinfo.dll" {
+    PlParam "port"	"8080"
+    PlParam "Host"	"127.0.0.1"
+    PlParam "Net"	"104.0.0.0 255.0.0.0"
+    PlParam "Net"	"192.168.0.0 255.255.0.0"
+}
+
+# Interfaces
+# Multiple interfaces with the same configuration
+# can shar the same config block. Just list the
+# interfaces(e.g. Interface "eth0" "eth2"
+
+Interface "GUI" {
+
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    #Ip4Broadcast	255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    Ip6AddrType 	global
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+    Ip6MulticastSite	ff05::15
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+    Ip6MulticastGlobal	ff0e::1
+
+    # Olsrd can autodetect changes in
+    # interface configurations. Enabled by default
+    # turn off to save CPU.
+    AutoDetectChanges: yes
+    # Emission and validity intervals.
+    # If not defined, RFC proposed values will
+    # in most cases be used.
+
+    HelloInterval	5.00
+    HelloValidityTime	125.00
+    TcInterval		3.00
+    TcValidityTime	375.00
+    MidInterval		25.00
+    MidValidityTime	375.00
+    HnaInterval		25.00
+    HnaValidityTime	375.00
+    #LinkQualityMult	default 1.0
+    # When multiple links exist between hosts
+    # the weight of interface is used to determine
+    # the link to use. Normally the weight is
+    # automatically calculated by olsrd based
+    # 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
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Main.vcproj ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Main.vcproj
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/Main.vcproj	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/Main.vcproj	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="Main"
+	ProjectGUID="{01BB6810-46BB-4BE5-BCE3-96FF48F5DF1D}"
+	RootNamespace="Main"
+	Keyword="MFCProj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="false"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\win32"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="iphlpapi.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="false"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\win32"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
+				MinimalRebuild="false"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="iphlpapi.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+				EmbedManifest="true"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Frontend.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\FrontendDlg.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\HnaEntry.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MidEntry.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MprEntry.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog1.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog2.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog3.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog4.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MyEdit.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MyTabCtrl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\NodeEntry.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\StdAfx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\TrayIcon.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Frontend.h"
+				>
+			</File>
+			<File
+				RelativePath=".\FrontendDlg.h"
+				>
+			</File>
+			<File
+				RelativePath=".\HnaEntry.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Ipc.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MidEntry.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MprEntry.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog1.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog2.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog3.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MyDialog4.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MyEdit.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MyTabCtrl.h"
+				>
+			</File>
+			<File
+				RelativePath=".\NodeEntry.h"
+				>
+			</File>
+			<File
+				RelativePath=".\resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\StdAfx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\TrayIcon.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\res\Frontend.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\Frontend.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\Tray1.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\res\Tray2.ico"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\olsrd_cfgparser.lib"
+			>
+		</File>
+		<File
+			RelativePath=".\trustInfo.manifest"
+			>
+		</File>
+	</Files>
+	<Globals>
+		<Global
+			Name="RESOURCE_FILE"
+			Value="Frontend.rc"
+		/>
+	</Globals>
+</VisualStudioProject>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MidEntry.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MidEntry.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MidEntry.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MidEntry.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,55 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "MidEntry.h"
+
+class MidEntry &MidEntry::operator=(class MidEntry &Src)
+{
+	Addr = Src.Addr;
+	Timeout = Src.Timeout;
+
+	return *this;
+}
+
+BOOL MidEntry::operator==(const class MidEntry &Comp) const
+{
+	return Addr == Comp.Addr;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MidEntry.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MidEntry.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MidEntry.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MidEntry.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,54 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_MIDENTRY_H
+#define TL_MIDENTRY_H
+
+class MidEntry
+{
+public:
+	unsigned int Addr;
+	unsigned __int64 Timeout;
+
+	class MidEntry &MidEntry::operator=(class MidEntry &);
+	BOOL MidEntry::operator==(const class MidEntry &) const;
+};
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MprEntry.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MprEntry.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MprEntry.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MprEntry.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,55 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "MprEntry.h"
+
+class MprEntry &MprEntry::operator=(class MprEntry &Src)
+{
+	Addr = Src.Addr;
+	Timeout = Src.Timeout;
+
+	return *this;
+}
+
+BOOL MprEntry::operator==(const class MprEntry &Comp) const
+{
+	return Addr == Comp.Addr;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MprEntry.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MprEntry.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MprEntry.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MprEntry.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,54 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_MPRENTRY_H
+#define TL_MPRENTRY_H
+
+class MprEntry
+{
+public:
+	unsigned int Addr;
+	unsigned __int64 Timeout;
+
+	class MprEntry &MprEntry::operator=(class MprEntry &);
+	BOOL MprEntry::operator==(const class MprEntry &) const;
+};
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog1.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog1.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog1.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog1.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,273 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "MyDialog1.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+MyDialog1::MyDialog1(CWnd* pParent)
+	: CDialog(MyDialog1::IDD, pParent)
+{
+	NumLines = 0;
+
+	//{{AFX_DATA_INIT(MyDialog1)
+	//}}AFX_DATA_INIT
+}
+
+BOOL MyDialog1::Create(CWnd *Parent)
+{
+	return CDialog::Create(MyDialog1::IDD, Parent);
+}
+
+void MyDialog1::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(MyDialog1)
+	DDX_Control(pDX, IDC_BUTTON4, m_SaveButton);
+	DDX_Control(pDX, IDC_BUTTON3, m_FreezeButton);
+	DDX_Control(pDX, IDC_BUTTON2, m_ContinueButton);
+	DDX_Control(pDX, IDC_BUTTON1, m_ClearButton);
+	DDX_Control(pDX, IDC_EDIT1, m_OutputWindow);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(MyDialog1, CDialog)
+	//{{AFX_MSG_MAP(MyDialog1)
+	ON_BN_CLICKED(IDC_BUTTON1, OnClearButton)
+	ON_BN_CLICKED(IDC_BUTTON2, OnContinueButton)
+	ON_BN_CLICKED(IDC_BUTTON3, OnFreezeButton)
+	ON_WM_CTLCOLOR()
+	ON_BN_CLICKED(IDOK, OnOK)
+	ON_BN_CLICKED(IDCANCEL, OnCancel)
+	ON_BN_CLICKED(IDC_BUTTON4, OnSaveButton)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void MyDialog1::OnOK()
+{
+}
+
+void MyDialog1::OnCancel()
+{
+}
+
+void MyDialog1::AddOutputLine(CString Line)
+{
+	int Index;
+
+	CritSect.Lock();
+
+	Output += Line + "\r\n";
+
+	if (NumLines == 1000)
+	{
+		Index = Output.Find("\r\n");
+		Output.Delete(0, Index + 2);
+	}
+
+	else
+		NumLines++;
+
+	CritSect.Unlock();
+
+	if (Frozen == 0)
+	{
+		m_OutputWindow.SetWindowText(Output);
+		m_OutputWindow.SetSel(Output.GetLength(), Output.GetLength());
+	}
+}
+
+void MyDialog1::SetFrozen(int NewFrozen)
+{
+	Frozen = NewFrozen;
+}
+
+BOOL MyDialog1::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	CClientDC DevCont(&m_OutputWindow);
+
+	EditFont.CreatePointFont(90, "Courier New", NULL);
+	m_OutputWindow.SetFont(&EditFont);
+
+	m_FreezeButton.EnableWindow(FALSE);
+	m_ContinueButton.EnableWindow(FALSE);
+
+	Frozen = 0;
+
+	WhiteBrush.CreateSolidBrush(RGB(255, 255, 255));
+
+	return TRUE;
+}
+
+void MyDialog1::OnClearButton() 
+{
+	CritSect.Lock();
+	Output.Empty();
+	NumLines = 0;
+	CritSect.Unlock();
+
+	m_OutputWindow.SetWindowText(Output);
+	m_OutputWindow.SetSel(0, 0);
+}
+
+void MyDialog1::OnContinueButton()
+{
+	CString Copy;
+	int Len;
+
+	m_FreezeButton.EnableWindow(TRUE);
+	m_ContinueButton.EnableWindow(FALSE);
+
+	Frozen = 0;
+
+	CritSect.Lock();
+	Copy = Output;
+	Len = Output.GetLength();
+	CritSect.Unlock();
+
+	m_OutputWindow.SetWindowText(Copy);
+	m_OutputWindow.SetSel(Len, Len);
+}
+
+void MyDialog1::OnFreezeButton() 
+{
+	m_FreezeButton.EnableWindow(FALSE);
+	m_ContinueButton.EnableWindow(TRUE);
+
+	Frozen = 1;
+}
+
+void MyDialog1::HandleStart(void)
+{
+	CString Copy;
+	int Len;
+
+	m_FreezeButton.EnableWindow(TRUE);
+	m_ContinueButton.EnableWindow(FALSE);
+
+	Frozen = 0;
+
+	CritSect.Lock();
+	Copy = Output;
+	Len = Output.GetLength();
+	CritSect.Unlock();
+
+	m_OutputWindow.SetWindowText(Copy);
+	m_OutputWindow.SetSel(Len, Len);
+}
+
+void MyDialog1::HandleStop(void)
+{
+	CString Copy;
+	int Len;
+
+	m_FreezeButton.EnableWindow(FALSE);
+	m_ContinueButton.EnableWindow(FALSE);
+
+	Frozen = 0;
+
+	CritSect.Lock();
+	Copy = Output;
+	Len = Output.GetLength();
+	CritSect.Unlock();
+
+	m_OutputWindow.SetWindowText(Copy);
+	m_OutputWindow.SetSel(Len, Len);
+}
+
+HBRUSH MyDialog1::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
+{
+	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
+
+	if (pWnd == &m_OutputWindow)
+	{
+		pDC->SetBkColor(RGB(255, 255, 255));
+		hbr = WhiteBrush;
+	}
+	
+	return hbr;
+}
+
+void MyDialog1::OnSaveButton()
+{
+	CString Copy;
+	int Len;
+	CFileDialog FileDialog(FALSE);
+	CString FileName = "OLSR log.txt";
+	CString PathName;
+	CFile File;
+
+	CritSect.Lock();
+	Copy = Output;
+	Len = Output.GetLength();
+	CritSect.Unlock();
+
+	FileDialog.m_ofn.lpstrFilter = "Text file (*.txt)\0*.txt\0";
+	FileDialog.m_ofn.nFilterIndex = 1;
+
+	FileDialog.m_ofn.lpstrFile = FileName.GetBuffer(500);
+	FileDialog.m_ofn.nMaxFile = 500;
+
+	if (FileDialog.DoModal() == IDOK)
+	{
+		PathName = FileDialog.GetPathName();
+
+		if (File.Open(PathName, CFile::modeCreate | CFile::modeWrite |
+			CFile::shareExclusive) == 0)
+			AfxMessageBox("Cannot open logfile '" + PathName + "'.");
+
+		else
+		{
+			File.Write((const char *)Copy, Len);
+			File.Close();
+		}
+	}
+
+	FileName.ReleaseBuffer();
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog1.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog1.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog1.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog1.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,101 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_MYDIALOG1_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_)
+#define AFX_MYDIALOG1_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+class MyDialog1 : public CDialog
+{
+public:
+	MyDialog1(CWnd* pParent = NULL);
+
+	BOOL Create(CWnd *Parent);
+
+	void AddOutputLine(CString);
+	void SetFrozen(int);
+	void HandleStart(void);
+	void HandleStop(void);
+
+	//{{AFX_DATA(MyDialog1)
+	enum { IDD = IDD_DIALOG1 };
+	CButton	m_SaveButton;
+	CButton	m_FreezeButton;
+	CButton	m_ContinueButton;
+	CButton	m_ClearButton;
+	CEdit	m_OutputWindow;
+	//}}AFX_DATA
+
+
+	//{{AFX_VIRTUAL(MyDialog1)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);
+	//}}AFX_VIRTUAL
+
+protected:
+
+	//{{AFX_MSG(MyDialog1)
+	afx_msg void OnOK();
+	afx_msg void OnCancel();
+	virtual BOOL OnInitDialog();
+	afx_msg void OnClearButton();
+	afx_msg void OnContinueButton();
+	afx_msg void OnFreezeButton();
+	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+	afx_msg void OnSaveButton();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	CCriticalSection CritSect;
+	CString Output;
+	int NumLines;
+
+	int Frozen;
+
+	CFont EditFont;
+	CBrush WhiteBrush;
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog2.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog2.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog2.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog2.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,715 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "MyDialog2.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define MAXIF 100
+
+MyDialog2::MyDialog2(CWnd* pParent)
+	: CDialog(MyDialog2::IDD, pParent)
+{
+	Conf = NULL;
+
+	//{{AFX_DATA_INIT(MyDialog2)
+	//}}AFX_DATA_INIT
+}
+
+void MyDialog2::SetDebugLevel(int Level)
+{
+	char LevelText[2];
+
+	LevelText[0] = (char)(Level + '0');
+	LevelText[1] = 0;
+
+	DebugLevel = Level;
+	m_DebugLevel.SetPos(Level);
+	m_DebugLevelText.SetWindowText(LevelText);
+}
+
+BOOL MyDialog2::Create(CWnd *Parent)
+{
+	return CDialog::Create(MyDialog2::IDD, Parent);
+}
+
+void MyDialog2::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(MyDialog2)
+	DDX_Control(pDX, IDC_COMBO1, m_TcRed);
+	DDX_Control(pDX, IDC_EDIT15, m_MprCov);
+	DDX_Control(pDX, IDC_RADIO2, m_EtxRadio2);
+	DDX_Control(pDX, IDC_RADIO1, m_EtxRadio1);
+//	DDX_Control(pDX, IDC_EDIT14, m_EtxWindowSize);
+	DDX_Control(pDX, IDC_CHECK5, m_FishEyeCheck);
+	DDX_Control(pDX, IDC_CHECK4, m_EtxCheck);
+	DDX_Control(pDX, IDC_CHECK3, m_Ipv6Check);
+	DDX_Control(pDX, IDC_CHECK2, m_InternetCheck);
+	DDX_Control(pDX, IDC_CHECK1, m_HystCheck);
+	DDX_Control(pDX, IDC_EDIT13, m_HystThresholdHigh);
+	DDX_Control(pDX, IDC_EDIT12, m_HystThresholdLow);
+	DDX_Control(pDX, IDC_EDIT11, m_HystScaling);
+	DDX_Control(pDX, IDC_EDIT10, m_HnaHold);
+	DDX_Control(pDX, IDC_EDIT9, m_MidHold);
+	DDX_Control(pDX, IDC_EDIT7, m_PollInt);
+	DDX_Control(pDX, IDC_EDIT6, m_TcHold);
+	DDX_Control(pDX, IDC_EDIT5, m_TcInt);
+	DDX_Control(pDX, IDC_EDIT4, m_HnaInt);
+	DDX_Control(pDX, IDC_EDIT3, m_MidInt);
+	DDX_Control(pDX, IDC_EDIT2, m_HelloHold);
+	DDX_Control(pDX, IDC_EDIT1, m_HelloInt);
+	DDX_Control(pDX, IDC_LIST1, m_InterfaceList);
+	DDX_Control(pDX, IDC_TEXT1, m_DebugLevelText);
+	DDX_Control(pDX, IDC_SLIDER2, m_DebugLevel);
+	//}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(MyDialog2, CDialog)
+	//{{AFX_MSG_MAP(MyDialog2)
+	ON_WM_HSCROLL()
+	ON_BN_CLICKED(IDC_CHECK1, OnHystCheck)
+	ON_BN_CLICKED(IDC_BUTTON4, OnOpenButton)
+	ON_BN_CLICKED(IDC_BUTTON5, OnSaveButton)
+	ON_BN_CLICKED(IDC_BUTTON1, OnResetButton)
+	ON_BN_CLICKED(IDC_CHECK4, OnEtxCheck)
+	ON_BN_CLICKED(IDC_RADIO1, OnEtxRadio1)
+	ON_BN_CLICKED(IDC_RADIO2, OnEtxRadio2)
+	ON_BN_CLICKED(IDOK, OnOK)
+	ON_BN_CLICKED(IDCANCEL, OnCancel)
+//	ON_EN_KILLFOCUS(IDC_EDIT14, OnKillfocusEtxWinSize)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void MyDialog2::OnOK()
+{
+}
+
+void MyDialog2::OnCancel()
+{
+}
+
+void MyDialog2::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
+{
+	if (pScrollBar == (CScrollBar *)&m_DebugLevel)
+		SetDebugLevel(m_DebugLevel.GetPos());
+	
+	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
+}
+
+void MyDialog2::Reset(void)
+{
+	char PathName[MAX_PATH + 50];
+	char *Walker;
+	int i;
+
+	::GetModuleFileName(NULL, PathName, MAX_PATH);
+
+	for (Walker = PathName; *Walker != 0; Walker++);
+	
+	while (*Walker != '\\')
+		Walker--;
+
+	lstrcpy(Walker + 1, "Default.olsr");
+
+	if (OpenConfigFile(PathName) < 0)
+		return;
+
+	m_Ipv6Check.SetCheck(FALSE);
+
+	if (Conf->interfaces == NULL)
+	{
+		for (i = 0; i < Interfaces->GetSize(); i++)
+		{
+			if ((*IsWlan)[i] == "-")
+				m_InterfaceList.SetCheck(i, FALSE);
+
+			else
+				m_InterfaceList.SetCheck(i, TRUE);
+		}
+	}
+}
+
+BOOL MyDialog2::OnInitDialog() 
+{
+	int i;
+
+	CDialog::OnInitDialog();
+	
+	m_DebugLevel.SetRange(0, 9, TRUE);
+
+	m_InterfaceList.SetExtendedStyle(m_InterfaceList.GetExtendedStyle() |
+			LVS_EX_CHECKBOXES);
+
+	for (i = 0; i < Interfaces->GetSize(); i++)
+	{
+		m_InterfaceList.InsertItem(i,
+		(*Interfaces)[i] + " - " + (*Addresses)[i]);
+	}
+
+	MIB_IPFORWARDROW IpFwdRow;
+
+	if (::GetBestRoute(0, 0, &IpFwdRow) != NO_ERROR)
+		m_InternetCheck.EnableWindow(FALSE);
+
+	m_MprCov.LimitText(1);
+
+	Reset();
+
+	return TRUE;
+}
+
+void MyDialog2::OnHystCheck() 
+{
+	BOOL EnaDis = m_HystCheck.GetCheck();
+
+	m_HystThresholdLow.EnableWindow(EnaDis);
+	m_HystThresholdHigh.EnableWindow(EnaDis);
+	m_HystScaling.EnableWindow(EnaDis);
+}
+
+void MyDialog2::OnEtxCheckWorker() 
+{
+	BOOL EnaDis = m_EtxCheck.GetCheck();
+
+#if 0
+	m_EtxWindowSize.EnableWindow(EnaDis);
+#endif
+	m_EtxRadio1.EnableWindow(EnaDis);
+	m_EtxRadio2.EnableWindow(EnaDis);
+	m_FishEyeCheck.EnableWindow(EnaDis);
+}
+
+void MyDialog2::OnEtxCheck()
+{
+	OnEtxCheckWorker();
+
+	AfxMessageBox("WARNING - This parameter breaks compliance with the OLSR standard.\n\n"
+		"Make sure that either all nodes in your network use ETX or all nodes in your network don't use ETX.\n\n"
+		"DO NOT MIX NODES WITH DIFFERENT ETX SETTINGS!");
+}
+
+int MyDialog2::OpenConfigFile(CString PathName)
+{
+	struct ip_prefix_list *Hna;
+	struct olsr_if *Int, *PrevInt;
+	struct olsr_msg_params *MsgPar;
+	int NumInt = m_InterfaceList.GetItemCount();
+	int i;
+	CString IntName;
+	CString Conv;
+
+	if (Conf != NULL)
+		olsrd_free_cnf(Conf);
+
+	Conf = olsrd_parse_cnf(PathName);
+
+	if (Conf == NULL)
+		return -1;
+
+	for (i = 0; i < NumInt; i++)
+		m_InterfaceList.SetCheck(i, FALSE);
+
+	for (Int = Conf->interfaces; Int != NULL; Int = Int->next)
+	{
+		IntName = Int->name;
+		IntName.MakeUpper();
+
+		for (i = 0; i < NumInt; i++)
+		{
+			if (m_InterfaceList.GetItemText(i, 0).Mid(0, 4) == IntName)
+				m_InterfaceList.SetCheck(i, TRUE);
+		}
+	}
+
+	Int = Conf->interfaces;
+
+	MsgPar = &Int->cnf->hello_params;
+
+	Conv.Format("%.2f", MsgPar->emission_interval);
+	m_HelloInt.SetWindowText(Conv);
+
+	Conv.Format("%.2f", MsgPar->validity_time);
+	m_HelloHold.SetWindowText(Conv);
+
+	MsgPar = &Int->cnf->tc_params;
+	
+	Conv.Format("%.2f", MsgPar->emission_interval);
+	m_TcInt.SetWindowText(Conv);
+
+	Conv.Format("%.2f", MsgPar->validity_time);
+	m_TcHold.SetWindowText(Conv);
+
+	MsgPar = &Int->cnf->mid_params;
+	
+	Conv.Format("%.2f", MsgPar->emission_interval);
+	m_MidInt.SetWindowText(Conv);
+
+	Conv.Format("%.2f", MsgPar->validity_time);
+	m_MidHold.SetWindowText(Conv);
+
+	MsgPar = &Int->cnf->hna_params;
+	
+	Conv.Format("%.2f", MsgPar->emission_interval);
+	m_HnaInt.SetWindowText(Conv);
+
+	Conv.Format("%.2f", MsgPar->validity_time);
+	m_HnaHold.SetWindowText(Conv);
+
+	SetDebugLevel(Conf->debug_level);
+
+	Conv.Format("%.2f", Conf->pollrate);
+	m_PollInt.SetWindowText(Conv);
+
+	Conv.Format("%d", Conf->mpr_coverage);
+	m_MprCov.SetWindowText(Conv);
+
+	m_TcRed.SetCurSel(Conf->tc_redundancy);
+
+	m_HystCheck.SetCheck(Conf->use_hysteresis);
+
+	Conv.Format("%.2f", Conf->hysteresis_param.scaling);
+	m_HystScaling.SetWindowText(Conv);
+
+	Conv.Format("%.2f", Conf->hysteresis_param.thr_high);
+	m_HystThresholdHigh.SetWindowText(Conv);
+
+	Conv.Format("%.2f", Conf->hysteresis_param.thr_low);
+	m_HystThresholdLow.SetWindowText(Conv);
+
+	OnHystCheck();
+
+	m_FishEyeCheck.SetCheck(Conf->lq_fish > 0);
+
+	m_EtxCheck.SetCheck(Conf->lq_level > 0);
+
+#if 0
+	Conv.Format("%d", Conf->lq_wsize);
+	m_EtxWindowSize.SetWindowText(Conv);
+#endif
+
+	m_EtxRadio1.SetCheck(Conf->lq_level == 1);
+	m_EtxRadio2.SetCheck(Conf->lq_level == 0 || Conf->lq_level == 2);
+
+	OnEtxCheckWorker();
+
+	m_InternetCheck.SetCheck(FALSE);
+
+	for (Hna = Conf->hna_entries; Hna != NULL; Hna = Hna->next)
+		if (0 == Hna->net.prefix_len &&
+			m_InternetCheck.IsWindowEnabled())
+		m_InternetCheck.SetCheck(TRUE);
+
+	PrevInt = NULL;
+
+	for (Int = Conf->interfaces; Int != NULL; Int = Int->next)
+	{
+		IntName = Int->name;
+
+		if (IntName.CompareNoCase("GUI") == 0)
+			break;
+
+		PrevInt = Int;
+	}
+
+	if (Int != NULL)
+	{
+		if (PrevInt == NULL)
+			Conf->interfaces = Int->next;
+
+		else
+			PrevInt->next = Int->next;
+
+		win32_olsrd_free(Int);
+	}
+
+	return 0;
+}
+
+static struct olsr_if *AddInterface(struct olsrd_config **Conf, CString Name)
+{
+	struct olsr_if *Int;
+
+	Int = (struct olsr_if *)win32_olsrd_malloc(sizeof (struct olsr_if));
+
+	if (Int == NULL)
+	{
+		AfxMessageBox("Cannot allocate memory.");
+		return NULL;
+	}
+
+	Int->name = (char *)win32_olsrd_malloc(Name.GetLength() + 1);
+
+	if (Int->name == NULL)
+	{
+		win32_olsrd_free(Int);
+
+		AfxMessageBox("Cannot allocate memory.");
+		return NULL;
+	}
+
+	::lstrcpy(Int->name, Name);
+
+	Int->config = NULL;
+	Int->configured = OLSR_FALSE;
+	Int->interf = NULL;
+
+	Int->cnf = get_default_if_config();
+
+	Int->next = (*Conf)->interfaces;
+	(*Conf)->interfaces = Int;
+
+	return Int;
+}
+
+int MyDialog2::SaveConfigFile(CString PathName, int Real)
+{
+	struct olsr_if *Int, *PrevInt;
+	struct olsr_msg_params *MsgPar;
+	CString Conv;
+	struct ip_prefix_list *Hna, *NewHna, *PrevHna;
+	int NumInt = m_InterfaceList.GetItemCount();
+	int i;
+	CString IntName, IntName2;
+	struct ip_prefix_list *IpcHost;
+	union olsr_ip_addr Local;
+
+	PrevInt = NULL;
+
+	// remove interfaces that we do not want
+	
+	for (Int = Conf->interfaces; Int != NULL; Int = Int->next)
+	{
+		IntName = Int->name;
+		IntName.MakeUpper();
+
+		for (i = 0; i < NumInt; i++)
+			if (m_InterfaceList.GetItemText(i, 0).Mid(0, 4) == IntName)
+				break;
+
+		if (i == NumInt || !m_InterfaceList.GetCheck(i))
+		{
+			if (PrevInt != NULL)
+				PrevInt->next = Int->next;
+
+			else
+				Conf->interfaces = Int->next;
+		}
+	}
+	
+	// add missing interfaces
+	
+	for (i = 0; i < NumInt; i++)
+	{
+		if (!m_InterfaceList.GetCheck(i))
+			continue;
+
+		IntName2 = m_InterfaceList.GetItemText(i, 0).Mid(0, 4);
+
+		for (Int = Conf->interfaces; Int != NULL; Int = Int->next)
+		{
+			IntName = Int->name;
+			IntName.MakeUpper();
+
+			if (IntName2 == IntName)
+				break;
+		}
+
+		if (Int == NULL)
+			AddInterface(&Conf, m_InterfaceList.GetItemText(i, 0).Mid(0, 4));
+	}
+
+	// add dummy interface, if there aren't any real interfaces
+
+	if (Conf->interfaces == NULL && Real != 0)
+		AddInterface(&Conf, "GUI");
+
+	// per-interface settings
+
+	for (Int = Conf->interfaces; Int != NULL; Int = Int->next)
+	{
+		MsgPar = &Int->cnf->hello_params;
+
+		m_HelloInt.GetWindowText(Conv);
+		MsgPar->emission_interval = (float)atof(Conv);
+
+		m_HelloHold.GetWindowText(Conv);
+		MsgPar->validity_time = (float)atof(Conv);
+
+		MsgPar = &Int->cnf->tc_params;
+
+		m_TcInt.GetWindowText(Conv);
+		MsgPar->emission_interval = (float)atof(Conv);
+
+		m_TcHold.GetWindowText(Conv);
+		MsgPar->validity_time = (float)atof(Conv);
+
+		MsgPar = &Int->cnf->mid_params;
+
+		m_MidInt.GetWindowText(Conv);
+		MsgPar->emission_interval = (float)atof(Conv);
+
+		m_MidHold.GetWindowText(Conv);
+		MsgPar->validity_time = (float)atof(Conv);
+
+		MsgPar = &Int->cnf->hna_params;
+
+		m_HnaInt.GetWindowText(Conv);
+		MsgPar->emission_interval = (float)atof(Conv);
+
+		m_HnaHold.GetWindowText(Conv);
+		MsgPar->validity_time = (float)atof(Conv);
+	}
+
+	// global settings
+
+	Conf->debug_level = DebugLevel;
+
+	m_PollInt.GetWindowText(Conv);
+	Conf->pollrate = (float)atof(Conv);
+
+	Conf->tc_redundancy = (unsigned char)m_TcRed.GetCurSel();
+
+	m_MprCov.GetWindowText(Conv);
+	Conf->mpr_coverage = (unsigned char)atoi(Conv);
+
+	Conf->use_hysteresis = m_HystCheck.GetCheck() ? OLSR_TRUE : OLSR_FALSE;
+
+	m_HystScaling.GetWindowText(Conv);
+	Conf->hysteresis_param.scaling = (float)atof(Conv);
+
+	m_HystThresholdHigh.GetWindowText(Conv);
+	Conf->hysteresis_param.thr_high = (float)atof(Conv);
+
+	m_HystThresholdLow.GetWindowText(Conv);
+	Conf->hysteresis_param.thr_low = (float)atof(Conv);
+
+	if (!m_EtxCheck.GetCheck())
+		Conf->lq_level = 0;
+
+	else if (m_EtxRadio1.GetCheck())
+		Conf->lq_level = 1;
+
+	else
+		Conf->lq_level = 2;
+
+	if (!m_FishEyeCheck.GetCheck())
+		Conf->lq_fish = 0;
+
+	else
+		Conf->lq_fish = 1;
+
+#if 0
+	m_EtxWindowSize.GetWindowText(Conv);
+	Conf->lq_wsize = atoi(Conv);
+#endif
+
+	PrevHna = NULL;
+
+	// check for a default gateway HNA4 entry
+
+	for (Hna = Conf->hna_entries; Hna != NULL; Hna = Hna->next)
+	{
+		if (0 == Hna->net.prefix_len)
+			break;
+
+		PrevHna = Hna;
+	}
+
+	// add default gateway HNA entry
+
+	if (m_InternetCheck.GetCheck() && Hna == NULL)
+	{
+		NewHna = (struct ip_prefix_list * )
+			win32_olsrd_malloc(sizeof (struct ip_prefix_list));
+
+		if (NewHna == NULL)
+		{
+			AfxMessageBox("Cannot allocate memory.");
+			return -1;
+		}
+
+		memset(NewHna, 0, sizeof (struct ip_prefix_list));
+
+		NewHna->next = Conf->hna_entries;
+		Conf->hna_entries = NewHna;
+	}
+
+	// remove default gateway HNA4 entry
+
+	if (!m_InternetCheck.GetCheck() && Hna != NULL)
+	{
+		if (PrevHna == NULL)
+			Conf->hna_entries = Hna->next;
+
+		else
+			PrevHna->next = Hna->next;
+
+		win32_olsrd_free(Hna);
+	}
+
+	if (AF_INET == Conf->ip_version)
+	{
+		Local.v4.s_addr = ::inet_addr("127.0.0.1");
+	}
+	else
+	{
+		memset(&Local, 0, sizeof(Local));
+		Local.v6.u.Byte[15] = 1;
+	}
+
+	for (IpcHost = Conf->ipc_nets; IpcHost != NULL; IpcHost = IpcHost->next)
+		if (0 == memcmp(&IpcHost->net.prefix, &Local, Conf->ipsize))
+			break;
+
+	if (IpcHost == NULL && Real == 0)
+	{
+		IpcHost = (struct ip_prefix_list *)
+			win32_olsrd_malloc(sizeof (struct ip_prefix_list));
+
+		if (IpcHost == NULL)
+		{
+			AfxMessageBox("Cannot allocate memory.");
+			return -1;
+		}
+
+		IpcHost->net.prefix = Local;
+		IpcHost->net.prefix_len = (olsr_u8_t)Conf->ipsize;
+
+		IpcHost->next = Conf->ipc_nets;
+		Conf->ipc_nets = IpcHost;
+
+		Conf->ipc_connections++;
+	}
+
+	// write configuration file
+
+	if (olsrd_write_cnf(Conf, PathName) < 0)
+		return -1;
+
+	return 0;
+}
+
+void MyDialog2::OnSaveButton()
+{
+	CFileDialog FileDialog(FALSE);
+	CString FileName = "Default.olsr";
+	CString PathName;
+
+	FileDialog.m_ofn.lpstrFilter = "Configuration file (*.olsr)\0*.olsr\0";
+	FileDialog.m_ofn.nFilterIndex = 1;
+
+	FileDialog.m_ofn.lpstrFile = FileName.GetBuffer(500);
+	FileDialog.m_ofn.nMaxFile = 500;
+
+	if (FileDialog.DoModal() == IDOK)
+	{
+		PathName = FileDialog.GetPathName();
+
+		if (SaveConfigFile(PathName, 1) < 0)
+			AfxMessageBox("Cannot save configuration file '" + PathName + "'.");
+	}
+
+	FileName.ReleaseBuffer();
+}
+
+void MyDialog2::OnOpenButton()
+{
+	CFileDialog FileDialog(TRUE);
+	CString FileName = "Default.olsr";
+	CString PathName;
+
+	FileDialog.m_ofn.lpstrFilter = "Configuration file (*.olsr)\0*.olsr\0";
+	FileDialog.m_ofn.nFilterIndex = 1;
+
+	FileDialog.m_ofn.lpstrFile = FileName.GetBuffer(500);
+	FileDialog.m_ofn.nMaxFile = 500;
+
+	if (FileDialog.DoModal() == IDOK)
+	{
+		PathName = FileDialog.GetPathName();
+
+		if (OpenConfigFile(PathName) < 0)
+			AfxMessageBox("Cannot open configuration file '" + PathName + "'.");
+	}
+
+	FileName.ReleaseBuffer();
+}
+
+void MyDialog2::OnResetButton() 
+{
+	Reset();
+}
+
+void MyDialog2::OnEtxRadio1() 
+{
+	m_EtxRadio2.SetCheck(FALSE);
+}
+
+void MyDialog2::OnEtxRadio2() 
+{
+	m_EtxRadio1.SetCheck(FALSE);
+}
+
+#if 0
+void MyDialog2::OnKillfocusEtxWinSize() 
+{
+	CString Conv;
+	int WinSize;
+
+	m_EtxWindowSize.GetWindowText(Conv);
+	WinSize = atoi(Conv);
+
+	if (WinSize < 3)
+		WinSize = 3;
+
+	else if (WinSize > 128)
+		WinSize = 128;
+
+	Conv.Format("%d", WinSize);
+	m_EtxWindowSize.SetWindowText(Conv);
+}
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog2.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog2.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog2.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog2.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,135 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_MYDIALOG2_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_)
+#define AFX_MYDIALOG2_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "MyEdit.h"
+
+#define MAKELIB
+#define OLSR_PLUGIN
+#include <olsr_cfg.h>
+#include "afxwin.h"
+
+class MyDialog2 : public CDialog
+{
+public:
+	MyDialog2(CWnd* pParent = NULL);
+
+	BOOL Create(CWnd *Parent);
+
+	int OpenConfigFile(CString);
+	int SaveConfigFile(CString, int);
+
+	CStringArray *Interfaces;
+	CStringArray *Addresses;
+	CStringArray *IsWlan;
+
+	struct olsrd_config *Conf;
+
+	//{{AFX_DATA(MyDialog2)
+	enum { IDD = IDD_DIALOG2 };
+	CComboBox	m_TcRed;
+	CEdit	m_MprCov;
+	CButton	m_EtxRadio2;
+	CButton	m_EtxRadio1;
+	// CEdit	m_EtxWindowSize;
+	CButton	m_EtxCheck;
+	CButton	m_Ipv6Check;
+	CButton	m_InternetCheck;
+	CButton	m_HystCheck;
+	CButton m_FishEyeCheck;
+	MyEdit	m_HystThresholdHigh;
+	MyEdit	m_HystThresholdLow;
+	MyEdit	m_HystScaling;
+	MyEdit	m_HnaHold;
+	MyEdit	m_MidHold;
+	MyEdit	m_PollInt;
+	MyEdit	m_TcHold;
+	MyEdit	m_TcInt;
+	MyEdit	m_HnaInt;
+	MyEdit	m_MidInt;
+	MyEdit	m_HelloHold;
+	MyEdit	m_HelloInt;
+	CListCtrl	m_InterfaceList;
+	CStatic	m_DebugLevelText;
+	CSliderCtrl	m_DebugLevel;
+	//}}AFX_DATA
+
+	//{{AFX_VIRTUAL(MyDialog2)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);
+	//}}AFX_VIRTUAL
+
+protected:
+
+	//{{AFX_MSG(MyDialog2)
+	afx_msg void OnOK();
+	afx_msg void OnCancel();
+	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+	virtual BOOL OnInitDialog();
+	afx_msg void OnHystCheck();
+	afx_msg void OnOpenButton();
+	afx_msg void OnSaveButton();
+	afx_msg void OnResetButton();
+	afx_msg void OnEtxCheck();
+	afx_msg void OnEtxRadio1();
+	afx_msg void OnEtxRadio2();
+	afx_msg void OnKillfocusEtxWinSize();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+	CFont EditFont;
+
+	int DebugLevel;
+	void SetDebugLevel(int);
+
+	void Reset(void);
+
+	void OnEtxCheckWorker(void);
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog3.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog3.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog3.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog3.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,307 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "MyDialog3.h"
+
+#include "MprEntry.h"
+#include "MidEntry.h"
+#include "HnaEntry.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+MyDialog3::MyDialog3(CWnd* pParent)
+	: CDialog(MyDialog3::IDD, pParent)
+{
+	LastUpdate = 0;
+	Info = NULL;
+
+	//{{AFX_DATA_INIT(MyDialog3)
+	//}}AFX_DATA_INIT
+}
+
+BOOL MyDialog3::Create(CWnd *Parent)
+{
+	return CDialog::Create(MyDialog3::IDD, Parent);
+}
+
+void MyDialog3::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(MyDialog3)
+	DDX_Control(pDX, IDC_LIST6, m_HnaList);
+	DDX_Control(pDX, IDC_LIST5, m_MidList);
+	DDX_Control(pDX, IDC_LIST4, m_MprList);
+	DDX_Control(pDX, IDC_LIST1, m_NodeList);
+	//}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(MyDialog3, CDialog)
+	//{{AFX_MSG_MAP(MyDialog3)
+	ON_BN_CLICKED(IDOK, OnOK)
+	ON_BN_CLICKED(IDCANCEL, OnCancel)
+	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, OnItemchangedNodeList)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void MyDialog3::OnOK()
+{
+}
+
+void MyDialog3::OnCancel()
+{
+}
+
+BOOL MyDialog3::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	m_NodeList.InsertColumn(0, "Address", LVCFMT_LEFT, 110, 0);
+	m_NodeList.InsertColumn(1, "Timeout", LVCFMT_LEFT, 110, 1);
+	m_NodeList.InsertColumn(2, "MID", LVCFMT_LEFT, 68, 2);
+	m_NodeList.InsertColumn(3, "HNA", LVCFMT_LEFT, 67, 3);
+
+	m_MprList.InsertColumn(0, "MPR", LVCFMT_LEFT, 169, 0);
+
+	m_MidList.InsertColumn(0, "MID", LVCFMT_LEFT, 169, 0);
+
+	m_HnaList.InsertColumn(0, "HNA", LVCFMT_LEFT, 169, 0);
+
+	return TRUE;
+}
+
+void MyDialog3::ClearNodeInfo(void)
+{
+	m_NodeList.DeleteAllItems();
+
+	m_MprList.DeleteAllItems();
+	m_MidList.DeleteAllItems();
+	m_HnaList.DeleteAllItems();
+
+	if (Info != NULL)
+	{
+		delete[] Info;
+		Info = NULL;
+	}
+}
+
+void MyDialog3::UpdateNodeInfo(CList<class NodeEntry, class NodeEntry &> &NodeList)
+{
+	SYSTEMTIME SysTime;
+	FILETIME FileTime;
+	unsigned __int64 Now;
+	class NodeEntry Entry;
+	POSITION Pos;
+	CString AddrStr;
+	CString TimeoutStr;
+	int Idx, Num;
+	POSITION Pos2;
+	class MprEntry MprEntry;
+	class MidEntry MidEntry;
+	class HnaEntry HnaEntry;
+	CString CurrNode;
+
+	::GetSystemTime(&SysTime);
+	::SystemTimeToFileTime(&SysTime, &FileTime);
+
+	Now = *(unsigned __int64 *)&FileTime;
+
+	if (Now < LastUpdate + (__int64)3 * (__int64)10000000)
+		return;
+
+	LastUpdate = Now;
+
+	int CurrItem = m_NodeList.GetNextItem(-1, LVNI_SELECTED);
+
+	if (CurrItem >= 0)
+		CurrNode = m_NodeList.GetItemText(CurrItem, 0);
+
+	m_NodeList.DeleteAllItems();
+
+	if (Info != NULL)
+	{
+		delete[] Info;
+		Info = NULL;
+	}
+
+	Num = NodeList.GetCount();
+
+	if (Num == 0)
+		return;
+
+	Info = new class NodeInfo[Num];
+
+	Pos = NodeList.GetHeadPosition();
+
+	Idx = 0;
+
+	while (Pos != NULL)
+	{
+		Entry = NodeList.GetNext(Pos);
+
+		Pos2 = Entry.MprList.GetHeadPosition();
+
+		while (Pos2 != NULL)
+		{
+			MprEntry = Entry.MprList.GetNext(Pos2);
+
+			AddrStr.Format("%d.%d.%d.%d",
+				((unsigned char *)&MprEntry.Addr)[0], ((unsigned char *)&MprEntry.Addr)[1],
+				((unsigned char *)&MprEntry.Addr)[2], ((unsigned char *)&MprEntry.Addr)[3]);
+
+			Info[Idx].MprList.Add(AddrStr);
+		}
+
+		Pos2 = Entry.MidList.GetHeadPosition();
+
+		while (Pos2 != NULL)
+		{
+			MidEntry = Entry.MidList.GetNext(Pos2);
+
+			AddrStr.Format("%d.%d.%d.%d",
+				((unsigned char *)&MidEntry.Addr)[0], ((unsigned char *)&MidEntry.Addr)[1],
+				((unsigned char *)&MidEntry.Addr)[2], ((unsigned char *)&MidEntry.Addr)[3]);
+
+			Info[Idx].MidList.Add(AddrStr);
+		}
+
+		Pos2 = Entry.HnaList.GetHeadPosition();
+
+		while (Pos2 != NULL)
+		{
+			HnaEntry = Entry.HnaList.GetNext(Pos2);
+
+			unsigned int Mask = 0x80000000;
+			unsigned int Val = ::ntohl(HnaEntry.Mask);
+			int Bits;
+
+			for (Bits = 0; Bits < 32; Bits++)
+			{
+				if ((Val & Mask) == 0)
+					break;
+
+				Mask >>= 1;
+			}
+
+			AddrStr.Format("%d.%d.%d.%d/%d",
+				((unsigned char *)&HnaEntry.Addr)[0], ((unsigned char *)&HnaEntry.Addr)[1],
+				((unsigned char *)&HnaEntry.Addr)[2], ((unsigned char *)&HnaEntry.Addr)[3],
+				Bits);
+
+			Info[Idx].HnaList.Add(AddrStr);
+		}
+
+		AddrStr.Format("%d.%d.%d.%d",
+			((unsigned char *)&Entry.Addr)[0], ((unsigned char *)&Entry.Addr)[1],
+			((unsigned char *)&Entry.Addr)[2], ((unsigned char *)&Entry.Addr)[3]);
+
+		m_NodeList.InsertItem(Idx, AddrStr);
+
+		if (AddrStr == CurrNode)
+			m_NodeList.SetItemState(Idx, LVIS_SELECTED, LVIS_SELECTED);
+
+		SYSTEMTIME SysTime;
+		FILETIME LocalFileTime;
+
+		::FileTimeToLocalFileTime((FILETIME *)&Entry.Timeout, &LocalFileTime);
+		::FileTimeToSystemTime(&LocalFileTime, &SysTime);
+
+		TimeoutStr.Format("%02d:%02d:%02d", SysTime.wHour, SysTime.wMinute,
+			SysTime.wSecond);
+
+		m_NodeList.SetItemText(Idx, 1, TimeoutStr);
+
+		if (Entry.MidList.IsEmpty())
+			m_NodeList.SetItemText(Idx, 2, "no");
+
+		else
+			m_NodeList.SetItemText(Idx, 2, "yes");
+
+		if (Entry.HnaList.IsEmpty())
+			m_NodeList.SetItemText(Idx, 3, "no");
+
+		else
+			m_NodeList.SetItemText(Idx, 3, "yes");
+
+		Idx++;
+	}
+}
+
+void MyDialog3::OnItemchangedNodeList(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	int Item;
+	int Idx;
+	int Num;
+
+	pNMHDR = pNMHDR;
+
+	*pResult = 0;
+
+	Item = m_NodeList.GetNextItem(-1, LVNI_SELECTED);
+
+	if (Item < 0)
+		return;
+
+	m_MprList.DeleteAllItems();
+
+	Num = Info[Item].MprList.GetSize();
+	
+	for (Idx = 0; Idx < Num; Idx++)
+		m_MprList.InsertItem(Idx, Info[Item].MprList.GetAt(Idx));
+
+	m_MidList.DeleteAllItems();
+
+	Num = Info[Item].MidList.GetSize();
+	
+	for (Idx = 0; Idx < Num; Idx++)
+		m_MidList.InsertItem(Idx, Info[Item].MidList.GetAt(Idx));
+
+	m_HnaList.DeleteAllItems();
+
+	Num = Info[Item].HnaList.GetSize();
+	
+	for (Idx = 0; Idx < Num; Idx++)
+		m_HnaList.InsertItem(Idx, Info[Item].HnaList.GetAt(Idx));
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog3.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog3.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog3.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog3.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,97 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_MYDIALOG3_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_)
+#define AFX_MYDIALOG3_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "NodeEntry.h"
+
+class NodeInfo
+{
+public:
+	CStringArray MprList;
+	CStringArray MidList;
+	CStringArray HnaList;
+};
+
+class MyDialog3 : public CDialog
+{
+public:
+	MyDialog3(CWnd* pParent = NULL);
+
+	BOOL Create(CWnd *Parent);
+
+	void UpdateNodeInfo(CList<class NodeEntry, class NodeEntry &> &);
+	void ClearNodeInfo(void);
+
+	//{{AFX_DATA(MyDialog3)
+	enum { IDD = IDD_DIALOG3 };
+	CListCtrl	m_HnaList;
+	CListCtrl	m_MidList;
+	CListCtrl	m_MprList;
+	CListCtrl	m_NodeList;
+	//}}AFX_DATA
+
+
+	//{{AFX_VIRTUAL(MyDialog3)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);
+	//}}AFX_VIRTUAL
+
+protected:
+	unsigned __int64 LastUpdate;
+	class NodeInfo *Info;
+
+	//{{AFX_MSG(MyDialog3)
+	afx_msg void OnOK();
+	afx_msg void OnCancel();
+	virtual BOOL OnInitDialog();
+	afx_msg void OnItemchangedNodeList(NMHDR* pNMHDR, LRESULT* pResult);
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog4.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog4.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog4.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog4.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,154 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "MyDialog4.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+MyDialog4::MyDialog4(CWnd* pParent)
+	: CDialog(MyDialog4::IDD, pParent)
+{
+	//{{AFX_DATA_INIT(MyDialog4)
+	//}}AFX_DATA_INIT
+}
+
+BOOL MyDialog4::Create(CWnd *Parent)
+{
+	return CDialog::Create(MyDialog4::IDD, Parent);
+}
+
+void MyDialog4::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(MyDialog4)
+	DDX_Control(pDX, IDC_LIST1, m_RoutingTable);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(MyDialog4, CDialog)
+	//{{AFX_MSG_MAP(MyDialog4)
+	ON_BN_CLICKED(IDOK, OnOK)
+	ON_BN_CLICKED(IDCANCEL, OnCancel)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void MyDialog4::OnOK()
+{
+}
+
+void MyDialog4::OnCancel()
+{
+}
+
+BOOL MyDialog4::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+
+	m_RoutingTable.InsertColumn(0, "Destination", LVCFMT_LEFT, 110, 0);
+	m_RoutingTable.InsertColumn(1, "Gateway", LVCFMT_LEFT, 110, 1);
+	m_RoutingTable.InsertColumn(2, "Metric", LVCFMT_LEFT, 68, 2);
+	m_RoutingTable.InsertColumn(3, "Interface", LVCFMT_LEFT, 67, 3);
+
+	return TRUE;
+}
+
+void MyDialog4::AddRoute(unsigned int Dest, unsigned int Gate, int Metric,
+						 char *Int)
+{
+	CString DestStr;
+	CString GateStr;
+	CString MetricStr;
+	CString IntStr;
+	int Idx;
+
+	DestStr.Format("%d.%d.%d.%d",
+		((unsigned char *)&Dest)[0], ((unsigned char *)&Dest)[1],
+		((unsigned char *)&Dest)[2], ((unsigned char *)&Dest)[3]);
+
+	GateStr.Format("%d.%d.%d.%d",
+		((unsigned char *)&Gate)[0], ((unsigned char *)&Gate)[1],
+		((unsigned char *)&Gate)[2], ((unsigned char *)&Gate)[3]);
+
+	MetricStr.Format("%d", Metric);
+
+	IntStr.Format("%c%c%c%c", Int[0], Int[1], Int[2], Int[3]);
+	IntStr.MakeUpper();
+
+	Idx = m_RoutingTable.GetItemCount();
+
+	m_RoutingTable.InsertItem(Idx, DestStr);
+
+	m_RoutingTable.SetItemText(Idx, 1, GateStr);
+	m_RoutingTable.SetItemText(Idx, 2, MetricStr);
+	m_RoutingTable.SetItemText(Idx, 3, IntStr);
+}
+
+void MyDialog4::DeleteRoute(unsigned int Dest)
+{
+	CString DestStr;
+	int Idx, Num;
+
+	DestStr.Format("%d.%d.%d.%d",
+		((unsigned char *)&Dest)[0], ((unsigned char *)&Dest)[1],
+		((unsigned char *)&Dest)[2], ((unsigned char *)&Dest)[3]);
+
+	Num = m_RoutingTable.GetItemCount();
+
+	for (Idx = 0; Idx < Num; Idx++)
+	{
+		if (m_RoutingTable.GetItemText(Idx, 0) == DestStr)
+		{
+			m_RoutingTable.DeleteItem(Idx);
+			break;
+		}
+	}
+}
+
+void MyDialog4::ClearRoutes(void)
+{
+	m_RoutingTable.DeleteAllItems();
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog4.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog4.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyDialog4.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyDialog4.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,82 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_MYDIALOG4_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_)
+#define AFX_MYDIALOG4_H__1A381668_A36B_4C51_9B79_643BC2A59D88__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+class MyDialog4 : public CDialog
+{
+public:
+	MyDialog4(CWnd* pParent = NULL);
+
+	BOOL Create(CWnd *Parent);
+
+	void AddRoute(unsigned int, unsigned int, int, char *);
+	void DeleteRoute(unsigned int);
+	void ClearRoutes(void);
+
+	//{{AFX_DATA(MyDialog4)
+	enum { IDD = IDD_DIALOG4 };
+	CListCtrl	m_RoutingTable;
+	//}}AFX_DATA
+
+
+	//{{AFX_VIRTUAL(MyDialog4)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);
+	//}}AFX_VIRTUAL
+
+protected:
+
+	//{{AFX_MSG(MyDialog4)
+	afx_msg void OnOK();
+	afx_msg void OnCancel();
+	virtual BOOL OnInitDialog();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyEdit.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyEdit.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyEdit.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyEdit.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,116 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "frontend.h"
+#include "MyEdit.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+MyEdit::MyEdit()
+{
+}
+
+MyEdit::~MyEdit()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(MyEdit, CEdit)
+	//{{AFX_MSG_MAP(MyEdit)
+	ON_WM_CHAR()
+	ON_WM_KILLFOCUS()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void MyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
+{
+	static unsigned char *Allowed = (unsigned char *)"0123456789.";
+	int i;
+	CString Text;
+
+	if (nChar >= 32)
+	{
+		for (i = 0; Allowed[i] != 0; i++)
+			if (nChar == Allowed[i])
+				break;
+
+		if (Allowed[i] == 0)
+			return;
+
+		GetWindowText(Text);
+
+		if (nChar == '.' && Text.Find('.') >= 0)
+			return;
+
+		if (Text.GetLength() > 2 && Text.Find('.') < 0 && nChar != '.')
+			return;
+	}
+	
+	CEdit::OnChar(nChar, nRepCnt, nFlags);
+}
+
+void MyEdit::OnKillFocus(CWnd* pNewWnd) 
+{
+	CString Text;
+	int Index;
+	int Len;
+
+	GetWindowText(Text);
+
+	Index = Text.Find('.');
+
+	Len = Text.GetLength();
+
+	if (Len == 0)
+		SetWindowText("0.0");
+
+	else if (Index < 0)
+		SetWindowText(Text + ".0");
+
+	else if (Index == Len - 1)
+		SetWindowText(Text + "0");
+
+	CEdit::OnKillFocus(pNewWnd);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyEdit.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyEdit.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyEdit.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyEdit.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_MYEDIT_H__951EC391_AFE3_428F_865D_24CA55C68C7C__INCLUDED_)
+#define AFX_MYEDIT_H__951EC391_AFE3_428F_865D_24CA55C68C7C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+class MyEdit : public CEdit
+{
+public:
+
+	MyEdit();
+
+	//{{AFX_VIRTUAL(MyEdit)
+	//}}AFX_VIRTUAL
+
+	virtual ~MyEdit();
+
+protected:
+	//{{AFX_MSG(MyEdit)
+	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+	afx_msg void OnKillFocus(CWnd* pNewWnd);
+	//}}AFX_MSG
+
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,123 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "Frontend.h"
+#include "MyTabCtrl.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+MyTabCtrl::MyTabCtrl()
+{
+}
+
+MyTabCtrl::~MyTabCtrl()
+{
+}
+
+BEGIN_MESSAGE_MAP(MyTabCtrl, CTabCtrl)
+	//{{AFX_MSG_MAP(MyTabCtrl)
+	ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelchange)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void MyTabCtrl::InitTabDialogs(CStringArray *Interfaces,
+							   CStringArray *Addresses,
+							   CStringArray *IsWlan)
+{
+	int i;
+	CRect Client;
+	CRect Win;
+
+	m_Dialog2.Interfaces = Interfaces;
+	m_Dialog2.Addresses = Addresses;
+	m_Dialog2.IsWlan = IsWlan;
+
+	m_Dialog1.Create(GetParent());
+	m_Dialog2.Create(GetParent());
+	m_Dialog3.Create(GetParent());
+	m_Dialog4.Create(GetParent());
+
+	Dialogs[0] = &m_Dialog2;
+	Dialogs[1] = &m_Dialog1;
+	Dialogs[2] = &m_Dialog3;
+	Dialogs[3] = &m_Dialog4;
+
+	Sel = -1;
+
+	for (i = 0; i < 4; i++)
+	{
+		GetClientRect(Client);
+		AdjustRect(FALSE, Client);
+
+		GetWindowRect(Win);
+		GetParent()->ScreenToClient(Win);
+
+		Client.OffsetRect(Win.left, Win.top);
+
+		Dialogs[i]->SetWindowPos(&wndTop, Client.left, Client.top,
+			Client.Width(), Client.Height(), SWP_HIDEWINDOW);
+	}
+
+	DisplayTabDialog();
+}
+
+void MyTabCtrl::DisplayTabDialog()
+{
+	if (Sel != -1)
+		Dialogs[Sel]->ShowWindow(SW_HIDE);
+
+	Sel = GetCurSel();
+
+	Dialogs[Sel]->ShowWindow(SW_SHOW);
+}
+
+void MyTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	pNMHDR = pNMHDR;
+
+	DisplayTabDialog();
+
+	*pResult = 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/MyTabCtrl.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,85 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined(AFX_MYTABCTRL_H__D443FF52_C52D_4C89_AB4B_19B09687EBAE__INCLUDED_)
+#define AFX_MYTABCTRL_H__D443FF52_C52D_4C89_AB4B_19B09687EBAE__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "MyDialog1.h"
+#include "MyDialog2.h"
+#include "MyDialog3.h"
+#include "MyDialog4.h"
+
+class MyTabCtrl : public CTabCtrl
+{
+public:
+	MyTabCtrl();
+
+	class MyDialog1 m_Dialog1;
+	class MyDialog2 m_Dialog2;
+	class MyDialog3 m_Dialog3;
+	class MyDialog4 m_Dialog4;
+
+	void InitTabDialogs(CStringArray *, CStringArray *, CStringArray *);
+	void DisplayTabDialog(void);
+
+	//{{AFX_VIRTUAL(MyTabCtrl)
+	//}}AFX_VIRTUAL
+
+	virtual ~MyTabCtrl();
+
+protected:
+	CDialog *Dialogs[4];
+
+	int Sel;
+
+	//{{AFX_MSG(MyTabCtrl)
+	afx_msg void OnSelchange(NMHDR* pNMHDR, LRESULT* pResult);
+	//}}AFX_MSG
+
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/NodeEntry.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/NodeEntry.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/NodeEntry.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/NodeEntry.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,132 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "stdafx.h"
+#include "NodeEntry.h"
+
+class NodeEntry &NodeEntry::operator=(class NodeEntry &Src)
+{
+	Addr = Src.Addr;
+	Timeout = Src.Timeout;
+
+	MprList.RemoveAll();
+	MprList.AddHead(&Src.MprList);
+
+	HnaList.RemoveAll();
+	HnaList.AddHead(&Src.HnaList);
+
+	MidList.RemoveAll();
+	MidList.AddHead(&Src.MidList);
+
+	return *this;
+}
+
+BOOL NodeEntry::operator==(const class NodeEntry &Comp) const
+{
+	return Addr == Comp.Addr;
+}
+
+void NodeEntry::AddMpr(unsigned int MprAddr, unsigned __int64 Timeout)
+{
+	class MprEntry NewEntry;
+	POSITION Pos;
+
+	NewEntry.Addr = MprAddr;
+
+	Pos = MprList.Find(NewEntry);
+
+	if (Pos != NULL)
+	{
+		class MprEntry &OldEntry = MprList.GetAt(Pos);
+		OldEntry.Timeout = Timeout;
+	}
+
+	else
+	{
+		NewEntry.Timeout = Timeout;
+		MprList.AddTail(NewEntry);
+	}
+}
+
+void NodeEntry::AddMid(unsigned int IntAddr, unsigned __int64 Timeout)
+{
+	class MidEntry NewEntry;
+	POSITION Pos;
+
+	NewEntry.Addr = IntAddr;
+
+	Pos = MidList.Find(NewEntry);
+
+	if (Pos != NULL)
+	{
+		class MidEntry &OldEntry = MidList.GetAt(Pos);
+		OldEntry.Timeout = Timeout;
+	}
+
+	else
+	{
+		NewEntry.Timeout = Timeout;
+		MidList.AddTail(NewEntry);
+	}
+}
+
+void NodeEntry::AddHna(unsigned int NetAddr, unsigned int NetMask,
+					   unsigned __int64 Timeout)
+{
+	class HnaEntry NewEntry;
+	POSITION Pos;
+
+	NewEntry.Addr = NetAddr;
+	NewEntry.Mask = NetMask;
+
+	Pos = HnaList.Find(NewEntry);
+
+	if (Pos != NULL)
+	{
+		class HnaEntry &OldEntry = HnaList.GetAt(Pos);
+		OldEntry.Timeout = Timeout;
+	}
+
+	else
+	{
+		NewEntry.Timeout = Timeout;
+		HnaList.AddTail(NewEntry);
+	}
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/NodeEntry.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/NodeEntry.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/NodeEntry.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/NodeEntry.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,66 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_NODEENTRY_H
+#define TL_NODEENTRY_H
+
+#include "MprEntry.h"
+#include "MidEntry.h"
+#include "HnaEntry.h"
+
+class NodeEntry
+{
+public:
+	unsigned int Addr;
+	unsigned __int64 Timeout;
+
+	CList<class MprEntry, class MprEntry &> MprList;
+	CList<class MidEntry, class MidEntry &> MidList;
+	CList<class HnaEntry, class HnaEntry &> HnaList;
+
+	void AddMpr(unsigned int, unsigned __int64);
+	void AddMid(unsigned int, unsigned __int64);
+	void AddHna(unsigned int, unsigned int, unsigned __int64);
+
+	class NodeEntry &NodeEntry::operator=(class NodeEntry &);
+	BOOL NodeEntry::operator==(const class NodeEntry &) const;
+};
+
+#endif
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/res/Frontend.ico and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/res/Frontend.ico sind verschieden.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/res/Frontend.rc2 ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/res/Frontend.rc2
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/res/Frontend.rc2	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/res/Frontend.rc2	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,13 @@
+//
+// FRONTEND.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+	#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/res/Tray1.ico and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/res/Tray1.ico sind verschieden.
BinÃ¤rdateien ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/res/Tray2.ico and ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/res/Tray2.ico sind verschieden.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/resource.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/resource.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/resource.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/resource.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,68 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Frontend.rc
+//
+#define IDD_FRONTEND_DIALOG             102
+#define IDP_SOCKETS_INIT_FAILED         103
+#define IDR_MAINFRAME                   128
+#define IDD_DIALOG1                     129
+#define IDD_DIALOG2                     130
+#define IDD_DIALOG3                     131
+#define IDD_DIALOG4                     132
+#define IDI_ICON1                       132
+#define IDR_241                         138
+#define IDI_ICON3                       141
+#define IDR_TRAYMENU                    141
+#define IDI_ICON2                       142
+#define IDC_TAB1                        1000
+#define IDC_BUTTON1                     1001
+#define IDC_EDIT1                       1003
+#define IDC_BUTTON2                     1004
+#define IDC_EDIT2                       1004
+#define IDC_EDIT3                       1005
+#define IDC_BUTTON3                     1006
+#define IDC_EDIT4                       1006
+#define IDC_EDIT5                       1007
+#define IDC_LIST1                       1008
+#define IDC_SLIDER2                     1009
+#define IDC_TEXT1                       1010
+#define IDC_EDIT6                       1011
+#define IDC_EDIT7                       1012
+#define IDC_CHECK1                      1013
+#define IDC_CHECK2                      1014
+#define IDC_EDIT9                       1015
+#define IDC_CHECK3                      1016
+#define IDC_BUTTON4                     1017
+#define IDC_BUTTON5                     1018
+#define IDC_CHECK4                      1019
+#define IDC_EDIT10                      1020
+#define IDC_EDIT11                      1021
+#define IDC_EDIT8                       1022
+#define IDC_CHECK5                      1022
+#define IDC_EDIT12                      1023
+#define IDC_EDIT13                      1024
+#define IDC_LIST4                       1025
+#define IDC_EDIT14                      1025
+#define IDC_LIST5                       1026
+#define IDC_EDIT15                      1026
+#define IDC_LIST6                       1027
+#define IDC_RADIO1                      1029
+#define IDC_RADIO2                      1030
+#define IDC_COMBO1                      1031
+#define IDM_START                       32773
+#define IDM_STOP                        32774
+#define IDM_WINDOW                      32775
+#define IDM_SETTINGS                    32776
+#define IDM_OUTPUT                      32777
+#define IDM_EXIT                        32778
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        143
+#define _APS_NEXT_COMMAND_VALUE         32779
+#define _APS_NEXT_CONTROL_VALUE         1032
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/RFC-Default.olsr ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/RFC-Default.olsr
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/RFC-Default.olsr	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/RFC-Default.olsr	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,191 @@
+#
+# Default configuration for the GUI
+#
+
+# Debug level(0-9)
+# If set to 0 the daemon runs in the background
+
+DebugLevel	0
+
+# IP version to use (4 or 6)
+
+IpVersion	4
+
+# FIBMetric ("flat" or "correct")
+
+FIBMetric	"flat"
+
+# HNA IPv4 routes
+# syntax: netaddr/prefix
+
+Hna4 {
+}
+
+# Should olsrd keep on running even if there are
+# no interfaces available? This is a good idea
+# for a PCMCIA/USB hotswap environment.
+# "yes" OR "no"
+
+AllowNoInt	yes
+
+# TOS(type of service) to use. Default is 16
+
+TosValue	16
+
+# Policy Routing Table to use. Default is 254
+
+RtTable		254
+
+# The fixed willingness to use(0-7)
+# If not set willingness will be calculated
+# dynammically based on battery/power status
+
+#Willingness	4
+
+# Allow processes like the GUI front-end
+# to connect to the daemon.
+
+IpcConnect {
+    MaxConnections	0
+}
+
+# Hysteresis adds more robustness to the
+# link sensing.
+# Used by default. 'yes' or 'no'
+
+UseHysteresis	no
+
+# Hysteresis parameters
+# Do not alter these unless you know 
+# what you are doing!
+# Set to auto by default. Allowed
+# values are floating point values
+# in the interval 0,1
+# THR_LOW must always be lower than
+# THR_HIGH!!
+
+#HystScaling	0.50
+#HystThrHigh	0.80
+#HystThrLow	0.30
+
+# Polling rate in seconds(float).
+# Auto uses default value 0.05 sec
+
+Pollrate	0.10
+# Interval to poll network interfaces for configuration
+# changes. Defaults to 2.5 seconds
+NicChgsPollInt	2.50
+# TC redundancy
+# Specifies how much neighbor info should
+# be sent in TC messages
+# Possible values are:
+# 0 - only send MPR selectors
+# 1 - send MPR selectors and MPRs
+# 2 - send all neighbors
+#
+# defaults to 0
+
+TcRedundancy	0
+
+# MPR coverage
+# Specifies how many MPRs a node should
+# try select to reach every 2 hop neighbor
+# Can be set to any integer >0
+# defaults to 1
+
+MprCoverage	1
+
+# Link quality level
+# 0 = do not use link quality
+# 1 = use link quality for MPR selection
+# 2 = use link quality for MPR selection and routing
+
+LinkQualityLevel	0
+
+# Fish Eye algorithm
+# 0 = do not use fish eye
+# 1 = use fish eye
+
+LinkQualityFishEye	0
+
+# Link quality window size
+
+LinkQualityWinSize	12
+
+# Clear screen when printing debug output?
+
+ClearScreen	no
+
+# Olsrd plugins to load
+# This must be the absolute path to the file
+# or the loader will use the following scheme:
+# - Try the paths in the LD_LIBRARY_PATH 
+#   environment variable.
+# - The list of libraries cached in /etc/ld.so.cache
+# - /lib, followed by /usr/lib
+
+LoadPlugin "olsrd_httpinfo.dll" {
+    PlParam "Net"	"0.0.0.0 0.0.0.0"
+}
+
+# Interfaces
+# Multiple interfaces with the same configuration
+# can shar the same config block. Just list the
+# interfaces(e.g. Interface "eth0" "eth2"
+
+Interface "GUI" {
+
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    #Ip4Broadcast	255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    Ip6AddrType 	global
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+    Ip6MulticastSite	ff05::15
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+    Ip6MulticastGlobal	ff0e::1
+
+    # Olsrd can autodetect changes in
+    # interface configurations. Enabled by default
+    # turn off to save CPU.
+    AutoDetectChanges: yes
+    # Emission and validity intervals.
+    # If not defined, RFC proposed values will
+    # in most cases be used.
+
+    #HelloInterval	2.00
+    #HelloValidityTime	6.00
+    #TcInterval		5.00
+    #TcValidityTime	15.00
+    #MidInterval	5.00
+    #MidValidityTime	15.00
+    #HnaInterval	5.00
+    #HnaValidityTime	15.00
+    #LinkQualityMult	default 1.0
+    # When multiple links exist between hosts
+    # the weight of interface is used to determine
+    # the link to use. Normally the weight is
+    # automatically calculated by olsrd based
+    # 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
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/StdAfx.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/StdAfx.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/StdAfx.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/StdAfx.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1 @@
+#include "stdafx.h"
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/StdAfx.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/StdAfx.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/StdAfx.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/StdAfx.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,30 @@
+// stdafx.h : Include-Datei für Standard-System-Include-Dateien,
+//  oder projektspezifische Include-Dateien, die häufig benutzt, aber
+//      in unregelmäßigen Abständen geändert werden.
+//
+
+#if !defined(AFX_STDAFX_H__D43BD17B_AEC0_43A5_9F3B_1DAA99152E38__INCLUDED_)
+#define AFX_STDAFX_H__D43BD17B_AEC0_43A5_9F3B_1DAA99152E38__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN		// Selten verwendete Teile der Windows-Header nicht einbinden
+
+#include <afxwin.h>         // MFC-Kern- und -Standardkomponenten
+#include <afxext.h>         // MFC-Erweiterungen
+#include <afxdtctl.h>		// MFC-Unterstützung für allgemeine Steuerelemente von Internet Explorer 4
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>			// MFC-Unterstützung für gängige Windows-Steuerelemente
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxmt.h>
+#include <afxtempl.h>
+#include <winsock2.h>
+#include <iphlpapi.h>
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein.
+
+#endif // !defined(AFX_STDAFX_H__D43BD17B_AEC0_43A5_9F3B_1DAA99152E38__INCLUDED_)
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/TrayIcon.cpp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/TrayIcon.cpp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/TrayIcon.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/TrayIcon.cpp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,185 @@
+#include "stdafx.h"
+#include "TrayIcon.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "Frontend.h"
+#include "FrontendDlg.h"
+#include "Resource.h"
+
+#define TRAYICONID 987435
+
+HWND s_hWnd;
+TrayIcon* TrayIcon::instance = NULL;
+
+LRESULT CALLBACK TrayIconProc( HWND, UINT, WPARAM, LPARAM lParam )
+{
+	switch (lParam)
+	{
+	case WM_LBUTTONDOWN:
+	case WM_RBUTTONDOWN:
+		TrayIcon::instance->displayPopup();
+		break;
+	}
+	
+	return 1;
+}
+
+void TrayIcon::displayPopup()
+{
+	HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_TRAYMENU));
+	HMENU hSubMenu = GetSubMenu(hMenu, 0);
+
+	EnableMenuItem(hSubMenu, IDM_STOP,
+		MF_BYCOMMAND | (main_dlg.m_StopButton.IsWindowEnabled() ? MF_ENABLED : MF_GRAYED));
+	
+	EnableMenuItem(hSubMenu, IDM_START,
+		MF_BYCOMMAND | (main_dlg.m_StartButton.IsWindowEnabled() ? MF_ENABLED : MF_GRAYED));
+
+	POINT pt;
+	
+	GetCursorPos(&pt);
+	
+	SetForegroundWindow( s_hWnd );
+	
+	int cmd = TrackPopupMenu(hSubMenu,
+		TPM_RIGHTBUTTON | TPM_RETURNCMD, 
+		pt.x, 
+		pt.y, 
+		0, 
+		s_hWnd, 
+		NULL);
+	
+	PostMessage(s_hWnd, WM_NULL, 0, 0); 
+	
+	switch(cmd)
+	{
+	case IDM_EXIT:
+		main_dlg.OnExitButton();
+		break;
+		
+	case IDM_WINDOW:
+		main_dlg.OpenIcon();
+		main_dlg.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+		break;
+
+	case IDM_SETTINGS:
+		main_dlg.m_TabCtrl.SetCurSel(0);
+		main_dlg.m_TabCtrl.DisplayTabDialog();
+		main_dlg.OpenIcon();
+		main_dlg.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+		break;
+		
+	case IDM_OUTPUT:
+		main_dlg.m_TabCtrl.SetCurSel(1);
+		main_dlg.m_TabCtrl.DisplayTabDialog();
+		main_dlg.OpenIcon();
+		main_dlg.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+		break;
+		
+	case IDM_STOP:
+		main_dlg.OnStopButton();
+		break;
+		
+	case IDM_START:
+		main_dlg.OnStartButton();
+		break;
+	}
+	
+	DestroyMenu(hMenu);
+}
+
+void TrayIcon::setStatus( status con_stat, const char* message )
+{
+	switch( con_stat )
+	{
+	case CONNECTED:
+		setTrayAppearance( false, IDI_ICON2, message );
+		break;
+		
+	case OFF:
+		setTrayAppearance( false, IDI_ICON3, message );
+		break;
+		
+	case ON:
+		setTrayAppearance( false, IDI_ICON1, message );
+		break;
+	}
+}
+
+void TrayIcon::setTrayAppearance( bool start, unsigned int res_id, const char* message )
+{
+	NOTIFYICONDATA notifyIconData;
+	
+	notifyIconData.cbSize = sizeof(notifyIconData);
+	notifyIconData.hWnd = s_hWnd;
+	
+	notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+	notifyIconData.uCallbackMessage = 123456;
+	notifyIconData.uID = TRAYICONID; 
+	notifyIconData.hIcon = (HICON)LoadIcon( hInst, MAKEINTRESOURCE( res_id ) );  
+	strncpy( notifyIconData.szTip, message, sizeof (notifyIconData.szTip) ); 
+	
+	if( start )
+		Shell_NotifyIcon( NIM_ADD, &notifyIconData );
+	else
+		Shell_NotifyIcon( NIM_MODIFY, &notifyIconData );
+}
+
+TrayIcon::TrayIcon( CFrontendDlg& dlg, HINSTANCE hInst ) : main_dlg( dlg ), hInst( hInst )
+{
+	instance = this;
+	WNDCLASS wndClass;
+	
+	wndClass.style = 0; 
+	wndClass.lpfnWndProc = TrayIconProc;
+	wndClass.cbClsExtra = 0;
+	wndClass.cbWndExtra = 0;
+	wndClass.hInstance = hInst;
+	wndClass.hIcon = NULL;
+	wndClass.hCursor = NULL;
+	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+	wndClass.lpszMenuName = NULL;
+	wndClass.lpszClassName = "OLSRdTrayIcon";
+	
+	if (0 != RegisterClass(&wndClass))
+	{
+		s_hWnd = CreateWindow( 
+			"OLSRdTrayIcon", 
+			"Invisible Message Window", 
+			WS_OVERLAPPEDWINDOW,
+			CW_USEDEFAULT,
+			CW_USEDEFAULT,
+			CW_USEDEFAULT,
+			CW_USEDEFAULT,
+			NULL,
+			NULL,
+			hInst,
+			NULL);
+		
+		if (s_hWnd)
+		{
+			ShowWindow(s_hWnd, SW_HIDE);
+			
+			UpdateWindow(s_hWnd);
+		}
+	}
+	
+	setTrayAppearance( true, IDI_ICON3, "Starting..." );
+}
+
+TrayIcon::~TrayIcon()
+{
+	NOTIFYICONDATA notifyIconData;
+	
+	notifyIconData.cbSize = sizeof(notifyIconData);
+	notifyIconData.hWnd = s_hWnd;
+	
+	notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+	notifyIconData.uCallbackMessage = 123456;
+	notifyIconData.uID = TRAYICONID; 
+	notifyIconData.hIcon = NULL;
+	
+	Shell_NotifyIcon( NIM_DELETE, &notifyIconData );
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/TrayIcon.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/TrayIcon.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/TrayIcon.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/TrayIcon.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,31 @@
+#ifndef TRAYICON_H_171149531
+#define TRAYICON_H_171149531
+
+class CFrontendDlg;
+
+class TrayIcon
+{
+public:
+	TrayIcon( CFrontendDlg&, HINSTANCE );
+	~TrayIcon();
+
+	void displayPopup();	
+
+	static TrayIcon* getInstance()	{ return instance; }
+
+	enum status { CONNECTED, ON, OFF };
+
+	void setStatus( status con_status, const char* message );
+
+private:
+	void setTrayAppearance( bool, unsigned int, const char* message );
+
+	HINSTANCE hInst;
+
+	CFrontendDlg& main_dlg;
+
+	friend LRESULT CALLBACK TrayIconProc( HWND, UINT, WPARAM, LPARAM );
+	static TrayIcon* instance;
+};
+
+#endif // TRAYICON_H_171149531
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/trustInfo.manifest ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/trustInfo.manifest
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Main/trustInfo.manifest	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Main/trustInfo.manifest	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="requireAdministrator" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+</assembly>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/readme.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/readme.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/readme.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/readme.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,39 @@
+Build the olsr.org Routing Daemon on Windows
+============================================
+
+Some remarks that may help you to build and run the olsr.org's
+routing daemon on Windows. You need the following softs to 
+compile:
+
+- A Cygwin compiling environment. Download the Cygwin setup.exe
+  from http://www.cygwin.com/ and install at least these packages:
+  devel/bison, devel/flex, devel/gcc-mingw-g++ and devel/make
+
+- You need a running copy of MSVC. Either MSVC6 or MSVC8 may be
+  supported. You also need the Microsoft Platform SDK installed.
+  MSVC8 should be easy, while MSVC6 needs an older version:
+  http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm
+  It's OK to install the "Core SDK" and ignore other stuff.
+
+- Be sure to add the Microsoft SDK pathes to your MSVC-GUI-Pathes
+  (Extras/Options/Pathes, Add Inlude and Lib at least)
+
+- To build the setup, Nullsoft's installer is required. Download:
+  http://nsis.sourceforge.net/
+
+You need the Cygwin suite up and running. Normally, the users home
+dir is not installed properly with this. Start the "bash" command
+line and check by entering "cd". If an error message shows up you
+can set a shortcut/link from c:\cygwin to c:\Docs+Settings, then go
+to Windows-SysCtl/System/Advanced/Envrionment and explicitly set the
+HOME=c:\Docs+Settings\[yourloginname]. Then try again to "cd".
+
+Then enter the olsrd's directory (either bash or cmd.exe will do).
+Start "make all libs". Should compile. Spits out olsrd.exe and some
+dll's for the plugins. For the GUI, you also need the linking lib to
+the olsrd_cfgparser.dll: "make gui/win32/Main/olsrd_cfgparser.lib"
+
+Then enter your favorite MSVC flavour and hit [F7]. After some prayers,
+you may be able to hack in the GUI changes you want...
+
+// Sven-Ola in Dec-2007
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Shim/shim.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Shim/shim.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Shim/shim.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Shim/shim.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,133 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 <windows.h>
+
+int main(int argc, char *argv[])
+{
+	STARTUPINFO StartInfo;
+	PROCESS_INFORMATION ProcInfo;
+	int i;
+	char *CmdLine;
+	char *Walker;
+	char NewCmdLine[MAX_PATH + 500];
+	HANDLE Handles[2];
+	unsigned long Res;
+	int Quotes;
+
+	Handles[0] = OpenEvent(EVENT_ALL_ACCESS, FALSE, "TheOlsrdShimEvent");
+
+	if (Handles[0] == NULL)
+	{
+		MessageBox(NULL, "Cannot open event.", "Shim Error", MB_ICONERROR | MB_OK);
+		ExitProcess(1);
+	}
+
+	CmdLine = GetCommandLine();
+
+	Quotes = 0;
+	
+	while (*CmdLine != 0)
+	{
+		if (*CmdLine == '"')
+			Quotes = !Quotes;
+
+		else if (*CmdLine == ' ' && !Quotes)
+			break;
+
+		CmdLine++;
+	}
+
+	if (*CmdLine == 0)
+	{
+		MessageBox(NULL, "Missing arguments.", "Shim Error", MB_ICONERROR | MB_OK);
+		ExitProcess(1);
+	}
+
+	GetModuleFileName(NULL, NewCmdLine, MAX_PATH);
+
+	for (Walker = NewCmdLine; *Walker != 0; Walker++);
+
+	while (*Walker != '\\')
+		Walker--;
+
+	Walker[1] = 'o';
+	Walker[2] = 'l';
+	Walker[3] = 's';
+	Walker[4] = 'r';
+	Walker[5] = 'd';
+	Walker[6] = '.';
+	Walker[7] = 'e';
+	Walker[8] = 'x';
+	Walker[9] = 'e';
+
+	Walker[10] = ' ';
+
+	Walker += 11;
+
+	while ((*Walker++ = *CmdLine++) != 0);
+
+	for (i = 0; i < sizeof (STARTUPINFO); i++)
+		((char *)&StartInfo)[i] = 0;
+
+	StartInfo.cb = sizeof (STARTUPINFO);
+
+	if (!CreateProcess(NULL, NewCmdLine, NULL, NULL, TRUE,
+		CREATE_NEW_PROCESS_GROUP, NULL, NULL, &StartInfo, &ProcInfo))
+	{
+		MessageBox(NULL, "Cannot execute OLSR server.", "Shim Error", MB_ICONERROR | MB_OK);
+		ExitProcess(1);
+	}
+
+	Handles[1] = ProcInfo.hProcess;
+
+	Res = WaitForMultipleObjects(2, Handles, FALSE, INFINITE);
+
+	if (Res == WAIT_OBJECT_0)
+	{
+		GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, ProcInfo.dwProcessId);
+		WaitForSingleObject(ProcInfo.hProcess, INFINITE);
+	}
+	
+	CloseHandle(ProcInfo.hThread);
+	CloseHandle(ProcInfo.hProcess);
+
+	ExitProcess(0);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Shim/Shim.dsp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Shim/Shim.dsp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Shim/Shim.dsp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Shim/Shim.dsp	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="Shim" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Shim - Win32 Debug
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE 
+!MESSAGE NMAKE /f "Shim.mak".
+!MESSAGE 
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE 
+!MESSAGE NMAKE /f "Shim.mak" CFG="Shim - Win32 Debug"
+!MESSAGE 
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE 
+!MESSAGE "Shim - Win32 Release" (basierend auf  "Win32 (x86) Console Application")
+!MESSAGE "Shim - Win32 Debug" (basierend auf  "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Shim - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "Shim - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Shim - Win32 Release"
+# Name "Shim - Win32 Debug"
+# Begin Group "Quellcodedateien"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\shim.c
+# End Source File
+# End Group
+# Begin Group "Header-Dateien"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Ressourcendateien"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Shim/Shim.vcproj ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Shim/Shim.vcproj
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Shim/Shim.vcproj	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Shim/Shim.vcproj	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="Shim"
+	ProjectGUID="{C09B8925-0F9C-4F88-9BAE-7D5EAD8159D3}"
+	RootNamespace="Shim"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				EntryPointSymbol=""
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol=""
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\shim.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Switch.dsw ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Switch.dsw
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Switch.dsw	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Switch.dsw	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
+
+###############################################################################
+
+Project: "Frontend"=".\Main\Frontend.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name Shim
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "Shim"=".\Shim\Shim.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Switch.sln ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Switch.sln
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/gui/win32/Switch.sln	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/gui/win32/Switch.sln	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,26 @@
+ï»¿
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shim", "Shim\Shim.vcproj", "{C09B8925-0F9C-4F88-9BAE-7D5EAD8159D3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Main", "Main\Main.vcproj", "{01BB6810-46BB-4BE5-BCE3-96FF48F5DF1D}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{C09B8925-0F9C-4F88-9BAE-7D5EAD8159D3}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C09B8925-0F9C-4F88-9BAE-7D5EAD8159D3}.Debug|Win32.Build.0 = Debug|Win32
+		{C09B8925-0F9C-4F88-9BAE-7D5EAD8159D3}.Release|Win32.ActiveCfg = Release|Win32
+		{C09B8925-0F9C-4F88-9BAE-7D5EAD8159D3}.Release|Win32.Build.0 = Release|Win32
+		{01BB6810-46BB-4BE5-BCE3-96FF48F5DF1D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{01BB6810-46BB-4BE5-BCE3-96FF48F5DF1D}.Debug|Win32.Build.0 = Debug|Win32
+		{01BB6810-46BB-4BE5-BCE3-96FF48F5DF1D}.Release|Win32.ActiveCfg = Release|Win32
+		{01BB6810-46BB-4BE5-BCE3-96FF48F5DF1D}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/ld-warnings ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/ld-warnings
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/ld-warnings	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/ld-warnings	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# We expect warning options for gcc as arguments and return the ones which are
+# accepted by the given gcc.
+#
+
+set -ue
+#set -vx
+
+# make sure we do not use some locale ....
+export LANG=C LC_ALL=C LC_COLLATE=C LC_CTYPE=C LC_MESSAGES=C LC_NUMERIC=C
+
+OPTS=""
+for param; do
+    case "$param" in
+    -[fWm]?*) OPTS="$OPTS $param";;
+    *)        echo "Ignoring $param" >&2
+    esac
+done
+
+testcompile() {
+    $CC $OPTS -x c -o /dev/null - 2>&1 <<- EOF
+       int main(void) {
+           return 0;
+       }
+EOF
+}
+
+parsetest() {
+    while read error; do 
+        case "$error" in
+        *ld:\ unrecognized\ *option\ \'*)
+            opt="${error#*\'}"
+            opt="${opt%\'*}"
+            ;;
+        *) continue
+            ;;
+       esac
+       # if we come here, we have in $opt the option to remove. and
+       # we remove all instances. And we save agoinst leading "-"
+       NEW_OPTS=""
+       for o in $OPTS; do
+           case "$o" in
+               -Wl,$opt) : echo "Removed $o" >&2;;
+               *)        NEW_OPTS="$NEW_OPTS $o";;
+           esac
+       done
+       OPTS="$NEW_OPTS"
+    done
+    echo $OPTS
+}
+
+testcompile | parsetest
+
+exit 0
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,57 @@
+# The olsr.org Optimized Link-State Routing daemon(olsrd)
+# Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+# Arprefresh plugin Copyright (c) 2007, Sven-Ola-aet-gmx.de
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_arprefresh
+PLUGIN_VER =	0.1
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/README_ARPREFRESH ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/README_ARPREFRESH
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/README_ARPREFRESH	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/README_ARPREFRESH	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,31 @@
+---------------------------------------------------------------------
+ARP REFRESH PLUGIN FOR OLSRD
+by Sven-Ola Tuecke <sven-ola-aet-gmx.de>
+---------------------------------------------------------------------
+
+This plugin listens to all recevice UDP packets and maintains an
+internal list of MAC addresses extracted from these. By hitchhiking
+the set-route-function, the kernel ARP cache will be refreshed from
+this list if a direct-neighbour host route is configured. Result:
+no more ARP lookups if you use a larger routing chain - e.g. fetch
+a web site 8 olsr-hops away does not show the typcial 8-nodes-need
+to ARP first delay.
+
+---------------------------------------------------------------------
+PLUGIN PARAMETERS (PlParam)
+---------------------------------------------------------------------
+
+None.
+
+---------------------------------------------------------------------
+SAMPLE CONFIG
+---------------------------------------------------------------------
+
+add in /etc/olsrd.conf:
+
+LoadPlugin "arprefresh.so.0.1"
+{
+}
+
+---------------------------------------------------------------------
+EOF / 2007-AUG-02
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007, Sven-Ola Tuecke <sven-ola-aet-gmx.de>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+
+/*
+ * Plugin to refresh the local ARP cache from received OLSR broadcasts
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netpacket/packet.h>
+#include <linux/types.h>
+#include <linux/filter.h>
+
+#include "olsrd_arprefresh.h"
+#include "kernel_routes.h"
+#include "scheduler.h"
+
+#undef ARPREFRESH_DEBUG
+#define PLUGIN_INTERFACE_VERSION 5
+
+/****************************************************************************
+ *                Functions that the plugin MUST provide                    *
+ ****************************************************************************/
+ 
+/**
+ * Plugin interface version
+ * Used by main olsrd to check plugin interface version
+ */
+int olsrd_plugin_interface_version(void)
+{
+	return PLUGIN_INTERFACE_VERSION;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+typedef struct
+{
+	struct ethhdr eth;
+	struct iphdr ip;
+	struct udphdr udp;
+} __attribute__((packed)) arprefresh_buf;
+
+static int arprefresh_sockfd = -1;
+static const int arprefresh_portnum = 698;
+
+/**
+ * Scheduled event to fetch gathered packets and update the ARP cache
+ * called from olsrd main thread
+ */
+static void olsr_arp_event(void* foo __attribute__((unused)))
+{
+	if (0 <= arprefresh_sockfd)
+	{
+		arprefresh_buf buf;
+		struct sockaddr_ll from;
+		socklen_t fromlen = sizeof(from);
+		
+		/*
+		 * Grab a single snapshot on the packet socket. This only works
+		 * if not too much IP traffic is currently flowing through.
+		 */
+		ssize_t size = recvfrom(arprefresh_sockfd, &buf, sizeof(buf),
+			MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
+
+		if (0 <= size &&
+		    size >= (ssize_t)sizeof(buf) /*** &&
+		    ETH_P_IP == ntohs(buf.eth.h_proto) &&
+		    IPPROTO_UDP == buf.ip.protocol &&
+		    arprefresh_portnum == ntohs(buf.udp.source) &&
+		    arprefresh_portnum == ntohs(buf.udp.dest) ***/)
+		{
+			union
+			{
+				struct arpreq arp;
+				struct sockaddr_in in_pa;
+				struct sockaddr_in6 in_pa6;
+			} req;
+
+			memset(&req, 0, sizeof(req));
+			req.in_pa.sin_family = AF_INET;
+			memcpy(&req.in_pa.sin_addr, &buf.ip.saddr, sizeof(buf.ip.saddr));
+			req.arp.arp_ha.sa_family = AF_LOCAL;
+			memcpy(&req.arp.arp_ha.sa_data, &buf.eth.h_source, sizeof(buf.eth.h_source));
+			req.arp.arp_flags = ATF_COM;
+			if_indextoname(from.sll_ifindex, req.arp.arp_dev);
+#ifdef ARPREFRESH_DEBUG
+			{
+				int i;
+				OLSR_PRINTF(0, "Refresh on %s, %s=", req.arp.arp_dev,
+					inet_ntoa(*((struct in_addr*)&buf.ip.saddr)));
+				for(i = 0; i < (ssize_t)sizeof(buf.eth.h_source); i++)
+				{
+					OLSR_PRINTF(0, "%02x%s", ((unsigned char *)&buf.eth.h_source)[i], i < (ssize_t)sizeof(buf.eth.h_source) -1 ? ":" : "\n");
+				}
+			}
+#endif
+			if (ioctl(arprefresh_sockfd, SIOCSARP, &req) < 0) {
+				OLSR_PRINTF(1, "*** ARPREFRESH: SIOCSARP: %s\n", strerror(errno));
+				close(arprefresh_sockfd);
+				arprefresh_sockfd = -1;
+				return;
+			}
+		}
+	}
+}
+
+/**
+ * Initialize plugin
+ * Called after all parameters are passed
+ */
+int olsrd_plugin_init(void)
+{
+	int ret = 0;
+	if (AF_INET == olsr_cnf->ip_version)
+	{
+		int flags;
+		struct sock_fprog filter;
+		struct sock_filter BPF_code[]=
+		{
+			/* tcpdump -s [sizeof(arprefresh_buf)] -ni lo udp and dst port [arprefresh_portnum] -dd */
+			{ 0x28, 0, 0, 0x0000000c },
+			{ 0x15, 0, 4, 0x000086dd },
+			{ 0x30, 0, 0, 0x00000014 },
+			{ 0x15, 0, 11, 0x00000011 },
+			{ 0x28, 0, 0, 0x00000038 },
+			{ 0x15, 8, 9, arprefresh_portnum },
+			{ 0x15, 0, 8, 0x00000800 },
+			{ 0x30, 0, 0, 0x00000017 },
+			{ 0x15, 0, 6, 0x00000011 },
+			{ 0x28, 0, 0, 0x00000014 },
+			{ 0x45, 4, 0, 0x00001fff },
+			{ 0xb1, 0, 0, 0x0000000e },
+			{ 0x48, 0, 0, 0x00000010 },
+			{ 0x15, 0, 1, arprefresh_portnum },
+			{ 0x6, 0, 0, sizeof(arprefresh_buf) },
+			{ 0x6, 0, 0, 0x00000000 }
+		};
+		filter.len = sizeof(BPF_code) / sizeof(BPF_code[0]);
+		filter.filter = BPF_code;
+		if (0 <= (arprefresh_sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) &&
+		    0 <= (flags = fcntl(arprefresh_sockfd, F_GETFL)) &&
+		    0 <= fcntl(arprefresh_sockfd, F_SETFL, flags | O_NONBLOCK) &&
+		    0 <= setsockopt(arprefresh_sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
+		{
+			/* Register the ARP refresh event */
+                        olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
+                                         &olsr_arp_event, NULL, 0);
+			ret = 1;
+		}
+		else
+		{
+			OLSR_PRINTF(1, "*** ARPREFRESH: Cannot create non-blocking filtering packet socket: %s\n", strerror(errno));
+		}
+	}
+	else
+	{
+		OLSR_PRINTF(1, "*** ARPREFRESH: IPv6 not supported\n");
+	}
+	return ret;
+}
+
+/****************************************************************************
+ *       Optional private constructor and destructor functions              *
+ ****************************************************************************/
+
+static void __attribute__ ((constructor)) my_init(void);
+static void __attribute__ ((destructor)) my_fini(void);
+
+static void my_init(void)
+{
+	printf("OLSRD arprefresh plugin by Sven-Ola\n");
+}
+
+/**
+ * Optional Private Destructor
+ */
+static void my_fini(void)
+{
+	if (0 <= arprefresh_sockfd)
+	{
+		close(arprefresh_sockfd);
+		arprefresh_sockfd = -1;
+	}
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/src/olsrd_arprefresh.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, Sven-Ola Tuecke <sven-ola-aet-gmx.de>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+
+#ifndef _OLSRD_ARPREFRESH
+#define _OLSRD_ARPREFRESH
+
+#include "olsr_types.h"
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+
+int olsrd_plugin_init(void);
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+int olsrd_plugin_interface_version(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/arprefresh/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/arprefresh/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,63 @@
+#
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_bmf
+PLUGIN_VER =	1.5.3
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+LIBS +=	$(OS_LIB_PTHREAD)
+
+ifneq ($(OS),linux)
+
+default_target install clean: 
+	@echo "*** BMF Plugin only supported on Linux, sorry!"
+
+else
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/README_BMF.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/README_BMF.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/README_BMF.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/README_BMF.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,719 @@
+BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD
+by Erik Tromp (erik.tromp@nl.thalesgroup.com, erik_tromp@hotmail.com)
+Version 1.5.3
+
+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 hosts 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.
+
+
+2. How to build and install
+---------------------------
+
+Download the olsr-bmf-v1.5.3.tar.gz file and save it into your OLSRD
+base install directory.
+
+Change directory (cd) to your OLSRD base install directory.
+
+At the command prompt, type:
+
+  tar -zxvf ./olsr-bmf-v1.5.3.tar.gz
+
+then type:
+
+  make build_all
+
+followed by:
+
+  make install_all
+
+Next, turn on the possibility to create a tuntap interface (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
+
+To configure BMF in OLSR, you must edit the file /etc/olsrd.conf
+to load the BMF plugin. For example, add the following lines:
+
+  LoadPlugin "olsrd_bmf.so.1.5.3"
+  {
+    # No PlParam entries required for basic operation
+  }
+
+
+3. How to run
+-------------
+
+After building and installing OLSRD with the BMF plugin, run the
+olsrd daemon by entering at the shell prompt:
+
+  olsrd
+
+Look at the output; it should list the BMF plugin, e.g.:
+
+  ---------- LOADING LIBRARY olsrd_bmf.so.1.5.3 ----------
+  OLSRD Basic Multicast Forwarding (BMF) plugin 1.5.3 (Feb 24 2008 17:58:02)
+    (C) Thales Communications Huizen, Netherlands
+    Erik Tromp (eriktromp@users.sourceforge.net)
+  Checking plugin interface version:  5 - OK
+  Trying to fetch plugin init function: OK
+  Trying to fetch parameter table and it's size...
+  Sending parameters...
+  "NonOlsrIf"/"eth0"... NonOlsrIf: OK
+  Running plugin_init function...
+  OLSRD Basic Multicast Forwarding (BMF) plugin: opened 5 sockets
+  ---------- LIBRARY olsrd_bmf.so.1.5.3 LOADED ----------
+
+
+4. How to check if it works
+---------------------------
+
+Enter the following command on the command prompt:
+  
+  ping 224.0.0.1
+
+All OLSR-BMF hosts in the OLSR network should respond. For example,
+assume we have three hosts, with IP addresses 192.168.151.50,
+192.168.151.53 and 192.168.151.55. On host 192.168.151.50 we enter
+the following ping command:
+
+root@IsdbServer:~# ping 224.0.0.1
+PING 224.0.0.1 (224.0.0.1) 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!)
+
+We can see the response from the originating host (192.168.151.50)
+(it is normal behaviour for hosts sending multicast packets to
+receive their own packets). We can also see the responses by the
+other hosts (correctly seen as DUPlicates by ping).
+
+Note: when using an older version of ping than the standard from
+iputils-20020927, as found in most current Linux distributions, you may want
+to test BMF by specifying the output interface to the ping command:
+
+  ping -I bmf0 224.0.0.1
+
+Older versions of 'ping' (e.g. as found in iputils-20020124) may bind to the
+autoselected source address, which may be incorrect. Since BMF re-uses
+one of the existing IP addresses for the "bmf0" network interface, the
+older-version ping command may 'autobind' to the wrong interface.
+
+See also the note in the iputils-20020927/RELNOTES file:
+"* Mads Martin Jørgensen <mmj@suse.de>: ping should not bind to autoselected
+  source address, it used to work when routing changes. Return classic
+  behaviour, option -B is added to enforce binding."
+
+
+5. How does it work
+-------------------
+
+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 host. We will need to know which
+host forwarded the IP packet to us. Since OLSR keeps track of which
+hosts select our host as MPR (see the olsr_lookup_mprs_set(...) function),
+we can determine if the host 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. If not, we do not forward the packet.
+
+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 50698. 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 an exact specification of the encapsulation
+format, refer to paragraph 10 below.
+
+For local reception, each received encapsulated packets is unpacked
+and passed into a tuntap interface which is specially created for
+this purpose.
+
+There are other flooding solutions available that do not use
+encapsulation. The problem with these solutions is that they cannot
+prevent duplicates of forwarded packets to enter the IP stack. For
+example, if a host is receiving flooded (unencapsulated, native IP)
+packets via two MPR hosts, there is no way to stop the reception of
+the packets coming in via the second MPR host. To prevent this, BMF
+uses a combination of encapsulated flooding and local reception via
+a tuntap interface.
+
+Here is in short how the flooding works (see also the
+BmfEncapsulatedPacketReceived(...) function; details with respect to
+the forwarding towards non-OLSR enabled hosts are omitted):
+  
+  On all OLSR-enabled interfaces, setup reception of packets
+    on UDP port 50698.
+  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 interface.
+    If I am an MPR for the host that forwarded the packet to me,
+      forward the packet to all OLSR-enabled interfaces *including*
+      the interface on which it was received.
+
+
+6. Advanced configuration
+-------------------------
+
+All configuration of BMF is done via the "LoadPlugin" section in
+the /etc/olsrd.conf file.
+
+The following gives an overview of all plugin parameters that can be
+configured:
+
+  LoadPlugin "olsrd_bmf.so.1.5.3"
+  {
+    # Specify the name of the BMF network interface.
+    # Defaults to "bmf0".
+    PlParam "BmfInterface" "mybmf0"
+
+    # Specify the IP address and mask for the BMF network interface.
+    # By default, the IP address of the first OLSR interface is copied.
+    # The default prefix length is 32.
+    PlParam "BmfInterfaceIp" "10.10.10.234/24"
+
+    # Enable or disable the flooding of local broadcast packets
+    # (e.g. packets with IP destination 192.168.1.255). Either "yes"
+    # or "no". Defaults to "yes".
+    PlParam "DoLocalBroadcast" "no"
+
+    # Enable or disable the capturing packets on the OLSR-enabled
+    # interfaces (in promiscuous mode). Either "yes" or "no". Defaults
+    # to "no".
+    # The multicast (and, if configured, local broadcast) packets sent on
+    # the non-OLSR network interfaces and on the BMF network interface will
+    # always be flooded over the OLSR network.
+    # If this parameter is "yes", also the packets sent on the OLSR-enabled
+    # network interfaces will be flooded over the OLSR network.
+    # NOTE: This parameter should be set consistently on all hosts throughout
+    # the network. If not, hosts may receive multicast packets in duplicate.
+    PlParam "CapturePacketsOnOlsrInterfaces" "yes"
+
+    # The forwarding mechanism to use. Either "Broadcast" or
+    # "UnicastPromiscuous". Defaults to "Broadcast".
+    # In the "UnicastPromiscuous" mode, packets are forwarded (unicast) to the
+    # best candidate neighbor; other neighbors listen promiscuously. IP-local
+    # broadcast is not used. This saves air time on 802.11 WLAN networks,
+    # on which unicast packets are usually sent at a much higher bit rate
+    # than broadcast packets (which are sent at a basic bit rate).
+    PlParam "BmfMechanism" "UnicastPromiscuous"
+
+    # The number of times BMF will transmit the same packet whenever it decides
+    # to use broadcast to forward a packet. Defaults to 1. Not used if
+    # "BmfMechanism" is set to "UnicastPromiscuous".
+    PlParam "BroadcastRetransmitCount" "2"
+
+    # If the number of neighbors to forward to is less than or equal to the
+    # FanOutLimit, then packets to be relayed will be sent via unicast.
+    # If the number is greater than the FanOutLimit the packet goes out
+    # as broadcast. Legal values are 1...10. See MAX_UNICAST_NEIGHBORS
+    # as defined in NetworkInterfaces.h . Defaults to 2. Not used if
+    # "BmfMechanism" is set to "UnicastPromiscuous".
+    PlParam "FanOutLimit" "4"
+
+    # List of non-OLSR interfaces to include
+    PlParam     "NonOlsrIf"  "eth2"
+    PlParam     "NonOlsrIf"  "eth3"
+  }
+
+BmfInterfaceIp
+--------------
+
+By default, the BMF network interface will get the IP address of the
+first OLSR interface, with a prefix length of 32. Having two network
+interfaces with the same IP address may seem strange, but it is not
+a problem, since the BMF network interface is not used in any point-to-
+point routing.
+
+The advantage of assigning a known OLSR IP address to the BMF network
+interface is that multicast packets, sent via the BMF network interface,
+get a known IP source address, to which the receivers of the packets
+can reply. That is useful when using, for example, the command
+"ping 224.0.0.1".
+
+An advantage of using a prefix length of 32 is that the Linux IP
+stack will not automatically enter a subnet routing entry (via the BMF
+network interface) into the kernel routing table. Such a routing entry
+would be useless, because the BMF network interface does not forward
+point-to-point traffic.
+
+If you configure a specific IP address and mask via the "BmfInterfaceIp"
+parameter, BMF will cause the specified IP host address to be advertised
+into the OLSR network via the HNA mechanism, so that the other hosts in
+the network know how to route back.
+
+CapturePacketsOnOlsrInterfaces
+------------------------------
+
+If "CapturePacketsOnOlsrInterfaces" is set to "yes", any multicast
+or local broadcast IP packet, sent by an application on *any* OLSR
+interface, will be flooded over the OLSR network. Each OLSR host
+will receive the packet on its BMF network interface, "bmf0". The
+OLSR-interfaces will be in promiscuous mode to capture the multicast
+or local broadcast packets.
+
+For example, if "eth1" is an OLSR interface, the following command
+will result in one response from each OLSR host in the network:
+
+  ping -I eth1 224.0.0.1
+
+A disadvantage of this configuration is that a host may, in rare
+cases, receive a multicast packet twice. This is best explained
+by looking at the following network diagram:
+
+        eth0   eth0
+      A ----------- B
+ eth1 |            / eth1
+      |           /
+ eth0 |          /
+      C --------+
+        eth1
+
+Suppose host A is running a ping session that is sending ping
+packets on "eth1". The BMF process on host A will see the outgoing
+packets on "eth1", encapsulates these packets and sends the
+encapsulated packets on "eth0". Let's assume we are using the link
+quality extensions of OLSR, and the 2-hop path A - B - C is better
+(in terms of ETX) than the 1-hop path A - C. In that case host B is
+an MPR for host A. Host B receives the encapsulated packets of host A
+on its "eth0" interface, and, since it is an MPR, it decides to
+forward them on "eth1".
+
+In most cases, host C will receive the original, unencapsulated
+ping packet on its "eth0" interface before the encapsulated
+ping packet from host B arrives on its "eth1" interface. When the
+encapsulated packet from B arrives, the BMF process will then see
+that it is a duplicate and discard it.
+
+However, in the IP world, there are no guarantees, so it may
+happen that host C receives the encapsulated packet from host B
+first. That packet is then unpacked and locally delivered to the
+BMF network interface "bmf0". When the original, unencapsulated
+packet then comes in on "eth0", there is no way to stop it from
+being received (for a second time) by the Linux IP stack.
+
+As said, this may be a rare case. Besides, most applications
+can deal with a duplicate reception of the same packet. But if
+you're a purist and want everything to work correct, you should
+leave "CapturePacketsOnOlsrInterfaces" to its default value "no".
+
+A disadvantage of leaving "CapturePacketsOnOlsrInterfaces" to its
+default value "no" is that all multicast traffic must go via the
+BMF network interface "bmf0". However, this should not be a problem,
+since a route to all multicast addresses via the BMF network
+interface "bmf0" is automatically added when BMF is started.
+
+
+7. Adding non-OLSR interfaces to the multicast flooding
+-------------------------------------------------------
+
+As a special feature, it is possible to also forward from and to
+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.5.3"
+  {
+    # 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.
+
+
+8. Interworking with other multicast routers
+--------------------------------------------
+
+In a typical interworking configuration there is a network of OLSR hosts
+in which one host acts as a gateway to a fixed infrastructure network.
+Usually that host will be advertising a default route via the HNA
+mechanism, e.g. by adding the following lines to its /etc/olsrd.conf
+file:
+
+  Hna4
+  {
+  #   Internet gateway:
+      0.0.0.0      0.0.0.0
+  }
+
+Alternatively, the gateway is running OLSRDs dynamic internet gateway
+plugin; read the file ../../lib/dyn_gw/README_DYN_GW .
+
+The gateway host will usually have at least one OLSR-interface, and
+at least one non-OLSR interface, running a third-party routing protocol
+like OSPF.
+
+It is beyond the scope of this document to deal with the interworking
+between BMF and all possible multicast routing daemons. As an example,
+let's assume the gateway is running the mrouted multicast daemon (which
+implements the DVMRP protocol). Also, assume that all the IP addresses
+in the OLSR network are within the IP subnet 10.0.0.0/8 . Then mrouted
+on the gateway needs to be configured to accept IGMP requests from IP
+clients within the 10.0.0.0/8 subnet on the BMF network interface
+("bmf0"). This is easily configured by adding a line to the
+/etc/mrouted.conf configuration file:
+
+  phyint bmf0 altnet 10.0.0.0/8
+
+Not strictly necessary, but clean, is to disable the DVMRP protocol
+on the OLSR interfaces, as no DVMRP routers are expected inside the
+OLSR network. Suppose the gateway is running OLSR on "eth1", then
+add the following line /etc/mrouted.conf :
+
+  phyint eth1 disable
+
+Finally, mrouted does not accept interfaces with prefix length 32.
+Therefore, override the default IP address and prefix length of
+the BMF network interface, by editing the /etc/olsrd.conf file.
+For example:
+
+  LoadPlugin "olsrd_bmf.so.1.5.3"
+  {
+      PlParam "BmfInterfaceIp" "10.10.10.4/24"
+  }
+
+Note that it is not necessary, and even incorrect, to pass the
+non-OLSR interface to BMF as a "NonOlsrIf" parameter in the
+"LoadPlugin" section of the gateway host. When the mrouted
+multicast daemon is running, the forwarding of multicast traffic
+between the OLSR interface and the non-OLSR interface is done by
+the Linux kernel.
+
+The remaining text in this section has nothing to do with BMF or
+OLSR, but is added to give a number of helpful hints you might
+need when your multicast interworking, for some reason, is not working.
+
+When using the mrouted multicast daemon, there is a useful command,
+mrinfo, that gives information about what mrouted thinks of its
+neighbor hosts. For example:
+
+  root@node-4:/# mrinfo
+  127.0.0.1 (localhost.localdomain) [DVMRPv3 compliant]:
+    10.1.2.4 -> 10.1.2.2 (10.1.2.2) [1/1/querier]
+    10.0.6.4 -> 0.0.0.0 (local) [1/1/disabled]
+    10.255.255.253 -> 0.0.0.0 (local) [1/1/querier/leaf]
+
+In this example, the line starting with "10.1.2.4" is for the
+non-OLSR interface "eth0", on which mrouted has found an
+mrouted-neighbor host "10.1.2.2". The next line is for the OLSR
+interface "eth1", which is disabled for mrouted. The last line
+is for the BMF interface "bmf0". It is clear that mrouted sees no
+mrouted-neighbors on that interface (leaf).
+
+To see what multicast traffic has flown through the gateway, view
+the files /proc/net/ip_mr_vif and /proc/net/ip_mr_cache:
+
+  root@node-4:/# cat /proc/net/ip_mr_vif
+  Interface      BytesIn  PktsIn  BytesOut PktsOut Flags Local    Remote
+   0 eth0          27832      98     14200      50 00000 0402010A 00000000
+   2 bmf0          14484      51     13916      49 00000 FDFFFF0A 00000000
+  root@node-4:/# cat /proc/net/ip_mr_cache
+  Group    Origin   Iif     Pkts    Bytes    Wrong Oifs
+  4D4237EA C747010A 0         51    14484        0  2:1
+  4D4237EA C702010A 0         51    14484        0  2:1
+  4D4237EA C84C000A 2         53    15052        0  0:1
+
+From the above we can deduce that traffic from input interface 0
+(Iif 0, "eth0") is forwarded on output interface 2 (Oifs 2, = "bmf0"),
+and traffic from input interface 2 (Iif 2, "bmf0") is forwarded on
+output interface 0 (Oifs 0, "eth0"). The ":1" behind the Oifs numbers
+indicates the TTL thresholds, in this case packets with TTL value 1
+or less will not be forwarded.
+
+Note that when you are connecting an OLSR-BMF network to another multicast
+network (e.g. a DVMRP-mrouted network), you might be surprised that, when
+you ping the all-routers multicast address 224.0.0.1 from within the OLSR
+network, only the OLSR hosts respond. This is, however, compliant behaviour:
+packets with their destination IP address in the range 224.0.0.0 -
+224.0.0.255 are not routed by normal multicast protocols (i.e. their
+TTL is implicitly assumed to be 1). It doesn't mean that multicast is
+not working; if your application uses a multicast address outisde the
+range 224.0.0.0 - 224.0.0.255, it should work.
+
+
+9. 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 (BMF) plugin: error opening /dev/net/tun: No such file or directory
+
+Wat to do?
+
+Answer:
+Turn on the possibility to create a tuntap interface; see section 2 of this
+file.
+
+
+---------
+Question:
+When starting OLSRD with the BMF plugin, I can see the following
+error message:
+
+OLSRD Basic Multicast Forwarding (BMF) plugin: error opening /dev/net/tun: No such device
+
+Wat to do?
+
+Answer:
+First, turn on the possibility to create a tuntap interface; see section 2 of this
+file. Check if the device is there:
+ 
+  ~ # ls -l /dev/net/tun
+  crw-------    1 root     root      10, 200 Sep  9  2006 /dev/net/tun
+
+If the device is there, but the error message remains to appear, the
+tap/tun device is not compiled in your kernel. Try the command:
+
+  modprobe tun
+
+If "modprobe tun" says something like "modprobe: Can't locate module tun", then either
+it is not compiled at all or it is not compiled into the kernel. 
+
+Note: if you do not want to receive multicast packets, only forward the packets
+that other hosts send, then you do not need the tuntap interface. This could be the
+case if your host is purely an OLSR router; normally no traffic will be directed
+to the router itself. In that case you can ignore this error message. Beware, though,
+that you will then not be able to do the simple 'ping 224.0.0.1' test (as described in
+section 4. How to check if it works) to check for the presence of all OLSR-BMF routers
+in the network. 
+
+
+---------
+Question:
+I have enabled BMF, but my multicast application is not receiving any
+multicast packets.
+
+Answer:
+Many multicast applications must be configured to listen to a specific
+network interface. Make sure that your multicast application is listening on
+the BMF network interface, either by specifying the interface name itself
+(e.g. "bmf0") or by specifying its IP address.
+
+
+10. Version history
+-------------------
+
+24 February 2008: Version 1.5.3
+
+* Fixed a bug so that dying or dead end edges are not taken into account.
+  As of OLSRd version 0.5.4 , stale TC entries are not cleaned up, but
+  marked with a flag OLSR_TC_EDGE_DOWN. This flag was not taken into account
+  by BMF.
+
+7 December 2007: Version 1.5.2
+
+* Fixed a bug that would cause BMF to always send encapsulated broadcast
+  packets twice --> thanks to Frank Renwick and Joseph Giovatto for finding
+  this bug :-)
+* Added the plugin parameters "BroadcastRetransmitCount" and "FanOutLimit";
+  thanks to Frank and Joe for the idea.
+
+3 September 2007: Version 1.5.1
+
+* Fixed a bug that would cause BMF to crash (and OLSR with it) if a link
+  was timing out --> thanks to Frank Renwick
+* Fixed bug in the checking of the packet length --> thanks to Frank Renwick
+* Fixed a bug in shutdown, which cause a crash if the BMF thread was not
+  yet running --> thanks to Bernd Petrovitsch
+* Updated to OLSR plugin interface version 5.
+
+16 May 2007: Version 1.5
+
+* Improved packet history list to take into account the full 32 bits
+  of the packet fingerprint.
+  Previous versions derived a 16-bits value from the 32-bits packet
+  fingerprint and used that 16-bits value to determine packet unicity. In
+  situations with high packet rates (e.g. multicast video), this leads to
+  packets being incorrectly seen as duplicates of other, previously received
+  packets.
+
+* New encapsulation format. In previous versions, a complete Ethernet
+  frame was encapsulated. This is unnecessary, and not very clean; e.g.
+  from packets coming in on non-Ethernet media such as PPP, the data in
+  the Ethernet header is bogus.
+  The new encapsulation format encapsulates only the IP packet. An
+  outer IP header [1], UDP header [2] and BMF Encapsulation Header are
+  inserted before the datagram's existing IP header, as follows:
+
+                                       +---------------------------+
+                                       |                           |
+                                       |      Outer IP Header      |
+                                       +---------------------------+
+                                       |                           |
+                                       |        UDP Header         |
+                                       +---------------------------+
+                                       |      BMF Encapsulation    |
+                                       |           Header          |
+   +---------------------------+       +---------------------------+
+   |                           |       |                           |
+   |         IP Header         |       |         IP Header         |
+   +---------------------------+ ====> +---------------------------+
+   |                           |       |                           |
+   |         IP Payload        |       |         IP Payload        |
+   |                           |       |                           |
+   |                           |       |                           |
+   +---------------------------+       +---------------------------+
+
+  The BMF encapsulation header has a typical type-length-value (TLV)
+  format:
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Type      |    Length     |            Reserved           |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                       Packet fingerprint                      |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Type                1
+
+   Length              6.  Length in bytes of this extension, not
+                       including the Type and Length bytes.
+
+   Reserved            Reserved for future use. MUST be set to 0 on
+                       sending, MUST be verified as 0 on receipt;
+                       otherwise the extension must be handled as not
+                       understood and silently skipped.
+
+   Packet fingerprint  32-bits unique fingerprint inserted by the
+                       encapsulator. MAY be used by the receiver to
+                       determine duplicate packet reception.
+
+  The new encapsulation format is incompatible with those of previous
+  BMF versions, implying that all network nodes need to be updated.
+
+
+31 Mar 2007: Version 1.4
+* Optimized the standard forwarding mechanism in such a way that
+  retransmissions of packets are only done on those network interfaces
+  that make a host a multi-point relay (MPR) for the sender. I.e.:
+  retransmitting a packet on a network interface is not done if that
+  does not lead to any new hosts being reached.
+* Optimized the standard forwarding mechanism such that, if the network
+  topology indicates there is only one neighbor on an interface, packets are
+  sent to the specific IP address (unicast) of that neighbor. If the network
+  topology indicates there are multiple neighbors, then BMF will still send
+  packets to the IP local-broadcast address.
+* Introduced a new forwarding mechanism, using only IP-unicast to
+  forward packets. Packets are forwarded to the best candidate neighbor;
+  other neighbors listen promiscuously. IP-local broadcast is not used.
+  This saves air time on 802.11 WLAN networks, on which unicast packets are
+  usually sent at a much higher bit rate than broadcast packets (which are
+  sent at a basic bit rate).
+  This mechanism can be activated by specifying the following plugin
+  parameter:
+    PlParam "BmfMechanism" "UnicastPromiscuous"
+  See also section 6 - Advanced configuration.
+
+18 Dec 2006: Version 1.3
+* Added the possibility to configure the BMF network interface:
+  name (e.g. "bmf0"), type (tun or tap), IP address and subnet
+  mask.
+* Flooding of local broadcast packets (e.g. with destination
+  IP address 192.168.1.255) can now be turned off by configuration.
+* When an application sends packets to the BMF network interface, BMF
+  also floods these packets over the OLSR network.
+* Removed the TTL decrementing so that equipment connected to
+  a non-OLSR interface can still send their IGMP messages (TTL = 1)
+  to a fixed multicast router (running e.g. mrouted - DVMRP)
+  connected to a non-OLSR interface on another host in
+  the OLSR network. In this way, a whole OLSR network, including
+  its non-OLSR capable hosts, can be made multicast-routable
+  from a fixed multicast-enabled IP network.
+  For an example of such a configuration read section 8 above.
+* Removed the check for 'IsNullMacAddress' when creating a network
+  interface object. The check was not necessary and prevented
+  BMF to work on non-ethernet interfaces such as ppp.
+* Bug fix: in case there are multiple OLSR interfaces, when an
+  application sends packets to one OLSR interface, BMF did not
+  flood these packets via the other OLSR interfaces. This is
+  fixed. Also, packets sent to an OLSR interface are transmitted
+  on the non-OLSR interfaces.
+
+23 Oct 2006: Version 1.2
+* Packets to a local broadcast destination have their destination
+  IP address adapted to the subnet on which they are forwarded.
+  This makes it possible to use broadcast-based services (such as
+  NetBIOS) across different IP subnets.
+* The code to relate fragments with their main IP packet did not
+  work when the fragment arrived earlier than the main packet.
+  This would cause fragments of BMF-packets to be falsely forwarded.
+  For now, removed the forwarding of IP fragments. (Who's using
+  IP-fragments anyway?)
+* Packets are forwarded from one non-OLSR interface to the other
+  non-OLSR interfaces.
+* Various small optimizations and style improvements.
+
+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. To run the olsr daemon with
+  debug level 9, run "olsrd -d 9"; if you're only interested in
+  BMF debug messages, run "olsrd -d 9 | grep -i bmf".
+* 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.
+
+
+11. Normative References
+------------------------
+
+   [1]  Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981.
+
+   [2]  Postel, J., "User Datagram Protocol", STD 6, RFC 768, August
+        1980.
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Address.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Address.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Address.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Address.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,154 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+ 
+#include "Address.h"
+
+/* System includes */
+#include <stddef.h> /* NULL */
+#include <assert.h> /* assert() */
+#include <netinet/ip.h> /* struct ip */
+#include <netinet/udp.h> /* struct udphdr */
+
+/* OLSRD includes */
+#include "defs.h" /* ipequal */
+
+/* Plugin includes */
+#include "Bmf.h" /* BMF_ENCAP_PORT */
+#include "NetworkInterfaces.h" /* TBmfInterface */
+
+/* Whether or not to flood local broadcast packets (e.g. packets with IP
+ * destination 192.168.1.255). May be overruled by setting the plugin
+ * parameter "DoLocalBroadcast" to "no" */
+int EnableLocalBroadcast = 1;
+
+/* -------------------------------------------------------------------------
+ * Function   : DoLocalBroadcast
+ * Description: Overrule the default setting, enabling or disabling the
+ *              flooding of local broadcast packets
+ * Input      : enable - either "yes" or "no"
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int DoLocalBroadcast(
+  const char* enable,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (strcmp(enable, "yes") == 0)
+  {
+    EnableLocalBroadcast = 1;
+    return 0;
+  }
+  else if (strcmp(enable, "no") == 0)
+  {
+    EnableLocalBroadcast = 0;
+    return 0;
+  }
+
+  /* Value not recognized */
+  return 1;
+}
+
+/* -------------------------------------------------------------------------
+ * 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.s_addr) & 0xF0000000) == 0xE0000000;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : IsOlsrOrBmfPacket
+ * Description: Check if an IP packet is either an OLSR packet or a BMF packet
+ * Input      : ipPacket
+ * Output     : none
+ * Return     : true (1) or false (0)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int IsOlsrOrBmfPacket(unsigned char* ipPacket)
+{
+  struct ip* ipHeader;
+  unsigned int ipHeaderLen;
+  struct udphdr* udpHeader;
+  u_int16_t destPort;
+
+  assert(ipPacket != NULL);
+
+  /* OLSR packets are UDP - port 698
+   * OLSR-BMF packets are UDP - port 50698
+   * OLSR-Autodetect probe packets are UDP - port 51698 */
+
+  /* Check if UDP */
+  ipHeader = (struct ip*) ipPacket;
+  if (ipHeader->ip_p != SOL_UDP)
+  {
+    /* Not UDP */
+    return 0;
+  }
+
+  /* The total length must be at least large enough to store the UDP header */
+  ipHeaderLen = GetIpHeaderLength(ipPacket);
+  if (GetIpTotalLength(ipPacket) < ipHeaderLen + sizeof(struct udphdr))
+  {
+    /* Not long enough */
+    return 0;
+  }
+
+  /* Go into the UDP header and check port number */
+  udpHeader = (struct udphdr*) (ipPacket + ipHeaderLen);
+  destPort = ntohs(udpHeader->dest);
+
+  if (destPort == OLSRPORT || destPort == BMF_ENCAP_PORT || destPort == 51698)
+      /* TODO: #define for 51698 */
+  {
+    return 1;
+  }
+
+  return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Address.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Address.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Address.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Address.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,55 @@
+#ifndef _BMF_ADDRESS_H
+#define _BMF_ADDRESS_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+#include "olsr_types.h" /* olsr_ip_addr */
+#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */
+#include "interfaces.h" /* struct interface */
+
+struct TBmfInterface;
+
+extern int EnableLocalBroadcast;
+
+int DoLocalBroadcast(const char* enable, void* data, set_plugin_parameter_addon addon);
+int IsMulticast(union olsr_ip_addr* ipAddress);
+int IsOlsrOrBmfPacket(unsigned char* ipPacket);
+
+#endif /* _BMF_ADDRESS_H */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Bmf.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Bmf.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Bmf.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Bmf.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,1560 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+#define _MULTI_THREADED
+
+#include "Bmf.h"
+
+/* System includes */
+#include <stddef.h> /* NULL */
+#include <sys/types.h> /* ssize_t */
+#include <string.h> /* strerror() */
+#include <stdarg.h> /* va_list, va_start, va_end */
+#include <errno.h> /* errno */
+#include <assert.h> /* assert() */
+#include <linux/if_ether.h> /* ETH_P_IP */
+#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 */
+#include <netinet/udp.h> /* struct udphdr */
+
+/* OLSRD includes */
+#include "plugin_util.h" /* set_plugin_int */
+#include "defs.h" /* olsr_cnf, OLSR_PRINTF */
+#include "ipcalc.h"
+#include "olsr.h" /* olsr_printf */
+#include "scheduler.h" /* olsr_start_timer() */
+#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() */
+#include "net_olsr.h" /* ipequal */
+
+/* BMF includes */
+#include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
+#include "Address.h" /* IsMulticast() */
+#include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
+#include "PacketHistory.h" /* InitPacketHistory() */
+
+static pthread_t BmfThread;
+static int BmfThreadRunning = 0;
+
+/* unicast/broadcast fan out limit */
+int FanOutLimit = 2;
+
+int BroadcastRetransmitCount = 1;
+
+/* -------------------------------------------------------------------------
+ * Function   : BmfPError
+ * Description: Prints an error message at OLSR debug level 1.
+ *              First the plug-in name is printed. Then (if format is not NULL
+ *              and *format is not empty) the arguments are printed, followed
+ *              by a colon and a blank. Then the message and a new-line.
+ * Input      : format, arguments
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+void BmfPError(const char* format, ...)
+{
+#define MAX_STR_DESC 255
+  char* strErr = strerror(errno);
+  char strDesc[MAX_STR_DESC];
+
+  /* Rely on short-circuit boolean evaluation */
+  if (format == NULL || *format == '\0')
+  {
+    olsr_printf(1, "%s: %s\n", PLUGIN_NAME, strErr);
+  }
+  else
+  {
+    va_list arglist;
+
+    olsr_printf(1, "%s: ", PLUGIN_NAME);
+
+    va_start(arglist, format);
+    vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
+    va_end(arglist);
+
+    strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
+
+    olsr_printf(1, "%s: %s\n", strDesc, strErr);
+  }
+} /* BmfPError */
+
+/* -------------------------------------------------------------------------
+ * Function   : MainAddressOf
+ * Description: Lookup the main address of a node
+ * Input      : ip - IP address of the node
+ * Output     : none
+ * Return     : The main IP address of the node
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
+{
+  union olsr_ip_addr* result;
+
+  /* TODO: mid_lookup_main_addr() is not thread-safe! */
+  result = mid_lookup_main_addr(ip);
+  if (result == NULL)
+  {
+    result = ip;
+  }
+  return result;
+} /* MainAddressOf */
+
+/* -------------------------------------------------------------------------
+ * Function   : EncapsulateAndForwardPacket
+ * Description: Encapsulate a captured raw IP packet and forward it
+ * Input      : intf - the network interface on which to forward the packet
+ *              encapsulationUdpData - The encapsulation header, followed by
+ *                the encapsulated IP packet
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+static void EncapsulateAndForwardPacket(
+  struct TBmfInterface* intf,
+  unsigned char* encapsulationUdpData)
+{
+  /* The packet */
+  u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
+
+  /* The next destination(s) */
+  struct TBestNeighbors bestNeighborLinks;
+  struct link_entry* bestNeighbor;
+
+  int nPossibleNeighbors = 0;
+  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
+  int nPacketsToSend;
+  int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
+
+  int i;
+
+  /* Find at most 'FanOutLimit' best neigbors to forward the packet to */
+  FindNeighbors(&bestNeighborLinks, &bestNeighbor, intf, NULL, NULL, NULL, &nPossibleNeighbors);
+
+  if (nPossibleNeighbors <= 0)
+  {
+    OLSR_PRINTF(
+      8,
+      "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
+      PLUGIN_NAME_SHORT,
+      intf->ifName);
+    return;
+  }
+
+  /* Compose destination of encapsulation packet */
+
+  memset(&forwardTo, 0, sizeof(forwardTo));
+  forwardTo.sin_family = AF_INET;
+  forwardTo.sin_port = htons(BMF_ENCAP_PORT);
+
+  /* Start by filling in the local broadcast address. This may be overwritten later. */
+  forwardTo.sin_addr = intf->broadAddr.v4;
+
+  /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
+   *   unicast packet (to the best neighbor).
+   * - But if the BMF mechanism is BM_BROADCAST,
+   *   - send 'nPossibleNeighbors' unicast packets if there are up to
+   *     'FanOutLimit' possible neighbors,
+   *   - if there are more than 'FanOutLimit' possible neighbors, then
+   *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
+  if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
+  {
+    /* One unicast packet to the best neighbor */
+    nPacketsToSend = 1;
+    sendUnicast = 1;
+    bestNeighborLinks.links[0] = bestNeighbor;
+  }
+  else /* BmfMechanism == BM_BROADCAST */
+  {
+    if (nPossibleNeighbors <= FanOutLimit)
+    {
+      /* 'nPossibleNeighbors' unicast packets */
+      nPacketsToSend = nPossibleNeighbors;
+      sendUnicast = 1;
+    }
+    else /* nPossibleNeighbors > FanOutLimit */
+    {
+      /* One broadcast packet, possibly retransmitted as specified in the
+       * 'BroadcastRetransmitCount' plugin parameter */
+      nPacketsToSend = BroadcastRetransmitCount;
+      sendUnicast = 0;
+    } /* if */
+  } /* if */
+
+  for (i = 0; i < nPacketsToSend; i++)
+  {
+    int nBytesWritten;
+
+    if (sendUnicast == 1)
+    {
+      /* For unicast, overwrite the local broadcast address which was filled in above */
+      forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
+    }
+
+    /* Forward the BMF packet via the encapsulation socket */
+    nBytesWritten = sendto(
+      intf->encapsulatingSkfd,
+      encapsulationUdpData,
+      udpDataLen,
+      MSG_DONTROUTE,
+      (struct sockaddr*) &forwardTo,
+      sizeof(forwardTo));                   
+
+    /* Evaluate and display result */
+    if (nBytesWritten != udpDataLen)
+    {
+      BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
+    }
+    else
+    {
+      /* Increase counter */
+      intf->nBmfPacketsTx++;
+
+      OLSR_PRINTF(
+        8,
+        "%s: --> encapsulated and forwarded on \"%s\" to %s\n",
+        PLUGIN_NAME_SHORT,
+        intf->ifName,
+        inet_ntoa(forwardTo.sin_addr));
+    } /* if (nBytesWritten != udpDataLen) */
+  } /* for */
+} /* EncapsulateAndForwardPacket */
+
+/* -------------------------------------------------------------------------
+ * Function   : BmfPacketCaptured
+ * Description: Handle a captured IP packet
+ * Input      : intf - the network interface on which the packet was captured
+ *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
+ *                PACKET_BROADCAST or PACKET_MULTICAST.
+ *              encapsulationUdpData - space for the encapsulation header, followed by
+ *                the captured IP packet
+ * Output     : none
+ * Return     : none
+ * Data Used  : BmfInterfaces
+ * Notes      : The IP packet is assumed to be captured on a socket of family
+ *              PF_PACKET and type SOCK_DGRAM (cooked).
+ * ------------------------------------------------------------------------- */
+static void BmfPacketCaptured(
+  struct TBmfInterface* intf,
+  unsigned char sllPkttype,
+  unsigned char* encapsulationUdpData)
+{
+  union olsr_ip_addr src; /* Source IP address in captured packet */
+  union olsr_ip_addr dst; /* Destination IP address in captured packet */
+  union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
+  struct TBmfInterface* walker;
+  int isFromOlsrIntf;
+  int isFromOlsrNeighbor;
+  int iAmMpr;
+  unsigned char* ipPacket; /* The captured IP packet... */
+  u_int16_t ipPacketLen; /* ...and its length */
+  struct ip* ipHeader; /* The IP header inside the captured IP packet */
+  u_int32_t crc32;
+  struct TEncapHeader* encapHdr;
+  struct ipaddr_str srcBuf, dstBuf;
+  ipHeader = GetIpHeader(encapsulationUdpData);
+
+  dst.v4 = ipHeader->ip_dst;
+
+  /* Only forward multicast packets. If configured, also forward local broadcast packets */
+  if (IsMulticast(&dst) ||
+      (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr)))
+  {
+    /* continue */
+  }
+  else
+  {
+    return;
+  }
+
+  ipPacket = GetIpPacket(encapsulationUdpData);
+
+  /* Don't forward fragments of IP packets: there is no way to distinguish fragments
+   * of BMF encapsulation packets from other fragments.
+   * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment
+   * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier
+   * than the first fragment, so that the list is not yet up to date and the second
+   * fragment is not recognized as a BMF packet.
+   * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */
+  if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
+  {
+    return;
+  }
+
+  /* Increase counter */
+  intf->nBmfPacketsRx++;
+
+  /* Check if the frame is captured on an OLSR-enabled interface */
+  isFromOlsrIntf = (intf->olsrIntf != NULL);
+
+  /* Retrieve the length of the captured packet */
+  ipPacketLen = GetIpTotalLength(ipPacket);
+
+  src.v4 = ipHeader->ip_src;
+
+  OLSR_PRINTF(
+    8,
+    "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
+    PLUGIN_NAME_SHORT,
+    sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
+    (long)ipPacketLen,
+    isFromOlsrIntf ? "OLSR" : "non-OLSR",
+    intf->ifName,
+    olsr_ip_to_string(&srcBuf, &src),
+    olsr_ip_to_string(&dstBuf, &dst));
+
+  /* Lookup main address of source in the MID table of OLSR */
+  origIp = MainAddressOf(&src);
+
+  /* Calculate packet fingerprint */
+  crc32 = PacketCrc32(ipPacket, ipPacketLen);
+
+  /* Check if this packet was seen recently */
+  if (CheckAndMarkRecentPacket(crc32))
+  {
+    /* Increase counter */
+    intf->nBmfPacketsRxDup++;
+
+    OLSR_PRINTF(
+      8,
+      "%s: --> discarding: packet is duplicate\n",
+      PLUGIN_NAME_SHORT);
+    return;
+  }
+
+  /* Compose encapsulation header */
+  encapHdr = (struct TEncapHeader*) encapsulationUdpData;
+  memset (encapHdr, 0, ENCAP_HDR_LEN);
+  encapHdr->type = BMF_ENCAP_TYPE;
+  encapHdr->len = BMF_ENCAP_LEN;
+  encapHdr->reserved = 0;
+  encapHdr->crc32 = htonl(crc32);
+
+  /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
+   * TODO1: get_best_link_to_neighbor() is not thread-safe.
+   * TODO2: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
+   * would do here (something like 'get_any_link_to_neighbor()'). */
+  isFromOlsrNeighbor =
+    (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
+    && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ 
+
+  /* Check with OLSR if I am MPR for that neighbor */
+  /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
+  iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
+
+  /* Check with each network interface what needs to be done on it */
+  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
+  {
+    /* Is the forwarding interface OLSR-enabled? */
+    int isToOlsrIntf = (walker->olsrIntf != NULL);
+
+    /* Depending on certain conditions, we decide whether or not to forward
+     * the packet, and if it is forwarded, in which form (encapsulated
+     * or not, TTL decreased or not). These conditions are:
+     * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
+     * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
+     * - if the packet if coming in on an OLSR interface:
+     *   - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
+     *   - has the node that forwarded the packet selected me as MPR? (iAmMpr)
+     *
+     * Based on these conditions, the following cases can be distinguished:
+     *
+     * - Case 1: Packet coming in on an OLSR interface. What to
+     *   do with it on an OLSR interface?
+     *   Answer:
+     *   - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
+     *     selected me as MPR: don't forward the packet.
+     *   - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
+     *     me as MPR: encapsulate and forward the packet.
+     *   - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
+     *     and forward the packet.
+     *     NOTE: Case 1.3 is a special case. In the perfect world, we expect to
+     *     see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
+     *     ignorant users will connect a host not running OLSR, to a LAN in
+     *     which there are hosts running OLSR. Of course these ignorant users,
+     *     expecting magic, want to see their multicast packets being forwarded
+     *     through the network.
+     *
+     * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
+     *   non-OLSR interface?
+     *   Answer: Forward it.
+     *
+     * - Case 3: Packet coming in on a non-OLSR interface. What to
+     *   do with it on an OLSR interface?
+     *   Answer: Encapsulate and forward it.
+     *
+     * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
+     *   non-OLSR interface?
+     *   Answer 1: nothing. Multicast routing between non-OLSR interfaces
+     *   is to be done by other protocols (e.g. PIM, DVMRP).
+     *   Answer 2 (better): Forward it.
+     */
+
+    if (isFromOlsrIntf && isToOlsrIntf)
+    {
+      /* Case 1: Forward from an OLSR interface to an OLSR interface */
+
+      if (isFromOlsrNeighbor && !iAmMpr)
+      {
+        /* Case 1.1 */
+        {
+          struct ipaddr_str buf;
+          OLSR_PRINTF(
+            8,
+            "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
+            PLUGIN_NAME_SHORT,
+            walker->ifName,
+            olsr_ip_to_string(&buf, &src));
+        }    
+      }
+      else if (sllPkttype == PACKET_OUTGOING && intf == walker)
+      {
+        OLSR_PRINTF(
+          8,
+          "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n",
+          PLUGIN_NAME_SHORT,
+          walker->ifName);
+      }
+      else
+      {
+        /* Case 1.2 and 1.3 */
+        EncapsulateAndForwardPacket(walker, encapsulationUdpData);
+      }
+    } /* if (isFromOlsrIntf && isToOlsrIntf) */
+
+    else if (isFromOlsrIntf && !isToOlsrIntf)
+    {
+      /* Case 2: Forward from OLSR interface to non-OLSR interface */
+
+      int nBytesWritten;
+      struct sockaddr_ll dest;
+
+      /* If the encapsulated IP packet is a local broadcast packet,
+       * update its destination address to match the subnet of the network
+       * interface on which the packet is being sent. */
+      CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      dest.sll_protocol = htons(ETH_P_IP);
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+
+      nBytesWritten = sendto(
+        walker->capturingSkfd,
+        ipPacket,
+        ipPacketLen,
+        0,
+        (struct sockaddr*) &dest,
+        sizeof(dest));
+      if (nBytesWritten != ipPacketLen)
+      {
+        BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
+      }
+      else
+      {
+        /* Increase counter */
+        walker->nBmfPacketsTx++;
+
+        OLSR_PRINTF(8, "%s: --> forwarded on \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName);
+      }
+    } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
+
+    else if (!isFromOlsrIntf && isToOlsrIntf)
+    {
+      /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
+       * Encapsulate and forward packet. */
+
+      EncapsulateAndForwardPacket(walker, encapsulationUdpData);
+    } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
+
+    else
+    {
+      /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */
+
+      /* Don't forward on interface on which packet was received */
+      if (intf == walker)
+      {
+        OLSR_PRINTF(
+          8,
+          "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n",
+          PLUGIN_NAME_SHORT,
+          walker->ifName);
+      }
+
+      else
+      {
+        int nBytesWritten;
+        struct sockaddr_ll dest;
+
+        /* If the encapsulated IP packet is a local broadcast packet,
+         * update its destination address to match the subnet of the network
+         * interface on which the packet is being sent. */
+        CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+        memset(&dest, 0, sizeof(dest));
+        dest.sll_family = AF_PACKET;
+        dest.sll_protocol = htons(ETH_P_IP);
+        dest.sll_ifindex = if_nametoindex(walker->ifName);
+        dest.sll_halen = IFHWADDRLEN;
+
+        /* Use all-ones as destination MAC address. When the IP destination is
+         * a multicast address, the destination MAC address should normally also
+         * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+         * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+         * seem to matter when the destination MAC address is set to all-ones
+         * in that case. */
+        memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+
+        nBytesWritten = sendto(
+          walker->capturingSkfd,
+          ipPacket,
+          ipPacketLen,
+          0,
+          (struct sockaddr*) &dest,
+          sizeof(dest));
+        if (nBytesWritten != ipPacketLen)
+        {
+          BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
+        }
+        else
+        {
+          /* Increase counter */
+          walker->nBmfPacketsTx++;
+
+          OLSR_PRINTF(
+            8,
+            "%s: --> forwarded from non-OLSR on non-OLSR \"%s\"\n",
+            PLUGIN_NAME_SHORT,
+            walker->ifName);
+        }
+      } /* if (intf == walker) */
+    } /* if */
+  } /* for */
+} /* BmfPacketCaptured */
+
+/* -------------------------------------------------------------------------
+ * Function   : BmfEncapsulationPacketReceived
+ * Description: Handle a received BMF-encapsulation packet
+ * Input      : intf - the network interface on which the packet was received
+ *              forwardedBy - the IP node that forwarded the packet to me
+ *              forwardedTo - the destination IP address of the encapsulation
+ *                packet, in case the packet was received promiscuously.
+ *                Pass NULL if the packet is received normally (unicast or
+ *                broadcast).
+ *              encapsulationUdpData - the encapsulating IP UDP data, containting
+ *                the BMF encapsulation header, followed by the encapsulated
+ *                IP packet
+ * Output     : none
+ * Return     : none
+ * Data Used  : BmfInterfaces
+ * ------------------------------------------------------------------------- */
+static void BmfEncapsulationPacketReceived(
+  struct TBmfInterface* intf,
+  union olsr_ip_addr* forwardedBy,
+  union olsr_ip_addr* forwardedTo,
+  unsigned char* encapsulationUdpData)
+{
+  int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
+  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
+  unsigned char* ipPacket; /* The encapsulated IP packet */
+  u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
+  struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
+  union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
+  union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
+  struct TEncapHeader* encapsulationHdr;
+  u_int16_t encapsulationUdpDataLen;
+  struct TBmfInterface* walker;
+  struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
+  /* Are we talking to ourselves? */
+  if (if_ifwithaddr(forwardedBy) != NULL)
+  {
+    return;
+  }
+
+  /* Discard encapsulated packets received on a non-OLSR interface */
+  if (intf->olsrIntf == NULL)
+  {
+    return;
+  }
+
+  /* Retrieve details about the encapsulated IP packet */
+  ipPacket = GetIpPacket(encapsulationUdpData);
+  ipPacketLen = GetIpTotalLength(ipPacket);
+  ipHeader = GetIpHeader(encapsulationUdpData);
+
+  mcSrc.v4 = ipHeader->ip_src;
+  mcDst.v4 = ipHeader->ip_dst;
+
+  /* Increase counter */
+  intf->nBmfPacketsRx++;
+
+  /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
+  OLSR_PRINTF(
+    8,
+    "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
+    PLUGIN_NAME_SHORT,
+    (long)ipPacketLen,
+    intf->ifName,
+    olsr_ip_to_string(&mcSrcBuf, &mcSrc),
+    olsr_ip_to_string(&mcDstBuf, &mcDst),
+    olsr_ip_to_string(&forwardedByBuf, forwardedBy),
+    forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");
+
+  /* Get encapsulation header */
+  encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
+
+  /* Verify correct format of BMF encapsulation header */
+  if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
+      encapsulationHdr->len != BMF_ENCAP_LEN ||
+      ntohs(encapsulationHdr->reserved != 0))
+  {
+    OLSR_PRINTF(
+      8,
+      "%s: --> discarding: format of BMF encapsulation header not recognized\n",
+      PLUGIN_NAME_SHORT);
+    return;
+  }
+
+  /* Check if this packet was seen recently */
+  if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
+  {
+    /* Increase counter */
+    intf->nBmfPacketsRxDup++;
+
+    OLSR_PRINTF(
+      8,
+      "%s: --> discarding: packet is duplicate\n",
+      PLUGIN_NAME_SHORT);
+    return;
+  }
+
+  if (EtherTunTapFd >= 0)
+  {
+    /* Unpack the encapsulated IP packet and deliver it locally, by sending
+     * a copy into the local IP stack via the EtherTunTap interface */
+
+    union olsr_ip_addr broadAddr;
+    int nBytesToWrite, nBytesWritten;
+    unsigned char* bufferToWrite;
+
+    /* If the encapsulated IP packet is a local broadcast packet,
+     * update its destination address to match the subnet of the EtherTunTap
+     * interface */
+    broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
+    CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
+
+    bufferToWrite = ipPacket;
+    nBytesToWrite = ipPacketLen;
+
+    /* Write the packet into the EtherTunTap interface for local delivery */
+    nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
+    if (nBytesWritten != nBytesToWrite)
+    {
+      BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
+    }
+    else
+    {
+      OLSR_PRINTF(
+        8,
+        "%s: --> unpacked and delivered locally on \"%s\"\n",
+        PLUGIN_NAME_SHORT,
+        EtherTunTapIfName);
+    }
+  } /* if (EtherTunTapFd >= 0) */
+
+  /* Check if I am MPR for the forwarder */
+  /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
+  iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
+
+  /* Compose destination address for next hop */
+  memset(&forwardTo, 0, sizeof(forwardTo));
+  forwardTo.sin_family = AF_INET;
+  forwardTo.sin_port = htons(BMF_ENCAP_PORT);
+
+  /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
+  encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
+
+  /* Check with each network interface what needs to be done on it */
+  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
+  {
+    /* What to do with the packet on a non-OLSR interface? Unpack
+     * encapsulated packet, and forward it.
+     *
+     * What to do with the packet on an OLSR interface? Forward it only
+     * if the forwarding node has selected us as MPR (iAmMpr).
+     *
+     * Note that the packet is always coming in on an OLSR interface, because
+     * it is an encapsulated BMF packet. */
+
+    /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
+    if (walker->olsrIntf == NULL)
+    {
+      int nBytesWritten;
+      struct sockaddr_ll dest;
+
+      /* If the encapsulated IP packet is a local broadcast packet,
+       * update its destination address to match the subnet of the network
+       * interface on which the packet is being sent. */
+      CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      dest.sll_protocol = htons(ETH_P_IP);
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+
+      nBytesWritten = sendto(
+        walker->capturingSkfd,
+        ipPacket,
+        ipPacketLen,
+        0,
+        (struct sockaddr*) &dest,
+        sizeof(dest));
+      if (nBytesWritten != ipPacketLen)
+      {
+        BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
+      }
+      else
+      {
+        /* Increase counter */
+        walker->nBmfPacketsTx++;
+
+        OLSR_PRINTF(
+          8,
+          "%s: --> unpacked and forwarded on \"%s\"\n",
+          PLUGIN_NAME_SHORT,
+          walker->ifName);
+      }
+    } /* if (walker->olsrIntf == NULL) */
+
+    /* To an OLSR interface: forward the packet, but only if this node is
+     * selected as MPR by the forwarding node */
+    else if (iAmMpr)
+    {
+      struct TBestNeighbors bestNeighborLinks;
+      struct link_entry* bestNeighbor;
+      int nPossibleNeighbors;
+      int nPacketsToSend;
+      int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
+      int i;
+
+      /* Retrieve at most two best neigbors to forward the packet to */
+      FindNeighbors(
+        &bestNeighborLinks,
+        &bestNeighbor,
+        walker,
+        &mcSrc,
+        forwardedBy,
+        forwardedTo,
+        &nPossibleNeighbors);
+
+      if (nPossibleNeighbors <= 0)
+      {
+        OLSR_PRINTF(
+          8,
+          "%s: --> not forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
+          PLUGIN_NAME_SHORT,
+          walker->ifName);
+
+        continue; /* for */
+      }
+
+      /* Compose destination of encapsulation packet.
+       * Start by filling in the local broadcast address. This may be overwritten later. */
+      forwardTo.sin_addr = walker->broadAddr.v4;
+
+      /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
+       *   unicast packet (to the best neighbor).
+       * - But if the BMF mechanism is BM_BROADCAST,
+       *   - send 'nPossibleNeighbors' unicast packets if there are up to
+       *     'FanOutLimit' possible neighbors,
+       *   - if there are more than 'FanOutLimit' possible neighbors, then
+       *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
+      if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
+      {
+        /* One unicast packet to the best neighbor */
+        nPacketsToSend = 1;
+        sendUnicast = 1;
+        bestNeighborLinks.links[0] = bestNeighbor;
+      }
+      else /* BmfMechanism == BM_BROADCAST */
+      {
+        if (nPossibleNeighbors <= FanOutLimit)
+        {
+          /* 'nPossibleNeighbors' unicast packets */
+          nPacketsToSend = nPossibleNeighbors;
+          sendUnicast = 1;
+        }
+        else /* nPossibleNeighbors > FanOutLimit */
+        {
+          /* One broadcast packet, possibly retransmitted as specified in the
+           * 'BroadcastRetransmitCount' plugin parameter */
+          nPacketsToSend = BroadcastRetransmitCount;
+          sendUnicast = 0;
+        } /* if */
+      } /* if */
+
+      for (i = 0; i < nPacketsToSend; i++)
+      {
+        int nBytesWritten;
+
+        if (sendUnicast)
+        {    
+          /* For unicast, overwrite the local broadcast address which was filled in above */
+          forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
+        }
+
+        /* Forward the BMF packet via the encapsulation socket */
+        nBytesWritten = sendto(
+          walker->encapsulatingSkfd,
+          encapsulationUdpData,
+          encapsulationUdpDataLen,
+          MSG_DONTROUTE,
+          (struct sockaddr*) &forwardTo,
+          sizeof(forwardTo));                   
+
+        /* Evaluate and display result */
+        if (nBytesWritten != encapsulationUdpDataLen)
+        {
+          BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName);
+        }
+        else
+        {
+          /* Increase counter */
+          walker->nBmfPacketsTx++;
+
+          OLSR_PRINTF(
+            8,
+            "%s: --> forwarded on \"%s\" to %s\n",
+            PLUGIN_NAME_SHORT,
+            walker->ifName,
+            inet_ntoa(forwardTo.sin_addr));
+        } /* if */
+      } /* for */
+    }  /* else if (iAmMpr) */
+
+    else /* walker->olsrIntf != NULL && !iAmMpr */
+    {
+      struct ipaddr_str buf;
+      /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
+       * case, don't forward. */
+      OLSR_PRINTF(
+        8,
+        "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
+        PLUGIN_NAME_SHORT,
+        walker->ifName,
+        olsr_ip_to_string(&buf, forwardedBy));
+    } /* else */
+  } /* for */
+} /* BmfEncapsulationPacketReceived */
+
+/* -------------------------------------------------------------------------
+ * Function   : BmfTunPacketCaptured
+ * Description: Handle an IP packet, captured outgoing on the tuntap interface
+ * Input      : encapsulationUdpData - space for the encapsulation header, followed by
+ *                the captured outgoing IP packet
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : The packet is assumed to be captured on a socket of family
+ *              PF_PACKET and type SOCK_DGRAM (cooked).
+ * ------------------------------------------------------------------------- */
+static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
+{
+  union olsr_ip_addr srcIp;
+  union olsr_ip_addr dstIp;
+  union olsr_ip_addr broadAddr;
+  struct TBmfInterface* walker;
+  unsigned char* ipPacket;
+  u_int16_t ipPacketLen;
+  struct ip* ipHeader;
+  u_int32_t crc32;
+  struct TEncapHeader* encapHdr;
+  struct ipaddr_str srcIpBuf, dstIpBuf;
+  ipPacket = GetIpPacket(encapsulationUdpData);
+  ipPacketLen = GetIpTotalLength(ipPacket);
+  ipHeader = GetIpHeader(encapsulationUdpData);
+
+  dstIp.v4 = ipHeader->ip_dst;
+  broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
+
+  /* Only forward multicast packets. If configured, also forward local broadcast packets */
+  if (IsMulticast(&dstIp) ||
+      (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr)))
+  {
+    /* continue */
+  }
+  else
+  {
+    return;
+  }
+
+  srcIp.v4 = ipHeader->ip_src;
+
+  OLSR_PRINTF(
+    8,
+    "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
+    PLUGIN_NAME_SHORT,
+    (long)ipPacketLen,
+    EtherTunTapIfName,
+    olsr_ip_to_string(&srcIpBuf, &srcIp),
+    olsr_ip_to_string(&dstIpBuf, &dstIp));
+
+  /* Calculate packet fingerprint */
+  crc32 = PacketCrc32(ipPacket, ipPacketLen);
+
+  /* Check if this packet was seen recently */
+  if (CheckAndMarkRecentPacket(crc32))
+  {
+    OLSR_PRINTF(
+      8,
+      "%s: --> discarding: packet is duplicate\n",
+      PLUGIN_NAME_SHORT);
+    return;
+  }
+
+  /* Compose encapsulation header */
+  encapHdr = (struct TEncapHeader*) encapsulationUdpData;
+  memset (encapHdr, 0, ENCAP_HDR_LEN);
+  encapHdr->type = BMF_ENCAP_TYPE;
+  encapHdr->len = BMF_ENCAP_LEN;
+  encapHdr->reserved = 0;
+  encapHdr->crc32 = htonl(crc32);
+
+  /* Check with each network interface what needs to be done on it */
+  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
+  {
+    /* Is the forwarding interface OLSR-enabled? */
+    if (walker->olsrIntf != NULL)
+    {
+      /* On an OLSR interface: encapsulate and forward packet. */
+
+      EncapsulateAndForwardPacket(walker, encapsulationUdpData);
+    }
+    else
+    {
+      /* On a non-OLSR interface: what to do?
+       * Answer 1: nothing. Multicast routing between non-OLSR interfaces
+       * is to be done by other protocols (e.g. PIM, DVMRP).
+       * Answer 2 (better): Forward it. */
+
+      int nBytesWritten;
+      struct sockaddr_ll dest;
+
+      /* If the encapsulated IP packet is a local broadcast packet,
+       * update its destination address to match the subnet of the network
+       * interface on which the packet is being sent. */
+      CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
+
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      dest.sll_protocol = htons(ETH_P_IP);
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+
+      nBytesWritten = sendto(
+        walker->capturingSkfd,
+        ipPacket,
+        ipPacketLen,
+        0,
+        (struct sockaddr*) &dest,
+        sizeof(dest));
+      if (nBytesWritten != ipPacketLen)
+      {
+        BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
+      }
+      else
+      {
+        /* Increase counter */
+        walker->nBmfPacketsTx++;
+
+        OLSR_PRINTF(
+          8,
+          "%s: --> forwarded from non-OLSR to non-OLSR \"%s\"\n",
+          PLUGIN_NAME_SHORT,
+          walker->ifName);
+      } /* if */
+    } /* if */
+  } /* for */
+} /* BmfTunPacketCaptured */
+
+/* -------------------------------------------------------------------------
+ * 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)
+{
+  int nFdBitsSet;
+  unsigned char rxBuffer[BMF_BUFFER_SIZE];
+  fd_set rxFdSet;
+
+  assert(HighestSkfd >= 0);
+
+  /* Make a local copy of the set of file descriptors that select() can
+   * modify to indicate which descriptors actually changed status */
+  rxFdSet = InputSet;
+
+  /* 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, &rxFdSet, NULL, NULL, NULL);
+  if (nFdBitsSet < 0)
+  {
+    if (errno != EINTR)
+    {
+      BmfPError("select() error");
+    }
+    return;
+  }
+
+  while (nFdBitsSet > 0)
+  {
+    struct TBmfInterface* walker;
+
+    /* Check if a packet was received on the capturing socket (if any)
+     * of each network interface */
+    for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
+    {
+      int skfd = walker->capturingSkfd;
+      if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
+      {
+        struct sockaddr_ll pktAddr;
+        socklen_t addrLen = sizeof(pktAddr);
+        int nBytes;
+        unsigned char* ipPacket;
+
+        /* A packet was captured. */
+
+        nFdBitsSet--;
+
+        /* Receive the captured Ethernet frame, leaving space for the BMF
+         * encapsulation header */
+        ipPacket = GetIpPacket(rxBuffer);
+        nBytes = recvfrom(
+          skfd,
+          ipPacket,
+          BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
+          0,
+          (struct sockaddr*)&pktAddr,
+          &addrLen);
+        if (nBytes < 0)
+        {
+          BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+
+          continue; /* for */
+        } /* if (nBytes < 0) */
+
+        /* Check if the number of received bytes is large enough for an IP
+         * packet which contains at least a minimum-size IP header.
+         * Note: There is an apparent bug in the packet socket implementation in
+         * combination with VLAN interfaces. On a VLAN interface, the value returned
+         * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
+         * returned on a non-VLAN interface, for the same ethernet frame. */
+        if (nBytes < (int)sizeof(struct ip))
+        {
+          olsr_printf(
+            1,
+            "%s: captured frame too short (%d bytes) on \"%s\"\n",
+            PLUGIN_NAME,
+            nBytes,
+            walker->ifName);
+
+          continue; /* for */
+        }
+
+        if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
+            pktAddr.sll_pkttype == PACKET_MULTICAST ||
+            pktAddr.sll_pkttype == PACKET_BROADCAST)
+        {
+          /* A multicast or broadcast packet was captured */
+
+          BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
+
+        } /* if (pktAddr.sll_pkttype == ...) */
+      } /* if (skfd >= 0 && (FD_ISSET...)) */
+    } /* for */
+    
+    /* Check if a BMF encapsulation packet was received on the listening
+     * socket (if any) of each network interface */
+    for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
+    {
+      int skfd = walker->listeningSkfd;
+      if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
+      {
+        struct sockaddr_ll pktAddr;
+        socklen_t addrLen = sizeof(pktAddr);
+        int nBytes;
+        int minimumLength;
+        struct ip* ipHeader;
+        struct udphdr* udpHeader;
+        u_int16_t destPort;
+        union olsr_ip_addr forwardedBy;
+        union olsr_ip_addr forwardedTo;
+
+        /* Heard a BMF packet */
+
+        nFdBitsSet--;
+
+        nBytes = recvfrom(
+          skfd,
+          rxBuffer,
+          BMF_BUFFER_SIZE,
+          0,
+          (struct sockaddr*)&pktAddr,
+          &addrLen);
+        if (nBytes < 0)
+        {
+          BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+
+          continue; /* for */
+        } /* if (nBytes < 0) */
+
+        /* Check if the received packet is actually directed to another
+         * node on the LAN */
+        if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
+        {
+          /* No, the packet is directed to this node. In that case it will
+           * be, or will already have been received, via the encapsulating
+           * socket. Discard it here. */
+          continue; /* for */
+        } /* if (pktAddr.sll_pkttype ...) */
+
+        /* Check if the received packet is UDP - BMF port */
+        ipHeader = (struct ip*)rxBuffer;
+        if (ipHeader->ip_p != SOL_UDP)
+        {
+          /* Not UDP */
+          continue; /* for */
+        }
+
+        udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
+        destPort = ntohs(udpHeader->dest);
+        if (destPort != BMF_ENCAP_PORT)
+        {
+          /* Not BMF */
+          continue; /* for */
+        }
+
+        /* Check if the number of received bytes is large enough for a minimal BMF
+         * encapsulation packet, at least:
+         * - the IP header of the encapsulation IP packet
+         * - the UDP header of the encapsulation IP packet
+         * - the encapsulation header
+         * - a minimum IP header inside the encapsulated packet
+         * Note: on a VLAN interface, the value returned by 'recvfrom' may (but need
+         * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
+         * the same ethernet frame. */
+        minimumLength =
+          GetIpHeaderLength(rxBuffer) +
+          sizeof(struct udphdr) +
+          ENCAP_HDR_LEN +
+          sizeof(struct ip);
+        if (nBytes < minimumLength)
+        {
+          olsr_printf(
+            1,
+            "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
+            PLUGIN_NAME,
+            nBytes,
+            walker->ifName);
+
+          continue; /* for */
+        }
+
+        forwardedBy.v4 = ipHeader->ip_src;
+        forwardedTo.v4 = ipHeader->ip_dst;
+        BmfEncapsulationPacketReceived(
+          walker,
+          &forwardedBy,
+          &forwardedTo,
+          rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
+
+      } /* if (skfd >= 0 && (FD_ISSET...)) */
+    } /* for */
+
+    /* Check if a packet was received on the encapsulating socket (if any)
+     * of each network interface */
+    for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
+    {
+      int skfd = walker->encapsulatingSkfd;
+      if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
+      {
+        struct sockaddr_in from;
+        socklen_t fromLen = sizeof(from);
+        int nBytes;
+        int minimumLength;
+        union olsr_ip_addr forwardedBy;
+
+        /* An encapsulated packet was received */
+
+        nFdBitsSet--;
+
+        nBytes = recvfrom(
+          skfd,
+          rxBuffer,
+          BMF_BUFFER_SIZE,
+          0,
+          (struct sockaddr*)&from,
+          &fromLen);
+        if (nBytes < 0)
+        {
+          BmfPError("recvfrom() error on \"%s\"", walker->ifName);
+
+          continue; /* for */
+        } /* if (nBytes < 0) */
+
+        forwardedBy.v4 = from.sin_addr;
+
+        /* Check if the number of received bytes is large enough for a minimal BMF
+         * encapsulation packet, at least:
+         * - the encapsulation header
+         * - a minimum IP header inside the encapsulated packet */
+        minimumLength =
+          ENCAP_HDR_LEN +
+          sizeof(struct ip);
+        if (nBytes < minimumLength)
+        {
+          struct ipaddr_str buf;
+          olsr_printf(
+            1,
+            "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
+            PLUGIN_NAME,
+            nBytes,
+            olsr_ip_to_string(&buf, &forwardedBy),
+            walker->ifName);
+
+          continue; /* for */
+        }
+
+        /* Unfortunately, the recvfrom call does not return the destination
+         * of the encapsulation packet (the destination may be either the
+         * my unicast or my local broadcast address). Therefore we fill in 'NULL'
+         * for the 'forwardedTo' parameter. */
+        BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
+
+      } /* if (skfd >= 0 && (FD_ISSET...)) */
+    } /* for */
+
+    if (nFdBitsSet > 0 && FD_ISSET(EtherTunTapFd, &rxFdSet))
+    {
+      /* Check if an application has sent a packet out via the tuntap
+       * network interface */
+
+      int nBytes;
+      unsigned char* ipPacket;
+      unsigned char* bufferToRead;
+      size_t nBytesToRead;
+
+      nFdBitsSet--;
+
+      /* Receive the packet, leaving space for the BMF encapsulation header */
+      ipPacket = GetIpPacket(rxBuffer);
+    
+      bufferToRead = ipPacket;
+      nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
+
+      nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
+
+      if (nBytes < 0)
+      {
+        BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
+      }
+      else
+      {
+        /* Check if the number of received bytes is large enough for an IP
+         * packet which contains at least a minimum-size IP header */
+        if (nBytes < (int)sizeof(struct ip))
+        {
+          olsr_printf(
+            1,
+            "%s: captured packet too short (%d bytes) on \"%s\"\n",
+            PLUGIN_NAME,
+            nBytes,
+            EtherTunTapIfName);
+        }
+        else
+        {
+          /* An outbound packet was captured */
+
+          BmfTunPacketCaptured(rxBuffer);
+
+        } /* if (nBytes < ... */
+      } /* if (nBytes < 0) */
+    } /* if (nFdBitsSet > 0 && ... */
+  } /* while (nFdBitsSet > 0) */
+} /* DoBmf */
+
+/* -------------------------------------------------------------------------
+ * Function   : BmfSignalHandler
+ * Description: Signal handler function
+ * Input      : signo - signal being handled
+ * Output     : none
+ * Return     : none
+ * Data Used  : BmfThreadRunning
+ * ------------------------------------------------------------------------- */
+static void BmfSignalHandler(int signo __attribute__((unused)))
+{
+  BmfThreadRunning = 0;
+} /* BmfSignalHandler */
+
+/* -------------------------------------------------------------------------
+ * 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 sending
+ *              a SIGALRM signal.
+ * ------------------------------------------------------------------------- */
+static void* BmfRun(void* useless __attribute__((unused)))
+{
+  /* Mask all signals except SIGALRM */
+  sigset_t blockedSigs;
+  sigfillset(&blockedSigs);
+  sigdelset(&blockedSigs, SIGALRM);
+  if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) != 0)
+  {
+    BmfPError("pthread_sigmask() error");
+  }
+
+  /* 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)
+  {
+    BmfPError("signal() error");
+  }
+
+  /* Call the thread function until flagged to exit */
+  while (BmfThreadRunning != 0)
+  {
+    DoBmf();
+  }
+
+  return NULL;
+} /* BmfRun */
+
+/* -------------------------------------------------------------------------
+ * 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):
+    /* We cannot just remove the interface, because the receive-thread is likely
+     * to be waiting in select(...) for packets coming in via the interface.
+     * Therefore we first close BMF (CloseBmf()), interrupting and kiling the
+     * receive-thread so that it is safe to remove this (and all other)
+     * interfaces. After that, BMF is re-started (InitBmf(interf)). */
+    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:
+    olsr_printf(
+      1,
+      "%s: interface %s: error - unknown action (%d)\n",
+      PLUGIN_NAME,
+      interf->int_name, action);
+    break;
+  }
+
+  return 0;
+} /* InterfaceChange */
+
+
+/* -------------------------------------------------------------------------
+ * Function   : SetFanOutLimit
+ * Description: Overrule the default fan out limit value (2)
+ * Input      : value - fan out limit value (1...MAX_UNICAST_NEIGHBORS)
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : FanOutLimit
+ * ------------------------------------------------------------------------- */
+int SetFanOutLimit(
+  const char* value,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (set_plugin_int(value, &FanOutLimit, addon) == 0)
+  {
+    /* Extra check if within range */
+    if (FanOutLimit >= 1 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
+    {
+      return 0;
+    }
+  }
+  return 1;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : InitBmf
+ * Description: Initialize the BMF plugin
+ * Input      : skipThisIntf - specifies which network interface should not
+ *              be enabled for BMF. Pass NULL if not applicable.
+ * Output     : none
+ * Return     : fail (0) or success (1)
+ * Data Used  : BmfThreadRunning, BmfThread
+ * ------------------------------------------------------------------------- */
+int InitBmf(struct interface* skipThisIntf)
+{
+  CreateBmfNetworkInterfaces(skipThisIntf);
+
+  /* Start running the multicast packet processing thread */
+  BmfThreadRunning = 1;
+  if (pthread_create(&BmfThread, NULL, BmfRun, NULL) != 0)
+  {
+    BmfPError("pthread_create() error");
+    return 0;
+  }
+
+  if (EtherTunTapFd >= 0)
+  {
+    /* Deactivate IP spoof filter for EtherTunTap interface */
+    DeactivateSpoofFilter();
+
+    /* If the BMF network interface has a sensible IP address, it is a good idea
+     * to route all multicast traffic through that interface */
+    if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
+    {
+      AddMulticastRoute();
+    }
+  }
+
+  return 1;
+} /* InitBmf */
+
+/* -------------------------------------------------------------------------
+ * Function   : CloseBmf
+ * Description: Close the BMF plugin and clean up
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : BmfThread
+ * ------------------------------------------------------------------------- */
+void CloseBmf(void)
+{
+  if (EtherTunTapFd >= 0)
+  {
+    /* If there is a multicast route, try to delete it first */
+    DeleteMulticastRoute();
+
+    /* Restore IP spoof filter for EtherTunTap interface */
+    RestoreSpoofFilter();
+  }
+
+  if (BmfThreadRunning)
+  {
+    /* Signal BmfThread to exit */
+    /* 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(...). */
+    if (pthread_kill(BmfThread, SIGALRM) != 0)
+    {
+      BmfPError("pthread_kill() error");
+    }
+
+    /* Wait for BmfThread to acknowledge */
+    if (pthread_join(BmfThread, NULL) != 0)
+    {
+      BmfPError("pthread_join() error");
+    }
+  }
+
+  /* Clean up after the BmfThread has been killed */
+  CloseBmfNetworkInterfaces();
+} /* CloseBmf */
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Bmf.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Bmf.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Bmf.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Bmf.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,70 @@
+#ifndef _BMF_BMF_H
+#define _BMF_BMF_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */ 
+
+/* BMF plugin data */
+#define PLUGIN_NAME "OLSRD Basic Multicast Forwarding (BMF) plugin"
+#define PLUGIN_NAME_SHORT "OLSRD BMF"
+#define PLUGIN_VERSION "1.5.3 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_COPYRIGHT "  (C) Thales Communications Huizen, Netherlands"
+#define PLUGIN_AUTHOR "  Erik Tromp (eriktromp@users.sourceforge.net)"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+/* UDP-Port on which multicast packets are encapsulated */
+#define BMF_ENCAP_PORT 50698
+
+/* Forward declaration of OLSR interface type */
+struct interface;
+
+extern int FanOutLimit;
+extern int BroadcastRetransmitCount;
+
+void BmfPError(const char* format, ...) __attribute__((format(printf, 1, 2)));
+union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip);
+int InterfaceChange(struct interface* interf, int action);
+int SetFanOutLimit(const char* value, void* data, set_plugin_parameter_addon addon);
+int InitBmf(struct interface* skipThisIntf);
+void CloseBmf(void);
+
+#endif /* _BMF_BMF_H */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,1970 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+#include "NetworkInterfaces.h"
+
+/* System includes */
+#include <stddef.h> /* NULL */
+#include <syslog.h> /* syslog() */
+#include <string.h> /* strerror(), strchr(), strcmp() */
+#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_IP */
+#include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
+#include <linux/if_tun.h> /* IFF_TAP */
+#include <netinet/ip.h> /* struct ip */
+#include <netinet/udp.h> /* SOL_UDP */
+
+/* OLSRD includes */
+#include "olsr.h" /* olsr_printf() */
+#include "ipcalc.h"
+#include "defs.h" /* olsr_cnf */
+#include "link_set.h" /* get_link_set() */
+#include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
+#include "net_olsr.h" /* ipequal */
+#include "lq_plugin.h"
+
+/* Plugin includes */
+#include "Packet.h" /* IFHWADDRLEN */
+#include "Bmf.h" /* PLUGIN_NAME, MainAddressOf() */
+#include "Address.h" /* IsMulticast() */
+
+/* List of network interface objects used by BMF plugin */
+struct TBmfInterface* BmfInterfaces = NULL;
+struct TBmfInterface* LastBmfInterface = NULL;
+
+/* Highest-numbered open socket file descriptor. To be used as first
+ * parameter in calls to select(...). */
+int HighestSkfd = -1;
+
+/* Set of socket file descriptors */
+fd_set InputSet;
+
+/* File descriptor of EtherTunTap interface */
+int EtherTunTapFd = -1;
+
+/* Network interface name of EtherTunTap interface. May be overruled by
+ * setting the plugin parameter "BmfInterface". */
+char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
+
+/* The underlying mechanism to forward multicast packets. Either:
+ * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
+ * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
+ *   destination address. The other neighbors listen promiscuously. */
+enum TBmfMechanism BmfMechanism = BM_BROADCAST;
+
+#define ETHERTUNTAPIPNOTSET 0
+
+/* The IP address of the BMF network interface in host byte order.
+ * May be overruled by setting the plugin parameter "BmfInterfaceIp". */
+u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET;
+
+/* 255.255.255.255 in host byte order. May be overruled by
+ * setting the plugin parameter "BmfInterfaceIp". */
+u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
+
+/* The IP broadcast address of the BMF network interface in host byte order.
+ * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
+u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
+
+/* Whether or not the configuration has overruled the default IP
+ * configuration of the EtherTunTap interface */
+int TunTapIpOverruled = 0;
+
+/* Whether or not to capture packets on the OLSR-enabled
+ * interfaces (in promiscuous mode). May be overruled by setting the plugin
+ * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */
+int CapturePacketsOnOlsrInterfaces = 0;
+
+/* -------------------------------------------------------------------------
+ * Function   : SetBmfInterfaceName
+ * Description: Overrule the default network interface name ("bmf0") of the
+ *              EtherTunTap interface
+ * Input      : ifname - network interface name (e.g. "mybmf0")
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : EtherTunTapIfName
+ * ------------------------------------------------------------------------- */
+int SetBmfInterfaceName(
+  const char* ifname,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
+  EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+  return 0;
+} /* SetBmfInterfaceName */
+
+/* -------------------------------------------------------------------------
+ * Function   : SetBmfInterfaceIp
+ * Description: Overrule the default IP address and prefix length
+ *              ("10.255.255.253/30") of the EtherTunTap interface
+ * Input      : ip - IP address string, followed by '/' and prefix length
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
+ *              TunTapIpOverruled
+ * ------------------------------------------------------------------------- */
+int SetBmfInterfaceIp(
+  const char* ip,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+#define IPV4_MAX_ADDRLEN 16
+#define IPV4_MAX_PREFIXLEN 32
+  char* slashAt;
+  char ipAddr[IPV4_MAX_ADDRLEN];
+  struct in_addr sinaddr;
+  int prefixLen;
+  int i;
+
+  /* Inspired by function str2prefix_ipv4 as found in Quagga source
+   * file lib/prefix.c */
+
+  /* Find slash inside string. */
+  slashAt = strchr(ip, '/');
+
+  /* String doesn't contain slash. */
+  if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN)
+  {
+    /* No prefix length specified, or IP address too long */
+    return 1;
+  }
+
+  strncpy(ipAddr, ip, slashAt - ip);
+  *(ipAddr + (slashAt - ip)) = '\0';
+  if (inet_aton(ipAddr, &sinaddr) == 0)
+  {
+    /* Invalid address passed */
+    return 1;
+  }
+
+  EtherTunTapIp = ntohl(sinaddr.s_addr);
+
+  /* Get prefix length. */
+  prefixLen = atoi(++slashAt);
+  if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN)
+  {
+    return 1;
+  }
+
+  /* Compose IP subnet mask in host byte order */
+  EtherTunTapIpMask = 0;
+  for (i = 0; i < prefixLen; i++)
+  {
+    EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
+  }
+
+  /* Compose IP broadcast address in host byte order */
+  EtherTunTapIpBroadcast = EtherTunTapIp;
+  for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
+  {
+    EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
+  }
+
+  TunTapIpOverruled = 1;
+
+  return 0;
+} /* SetBmfInterfaceIp */
+
+/* -------------------------------------------------------------------------
+ * Function   : SetCapturePacketsOnOlsrInterfaces
+ * Description: Overrule the default setting, enabling or disabling the
+ *              capturing of packets on OLSR-enabled interfaces.
+ * Input      : enable - either "yes" or "no"
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int SetCapturePacketsOnOlsrInterfaces(
+  const char* enable,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (strcmp(enable, "yes") == 0)
+  {
+    CapturePacketsOnOlsrInterfaces = 1;
+    return 0;
+  }
+  else if (strcmp(enable, "no") == 0)
+  {
+    CapturePacketsOnOlsrInterfaces = 0;
+    return 0;
+  }
+
+  /* Value not recognized */
+  return 1;
+} /* SetCapturePacketsOnOlsrInterfaces */
+
+/* -------------------------------------------------------------------------
+ * Function   : SetBmfMechanism
+ * Description: Overrule the default BMF mechanism to either BM_BROADCAST or
+ *              BM_UNICAST_PROMISCUOUS.
+ * Input      : mechanism - either "Broadcast" or "UnicastPromiscuous"
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int SetBmfMechanism(
+  const char* mechanism,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (strcmp(mechanism, "Broadcast") == 0)
+  {
+    BmfMechanism = BM_BROADCAST;
+    return 0;
+  }
+  else if (strcmp(mechanism, "UnicastPromiscuous") == 0)
+  {
+    BmfMechanism = BM_UNICAST_PROMISCUOUS;
+    return 0;
+  }
+
+  /* Value not recognized */
+  return 1;
+} /* SetBmfMechanism */
+
+/* -------------------------------------------------------------------------
+ * Function   : AddDescriptorToInputSet
+ * Description: Add a socket descriptor to the global set of socket file descriptors
+ * Input      : skfd - socket file descriptor
+ * Output     : none
+ * Return     : none
+ * Data Used  : HighestSkfd, InputSet
+ * Notes      : Keeps track of the highest-numbered descriptor
+ * ------------------------------------------------------------------------- */
+static void AddDescriptorToInputSet(int skfd)
+{
+  /* Keep the highest-numbered descriptor */
+  if (skfd > HighestSkfd)
+  {
+    HighestSkfd = skfd;
+  }
+
+  /* Add descriptor to input set */
+  FD_SET(skfd, &InputSet);
+} /* AddDescriptorToInputSet */
+
+/* To save the state of the IP spoof filter for the EtherTunTap interface */
+static char EthTapSpoofState = '1';
+
+/* -------------------------------------------------------------------------
+ * Function   : DeactivateSpoofFilter
+ * Description: Deactivates the Linux anti-spoofing filter for the tuntap
+ *              interface
+ * Input      : none
+ * Output     : none
+ * Return     : fail (0) or success (1)
+ * Data Used  : EtherTunTapIfName, EthTapSpoofState
+ * Notes      : Saves the current filter state for later restoring
+ * ------------------------------------------------------------------------- */
+int DeactivateSpoofFilter(void)
+{
+  FILE* procSpoof;
+  char procFile[FILENAME_MAX];
+
+  /* Generate the procfile name */
+  sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
+
+  /* Open procfile for reading */
+  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);
+
+  /* Open procfile for writing */
+  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;
+} /* DeactivateSpoofFilter */
+
+/* -------------------------------------------------------------------------
+ * Function   : RestoreSpoofFilter
+ * Description: Restores the Linux anti-spoofing filter setting for the tuntap
+ *              interface
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : EtherTunTapIfName, EthTapSpoofState
+ * ------------------------------------------------------------------------- */
+void RestoreSpoofFilter(void)
+{
+  FILE* procSpoof;
+  char procFile[FILENAME_MAX];
+
+  /* Generate the procfile name */
+  sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
+
+  /* Open procfile for writing */
+  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);
+  }
+} /* RestoreSpoofFilter */
+
+/* -------------------------------------------------------------------------
+ * Function   : FindNeighbors
+ * Description: Find the neighbors on a network interface to forward a BMF
+ *              packet to
+ * Input      : intf - the network interface
+ *              source - the source IP address of the BMF packet 
+ *              forwardedBy - the IP address of the node that forwarded the BMF
+ *                packet
+ *              forwardedTo - the IP address of the node to which the BMF packet
+ *                was directed
+ * Output     : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
+ *              bestNeighbor - the best neighbor (in terms of lowest cost or ETX
+ *                value)
+ *              nPossibleNeighbors - number of found possible neighbors
+ * Data Used  : FanOutLimit
+ * ------------------------------------------------------------------------- */
+void FindNeighbors(
+  struct TBestNeighbors* neighbors,
+  struct link_entry** bestNeighbor,
+  struct TBmfInterface* intf,
+  union olsr_ip_addr* source,
+  union olsr_ip_addr* forwardedBy,
+  union olsr_ip_addr* forwardedTo,
+  int* nPossibleNeighbors)
+{
+  int i;
+
+  /* Initialize */
+  *bestNeighbor = NULL;
+  for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
+  {
+    neighbors->links[i] = NULL;
+  }
+  *nPossibleNeighbors = 0;
+
+  /* handle the non-LQ case */
+
+  if (olsr_cnf->lq_level == 0)
+  {
+    struct link_entry* walker;
+
+    OLSR_FOR_ALL_LINK_ENTRIES(walker) {
+      struct ipaddr_str buf;
+      union olsr_ip_addr* neighborMainIp;
+
+      /* Consider only links from the specified interface */
+      if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
+      {
+        continue; /* for */
+      }
+
+      OLSR_PRINTF(
+        8,
+        "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
+        PLUGIN_NAME_SHORT,
+        intf->ifName,
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+      neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
+
+      /* Consider only neighbors with an IP address that differs from the
+       * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
+      if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
+      {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is source of pkt\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Rely on short-circuit boolean evaluation */
+      if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
+      {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Rely on short-circuit boolean evaluation */
+      if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
+      {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Found a candidate neighbor to direct our packet to */
+
+      /* In the non-LQ case, it is not possible to select neigbors
+       * by quality or cost. So just remember the first found link.
+       * TODO: come on, there must be something better than to simply
+       * select the first one found! */
+      if (*bestNeighbor == NULL)
+      {
+        *bestNeighbor = walker;
+      }
+
+      /* Fill the list with up to 'FanOutLimit' neighbors. If there
+       * are more neighbors, broadcast is used instead of unicast. In that
+       * case we do not need the list of neighbors. */
+      if (*nPossibleNeighbors < FanOutLimit)
+      {
+        neighbors->links[*nPossibleNeighbors] = walker;
+      }
+
+      *nPossibleNeighbors += 1;
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
+
+  }
+  /* handle the LQ case */
+  else
+  {
+#ifdef USING_THALES_LINK_COST_ROUTING
+
+    struct link_entry* walker;
+    float previousLinkCost = 2 * INFINITE_COST;
+    float bestLinkCost = 2 * INFINITE_COST;
+
+    if (forwardedBy != NULL)
+    {
+      /* Retrieve the cost of the link from 'forwardedBy' to myself */
+      struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
+      if (bestLinkFromForwarder != NULL)
+      {
+        previousLinkCost = bestLinkFromForwarder->link_cost;
+      }
+    }
+
+    /* TODO: get_link_set() is not thread-safe! */
+    for (walker = get_link_set(); walker != NULL; walker = walker->next) 
+    {
+      struct ipaddr_str buf;
+      union olsr_ip_addr* neighborMainIp;
+      struct link_entry* bestLinkToNeighbor;
+      struct tc_entry* tcLastHop;
+
+      /* Consider only links from the specified interface */
+      if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
+      {
+        continue; /* for */
+      }
+
+      OLSR_PRINTF(
+        9,
+        "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
+        PLUGIN_NAME_SHORT,
+        intf->ifName,
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+      neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
+
+      /* Consider only neighbors with an IP address that differs from the
+       * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
+      if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is source of pkt\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Rely on short-circuit boolean evaluation */
+      if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Rely on short-circuit boolean evaluation */
+      if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Found a candidate neighbor to direct our packet to */
+
+      if (walker->link_cost >= INFINITE_COST)
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: link is timing out\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
+      OLSR_PRINTF(
+        9,
+        "%s: ----> Forwarding pkt to %s will cost %5.2f\n",
+        PLUGIN_NAME_SHORT,
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
+        walker->link_cost);
+
+      /* If the candidate neighbor is best reached via another interface, then skip 
+       * the candidate neighbor; the candidate neighbor has been / will be selected via that
+       * other interface.
+       * TODO: get_best_link_to_neighbor() is not thread-safe. */
+      bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
+
+      if (walker != bestLinkToNeighbor)
+      {
+        if (bestLinkToNeighbor == NULL)
+        {
+          OLSR_PRINTF(
+            9,
+            "%s: ----> Not forwarding to %s: no link found\n",
+            PLUGIN_NAME_SHORT,
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+        }
+        else
+        {
+          struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
+
+          OLSR_PRINTF(
+            9,
+            "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
+            PLUGIN_NAME_SHORT,
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
+            bestIntf->int_name,
+            bestLinkToNeighbor->link_cost);
+        }
+
+        continue; /* for */
+      }
+
+      if (forwardedBy != NULL)
+      {
+        struct ipaddr_str forwardedByBuf, niaBuf;
+        OLSR_PRINTF(
+          9,
+          "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&forwardedByBuf, forwardedBy),
+          olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
+          previousLinkCost + walker->link_cost);
+      }
+
+      /* Check the topology table whether the 'forwardedBy' node is itself a direct
+       * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
+       * via myself. If so, we do not need to forward the BMF packet to the candidate
+       * neighbor, because the 'forwardedBy' node will forward the packet. */
+      if (forwardedBy != NULL)
+      {
+        /* TODO: olsr_lookup_tc_entry() is not thread-safe. */
+        tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
+        if (tcLastHop != NULL)
+        {
+          struct tc_edge_entry* tc_edge;
+
+          /* TODO: olsr_lookup_tc_edge() is not thread-safe. */
+          tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
+          
+          /* We are not interested in dead-end or dying edges. */
+          if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
+          {
+            if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
+            {
+#ifndef NODEBUG
+              struct ipaddr_str neighbor_iface_buf, forw_buf;
+              olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
+#endif
+              OLSR_PRINTF(
+                9,
+                "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
+                PLUGIN_NAME_SHORT,
+                neighbor_iface_buf.buf,
+                olsr_ip_to_string(&forw_buf, forwardedBy),
+                neighbor_iface_buf.buf,
+                tc_edge->link_cost);
+
+              continue; /* for */
+            } /* if */
+          } /* if */
+        } /* if */
+      } /* if */
+
+      /* Remember the best neighbor. If all are very bad, remember none. */
+      if (walker->link_cost < bestLinkCost)
+      {
+        *bestNeighbor = walker;
+        bestLinkCost = walker->link_cost;
+      }
+
+      /* Fill the list with up to 'FanOutLimit' neighbors. If there
+       * are more neighbors, broadcast is used instead of unicast. In that
+       * case we do not need the list of neighbors. */
+      if (*nPossibleNeighbors < FanOutLimit)
+      {
+        neighbors->links[*nPossibleNeighbors] = walker;
+      }
+
+      *nPossibleNeighbors += 1;
+
+    } /* for */
+
+#else /* USING_THALES_LINK_COST_ROUTING */
+        
+    struct link_entry* walker;
+    olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
+    olsr_linkcost bestEtx = LINK_COST_BROKEN;
+
+    if (forwardedBy != NULL)
+    {
+      /* Retrieve the cost of the link from 'forwardedBy' to myself */
+      struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
+      if (bestLinkFromForwarder != NULL)
+      {
+        previousLinkEtx = bestLinkFromForwarder->linkcost;
+      }
+    }
+
+    OLSR_FOR_ALL_LINK_ENTRIES(walker) {
+      struct ipaddr_str buf;
+      union olsr_ip_addr* neighborMainIp;
+      struct link_entry* bestLinkToNeighbor;
+      struct tc_entry* tcLastHop;
+      float currEtx;
+ 
+      /* Consider only links from the specified interface */
+      if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
+      {
+        continue; /* for */
+      }
+
+      OLSR_PRINTF(
+        9,
+        "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
+        PLUGIN_NAME_SHORT,
+        intf->ifName,
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+      neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
+
+      /* Consider only neighbors with an IP address that differs from the
+       * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
+      if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is source of pkt\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Rely on short-circuit boolean evaluation */
+      if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Rely on short-circuit boolean evaluation */
+      if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Found a candidate neighbor to direct our packet to */
+
+      /* Calculate the link quality (ETX) of the link to the found neighbor */
+      currEtx = walker->linkcost;
+ 
+      if (currEtx < LINK_COST_BROKEN)
+      {
+        OLSR_PRINTF(
+          9,
+          "%s: ----> Not forwarding to %s: link is timing out\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+
+        continue; /* for */
+      }
+
+      /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
+      OLSR_PRINTF(
+        9,
+        "%s: ----> Forwarding pkt to %s will cost ETX %5.2f\n",
+        PLUGIN_NAME_SHORT,
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
+        currEtx);
+
+      /* If the candidate neighbor is best reached via another interface, then skip 
+       * the candidate neighbor; the candidate neighbor has been / will be selected via that
+       * other interface.
+       * TODO: get_best_link_to_neighbor() is not thread-safe. */
+      bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
+
+      if (walker != bestLinkToNeighbor)
+      {
+        if (bestLinkToNeighbor == NULL)
+        {
+          struct ipaddr_str buf;
+          OLSR_PRINTF(
+            9,
+            "%s: ----> Not forwarding to %s: no link found\n",
+            PLUGIN_NAME_SHORT,
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
+        }
+        else
+        {
+#ifndef NODEBUG
+          struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
+          struct ipaddr_str buf;
+          struct lqtextbuffer lqbuffer;
+#endif
+          OLSR_PRINTF(
+            9,
+            "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
+            PLUGIN_NAME_SHORT,
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
+            bestIntf->int_name,
+            get_linkcost_text(bestLinkToNeighbor->linkcost, OLSR_FALSE, &lqbuffer));
+        }
+
+        continue; /* for */
+      }
+
+      if (forwardedBy != NULL)
+      {
+#ifndef NODEBUG
+        struct ipaddr_str forwardedByBuf, niaBuf;
+        struct lqtextbuffer lqbuffer;
+#endif
+        OLSR_PRINTF(
+          9,
+          "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n",
+          PLUGIN_NAME_SHORT,
+          olsr_ip_to_string(&forwardedByBuf, forwardedBy),
+          olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
+          get_linkcost_text(previousLinkEtx + currEtx, OLSR_TRUE, &lqbuffer));
+      }
+
+      /* Check the topology table whether the 'forwardedBy' node is itself a direct
+       * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
+       * via myself. If so, we do not need to forward the BMF packet to the candidate
+       * neighbor, because the 'forwardedBy' node will forward the packet. */
+      if (forwardedBy != NULL)
+      {
+        /* TODO: olsr_lookup_tc_entry() is not thread-safe. */
+        tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
+        if (tcLastHop != NULL)
+        {
+          struct tc_edge_entry* tc_edge;
+
+          /* TODO: olsr_lookup_tc_edge() is not thread-safe. */
+          tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
+
+          /* We are not interested in dead-end edges. */
+          if (tc_edge) {
+            olsr_linkcost tcEtx = tc_edge->cost;
+
+            if (previousLinkEtx + currEtx > tcEtx)
+            {
+#ifndef NODEBUG
+              struct ipaddr_str neighbor_iface_buf, forw_buf;
+              struct lqtextbuffer lqbuffer;
+              olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
+#endif
+              OLSR_PRINTF(
+                9,
+                "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
+                PLUGIN_NAME_SHORT,
+                neighbor_iface_buf.buf,
+                olsr_ip_to_string(&forw_buf, forwardedBy),
+                neighbor_iface_buf.buf,
+                get_linkcost_text(tcEtx, OLSR_FALSE, &lqbuffer));
+
+              continue; /* for */
+            } /* if */
+          } /* if */
+        } /* if */
+      } /* if */
+
+      /* Remember the best neighbor. If all are very bad, remember none. */
+      if (currEtx < bestEtx)
+      {
+        *bestNeighbor = walker;
+        bestEtx = currEtx;
+      }
+
+      /* Fill the list with up to 'FanOutLimit' neighbors. If there
+       * are more neighbors, broadcast is used instead of unicast. In that
+       * case we do not need the list of neighbors. */
+      if (*nPossibleNeighbors < FanOutLimit)
+      {
+        neighbors->links[*nPossibleNeighbors] = walker;
+      }
+
+      *nPossibleNeighbors += 1;
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
+
+#endif /* USING_THALES_LINK_COST_ROUTING */
+
+  } /* if */
+
+  /* Display the result of the neighbor search */
+  if (*nPossibleNeighbors == 0)
+  {
+    OLSR_PRINTF(
+      9,
+      "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
+      PLUGIN_NAME_SHORT,
+      intf->ifName);
+  }
+  else
+  {
+    struct ipaddr_str buf;
+    OLSR_PRINTF(
+      9,
+      "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
+      PLUGIN_NAME_SHORT,
+      *nPossibleNeighbors,
+      intf->ifName,
+      olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
+  } /* if */
+
+} /* FindNeighbors */
+
+/* -------------------------------------------------------------------------
+ * 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 cooked IP 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 cooked IP packet socket */
+  int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+  if (skfd < 0)
+  {
+    BmfPError("socket(PF_PACKET) error");
+    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)
+  {
+    BmfPError("setsockopt(PACKET_MR_PROMISC) error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Get hardware (MAC) address */
+  memset(&req, 0, sizeof(struct ifreq));
+  strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
+  req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
+  if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
+  {
+    BmfPError("error retrieving MAC address");
+    close(skfd);
+    return -1;
+  }
+   
+  /* Bind the socket to the specified interface */
+  memset(&bindTo, 0, sizeof(bindTo));
+  bindTo.sll_family = AF_PACKET;
+  bindTo.sll_protocol = htons(ETH_P_IP);
+  bindTo.sll_ifindex = ifIndex;
+  memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  bindTo.sll_halen = IFHWADDRLEN;
+    
+  if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
+  {
+    BmfPError("bind() error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
+  {
+    BmfPError("fcntl() error");
+    close(skfd);
+    return -1;
+  }
+
+  AddDescriptorToInputSet(skfd);
+
+  return skfd;
+} /* CreateCaptureSocket */
+
+/* -------------------------------------------------------------------------
+ * Function   : CreateListeningSocket
+ * Description: Create socket for promiscuously listening to BMF packets.
+ *              Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
+ * 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 cooked IP packet socket, bound to the specified
+ *              network interface
+ * ------------------------------------------------------------------------- */
+static int CreateListeningSocket(const char* ifName)
+{
+  int ifIndex = if_nametoindex(ifName);
+  struct packet_mreq mreq;
+  struct ifreq req;
+  struct sockaddr_ll bindTo;
+
+  /* Open cooked IP packet socket */
+  int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+  if (skfd < 0)
+  {
+    BmfPError("socket(PF_PACKET) error");
+    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)
+  {
+    BmfPError("setsockopt(PACKET_MR_PROMISC) error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Get hardware (MAC) address */
+  memset(&req, 0, sizeof(struct ifreq));
+  strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
+  req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
+  if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
+  {
+    BmfPError("error retrieving MAC address");
+    close(skfd);
+    return -1;
+  }
+
+  /* Bind the socket to the specified interface */
+  memset(&bindTo, 0, sizeof(bindTo));
+  bindTo.sll_family = AF_PACKET;
+  bindTo.sll_protocol = htons(ETH_P_IP);
+  bindTo.sll_ifindex = ifIndex;
+  memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  bindTo.sll_halen = IFHWADDRLEN;
+    
+  if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
+  {
+    BmfPError("bind() error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
+  {
+    BmfPError("fcntl() error");
+    close(skfd);
+    return -1;
+  }
+
+  AddDescriptorToInputSet(skfd);
+
+  return skfd;
+} /* CreateListeningSocket */
+
+/* -------------------------------------------------------------------------
+ * 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)
+  {
+    BmfPError("socket(PF_INET) error");
+    return -1;
+  }
+
+  /* Enable sending to broadcast addresses */
+  if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
+  {
+    BmfPError("setsockopt(SO_BROADCAST) error");
+    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)
+  {
+    BmfPError("setsockopt(SO_BINDTODEVICE) error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Bind to BMF 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) 
+  {
+    BmfPError("bind() error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
+  {
+    BmfPError("fcntl() error");
+    close(skfd);
+    return -1;
+  }
+
+  AddDescriptorToInputSet(skfd);
+
+  return skfd;
+} /* CreateEncapsulateSocket */
+
+/* -------------------------------------------------------------------------
+ * Function   : CreateLocalEtherTunTap
+ * Description: Creates and brings up an EtherTunTap interface
+ * Input      : none
+ * Output     : none
+ * Return     : the socket file descriptor (>= 0), or -1 in case of failure
+ * Data Used  : EtherTunTapIfName - name used for the tuntap interface (e.g.
+ *                "bmf0")
+ *              EtherTunTapIp
+ *              EtherTunTapIpMask
+ *              EtherTunTapIpBroadcast
+ *              BmfInterfaces
+ * Note       : Order dependency: call this function only if BmfInterfaces
+ *              is filled with a list of network interfaces.
+ * ------------------------------------------------------------------------- */
+static int CreateLocalEtherTunTap(void)
+{
+  static const char deviceName[] = "/dev/net/tun";
+  struct ifreq ifreq;
+  int etfd;
+  int ioctlSkfd;
+  int ioctlres;
+
+  etfd = open(deviceName, O_RDWR | O_NONBLOCK);
+  if (etfd < 0)
+  {
+    BmfPError("error opening %s", deviceName);
+    return -1;
+  }
+
+  memset(&ifreq, 0, sizeof(ifreq));
+  strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
+  ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+
+  /* Specify the IFF_TUN flag for IP packets.
+   * Specify IFF_NO_PI for not receiving extra meta packet information. */
+  ifreq.ifr_flags = IFF_TUN;
+  ifreq.ifr_flags |= IFF_NO_PI;
+
+  if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
+  {
+    BmfPError("ioctl(TUNSETIFF) error on %s", deviceName);
+    close(etfd);
+    return -1;
+  }
+
+  memset(&ifreq, 0, sizeof(ifreq));
+  strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
+  ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+  ifreq.ifr_addr.sa_family = AF_INET;
+
+  ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (ioctlSkfd < 0)
+  {
+    BmfPError("socket(PF_INET) error on %s", deviceName);
+    close(etfd);
+    return -1;
+  }
+
+  /* Give the EtherTunTap interface an IP address.
+   * The default IP address is the address of the first OLSR interface;
+   * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents
+   * automatic entry of the BMF network interface in the routing table. */
+  if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
+  {
+    struct TBmfInterface* nextBmfIf = BmfInterfaces;
+    while (nextBmfIf != NULL)
+    {
+      struct TBmfInterface* bmfIf = nextBmfIf;
+      nextBmfIf = bmfIf->next;
+
+      if (bmfIf->olsrIntf != NULL)
+      {
+        EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr);
+        EtherTunTapIpBroadcast = EtherTunTapIp;
+      }
+    }
+  }
+
+  if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
+  {
+    /* No IP address configured for BMF network interface, and no OLSR interface found to
+     * copy IP address from. Fall back to default: 10.255.255.253 . */
+    EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
+  }
+
+  ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr = htonl(EtherTunTapIp);
+  ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
+  if (ioctlres >= 0)
+  {
+    /* Set net mask */
+    ((struct sockaddr_in*)&ifreq.ifr_netmask)->sin_addr.s_addr = htonl(EtherTunTapIpMask);
+    ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
+    if (ioctlres >= 0)
+    {
+      /* Set broadcast IP */
+      ((struct sockaddr_in*)&ifreq.ifr_broadaddr)->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
+      ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
+      if (ioctlres >= 0)
+      {
+        /* Bring EtherTunTap interface up (if not already) */
+        ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
+        if (ioctlres >= 0)
+        {
+          ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
+          ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
+        }
+      }
+    }
+  }
+
+  if (ioctlres < 0)
+  {
+    /* Any of the above ioctl() calls failed */
+    BmfPError("error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName);
+
+    close(etfd);
+    close(ioctlSkfd);
+    return -1;
+  } /* if (ioctlres < 0) */
+
+  /* Set the multicast flag on the interface */
+  memset(&ifreq, 0, sizeof(ifreq));
+  strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
+  ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+
+  ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
+  if (ioctlres >= 0)
+  {
+    ifreq.ifr_flags |= IFF_MULTICAST;
+    ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
+  }
+  if (ioctlres < 0)
+  {
+    /* Any of the two above ioctl() calls failed */
+    BmfPError("error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName);
+
+    /* Continue anyway */
+  }
+
+  /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
+   * when this program exits. That is not desirable, since a multicast
+   * daemon (e.g. mrouted) may be using the tuntap interface. */
+  if (ioctl(etfd, TUNSETPERSIST, (void *)&ifreq) < 0)
+  {
+    BmfPError("error making EtherTunTap interface \"%s\" persistent", EtherTunTapIfName);
+
+    /* Continue anyway */
+  }
+
+  OLSR_PRINTF(8, "%s: opened 1 socket on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
+
+  AddDescriptorToInputSet(etfd);
+
+  /* If the user configured a specific IP address for the BMF network interface,
+   * help the user and advertise the IP address of the BMF network interface
+   * on the OLSR network via HNA */
+  if (TunTapIpOverruled != 0)
+  {
+    union olsr_ip_addr temp_net;
+
+    temp_net.v4.s_addr = htonl(EtherTunTapIp);
+    ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32);
+  }
+
+  close(ioctlSkfd);
+
+  return etfd;
+} /* CreateLocalEtherTunTap */
+
+/* -------------------------------------------------------------------------
+ * 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")
+ *            : olsrIntf - OLSR interface object of the network interface, or
+ *                NULL if the network interface is not OLSR-enabled
+ * Output     : none
+ * Return     : the number of opened sockets
+ * Data Used  : BmfInterfaces, LastBmfInterface
+ * ------------------------------------------------------------------------- */
+static int CreateInterface(
+  const char* ifName,
+  struct interface* olsrIntf)
+{
+  int capturingSkfd = -1;
+  int encapsulatingSkfd = -1;
+  int listeningSkfd = -1;
+  int ioctlSkfd;
+  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-enabled interfaces, create socket for encapsulating and forwarding 
+     * multicast packets */
+    encapsulatingSkfd = CreateEncapsulateSocket(ifName);
+    if (encapsulatingSkfd < 0)
+    {
+      free(newIf);
+      return 0;
+    }
+    nOpened++;
+  }
+
+  /* Create socket for capturing and sending of multicast packets on
+   * non-OLSR interfaces, and on OLSR-interfaces if configured. */
+  if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0))
+  {
+    capturingSkfd = CreateCaptureSocket(ifName);
+    if (capturingSkfd < 0)
+    {
+      close(encapsulatingSkfd);
+      free(newIf);
+      return 0;
+    }
+
+    nOpened++;
+  }
+
+  /* Create promiscuous mode listening interface if BMF uses IP unicast
+   * as underlying forwarding mechanism */
+  if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
+  {
+    listeningSkfd = CreateListeningSocket(ifName);
+    if (listeningSkfd < 0)
+    {
+      close(listeningSkfd);
+      close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
+      free(newIf);
+      return 0;
+    }
+
+    nOpened++;
+  }
+
+  /* For ioctl operations on the network interface, use either capturingSkfd
+   * or encapsulatingSkfd, whichever is available */
+  ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
+
+  /* Retrieve the MAC address of the interface. */
+  memset(&ifr, 0, sizeof(struct ifreq));
+  strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
+  ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+  if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
+  {
+    BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
+    close(capturingSkfd);
+    close(encapsulatingSkfd);
+    free(newIf);
+    return 0;
+  }
+
+  /* Copy data into TBmfInterface object */
+  newIf->capturingSkfd = capturingSkfd;
+  newIf->encapsulatingSkfd = encapsulatingSkfd;
+  newIf->listeningSkfd = listeningSkfd;
+  memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  memcpy(newIf->ifName, ifName, IFNAMSIZ);
+  newIf->olsrIntf = olsrIntf;
+  if (olsrIntf != NULL)
+  {
+    /* For an OLSR-interface, copy the interface address and broadcast
+     * address from the OLSR interface object. Downcast to correct sockaddr
+     * subtype. */
+    newIf->intAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_addr)->sin_addr;
+    newIf->broadAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_broadaddr)->sin_addr;
+  }
+  else
+  {
+    /* For a non-OLSR interface, retrieve the IP address ourselves */
+    memset(&ifr, 0, sizeof(struct ifreq));
+    strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
+    ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+    if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) 
+    {
+      BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
+
+      newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
+    }
+    else
+    {
+      /* Downcast to correct sockaddr subtype */
+      newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+    }
+
+    /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
+    memset(&ifr, 0, sizeof(struct ifreq));
+    strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
+    ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+    if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) 
+    {
+      BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
+
+      newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
+    }
+    else
+    {
+      /* Downcast to correct sockaddr subtype */
+      newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
+    }
+  }
+
+  /* Initialize fragment history table */
+  memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
+  newIf->nextFragmentHistoryEntry = 0;
+
+  /* Reset counters */
+  newIf->nBmfPacketsRx = 0;
+  newIf->nBmfPacketsRxDup = 0;
+  newIf->nBmfPacketsTx = 0;
+
+  /* Add new TBmfInterface object to global list. OLSR interfaces are
+   * added at the front of the list, non-OLSR interfaces at the back. */
+  if (BmfInterfaces == NULL)
+  {
+    /* First TBmfInterface object in list */
+    BmfInterfaces = newIf;
+    LastBmfInterface = newIf;
+  }
+  else if (olsrIntf != NULL)
+  {
+    /* Add new TBmfInterface object at front of list */
+    newIf->next = BmfInterfaces;
+    BmfInterfaces = newIf;
+  }
+  else
+  {
+    /* Add new TBmfInterface object at back of list */
+    newIf->next = NULL;
+    LastBmfInterface->next= newIf;
+    LastBmfInterface = newIf;
+  }
+
+  OLSR_PRINTF(
+    8,
+    "%s: opened %d socket%s on %s interface \"%s\"\n",
+    PLUGIN_NAME_SHORT,
+    nOpened,
+    nOpened == 1 ? "" : "s",
+    olsrIntf != NULL ? "OLSR" : "non-OLSR",
+    ifName);
+
+  return nOpened;
+} /* CreateInterface */
+
+/* -------------------------------------------------------------------------
+ * 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     : fail (-1) or success (0)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
+{
+  int skfd;
+  struct ifconf ifc;
+  int numreqs = 30;
+  struct ifreq* ifr;
+  int n;
+  int nOpenedSockets = 0;
+
+  /* Clear input descriptor set */
+  FD_ZERO(&InputSet);
+
+  skfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (skfd < 0)
+  {
+    BmfPError("no inet socket available to retrieve interface list");
+    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)
+    {
+      BmfPError("ioctl(SIOCGIFCONF) error");
+
+      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;
+    union olsr_ip_addr ipAddr;
+
+    /* Skip the BMF network interface itself */
+    if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
+    {
+      continue; /* for (n = ...) */
+    }
+
+    /* ...find the OLSR interface structure, if any */
+    ipAddr.v4 =  ((struct sockaddr_in*)&ifr->ifr_addr)->sin_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 = ...) */
+    }
+
+    nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
+
+  } /* for (n = ...) */
+
+  free(ifc.ifc_buf);
+  
+  /* Create the BMF network interface */
+  EtherTunTapFd = CreateLocalEtherTunTap();
+  if (EtherTunTapFd >= 0)
+  {
+    nOpenedSockets++;
+  }
+
+  if (BmfInterfaces == NULL)
+  {
+    olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
+  }
+  else
+  {
+    olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
+  }
+  return 0;
+} /* CreateBmfNetworkInterfaces */
+
+/* -------------------------------------------------------------------------
+ * 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);
+} /* AddInterface */
+
+/* -------------------------------------------------------------------------
+ * Function   : CloseBmfNetworkInterfaces
+ * Description: Closes every socket on each network interface used by BMF
+ * Input      : none
+ * 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(void)
+{
+  int nClosed = 0;
+  u_int32_t totalOlsrBmfPacketsRx = 0;
+  u_int32_t totalOlsrBmfPacketsRxDup = 0;
+  u_int32_t totalOlsrBmfPacketsTx = 0;
+  u_int32_t totalNonOlsrBmfPacketsRx = 0;
+  u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
+  u_int32_t totalNonOlsrBmfPacketsTx = 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(
+      7,
+      "%s: %s interface \"%s\": RX pkts %d (%d dups); TX pkts %d\n", 
+      PLUGIN_NAME_SHORT,
+      bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
+      bmfIf->ifName,
+      bmfIf->nBmfPacketsRx,
+      bmfIf->nBmfPacketsRxDup,
+      bmfIf->nBmfPacketsTx);
+
+    olsr_printf(
+      1,
+      "%s: closed %s interface \"%s\"\n", 
+      PLUGIN_NAME_SHORT,
+      bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
+      bmfIf->ifName);
+
+    /* Add totals */
+    if (bmfIf->olsrIntf != NULL)
+    {
+      totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
+      totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
+      totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
+    }
+    else
+    {
+      totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
+      totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
+      totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
+    }
+
+    free(bmfIf);
+  } /* while */
+  
+  if (EtherTunTapFd >= 0)
+  {
+    close(EtherTunTapFd);
+    nClosed++;
+
+    OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
+  }
+
+  BmfInterfaces = NULL;
+
+  olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
+
+  OLSR_PRINTF(
+    7,
+    "%s: Total all OLSR interfaces    : RX pkts %d (%d dups); TX pkts %d\n",
+    PLUGIN_NAME_SHORT,
+    totalOlsrBmfPacketsRx,
+    totalOlsrBmfPacketsRxDup,
+    totalOlsrBmfPacketsTx);
+  OLSR_PRINTF(
+    7,
+    "%s: Total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
+    PLUGIN_NAME_SHORT,
+    totalNonOlsrBmfPacketsRx,
+    totalNonOlsrBmfPacketsRxDup,
+    totalNonOlsrBmfPacketsTx);
+} /* CloseBmfNetworkInterfaces */
+
+#define MAX_NON_OLSR_IFS 32
+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")
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : NonOlsrIfNames
+ * ------------------------------------------------------------------------- */
+int AddNonOlsrBmfIf(
+  const char* ifName,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  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 1;
+  }
+
+  strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
+  NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
+  nNonOlsrIfs++;
+  return 0;
+} /* AddNonOlsrBmfIf */
+
+/* -------------------------------------------------------------------------
+ * 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  : NonOlsrIfNames
+ * ------------------------------------------------------------------------- */
+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;
+} /* IsNonOlsrBmfIf */
+
+/* -------------------------------------------------------------------------
+ * Function   : CheckAndUpdateLocalBroadcast
+ * Description: For an IP packet, check if the destination address is not a
+ *              multicast address. If it is not, the packet is assumed to be
+ *              a local broadcast packet. In that case, set the destination
+ *              address of the IP packet to the passed broadcast address.
+ * Input      : ipPacket - the IP packet
+ *              broadAddr - the broadcast address to fill in
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : See also RFC1141
+ * ------------------------------------------------------------------------- */
+void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr)
+{
+  struct iphdr* iph;
+  union olsr_ip_addr destIp;
+
+  assert(ipPacket != NULL && broadAddr != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+  destIp.v4.s_addr = iph->daddr;
+  if (! IsMulticast(&destIp))
+  {
+    u_int32_t origDaddr, newDaddr;
+    u_int32_t check;
+
+    origDaddr = ntohl(iph->daddr);
+
+    iph->daddr = broadAddr->v4.s_addr;
+    newDaddr = ntohl(iph->daddr);
+
+    /* Re-calculate IP header checksum for new destination */
+    check = ntohs(iph->check);
+
+    check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
+    check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
+
+    /* Add carry */
+    check = check + (check >> 16);
+
+    iph->check = htons(check);
+
+    if (iph->protocol == SOL_UDP)
+    {
+      /* Re-calculate UDP/IP checksum for new destination */
+
+      int ipHeaderLen = GetIpHeaderLength(ipPacket);
+      struct udphdr* udph = (struct udphdr*) (ipPacket + ipHeaderLen);
+
+      /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
+
+      check = ntohs(udph->check);
+
+      check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
+      check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
+
+      /* Add carry */
+      check = check + (check >> 16);
+
+      udph->check = htons(check);
+     } /* if */
+  } /* if */
+} /* CheckAndUpdateLocalBroadcast */
+
+/* -------------------------------------------------------------------------
+ * Function   : AddMulticastRoute
+ * Description: Insert a route to all multicast addresses in the kernel
+ *              routing table. The route will be via the BMF network interface.
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+void AddMulticastRoute(void)
+{
+  struct rtentry kernel_route;
+  int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (ioctlSkfd < 0)
+  {
+    BmfPError("socket(PF_INET) error");
+    return;
+  }
+
+  memset(&kernel_route, 0, sizeof(struct rtentry));
+
+  ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
+
+  /* 224.0.0.0/4 */
+  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000);
+  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000);
+
+  kernel_route.rt_metric = 0;
+  kernel_route.rt_flags = RTF_UP;
+
+  kernel_route.rt_dev = EtherTunTapIfName;
+
+  if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0)
+  {
+    BmfPError("error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
+
+    /* Continue anyway */
+  }
+  close(ioctlSkfd);
+} /* AddMulticastRoute */
+
+/* -------------------------------------------------------------------------
+ * Function   : DeleteMulticastRoute
+ * Description: Delete the route to all multicast addresses from the kernel
+ *              routing table
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+void DeleteMulticastRoute(void)
+{
+  if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
+  {
+    struct rtentry kernel_route;
+    int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
+    if (ioctlSkfd < 0)
+    {
+      BmfPError("socket(PF_INET) error");
+      return;
+    }
+
+    memset(&kernel_route, 0, sizeof(struct rtentry));
+
+    ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
+    ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
+    ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
+
+    /* 224.0.0.0/4 */
+    ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000);
+    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000);
+
+    kernel_route.rt_metric = 0;
+    kernel_route.rt_flags = RTF_UP;
+
+    kernel_route.rt_dev = EtherTunTapIfName;
+
+    if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0)
+    {
+      BmfPError("error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
+
+      /* Continue anyway */
+    }
+    close(ioctlSkfd);
+  } /* if */
+} /* DeleteMulticastRoute */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/NetworkInterfaces.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,155 @@
+#ifndef _BMF_NETWORKINTERFACES_H
+#define _BMF_NETWORKINTERFACES_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+/* System includes */
+#include <netinet/in.h> /* struct in_addr */
+
+/* OLSR includes */
+#include "olsr_types.h" /* olsr_ip_addr */
+#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */
+
+/* Plugin includes */
+#include "Packet.h" /* IFHWADDRLEN */
+
+/* Size of buffer in which packets are received */
+#define BMF_BUFFER_SIZE 2048
+
+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;
+
+  /* File descriptor of UDP packet socket, used for listening to encapsulation packets.
+   * Used only when PlParam "BmfMechanism" is set to "UnicastPromiscuous". */
+  int listeningSkfd;
+
+  unsigned char macAddr[IFHWADDRLEN];
+
+  char ifName[IFNAMSIZ];
+
+  /* OLSRs idea of this network interface. NULL if this interface is not
+   * OLSR-enabled. */
+  struct interface* olsrIntf;
+
+  /* IP address of this network interface */
+  union olsr_ip_addr intAddr;
+
+  /* Broadcast address of this network interface */
+  union olsr_ip_addr 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;
+
+  /* Number of received and transmitted BMF packets on this interface */
+  u_int32_t nBmfPacketsRx;
+  u_int32_t nBmfPacketsRxDup;
+  u_int32_t nBmfPacketsTx;
+
+  /* Next element in list */
+  struct TBmfInterface* next; 
+};
+
+extern struct TBmfInterface* BmfInterfaces;
+
+extern int HighestSkfd;
+extern fd_set InputSet;
+
+extern int EtherTunTapFd;
+
+extern char EtherTunTapIfName[];
+
+/* 10.255.255.253 in host byte order */
+#define ETHERTUNTAPDEFAULTIP 0x0AFFFFFD
+
+extern u_int32_t EtherTunTapIp;
+extern u_int32_t EtherTunTapIpMask;
+extern u_int32_t EtherTunTapIpBroadcast;
+
+extern int CapturePacketsOnOlsrInterfaces;
+
+enum TBmfMechanism { BM_BROADCAST = 0, BM_UNICAST_PROMISCUOUS };
+extern enum TBmfMechanism BmfMechanism;
+
+int SetBmfInterfaceName(const char* ifname, void* data, set_plugin_parameter_addon addon);
+int SetBmfInterfaceIp(const char* ip, void* data, set_plugin_parameter_addon addon);
+int SetCapturePacketsOnOlsrInterfaces(const char* enable, void* data, set_plugin_parameter_addon addon);
+int SetBmfMechanism(const char* mechanism, void* data, set_plugin_parameter_addon addon);
+int DeactivateSpoofFilter(void);
+void RestoreSpoofFilter(void);
+
+#define MAX_UNICAST_NEIGHBORS 10
+struct TBestNeighbors
+{
+  struct link_entry* links[MAX_UNICAST_NEIGHBORS];
+};
+
+void FindNeighbors(
+  struct TBestNeighbors* neighbors,
+  struct link_entry** bestNeighbor,
+  struct TBmfInterface* intf,
+  union olsr_ip_addr* source,
+  union olsr_ip_addr* forwardedBy,
+  union olsr_ip_addr* forwardedTo,
+  int* nPossibleNeighbors);
+
+int CreateBmfNetworkInterfaces(struct interface* skipThisIntf);
+void AddInterface(struct interface* newIntf);
+void CloseBmfNetworkInterfaces(void);
+int AddNonOlsrBmfIf(const char* ifName, void* data, set_plugin_parameter_addon addon);
+int IsNonOlsrBmfIf(const char* ifName);
+void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr);
+void AddMulticastRoute(void);
+void DeleteMulticastRoute(void);
+
+#endif /* _BMF_NETWORKINTERFACES_H */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/olsrd_plugin.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,178 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+/* System includes */
+#include <assert.h> /* assert() */
+#include <stddef.h> /* NULL */
+
+/* OLSRD includes */
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+#include "defs.h" /* olsr_u8_t, olsr_cnf */
+#include "scheduler.h" /* olsr_start_timer() */
+
+/* BMF includes */
+#include "Bmf.h" /* InitBmf(), CloseBmf() */
+#include "PacketHistory.h" /* InitPacketHistory() */
+#include "NetworkInterfaces.h" /* AddNonOlsrBmfIf(), SetBmfInterfaceIp(), ... */
+#include "Address.h" /* DoLocalBroadcast() */
+
+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(void)
+{
+  return 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(void)
+{
+  /* 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_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
+                   &PrunePacketHistory, NULL, 0);
+
+
+  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(void)
+{
+  CloseBmf();
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "NonOlsrIf", .set_plugin_parameter = &AddNonOlsrBmfIf, .data = NULL },
+    { .name = "DoLocalBroadcast", .set_plugin_parameter = &DoLocalBroadcast, .data = NULL },
+    { .name = "BmfInterface", .set_plugin_parameter = &SetBmfInterfaceName, .data = NULL },
+    { .name = "BmfInterfaceIp", .set_plugin_parameter = &SetBmfInterfaceIp, .data = NULL },
+    { .name = "CapturePacketsOnOlsrInterfaces", .set_plugin_parameter = &SetCapturePacketsOnOlsrInterfaces, .data = NULL },
+    { .name = "BmfMechanism", .set_plugin_parameter = &SetBmfMechanism, .data = NULL },
+    { .name = "FanOutLimit", .set_plugin_parameter = &SetFanOutLimit, .data = NULL },
+    { .name = "BroadcastRetransmitCount", .set_plugin_parameter = &set_plugin_int, .data = &BroadcastRetransmitCount},
+};
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_get_plugin_parameters
+ * Description: Return the parameter table and its size
+ * Input      : none
+ * Output     : params - the parameter table
+ *              size - its size in no. of entries
+ * Return     : none
+ * Data Used  : plugin_parameters
+ * Notes      : Called by main OLSR (init_olsr_plugin) for all plugins
+ * ------------------------------------------------------------------------- */
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/* -------------------------------------------------------------------------
+ * 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(void)
+{
+  /* 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(void)
+{
+  olsr_plugin_exit();
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Packet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Packet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Packet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Packet.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,231 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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: IP packet and Ethernet frame processing functions
+ * Created    : 29 Jun 2006
+ *
+ * ------------------------------------------------------------------------- */
+
+#include "Packet.h"
+
+/* System includes */
+#include <stddef.h> /* NULL */
+#include <assert.h> /* assert() */
+#include <string.h> /* memcpy() */
+#include <sys/types.h> /* u_int8_t, u_int16_t, u_int32_t */
+#include <netinet/in.h> /* ntohs(), htons() */
+#include <netinet/ip.h> /* struct iphdr */
+
+/* -------------------------------------------------------------------------
+ * Function   : IsIpFragment
+ * Description: Check if an IP packet is an IP fragment
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : true (1) or false (0)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int IsIpFragment(unsigned char* ipPacket)
+{
+  struct ip* iph;
+
+  assert(ipPacket != NULL);
+
+  iph = (struct ip*) ipPacket;
+  if ((ntohs(iph->ip_off) & IP_OFFMASK) != 0)
+  {
+    return 1;
+  }
+  return 0;
+} /* IsIpFragment */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetIpTotalLength
+ * Description: Retrieve the total length of the IP packet (in bytes) of
+ *              an IP packet
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : IP packet length
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+u_int16_t GetIpTotalLength(unsigned char* ipPacket)
+{
+  struct iphdr* iph;
+
+  assert(ipPacket != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+  return ntohs(iph->tot_len);
+} /* GetIpTotalLength */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetIpHeaderLength
+ * Description: Retrieve the IP header length (in bytes) of an IP packet
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : IP header length
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+unsigned int GetIpHeaderLength(unsigned char* ipPacket)
+{
+  struct iphdr* iph;
+
+  assert(ipPacket != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+  return iph->ihl << 2;
+} /* GetIpHeaderLength */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetTtl
+ * Description: Retrieve the TTL (Time To Live) value from the IP header of
+ *              an IP packet
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : TTL value
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+u_int8_t GetTtl(unsigned char* ipPacket)
+{
+  struct iphdr* iph;
+
+  assert(ipPacket != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+  return iph->ttl;
+} /* GetTtl */
+
+/* -------------------------------------------------------------------------
+ * Function   : SaveTtlAndChecksum
+ * Description: Save the TTL (Time To Live) value and IP checksum as found in
+ *              the IP header of an IP packet
+ * Input      : ipPacket - the IP packet
+ * Output     : sttl - the TTL and checksum values
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+void SaveTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl)
+{
+  struct iphdr* iph;
+
+  assert(ipPacket != NULL && sttl != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+  sttl->ttl = iph->ttl;
+  sttl->check = ntohs(iph->check);
+} /* SaveTtlAndChecksum */
+
+/* -------------------------------------------------------------------------
+ * Function   : RestoreTtlAndChecksum
+ * Description: Restore the TTL (Time To Live) value and IP checksum in
+ *              the IP header of an IP packet
+ * Input      : ipPacket - the IP packet
+ *              sttl - the TTL and checksum values
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+void RestoreTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl)
+{
+  struct iphdr* iph;
+
+  assert(ipPacket != NULL && sttl != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+  iph->ttl = sttl->ttl;
+  iph->check = htons(sttl->check);
+} /* RestoreTtlAndChecksum */
+
+/* -------------------------------------------------------------------------
+ * Function   : DecreaseTtlAndUpdateHeaderChecksum
+ * Description: For an IP packet, decrement the TTL value and update the IP header
+ *              checksum accordingly.
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : See also RFC1141
+ * ------------------------------------------------------------------------- */
+void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* ipPacket)
+{
+  struct iphdr* iph;
+  u_int32_t sum;
+
+  assert(ipPacket != NULL);
+
+  iph = (struct iphdr*) ipPacket;
+
+  iph->ttl--; /* decrement ttl */
+  sum = ntohs(iph->check) + 0x100; /* increment checksum high byte */
+  iph->check = htons(sum + (sum>>16)); /* add carry */
+} /* DecreaseTtlAndUpdateHeaderChecksum */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetIpHeader
+ * Description: Retrieve the IP header from BMF encapsulation UDP data
+ * Input      : encapsulationUdpData - the encapsulation UDP data
+ * Output     : none
+ * Return     : IP header
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+struct ip* GetIpHeader(unsigned char* encapsulationUdpData)
+{
+  return (struct ip*)(encapsulationUdpData + ENCAP_HDR_LEN);
+} /* GetIpHeader */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetIpPacket
+ * Description: Retrieve the IP packet from BMF encapsulation UDP data
+ * Input      : encapsulationUdpData - the encapsulation UDP data
+ * Output     : none
+ * Return     : The IP packet
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+unsigned char* GetIpPacket(unsigned char* encapsulationUdpData)
+{
+  return encapsulationUdpData + ENCAP_HDR_LEN;
+} /* GetIpPacket */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetEncapsulationUdpDataLength
+ * Description: Return the length of BMF encapsulation UDP data
+ * Input      : encapsulationUdpData - the encapsulation UDP data
+ * Output     : none
+ * Return     : The encapsulation data length
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+u_int16_t GetEncapsulationUdpDataLength(unsigned char* encapsulationUdpData)
+{
+  return GetIpTotalLength(GetIpPacket(encapsulationUdpData)) + ENCAP_HDR_LEN;
+} /* GetEncapsulationUdpDataLength */
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Packet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Packet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/Packet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/Packet.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,81 @@
+#ifndef _BMF_PACKET_H
+#define _BMF_PACKET_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+/* System includes */
+#include <net/if.h> /* IFNAMSIZ, IFHWADDRLEN */
+#include <sys/types.h> /* u_int8_t, u_int16_t */
+
+/* BMF-encapsulated packets are Ethernet-IP-UDP packets, which start
+ * with a 8-bytes BMF header (struct TEncapHeader), followed by the
+ * encapsulated Ethernet-IP packet itself */
+
+struct TEncapHeader
+{
+  /* Use a standard Type-Length-Value (TLV) element */
+  u_int8_t type;
+  u_int8_t len;
+  u_int16_t reserved; /* Always 0 */
+  u_int32_t crc32;
+} __attribute__((__packed__));
+
+#define ENCAP_HDR_LEN ((int)sizeof(struct TEncapHeader))
+#define BMF_ENCAP_TYPE 1
+#define BMF_ENCAP_LEN 6
+
+struct TSaveTtl
+{
+  u_int8_t ttl;
+  u_int16_t check;
+} __attribute__((__packed__));
+
+int IsIpFragment(unsigned char* ipPacket);
+u_int16_t GetIpTotalLength(unsigned char* ipPacket);
+unsigned int GetIpHeaderLength(unsigned char* ipPacket);
+u_int8_t GetTtl(unsigned char* ipPacket);
+void SaveTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl);
+void RestoreTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl);
+void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* ipPacket);
+struct ip* GetIpHeader(unsigned char* encapsulationUdpData);
+unsigned char* GetIpPacket(unsigned char* encapsulationUdpData);
+u_int16_t GetEncapsulationUdpDataLength(unsigned char* encapsulationUdpData);
+
+#endif /* _BMF_PACKET_H */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/PacketHistory.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/PacketHistory.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/PacketHistory.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/PacketHistory.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,315 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+#include "PacketHistory.h"
+
+/* System includes */
+#include <stddef.h> /* NULL */
+#include <assert.h> /* assert() */
+#include <string.h> /* memset */
+#include <sys/types.h> /* u_int16_t, u_int32_t */
+#include <netinet/ip.h> /* struct iphdr */
+
+/* OLSRD includes */
+#include "defs.h" /* GET_TIMESTAMP, TIMED_OUT */
+#include "olsr.h" /* olsr_printf */
+
+/* Plugin includes */
+#include "Packet.h"
+
+static struct TDupEntry* PacketHistory[HISTORY_HASH_SIZE];
+
+#define CRC_UPTO_NBYTES 256
+
+#if 0
+/* -------------------------------------------------------------------------
+ * 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;
+} /* CalcCrcCcitt */
+#endif
+
+/* -------------------------------------------------------------------------
+ * 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;
+  } /* for */
+} /* GenerateCrc32Table */
+
+/* -------------------------------------------------------------------------
+ * 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++)
+  {
+    j = ((int) (crc & 0xFF) ^ *buffer++);
+    crc = (crc >> 8) ^ CrcTable[j];
+  }
+  return crc ^ 0xffffffffUL;
+} /* CalcCrc32 */
+
+/* -------------------------------------------------------------------------
+ * Function   : PacketCrc32
+ * Description: Calculates the CRC-32 value for an IP packet
+ * Input      : ipPacket - the IP packet
+ *              len - the number of octets in the IP packet
+ * Output     : none
+ * Return     : 32-bits CRC value
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+u_int32_t PacketCrc32(unsigned char* ipPacket, ssize_t len)
+{
+  struct TSaveTtl sttl;
+  struct ip* ipHeader;
+  u_int32_t result;
+
+  assert(ipPacket != NULL);
+
+  /* Skip TTL: in a multi-homed OLSR-network, the same multicast packet
+   * may enter the network multiple times, each copy differing only in its
+   * TTL value. BMF must not calculate a different CRC for packets that
+   * differ only in TTL. Skip also the IP-header checksum, because it changes
+   * along with TTL. Besides, it is not a good idea to calculate a CRC over
+   * data that already contains a checksum.
+   *
+   * Clip number of bytes over which CRC is calculated to prevent
+   * long packets from possibly claiming too much CPU resources. */
+  assert(len > 0);
+  if (len > CRC_UPTO_NBYTES)
+  {
+    len = CRC_UPTO_NBYTES;
+  }
+
+  SaveTtlAndChecksum(ipPacket, &sttl);
+
+  ipHeader = (struct ip*)ipPacket;
+  ipHeader->ip_ttl = 0xFF; /* fixed value of TTL for CRC-32 calculation */
+  ipHeader->ip_sum = 0x5A5A; /* fixed value of IP header checksum for CRC-32 calculation */
+
+  result = CalcCrc32(ipPacket, len);
+
+  RestoreTtlAndChecksum(ipPacket, &sttl);
+  return result;
+} /* PacketCrc32 */
+
+/* -------------------------------------------------------------------------
+ * Function   : Hash
+ * Description: Calculates a hash value from a 32-bit value
+ * Input      : from32 - 32-bit value
+ * Output     : none
+ * Return     : hash value
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+u_int32_t Hash(u_int32_t from32)
+{
+  return ((from32 >> N_HASH_BITS) + from32) & ((1 << N_HASH_BITS) - 1);
+} /* Hash */
+
+/* -------------------------------------------------------------------------
+ * Function   : InitPacketHistory
+ * Description: Initialize the packet history table and CRC-32 table
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : PacketHistory
+ * ------------------------------------------------------------------------- */
+void InitPacketHistory(void)
+{
+  int i;
+
+  GenerateCrc32Table();
+
+  for(i = 0; i < HISTORY_HASH_SIZE; i++)
+  {
+    PacketHistory[i] = NULL;
+  }
+} /* InitPacketHistory */
+
+/* -------------------------------------------------------------------------
+ * Function   : CheckAndMarkRecentPacket
+ * Description: Check if this packet was seen recently, then record the fact
+ *              that this packet was seen recently.
+ * Input      : crc32 - 32-bits crc value of the packet
+ * Output     : none
+ * Return     : not recently seen (0), recently seen (1)
+ * Data Used  : PacketHistory
+ * ------------------------------------------------------------------------- */
+int CheckAndMarkRecentPacket(u_int32_t crc32)
+{
+  u_int32_t index;
+  struct TDupEntry* walker;
+  struct TDupEntry* newEntry;
+
+  index = Hash(crc32);
+  assert(index < HISTORY_HASH_SIZE);
+
+  for (walker = PacketHistory[index]; walker != NULL; walker = walker->next)
+  {
+    if (walker->crc32 == crc32)
+    {
+      /* Found duplicate entry */
+
+      /* Always mark as "seen recently": refresh time-out */
+      walker->timeOut = GET_TIMESTAMP(HISTORY_HOLD_TIME);
+
+      return 1;
+    } /* if */
+  } /* for */
+
+  /* No duplicate entry found: create one */
+  newEntry = malloc(sizeof(struct TDupEntry));
+  if (newEntry != NULL)
+  {
+    newEntry->crc32 = crc32;
+    newEntry->timeOut = GET_TIMESTAMP(HISTORY_HOLD_TIME);
+
+    /* Add new entry at the front of the list */
+    newEntry->next = PacketHistory[index];
+    PacketHistory[index] = newEntry;
+  }
+
+  return 0;
+} /* CheckAndMarkRecentPacket */
+  
+/* -------------------------------------------------------------------------
+ * Function   : PrunePacketHistory
+ * Description: Prune the packet history table.
+ * Input      : useless - not used
+ * Output     : none
+ * Return     : none
+ * Data Used  : PacketHistory
+ * ------------------------------------------------------------------------- */
+void PrunePacketHistory(void* useless __attribute__((unused)))
+{
+  uint i;
+  for (i = 0; i < HISTORY_HASH_SIZE; i++)
+  {
+    if (PacketHistory[i] != NULL)
+    {
+      struct TDupEntry* nextEntry = PacketHistory[i];
+      struct TDupEntry* prevEntry = NULL;
+      while (nextEntry != NULL) 
+      {
+        struct TDupEntry* entry = nextEntry;
+        nextEntry = entry->next;
+
+        if (TIMED_OUT(entry->timeOut))
+        {
+          /* De-queue */
+          if (prevEntry != NULL)
+          {
+            prevEntry->next = entry->next;
+          }
+          else
+          {
+            PacketHistory[i] = entry->next;
+          } /* if */
+
+          /* De-allocate memory */
+          free(entry); 
+	      }
+	      else
+	      {
+	        prevEntry = entry;
+	      } /* if */
+      } /* while */
+    } /* if (PacketHistory[i] != NULL) */
+  } /* for (i = ...) */
+} /* PrunePacketHistory */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/PacketHistory.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/PacketHistory.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/src/PacketHistory.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/src/PacketHistory.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,68 @@
+#ifndef _BMF_PACKETHISTORY_H
+#define _BMF_PACKETHISTORY_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005 - 2007, 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
+ *
+ * ------------------------------------------------------------------------- */
+
+/* System includes */
+#include <sys/types.h> /* ssize_t */
+#include <sys/times.h> /* clock_t */
+
+#define N_HASH_BITS 12
+#define HISTORY_HASH_SIZE (1 << N_HASH_BITS)
+
+/* Time-out of duplicate entries, in milliseconds */
+#define HISTORY_HOLD_TIME 3000
+
+struct TDupEntry
+{
+  u_int32_t crc32;
+  clock_t timeOut;
+  struct TDupEntry* next;
+};
+
+void InitPacketHistory(void);
+u_int32_t PacketCrc32(unsigned char* ipPkt, ssize_t len);
+u_int32_t Hash(u_int32_t from32);
+void MarkRecentPacket(u_int32_t crc32);
+int CheckAndMarkRecentPacket(u_int32_t crc32);
+void PrunePacketHistory(void*);
+
+#endif /* _BMF_PACKETHISTORY_H */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/bmf/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/bmf/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,56 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_dot_draw
+PLUGIN_VER =	0.3
+
+TOPDIR =	../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/misc/olsr-topology-view.pl ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/misc/olsr-topology-view.pl
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/misc/olsr-topology-view.pl	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/misc/olsr-topology-view.pl	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,206 @@
+#!/usr/bin/perl
+
+# a hack to display OLSR topology information
+#
+# copyleft 2004 Bruno Randolf <br1@subnet.at>
+# licensed under the GPL
+
+use IO::Socket;
+use Getopt::Long;
+
+$TOPPATH = "/tmp";
+$NAME = "topology";
+$FILENAME = "$TOPPATH/$NAME.dot";
+$EXT = "png";
+$SERVER = "localhost";
+$PORT = "2004";
+$FULLSCREEN = 0;
+$HELP = 0;
+$KEEP = 0;
+$BGCOLOR = "black";
+$STYLE = 1;
+$SIZE = "8,8";
+$ROOTWIN = 0;
+$ONCE = 0;
+$GRAPH = 1;
+$SHOW = 1;
+$FONTNAME = "Courier";
+$FONTSIZE = 12;
+$LINEWIDTH = 0;
+$LINECOLOR = 0;
+$RESOLV = 0;
+
+GetOptions ("server=s" => \$SERVER,
+	    "port=s" => \$PORT,
+	    "fullscreen!" => \$FULLSCREEN,
+	    "help!" => \$HELP,
+	    "keep!" => \$KEEP,
+	    "bgcolor=s" => \$BGCOLOR,
+	    "fontname=s" => \$FONTNAME,
+	    "fontsize=s" => \$FONTSIZE,
+	    "style=i" => \$STYLE,
+	    "size=s" => \$SIZE,
+	    "rootwin!" => \$ROOTWIN,
+	    "once!" => \$ONCE,
+	    "graph!" => \$GRAPH,
+	    "show!" => \$SHOW,
+	    "linewidth!" => \$LINEWIDTH,
+	    "linecolor!" => \$LINECOLOR,
+	    "resolv" => \$RESOLV,
+	     );
+
+if ($HELP) {
+	print << "EOF";
+usage: $0 [ --server SERVER ] [--port PORT] [--fullscreen] [--keep]
+
+a hack to display OLSR topology information
+
+options:
+        --server SERVER    connect to OLSR node (default: localhost)
+        --port PORT        connect to port (default: 2004)
+        --bgcolor          background color (default: black)
+        --fontname         font name (default: Courier)
+        --fontsize         font size (default: 12)
+        --style            drawing style 1, 2 or 3 (default:1)
+        --size X,Y         image size in inches for graphviz (default: 8,8)
+        --[no]fullscreen   display fullscreen (default: off)
+        --[no]rootwin      display in root window (default: off)
+        --[no]graph        genereate graphics (default: on)
+        --[no]show         display the graphics (default: on)
+        --[no]once         run only 1 time, then exit (default: run forever)
+        --[no]linewith     change line width according to metric (default: off)
+        --[no]linecolor    change line color according to metric (default: off)
+        --[no]resolv       resolv hostnames (default: off)
+        --[no]keep         keep the .dot files with timestamp in /tmp (default: off)
+
+requires the "graphviz" and "imagemagick" packages installed
+and the "olsrd_dot_draw" plugin configured on the olsr node
+
+EOF
+	exit;
+}
+
+
+`touch $TOPPATH/$NAME.$EXT`;
+
+$remote = IO::Socket::INET->new(
+                        Proto    => "tcp",
+                        PeerAddr => $SERVER,
+                        PeerPort => $PORT,
+                    )
+                  or die "cannot connect to port $PORT at $SERVER!\nis the olsrd_dot_draw plugin loaded and configured to allow connections from this host?\n";
+
+$f;
+$start = 1;
+
+$FULLOPT = "-backdrop -background black" if $FULLSCREEN;
+
+if ($STYLE == 1) {
+	$DOT_CMD = "neato -Tpng -Gsize=${SIZE} -Gbgcolor=${BGCOLOR} -Gsplines=true -Nstyle=filled -Nfontname=${FONTNAME} -Nfontsize=${FONTSIZE} -Efontname=${FONTNAME} -Efontsize=${FONTSIZE} -Ncolor=white -Nfillcolor=white -Ecolor=grey -Elen=4 -Earrowsize=2 -Efontcolor=white $FILENAME -o $TOPPATH/$NAME.new";
+}
+elsif ($STYLE == 2) {
+	$BGCOLOR = "grey";
+	$DOT_CMD = "dot -Tpng -Gsize=${SIZE} -Elen=2 -Ncolor=grey -Nstyle=filled -Nfillcolor=white -Nfontname=${FONTNAME} -Nfontsize=${FONTSIZE} -Efontname=${FONTNAME} -Efontsize=${FONTSIZE} -Nfontcolor=red -Nwidth=1 -Gbgcolor=$BGCOLOR $FILENAME -o $TOPPATH/$NAME.new";
+}
+elsif ($STYLE == 3) {
+	$BGCOLOR = "\#ff6600";
+	$DOT_CMD = "neato -Tpng -Gsize=10,9 -Gbgcolor=${BGCOLOR} -Gsplines=true -Nstyle=filled -Nfontname=${FONTNAME} -Nfontsize=${FONTSIZE} -Efontname=${FONTNAME} -Efontsize=${FONTSIZE} -Nheight=1.3 -Nwidth=1.3 -Gsplines=true -Ncolor=darkslategrey -Nfillcolor=darkslategrey -Ecolor=black -Elen=4 -Earrowsize=3 $FILENAME -o $TOPPATH/$NAME.new";
+}
+
+
+while ( <$remote> ) 
+{
+	$line = $_;
+	if ($RESOLV) {
+		$line = resolv( $line );
+	}
+	if ($LINEWIDTH || $LINECOLOR) {
+		$line = draw_thicker_metric_lines( $line );
+	}
+	$f = $f . $line;
+
+	# end of one graph
+	if ( $line =~ /}/i ) { 
+		#print "* ";
+		open DOTFILE, ">$FILENAME";
+		print DOTFILE $f;
+		close DOTFILE;
+		$f = "";
+
+		if ($GRAPH) {
+			`$DOT_CMD`;
+			`mv $TOPPATH/$NAME.new $TOPPATH/$NAME.$EXT`;
+		}
+		if ($KEEP) {
+			`cp $TOPPATH/$NAME.dot $TOPPATH/$NAME-\$(date +'%Y-%m-%d-%H-%M-%S').dot`;
+		}
+		if ($SHOW) {
+			if ($ROOTWIN) {
+				system "display -window root -backdrop $TOPPATH/$NAME.$EXT &";
+			}
+			elsif ($start) {
+				system "display $FULLOPT -update 5 $TOPPATH/$NAME.$EXT &";
+				$start = 0;
+			}
+		}
+		exit if $ONCE;
+	}
+}
+
+print "connection closed\n";
+
+
+sub resolv {
+	my $l = shift;
+	if ( $l =~ /\"(.*)\" -> "([^[]*)"(.*)/) {
+		my $from = $1;
+		my $to = $2;
+		my $rest = $3;
+		$from =~ s/\"//g;
+		$to =~ s/\"//g;
+		my $iaddrf = inet_aton($from);
+		my $fromn  = gethostbyaddr($iaddrf, AF_INET);
+		my $iaddrt = inet_aton($to);
+		my $ton  = gethostbyaddr($iaddrt, AF_INET);
+		$fromn = $from if ! $fromn;
+		$ton = $to if ! $ton;
+		$l = "\"$fromn\" -> \"$ton\"$rest\n";
+	}
+	return $l;
+}
+
+
+sub draw_thicker_metric_lines { 
+	# sla 04.04.2005
+	# a hack to draws thicker lines for better metrics (the better the thicker).
+	# colorize the metric lines.
+	#
+	my $l = shift;
+	if ($l =~ /.*label="[0-9].*/){     # recognizion pattern
+		@n=split (/"/,$l);         # split the string to get the metric value
+		if ($LINECOLOR) {
+			if ( $n[5]>2 ) {        # colorize metrics greater than 2 gray            
+				$c="888888";
+			}
+			else {                     # colorize metrics less than 2 black
+				$c="000000";            
+			}
+			$setcol = "color=\"#$c\",";
+		}
+		if ($LINEWIDTH) {
+			if ($n[5]>0 && $n[5]<10) {  # thicker lines if 10 > metric > 0
+				$lt=6/$n[5];
+				$at=$lt/2;
+			}
+			else {                     # at least draw a thin line
+				$lt=1;
+				$at=$lt;
+			}
+			$setwidth = "style=\"setlinewidth($lt)\", arrowsize=$at";
+		}
+		$l =~ s/\]/, $setcol $setwidth]/g; # replace pattern
+	}
+	return $l;
+}
+
+__END__
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/README_DOT_DRAW ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/README_DOT_DRAW
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/README_DOT_DRAW	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/README_DOT_DRAW	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,37 @@
+DOT DATA GENERATION PLUGIN FOR OLSRD
+by Andreas Tønnesen(andreto@olsr.org)
+   Bruno Randolf
+
+02.06.05
+
+Added patch by Sebastian Hagen to fix FD leakage
+
+05.12.2004
+
+Various updates by Bruno Randolf has been applied to this
+plugin
+
+06.11.2004
+
+- Updated plugin interface version
+- Added plugin interface version function
+- Topology is generated upon every new connection
+
+29.06.2004
+
+ABOUT
+
+Note that this code is a quick hack done at the Wizards Of Oz 3
+
+The plugin generates output (over a TCP socket) in the dot format.
+The dot tool generates visual presentations of directed graphs.
+It can be downloaded as part of the GraphViz package from:
+http://www.graphviz.org/
+
+telet to 127.0.0.1 port 2004 to receive the data
+
+installation:
+make
+make install
+
+- Andreas T
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifdef _WRS_KERNEL
+#include <vxWorks.h>
+#include <sockLib.h>
+#include <wrn/coreip/netinet/in.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.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 <unistd.h>
+#include <errno.h>
+#include <stdarg.h>
+#endif
+
+#include "olsr.h"
+#include "ipcalc.h"
+#include "olsr_types.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "link_set.h"
+#include "socket_parser.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+
+#include "olsrd_dot_draw.h"
+#include "olsrd_plugin.h"
+
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+#endif
+
+#ifdef _WRS_KERNEL
+static int ipc_open;
+static int ipc_socket_up;
+#define DOT_DRAW_PORT 2004
+#endif
+
+static int ipc_socket;
+static int ipc_connection;
+
+/* IPC initialization function */
+static int
+plugin_ipc_init(void);
+
+/* Event function to register with the sceduler */
+static int
+pcf_event(int, int, int);
+
+static void
+ipc_action(int);
+
+static void
+ipc_print_neigh_link(const struct neighbor_entry *neighbor);
+
+static void
+ipc_print_tc_link(const struct tc_entry *, const struct tc_edge_entry *);
+
+static void
+ipc_print_net(const union olsr_ip_addr *, const union olsr_ip_addr *, olsr_u8_t);
+
+static void
+ipc_send(const char *, int);
+
+static void
+ipc_send_fmt(const char *format, ...) __attribute__((format(printf,1,2)));
+
+#define ipc_send_str(data) ipc_send((data), strlen(data))
+
+
+/**
+ *Do initialization here
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ */
+#ifdef _WRS_KERNEL
+int olsrd_dotdraw_init(void)
+#else
+int olsrd_plugin_init(void)
+#endif
+{
+  /* Initial IPC value */
+  ipc_socket = -1;
+  ipc_connection = -1;
+
+  /* Register the "ProcessChanges" function */
+  register_pcf(&pcf_event);
+
+  plugin_ipc_init();
+
+  return 1;
+}
+
+
+/**
+ * destructor - called at unload
+ */
+#ifdef _WRS_KERNEL
+void olsrd_dotdraw_exit(void)
+#else
+void olsr_plugin_exit(void)
+#endif
+{
+  if (ipc_connection != -1) {
+    CLOSE(ipc_connection);
+  }
+  if (ipc_socket != -1) {
+    CLOSE(ipc_socket);
+  }
+}
+
+
+static void
+ipc_print_neigh_link(const struct neighbor_entry *neighbor)
+{
+  struct ipaddr_str mainaddrstrbuf, strbuf;
+  olsr_linkcost etx = 0.0;
+  const char *style;
+  const char *adr = olsr_ip_to_string(&mainaddrstrbuf, &olsr_cnf->main_addr);
+  struct link_entry* link;
+  struct lqtextbuffer lqbuffer;
+  
+  if (neighbor->status == 0) { /* non SYM */
+    style = "dashed";
+  } else {   
+    link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
+    if (link) {
+      etx = link->linkcost;
+    }
+    style = "solid";
+  }
+    
+  ipc_send_fmt("\"%s\" -> \"%s\"[label=\"%s\", style=%s];\n",
+               adr,
+               olsr_ip_to_string(&strbuf, &neighbor->neighbor_main_addr),
+               get_linkcost_text(etx, OLSR_FALSE, &lqbuffer),
+               style);
+  
+  if (neighbor->is_mpr) {
+    ipc_send_fmt("\"%s\"[shape=box];\n", adr);
+  }
+}
+
+
+static int
+plugin_ipc_init(void)
+{
+  struct sockaddr_in sin;
+  olsr_u32_t yes = 1;
+
+  if (ipc_socket != -1) {
+    close(ipc_socket);
+  }
+
+  /* Init ipc socket */
+  ipc_socket = socket(AF_INET, SOCK_STREAM, 0);
+  if (ipc_socket == -1) {
+    olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
+    return 0;
+  }
+
+  if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
+    perror("SO_REUSEADDR failed");
+    CLOSE(ipc_socket);
+    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");
+    CLOSE(ipc_socket);
+    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) {
+    olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
+    CLOSE(ipc_socket);
+    return 0;
+  }
+      
+  /* show that we are willing to listen */
+  if (listen(ipc_socket, 1) == -1) {
+    olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
+    CLOSE(ipc_socket);
+    return 0;
+  }
+
+  /* Register with olsrd */
+#if 0
+  printf("Adding socket with olsrd\n");
+#endif
+  add_olsr_socket(ipc_socket, &ipc_action);
+
+  return 1;
+}
+
+
+static void
+ipc_action(int fd __attribute__((unused)))
+{
+  struct sockaddr_in pin;
+  socklen_t addrlen = sizeof(struct sockaddr_in);
+
+  if (ipc_connection != -1) {
+    close(ipc_connection);
+  }
+  
+  ipc_connection = accept(ipc_socket, (struct sockaddr *)&pin, &addrlen);
+  if (ipc_connection == -1) {
+    olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
+    return;
+  }
+#ifndef _WRS_KERNEL
+  if (!ip4equal(&pin.sin_addr, &ipc_accept_ip.v4)) {
+    olsr_printf(0, "Front end-connection from foreign host (%s) not allowed!\n", inet_ntoa(pin.sin_addr));
+    CLOSE(ipc_connection);
+    return;
+  }
+#endif
+  olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n", inet_ntoa(pin.sin_addr));
+  pcf_event(1, 1, 1);
+  close(ipc_connection); /* close connection after one output */
+}
+
+
+/**
+ *Scheduled event
+ */
+static int
+pcf_event(int changes_neighborhood,
+	  int changes_topology,
+	  int changes_hna)
+{
+  struct neighbor_entry *neighbor_table_tmp;
+  struct tc_entry *tc;
+  struct tc_edge_entry *tc_edge;
+  struct hna_entry *tmp_hna;
+  struct hna_net *tmp_net;
+  struct ip_prefix_list *hna;
+  int res = 0;
+
+  if (changes_neighborhood || changes_topology || changes_hna) {
+    
+    /* Print tables to IPC socket */
+    ipc_send_str("digraph topology\n{\n");
+
+    /* Neighbors */
+    OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp) {
+      ipc_print_neigh_link( neighbor_table_tmp );
+    } OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor_table_tmp);
+
+    /* Topology */  
+    OLSR_FOR_ALL_TC_ENTRIES(tc) {
+      OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+        if (tc_edge->edge_inv) {
+          ipc_print_tc_link(tc, tc_edge);
+        }
+      } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+    } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+
+    /* HNA entries */
+    OLSR_FOR_ALL_HNA_ENTRIES(tmp_hna) {
+
+      /* Check all networks */
+      for (tmp_net = tmp_hna->networks.next;
+           tmp_net != &tmp_hna->networks;
+           tmp_net = tmp_net->next) {
+        ipc_print_net(&tmp_hna->A_gateway_addr, 
+                      &tmp_net->A_network_addr, 
+                      tmp_net->prefixlen);
+      }
+    } OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
+
+    /* Local HNA entries */
+    for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
+      ipc_print_net(&olsr_cnf->main_addr,
+                    &hna->net.prefix,
+                    hna->net.prefix_len);
+    }
+    ipc_send_str("}\n\n");
+
+    res = 1;
+  }
+
+  if (ipc_socket == -1) {
+    plugin_ipc_init();
+  }
+  return res;
+}
+
+static void
+ipc_print_tc_link(const struct tc_entry *entry, const struct tc_edge_entry *dst_entry)
+{
+  struct ipaddr_str strbuf1, strbuf2;
+  struct lqtextbuffer lqbuffer;
+  
+  ipc_send_fmt("\"%s\" -> \"%s\"[label=\"%s\"];\n",
+               olsr_ip_to_string(&strbuf1, &entry->addr),
+               olsr_ip_to_string(&strbuf2, &dst_entry->T_dest_addr),
+               get_linkcost_text(dst_entry->cost, OLSR_FALSE, &lqbuffer));
+}
+
+
+static void
+ipc_print_net(const union olsr_ip_addr *gw, const union olsr_ip_addr *net, olsr_u8_t prefixlen)
+{
+  struct ipaddr_str gwbuf, netbuf;
+
+  ipc_send_fmt("\"%s\" -> \"%s/%d\"[label=\"HNA\"];\n",
+               olsr_ip_to_string(&gwbuf, gw),
+               olsr_ip_to_string(&netbuf, net),
+               prefixlen);
+
+  ipc_send_fmt("\"%s/%d\"[shape=diamond];\n",
+               olsr_ip_to_string(&netbuf, net),
+               prefixlen);
+}
+
+static void
+ipc_send(const char *data, int size)
+{
+  if (ipc_connection != -1) {
+#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__ || \
+defined _WRS_KERNEL
+#define FLAGS 0
+#else
+#define FLAGS MSG_NOSIGNAL
+#endif
+    if (send(ipc_connection, data, size, FLAGS) == -1) {
+      olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
+      CLOSE(ipc_connection);
+    }
+  }
+}
+
+static void
+ipc_send_fmt(const char *format, ...)
+{
+  if (ipc_connection != -1) {
+    char buf[4096];
+    int len;
+    va_list arg;
+    va_start(arg, format);
+    len = vsnprintf(buf, sizeof(buf), format, arg);
+    va_end(arg);
+    ipc_send(buf, len);
+  }
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/src/olsrd_dot_draw.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_DOT_DRAW
+#define _OLSRD_DOT_DRAW
+
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+
+extern union olsr_ip_addr ipc_accept_ip;
+extern int ipc_port;
+
+int olsrd_plugin_interface_version(void);
+int olsrd_plugin_init(void);
+void olsr_plugin_exit(void);
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/src/olsrd_plugin.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * 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 "olsr.h"
+#include "olsrd_plugin.h"
+#include "olsrd_dot_draw.h"
+
+
+#define PLUGIN_NAME    "OLSRD dot draw plugin"
+#define PLUGIN_VERSION "0.3"
+#define PLUGIN_AUTHOR   "Andreas Tønnesen"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+union olsr_ip_addr ipc_accept_ip;
+int ipc_port;
+
+static void my_init(void) __attribute__((constructor));
+static void my_fini(void) __attribute__((destructor));
+
+
+/**
+ *Constructor
+ */
+static void my_init(void)
+{
+    /* Print plugin info to stdout */
+    printf("%s\n", MOD_DESC);
+
+    /* defaults for parameters */
+    ipc_port = 2004;
+    ipc_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
+}
+
+
+/**
+ *Destructor
+ */
+static void my_fini(void)
+{
+    /* 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(void)
+{
+    return PLUGIN_INTERFACE_VERSION;
+}
+
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "port",   .set_plugin_parameter = &set_plugin_port,      .data = &ipc_port },
+    { .name = "accept", .set_plugin_parameter = &set_plugin_ipaddress, .data = &ipc_accept_ip },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dot_draw/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dot_draw/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,58 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_dyn_gw
+PLUGIN_VER =	0.4
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+LIBS +=		$(OS_LIB_PTHREAD)
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/README_DYN_GW ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/README_DYN_GW
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/README_DYN_GW	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/README_DYN_GW	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,84 @@
+DYNAMIC INTERNET GATEWAY PLUGIN FOR olsr.org olsrd
+by Andreas Tønnesen(andreto@olsr.org)
+addittions by Jens Nachitgall
+
+21.12.2004
+  bjoern Riemer
+- added universal hna checking
+  the plParams are parsed in spechial order, first the HNA parameter syntax: "net mask"
+  the following Ping parameter are only used for the previus HNA entry.
+  if there is no previus HNA entry then HNA "0.0.0.0 0.0.0.0" for internet GW is assumed
+
+30.11.2004
+
+  updates by Jens:
+
+- Upgraded to confirm with v2 plugin interface
+- removed IPC stuff
+- Removed much unnessecarry stuff
+- Added an optional validation based on the ping command, which caused
+  some internal restructuring, e.g. the dependency of a threading
+  library)
+- the config file accepts an "Interval", meaning how often the check is
+  done
+
+HOW TO USE
+
+Add an entry like this to your olsrd configuration file:
+
+LoadPlugin "olsrd_dyn_gw.so.0.4"
+{
+    # how often to look for a inet gw, in seconds
+    # defaults to 5 secs, if commented out
+    PlParam     "Interval"   "40"
+    
+    # if one or more IPv4 addresses are given, do a ping on these in
+    # descending order to validate that there is not only an entry in
+    # routing table, but also a real internet connection. If any of
+    # these addresses could be pinged successfully, the test was
+    # succesful, i.e. if the ping on the 1st address was successful,the
+    # 2nd won't be pinged
+    PlParam     "Ping"       "141.1.1.1"
+    PlParam     "Ping"       "194.25.2.129"
+    PlParam	"HNA"	"192.168.80.0 255.255.255.0"
+    PlParam	"HNA"	"192.168.81.0 255.255.255.0"
+    PlParam	"Ping"	"192.168.81.12"
+}
+
+
+ABOUT
+
+Plugin is IPv4 only and it only runs on Linux with the libpthread
+library installed!
+
+This is a plugin that checks if the local node has a Internet-
+connection. A Internet-connetion is identified by a "default gw" with a
+hopcount of 0. That is a route to 0.0.0.0/0 with metric 0.  By default
+the check is done every 5 secs. You can change the check interval by
+providing an value for "Interval" in the plugin's section of olsrd.conf.
+
+If one or more IPv4 addresses are given as values for "Ping" in the
+section or dyn_gw in olsrd.conf, then a test is done to validate if
+there is really an internet connection (and not just an entry in the
+routing table). If any of the arbitrary many given IPv4 addresses can be
+pinged, the validation was successful. The addresses are pinged in the
+order given in the olsrd.conf (i.e. the first given address is pinged
+first, the the 2nd, and so on). For this to work a command like 
+"ping -c 1 -q <PING-ADDRESS>" must be possible on the system olsrd runs
+on. The validation is based on the return value of this ping command.
+
+Since OLSR uses hopcount/metric on all routes this plugin will
+not respond to Internet gateways added by olsrd.
+
+When a Internet gateway is discovered - this node will start
+announcing 0.0.0.0/0 connectivity by HNA messages flooded into
+the OLSR network. If the route is removed the HNA messages
+will not be transmitted. This check is totally dynamic and
+Internet connectivity might come and go.
+
+This plugin will work very good with a automatic network cable
+detection daemon such as  netplug:
+http://freshmeat.net/projects/key-netplug/
+
+This plugin is a good example of using plugins for other stuff
+than packet transmission.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,525 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * -Threaded ping code added by Jens Nachtigall
+ * -HNA4 checking by bjoern riemer
+ */
+
+#include <arpa/inet.h>
+
+#include "olsr_types.h"
+#include "olsrd_dyn_gw.h"
+#include "olsr.h"
+#include "defs.h"
+#include "ipcalc.h"
+#include "scheduler.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <net/route.h>
+#ifdef linux
+#include <linux/in_route.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#ifndef WIN32
+#include <pthread.h>
+#else
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef interface
+
+#define close(x) closesocket(x)
+
+typedef HANDLE pthread_mutex_t;
+typedef HANDLE pthread_t;
+
+int pthread_create(HANDLE *Hand, void *Attr, void *(*Func)(void *), void *Arg);
+int pthread_kill(HANDLE Hand, int Sig);
+int pthread_mutex_init(HANDLE *Hand, void *Attr);
+int pthread_mutex_lock(HANDLE *Hand);
+int pthread_mutex_unlock(HANDLE *Hand);
+
+struct ThreadPara
+{
+  void *(*Func)(void *);
+  void *Arg;
+};
+#endif
+
+
+/* set default interval, in case none is given in the config file */
+static int check_interval = 5;
+
+/* list to store the Ping IP addresses given in the config file */
+struct ping_list {
+  char *ping_address;
+  struct ping_list *next;
+};
+
+static struct ping_list *
+add_to_ping_list(const char *, struct ping_list *);
+
+struct hna_list {
+  union olsr_ip_addr hna_net;
+  olsr_u8_t hna_prefixlen;
+  struct ping_list *ping_hosts;
+  int hna_added;
+  int probe_ok;
+  struct hna_list *next;
+};
+
+static struct hna_list *
+	add_to_hna_list(struct hna_list *,
+				union olsr_ip_addr *hna_net,
+				olsr_u8_t hna_prefixlen );
+
+struct hna_list *the_hna_list = NULL;
+
+static void
+looped_checks(void *) __attribute__((noreturn));
+
+static int
+check_gw(union olsr_ip_addr *, olsr_u8_t,struct ping_list *);
+
+static int
+ping_is_possible(struct ping_list *);
+
+/* Event function to register with the scheduler */
+static void
+olsr_event_doing_hna(void *);
+
+/**
+ * read config file parameters
+ */
+static int set_plugin_double(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    double d = 0.0;
+    sscanf(value, "%lf", &d);
+    if (data != NULL) {
+        double *v = data;
+        *v = d;
+        OLSR_PRINTF(1, "%s double %lf\n", "Got", d);
+    } else {
+        OLSR_PRINTF(0, "%s double %lf\n", "Ignored", d);
+    }
+    return 0;
+}
+
+static int set_plugin_ping(const char *value, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    union olsr_ip_addr foo_addr;
+
+    if (inet_pton(olsr_cnf->ip_version, value, &foo_addr) <= 0) {
+        OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
+        return 1;
+    }
+    /*if first ping without hna then assume inet gateway*/
+    if (the_hna_list == NULL){
+        union olsr_ip_addr temp_net;
+        union olsr_ip_addr temp_netmask;
+        temp_net.v4.s_addr = INET_NET;
+        temp_netmask.v4.s_addr = INET_PREFIX;
+        the_hna_list = add_to_hna_list(the_hna_list, &temp_net, olsr_netmask_to_prefix(&temp_netmask));
+        if (the_hna_list == NULL) {
+            return 1;
+        }
+    }
+    the_hna_list->ping_hosts = add_to_ping_list(value, the_hna_list->ping_hosts);
+    return 0;
+}
+
+static int set_plugin_hna(const char *value, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    union olsr_ip_addr temp_net;
+    union olsr_ip_addr temp_netmask;
+    char s_netaddr[128];
+    char s_mask[128];
+
+    //192.168.1.0  255.255.255.0
+    int i = sscanf(value,"%128s %128s", s_netaddr, s_mask);
+    if (i != 2) {
+        OLSR_PRINTF(0, "Cannot get IP address and netmask from \"%s\"", value);
+        return 1;
+    }
+
+    //printf("%s():i:%i; net:%s; mask:%s\n",__func__,i,s_netaddr,s_mask);
+    if (inet_pton(olsr_cnf->ip_version, s_netaddr, &temp_net) <= 0) {
+        OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_netaddr);
+        return 1;
+    }
+
+    //printf("GOT: %s(%08x)",inet_ntoa(foo_addr),foo_addr.s_addr);
+    if (inet_pton(olsr_cnf->ip_version, s_netaddr, &temp_netmask) <= 0) {
+        OLSR_PRINTF(0, "Illegal netmask \"%s\"", s_netaddr);
+        return 1;
+    }
+
+    //printf("/%s(%08x)\n",inet_ntoa(foo_addr),foo_addr.s_addr);
+    //printf("%s():got->%s/%s\n",__func__,olsr_ip_to_string((union olsr_ip_addr *)&));
+    the_hna_list = add_to_hna_list(the_hna_list, &temp_net, olsr_netmask_to_prefix(&temp_netmask));
+    if (the_hna_list != NULL) {
+        return 1;
+    }
+    return 0;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "interval", .set_plugin_parameter = &set_plugin_double, .data = &check_interval },
+    { .name = "ping",     .set_plugin_parameter = &set_plugin_ping,   .data = NULL },
+    { .name = "hna",      .set_plugin_parameter = &set_plugin_hna,    .data = NULL },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/**
+ *Do initialization here
+ * 
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ *It is ran _after_ register_olsr_param
+ */
+int
+olsrd_plugin_init(void)
+{
+  pthread_t ping_thread;
+  
+  //gw_net.v4 = INET_NET;
+  //gw_netmask.v4 = INET_PREFIX;
+
+  //gw_already_added = 0;
+  //has_available_gw = 0;
+
+  
+  /* Remove all local Inet HNA entries */
+  /*while(remove_local_hna4_entry(&gw_net, &gw_netmask))
+  {
+    olsr_printf(1, "HNA Internet gateway deleted\n");
+  }*/
+
+  pthread_create(&ping_thread, NULL, (void *(*)(void *))looped_checks, NULL);
+  
+  /* Register the GW check */
+  olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
+                   &olsr_event_doing_hna, NULL, 0);
+
+  return 1;
+}
+
+
+/**
+ * Scheduled event to update the hna table,
+ * called from olsrd main thread to keep the hna table thread-safe
+ */
+static void
+olsr_event_doing_hna(void *foo __attribute__((unused)))
+{
+	struct hna_list *li;
+	/*
+  if (has_available_gw == 1 && gw_already_added == 0) {
+    olsr_printf(1, "Adding OLSR local HNA entry for Internet\n");
+    add_local_hna_entry(&gw_net, &gw_netmask);
+    gw_already_added = 1;
+  } else if ((has_available_gw == 0) && (gw_already_added == 1)) {
+    // Remove all local Inet HNA entries /
+    while(remove_local_hna4_entry(&gw_net, &gw_netmask)) {
+      olsr_printf(1, "Removing OLSR local HNA entry for Internet\n");
+    }
+    gw_already_added = 0;
+  }
+	*/
+	for(li=the_hna_list; li; li=li->next){
+		if((li->probe_ok==1)&&(li->hna_added==0)){
+			olsr_printf(1, "Adding OLSR local HNA entry\n");
+			ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_net, li->hna_prefixlen);
+			li->hna_added=1;
+		}else if((li->probe_ok==0)&&(li->hna_added==1)){
+			while(ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_net, li->hna_prefixlen)) {
+				olsr_printf(1, "Removing OLSR local HNA entry\n");
+			}
+			li->hna_added=0;
+		}
+	}
+}
+
+
+
+/**
+ * the threaded function which happens within an endless loop,
+ * reiterated every "Interval" sec (as given in the config or 
+ * the default value)
+ */
+static void
+looped_checks(void *foo __attribute__((unused)))
+{
+  for(;;) {
+    struct hna_list *li;
+    struct timespec remainder_spec;
+    /* the time to wait in "Interval" sec (see connfig), default=5sec */
+    struct timespec sleeptime_spec  = { check_interval, 0L };
+
+    for(li = the_hna_list; li; li = li->next){
+      /* check for gw in table entry and if Ping IPs are given also do pings */
+      li->probe_ok = check_gw(&li->hna_net,li->hna_prefixlen,li->ping_hosts);
+      //has_available_gw = check_gw(&gw_net, &gw_netmask);
+    }
+
+    while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
+      sleeptime_spec = remainder_spec;
+  }
+  // return NULL;
+}
+
+
+
+static int
+check_gw(union olsr_ip_addr *net, olsr_u8_t prefixlen, struct ping_list *the_ping_list)
+{
+    char buf[1024], iface[16];
+    olsr_u32_t gate_addr, dest_addr, netmask;
+    unsigned int iflags;
+    int metric, refcnt, use;
+    int retval = 0;
+    union olsr_ip_addr mask;
+
+    FILE *fp = fopen(PROCENTRY_ROUTE, "r");
+    if (!fp) 
+      {
+        perror(PROCENTRY_ROUTE);
+        olsr_printf(1, "INET (IPv4) not configured in this system.\n");
+	return -1;
+      }    
+
+    olsr_prefix_to_netmask(&mask, prefixlen);
+    /*
+    olsr_printf(1, "Genmask         Destination     Gateway         "
+                "Flags Metric Ref    Use Iface\n");
+    */
+    while (fgets(buf, sizeof(buf), fp))
+      {	
+	int num = sscanf(buf, "%15s %128X %128X %X %d %d %d %128X \n",
+                         iface, &dest_addr, &gate_addr,
+                         &iflags, &refcnt, &use, &metric, &netmask);
+	if (num < 8)
+	    continue;
+
+	/*
+	olsr_printf(1, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&netmask));
+
+	olsr_printf(1, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&dest_addr));
+
+	olsr_printf(1, "%-15s %-6d %-2d %7d %s\n",
+		    olsr_ip_to_string((union olsr_ip_addr *)&gate_addr),
+		    metric, refcnt, use, iface);
+	*/
+
+        if( (iflags & RTF_UP) &&
+            (metric == 0) &&
+            (netmask == mask.v4.s_addr) && 
+            (dest_addr == net->v4.s_addr))
+          {
+            if ( ((mask.v4.s_addr == INET_PREFIX)&&(net->v4.s_addr == INET_NET))&&(!(iflags & RTF_GATEWAY)))
+              {
+                fclose(fp);  
+                return retval;
+              }
+            /* don't ping, if there was no "Ping" IP addr in the config file */
+            if (the_ping_list != NULL) {  
+              /*validate the found inet gw by pinging*/ 
+              if (ping_is_possible(the_ping_list)) {
+                olsr_printf(1, "HNA[%08x/%08x](ping is possible) VIA %s detected in routing table.\n", dest_addr,netmask,iface);
+                retval=1;      
+              }
+            } else {
+              olsr_printf(1, "HNA[%08x/%08x] VIA %s detected in routing table.\n", dest_addr,netmask,iface);
+              retval=1;      
+            }
+          }
+      }
+
+    fclose(fp);      
+    if(retval == 0){
+      /* And we cast here since we get warnings on Win32 */
+      olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)net->v4.s_addr, (unsigned int)mask.v4.s_addr);
+    }  
+    return retval;
+}
+
+static int
+ping_is_possible(struct ping_list *the_ping_list) 
+{
+  struct ping_list *list;
+  for(list = the_ping_list; list; list = list->next) {
+    char ping_command[50];
+    snprintf(ping_command, sizeof(ping_command), "ping -c 1 -q %s", list->ping_address);
+    olsr_printf(1, "\nDo ping on %s ...\n", list->ping_address);
+    if (system(ping_command) == 0) {
+      olsr_printf(1, "...OK\n\n");
+      return 1;      
+    }
+    olsr_printf(1, "...FAILED\n\n");
+  }
+  return 0;
+}
+
+/* add the valid IPs to the head of the list */
+static struct ping_list *
+add_to_ping_list(const char *ping_address, struct ping_list *the_ping_list)
+{
+  struct ping_list *new = malloc(sizeof(struct ping_list));
+  if(!new)
+  {
+    fprintf(stderr, "DYN GW: Out of memory!\n");
+    exit(0);
+  }
+  new->ping_address = strdup(ping_address);
+  new->next = the_ping_list;
+  return new;
+}    
+
+
+
+static struct hna_list *
+add_to_hna_list(struct hna_list * list_root, union olsr_ip_addr *hna_net, olsr_u8_t hna_prefixlen )
+{
+  struct hna_list *new = malloc(sizeof(struct hna_list));
+  if(new == NULL)
+  {
+    fprintf(stderr, "DYN GW: Out of memory!\n");
+    exit(0);
+  }
+  //memcpy(&new->hna_net,hna_net,sizeof(union hna_net));
+  //memcpy(&new->hna_netmask,hna_netmask,sizeof(union hna_netmask));
+  new->hna_net.v4=hna_net->v4;
+  new->hna_prefixlen=hna_prefixlen;
+  new->hna_added=0;
+  new->probe_ok=0;
+  new->ping_hosts=NULL;
+  new->next=list_root;  
+  return new;
+}
+
+#ifdef WIN32
+/*
+ * Windows ptread compat stuff
+ */
+static unsigned long __stdcall ThreadWrapper(void *Para)
+{
+  struct ThreadPara *Cast;
+  void *(*Func)(void *);
+  void *Arg;
+
+  Cast = (struct ThreadPara *)Para;
+
+  Func = Cast->Func;
+  Arg = Cast->Arg;
+  
+  HeapFree(GetProcessHeap(), 0, Para);
+
+  Func(Arg);
+
+  return 0;
+}
+
+int pthread_create(HANDLE *Hand, void *Attr __attribute__((unused)), void *(*Func)(void *), void *Arg)
+{
+  struct ThreadPara *Para;
+  unsigned long ThreadId;
+
+  Para = HeapAlloc(GetProcessHeap(), 0, sizeof (struct ThreadPara));
+
+  if (Para == NULL)
+    return -1;
+
+  Para->Func = Func;
+  Para->Arg = Arg;
+
+  *Hand = CreateThread(NULL, 0, ThreadWrapper, Para, 0, &ThreadId);
+
+  if (*Hand == NULL)
+    return -1;
+
+  return 0;
+}
+
+int pthread_kill(HANDLE Hand, int Sig __attribute__((unused)))
+{
+  if (!TerminateThread(Hand, 0))
+    return -1;
+
+  return 0;
+}
+
+int pthread_mutex_init(HANDLE *Hand, void *Attr __attribute__((unused)))
+{
+  *Hand = CreateMutex(NULL, FALSE, NULL);
+
+  if (*Hand == NULL)
+    return -1;
+
+  return 0;
+}
+
+int pthread_mutex_lock(HANDLE *Hand)
+{
+  if (WaitForSingleObject(*Hand, INFINITE) == WAIT_FAILED)
+    return -1;
+
+  return 0;
+}
+
+int pthread_mutex_unlock(HANDLE *Hand)
+{
+  if (!ReleaseMutex(*Hand))
+    return -1;
+
+  return 0;
+}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_dyn_gw.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,58 @@
+
+/*
+ * 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"
+
+#define INET_NET       0
+#define INET_PREFIX    0
+
+#define PROCENTRY_ROUTE "/proc/net/route"
+
+int olsrd_plugin_init(void);
+
+int olsrd_plugin_interface_version(void);
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/src/olsrd_plugin.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,80 @@
+
+/*
+ * 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 "olsrd_plugin.h"
+#include "olsrd_dyn_gw.h"
+#include <stdio.h>
+
+#define PLUGIN_NAME    "OLSRD dynamic gateway plugin"
+#define PLUGIN_VERSION "0.4"
+#define PLUGIN_AUTHOR   "Various artists"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+
+/**
+ * "Private" declarations
+ */
+
+static void my_init(void) __attribute__ ((constructor));
+
+
+/*
+ * Defines the version of the plugin interface that is used
+ * THIS IS NOT THE VERSION OF YOUR PLUGIN!
+ * Do not alter unless you know what you are doing!
+ */
+int 
+olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+
+/**
+ *Constructor
+ */
+void
+my_init(void)
+{
+  /* Print plugin info to stdout */
+  printf("%s\n", MOD_DESC);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,56 @@
+# 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.
+#
+
+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) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/README_DYN_GW_PLAIN ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/README_DYN_GW_PLAIN
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/README_DYN_GW_PLAIN	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/README_DYN_GW_PLAIN	2008-10-03 14:45:06.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2006, Sven-Ola Tuecke <sven-ola-aet-gmx.de>
+ * 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 "olsrd_dyn_gw_plain.h"
+#include "olsr_types.h"
+#include "ipcalc.h"
+#include "scheduler.h"
+#include "olsr.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <net/route.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define DEBUGLEV 1
+
+#define PLUGIN_INTERFACE_VERSION 5
+
+static int has_inet_gateway;
+
+/**
+ * Plugin interface version
+ * Used by main olsrd to check plugin interface version
+ */
+int 
+olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/**
+ * Initialize plugin
+ * Called after all parameters are passed
+ */
+int
+olsrd_plugin_init(void)
+{
+  printf("OLSRD dyn_gw_plain plugin by Sven-Ola\n");
+  
+  gw_net.v4.s_addr = INET_NET;
+  gw_netmask.v4.s_addr = INET_PREFIX;
+
+  has_inet_gateway = 0;
+  
+  /* Remove all local Inet HNA entries */
+  while(ip_prefix_list_remove(&olsr_cnf->hna_entries, &gw_net, olsr_netmask_to_prefix(&gw_netmask))) {
+    olsr_printf(DEBUGLEV, "HNA Internet gateway deleted\n");
+  }
+
+  /* Register the GW check */
+  olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
+                   &olsr_event, NULL, 0);
+
+  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.s_addr) && 
+	   (dest_addr == net->v4.s_addr))
+	  {
+            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 __attribute__((unused)))
+{
+  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");
+    ip_prefix_list_add(&olsr_cnf->hna_entries, &gw_net, olsr_netmask_to_prefix(&gw_netmask));
+    has_inet_gateway = 1;
+  }
+  else if (0 == res && 1 == has_inet_gateway) {
+    /* Remove all local Inet HNA entries */
+    while(ip_prefix_list_remove(&olsr_cnf->hna_entries, &gw_net, olsr_netmask_to_prefix(&gw_netmask))) {
+      olsr_printf(DEBUGLEV, "Removing OLSR local HNA entry for Internet\n");
+    }
+    has_inet_gateway = 0;
+  }
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/src/olsrd_dyn_gw_plain.h	2008-10-03 14:45:06.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/dyn_gw_plain/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/dyn_gw_plain/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_httpinfo
+PLUGIN_VER =	0.1
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+ifdef ADMIN_INTERFACE
+CPPFLAGS +=	-DADMIN_INTERFACE
+endif
+
+OBJS += $(TOPDIR)/src/cfgparser/cfgfile_gen.o
+
+default_target: $(PLUGIN_FULLNAME)
+ifdef ADMIN_INTERFACE
+		@echo 'WARNING - BUILT WITH EXPERIMENTAL ADMIN INTERFACE!'
+endif
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/README_HTTPINFO ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/README_HTTPINFO
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/README_HTTPINFO	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/README_HTTPINFO	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,82 @@
+HTTP MINI-SERVER PLUGIN FOR OLSRD 0.1
+by Andreas Tønnesen(andreto@olsr.org)
+
+-----------------------------------------------------
+
+ ABOUT
+
+This plugin implements a tiny HTTP server that
+will gespond to a GET request by returning a HTML
+formatted page contanin various information about
+the currently running olsrd process.
+This information includes detailed link status for
+all links and neighbors, all olsrd routes in the 
+kernel, local configuration, uptime and more. The
+plugin can also generate a olsrd configfile based
+on current running configuration.
+In adittion an experimental administrtion interface
+is available.
+
+-----------------------------------------------------
+
+ PARAMETERS
+
+The plugin takes the parameter "Port" "[portnumber]" 
+to set the TCP port on which the server is to run. 
+It defaults to 1978.
+Now remember to open this port in your firewall if 
+planning to access the HTTP server from a remote host!
+The parameter "Host" "[IP address]" is used to allow
+access from a single host(muliple such entries can
+be set) and the parameter "Net" "[IP net] [IP mask]"
+is used to allow access from entire net-ranges.
+To allow access from all hosts do:
+ PlParam   "Net" "0.0.0.0 0.0.0.0"
+
+A configuration example:
+LoadPlugin "olsrd_httpinfo.so.0.1"
+{
+    PlParam     "port"   "80"
+    PlParam     "Host"   "163.24.87.3"
+    PlParam     "Host"   "80.23.53.22"
+    PlParam     "Net"    "10.0.0.0 255.0.0.0"
+    PlParam     "Net"    "192.168.0.0 255.255.0.0"
+}
+
+This will run the webserver on port 80(the normal
+HTTP port) and allow access from the hosts 163.24.87.3
+and 80.23.53.22 and the networks 10.0.0.0/8 and
+192.168.0.0/16.
+access is always allowed from 127.0.0.1(localhost).
+
+-----------------------------------------------------
+
+ EXPERIMENTAL ADMIN INTERFACE
+
+The plugin can be compiled with a experimental 
+adminitrator interface. This is a web page that will
+let the user change olsrd settings in realtime.
+To compile with this feature pass ADMIN_INTERFACE=1
+as an argument to make(eg. make ADMIN_INTERFACE=1)
+
+-----------------------------------------------------
+
+NOTE!
+This plugin is very olsrd version sensitive. This means
+that to be sure everything woks as it is supposed to
+you should use the version of olsrd that the plugin 
+was shipped with. If using CVS you should check 
+out/update both olsrd and this plugin.
+
+The plugin should now compile on windows and FreeBSD
+as well.
+To compile in windows:
+make OS=win32
+to compile in FreeBSD:
+gmake OS=fbsd
+
+installation:
+make
+make install
+
+- Andreas T
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,415 @@
+
+/*
+ * HTTP Info plugin for the olsr.org OLSR daemon
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+
+#include "olsr.h"
+#include "olsrd_httpinfo.h"
+#include "olsr_cfg.h"
+#include "admin_interface.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if 0
+#define sprintf netsprintf
+#define NETDIRECT
+#endif
+
+static const char admin_basic_setting_int[] = "<td><strong>%s</strong></td><td><input type=\"text\" name=\"%s\" maxlength=\"%d\" class=\"input_text\" value=\"%d\"></td>\n";
+static const char admin_basic_setting_float[] = "<td><strong>%s</strong></td><td><input type=\"text\" name=\"%s\" maxlength=\"%d\" class=\"input_text\" value=\"%0.2f\"></td>\n";
+static const char admin_basic_setting_string[] = "<td><strong>%s</strong></td><td><input type=\"text\" name=\"%s\" maxlength=\"%d\" class=\"input_text\" value=\"%s\"></td>\n";
+
+static const char admin_frame_prolog[] =
+    "<strong>Administrator interface</strong><hr>\n"
+    "<h2>Change basic settings</h2>\n"
+    "<form action=\"set_values\" method=\"post\">\n"
+    "<table width=\"100%%\">\n";
+
+static const char admin_frame_mid[] =
+    "</table>\n<br>\n"
+    "<center><input type=\"submit\" value=\"Submit\" class=\"input_button\">\n"
+    "<input type=\"reset\" value=\"Reset\" class=\"input_button\"></center>\n"
+    "</form>\n"
+    "<h2>Add/remove local HNA entries</h2>\n"
+    "<form action=\"set_values\" method=\"post\">\n"
+    "<table width=\"100%%\"><tr><td><strong>Network:</strong></td>\n"
+    "<td><input type=\"text\" name=\"hna_new_net\" maxlength=\"16\" class=\"input_text\" value=\"0.0.0.0\"></td>\n"
+    "<td><strong>Netmask/Prefix:</strong></td>\n"
+    "<td><input type=\"text\" name=\"hna_new_netmask\" maxlength=\"16\" class=\"input_text\" value=\"0.0.0.0\"></td>\n"
+    "<td><input type=\"submit\" value=\"Add entry\" class=\"input_button\"></td></form>\n"
+    "</table><hr>\n"
+    "<form action=\"set_values\" method=\"post\">\n"
+    "<table width=\"100%%\">\n"
+  "<tr><th width=50 halign=\"middle\">Delete</th><th>Network</th><th>Netmask</th></tr>\n";
+
+static const char admin_frame_epilog[] =
+    "</table>\n<br>\n"
+    "<center><input type=\"submit\" value=\"Delete selected\" class=\"input_button\"></center>\n"
+    "</form>\n";
+
+int
+build_admin_body(char *buf, olsr_u32_t bufsize __attribute__((unused)))
+{
+  int size = 0;
+  size += snprintf(&buf[size], bufsize-size, admin_frame_prolog);
+
+  size += snprintf(&buf[size], bufsize-size, "<tr>\n");
+
+  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+		  "Debug level:", "debug_level", 2, olsr_cnf->debug_level);
+  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+		  "Pollrate:", "pollrate", 4, olsr_cnf->pollrate);
+  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_string,
+		  "TOS:", "tos", 6, "TBD");
+
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+                                             "<tr>\n");
+
+  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+		  "TC redundancy:", "tc_redundancy", 1, olsr_cnf->tc_redundancy);
+  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+		  "MPR coverage:", "mpr_coverage", 1, olsr_cnf->mpr_coverage);
+  size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+		  "Willingness:", "willingness", 1, olsr_cnf->willingness);
+
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+                                             "<tr>\n");
+
+  if(olsr_cnf->use_hysteresis) {
+    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+                     "Hyst scaling:", "hyst_scaling", 4, olsr_cnf->hysteresis_param.scaling);
+
+    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+                     "Lower thr:", "hyst_lower", 4, olsr_cnf->hysteresis_param.thr_low);
+    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+                     "Upper thr:", "hyst_upper", 4, olsr_cnf->hysteresis_param.thr_high);
+  } else {
+    size += snprintf(&buf[size], bufsize-size, "<td>Hysteresis disabled</td>\n");
+  }
+
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+                                             "<tr>\n");
+  
+  if(olsr_cnf->lq_level) {
+    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_int,
+                     "LQ level:", "lq_level", 1, olsr_cnf->lq_level);
+    size += snprintf(&buf[size], bufsize-size, admin_basic_setting_float,
+                     "LQ aging:", "lq_aging", 2, olsr_cnf->lq_aging);
+  } else {
+    size += snprintf(&buf[size], bufsize-size, "<td>LQ disabled</td>\n");
+  }
+
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n"
+                                             "<tr>\n");
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+  
+  size += snprintf(&buf[size], bufsize-size, admin_frame_mid);
+
+  if(olsr_cnf->hna_entries) {
+    struct ip_prefix_list *hna;
+    for(hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
+      struct ipaddr_str netbuf;
+      olsr_ip_to_string(&netbuf, &hna->net.prefix);
+      size += snprintf(&buf[size], bufsize-size,
+                       "<tr><td halign=\"middle\"><input type=\"checkbox\" name=\"del_hna%s*%d\" class=\"input_checkbox\"></td><td>%s</td><td>%d</td></tr>\n",
+                       netbuf.buf,
+                       hna->net.prefix_len,
+                       netbuf.buf,
+                       hna->net.prefix_len);
+    }
+  }
+  size += snprintf(&buf[size], bufsize-size, admin_frame_epilog);
+  return size;
+}
+
+
+#ifdef ADMIN_INTERFACE
+
+int
+process_param(char *key, char *value)
+{
+  static union olsr_ip_addr curr_hna_net;
+  static olsr_bool curr_hna_ok = OLSR_FALSE;
+
+  if(!strcmp(key, "debug_level"))
+    {
+      int ival = atoi(value);
+      if((ival < 0) || (ival > 9))
+	return -1;
+
+      olsr_cnf->debug_level = ival;
+      return 1;
+    }
+
+  if(!strcmp(key, "tc_redundancy"))
+    {
+      int ival = atoi(value);
+      if((ival < 0) || (ival > 3))
+	return -1;
+
+      olsr_cnf->tc_redundancy = ival;
+      return 1;
+    }
+
+  if(!strcmp(key, "mpr_coverage"))
+    {
+      int ival = atoi(value);
+      if(ival < 0)
+	return -1;
+
+      olsr_cnf->mpr_coverage = ival;
+      return 1;
+    }
+
+  if(!strcmp(key, "willingness"))
+    {
+      int ival = atoi(value);
+      if((ival < 0) || (ival > 7))
+	return -1;
+
+      olsr_cnf->willingness = ival;
+      return 1;
+    }
+
+  if(!strcmp(key, "lq_level"))
+    {
+      int ival = atoi(value);
+      if((ival < 0) || (ival > 2))
+	return -1;
+
+      olsr_cnf->lq_level = ival;
+      return 1;
+    }
+
+  if(!strcmp(key, "lq_wsize"))
+    {
+      int ival = atoi(value);
+      if((ival < 0) || (ival > 10))
+	return -1;
+
+      olsr_cnf->lq_wsize = ival;
+      return 1;
+    }
+
+  if(!strcmp(key, "hyst_scaling"))
+    {
+      float fval = 1.1;
+      sscanf(value, "%f", &fval);
+      if((fval < 0.0) || (fval > 1.0))
+	return -1;
+
+      olsr_cnf->hysteresis_param.scaling = fval;
+      return 1;
+    }
+
+  if(!strcmp(key, "hyst_scaling"))
+    {
+      float fval = 1.1;
+      sscanf(value, "%f", &fval);
+      if((fval < 0.0) || (fval > 1.0))
+	return -1;
+
+      olsr_cnf->hysteresis_param.scaling = fval;
+      return 1;
+    }
+
+  if(!strcmp(key, "hyst_lower"))
+    {
+      float fval = 1.1;
+      sscanf(value, "%f", &fval);
+      if((fval < 0.0) || (fval > 1.0))
+	return -1;
+
+      olsr_cnf->hysteresis_param.thr_low = fval;
+      return 1;
+    }
+
+  if(!strcmp(key, "hyst_upper"))
+    {
+      float fval = 1.1;
+      sscanf(value, "%f", &fval);
+      if((fval < 0.0) || (fval > 1.0))
+	return -1;
+
+      olsr_cnf->hysteresis_param.thr_high = fval;
+      return 1;
+    }
+
+  if(!strcmp(key, "pollrate"))
+    {
+      float fval = 1.1;
+      sscanf(value, "%f", &fval);
+      if((fval < 0.0) || (fval > 1.0))
+	return -1;
+
+      olsr_cnf->pollrate = fval;
+      return 1;
+    }
+
+
+  if(!strcmp(key, "hna_new_net"))
+    {
+      if(inet_pton(olsr_cnf->ipsize, value, &curr_hna_net.v4) == 0)
+	{
+	  fprintf(stderr, "Failed converting new HNA net %s\n", value);
+	  return -1;
+	}
+      curr_hna_ok = OLSR_TRUE;
+      return 1;
+    }
+
+  if(!strcmp(key, "hna_new_netmask"))
+    {
+      struct in_addr in;
+      olsr_u8_t prefixlen;
+
+      if(!curr_hna_ok)
+	return -1;
+
+      curr_hna_ok = OLSR_FALSE;
+
+      if(inet_aton(value, &in) == 0) {
+        fprintf(stderr, "Failed converting new HNA netmask %s\n", value);
+        return -1;
+      }
+      prefixlen = netmask_to_prefix((olsr_u8_t *)&in, olsr_cnf->ipsize);
+      if(prefixlen == UCHAR_MAX) {
+        fprintf(stderr, "Failed converting new HNA netmask %s\n", value);
+        return -1;
+      }
+      ip_prefix_list_add(&olsr_cnf->hna_entries, &curr_hna_net, prefixlen);
+      return 1;
+    }
+
+  if(!strncmp(key, "del_hna", 7) && !strcmp(value, "on"))
+    {
+      struct in_addr net, mask;
+      char ip_net[16], ip_mask[16];
+      int seperator = 0;
+      olsr_u8_t prefixlen;
+
+      while(key[7 + seperator] != '*') {
+	seperator++;
+      }
+      memcpy(ip_net, &key[7], seperator);
+      ip_net[seperator] = 0;
+      memcpy(ip_mask, &key[7 + seperator + 1], 16);
+      olsr_printf(1, "Deleting HNA %s/%s\n", ip_net, ip_mask);
+
+      if(inet_aton(ip_net, &net) == 0)
+	{
+	  fprintf(stderr, "Failed converting HNA net %s for deletion\n", ip_net);
+	  return -1;
+	}
+
+      if(inet_aton(ip_mask, &mask) == 0) {
+        fprintf(stderr, "Failed converting HNA netmask %s for deletion\n", ip_mask);
+        return -1;
+      }
+      prefixlen = netmask_to_prefix((olsr_u8_t *)&mask, olsr_cnf->ipsize);
+      if(prefixlen == UCHAR_MAX) {
+        fprintf(stderr, "Failed converting new HNA netmask %s\n", value);
+        return -1;
+      }
+      ip_prefix_list_add(&olsr_cnf->hna_entries, &curr_hna_net, prefixlen);
+      return 1;
+    }
+
+  return 0;
+#if 0
+  { 1, admin_basic_setting_string, "TOS:", "tos", 6, "TBD" },
+#endif
+}
+
+int
+process_set_values(char *data, olsr_u32_t data_size, char *buf, olsr_u32_t bufsize __attribute__((unused)))
+{
+  int size = 0;
+  int val_start, key_start;
+  olsr_u32_t i;
+
+  size += sprintf(buf, "<html>\n<head><title>olsr.org httpinfo plugin</title></head>\n<body>\n");
+
+  key_start = 0;
+  val_start = 0;
+
+  for(i = 0; i < data_size; i++)
+    {
+      if(data[i] == '=')
+	{
+	  data[i] = '\0';
+	  val_start = i + 1;
+	}
+
+      if(data[i] == '&')
+	{
+	  data[i] = '\0';
+	  if(!process_param(&data[key_start], &data[val_start]))
+	    {
+	      size += snprintf(&buf[size], bufsize-size, "<h2>FAILED PROCESSING!</h2><br>Key: %s Value: %s<br>\n", 
+			      &data[key_start], &data[val_start]);
+	      return -1;
+	    }
+
+	  key_start = i + 1;
+	}
+    }  
+
+  if(!process_param(&data[key_start], &data[val_start]))
+    {
+      size += snprintf(&buf[size], bufsize-size, "<b>FAILED PROCESSING!</b><br>Key: %s Value: %s<br>\n", 
+		      &data[key_start], &data[val_start]);
+      return -1;
+    }
+
+  size += snprintf(&buf[size], bufsize-size, "<h2>UPDATE SUCESSFULL!</h2><br>Press BACK and RELOAD in your browser to return to the plugin<br>\n</body>\n</html>\n");
+  size += snprintf(&buf[size], bufsize-size, "\n</body>\n</html>\n");
+
+  return size;
+}
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/admin_interface.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * HTTP Info plugin for the olsr.org OLSR daemon
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef ADMIN_INTERFACE_H
+#define ADMIN_INTERFACE_H
+
+int
+build_admin_body(char *, olsr_u32_t);
+
+int
+process_set_values(char*, olsr_u32_t, char *, olsr_u32_t);
+
+int
+process_param(char *, char *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/gfx.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/gfx.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/gfx.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/gfx.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,418 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _GFX_H
+#define _GFX_H
+
+
+
+
+static unsigned char favicon_ico[] = {
+  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x68, 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x31, 0x73,
+  0xde, 0x00, 0x42, 0xff, 0xff, 0x00, 0x52, 0x52, 0x52, 0x00, 0xad, 0xad,
+  0xad, 0x00, 0x21, 0x21, 0x9c, 0x00, 0x9c, 0xef, 0xff, 0x00, 0x39, 0xb5,
+  0xff, 0x00, 0x29, 0x29, 0x29, 0x00, 0xd6, 0xd6, 0xd6, 0x00, 0x7b, 0x7b,
+  0x7b, 0x00, 0x29, 0x31, 0xce, 0x00, 0xc6, 0xff, 0xff, 0x00, 0x94, 0x94,
+  0x94, 0x00, 0xc6, 0xbd, 0xbd, 0x00, 0x29, 0x52, 0xce, 0x00, 0x94, 0xa5,
+  0xbd, 0x00, 0x7b, 0x84, 0x9c, 0x00, 0x52, 0x63, 0x6b, 0x00, 0x29, 0xce,
+  0xff, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe7, 0xe7, 0xe7, 0x00, 0x39, 0x39,
+  0x39, 0x00, 0x31, 0x9c, 0xf7, 0x00, 0x6b, 0x6b, 0x6b, 0x00, 0x4a, 0xe7,
+  0xff, 0x00, 0x42, 0xce, 0xff, 0x00, 0x8c, 0xf7, 0xff, 0x00, 0x31, 0xb5,
+  0xef, 0x00, 0xb5, 0xff, 0xff, 0x00, 0x84, 0x84, 0x84, 0x00, 0x08, 0x08,
+  0x08, 0x00, 0x10, 0x10, 0x10, 0x00, 0xf7, 0xf7, 0xf7, 0x00, 0xef, 0xef,
+  0xef, 0x00, 0x31, 0x31, 0x31, 0x00, 0xde, 0xde, 0xde, 0x00, 0x4a, 0x4a,
+  0x4a, 0x00, 0xce, 0xce, 0xce, 0x00, 0x5a, 0x5a, 0x5a, 0x00, 0xb5, 0xb5,
+  0xb5, 0x00, 0x73, 0x73, 0x73, 0x00, 0xa5, 0xa5, 0xa5, 0x00, 0x9c, 0x9c,
+  0x9c, 0x00, 0x8c, 0x8c, 0x8c, 0x00, 0xc6, 0xc6, 0xc6, 0x00, 0x29, 0x4a,
+  0xc6, 0x00, 0x29, 0x5a, 0xd6, 0x00, 0xe7, 0xde, 0xde, 0x00, 0xbd, 0xbd,
+  0xbd, 0x00, 0xf7, 0xff, 0xff, 0x00, 0x73, 0x6b, 0x6b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x18, 0x02, 0x0c, 0x05, 0x25, 0x25, 0x30, 0x10, 0x2f, 0x06, 0x12,
+  0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1a, 0x1b, 0x13, 0x2a, 0x34, 0x1e,
+  0x0d, 0x07, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x2d,
+  0x0e, 0x2b, 0x0e, 0x2a, 0x19, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x05, 0x32, 0x2e, 0x27, 0x2e, 0x32, 0x2b, 0x2d, 0x2a, 0x2a, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x09, 0x25, 0x00, 0x26, 0x00, 0x0b,
+  0x1f, 0x2d, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x0a, 0x00,
+  0x26, 0x16, 0x00, 0x2d, 0x00, 0x2c, 0x2d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x27, 0x24, 0x23, 0x26, 0x22, 0x00, 0x0e, 0x00, 0x05, 0x04, 0x24,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x16, 0x22, 0x22, 0x22, 0x22, 0x16,
+  0x0a, 0x32, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22,
+  0x22, 0x01, 0x22, 0x23, 0x25, 0x24, 0x21, 0x15, 0x00, 0x00, 0x00, 0x00,
+  0x20, 0x17, 0x17, 0x2c, 0x32, 0x03, 0x14, 0x33, 0x09, 0x00, 0x21, 0x04,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0a, 0x0a, 0x31, 0x0f, 0x22, 0x16,
+  0x27, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x28, 0x16, 0x23,
+  0x16, 0x28, 0x19, 0x22, 0x16, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x19, 0x01, 0x01, 0x01, 0x32, 0x27, 0x01, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x29, 0x2d, 0x0b, 0x19,
+  0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2c, 0x05, 0x1f, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xf0, 0x0f,
+  0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x03,
+  0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x03,
+  0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xfc, 0x3f,
+  0x00, 0x00
+};
+
+
+static unsigned char logo_gif[] = {
+  0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x50, 0x00, 0x50, 0x00, 0xf7, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x84, 0x10, 0x18, 0x7b, 0x10,
+  0x18, 0x7b, 0x42, 0x4a, 0x84, 0x84, 0x94, 0x5a, 0x5a, 0x63, 0x7b, 0x7b,
+  0x84, 0x6b, 0x6b, 0x73, 0x84, 0x84, 0x8c, 0x94, 0x94, 0x9c, 0xbd, 0xbd,
+  0xc6, 0xb5, 0xb5, 0xbd, 0xde, 0xde, 0xe7, 0xc6, 0xc6, 0xce, 0xe7, 0xe7,
+  0xef, 0x39, 0x42, 0x4a, 0x5a, 0x63, 0x63, 0x52, 0x5a, 0x5a, 0xd6, 0xde,
+  0xde, 0xa5, 0xad, 0x73, 0xff, 0xff, 0x42, 0xff, 0xff, 0x4a, 0xff, 0xff,
+  0x52, 0xff, 0xff, 0x63, 0xff, 0xff, 0x7b, 0xde, 0xde, 0x73, 0xff, 0xff,
+  0x94, 0xff, 0xff, 0x9c, 0xa5, 0xa5, 0x6b, 0x7b, 0x7b, 0x52, 0xde, 0xde,
+  0x9c, 0xff, 0xff, 0xb5, 0xff, 0xff, 0xc6, 0x73, 0x73, 0x5a, 0xef, 0xef,
+  0xbd, 0xd6, 0xd6, 0xad, 0x7b, 0x7b, 0x63, 0x84, 0x84, 0x6b, 0xde, 0xde,
+  0xb5, 0xe7, 0xe7, 0xbd, 0xef, 0xef, 0xc6, 0xf7, 0xf7, 0xce, 0xa5, 0xa5,
+  0x8c, 0xad, 0xad, 0x94, 0x7b, 0x7b, 0x6b, 0xde, 0xde, 0xc6, 0xc6, 0xc6,
+  0xb5, 0x73, 0x73, 0x6b, 0xf7, 0xf7, 0xe7, 0x9c, 0x9c, 0x94, 0xff, 0xff,
+  0xf7, 0xff, 0xf7, 0x31, 0xff, 0xf7, 0x4a, 0xef, 0xe7, 0x6b, 0xff, 0xf7,
+  0x73, 0xff, 0xef, 0x29, 0xff, 0xef, 0x39, 0xff, 0xf7, 0x8c, 0xff, 0xef,
+  0x6b, 0xd6, 0xce, 0x7b, 0xff, 0xf7, 0xad, 0xff, 0xf7, 0xb5, 0xff, 0xe7,
+  0x31, 0xff, 0xe7, 0x39, 0xff, 0xe7, 0x42, 0xff, 0xe7, 0x4a, 0xff, 0xef,
+  0x73, 0xff, 0xef, 0x7b, 0xff, 0xf7, 0xbd, 0xf7, 0xde, 0x42, 0xe7, 0xce,
+  0x42, 0xf7, 0xde, 0x4a, 0xff, 0xe7, 0x5a, 0xbd, 0xad, 0x52, 0xf7, 0xe7,
+  0x8c, 0xd6, 0xce, 0x9c, 0xef, 0xce, 0x29, 0xe7, 0xce, 0x5a, 0xf7, 0xe7,
+  0x94, 0xff, 0xef, 0x9c, 0xff, 0xd6, 0x21, 0xff, 0xd6, 0x31, 0xce, 0xb5,
+  0x4a, 0xa5, 0x94, 0x4a, 0x9c, 0x94, 0x73, 0xff, 0xd6, 0x39, 0xf7, 0xde,
+  0x84, 0xff, 0xce, 0x29, 0xf7, 0xc6, 0x31, 0xf7, 0xce, 0x4a, 0xff, 0xd6,
+  0x52, 0xd6, 0xb5, 0x4a, 0xf7, 0xd6, 0x6b, 0xff, 0xe7, 0x9c, 0x73, 0x6b,
+  0x52, 0xff, 0xce, 0x42, 0xff, 0xe7, 0xa5, 0xe7, 0xde, 0xc6, 0xd6, 0xbd,
+  0x7b, 0xef, 0xde, 0xb5, 0xe7, 0xad, 0x29, 0xef, 0xb5, 0x31, 0xef, 0xb5,
+  0x39, 0xef, 0xc6, 0x6b, 0x6b, 0x63, 0x52, 0xff, 0xb5, 0x21, 0xf7, 0xb5,
+  0x31, 0xef, 0xbd, 0x5a, 0xde, 0xb5, 0x63, 0xef, 0xc6, 0x73, 0xef, 0xad,
+  0x39, 0xbd, 0x94, 0x4a, 0xef, 0xc6, 0x7b, 0xff, 0xad, 0x29, 0xef, 0xa5,
+  0x31, 0xff, 0xb5, 0x39, 0xf7, 0xb5, 0x4a, 0xef, 0xb5, 0x52, 0xef, 0xa5,
+  0x39, 0xf7, 0xa5, 0x31, 0xbd, 0xa5, 0x84, 0xde, 0xc6, 0xa5, 0xde, 0x8c,
+  0x29, 0xf7, 0x9c, 0x31, 0xef, 0x9c, 0x39, 0xd6, 0x84, 0x29, 0xe7, 0x8c,
+  0x31, 0xf7, 0x9c, 0x42, 0xd6, 0x8c, 0x42, 0xc6, 0x8c, 0x52, 0xde, 0xce,
+  0xbd, 0x73, 0x6b, 0x63, 0x7b, 0x73, 0x6b, 0xef, 0x8c, 0x31, 0xf7, 0x8c,
+  0x31, 0xce, 0x73, 0x29, 0xe7, 0x84, 0x31, 0xde, 0x84, 0x39, 0xce, 0x94,
+  0x63, 0xde, 0x7b, 0x31, 0xce, 0x7b, 0x42, 0xbd, 0xa5, 0x94, 0xde, 0x73,
+  0x31, 0x7b, 0x52, 0x39, 0xb5, 0x8c, 0x73, 0xbd, 0x5a, 0x21, 0xde, 0x6b,
+  0x29, 0xc6, 0x63, 0x29, 0xc6, 0x6b, 0x39, 0xef, 0x73, 0x31, 0xd6, 0x6b,
+  0x31, 0xe7, 0x73, 0x39, 0xe7, 0x63, 0x29, 0x6b, 0x5a, 0x52, 0xd6, 0x5a,
+  0x29, 0xc6, 0x63, 0x39, 0xce, 0x6b, 0x42, 0xb5, 0x4a, 0x21, 0x9c, 0x84,
+  0x7b, 0xce, 0x52, 0x29, 0xbd, 0x42, 0x21, 0xb5, 0x42, 0x21, 0xc6, 0x5a,
+  0x39, 0xd6, 0x4a, 0x29, 0xc6, 0x4a, 0x29, 0xad, 0x84, 0x7b, 0xa5, 0x31,
+  0x21, 0xb5, 0x4a, 0x39, 0xb5, 0x31, 0x21, 0xad, 0x31, 0x21, 0xa5, 0x5a,
+  0x52, 0xad, 0x6b, 0x63, 0x9c, 0x39, 0x31, 0xa5, 0x42, 0x39, 0xad, 0x4a,
+  0x42, 0xce, 0x31, 0x29, 0x9c, 0x21, 0x21, 0x94, 0x31, 0x31, 0x8c, 0x31,
+  0x31, 0x84, 0x31, 0x31, 0xa5, 0x52, 0x52, 0x94, 0x63, 0x63, 0x94, 0x73,
+  0x73, 0xa5, 0x94, 0x94, 0xc6, 0xbd, 0xbd, 0xd6, 0xce, 0xce, 0xf7, 0xf7,
+  0xf7, 0xef, 0xef, 0xef, 0xe7, 0xe7, 0xe7, 0xde, 0xde, 0xde, 0xd6, 0xd6,
+  0xd6, 0xce, 0xce, 0xce, 0xc6, 0xc6, 0xc6, 0xbd, 0xbd, 0xbd, 0xb5, 0xb5,
+  0xb5, 0xad, 0xad, 0xad, 0xa5, 0xa5, 0xa5, 0x9c, 0x9c, 0x9c, 0x94, 0x94,
+  0x94, 0x8c, 0x8c, 0x8c, 0x84, 0x84, 0x84, 0x7b, 0x7b, 0x7b, 0x73, 0x73,
+  0x73, 0x6b, 0x6b, 0x6b, 0x63, 0x63, 0x63, 0x5a, 0x5a, 0x5a, 0x52, 0x52,
+  0x52, 0x4a, 0x4a, 0x4a, 0x42, 0x42, 0x42, 0x39, 0x39, 0x39, 0x31, 0x31,
+  0x31, 0x29, 0x29, 0x29, 0x21, 0x21, 0x21, 0x18, 0x18, 0x18, 0x10, 0x10,
+  0x10, 0x08, 0x08, 0x08, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x21, 0xf9, 0x04, 0x01, 0x00, 0x00, 0xd9, 0x00, 0x2c, 0x00, 0x00,
+  0x00, 0x00, 0x50, 0x00, 0x50, 0x00, 0x00, 0x08, 0xff, 0x00, 0xb3, 0x09,
+  0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x13, 0x2a, 0x5c, 0xc8, 0xb0,
+  0xa1, 0xc3, 0x87, 0x10, 0x23, 0x4a, 0x9c, 0x48, 0xb1, 0xa2, 0xc5, 0x8b,
+  0x18, 0x33, 0x6a, 0xdc, 0xc8, 0xb1, 0xa3, 0xc7, 0x8f, 0x20, 0x43, 0x8a,
+  0x1c, 0x49, 0xb2, 0xa4, 0x49, 0x87, 0xc7, 0x96, 0x35, 0x6b, 0xe6, 0xac,
+  0x19, 0x33, 0x65, 0xc7, 0x4e, 0x76, 0x2c, 0x76, 0xcc, 0x98, 0x31, 0x62,
+  0x38, 0x8b, 0xd1, 0x4c, 0xc6, 0x2c, 0x5a, 0x34, 0x65, 0x32, 0x2f, 0xea,
+  0x2c, 0x46, 0x4c, 0xa7, 0xcd, 0x63, 0x48, 0x8f, 0x21, 0x5b, 0xca, 0x4c,
+  0x9a, 0x35, 0x67, 0x41, 0x25, 0x0e, 0xb5, 0x49, 0xf5, 0x28, 0xd2, 0x64,
+  0xc8, 0x92, 0x29, 0xdb, 0xfa, 0xec, 0x1a, 0xb6, 0x65, 0x51, 0x51, 0x26,
+  0x1d, 0x3b, 0x76, 0x69, 0x32, 0xad, 0xca, 0x96, 0x31, 0x63, 0xd6, 0xcc,
+  0x1a, 0x80, 0x69, 0x61, 0x15, 0x22, 0x53, 0x7a, 0x8c, 0xd8, 0xaf, 0x5e,
+  0xbd, 0x7e, 0x0d, 0xa3, 0xbb, 0x34, 0xeb, 0x56, 0xb5, 0x6c, 0x9b, 0x75,
+  0x05, 0x80, 0x0d, 0x59, 0x5c, 0x83, 0x58, 0x93, 0x1d, 0xf3, 0x15, 0xa0,
+  0xb1, 0xe3, 0x5e, 0xc6, 0x12, 0xa3, 0x4d, 0xcb, 0xcc, 0x99, 0xb3, 0x67,
+  0xcf, 0xa2, 0x01, 0x20, 0x0c, 0xf4, 0xb0, 0x40, 0x65, 0x5a, 0x8f, 0xf1,
+  0x72, 0x4c, 0x3a, 0xc0, 0x2e, 0x63, 0xa0, 0xb5, 0xaa, 0x75, 0xb9, 0x1a,
+  0x5a, 0xb4, 0x6a, 0x9b, 0x01, 0x74, 0x8e, 0xfb, 0x72, 0x2b, 0xe3, 0xd2,
+  0xa4, 0x79, 0xa1, 0x55, 0x7b, 0x0c, 0x58, 0xaf, 0x5d, 0xbb, 0x7a, 0x01,
+  0x43, 0x26, 0x2d, 0x36, 0x80, 0x64, 0x71, 0x59, 0x33, 0x23, 0xd6, 0x18,
+  0x38, 0xee, 0xc6, 0xc2, 0x96, 0x49, 0x07, 0xf6, 0x3c, 0xc0, 0xaf, 0x69,
+  0xb1, 0xb1, 0x15, 0x8b, 0x8a, 0x2c, 0x9a, 0xda, 0x65, 0x8c, 0x9d, 0x8b,
+  0xff, 0xcf, 0xad, 0xf6, 0x57, 0x69, 0xe0, 0xce, 0x7f, 0xc1, 0xde, 0x4c,
+  0x2d, 0x6a, 0xb5, 0x95, 0xcd, 0x92, 0xf1, 0x42, 0xbf, 0xcb, 0x74, 0xfd,
+  0xfa, 0xf3, 0x03, 0x20, 0x63, 0xee, 0xf8, 0x3e, 0x70, 0x5e, 0xf3, 0x19,
+  0x63, 0x5c, 0x33, 0x32, 0x41, 0x33, 0xcd, 0x4a, 0xce, 0x20, 0xf3, 0x1f,
+  0x7d, 0xce, 0xf9, 0x32, 0x0c, 0x32, 0xc2, 0x0c, 0x03, 0x4c, 0x30, 0xa3,
+  0x31, 0x08, 0x20, 0x5e, 0xd7, 0x65, 0x67, 0x8c, 0x49, 0xc6, 0x60, 0x03,
+  0x8d, 0x65, 0xcf, 0x20, 0xc3, 0x4b, 0x2f, 0x00, 0x02, 0x88, 0x5e, 0x2f,
+  0xc7, 0xf4, 0x32, 0x8c, 0x33, 0xc6, 0x0c, 0xb3, 0x56, 0x2f, 0xf6, 0xed,
+  0x72, 0x61, 0x2f, 0xbe, 0xf8, 0xf2, 0x8c, 0x71, 0xd1, 0x98, 0x44, 0x8d,
+  0x35, 0x98, 0x3d, 0x03, 0x8d, 0x88, 0x78, 0x91, 0x58, 0xe2, 0x2e, 0xbf,
+  0xb8, 0xc4, 0x96, 0x74, 0x3d, 0x51, 0x27, 0xe3, 0x8c, 0xbe, 0xfc, 0x02,
+  0xcc, 0x8d, 0x9b, 0x61, 0x83, 0x4d, 0x4c, 0x23, 0x09, 0x48, 0x0d, 0x34,
+  0xd0, 0xf8, 0x08, 0x9e, 0x2f, 0x41, 0xe2, 0x35, 0x9f, 0x2f, 0x2c, 0x59,
+  0xa6, 0x56, 0x34, 0xcd, 0xf8, 0xb2, 0xe4, 0x88, 0x34, 0x3a, 0x19, 0x4c,
+  0x71, 0x51, 0x62, 0x93, 0xe3, 0x48, 0xd0, 0x00, 0x70, 0x25, 0x96, 0xd0,
+  0x34, 0x03, 0xcc, 0x2f, 0xbf, 0xd4, 0xc8, 0xa5, 0x97, 0xc5, 0x60, 0xa6,
+  0x0c, 0x33, 0xc5, 0x08, 0xf3, 0xcb, 0x92, 0x78, 0xd5, 0xa8, 0xa6, 0x31,
+  0xd7, 0xb4, 0x79, 0xcd, 0x35, 0x1b, 0x8a, 0x94, 0x68, 0x35, 0x3e, 0xb9,
+  0x06, 0x8d, 0x5d, 0xc0, 0xdc, 0x99, 0x67, 0x9e, 0x0d, 0x3c, 0xb0, 0x00,
+  0x03, 0x0b, 0x48, 0x80, 0xc0, 0x7c, 0x0f, 0x84, 0x4a, 0x63, 0x93, 0x13,
+  0x0a, 0xa3, 0x59, 0x94, 0x8b, 0x5e, 0x43, 0x60, 0x48, 0xca, 0x60, 0x03,
+  0x80, 0x35, 0xd2, 0xf8, 0xff, 0xe4, 0x13, 0x33, 0xc1, 0xd4, 0x5a, 0xa9,
+  0xa5, 0x2e, 0xa0, 0x90, 0x82, 0x0a, 0x29, 0x9c, 0x40, 0x82, 0x18, 0x29,
+  0xa4, 0x80, 0xc2, 0x09, 0x4d, 0x3a, 0x09, 0x8c, 0x30, 0x50, 0x2a, 0x0a,
+  0xab, 0x48, 0x9a, 0x49, 0x39, 0x8d, 0x34, 0xb1, 0xfa, 0x04, 0xa1, 0x30,
+  0xd4, 0xd6, 0xea, 0xc0, 0x07, 0x15, 0x64, 0x6b, 0xc1, 0xb6, 0x15, 0xd0,
+  0xf0, 0x43, 0x14, 0x6c, 0x04, 0xe3, 0x40, 0x30, 0xc2, 0x1c, 0x83, 0x5d,
+  0x76, 0xd8, 0x2c, 0x6a, 0x4d, 0x35, 0x8d, 0x7e, 0xe4, 0xd5, 0x66, 0xd5,
+  0x40, 0x1b, 0xab, 0x34, 0xd0, 0xd4, 0x45, 0xcc, 0x30, 0xc3, 0x08, 0xb3,
+  0xc0, 0x02, 0x1a, 0x64, 0xeb, 0x6f, 0x0e, 0x56, 0x60, 0xc1, 0x06, 0x30,
+  0x13, 0xf4, 0x22, 0x0c, 0x9b, 0xc6, 0x11, 0x76, 0x8d, 0x35, 0x0c, 0x83,
+  0xf5, 0x51, 0x87, 0x52, 0x12, 0xf6, 0xac, 0xbc, 0xd2, 0x4c, 0xb3, 0x9f,
+  0x31, 0x3a, 0x11, 0x23, 0xcc, 0x04, 0x19, 0xd0, 0x90, 0x6d, 0x0e, 0x40,
+  0x60, 0x51, 0x87, 0x2e, 0xbc, 0xcc, 0x00, 0xdc, 0x30, 0xd4, 0x24, 0x2c,
+  0xe5, 0xc2, 0xd5, 0x54, 0xf3, 0x0c, 0x48, 0xcb, 0x10, 0x16, 0x9b, 0x35,
+  0xd3, 0x4c, 0x3c, 0x0d, 0x33, 0xbf, 0x19, 0x6b, 0xa6, 0x69, 0x18, 0xd0,
+  0x00, 0x32, 0x16, 0x6f, 0x0c, 0xf2, 0xc0, 0x7f, 0x5f, 0xc6, 0xd9, 0x66,
+  0xba, 0xeb, 0x42, 0x2a, 0xcc, 0x47, 0x37, 0x46, 0xcc, 0x5e, 0xcd, 0xd5,
+  0x2c, 0x73, 0xdf, 0x73, 0x31, 0xd4, 0x80, 0x83, 0x14, 0x72, 0xe8, 0x31,
+  0x34, 0xd1, 0x24, 0xf6, 0x62, 0xb4, 0x94, 0x48, 0x57, 0x43, 0x4d, 0x35,
+  0xc3, 0x78, 0x04, 0xb1, 0xab, 0xc6, 0x8d, 0xdd, 0x0c, 0x83, 0xfe, 0xd5,
+  0x17, 0x80, 0x0a, 0x52, 0xa8, 0xa1, 0x35, 0x7a, 0x33, 0x06, 0x79, 0x2a,
+  0xd2, 0xd6, 0x8c, 0xad, 0x6a, 0x47, 0xc7, 0x64, 0xff, 0x97, 0x30, 0x00,
+  0xd1, 0xfc, 0x36, 0x1f, 0x7d, 0xa6, 0x91, 0x46, 0xc6, 0x18, 0x0d, 0xd0,
+  0xcd, 0x64, 0x8d, 0xc0, 0x60, 0x97, 0xee, 0x35, 0x62, 0x57, 0xe3, 0xd6,
+  0xaa, 0x19, 0xc5, 0x6c, 0x1c, 0xda, 0x51, 0x0a, 0x23, 0xe3, 0xe6, 0x84,
+  0x8f, 0x47, 0x5f, 0x89, 0x85, 0x16, 0xeb, 0x0b, 0x31, 0x5e, 0xb1, 0xdc,
+  0xb2, 0x35, 0xae, 0x42, 0x93, 0x51, 0x33, 0x7f, 0x27, 0xac, 0x4c, 0x70,
+  0x42, 0xb2, 0x5d, 0x38, 0xdb, 0x75, 0x1b, 0x5a, 0xe9, 0x2f, 0x31, 0x9b,
+  0x2e, 0x39, 0xda, 0x70, 0x59, 0x74, 0x6a, 0xeb, 0xec, 0xdd, 0xe5, 0xcb,
+  0x88, 0x43, 0xfa, 0x67, 0x9f, 0x7d, 0xf3, 0xd5, 0x8e, 0xe7, 0x84, 0xe4,
+  0x4e, 0x03, 0x79, 0xcb, 0xbb, 0xc7, 0x56, 0x4d, 0x45, 0x08, 0x03, 0x0f,
+  0x00, 0x32, 0x34, 0x06, 0x69, 0xe2, 0xe0, 0x6c, 0x2b, 0x1e, 0xa4, 0xed,
+  0xa5, 0x06, 0x93, 0x8c, 0xee, 0xa8, 0x1b, 0x67, 0xcd, 0x44, 0x29, 0x5b,
+  0x0f, 0x6f, 0x9e, 0x35, 0x7a, 0x69, 0x62, 0xf7, 0x8a, 0xa3, 0x69, 0xa8,
+  0x9a, 0xe4, 0x0e, 0x43, 0x8c, 0x53, 0x2d, 0x8f, 0x8d, 0x79, 0x94, 0x54,
+  0x3e, 0xa4, 0x7e, 0x6c, 0xe0, 0xc1, 0x53, 0xfb, 0x84, 0xf4, 0x3e, 0xda,
+  0xd5, 0x8e, 0x54, 0xb5, 0x8a, 0x10, 0xbe, 0x98, 0x91, 0x34, 0xc9, 0x79,
+  0x05, 0x69, 0xd4, 0xa0, 0xc6, 0xcb, 0x22, 0xb2, 0x13, 0xca, 0xb8, 0x25,
+  0x3b, 0x76, 0x11, 0xe0, 0x9e, 0x08, 0xc8, 0xbd, 0x25, 0x71, 0x6d, 0x54,
+  0xc6, 0xaa, 0x9f, 0xfd, 0x88, 0x61, 0x2e, 0x6a, 0x3c, 0x8b, 0x1a, 0xc9,
+  0xc0, 0x97, 0x30, 0x6c, 0x95, 0x11, 0xa3, 0x6d, 0x66, 0x1a, 0xb7, 0xfa,
+  0x85, 0x33, 0xb0, 0xa3, 0x2a, 0x00, 0x15, 0x03, 0x00, 0xd0, 0x18, 0x92,
+  0x30, 0xce, 0x05, 0x80, 0x66, 0xa0, 0xc8, 0x38, 0xcf, 0x88, 0x50, 0x51,
+  0xff, 0x8a, 0x61, 0x8c, 0x67, 0x50, 0x03, 0x5a, 0xd3, 0x20, 0xc6, 0x47,
+  0x62, 0x86, 0x36, 0x3b, 0x55, 0x2a, 0x66, 0x65, 0x12, 0x50, 0x33, 0x78,
+  0x21, 0xa0, 0x67, 0xd0, 0x8d, 0x66, 0xc3, 0x18, 0xd1, 0x30, 0x7c, 0x81,
+  0x0c, 0xc0, 0x01, 0x83, 0x19, 0xb2, 0xb1, 0x1f, 0x11, 0x8d, 0xc1, 0x8c,
+  0x67, 0x4d, 0x23, 0x1a, 0x65, 0xf3, 0xc8, 0x0d, 0x63, 0x83, 0x8c, 0x09,
+  0x01, 0x23, 0x1a, 0xd7, 0x68, 0x9f, 0x5b, 0xa8, 0x88, 0xc3, 0x12, 0xf1,
+  0xe2, 0x2d, 0xbe, 0x19, 0x55, 0x17, 0xa3, 0x01, 0x8c, 0x64, 0x00, 0x60,
+  0x19, 0x45, 0x39, 0x8a, 0x32, 0xcc, 0xf8, 0x8c, 0x60, 0x80, 0xe4, 0x82,
+  0xd7, 0x08, 0x94, 0x30, 0x80, 0x01, 0x38, 0xf6, 0xc5, 0xa9, 0x26, 0x75,
+  0x2c, 0x91, 0xd1, 0x9a, 0x11, 0x8c, 0x1a, 0xed, 0x91, 0x18, 0x29, 0xc3,
+  0x18, 0x11, 0xaf, 0x12, 0x0d, 0x69, 0x50, 0x63, 0x19, 0xbf, 0x00, 0x89,
+  0xd1, 0xa8, 0x91, 0xaf, 0x5a, 0x35, 0xb2, 0x46, 0x71, 0xb2, 0x49, 0x24,
+  0xbd, 0x34, 0xc8, 0xcd, 0x20, 0xe3, 0x17, 0x5d, 0x04, 0x60, 0x20, 0x91,
+  0xb2, 0x14, 0x03, 0x51, 0xa3, 0x7f, 0x1e, 0xf1, 0x23, 0xe0, 0x54, 0x18,
+  0x8c, 0x46, 0xe6, 0xe9, 0x91, 0x02, 0x82, 0x46, 0x97, 0x0a, 0x45, 0xba,
+  0x3f, 0xfa, 0x51, 0x1a, 0x37, 0x42, 0xc6, 0x18, 0x95, 0x72, 0x16, 0x23,
+  0xa2, 0xd1, 0x51, 0x38, 0x8c, 0xd0, 0x0a, 0xe1, 0x88, 0xa7, 0x5f, 0xb8,
+  0xe5, 0x87, 0xc2, 0xfc, 0x9e, 0x9e, 0xf6, 0xe8, 0xc7, 0x68, 0xdc, 0x30,
+  0x91, 0xc6, 0x60, 0x66, 0x33, 0xdf, 0x03, 0x0c, 0x91, 0xdc, 0x08, 0x1a,
+  0xf8, 0xca, 0x17, 0x18, 0x9d, 0x01, 0x4b, 0x00, 0x38, 0xc3, 0x17, 0x7d,
+  0x13, 0x66, 0xfb, 0xa8, 0xa1, 0x8c, 0xa5, 0xb8, 0x65, 0x19, 0xc7, 0x1c,
+  0x06, 0x6c, 0x96, 0xa1, 0xff, 0x14, 0xbf, 0x28, 0x03, 0x1a, 0xd5, 0xc0,
+  0xe5, 0x47, 0x6e, 0x88, 0xce, 0x7b, 0xad, 0x90, 0x19, 0x29, 0xb3, 0xc6,
+  0x96, 0xfa, 0x66, 0x1c, 0x68, 0xa4, 0x4f, 0x4e, 0xc9, 0x08, 0x86, 0x32,
+  0x00, 0x20, 0x0d, 0x62, 0xe8, 0x32, 0x31, 0x7f, 0xf1, 0x89, 0x21, 0x47,
+  0x72, 0x46, 0xfb, 0xf1, 0xf2, 0x76, 0xd5, 0xd4, 0x93, 0x48, 0xab, 0x59,
+  0xa9, 0x04, 0x8a, 0x91, 0x26, 0xe2, 0x4c, 0x4b, 0x33, 0xa4, 0x91, 0x8c,
+  0x50, 0x8e, 0xa4, 0x18, 0x15, 0x25, 0x0a, 0xb5, 0x56, 0x18, 0x0c, 0x90,
+  0x56, 0x93, 0xa4, 0x21, 0x24, 0x97, 0x10, 0x8b, 0x42, 0xcb, 0xb3, 0x50,
+  0xe6, 0x32, 0x4b, 0x2b, 0x89, 0x32, 0x30, 0x66, 0x50, 0x9a, 0xd6, 0x34,
+  0x86, 0x77, 0xba, 0x15, 0xf3, 0x44, 0x18, 0xc8, 0x70, 0x66, 0x45, 0x35,
+  0x95, 0x79, 0x86, 0x40, 0xab, 0x44, 0x94, 0x7b, 0xe5, 0xcb, 0xa8, 0x35,
+  0xcd, 0x6a, 0x49, 0x13, 0xa8, 0xc0, 0xa6, 0xa6, 0x74, 0x35, 0xcf, 0x58,
+  0xc6, 0x46, 0x4f, 0x92, 0x31, 0x15, 0xce, 0xf4, 0xac, 0xe4, 0xd2, 0x29,
+  0xb5, 0xf0, 0xe5, 0x55, 0xb3, 0xa8, 0x46, 0x25, 0xcf, 0x70, 0x46, 0x1a,
+  0x83, 0x52, 0x14, 0x9c, 0x58, 0xd5, 0xaa, 0xe9, 0xbc, 0x2a, 0x5b, 0xdb,
+  0xea, 0xcf, 0xb4, 0xc0, 0xf5, 0x19, 0xed, 0x0a, 0x0a, 0x51, 0xaa, 0x3a,
+  0x94, 0xc2, 0x56, 0xd5, 0xae, 0xb3, 0x34, 0xcb, 0x5f, 0x90, 0x24, 0x18,
+  0x68, 0x20, 0xe7, 0x30, 0x37, 0x19, 0xa3, 0x0c, 0xfa, 0x39, 0x97, 0x9a,
+  0xd8, 0x64, 0x99, 0xcc, 0xf4, 0xeb, 0x5a, 0xd6, 0xd2, 0xd8, 0x88, 0x7a,
+  0x26, 0x1b, 0x0a, 0x50, 0x00, 0x32, 0x0a, 0x90, 0x80, 0x03, 0x28, 0xa3,
+  0x05, 0x5b, 0xc1, 0x4a, 0x65, 0x7b, 0x4a, 0x99, 0xc0, 0x38, 0x43, 0x02,
+  0xcf, 0x80, 0x00, 0x04, 0x92, 0x01, 0x0c, 0x5f, 0xff, 0x7c, 0x96, 0x05,
+  0x1d, 0xa0, 0x40, 0x15, 0x4c, 0x00, 0x83, 0x08, 0x18, 0xc0, 0x00, 0xcc,
+  0x58, 0x46, 0x6a, 0xfa, 0x82, 0x16, 0x04, 0x34, 0x43, 0x02, 0x2d, 0x29,
+  0x44, 0x0b, 0x4a, 0xe0, 0x01, 0x13, 0xac, 0x80, 0x05, 0x2f, 0x08, 0x0b,
+  0x07, 0x38, 0xa0, 0x83, 0x0c, 0x60, 0xa0, 0x02, 0x3f, 0xc8, 0x81, 0x11,
+  0x8e, 0x30, 0x05, 0x2a, 0x7c, 0x41, 0x02, 0xc0, 0x15, 0x2e, 0x68, 0xfe,
+  0xc2, 0x0c, 0x03, 0x88, 0xa0, 0x03, 0x4c, 0x18, 0x41, 0x08, 0xd6, 0x0b,
+  0x02, 0x0e, 0x64, 0xe0, 0x02, 0xda, 0x75, 0xc2, 0x18, 0x48, 0xa2, 0x83,
+  0xfa, 0xea, 0x60, 0x03, 0xf6, 0x1d, 0xc2, 0x10, 0x84, 0x20, 0x05, 0x2b,
+  0x58, 0x01, 0x0c, 0x60, 0xa8, 0x03, 0x1c, 0xd2, 0xe0, 0x8c, 0xe0, 0x8a,
+  0x77, 0x19, 0x08, 0x20, 0x84, 0x12, 0x6c, 0x00, 0x82, 0xf5, 0xae, 0xb7,
+  0x08, 0x3e, 0xe8, 0x01, 0x14, 0x88, 0x80, 0x84, 0x26, 0x98, 0xc1, 0x0c,
+  0x7b, 0x68, 0x84, 0x23, 0x40, 0x52, 0x01, 0x0c, 0xec, 0xe0, 0x06, 0x37,
+  0xd0, 0xef, 0x0e, 0x92, 0x90, 0x84, 0x2e, 0x68, 0x21, 0x0b, 0x66, 0xb8,
+  0xc3, 0x1d, 0xfa, 0xd0, 0x07, 0x40, 0x04, 0x42, 0x13, 0x12, 0x30, 0x12,
+  0x5b, 0xd2, 0xc0, 0x85, 0x20, 0x0c, 0xe1, 0x09, 0x61, 0xc8, 0x71, 0x18,
+  0xbc, 0xf0, 0x84, 0x25, 0x5c, 0x01, 0x0d, 0x67, 0x28, 0xc3, 0x1f, 0xfc,
+  0x40, 0x09, 0x4f, 0xa8, 0xc2, 0x14, 0x1e, 0xe1, 0x01, 0x0d, 0x8c, 0x80,
+  0x04, 0x12, 0x77, 0x21, 0x09, 0x5b, 0x70, 0x82, 0x16, 0xce, 0x60, 0x86,
+  0x39, 0xcc, 0xe1, 0x0f, 0x89, 0x60, 0xc4, 0x25, 0x30, 0x81, 0x09, 0x48,
+  0x40, 0x00, 0x33, 0x97, 0x91, 0xc0, 0x17, 0xde, 0x70, 0x87, 0x37, 0xd8,
+  0x01, 0x0d, 0x6e, 0x88, 0x83, 0x9a, 0xdd, 0xd0, 0x06, 0x3b, 0xf4, 0xc1,
+  0xce, 0x0f, 0x7e, 0x40, 0x84, 0x24, 0x44, 0x71, 0x0a, 0x01, 0x10, 0xe0,
+  0x23, 0x41, 0x90, 0x42, 0x13, 0xb2, 0xc0, 0xe7, 0x33, 0x9c, 0x61, 0x0d,
+  0x78, 0x98, 0x83, 0x21, 0x12, 0xf1, 0x88, 0x47, 0x6c, 0x02, 0x14, 0xa0,
+  0x28, 0x05, 0x2a, 0x0a, 0x21, 0x9d, 0xad, 0x98, 0x16, 0x19, 0x82, 0x18,
+  0x32, 0x9c, 0xff, 0xa0, 0x88, 0x4a, 0x33, 0x62, 0x12, 0x88, 0xa0, 0x04,
+  0x25, 0x4a, 0xe1, 0x89, 0x53, 0xc4, 0x62, 0x00, 0x03, 0xb8, 0x05, 0x48,
+  0xda, 0x40, 0x07, 0x3a, 0xe0, 0xe1, 0xd4, 0x7c, 0x38, 0x84, 0x21, 0x2c,
+  0xf1, 0x88, 0x4c, 0x64, 0x82, 0x14, 0xb0, 0x80, 0x45, 0x2a, 0x56, 0x41,
+  0x0c, 0x07, 0xb0, 0xaf, 0x7d, 0xbe, 0x70, 0x40, 0x24, 0x2a, 0xb1, 0x89,
+  0x43, 0x23, 0x3a, 0xd1, 0xa5, 0x28, 0x45, 0x28, 0xe8, 0x1c, 0x8b, 0x4f,
+  0xd3, 0xe2, 0x13, 0x23, 0xc9, 0xc3, 0x22, 0x04, 0xd1, 0x88, 0x46, 0x74,
+  0xa2, 0x13, 0x9c, 0x18, 0xc5, 0x2b, 0xa6, 0xbd, 0x8a, 0x4f, 0xd4, 0x9a,
+  0x21, 0xb8, 0x60, 0x45, 0x2d, 0x5c, 0xc1, 0xed, 0x56, 0xb8, 0x42, 0x16,
+  0xe0, 0x9e, 0x05, 0x01, 0x6c, 0x21, 0x83, 0xa0, 0x96, 0x24, 0x18, 0xb9,
+  0x98, 0x69, 0x2e, 0xd6, 0x5d, 0x53, 0x89, 0xa0, 0xfb, 0xac, 0x0b, 0x58,
+  0xe1, 0x9d, 0x3e, 0x4b, 0xef, 0x7a, 0xdb, 0xfb, 0xde, 0xf8, 0xce, 0xb7,
+  0xbe, 0xf7, 0xcd, 0xef, 0x7e, 0xfb, 0xfb, 0xdf, 0x00, 0x0f, 0xb8, 0xc0,
+  0x39, 0x12, 0x10, 0x00, 0x3b
+};
+
+static unsigned char grayline_gif[] = {
+  0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00,
+  0x00, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b
+};
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,1280 @@
+/*
+ * HTTP Info plugin for the olsr.org OLSR daemon
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef WIN32
+#include <io.h>
+#else
+#include <netdb.h>
+#endif
+
+#include "olsr.h"
+#include "olsr_cfg.h"
+#include "interfaces.h"
+#include "olsr_protocol.h"
+#include "net_olsr.h"
+#include "link_set.h"
+#include "socket_parser.h"
+#include "ipcalc.h"
+#include "lq_plugin.h"
+
+#include "olsrd_httpinfo.h"
+#include "admin_interface.h"
+#include "gfx.h"
+
+#ifdef OS
+#undef OS
+#endif
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+#define OS "Windows"
+#endif
+#ifdef linux
+#define OS "GNU/Linux"
+#endif
+#ifdef __FreeBSD__
+#define OS "FreeBSD"
+#endif
+
+#ifndef OS
+#define OS "Undefined"
+#endif
+
+static char copyright_string[] __attribute__((unused)) = "olsr.org HTTPINFO plugin Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org) All rights reserved.";
+
+#define MAX_CLIENTS 3
+
+#define MAX_HTTPREQ_SIZE (1024 * 10)
+
+#define DEFAULT_TCP_PORT 1978
+
+#define HTML_BUFSIZE (1024 * 4000)
+
+#define FRAMEWIDTH (resolve_ip_addresses ? 900 : 800)
+
+#define FILENREQ_MATCH(req, filename) \
+        !strcmp(req, filename) || \
+        (strlen(req) && !strcmp(&req[1], filename))
+
+static const char httpinfo_css[] =
+  "#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"
+  "line-height: 16px;\ntext-decoration: none;\nborder: 1px solid #ccc;\n"
+  "margin: 5px;\nbackground: #ececec;\n}\n"
+  "hr\n{\nborder: none;\npadding: 1px;\nbackground: url(grayline.gif) repeat-x bottom;\n}\n"
+  "#maintable\n{\nmargin: 0px;\npadding: 5px;\nborder-left: 1px solid #ccc;\n"
+  "border-right: 1px solid #ccc;\nborder-bottom: 1px solid #ccc;\n}\n"
+  "#footer\n{\nfont-size: 10px;\nline-height: 14px;\ntext-decoration: none;\ncolor: #666;\n}\n"
+  "#hdr\n{\nfont-size: 14px;\ntext-align: center;\nline-height: 16px;\n"
+  "text-decoration: none;\nborder: 1px solid #ccc;\n"
+  "margin: 5px;\nbackground: #ececec;\n}\n"
+  "#container\n{\nwidth: 1000px;\npadding: 30px;\nborder: 1px solid #ccc;\nbackground: #fff;\n}\n"
+  "#tabnav\n{\nheight: 20px;\nmargin: 0;\npadding-left: 10px;\n"
+  "background: url(grayline.gif) repeat-x bottom;\n}\n"
+  "#tabnav li\n{\nmargin: 0;\npadding: 0;\ndisplay: inline;\nlist-style-type: none;\n}\n"
+  "#tabnav a:link, #tabnav a:visited\n{\nfloat: left;\nbackground: #ececec;\n"
+  "font-size: 12px;\nline-height: 14px;\nfont-weight: bold;\npadding: 2px 10px 2px 10px;\n"
+  "margin-right: 4px;\nborder: 1px solid #ccc;\ntext-decoration: none;\ncolor: #777;\n}\n"
+  "#tabnav a:link.active, #tabnav a:visited.active\n{\nborder-bottom: 1px solid #fff;\n"
+  "background: #ffffff;\ncolor: #000;\n}\n"
+  "#tabnav a:hover\n{\nbackground: #777777;\ncolor: #ffffff;\n}\n"
+  ".input_text\n{\nbackground: #E5E5E5;\nmargin-left: 5px; margin-top: 0px;\n"
+  "text-align: left;\n\nwidth: 100px;\npadding: 0px;\ncolor: #000000;\n"
+  "text-decoration: none;\nfont-family: verdana;\nfont-size: 12px;\n"
+  "border: 1px solid #ccc;\n}\n"
+  ".input_button\n{\nbackground: #B5D1EE;\nmargin-left: 5px;\nmargin-top: 0px;\n"
+  "text-align: center;\nwidth: 120px;\npadding: 0px;\ncolor: #000000;\n"
+  "text-decoration: none;\nfont-family: verdana;\nfont-size: 12px;\n"
+  "border: 1px solid #000;\n}\n";
+
+typedef int(*build_body_callback)(char *, olsr_u32_t);
+
+struct tab_entry
+{
+  const char *tab_label;
+  const char *filename;
+  build_body_callback build_body_cb;
+  olsr_bool display_tab;
+};
+
+struct static_bin_file_entry
+{
+  const char *filename;
+  unsigned char *data;
+  unsigned int data_size;
+};
+
+struct static_txt_file_entry
+{
+  const char *filename;
+  const char *data;
+};
+
+struct dynamic_file_entry
+{
+  const char *filename;
+  int(*process_data_cb)(char *, olsr_u32_t, char *, olsr_u32_t);
+};
+
+static int get_http_socket(int);
+
+static int build_tabs(char *, olsr_u32_t, int);
+
+static void parse_http_request(int);
+
+static int build_http_header(http_header_type, olsr_bool, olsr_u32_t, char *, olsr_u32_t);
+
+static int build_frame(char *, olsr_u32_t, const char *, const char *, int, build_body_callback frame_body_cb);
+
+static int build_routes_body(char *, olsr_u32_t);
+
+static int build_config_body(char *, olsr_u32_t);
+
+static int build_neigh_body(char *, olsr_u32_t);
+
+static int build_topo_body(char *, olsr_u32_t);
+
+static int build_mid_body(char *, olsr_u32_t);
+
+static int build_nodes_body(char *, olsr_u32_t);
+
+static int build_all_body(char *, olsr_u32_t);
+
+static int build_about_body(char *, olsr_u32_t);
+
+static int build_cfgfile_body(char *, olsr_u32_t);
+
+static int check_allowed_ip(const struct allowed_net * const allowed_nets, const union olsr_ip_addr * const addr);
+
+static int build_ip_txt(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link,
+                        const char * const ipaddrstr, const int prefix_len);
+
+static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize, const olsr_bool want_link,
+                             const union olsr_ip_addr * const ipaddr,
+                             const int prefix_len);
+static int section_title(char *buf, olsr_u32_t bufsize, const char *title);
+
+static ssize_t writen(int fd, const void *buf, size_t count);
+
+static struct timeval start_time;
+static struct http_stats stats;
+static int client_sockets[MAX_CLIENTS];
+static int curr_clients;
+static int http_socket;
+
+#if 0
+int netsprintf(char *str, const char* format, ...) __attribute__((format(printf, 2, 3)));
+static int netsprintf_direct = 0;
+static int netsprintf_error = 0;
+#define sprintf netsprintf
+#define NETDIRECT
+#endif
+
+static const struct tab_entry tab_entries[] = {
+    {"Configuration",  "config",  build_config_body,  OLSR_TRUE},
+    {"Routes",         "routes",  build_routes_body,  OLSR_TRUE},
+    {"Links/Topology", "nodes",   build_nodes_body,   OLSR_TRUE},
+    {"All",            "all",     build_all_body,     OLSR_TRUE},
+#ifdef ADMIN_INTERFACE
+    {"Admin",          "admin",   build_admin_body,   OLSR_TRUE},
+#endif
+    {"About",          "about",   build_about_body,   OLSR_TRUE},
+    {"FOO",            "cfgfile", build_cfgfile_body, OLSR_FALSE},
+    {NULL,             NULL,      NULL,               OLSR_FALSE}
+};
+
+static const struct static_bin_file_entry static_bin_files[] = {
+    {"favicon.ico",  favicon_ico, sizeof(favicon_ico)},
+    {"logo.gif",     logo_gif, sizeof(logo_gif)},
+    {"grayline.gif", grayline_gif, sizeof(grayline_gif)},
+    {NULL, NULL, 0}
+};
+
+static const struct static_txt_file_entry static_txt_files[] = {
+    {"httpinfo.css", httpinfo_css},
+    {NULL, NULL}
+};
+
+
+static const struct dynamic_file_entry dynamic_files[] =
+  {
+#ifdef ADMIN_INTERFACE
+    {"set_values", process_set_values},
+#endif
+    {NULL, NULL}
+  };
+
+
+static int
+get_http_socket(int port)
+{
+  struct sockaddr_in sin;
+  olsr_u32_t yes = 1;
+
+  /* Init ipc socket */
+  int s = socket(AF_INET, SOCK_STREAM, 0);
+  if (s == -1) {
+    olsr_printf(1, "(HTTPINFO)socket %s\n", strerror(errno));
+    return -1;
+  }
+
+  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
+    olsr_printf(1, "(HTTPINFO)SO_REUSEADDR failed %s\n", strerror(errno));
+    close(s);
+    return -1;
+  }
+
+  /* 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(port);
+
+  /* bind the socket to the port number */
+  if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
+    olsr_printf(1, "(HTTPINFO) bind failed %s\n", strerror(errno));
+    close(s);
+    return -1;
+  }
+
+  /* show that we are willing to listen */
+  if (listen(s, 1) == -1) {
+    olsr_printf(1, "(HTTPINFO) listen failed %s\n", strerror(errno));
+    close(s);
+    return -1;
+  }
+
+  return s;
+}
+
+/**
+ *Do initialization here
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ */
+int
+olsrd_plugin_init(void)
+{
+  /* Get start time */
+  gettimeofday(&start_time, NULL);
+
+  curr_clients = 0;
+  /* set up HTTP socket */
+  http_socket = get_http_socket(http_port != 0 ? http_port :  DEFAULT_TCP_PORT);
+
+  if (http_socket < 0) {
+    fprintf(stderr, "(HTTPINFO) could not initialize HTTP socket\n");
+    exit(0);
+  }
+
+  /* Register socket */
+  add_olsr_socket(http_socket, &parse_http_request);
+
+  return 1;
+}
+
+/* Non reentrant - but we are not multithreaded anyway */
+void
+parse_http_request(int fd)
+{
+  struct sockaddr_in pin;
+  socklen_t addrlen;
+  char *addr;
+  char req[MAX_HTTPREQ_SIZE];
+  static char body[HTML_BUFSIZE];
+  char req_type[11];
+  char filename[251];
+  char http_version[11];
+  unsigned int c = 0;
+  int r = 1, size = 0;
+
+  if (curr_clients >= MAX_CLIENTS) {
+    return;
+  }
+  curr_clients++;
+
+  addrlen = sizeof(struct sockaddr_in);
+  client_sockets[curr_clients] = accept(fd, (struct sockaddr *)  &pin, &addrlen);
+  if (client_sockets[curr_clients] == -1) {
+    olsr_printf(1, "(HTTPINFO) accept: %s\n", strerror(errno));
+    goto close_connection;
+  }
+
+  if (!check_allowed_ip(allowed_nets, (union olsr_ip_addr *)&pin.sin_addr.s_addr)) {
+    struct ipaddr_str strbuf;
+    olsr_printf(0, "HTTP request from non-allowed host %s!\n",
+                olsr_ip_to_string(&strbuf, (union olsr_ip_addr *)&pin.sin_addr.s_addr));
+    close(client_sockets[curr_clients]);
+  }
+
+  addr = inet_ntoa(pin.sin_addr);
+
+  memset(req, 0, sizeof(req));
+  memset(body, 0, sizeof(body));
+
+  while ((r = recv(client_sockets[curr_clients], &req[c], 1, 0)) > 0 && (c < sizeof(req)-1)) {
+      c++;
+
+      if ((c > 3 && !strcmp(&req[c-4], "\r\n\r\n")) ||
+	 (c > 1 && !strcmp(&req[c-2], "\n\n")))
+          break;
+  }
+
+  if (r < 0) {
+    olsr_printf(1, "(HTTPINFO) Failed to recieve data from client!\n");
+    stats.err_hits++;
+    goto close_connection;
+  }
+
+  /* Get the request */
+  if (sscanf(req, "%10s %250s %10s\n", req_type, filename, http_version) != 3) {
+    /* Try without HTTP version */
+    if (sscanf(req, "%10s %250s\n", req_type, filename) != 2) {
+      olsr_printf(1, "(HTTPINFO) Error parsing request %s!\n", req);
+      stats.err_hits++;
+      goto close_connection;
+    }
+  }
+
+  olsr_printf(1, "Request: %s\nfile: %s\nVersion: %s\n\n", req_type, filename, http_version);
+
+  if (!strcmp(req_type, "POST")) {
+#ifdef ADMIN_INTERFACE
+    int i = 0;
+    while (dynamic_files[i].filename) {
+        printf("POST checking %s\n", dynamic_files[i].filename);
+        if (FILENREQ_MATCH(filename, dynamic_files[i].filename)) {
+            olsr_u32_t param_size;
+
+            stats.ok_hits++;
+
+            param_size = recv(client_sockets[curr_clients], req, sizeof(req)-1, 0);
+
+            req[param_size] = '\0';
+            printf("Dynamic read %d bytes\n", param_size);
+	
+            //memcpy(body, dynamic_files[i].data, static_bin_files[i].data_size);
+            size += dynamic_files[i].process_data_cb(req, param_size, &body[size], sizeof(body)-size);
+            c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, sizeof(req));
+            goto send_http_data;
+        }
+        i++;
+    }
+#endif
+    /* We only support GET */
+    strscpy(body, HTTP_400_MSG, sizeof(body));
+    stats.ill_hits++;
+    c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, sizeof(req));
+  } else if (!strcmp(req_type, "GET")) {
+    int i = 0;
+
+    for (i = 0; static_bin_files[i].filename; i++) {
+        if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) {
+	    break;
+        }
+    }
+
+    if (static_bin_files[i].filename) {
+      stats.ok_hits++;
+      memcpy(body, static_bin_files[i].data, static_bin_files[i].data_size);
+      size = static_bin_files[i].data_size;
+      c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, sizeof(req));
+      goto send_http_data;
+    }
+
+    i = 0;
+    while (static_txt_files[i].filename)	{
+      if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) {
+        break;
+      }
+      i++;
+    }
+
+    if (static_txt_files[i].filename) {
+      stats.ok_hits++;
+      size += snprintf(&body[size], sizeof(body)-size, "%s", static_txt_files[i].data);
+      c = build_http_header(HTTP_OK, OLSR_FALSE, size, req, sizeof(req));
+      goto send_http_data;
+    }
+
+    i = 0;
+    if (strlen(filename) > 1) {
+      while (tab_entries[i].filename) {
+        if (FILENREQ_MATCH(filename, tab_entries[i].filename)) {
+          break;
+        }
+        i++;
+      }
+    }
+
+    if (tab_entries[i].filename) {
+#ifdef NETDIRECT
+      c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, sizeof(req));
+      r = send(client_sockets[curr_clients], req, c, 0);
+      if (r < 0) {
+        olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
+        goto close_connection;
+      }
+      netsprintf_error = 0;
+      netsprintf_direct = 1;
+#endif
+      size += snprintf(&body[size], sizeof(body)-size,
+                       "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
+                       "<head>\n"
+                       "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
+                       "<title>olsr.org httpinfo plugin</title>\n"
+                       "<link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
+                       "<link rel=\"shortcut icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"
+                       "<link rel=\"stylesheet\" type=\"text/css\" href=\"httpinfo.css\">\n"
+                       "</head>\n"
+                       "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
+                       "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
+                       "<tbody><tr bgcolor=\"#ffffff\">\n"
+                       "<td align=\"left\" height=\"69\" valign=\"middle\" width=\"80%%\">\n"
+                       "<font color=\"black\" face=\"timesroman\" size=\"6\">&nbsp;&nbsp;&nbsp;<a href=\"http://www.olsr.org/\">olsr.org OLSR daemon</a></font></td>\n"
+                       "<td align=\"right\" height=\"69\" valign=\"middle\" width=\"20%%\">\n"
+                       "<a href=\"http://www.olsr.org/\"><img border=\"0\" src=\"/logo.gif\" alt=\"olsrd logo\"></a></td>\n"
+                       "</tr>\n"
+                       "</tbody>\n"
+                       "</table>\n",
+                       FRAMEWIDTH);
+	
+      size += build_tabs(&body[size], sizeof(body)-size, i);
+      size += build_frame(&body[size],
+                          sizeof(body)-size,
+                          "Current Routes",
+                          "routes",
+                          FRAMEWIDTH,
+                          tab_entries[i].build_body_cb);
+	
+      stats.ok_hits++;
+
+      size += snprintf(&body[size], sizeof(body)-size,
+                       "</table>\n"
+                       "<div id=\"footer\">\n"
+                       "<center>\n"
+                       "(C)2005 Andreas T&oslash;nnesen<br/>\n"
+                       "<a href=\"http://www.olsr.org/\">http://www.olsr.org</a>\n"
+                       "</center>\n"
+                       "</div>\n"
+                       "</body>\n"
+                       "</html>\n");
+	
+#ifdef NETDIRECT
+      netsprintf_direct = 1;
+      goto close_connection;
+#else
+      c = build_http_header(HTTP_OK, OLSR_TRUE, size, req, sizeof(req));
+      goto send_http_data;
+#endif
+    }
+
+
+    stats.ill_hits++;
+    strscpy(body, HTTP_404_MSG, sizeof(body));
+    c = build_http_header(HTTP_BAD_FILE, OLSR_TRUE, strlen(body), req, sizeof(req));
+  } else {
+    /* We only support GET */
+    strscpy(body, HTTP_400_MSG, sizeof(body));
+    stats.ill_hits++;
+    c = build_http_header(HTTP_BAD_REQ, OLSR_TRUE, strlen(body), req, sizeof(req));
+  }
+
+ send_http_data:
+
+  r = writen(client_sockets[curr_clients], req, c);
+  if (r < 0) {
+      olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
+      goto close_connection;
+  }
+
+  r = writen(client_sockets[curr_clients], body, size);
+  if (r < 0) {
+      olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
+      goto close_connection;
+  }
+
+ close_connection:
+  close(client_sockets[curr_clients]);
+  curr_clients--;
+
+}
+
+
+int
+build_http_header(http_header_type type,
+		  olsr_bool is_html,
+		  olsr_u32_t msgsize,
+		  char *buf,
+		  olsr_u32_t bufsize)
+{
+  time_t currtime;
+  const char *h;
+  int size;
+
+  switch(type) {
+  case HTTP_BAD_REQ:
+      h = HTTP_400;
+      break;
+  case HTTP_BAD_FILE:
+      h = HTTP_404;
+      break;
+  default:
+      /* Defaults to OK */
+      h = HTTP_200;
+      break;
+  }
+  size = snprintf(buf, bufsize, "%s", h);
+
+  /* Date */
+  time(&currtime);
+  size += strftime(&buf[size], bufsize-size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
+
+  /* Server version */
+  size += snprintf(&buf[size], bufsize-size, "Server: %s %s %s\r\n", PLUGIN_NAME, PLUGIN_VERSION, HTTP_VERSION);
+
+  /* connection-type */
+  size += snprintf(&buf[size], bufsize-size, "Connection: closed\r\n");
+
+  /* MIME type */
+  size += snprintf(&buf[size], bufsize-size, "Content-type: text/%s\r\n", is_html ? "html" : "plain");
+
+  /* Content length */
+  if (msgsize > 0) {
+      size += snprintf(&buf[size], bufsize-size, "Content-length: %i\r\n", msgsize);
+  }
+
+  /* Cache-control
+   * No caching dynamic pages
+   */
+  size += snprintf(&buf[size], bufsize-size, "Cache-Control: no-cache\r\n");
+
+  if (!is_html) {
+    size += snprintf(&buf[size], bufsize-size, "Accept-Ranges: bytes\r\n");
+  }
+  /* End header */
+  size += snprintf(&buf[size], bufsize-size, "\r\n");
+
+  olsr_printf(1, "HEADER:\n%s", buf);
+
+  return size;
+}
+
+
+
+static int build_tabs(char *buf, const olsr_u32_t bufsize, int active)
+{
+  int size = 0, tabs = 0;
+
+  size += snprintf(&buf[size], bufsize-size,
+                   "<table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"%d\">\n"
+                   "<tr bgcolor=\"#ffffff\"><td>\n"
+                   "<ul id=\"tabnav\">\n",
+                   FRAMEWIDTH);
+  for (tabs = 0; tab_entries[tabs].tab_label; tabs++) {
+    if (!tab_entries[tabs].display_tab) {
+      continue;
+    }
+    size += snprintf(&buf[size], bufsize-size,
+                     "<li><a href=\"%s\"%s>%s</a></li>\n",
+                     tab_entries[tabs].filename,
+                     tabs == active ? " class=\"active\"" : "",
+                     tab_entries[tabs].tab_label);
+  }
+  size += snprintf(&buf[size], bufsize-size,
+                   "</ul>\n"
+                   "</td></tr>\n"
+                   "<tr><td>\n");
+  return size;
+}
+
+
+/*
+ * destructor - called at unload
+ */
+void
+olsr_plugin_exit(void)
+{
+  if (http_socket >= 0) {
+    CLOSE(http_socket);
+  }
+}
+
+
+static int section_title(char *buf, olsr_u32_t bufsize, const char *title)
+{
+  return snprintf(buf, bufsize,
+                  "<h2>%s</h2>\n"
+                  "<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n", title);
+}
+
+static int build_frame(char *buf,
+                       olsr_u32_t bufsize,
+                       const char *title __attribute__((unused)),
+                       const char *link __attribute__((unused)),
+                       int width __attribute__((unused)),
+                       build_body_callback frame_body_cb)
+{
+  int size = 0;
+  size += snprintf(&buf[size], bufsize-size, "<div id=\"maintable\">\n");
+  size += frame_body_cb(&buf[size], bufsize-size);
+  size += snprintf(&buf[size], bufsize-size, "</div>\n");
+  return size;
+}
+
+static int fmt_href(char *buf,
+                    const olsr_u32_t bufsize,
+                    const char * const ipaddr)
+{
+  return snprintf(buf, bufsize, "<a href=\"http://%s:%d/all\">", ipaddr, http_port);
+}
+
+static int build_ip_txt(char *buf,
+                        const olsr_u32_t bufsize,
+                        const olsr_bool print_link,
+                        const char * const ipaddrstr,
+                        const int prefix_len)
+{
+  int size = 0;
+
+  if (print_link) {
+    size += fmt_href(&buf[size], bufsize-size, ipaddrstr);
+  }
+
+  size += snprintf(&buf[size], bufsize-size, "%s", ipaddrstr);
+  /* print ip address or ip prefix ? */
+  if (prefix_len != -1 && prefix_len != olsr_cnf->maxplen) {
+      size += snprintf(&buf[size], bufsize-size, "/%d", prefix_len);
+  }
+
+  if (print_link) { /* Print the link only if there is no prefix_len */
+    size += snprintf(&buf[size], bufsize-size, "</a>");
+  }
+  return size;
+}
+
+static int build_ipaddr_link(char *buf, const olsr_u32_t bufsize,
+                             const olsr_bool want_link,
+                             const union olsr_ip_addr * const ipaddr,
+                             const int prefix_len)
+{
+  int size = 0;
+  struct ipaddr_str ipaddrstr;
+  const struct hostent * const hp =
+#ifndef WIN32
+      resolve_ip_addresses ? gethostbyaddr(ipaddr, olsr_cnf->ipsize, olsr_cnf->ip_version) :
+#endif
+      NULL;
+  /* Print the link only if there is no prefix_len */
+  const int print_link = want_link && (prefix_len == -1 || prefix_len == olsr_cnf->maxplen);
+  olsr_ip_to_string(&ipaddrstr, ipaddr);
+
+  size += snprintf(&buf[size], bufsize-size, "<td>");
+  size += build_ip_txt(&buf[size], bufsize-size, print_link, ipaddrstr.buf, prefix_len);
+  size += snprintf(&buf[size], bufsize-size, "</td>");
+
+  if (resolve_ip_addresses) {
+    if (hp) {
+      size += snprintf(&buf[size], bufsize-size, "<td>(");
+      if (print_link) {
+        size += fmt_href(&buf[size], bufsize-size, ipaddrstr.buf);
+      }
+      size += snprintf(&buf[size], bufsize-size, "%s", hp->h_name);
+      if (print_link) {
+        size += snprintf(&buf[size], bufsize-size, "</a>");
+      }
+      size += snprintf(&buf[size], bufsize-size, ")</td>");
+    } else {
+      size += snprintf(&buf[size], bufsize-size, "<td/>");
+    }
+  }
+  return size;
+}
+
+#define build_ipaddr_with_link(buf, bufsize, ipaddr, plen) \
+          build_ipaddr_link((buf), (bufsize), OLSR_TRUE, (ipaddr), (plen))
+#define build_ipaddr_no_link(buf, bufsize, ipaddr, plen) \
+          build_ipaddr_link((buf), (bufsize), OLSR_FALSE, (ipaddr), (plen))
+
+static int build_route(char *buf, olsr_u32_t bufsize, const struct rt_entry * rt)
+{
+  int size = 0;
+  struct lqtextbuffer lqbuffer;
+  
+  size += snprintf(&buf[size], bufsize-size, "<tr>");
+  size += build_ipaddr_with_link(&buf[size], bufsize-size,
+                                 &rt->rt_dst.prefix,
+                                 rt->rt_dst.prefix_len);
+  size += build_ipaddr_with_link(&buf[size], bufsize-size,
+                                 &rt->rt_best->rtp_nexthop.gateway,
+                                 -1);
+
+  size += snprintf(&buf[size], bufsize-size,
+                   "<td align=\"center\">%d</td>",
+                   rt->rt_best->rtp_metric.hops);
+  size += snprintf(&buf[size], bufsize-size,
+                   "<td align=\"right\">%s</td>",
+                   get_linkcost_text(rt->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
+  size += snprintf(&buf[size], bufsize-size,
+                   "<td align=\"center\">%s</td></tr>\n",
+                   if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
+  return size;
+}
+
+static int build_routes_body(char *buf, olsr_u32_t bufsize)
+{
+  int size = 0;
+  struct rt_entry *rt;
+  const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
+  size += section_title(&buf[size], bufsize-size, "OLSR Routes in Kernel");
+  size += snprintf(&buf[size], bufsize-size, "<tr><th align=\"center\"%s>Destination</th><th align=\"center\"%s>Gateway</th><th>Metric</th><th align=\"right\">ETX</th><th>Interface</th></tr>\n", colspan, colspan);
+
+  /* Walk the route table */
+  OLSR_FOR_ALL_RT_ENTRIES(rt) {
+      size += build_route(&buf[size], bufsize-size, rt);
+  } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
+
+  size += snprintf(&buf[size], bufsize-size, "</table>\n");
+
+  return size;
+}
+
+static int build_config_body(char *buf, olsr_u32_t bufsize)
+{
+    int size = 0;
+    const struct olsr_if *ifs;
+    const struct plugin_entry *pentry;
+    const struct plugin_param *pparam;
+    struct ipaddr_str mainaddrbuf;
+
+    size += snprintf(&buf[size], bufsize-size, "Version: %s (built on %s on %s)\n<br>", olsrd_version, build_date, build_host);
+    size += snprintf(&buf[size], bufsize-size, "OS: %s\n<br>", OS);
+
+    {
+      const time_t currtime = time(NULL);
+      const int rc = strftime(&buf[size], bufsize-size, "System time: <em>%a, %d %b %Y %H:%M:%S</em><br>", localtime(&currtime));
+      if (rc > 0) {
+        size += rc;
+      }
+    }
+
+    {
+      struct timeval now, uptime;
+      int hours, mins, days;
+      gettimeofday(&now, NULL);
+      timersub(&now, &start_time, &uptime);
+
+      days = uptime.tv_sec/86400;
+      uptime.tv_sec %= 86400;
+      hours = uptime.tv_sec/3600;
+      uptime.tv_sec %= 3600;
+      mins = uptime.tv_sec/60;
+      uptime.tv_sec %= 60;
+
+      size += snprintf(&buf[size], bufsize-size, "Olsrd uptime: <em>");
+      if (days) {
+        size += snprintf(&buf[size], bufsize-size, "%d day(s) ", days);
+      }
+      size += snprintf(&buf[size], bufsize-size, "%02d hours %02d minutes %02d seconds</em><br/>\n", hours, mins, (int)uptime.tv_sec);
+    }
+
+    size += snprintf(&buf[size], bufsize-size, "HTTP stats(ok/dyn/error/illegal): <em>%d/%d/%d/%d</em><br>\n", stats.ok_hits, stats.dyn_hits, stats.err_hits, stats.ill_hits);
+
+    size += snprintf(&buf[size], bufsize-size, "Click <a href=\"/cfgfile\">here</a> to <em>generate a configuration file for this node</em>.\n");
+
+    size += snprintf(&buf[size], bufsize-size, "<h2>Variables</h2>\n");
+
+    size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\">\n<tr>");
+
+    size += snprintf(&buf[size], bufsize-size, "<td>Main address: <strong>%s</strong></td>\n", olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
+    size += snprintf(&buf[size], bufsize-size, "<td>IP version: %d</td>\n", olsr_cnf->ip_version == AF_INET ? 4 : 6);
+    size += snprintf(&buf[size], bufsize-size, "<td>Debug level: %d</td>\n", olsr_cnf->debug_level);
+    size += snprintf(&buf[size], bufsize-size, "<td>FIB Metrics: %s</td>\n", FIBM_FLAT == olsr_cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == olsr_cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
+
+    size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
+
+    size += snprintf(&buf[size], bufsize-size, "<td>Pollrate: %0.2f</td>\n", olsr_cnf->pollrate);
+    size += snprintf(&buf[size], bufsize-size, "<td>TC redundancy: %d</td>\n", olsr_cnf->tc_redundancy);
+    size += snprintf(&buf[size], bufsize-size, "<td>MPR coverage: %d</td>\n", olsr_cnf->mpr_coverage);
+    size += snprintf(&buf[size], bufsize-size, "<td>NAT threshold: %f</td>\n", olsr_cnf->lq_nat_thresh);
+
+    size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n");
+
+    size += snprintf(&buf[size], bufsize-size, "<td>Fisheye: %s</td>\n", olsr_cnf->lq_fish ? "Enabled" : "Disabled");
+    size += snprintf(&buf[size], bufsize-size, "<td>TOS: 0x%04x</td>\n", olsr_cnf->tos);
+    size += snprintf(&buf[size], bufsize-size, "<td>RtTable: 0x%04x/%d</td>\n", olsr_cnf->rttable, olsr_cnf->rttable);
+    size += snprintf(&buf[size], bufsize-size, "<td>RtTableDefault: 0x%04x/%d</td>\n", olsr_cnf->rttable_default, olsr_cnf->rttable_default);
+    size += snprintf(&buf[size], bufsize-size, "<td>Willingness: %d %s</td>\n", olsr_cnf->willingness, olsr_cnf->willingness_auto ? "(auto)" : "");
+
+    if (olsr_cnf->lq_level == 0) {
+      size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n"
+                                                  "<td>Hysteresis: %s</td>\n", olsr_cnf->use_hysteresis ? "Enabled" : "Disabled");
+      if (olsr_cnf->use_hysteresis) {
+        size += snprintf(&buf[size], bufsize-size, "<td>Hyst scaling: %0.2f</td>\n", olsr_cnf->hysteresis_param.scaling);
+        size += snprintf(&buf[size], bufsize-size, "<td>Hyst lower/upper: %0.2f/%0.2f</td>\n", olsr_cnf->hysteresis_param.thr_low, olsr_cnf->hysteresis_param.thr_high);
+      }
+    }
+
+    size += snprintf(&buf[size], bufsize-size, "</tr>\n<tr>\n"
+                                               "<td>LQ extension: %s</td>\n", olsr_cnf->lq_level ? "Enabled" : "Disabled");
+    if (olsr_cnf->lq_level) {
+      size += snprintf(&buf[size], bufsize-size,
+                       "<td>LQ level: %d</td>\n"
+                       "<td>LQ aging: %f</td>\n",
+                       olsr_cnf->lq_level,
+                       olsr_cnf->lq_aging);
+    }
+    size += snprintf(&buf[size], bufsize-size, "</tr></table>\n");
+
+    size += snprintf(&buf[size], bufsize-size, "<h2>Interfaces</h2>\n");
+    size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\">\n");
+    for (ifs = olsr_cnf->interfaces; ifs != NULL; ifs = ifs->next) {
+	const struct interface * const rifs = ifs->interf;
+	size += snprintf(&buf[size], bufsize-size, "<tr><th colspan=\"3\">%s</th>\n", ifs->name);
+	if (!rifs) {
+	  size += snprintf(&buf[size], bufsize-size, "<tr><td colspan=\"3\">Status: DOWN</td></tr>\n");
+          continue;
+        }
+
+	if (olsr_cnf->ip_version == AF_INET) {
+          struct ipaddr_str addrbuf, maskbuf, bcastbuf;
+	  size += snprintf(&buf[size], bufsize-size,
+                           "<tr>\n"
+                           "<td>IP: %s</td>\n"
+                           "<td>MASK: %s</td>\n"
+                           "<td>BCAST: %s</td>\n"
+                           "</tr>\n",
+                           ip4_to_string(&addrbuf, rifs->int_addr.sin_addr),
+                           ip4_to_string(&maskbuf, rifs->int_netmask.sin_addr),
+                           ip4_to_string(&bcastbuf, rifs->int_broadaddr.sin_addr));
+	} else {
+          struct ipaddr_str addrbuf, maskbuf;
+	  size += snprintf(&buf[size], bufsize-size,
+                           "<tr>\n"
+                           "<td>IP: %s</td>\n"
+                           "<td>MCAST: %s</td>\n"
+                           "<td></td>\n"
+                           "</tr>\n",
+                           ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr),
+                           ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr));
+        }	
+        size += snprintf(&buf[size], bufsize-size,
+                         "<tr>\n"
+                         "<td>MTU: %d</td>\n"
+                         "<td>WLAN: %s</td>\n"
+                         "<td>STATUS: UP</td>\n"
+                         "</tr>\n",
+                         rifs->int_mtu,
+                         rifs->is_wireless ? "Yes" : "No");
+    }
+    size += snprintf(&buf[size], bufsize-size, "</table>\n");
+
+    size += snprintf(&buf[size], bufsize-size,
+                     "<em>Olsrd is configured to %s if no interfaces are available</em><br>\n",
+                     olsr_cnf->allow_no_interfaces ? "run even" : "halt");
+
+    size += snprintf(&buf[size], bufsize-size, "<h2>Plugins</h2>\n");
+    size += snprintf(&buf[size], bufsize-size, "<table width=\"100%%\" border=\"0\"><tr><th>Name</th><th>Parameters</th></tr>\n");
+    for (pentry = olsr_cnf->plugins; pentry; pentry = pentry->next)
+      {
+	size += snprintf(&buf[size], bufsize-size,
+                         "<tr><td>%s</td>\n"
+                         "<td><select>\n"
+                         "<option>KEY, VALUE</option>\n",
+                         pentry->name);
+
+	for (pparam = pentry->params; pparam; pparam = pparam->next)
+	  {
+	    size += snprintf(&buf[size], bufsize-size, "<option>\"%s\", \"%s\"</option>\n", pparam->key, pparam->value);
+	  }
+	size += snprintf(&buf[size], bufsize-size, "</select></td></tr>\n");
+
+      }
+    size += snprintf(&buf[size], bufsize-size, "</table>\n");
+
+    size += section_title(&buf[size], bufsize-size, "Announced HNA entries");
+    if (olsr_cnf->hna_entries) {
+      struct ip_prefix_list *hna;
+      size += snprintf(&buf[size], bufsize-size, "<tr><th>Network</th></tr>\n");
+      for (hna = olsr_cnf->hna_entries; hna; hna = hna->next) {
+        struct ipaddr_str netbuf;
+        size += snprintf(&buf[size], bufsize-size,
+                         "<tr><td>%s/%d</td></tr>\n",
+                         olsr_ip_to_string(&netbuf, &hna->net.prefix),
+                         hna->net.prefix_len);
+      }
+    } else {
+      size += snprintf(&buf[size], bufsize-size, "<tr><td></td></tr>\n");
+    }
+    size += snprintf(&buf[size], bufsize-size, "</table>\n");
+    return size;
+}
+
+
+
+static int build_neigh_body(char *buf, olsr_u32_t bufsize)
+{
+  struct neighbor_entry *neigh;
+  struct link_entry *link = NULL;
+  int size = 0;
+  const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
+
+  size += section_title(&buf[size], bufsize-size, "Links");
+
+  size += snprintf(&buf[size], bufsize-size,
+                   "<tr><th align=\"center\"%s>Local IP</th><th align=\"center\"%s>Remote IP</th><th align=\"right\">Hysteresis</th>", colspan, colspan);
+  if (olsr_cnf->lq_level > 0) {
+    size += snprintf(&buf[size], bufsize-size,
+                     "<th align=\"right\">LinkCost</th>");
+  }
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+
+  /* Link set */
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    size += snprintf(&buf[size], bufsize-size, "<tr>");
+    size += build_ipaddr_with_link(&buf[size], bufsize, &link->local_iface_addr, -1);
+    size += build_ipaddr_with_link(&buf[size], bufsize, &link->neighbor_iface_addr, -1);
+    size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%0.2f</td>", link->L_link_quality);
+    if (olsr_cnf->lq_level > 0) {
+      struct lqtextbuffer lqbuffer1, lqbuffer2;
+      size += snprintf(&buf[size], bufsize-size,
+                       "<td align=\"right\">(%s) %s</td>",
+                       get_link_entry_text(link, '/', &lqbuffer1),
+                       get_linkcost_text(link->linkcost, OLSR_FALSE, &lqbuffer2));
+    }
+    size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+
+  size += snprintf(&buf[size], bufsize-size, "</table>\n");
+
+  size += section_title(&buf[size], bufsize-size, "Neighbors");
+  size += snprintf(&buf[size], bufsize-size,
+                   "<tr><th align=\"center\"%s>IP Address</th><th align=\"center\">SYM</th><th align=\"center\">MPR</th><th align=\"center\">MPRS</th><th align=\"center\">Willingness</th><th>2 Hop Neighbors</th></tr>\n", colspan);
+  /* Neighbors */
+  OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
+
+    struct neighbor_2_list_entry *list_2;
+    int thop_cnt;
+    size += snprintf(&buf[size], bufsize-size, "<tr>");
+    size += build_ipaddr_with_link(&buf[size], bufsize, &neigh->neighbor_main_addr, -1);
+    size += snprintf(&buf[size], bufsize-size,
+                     "<td align=\"center\">%s</td>"
+                     "<td align=\"center\">%s</td>"
+                     "<td align=\"center\">%s</td>"
+                     "<td align=\"center\">%d</td>",
+                     (neigh->status == SYM) ? "YES" : "NO",
+                     neigh->is_mpr ? "YES" : "NO",
+                     olsr_lookup_mprs_set(&neigh->neighbor_main_addr) ? "YES" : "NO",
+                     neigh->willingness);
+
+    size += snprintf(&buf[size], bufsize-size, "<td><select>\n"
+                     "<option>IP ADDRESS</option>\n");
+
+
+    for (list_2 = neigh->neighbor_2_list.next, thop_cnt = 0;
+         list_2 != &neigh->neighbor_2_list;
+         list_2 = list_2->next, thop_cnt++) {
+      struct ipaddr_str strbuf;
+      size += snprintf(&buf[size], bufsize-size, "<option>%s</option>\n",
+                       olsr_ip_to_string(&strbuf, &list_2->neighbor_2->neighbor_2_addr));
+    }
+    size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", thop_cnt);
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
+
+  size += snprintf(&buf[size], bufsize-size, "</table>\n");
+  return size;
+}
+
+static int build_topo_body(char *buf, olsr_u32_t bufsize)
+{
+  int size = 0;
+  struct tc_entry *tc;
+  const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
+
+  size += section_title(&buf[size], bufsize-size, "Topology Entries");
+  size += snprintf(&buf[size], bufsize-size, "<tr><th align=\"center\"%s>Destination IP</th><th align=\"center\"%s>Last Hop IP</th>", colspan, colspan);
+  if (olsr_cnf->lq_level > 0) {
+    size += snprintf(&buf[size], bufsize-size, "<th align=\"right\">Linkcost</th>");
+  }
+  size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+
+  OLSR_FOR_ALL_TC_ENTRIES(tc) {
+      struct tc_edge_entry *tc_edge;
+      OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+      	if (tc_edge->edge_inv)  {
+          size += snprintf(&buf[size], bufsize-size, "<tr>");
+          size += build_ipaddr_with_link(&buf[size], bufsize, &tc_edge->T_dest_addr, -1);
+          size += build_ipaddr_with_link(&buf[size], bufsize, &tc->addr, -1);
+          if (olsr_cnf->lq_level > 0) {
+            struct lqtextbuffer lqbuffer1, lqbuffer2;
+              size += snprintf(&buf[size], bufsize-size,
+                               "<td align=\"right\">(%s) %s</td>\n",
+                               get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1),
+                               get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2));
+          }
+          size += snprintf(&buf[size], bufsize-size, "</tr>\n");
+      	}
+      } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+
+  size += snprintf(&buf[size], bufsize-size, "</table>\n");
+
+  return size;
+}
+
+static int build_mid_body(char *buf, olsr_u32_t bufsize)
+{
+  int size = 0;
+  int idx;
+  const char *colspan = resolve_ip_addresses ? " colspan=\"2\"" : "";
+
+  size += section_title(&buf[size], bufsize-size, "MID Entries");
+  size += snprintf(&buf[size], bufsize-size,
+                   "<tr><th align=\"center\"%s>Main Address</th><th>Aliases</th></tr>\n", colspan);
+
+  /* MID */
+  for (idx = 0; idx < HASHSIZE; idx++) {
+    struct mid_entry *entry;
+    for (entry = mid_set[idx].next; entry != &mid_set[idx]; entry = entry->next) {
+      int mid_cnt;
+      struct mid_address *alias;
+      size += snprintf(&buf[size], bufsize-size, "<tr>");
+      size += build_ipaddr_with_link(&buf[size], bufsize, &entry->main_addr, -1);
+      size += snprintf(&buf[size], bufsize-size, "<td><select>\n<option>IP ADDRESS</option>\n");
+
+      for (mid_cnt = 0, alias = entry->aliases; alias != NULL; alias = alias->next_alias, mid_cnt++) {
+        struct ipaddr_str strbuf;
+        size += snprintf(&buf[size], bufsize-size, "<option>%s</option>\n", olsr_ip_to_string(&strbuf, &alias->alias));
+      }
+      size += snprintf(&buf[size], bufsize-size, "</select> (%d)</td></tr>\n", mid_cnt);
+    }
+  }
+
+  size += snprintf(&buf[size], bufsize-size, "</table>\n");
+  return size;
+}
+
+
+static int build_nodes_body(char *buf, olsr_u32_t bufsize)
+{
+  int size = 0;
+
+  size += build_neigh_body(&buf[size], bufsize-size);
+  size += build_topo_body(&buf[size], bufsize-size);
+  size += build_mid_body(&buf[size], bufsize-size);
+
+  return size;
+}
+
+static int build_all_body(char *buf, olsr_u32_t bufsize)
+{
+  int size = 0;
+
+  size += build_config_body(&buf[size], bufsize-size);
+  size += build_routes_body(&buf[size], bufsize-size);
+  size += build_neigh_body(&buf[size], bufsize-size);
+  size += build_topo_body(&buf[size], bufsize-size);
+  size += build_mid_body(&buf[size], bufsize-size);
+
+  return size;
+}
+
+
+static int build_about_body(char *buf, olsr_u32_t bufsize)
+{
+  return snprintf(buf, bufsize,
+                  "<strong>" PLUGIN_NAME " version " PLUGIN_VERSION "</strong><br/>\n"
+                  "by Andreas T&oslash;nnesen (C)2005.<br/>\n"
+                  "Compiled "
+#ifdef ADMIN_INTERFACE
+                           "<em>with experimental admin interface</em> "
+#endif
+                                                                      "%s at %s<hr/>\n"
+                  "This plugin implements a HTTP server that supplies\n"
+                  "the client with various dynamic web pages representing\n"
+                  "the current olsrd status.<br/>The different pages include:\n"
+                  "<ul>\n<li><strong>Configuration</strong> - This page displays information\n"
+                  "about the current olsrd configuration. This includes various\n"
+                  "olsr settings such as IP version, MID/TC redundancy, hysteresis\n"
+                  "etc. Information about the current status of the interfaces on\n"
+                  "which olsrd is configured to run is also displayed. Loaded olsrd\n"
+                  "plugins are shown with their plugin parameters. Finally all local\n"
+                  "HNA entries are shown. These are the networks that the local host\n"
+                  "will anounce itself as a gateway to.</li>\n"
+                  "<li><strong>Routes</strong> - This page displays all routes currently set in\n"
+                  "the kernel <em>by olsrd</em>. The type of route is also displayed(host\n"
+                  "or HNA).</li>\n"
+                  "<li><strong>Links/Topology</strong> - This page displays all information about\n"
+                  "links, neighbors, topology, MID and HNA entries.</li>\n"
+                  "<li><strong>All</strong> - Here all the previous pages are displayed as one.\n"
+                  "This is to make all information available as easy as possible(for example\n"
+                  "for a script) and using as few resources as possible.</li>\n"
+#ifdef ADMIN_INTERFACE
+                  "<li><strong>Admin</strong> - This page is highly experimental(and unsecure)!\n"
+                  "As of now it is not working at all but it provides a impression of\n"
+                  "the future possibilities of httpinfo. This is to be a interface to\n"
+                  "changing olsrd settings in realtime. These settings include various\n"
+                  "\"basic\" settings and local HNA settings.</li>\n"
+#endif
+                  "<li><strong>About</strong> - this help page.</li>\n</ul>"
+                  "<hr/>\n"
+                  "Send questions or comments to\n"
+                  "<a href=\"mailto:olsr-users@olsr.org\">olsr-users@olsr.org</a> or\n"
+                  "<a href=\"mailto:andreto-at-olsr.org\">andreto-at-olsr.org</a><br/>\n"
+                  "Official olsrd homepage: <a href=\"http://www.olsr.org/\">http://www.olsr.org</a><br/>\n",
+                  build_date, build_host);
+}
+
+static int build_cfgfile_body(char *buf, olsr_u32_t bufsize)
+{
+  int size = 0;
+
+  size += snprintf(&buf[size], bufsize-size,
+                   "\n\n"
+                   "<strong>This is a automatically generated configuration\n"
+                   "file based on the current olsrd configuration of this node.<br/>\n"
+                   "<hr/>\n"
+                   "<pre>\n");
+
+#ifdef NETDIRECT
+  {
+        /* Hack to make netdirect stuff work with
+           olsrd_write_cnf_buf
+        */
+        char tmpBuf[10000];
+        size = olsrd_write_cnf_buf(olsr_cnf, tmpBuf, 10000);
+        snprintf(&buf[size], bufsize-size, tmpBuf);
+  }
+#else
+  size += olsrd_write_cnf_buf(olsr_cnf, &buf[size], bufsize-size);
+#endif
+
+  if (size < 0) {
+    size = snprintf(buf, size, "ERROR GENERATING CONFIGFILE!\n");
+  }
+
+  size += snprintf(&buf[size], bufsize-size, "</pre>\n<hr/>\n");
+
+#if 0
+  printf("RETURNING %d\n", size);
+#endif
+  return size;
+}
+
+static int check_allowed_ip(const struct allowed_net * const allowed_nets, const union olsr_ip_addr * const addr)
+{
+    const struct allowed_net *alln;
+    for (alln = allowed_nets; alln != NULL; alln = alln->next) {
+        if ((addr->v4.s_addr & alln->mask.v4.s_addr) == (alln->net.v4.s_addr & alln->mask.v4.s_addr)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+
+#if 0
+/*
+ * 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.
+ */
+
+int netsprintf(char *str, const char* format, ...)
+{
+	va_list arg;
+	int rv;
+	va_start(arg, format);
+	rv = vsprintf(str, format, arg);
+	va_end(arg);
+	if (0 != netsprintf_direct) {
+		if (0 == netsprintf_error) {
+			if (0 > send(client_sockets[curr_clients], str, rv, 0)) {
+				olsr_printf(1, "(HTTPINFO) Failed sending data to client!\n");
+				netsprintf_error = 1;
+			}
+		}
+		return 0;
+	}
+	return rv;
+}
+#endif
+
+static ssize_t writen(int fd, const void *buf, size_t count)
+{
+    size_t bytes_left = count;
+    const char *p = buf;
+    while (bytes_left > 0) {
+        const ssize_t written = write(fd, p, bytes_left);
+        if (written == -1)  { /* error */
+            if (errno == EINTR ) {
+                continue;
+            }
+            return -1;
+        }
+        /* We wrote something */
+        bytes_left -= written;
+        p += written;
+    }
+    return count;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_httpinfo.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_HTTP_INFO
+#define _OLSRD_HTTP_INFO
+
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+
+
+#define HTTP_VERSION "HTTP/1.1"
+
+/**Response types */
+#define HTTP_200 HTTP_VERSION " 200 OK\r\n"
+#define HTTP_400 HTTP_VERSION " 400 Bad Request\r\n"
+#define HTTP_404 HTTP_VERSION " 404 Not Found\r\n"
+
+
+#define HTTP_400_MSG "<html><h1>400 - ERROR</h1><hr><i>" PLUGIN_NAME " version " PLUGIN_VERSION  "</i></html>"
+#define HTTP_404_MSG "<html><h1>404 - ERROR, no such file</h1><hr>This server does not support file requests!<br><br><i>" PLUGIN_NAME " version " PLUGIN_VERSION  "</i></html>"
+
+
+typedef enum {
+    HTTP_BAD_REQ,
+    HTTP_BAD_FILE,
+    HTTP_OK
+} http_header_type;
+
+
+struct http_stats {
+    olsr_u32_t ok_hits;
+    olsr_u32_t dyn_hits;
+    olsr_u32_t err_hits;
+    olsr_u32_t ill_hits;
+};
+
+extern struct olsrd_config *olsr_cfg;
+
+/* Destructor function */
+void olsr_plugin_exit(void);
+void olsr_plugin_exit(void);
+
+#if 0
+extern int netsprintf(char *str, const char* format, ...);
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#include "olsr.h"
+#include "olsrd_plugin.h"
+#include "olsr_cfg.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#ifndef WIN32
+#include <arpa/nameser.h>
+#endif
+
+#include "olsrd_httpinfo.h"
+
+
+int http_port = 0;
+int resolve_ip_addresses = 0;
+struct allowed_net *allowed_nets = NULL;
+
+static void my_init(void) __attribute__ ((constructor));
+static void my_fini(void) __attribute__ ((destructor));
+
+static int add_plugin_ipnet(const char *value, void *data, set_plugin_parameter_addon);
+static int add_plugin_ipaddr(const char *value, void *data, set_plugin_parameter_addon);
+
+static int insert_plugin_ipnet(const char *sz_net, const char *sz_mask, struct allowed_net **allowed_nets);
+
+/*
+ * Defines the version of the plugin interface that is used
+ * THIS IS NOT THE VERSION OF YOUR PLUGIN!
+ * Do not alter unless you know what you are doing!
+ */
+int olsrd_plugin_interface_version(void)
+{
+    return PLUGIN_INTERFACE_VERSION;
+}
+
+/**
+ *Constructor
+ */
+static void my_init(void)
+{
+    /* Print plugin info to stdout */
+    printf("%s\n", MOD_DESC);
+}
+
+/**
+ *Destructor
+ */
+static void my_fini(void)
+{
+    /* 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();
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "port",   .set_plugin_parameter = &set_plugin_port,      .data = &http_port },
+    { .name = "host",   .set_plugin_parameter = &add_plugin_ipaddr,    .data = &allowed_nets },
+    { .name = "net",    .set_plugin_parameter = &add_plugin_ipnet,     .data = &allowed_nets },
+    { .name = "resolve",.set_plugin_parameter = &set_plugin_boolean,          .data = &resolve_ip_addresses },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+static int insert_plugin_ipnet(const char *sz_net, const char *sz_mask, struct allowed_net **allowed_nets)
+{
+    struct allowed_net *an;
+
+    an = olsr_malloc(sizeof(*an), __func__);
+    if (an == NULL) {
+        fprintf(stderr, "(HTTPINFO) register param net out of memory!\n");
+        exit(0);
+    }
+
+    if(inet_aton(sz_net, &an->net.v4) == 0 || 
+       inet_aton(sz_mask, &an->mask.v4) == 0) {
+        free(an);
+	return 1;
+    }
+    an->next = *allowed_nets;
+    *allowed_nets = an;
+    return 0;
+}
+
+static int add_plugin_ipnet(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    char sz_net[100], sz_mask[100]; /* IPv6 in the future */
+
+    if(sscanf(value, "%99s %99s", sz_net, sz_mask) != 2) {
+        olsr_printf(1, "(HTTPINFO) Error parsing net param \"%s\"!\n", value);
+        return 0;
+    }
+    return insert_plugin_ipnet(sz_net, sz_mask, data);
+}
+
+static int add_plugin_ipaddr(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    return insert_plugin_ipnet(value, "255.255.255.255", data);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/src/olsrd_plugin.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_PLUGIN_DEFS
+#define _OLSRD_PLUGIN_DEFS
+
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/times.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+
+#include "olsr_types.h"
+#include "../../../src/olsrd_plugin.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "mpr_selector_set.h"
+#include "routing_table.h"
+
+#define PLUGIN_NAME    "Httpinfo olsrd plugin"
+#define PLUGIN_VERSION "0.1"
+#define PLUGIN_AUTHOR   "Andreas Tønnesen"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+extern int http_port;
+extern int resolve_ip_addresses;
+
+/* Allowed hosts stuff */
+
+struct allowed_net {
+    union olsr_ip_addr       net;
+    union olsr_ip_addr       mask;
+    struct allowed_net      *next;
+};
+
+extern struct allowed_net    *allowed_nets;
+
+
+/****************************************************************************
+ *                Functions that the plugin MUST provide                    *
+ ****************************************************************************/
+
+/* Initialization function */
+int olsrd_plugin_init(void);
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+
+int olsrd_plugin_interface_version(void);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/httpinfo/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/httpinfo/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,56 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_mini
+PLUGIN_VER =	0.1
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/README_MINI ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/README_MINI
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/README_MINI	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/README_MINI	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,36 @@
+---------------------------------------------------------------------
+MINI PLUGIN FOR OLSRD
+by Bruno Randolf <bruno.randolf@4g-systems.biz>
+---------------------------------------------------------------------
+
+This is a minimal example plugin to demonstrate the functions a plugin
+must implement. It documents the minimal requirements for the new
+plugin interface and is a good start for creating new plugins and 
+testing the plugin loader.
+
+This plugin does nothing, except printing messages when it is loaded
+and unloaded.
+
+
+---------------------------------------------------------------------
+PLUGIN PARAMETERS (PlParam)
+---------------------------------------------------------------------
+
+PlParam "test" "anything"
+	just for a test: print the parameter.
+
+
+---------------------------------------------------------------------
+SAMPLE CONFIG
+---------------------------------------------------------------------
+
+add in /etc/olsrd.conf:
+
+LoadPlugin "olsrd_mini.so.0.1"
+{
+	PlParam "test" "hello"
+}
+
+
+---------------------------------------------------------------------
+EOF / 26.05.2005
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+
+ /*
+ * Example plugin for olsrd.org OLSR daemon
+ * Only the bare minimum
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../../src/olsrd_plugin.h"
+
+#include "olsrd_plugin.h"
+#include "olsr.h"
+
+#define PLUGIN_INTERFACE_VERSION 5
+
+
+/****************************************************************************
+ *                Functions that the plugin MUST provide                    *
+ ****************************************************************************/
+ 
+/**
+ * Plugin interface version
+ * Used by main olsrd to check plugin interface version
+ */
+int olsrd_plugin_interface_version(void)
+{
+    return PLUGIN_INTERFACE_VERSION;
+}
+
+
+static int set_plugin_test(const char *value, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    printf("\n*** MINI: parameter test: %s\n", value);
+    return 0;
+}
+
+/**
+ * Register parameters from config file
+ * Called for all plugin parameters
+ */
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "test",   .set_plugin_parameter = &set_plugin_test,      .data = NULL },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+
+/**
+ * Initialize plugin
+ * Called after all parameters are passed
+ */
+int
+olsrd_plugin_init(void)
+{
+	printf("*** MINI: plugin_init\n");
+	
+	/* call a function from main olsrd */
+	olsr_printf(2, "*** MINI: printed this with olsr_printf\n");
+	
+	return 1;
+}
+
+
+/****************************************************************************
+ *       Optional private constructor and destructor functions              *
+ ****************************************************************************/
+
+/* attention: make static to avoid name clashes */
+
+static void my_init(void) __attribute__ ((constructor));
+static void my_fini(void) __attribute__ ((destructor));
+
+
+/**
+ * Optional Private Constructor
+ */
+static void my_init(void)
+{
+    printf("*** MINI: constructor\n");
+}
+
+
+/**
+ * Optional Private Destructor
+ */
+static void my_fini(void)
+{
+    printf("*** MINI: destructor\n");
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/src/olsrd_plugin.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_PLUGIN_MINI
+#define _OLSRD_PLUGIN_MINI
+
+
+/****************************************************************************
+ *                Functions that the plugin MUST provide                    *
+ ****************************************************************************/
+
+
+/* Initialization function */
+int
+olsrd_plugin_init(void);
+
+int 
+olsrd_plugin_interface_version(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/mini/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/mini/version-script.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,61 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_nameservice
+PLUGIN_VER =	0.3
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+ifeq ($(OS),win32)
+default_target install clean:
+	@echo "**** We use the regex library here. Does Win32 has something like this?"
+else
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/README_NAMESERVICE ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/README_NAMESERVICE
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/README_NAMESERVICE	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/README_NAMESERVICE	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,180 @@
+---------------------------------------------------------------------
+NAMESERVICE PLUGIN FOR OLSRD
+by Bruno Randolf <bruno.randolf@4g-systems.biz>
+---------------------------------------------------------------------
+
+a simple DNS replacement for OLSR networks
+
+this plugin distributes host name (DNS) information over OLSR. every 
+node which runs the olsr daemon can announce it's own name, names for
+other IP adresses it is associated with (HNAs) and if it is running
+a "real" nameserver which can resolve other (internet) names (upstream 
+dns server).
+
+the nodes in the network collect this information and write the host 
+names to a file (possibly /etc/hosts), and the 3 nearest upstream 
+nameservers to another file (possibly /etc/resolv.conf).
+
+these files can be used to resolve hostnames on the local system and/or
+be read by a DNS server like "dnsmasq", to make the names available 
+via the ordinary DNS protocol to other clients as well.
+
+the default location of the hosts file is
+"/var/run/hosts_olsr" on unixes
+"C:\WINDOWS\hosts_olsr" on windows
+
+
+---------------------------------------------------------------------
+PLUGIN PARAMETERS (PlParam)
+---------------------------------------------------------------------
+
+PlParam "name" "my-name.mesh"
+	the name of this OLSR node (main address).
+	can be specified multiple times for different names.
+
+PlParam "IP.ADDR" "another-name.mesh"
+	a name for a specified IP address.
+	the IP address has to be either from one of the olsr 
+	interfaces or within a HNA network we announce.
+	can be specified multiple times.
+
+PlParam "hosts-file" "/path/to/hosts_file"
+	which file to write to (usually /etc/hosts).
+	(default: /var/run/hosts_olsr)
+
+PlParam "suffix" ".olsr"
+	local suffix which is appended to all received names.
+	(default: "")
+
+PlParam "add-hosts" "/path/to/file"
+	copy contents of this additional hosts file to output file.
+	this is practical if you alreay use your /etc/hosts file.
+
+PlParam "dns-server" "IP.ADDR"
+	anounce that this IP has a full (upstream) DNS server. if 
+	IP.ADDR is not specified (""), the main address is used.
+	nodes which don't know a nameserver will automatically use
+	this nameserver.
+
+PlParam "resolv-file" "/path/to/resolv.conf"
+	path to resolv.conf file (usually /etc/resolv.conf)
+	if set, the 3 nearest (best ETX) upstream nameservers annonced 
+	by other nodes in the network are written to this file
+
+PlParam "interval" "SEC"
+	interval for sending NAME messages in seconds.
+	(default: 120 - 2 minutes)
+
+PlParam "timeout" "SEC"
+	validity time for received NAME messages in seconds.
+	(default: 3600 - 1 hour)
+
+PlParam "lat" "12.123"
+	Float: Decimal latitude for this node to be flooded in the mesh
+
+PlParam "lon" "12.123"
+	Float: Decimal longitude for this node to be flooded in the mesh
+
+PlParam "latlon-file" "/var/run/latlon.js"
+	Filename to write Javascript statements to. Default is "latlon.js"
+	(either /var/run or windows directory). This file is written, if
+	the "lat" and "lon" parameters are set. It has this format:
+
+	/* One or more mid-aliases of multihomed nodes */
+	Mid('fromip','toip');
+
+	/* One special Node() entry for this node
+	 * defhna means: This node announces hna 0.0.0.0/0
+	 * defroute means: The current neighbour IP for 0.0.0.0/0
+	 */
+	Self('mainip',lat,lon,defhna?1:0,'defroute','name');
+
+	/* One or more node entires for other nodes */
+	Node('mainip',lat,lon,this-node-defhna?1:0,'defroute','name');
+
+	/* One or more links between nodes */
+	Link('fromip','toip',lq,nlq,etx);
+
+PlParam "latlon-infile" "name-of-input.txt"
+	Filename to read lat/lon positions from. Meant to be used
+	by a walking GPS receiver. Just write comma separated decimal
+	latitude and longitude to this file. Will overwrite the
+	"lat" and "lon" parameters during runtime.
+
+PlParam "sighup-pid-file" "/path/to/pidfile.pid"
+        (*nix systems only) Sends a HUP signal to the process specified
+        by the pidfile (usually /var/run/dnsmasq.pid) when the host name
+        table changes. This is useful for letting dnsmasq or bind know
+        they have to reload their hosts file.
+
+PlParam "name-change-script" "/path/to/script"
+        Script to execute when there is a change in the hosts names
+        table. Useful for executing a script that uses the hosts file
+        to keep a website or a database updated.
+
+PlParam "services-change-script" "/path/to/script"
+        Similar to the previous parameter. Script to execute when there
+        is a change in the services list propagated by the nameserver
+        plugin. Useful for executing a script that uses the services file
+        to keep a website or a database updated.
+
+---------------------------------------------------------------------
+SAMPLE CONFIG
+---------------------------------------------------------------------
+
+add in /etc/olsrd.conf:
+
+LoadPlugin "olsrd_nameservice.so.0.2"
+{
+	PlParam "name" "thisismyname"
+	PlParam "hosts-file" "/etc/hosts"
+	PlParam "resolv-file" "/etc/resolv.conf"
+}
+
+
+---------------------------------------------------------------------
+USING THE NAME INFORMATION
+---------------------------------------------------------------------
+
+to use the name information distributed by the plugin actually for
+name resolution you can do one of the following.
+
+UNIX VARIANTS:
+
+* overwrite /etc/hosts
+	be sure you have nothing in /etc/hosts which you still need and
+	configure the plugin with PlParam "host-file" "/etc/hosts"
+
+* link /etc/hosts
+	ln -s /var/run/hosts_olsr /etc/hosts
+
+* use dnsmasq
+	if you want to make the names available via ordinary DNS
+	you can use dnsmasq to read the hosts file and serve it to
+	users. add "addn-hosts=/var/run/hosts_olsr" to dnsmasq.conf 
+        and:
+               PlParam "sighup-pid-file" "/var/run/dnsmasq.pid"
+
+        to your nameservice plugin configuration.
+
+        This is especially usefull for infrastructure mesh networks that
+        can't afford to run olsrd on all the clients but wish to provide
+        DNS to them. This is solved by running dnsmasq and olsrd with
+        this setup on "edge" nodes that provide connectivity.
+
+WINDOWS:
+
+* overwrite C:\WINDOWS\system32\drivers\etc\hosts
+	be sure you have nothing in the file which you still need 
+	and configure the plugin with
+        PlParam "hosts-file" "C:\WINDOWS\system32\drivers\etc\hosts"
+
+---------------------------------------------------------------------
+TODO
+---------------------------------------------------------------------
+  
+  * implement a small DNS server into the plugin?
+  * or make dynamic DNS updates for bind?
+
+---------------------------------------------------------------------
+EOF / 30.06.2007
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/compat.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/compat.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/compat.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/compat.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,28 @@
+#include "compat.h"
+
+#ifndef linux
+#include <stdlib.h>
+#include <string.h>
+
+/* strndup() is a GNU extention */
+char *
+strndup(const char *ptr, size_t size)
+{
+  size_t len = strlen(ptr);
+  char *ret = NULL;
+
+  if(len > size)
+    len = size;
+
+  ret = malloc(len + 1);
+  
+  if(!ret)
+    return NULL;
+
+  memcpy(ret, ptr, len);
+  ret[len] = '\0';
+
+  return ret;
+}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/compat.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/compat.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/compat.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/compat.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,9 @@
+#ifndef _NAMESERVICE_COMPAT
+#define _NAMESERVICE_COMPAT
+
+#include <sys/types.h>
+
+char *
+strndup(const char *ptr, size_t size);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/mapwrite.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/mapwrite.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/mapwrite.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/mapwrite.c	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2007, Sven-Ola <sven-ola-aet-gmx.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the UniK olsr daemon 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.
+ *
+ */
+
+ 
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "defs.h"
+#include "scheduler.h"
+#include "nameservice.h"
+#include "mid_set.h"
+#include "tc_set.h"
+#include "ipcalc.h"
+#include "lq_plugin.h"
+
+#include "mapwrite.h"
+
+static char my_latlon_str[48];
+
+/**
+ * lookup a nodes position
+ */
+static char* lookup_position_latlon(union olsr_ip_addr *ip)
+{
+  int hash;
+  struct db_entry *entry;
+  struct list_node *list_head, *list_node;
+
+  if (ipequal(ip, &olsr_cnf->main_addr)) {
+    return my_latlon_str;
+  }
+
+  for (hash = 0; hash < HASHSIZE; hash++) {
+      list_head = &latlon_list[hash];
+      for (list_node = list_head->next; list_node != list_head;
+           list_node = list_node->next) {
+
+          entry = list2db(list_node);
+
+      if (entry->names && ipequal(&entry->originator, ip)) {
+        return entry->names->name;
+      }
+    }
+  }
+  return NULL;
+}
+
+/**
+ * write latlon positions to a file
+ */
+void mapwrite_work(FILE* fmap)
+{
+  int hash;
+  struct olsr_if *ifs;
+  union olsr_ip_addr ip;
+  struct ipaddr_str strbuf1, strbuf2;
+  struct tc_entry *tc;
+  struct tc_edge_entry *tc_edge;
+
+  if (!my_names || !fmap) return;
+
+  for (ifs = olsr_cnf->interfaces; ifs; ifs = ifs->next)
+  {
+    if (0 != ifs->interf)
+    {
+      if (olsr_cnf->ip_version == AF_INET)
+      {
+        if (!(ip4equal((struct in_addr *)&olsr_cnf->main_addr, &ifs->interf->int_addr.sin_addr)))
+        {
+          if (0 > fprintf(fmap, "Mid('%s','%s');\n",
+            olsr_ip_to_string(&strbuf1, &olsr_cnf->main_addr),
+            olsr_ip_to_string(&strbuf2, (union olsr_ip_addr *)&ifs->interf->int_addr.sin_addr)))
+          {
+            return;
+          }
+        }
+      }
+      else if (!(ip6equal((struct in6_addr *)&olsr_cnf->main_addr, &ifs->interf->int6_addr.sin6_addr)))
+      {
+        if (0 > fprintf(fmap, "Mid('%s','%s');\n",
+          olsr_ip_to_string(&strbuf1, &olsr_cnf->main_addr),
+          olsr_ip_to_string(&strbuf2, (union olsr_ip_addr *)&ifs->interf->int6_addr.sin6_addr)))
+        {
+          return;
+        }
+      }
+    }
+  }
+
+  for (hash = 0; hash < HASHSIZE; hash++) 
+  {
+    struct mid_entry *entry = mid_set[hash].next;
+    while(entry != &mid_set[hash])
+    {
+      struct mid_address *alias = entry->aliases;
+      while(alias)
+      {
+        if (0 > fprintf(fmap, "Mid('%s','%s');\n",
+          olsr_ip_to_string(&strbuf1, &entry->main_addr),
+          olsr_ip_to_string(&strbuf2, &alias->alias)))
+        {
+          return;
+        }
+        alias = alias->next_alias;
+      }
+      entry = entry->next;
+    }
+  }
+  lookup_defhna_latlon(&ip);
+  sprintf(my_latlon_str, "%f,%f,%d", my_lat, my_lon, get_isdefhna_latlon());
+  if (0 > fprintf(fmap, "Self('%s',%s,'%s','%s');\n",
+    olsr_ip_to_string(&strbuf1, &olsr_cnf->main_addr), my_latlon_str, 
+    olsr_ip_to_string(&strbuf2, &ip), my_names->name))
+  {
+    return;
+  }
+  for (hash = 0; hash < HASHSIZE; hash++) 
+  {
+    struct db_entry *entry;
+	struct list_node *list_head, *list_node;
+
+    list_head = &latlon_list[hash];
+    for (list_node = list_head->next; list_node != list_head;
+         list_node = list_node->next) {
+        
+      entry = list2db(list_node);
+
+      if (NULL != entry->names)
+      {
+        if (0 > fprintf(fmap, "Node('%s',%s,'%s','%s');\n",
+          olsr_ip_to_string(&strbuf1, &entry->originator),
+          entry->names->name, olsr_ip_to_string(&strbuf2, &entry->names->ip),
+          lookup_name_latlon(&entry->originator)))
+        {
+          return;
+        }
+      }
+    }
+  }
+
+  OLSR_FOR_ALL_TC_ENTRIES(tc) {
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+    char* lla = lookup_position_latlon(&tc->addr);
+    char* llb = lookup_position_latlon(&tc_edge->T_dest_addr);
+    if (NULL != lla && NULL != llb)
+    {
+      struct lqtextbuffer lqbuffer, lqbuffer2;
+      
+      /*
+       * To speed up processing, Links with both positions are named PLink()
+       */
+      if (0 > fprintf(fmap, "PLink('%s','%s',%s,%s,%s,%s);\n", 
+            olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
+            olsr_ip_to_string(&strbuf2, &tc->addr), 
+            get_tc_edge_entry_text(tc_edge, ',', &lqbuffer2),
+            get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer),
+            lla, llb))
+      {
+        return;
+      }
+    }
+    else
+    {
+      struct lqtextbuffer lqbuffer, lqbuffer2;
+      
+      /*
+       * If one link end pos is unkown, only send Link()
+       */
+      if (0 > fprintf(fmap, "Link('%s','%s',%s,%s);\n", 
+            olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
+            olsr_ip_to_string(&strbuf2, &tc->addr), 
+            get_tc_edge_entry_text(tc_edge, ',', &lqbuffer2),
+            get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer)))
+      {
+        return;
+      }
+    }
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+}
+
+#ifndef WIN32
+
+/*
+ * Windows doesn't know fifo's AFAIK. We better write
+ * to a file (done in nameservice.c, see #ifdef WIN32)
+ */
+ 
+static const char* the_fifoname = 0;
+static int fifopolltime = 0;
+
+static void mapwrite_poll(void *context __attribute__((unused)))
+{
+  fifopolltime++;
+  if (0 == (fifopolltime & 7) && 0 != the_fifoname)
+  {
+    FILE * fout;
+    /* Non-blocking means: fail open if no pipe reader */
+    int fd = open(the_fifoname, O_WRONLY | O_NONBLOCK);
+    if (0 <= fd)
+    {
+      /* 
+       * Change to blocking, otherwhise expect fprintf errors
+       */
+      fcntl(fd, F_SETFL, O_WRONLY);
+      fout = fdopen(fd, "w");
+      if (0 != fout)
+      {
+        mapwrite_work(fout);
+        fclose(fout);
+        /* Give pipe reader cpu slot to detect EOF */
+        usleep(1);
+      }
+      else
+      {
+        close(fd);
+      }
+    }
+  }
+}
+
+int mapwrite_init(const char* fifoname)
+{
+  the_fifoname = fifoname;
+  if (0 != fifoname && 0 != *fifoname)
+  {
+    unlink(fifoname);
+    if (0 > mkfifo(fifoname, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH))
+    {
+      OLSR_PRINTF(1, "mkfifo(%s): %s", fifoname, strerror(errno));
+      return OLSR_FALSE;
+    }
+    else
+    {
+      the_fifoname = fifoname;
+      olsr_start_timer(100, 5, OLSR_TIMER_PERIODIC, &mapwrite_poll, NULL, 0);
+    }
+  }
+  return OLSR_TRUE;
+}
+
+void mapwrite_exit(void)
+{
+  if (0 != the_fifoname)
+  {
+    unlink(the_fifoname);
+    /* Ignore any Error */
+    the_fifoname = 0;
+  }
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/mapwrite.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/mapwrite.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/mapwrite.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/mapwrite.h	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007, Sven-Ola <sven-ola-aet-gmx.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the UniK olsr daemon 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.
+ *
+ */
+
+ 
+#ifndef _MAPWRITE_H
+#define _MAPWRITE_H
+
+int mapwrite_init(const char* fifoname);
+void mapwrite_work(FILE* fmap);
+void mapwrite_exit(void);
+
+#endif /* _MAPWRITE_H */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/nameservice.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/nameservice.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/nameservice.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/nameservice.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1683 @@
+/*
+ * 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)
+ * Copyright (c) 2007, Sven-Ola <sven-ola@gmx.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the UniK olsr daemon 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.
+ *
+ */
+
+
+/*
+ * Dynamic linked library for UniK OLSRd
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include "olsr.h"
+#include "ipcalc.h"
+#include "net_olsr.h"
+#include "routing_table.h"
+#include "mantissa.h"
+#include "scheduler.h"
+#include "parser.h"
+#include "duplicate_set.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "link_set.h"
+
+#include "plugin_util.h"
+#include "nameservice.h"
+#include "mapwrite.h"
+#include "compat.h"
+
+
+/* config parameters */
+static char my_hosts_file[MAX_FILE + 1];
+static char my_sighup_pid_file[MAX_FILE + 1];
+
+static char my_add_hosts[MAX_FILE + 1];
+static char my_suffix[MAX_SUFFIX];
+static int my_interval = EMISSION_INTERVAL;
+static double my_timeout = NAME_VALID_TIME;
+static char my_resolv_file[MAX_FILE +1];
+static char my_services_file[MAX_FILE + 1];
+static char my_name_change_script[MAX_FILE + 1];
+static char my_services_change_script[MAX_FILE + 1];
+static char latlon_in_file[MAX_FILE + 1];
+static char my_latlon_file[MAX_FILE + 1];
+float my_lat = 0.0, my_lon = 0.0;
+
+/* 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)
+ * */
+static struct list_node name_list[HASHSIZE];
+struct name_entry *my_names = NULL;
+struct timer_entry *name_table_write = NULL;
+static olsr_bool name_table_changed = OLSR_TRUE;
+
+static struct list_node service_list[HASHSIZE];
+static struct name_entry *my_services = NULL;
+static olsr_bool service_table_changed = OLSR_TRUE;
+
+static struct list_node forwarder_list[HASHSIZE];
+static struct name_entry *my_forwarders = NULL;
+static olsr_bool forwarder_table_changed = OLSR_TRUE;
+
+struct list_node latlon_list[HASHSIZE];
+static olsr_bool latlon_table_changed = OLSR_TRUE;
+
+/* backoff timer for writing changes into a file */
+struct timer_entry *write_file_timer = NULL;
+
+/* periodic message generation */
+struct timer_entry *msg_gen_timer = NULL;
+
+/* regular expression to be matched by valid hostnames, compiled in name_init() */
+static regex_t regex_t_name;
+static regmatch_t regmatch_t_name;
+
+/* regular expression to be matched by valid service_lines, compiled in name_init() */
+static regex_t regex_t_service;
+static int pmatch_service = 10;
+static regmatch_t regmatch_t_service[10];
+
+/**
+ * do initialization
+ */
+void
+name_constructor(void) 
+{
+	int i;
+	
+#ifdef WIN32
+	int len;
+
+	GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
+	GetWindowsDirectory(my_services_file, MAX_FILE - 12);
+	GetWindowsDirectory(my_resolv_file, MAX_FILE - 12);
+
+	len = strlen(my_hosts_file);
+	if (my_hosts_file[len - 1] != '\\')
+		strscat(my_hosts_file, "\\", sizeof(my_host_file));
+	strscat(my_hosts_file, "hosts_olsr", sizeof(my_host_file));
+	
+	len = strlen(my_services_file);
+	if (my_services_file[len - 1] != '\\')
+		strscat(my_services_file, "\\", sizeof(my_services_file));
+	strscat(my_services_file, "services_olsr", sizeof(my_services_file));
+
+	len = strlen(my_resolv_file);
+	if (my_resolv_file[len - 1] != '\\')
+		strscat(my_resolv_file, "\\", sizeof(my_resolv_file));
+	strscat(my_resolv_file, "resolvconf_olsr", sizeof(my_resolv_file));
+#else
+	strscpy(my_hosts_file, "/var/run/hosts_olsr", sizeof(my_hosts_file));
+	strscpy(my_services_file, "/var/run/services_olsr", sizeof(my_services_file));
+	strscpy(my_resolv_file, "/var/run/resolvconf_olsr", sizeof(my_resolv_file));
+	*my_sighup_pid_file = 0;
+#endif
+
+	my_suffix[0] = '\0';
+	my_add_hosts[0] = '\0';
+	my_latlon_file[0] = '\0';
+	latlon_in_file[0] = '\0';
+	my_name_change_script[0] = '\0';
+	my_services_change_script[0] = '\0';
+	
+	/* init the lists heads */
+	for(i = 0; i < HASHSIZE; i++) {
+		list_head_init(&name_list[i]);
+		list_head_init(&forwarder_list[i]);
+		list_head_init(&service_list[i]);
+		list_head_init(&latlon_list[i]);
+	}
+	
+
+}
+
+
+static int set_nameservice_server(const char *value, void *data, set_plugin_parameter_addon addon)
+{
+	union olsr_ip_addr ip;
+	struct name_entry **v = data;
+	if (0 == strlen(value))
+	{
+		*v = add_name_to_list(*v, "", addon.ui, NULL);
+		OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value);
+		return 0;
+	}
+	else if (0 < inet_pton(olsr_cnf->ip_version, value, &ip))
+	{
+		*v = add_name_to_list(*v, "", addon.ui, &ip);
+		OLSR_PRINTF(1, "%s got %s\n", "Got", value);
+		return 0;
+	}
+	else
+	{
+		OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
+	}
+	return 1;
+}
+
+static int set_nameservice_name(const char *value, void *data, set_plugin_parameter_addon addon)
+{
+	struct name_entry **v = data;
+	if (0 < strlen(value))
+	{
+		*v = add_name_to_list(*v, value, addon.ui, NULL);
+		OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value);
+		return 0;
+	}
+	else
+	{
+		OLSR_PRINTF(0, "Illegal name \"%s\"", value);
+	}
+	return 1;
+}
+
+static int set_nameservice_host(const char *value, void *data, set_plugin_parameter_addon addon)
+{
+	union olsr_ip_addr ip;
+	struct name_entry **v = data;
+	if (0 < inet_pton(olsr_cnf->ip_version, addon.pc, &ip))
+	{
+		// the IP is validated later
+		*v = add_name_to_list(*v, value, NAME_HOST, &ip);
+		OLSR_PRINTF(1, "%s: %s got %s\n", "Got", addon.pc, value);
+		return 0;
+	}
+	else
+	{
+		OLSR_PRINTF(0, "%s: Illegal IP address \"%s\"", addon.pc, value);
+	}
+	return 1;
+}
+
+static int set_nameservice_float(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+	if (data != NULL)
+	{
+		sscanf(value, "%f", (float*)data);
+		OLSR_PRINTF(1, "%s float %f\n", "Got", *(float*)data);
+	}
+	else
+	{
+		OLSR_PRINTF(0, "%s float %s\n", "Ignored", value);
+	}
+	return 0;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "interval",      .set_plugin_parameter = &set_plugin_int,         .data = &my_interval },
+    { .name = "timeout",       .set_plugin_parameter = &set_nameservice_float,  .data = &my_timeout },
+    { .name = "sighup-pid-file",.set_plugin_parameter = &set_plugin_string,      .data = &my_sighup_pid_file, .addon = {sizeof(my_sighup_pid_file)} },
+    { .name = "hosts-file",    .set_plugin_parameter = &set_plugin_string,      .data = &my_hosts_file,    .addon = {sizeof(my_hosts_file)} },
+    { .name = "name-change-script", .set_plugin_parameter = &set_plugin_string,  .data = &my_name_change_script, .addon = {sizeof(my_name_change_script)} },
+    { .name = "services-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_services_change_script, .addon = {sizeof(my_services_change_script)} },
+    { .name = "resolv-file",   .set_plugin_parameter = &set_plugin_string,      .data = &my_resolv_file,   .addon = {sizeof(my_resolv_file)} },
+    { .name = "suffix",        .set_plugin_parameter = &set_plugin_string,      .data = &my_suffix,        .addon = {sizeof(my_suffix)} },
+    { .name = "add-hosts",     .set_plugin_parameter = &set_plugin_string,      .data = &my_add_hosts,     .addon = {sizeof(my_add_hosts)} },
+    { .name = "services-file", .set_plugin_parameter = &set_plugin_string,      .data = &my_services_file, .addon = {sizeof(my_services_file)} },
+    { .name = "lat",           .set_plugin_parameter = &set_nameservice_float,  .data = &my_lat },
+    { .name = "lon",           .set_plugin_parameter = &set_nameservice_float,  .data = &my_lon },
+    { .name = "latlon-file",   .set_plugin_parameter = &set_plugin_string,      .data = &my_latlon_file,   .addon = {sizeof(my_latlon_file)} },
+    { .name = "latlon-infile", .set_plugin_parameter = &set_plugin_string,      .data = &latlon_in_file,   .addon = {sizeof(latlon_in_file)} },
+    { .name = "dns-server",    .set_plugin_parameter = &set_nameservice_server, .data = &my_forwarders,    .addon = {NAME_FORWARDER} },
+    { .name = "name",          .set_plugin_parameter = &set_nameservice_name,   .data = &my_names,         .addon = {NAME_HOST} },
+    { .name = "service",       .set_plugin_parameter = &set_nameservice_name,   .data = &my_services,      .addon = {NAME_SERVICE} },
+    { .name = "",              .set_plugin_parameter = &set_nameservice_host,   .data = &my_names },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+	*params = plugin_parameters;
+	*size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+
+/**
+ * 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, const char *value, int type, const union olsr_ip_addr *ip) 
+{
+	struct name_entry *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 = *ip;
+	tmp->next = my_list;
+	return tmp;
+}
+
+
+/**
+ * last initialization
+ *
+ * we have to do this here because some things like main_addr 
+ * or the dns suffix (for validation) are not known before
+ *
+ * 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
+ *     which sets up main_addr and some other variables
+ *   - register_olsr_data() then then finally calls this function
+ */
+int
+name_init(void)
+{
+	struct name_entry *name;
+	union olsr_ip_addr ipz;
+	int ret;
+
+	//regex string for validating the hostnames
+	const char *regex_name = "^[[:alnum:]_.-]+$";
+	//regex string for the service line
+	size_t regex_size = 256 * sizeof(char) + strlen(my_suffix);
+	char *regex_service = olsr_malloc(regex_size, "new *char from name_init for regex_service");
+	memset(&ipz, 0, sizeof(ipz));
+
+	//compile the regex from the string
+	if ((ret = regcomp(&regex_t_name, regex_name , REG_EXTENDED)) != 0)
+	{
+		/* #2: call regerror() if regcomp failed 
+		 * commented out, because only for debuggin needed
+		 *
+		int errmsgsz = regerror(ret, &regex_t_name, NULL, 0);
+		char *errmsg = malloc(errmsgsz);
+		regerror(ret, &regex_t_name, errmsg, errmsgsz);
+		fprintf(stderr, "regcomp: %s", errmsg);
+		free(errmsg);
+		regfree(&regex_t_name);
+		* */
+		OLSR_PRINTF(0, "compilation of regex \"%s\" for hostname failed", regex_name);
+	}
+
+	// a service line is something like prot://hostname.suffix:port|tcp|my little description about this service
+	//                  for example     http://router.olsr:80|tcp|my homepage
+	//                     prot     ://  (hostname.suffix     OR         ip)
+	//regex_service = "^[[:alnum:]]+://(([[:alnum:]_.-]+.olsr)|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}))
+	//                 :    port              /path      |(tcp OR udp) |short description
+	//                 :[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$";
+	strscpy(regex_service, "^[[:alnum:]]+://(([[:alnum:]_.-]+", regex_size);
+	strscat(regex_service, my_suffix, regex_size);
+	strscat(regex_service, ")|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3})):[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$", regex_size);
+
+	/* #1: call regcomp() to compile the regex */
+	if ((ret = regcomp(&regex_t_service, regex_service , REG_EXTENDED )) != 0)
+	{
+		/* #2: call regerror() if regcomp failed 
+		 * commented out, because only for debuggin needed
+		 *
+		int errmsgsz = regerror(ret, &regex_t_service, NULL, 0);
+		char *errmsg = malloc(errmsgsz);
+		regerror(ret, &regex_t_service, errmsg, errmsgsz);
+		fprintf(stderr, "regcomp: %s", errmsg);
+		free(errmsg);
+		regfree(&regex_t_service);
+		* */
+		OLSR_PRINTF(0, "compilation of regex \"%s\" for hostname failed", regex_name);
+	}
+	free(regex_service);
+	regex_service = NULL;
+
+	//fill in main addr for all entries with ip==0
+	//this does not matter for service, because the ip does not matter
+	//for service
+
+	for (name = my_names; name != NULL; name = name->next) {
+		if (ipequal(&name->ip, &ipz)) {
+			OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
+			name->ip = olsr_cnf->main_addr;
+		}
+	}
+	for (name = my_forwarders; name != NULL; name = name->next) {
+		if (name->ip.v4.s_addr == 0) {
+			OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
+			name->ip = olsr_cnf->main_addr;
+		}
+	}
+
+	//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);
+
+
+	/* register functions with olsrd */
+	olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
+
+	/* periodic message generation */
+	msg_gen_timer = olsr_start_timer(my_interval * MSEC_PER_SEC, EMISSION_JITTER,
+									 OLSR_TIMER_PERIODIC, &olsr_namesvc_gen,
+									 NULL, 0);
+
+	mapwrite_init(my_latlon_file);
+
+	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;
+		case NAME_LATLON:
+			valid = is_latlon_wellformed(my_list->name);
+			break;
+	}
+
+	if ( !valid  ) {
+		struct ipaddr_str strbuf;
+		OLSR_PRINTF(1, "NAME PLUGIN: invalid or malformed parameter %s (%s), fix your config!\n", my_list->name, olsr_ip_to_string(&strbuf, &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 {
+		struct ipaddr_str strbuf;
+		OLSR_PRINTF(2, "NAME PLUGIN: validate parameter %s (%s) -> OK\n", my_list->name, olsr_ip_to_string(&strbuf, &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(void)
+{
+	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(name_list);
+	free_all_list_entries(service_list);
+	free_all_list_entries(forwarder_list);
+	free_all_list_entries(latlon_list);
+
+	olsr_stop_timer(write_file_timer);
+	olsr_stop_timer(msg_gen_timer);
+
+	regfree(&regex_t_name);
+	regfree(&regex_t_service);
+	mapwrite_exit();
+}
+
+/* free all list entries */
+void 
+free_all_list_entries(struct list_node *this_db_list) 
+{
+	struct db_entry *db;
+	struct list_node *list_head, *list_node, *list_node_next;
+
+	int i;
+	
+	for (i = 0; i < HASHSIZE; i++) {
+
+		list_head = &this_db_list[i];
+
+		for (list_node = list_head->next;
+			 list_node != list_head;
+			 list_node = list_node_next) {
+
+			/* prefetch next node before loosing context */
+			list_node_next = list_node->next;
+
+			db = list2db(list_node);
+			olsr_namesvc_delete_db_entry(db);
+		}
+	}
+}
+
+
+/**
+ * The write file timer has fired.
+ */
+void
+olsr_expire_write_file_timer(void *context __attribute__((unused)))
+{
+	write_file_timer = NULL;
+
+	write_resolv_file();   /* if forwarder_table_changed */
+	write_hosts_file();    /* if name_table_changed */
+	write_services_file(); /* if service_table_changed */
+#ifdef WIN32
+	write_latlon_file();   /* if latlon_table_changed */
+#endif
+}
+
+
+/*
+ * Kick a timer to write everything into a file.
+ * This also paces things a bit.
+ */
+static void
+olsr_start_write_file_timer(void)
+{
+	if (write_file_timer) {
+		return;
+	}
+
+	write_file_timer = olsr_start_timer(5 * MSEC_PER_SEC, 5, OLSR_TIMER_ONESHOT,
+										olsr_expire_write_file_timer, NULL, 0);
+}
+
+/*
+ * Delete and unlink db_entry.
+ */
+void
+olsr_namesvc_delete_db_entry(struct db_entry *db)
+{
+	struct ipaddr_str strbuf;
+	OLSR_PRINTF(2, "NAME PLUGIN: %s timed out... deleting\n", 
+				olsr_ip_to_string(&strbuf, &db->originator));
+
+	olsr_start_write_file_timer();
+	olsr_stop_timer(db->db_timer); /* stop timer if running */
+	
+	/* Delete */
+	free_name_entry_list(&db->names);
+	list_remove(&db->db_list);
+	free(db);
+}
+
+/**
+ * Callback for the db validity timer.
+ */
+static void
+olsr_nameservice_expire_db_timer(void *context)
+{
+  struct db_entry *db;
+
+  db = (struct db_entry *)context;
+  db->db_timer = NULL; /* be pedandic */
+
+  olsr_namesvc_delete_db_entry(db);
+}
+
+/**
+ * Scheduled event: generate and send NAME packet
+ */
+void
+olsr_namesvc_gen(void *foo __attribute__((unused)))
+{
+	/* send buffer: huge */
+	char buffer[10240];
+	union olsr_message *message = (union olsr_message *)buffer;
+	struct interface *ifn;
+	int namesize;
+
+	/* fill message */
+	if(olsr_cnf->ip_version == AF_INET)
+	{
+		/* IPv4 */
+		message->v4.olsr_msgtype = MESSAGE_TYPE;
+		message->v4.olsr_vtime = reltime_to_me(my_timeout * MSEC_PER_SEC);
+		memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+		message->v4.ttl = MAX_TTL;
+		message->v4.hopcnt = 0;
+		message->v4.seqno = htons(get_msg_seqno());
+
+		namesize = encap_namemsg((struct namemsg*)&message->v4.message);
+		namesize = namesize + sizeof(struct olsrmsg);
+
+		message->v4.olsr_msgsize = htons(namesize);
+	}
+	else
+	{
+		/* IPv6 */
+		message->v6.olsr_msgtype = MESSAGE_TYPE;
+		message->v6.olsr_vtime = reltime_to_me(my_timeout * MSEC_PER_SEC);
+		memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+		message->v6.ttl = MAX_TTL;
+		message->v6.hopcnt = 0;
+		message->v6.seqno = htons(get_msg_seqno());
+
+		namesize = encap_namemsg((struct namemsg*)&message->v6.message);
+		namesize = namesize + sizeof(struct olsrmsg6);
+		
+		message->v6.olsr_msgsize = htons(namesize);
+	}
+
+	/* looping trough interfaces */
+	for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
+	{
+		OLSR_PRINTF(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
+
+		if(net_outbuffer_push(ifn, message, namesize) != namesize ) {
+			/* send data and try again */
+			net_output(ifn);
+			if(net_outbuffer_push(ifn, message, namesize) != namesize ) {
+				OLSR_PRINTF(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
+			}
+		}
+	}
+}
+
+
+/**
+ * Parse name olsr message of NAME type
+ */
+void
+olsr_parser(union olsr_message *m,
+			struct interface *in_if __attribute__((unused)),
+			union olsr_ip_addr *ipaddr)
+{
+	struct namemsg *namemessage;
+	union olsr_ip_addr originator;
+	olsr_reltime vtime;
+	int size;
+	olsr_u16_t seqno;
+
+	/* Fetch the originator of the messsage */
+	if(olsr_cnf->ip_version == AF_INET) {
+		memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
+		seqno = ntohs(m->v4.seqno);
+	} else {
+		memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
+		seqno = ntohs(m->v6.seqno);
+	}
+		
+	/* Fetch the message based on IP version */
+	if(olsr_cnf->ip_version == AF_INET) {
+		vtime = me_to_reltime(m->v4.olsr_vtime);
+		size = ntohs(m->v4.olsr_msgsize);
+		namemessage = (struct namemsg*)&m->v4.message;
+	}
+	else {
+		vtime = me_to_reltime(m->v6.olsr_vtime);
+		size = ntohs(m->v6.olsr_msgsize);
+		namemessage = (struct namemsg*)&m->v6.message;
+	}
+
+	/* Check if message originated from this node. 
+	If so - back off */
+	if(ipequal(&originator, &olsr_cnf->main_addr))
+		return;
+
+	/* Check that the neighbor this message was received from is symmetric. 
+	If not - back off*/
+	if(check_neighbor_link(ipaddr) != SYM_LINK) {
+		struct ipaddr_str strbuf;
+		OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
+		return;
+	}
+
+	update_name_entry(&originator, namemessage, size, vtime);
+
+	/* Forward the message if nessecary
+	* default_fwd does all the work for us! */
+	olsr_forward_message(m, ipaddr);
+}
+
+/**
+ * Encapsulate a name message into a packet. 
+ *
+ * It assumed that there is enough space in the buffer to do this!
+ *
+ * Returns: the length of the message that was appended
+ */
+int
+encap_namemsg(struct namemsg* msg)
+{
+	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;
+
+	// names
+	for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
+	{
+		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++;
+	}
+	// latlon
+	if ('\0' != latlon_in_file[0])
+	{
+		FILE* in = fopen( latlon_in_file, "r" );
+		if (in != NULL) {
+			fscanf(in, "%f,%f", &my_lat, &my_lon);
+			fclose(in);
+		}
+		else
+		{
+			OLSR_PRINTF(0, "NAME PLUGIN: cant read latlon in file %s\n", latlon_in_file);
+		}
+	}
+	if (0.0 != my_lat && 0.0 != my_lon)
+	{
+		char s[64];
+		struct name_entry e;
+		memset(&e, 0, sizeof(e));
+		sprintf(s, "%f,%f,%d", my_lat, my_lon, get_isdefhna_latlon());
+		e.len = strlen(s);
+		e.type = NAME_LATLON;
+		e.name = s;
+		lookup_defhna_latlon(&e.ip);
+		pos = create_packet( (struct name*) pos, &e);
+		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
+}
+
+
+/**
+ * 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;
+	struct ipaddr_str strbuf;
+	OLSR_PRINTF(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
+		from->name, olsr_ip_to_string(&strbuf, &from->ip), from->len);
+	to->type = htons(from->type);
+	to->len = htons(from->len);
+	to->ip = from->ip;
+	pos += sizeof(struct name);
+	memcpy(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 ipaddr_str strbuf;
+	struct name_entry *tmp;
+	struct name_entry *already_saved_name_entries;
+	char *name = (char*)from_packet + sizeof(struct name);
+	int type_of_from_packet = ntohs(from_packet->type);
+	unsigned int len_of_name = ntohs(from_packet->len);
+	OLSR_PRINTF(4, "NAME PLUGIN: decap type=%d, len=%d, name=%s\n",
+		type_of_from_packet, len_of_name, name);
+
+	//XXX: should I check the from_packet->ip here? If so, why not also check the ip from HOST and SERVICE?
+	if( (type_of_from_packet==NAME_HOST && !is_name_wellformed(name)) ||
+		(type_of_from_packet==NAME_SERVICE && !is_service_wellformed(name)) ||
+		(type_of_from_packet==NAME_LATLON && !is_latlon_wellformed(name)))
+	{
+		OLSR_PRINTF(4, "NAME 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 || NULL != strchr(name, '\\') || NULL != strchr(name, '\'')) {
+		OLSR_PRINTF(4, "NAME 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;
+	}
+
+	// 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, "NAME PLUGIN: received name or service entry %s (%s) already in hash table\n",
+				name, olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
+			return;
+		} else if (type_of_from_packet==NAME_FORWARDER && ipequal(&already_saved_name_entries->ip, &from_packet->ip) ) {
+			OLSR_PRINTF(4, "NAME PLUGIN: received forwarder entry %s (%s) already in hash table\n",
+				name, olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
+			return;
+		} else if (type_of_from_packet==NAME_LATLON ) {
+			if (0 != strncmp(already_saved_name_entries->name, name, len_of_name))
+			{
+				OLSR_PRINTF(4, "NAME PLUGIN: updating name %s -> %s (%s)\n",
+					already_saved_name_entries->name, name,
+					olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
+				free(already_saved_name_entries->name);
+				already_saved_name_entries->name = olsr_malloc(len_of_name + 1, "upd name_entry name");
+				strscpy(already_saved_name_entries->name, name, len_of_name + 1);
+
+				*this_table_changed = OLSR_TRUE;
+				olsr_start_write_file_timer();
+			}
+			if (!ipequal(&already_saved_name_entries->ip, &from_packet->ip))
+			{
+				struct ipaddr_str strbuf2, strbuf3;
+				OLSR_PRINTF(4, "NAME PLUGIN: updating ip %s -> %s (%s)\n",
+					olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip),
+					olsr_ip_to_string(&strbuf2, &from_packet->ip),
+					olsr_ip_to_string(&strbuf3, &already_saved_name_entries->ip));
+				already_saved_name_entries->ip = from_packet->ip;
+
+				*this_table_changed = OLSR_TRUE;
+				olsr_start_write_file_timer();
+			}
+			if (!*this_table_changed)
+			{
+				OLSR_PRINTF(4, "NAME PLUGIN: received latlon entry %s (%s) already in hash table\n",
+					name, olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
+			}
+			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");
+	tmp->ip = from_packet->ip;
+	strscpy(tmp->name, name, tmp->len + 1);
+
+	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(&strbuf, &tmp->ip), tmp->len, tmp->type);
+
+	*this_table_changed = OLSR_TRUE;
+	olsr_start_write_file_timer();
+
+	// queue to front
+	tmp->next = *to;
+	*to = tmp;
+}
+
+
+/**
+ * unpack the received message and delegate to the decapsulation function for each
+ * name/service/forwarder entry in the message
+ */
+void
+update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, olsr_reltime vtime)
+{
+	struct ipaddr_str strbuf;
+	char *pos, *end_pos;
+	struct name *from_packet; 
+	int i;
+
+	OLSR_PRINTF(3, "NAME PLUGIN: Received Message from %s\n", 
+				olsr_ip_to_string(&strbuf, originator));
+	
+	if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
+		OLSR_PRINTF(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
+		return;
+	}
+	
+	/* now add the names from the message */
+	pos = (char*)msg + sizeof(struct namemsg);
+	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;
+		
+		switch (ntohs(from_packet->type)) {
+			case NAME_HOST: 
+				insert_new_name_in_list(originator, name_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;
+			case NAME_LATLON:
+				insert_new_name_in_list(originator, latlon_list, from_packet,
+										&latlon_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(&strbuf, originator));
+				break;
+		}
+
+		pos += sizeof(struct name);
+		pos += 1 + (( ntohs(from_packet->len) - 1) | 3);
+	}
+	if (i!=0)
+		OLSR_PRINTF(4, "NAME PLUGIN: Lost %d entries in received packet due to length inconsistency (%s)\n", i, olsr_ip_to_string(&strbuf, originator));
+}
+
+
+/**
+ * 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
+insert_new_name_in_list(union olsr_ip_addr *originator,
+						struct list_node *this_list,
+						struct name *from_packet, olsr_bool *this_table_changed,
+						olsr_reltime vtime)
+{
+	int hash;
+	struct db_entry *entry;
+	struct list_node *list_head, *list_node;
+
+	olsr_bool entry_found = OLSR_FALSE;
+
+	hash = olsr_ip_hashing(originator);
+
+	/* find the entry for originator, if there is already one */
+	list_head = &this_list[hash];
+	for (list_node = list_head->next; list_node != list_head;
+		 list_node = list_node->next) {
+
+		entry = list2db(list_node);
+
+		if (ipequal(originator, &entry->originator)) {
+			struct ipaddr_str strbuf;
+			// found
+			OLSR_PRINTF(4, "NAME PLUGIN: found entry for (%s) in its hash table\n",
+						olsr_ip_to_string(&strbuf, originator));
+
+			//delegate to function for parsing the packet and linking it to entry->names
+			decap_namemsg(from_packet, &entry->names, this_table_changed);
+
+			olsr_set_timer(&entry->db_timer, vtime,
+						   OLSR_NAMESVC_DB_JITTER, OLSR_TIMER_ONESHOT,
+						   &olsr_nameservice_expire_db_timer, entry, 0);
+
+			entry_found = OLSR_TRUE;
+		}
+	}
+
+	if (! entry_found)
+	{
+		struct ipaddr_str strbuf;
+		OLSR_PRINTF(3, "NAME PLUGIN: create new db entry for ip (%s) in hash table\n",
+					olsr_ip_to_string(&strbuf, originator));
+
+		/* insert a new entry */
+		entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
+		memset(entry, 0, sizeof(struct db_entry));
+
+		entry->originator = *originator;
+
+		olsr_set_timer(&entry->db_timer, vtime,
+					   OLSR_LINK_LOSS_JITTER, OLSR_TIMER_ONESHOT,
+					   &olsr_nameservice_expire_db_timer, entry, 0);
+
+		entry->names = NULL;
+
+		/* insert to the list */
+		list_add_before(&this_list[hash], &entry->db_list);
+		
+		//delegate to function for parsing the packet and linking it to entry->names
+		decap_namemsg(from_packet, &entry->names, this_table_changed);
+	}
+}
+
+#ifndef WIN32
+static void
+send_sighup_to_pidfile(char * pid_file){
+	int fd;
+	int i=0;
+	int result;
+	pid_t ipid;
+	char line[20];
+	char * endptr;
+
+	fd = open(pid_file, O_RDONLY);
+	if (fd<0) {
+		OLSR_PRINTF(2, "NAME PLUGIN: can't open file %s\n", pid_file);
+		return;
+	}
+
+	while (i<19) {
+		result = read(fd, line+i, 19-i);
+		if (!result) { /* EOF */
+			break;
+		} else if (result>0) {
+			i += result;
+		} else if(errno!=EINTR && errno!=EAGAIN) {
+			OLSR_PRINTF(2, "NAME PLUGIN: can't read file %s\n", pid_file);
+			return;
+		}
+	}
+	line[i]=0;
+	close(fd);
+	ipid = strtol(line, &endptr, 0);
+	if (endptr==line) {
+		OLSR_PRINTF(2, "NAME PLUGIN: invalid pid at file %s\n", pid_file);
+		return;	
+	}
+
+	result=kill(ipid, SIGHUP);
+	if (result==0){
+		OLSR_PRINTF(2, "NAME PLUGIN: SIGHUP sent to pid %i\n", ipid);	
+	} else {
+		OLSR_PRINTF(2, "NAME PLUGIN: failed to send SIGHUP to pid %i\n", ipid);
+	}
+
+}
+#endif
+
+/**
+ * write names to a file in /etc/hosts compatible format
+ */
+void
+write_hosts_file(void)
+{
+	int hash;
+	struct name_entry *name;
+	struct db_entry *entry;
+	struct list_node *list_head, *list_node;
+	FILE* hosts;
+	FILE* add_hosts;
+	int c=0;
+	time_t currtime;
+
+#ifdef MID_ENTRIES
+	struct mid_address *alias;
+#endif
+
+	if (!name_table_changed)
+		return;
+
+	OLSR_PRINTF(2, "NAME PLUGIN: writing hosts file\n");
+
+	hosts = fopen( my_hosts_file, "w" );
+	if (hosts == NULL) {
+		OLSR_PRINTF(2, "NAME PLUGIN: cant write hosts file\n");
+		return;
+	}
+	
+	fprintf(hosts, "### this /etc/hosts file is overwritten regularly by olsrd\n");
+	fprintf(hosts, "### do not edit\n\n");
+
+	fprintf(hosts, "127.0.0.1\tlocalhost\n");
+	fprintf(hosts, "::1\t\tlocalhost\n\n");
+	
+	// copy content from additional hosts filename
+	if (my_add_hosts[0] != '\0') {
+		add_hosts = fopen( my_add_hosts, "r" );
+		if (add_hosts == NULL) {
+			OLSR_PRINTF(2, "NAME PLUGIN: cant open additional hosts file\n");
+		}
+		else {
+			fprintf(hosts, "### contents from '%s' ###\n\n", my_add_hosts);
+			while ((c = getc(add_hosts)) != EOF)
+				putc(c, hosts);
+		}
+		fclose(add_hosts);		
+		fprintf(hosts, "\n### olsr names ###\n\n");
+	}
+	
+	// write own names
+	for (name = my_names; name != NULL; name = name->next) {
+		struct ipaddr_str strbuf;
+		fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&strbuf, &name->ip), name->name, my_suffix );
+	}
+	
+	// write received names
+	for (hash = 0; hash < HASHSIZE; hash++) {
+		list_head = &name_list[hash];
+		for (list_node = list_head->next; list_node != list_head;
+			 list_node = list_node->next) {
+
+			entry = list2db(list_node);
+
+			for (name = entry->names; name != NULL; name = name->next) {
+				struct ipaddr_str strbuf;
+				OLSR_PRINTF(
+					6, "%s\t%s%s\t#%s\n",
+					olsr_ip_to_string( &strbuf, &name->ip ), name->name, my_suffix,
+					olsr_ip_to_string( &strbuf, &entry->originator )
+					);
+
+				fprintf(
+					hosts, "%s\t%s%s\t# %s\n",
+					olsr_ip_to_string( &strbuf, &name->ip ), name->name, my_suffix,
+					olsr_ip_to_string( &strbuf, &entry->originator )
+					);
+
+#ifdef MID_ENTRIES
+				// write mid entries
+				if( ( alias = mid_lookup_aliases( &name->ip ) ) != NULL )
+				{
+					unsigned short mid_num = 1;
+					char	   mid_prefix[MID_MAXLEN];
+
+					while( alias != NULL )
+					{
+						struct ipaddr_str midbuf;
+
+						// generate mid prefix
+						sprintf( mid_prefix, MID_PREFIX, mid_num );
+
+						OLSR_PRINTF(
+							6, "%s\t%s%s%s\t# %s (mid #%i)\n",
+							olsr_ip_to_string( &midbuf, &alias->alias ),
+							mid_prefix, name->name, my_suffix,
+							olsr_ip_to_string( &strbuf, &entry->originator ),
+							mid_num
+							);
+
+						fprintf(
+							hosts, "%s\t%s%s%s\t# %s (mid #%i)\n",
+							olsr_ip_to_string( &midbuf, &alias->alias ),
+							mid_prefix, name->name, my_suffix,
+							olsr_ip_to_string( &strbuf, &entry->originator ),
+							mid_num
+							);
+
+						alias = alias->next_alias;
+						mid_num++;
+					}
+				}
+#endif
+			}
+		}
+	}
+
+	if (time(&currtime)) {
+		fprintf(hosts, "\n### written by olsrd at %s", ctime(&currtime));
+	}
+	  
+	fclose(hosts);
+
+#ifndef WIN32
+	if (*my_sighup_pid_file)
+		send_sighup_to_pidfile(my_sighup_pid_file);
+#endif
+	name_table_changed = OLSR_FALSE;
+
+	// Executes my_name_change_script after writing the hosts file
+        if (my_name_change_script[0] != '\0') {
+		if(system(my_name_change_script) != -1) {
+			OLSR_PRINTF(2, "NAME PLUGIN: Name changed, %s executed\n", my_name_change_script);
+		}
+		else {
+			OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on hosts change\n", my_name_change_script);
+		}
+	}
+}
+
+
+/**
+ * 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(void)
+{
+	int hash;
+	struct name_entry *name;
+	struct db_entry *entry;
+	struct list_node *list_head, *list_node;
+	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++) {
+		list_head = &service_list[hash];
+		for (list_node = list_head->next; list_node != list_head;
+			 list_node = list_node->next) {
+
+			entry = list2db(list_node);
+
+			for (name = entry->names; name != NULL; name = name->next) {
+				struct ipaddr_str strbuf;
+				OLSR_PRINTF(6, "%s\t",  name->name);
+				OLSR_PRINTF(6, "\t#%s\n",
+							olsr_ip_to_string(&strbuf, &entry->originator));
+
+				fprintf(services_file, "%s\t", name->name );
+				fprintf(services_file, "\t#%s\n",
+						olsr_ip_to_string(&strbuf, &entry->originator));
+			}
+		}
+	}
+
+	if (time(&currtime)) {
+		fprintf(services_file, "\n### written by olsrd at %s", ctime(&currtime));
+	}
+	  
+	fclose(services_file);
+	service_table_changed = OLSR_FALSE;
+	
+	// Executes my_services_change_script after writing the services file
+	if (my_services_change_script[0] != '\0') {
+		if(system(my_services_change_script) != -1) {
+			OLSR_PRINTF(2, "NAME PLUGIN: Service changed, %s executed\n", my_services_change_script);
+		}
+		else {
+			OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on service change\n", my_services_change_script);
+		}
+	}
+}
+
+/**
+ * Sort the nameserver pointer array.
+ *
+ * fresh entries are at the beginning of the array and
+ * the best entry is at the end of the array.
+ */
+static void
+select_best_nameserver(struct rt_entry **rt)
+{
+	int nameserver_idx;
+	struct rt_entry *rt1, *rt2;
+
+	for (nameserver_idx = 0;
+		 nameserver_idx < NAMESERVER_COUNT;
+		 nameserver_idx++) {
+
+		rt1 = rt[nameserver_idx];
+		rt2 = rt[nameserver_idx+1];
+
+		/*
+		 * compare the next two pointers in the array.
+		 * if the second pointer is NULL then percolate it up.
+		 */
+		if (!rt2 || olsr_cmp_rt(rt1, rt2)) {
+#ifndef NODEBUG
+			struct ipaddr_str strbuf;
+			struct lqtextbuffer lqbuffer;
+#endif
+			/*
+			 * first is better, swap the pointers.
+			 */
+			OLSR_PRINTF(6, "NAME PLUGIN: nameserver %s, cost %s\n",
+						olsr_ip_to_string(&strbuf, &rt1->rt_dst.prefix),
+						get_linkcost_text(rt1->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
+
+			rt[nameserver_idx] = rt2;
+			rt[nameserver_idx+1] = rt1;
+		}
+	}
+}
+
+/**
+ * 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(void)
+{
+	int hash;
+	struct name_entry *name;
+	struct db_entry *entry;
+	struct list_node *list_head, *list_node;
+	struct rt_entry *route;
+	static struct rt_entry *nameserver_routes[NAMESERVER_COUNT+1];
+	FILE* resolv;
+	int i=0;
+	time_t currtime;
+
+	if (!forwarder_table_changed || my_forwarders != NULL || my_resolv_file[0] == '\0')
+		return;
+
+	/* clear the array of 3+1 nameserver routes */
+	memset(nameserver_routes, 0, sizeof(nameserver_routes));
+
+	for (hash = 0; hash < HASHSIZE; hash++) {
+		list_head = &forwarder_list[hash];
+		for (list_node = list_head->next; list_node != list_head;
+			 list_node = list_node->next) {
+
+			entry = list2db(list_node);
+
+			for (name = entry->names; name != NULL; name = name->next) {
+#ifndef NODEBUG
+				struct ipaddr_str strbuf;
+				struct lqtextbuffer lqbuffer;
+#endif
+				route = olsr_lookup_routing_table(&name->ip);
+
+				OLSR_PRINTF(6, "NAME PLUGIN: check route for nameserver %s %s",
+							olsr_ip_to_string(&strbuf, &name->ip),
+							route ? "suceeded" : "failed");
+
+				if (route==NULL) // it's possible that route is not present yet
+					continue;
+
+				/* enqueue it on the head of list */
+				*nameserver_routes = route;
+				OLSR_PRINTF(6, "NAME PLUGIN: found nameserver %s, cost %s",
+							olsr_ip_to_string(&strbuf, &name->ip),
+							get_linkcost_text(route->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
+
+				/* find the closet one */
+				select_best_nameserver(nameserver_routes);
+			}
+		}
+	}
+
+	/* if there is no best route we are done */
+	if (nameserver_routes[NAMESERVER_COUNT]==NULL)
+		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");
+
+	for (i = NAMESERVER_COUNT; i >= 0; i--) {
+		struct ipaddr_str strbuf;
+
+		route = nameserver_routes[i];
+
+		OLSR_PRINTF(2, "NAME PLUGIN: nameserver_routes #%d %p\n", i, route);
+
+		if (!route) {
+			continue;
+		}
+
+		OLSR_PRINTF(2, "NAME PLUGIN: nameserver %s\n",
+					olsr_ip_to_string(&strbuf, &route->rt_dst.prefix));
+		fprintf(resolv, "nameserver %s\n",
+				olsr_ip_to_string(&strbuf, &route->rt_dst.prefix));
+	}
+	if (time(&currtime)) {
+		fprintf(resolv, "\n### written by olsrd at %s", ctime(&currtime));
+	}
+	fclose(resolv);
+	forwarder_table_changed = OLSR_FALSE;
+}
+
+
+/**
+ * completely free a list of name_entries
+ */
+void 
+free_name_entry_list(struct name_entry **list) 
+{
+	struct name_entry **tmp = list;
+	struct name_entry *to_delete;
+	while (*tmp != NULL) {
+		to_delete = *tmp;
+		*tmp = (*tmp)->next;
+
+		/* flag changes */
+		switch (to_delete->type) {
+		case NAME_HOST:
+			name_table_changed = OLSR_TRUE;
+			break;
+		case NAME_FORWARDER:
+			forwarder_table_changed = OLSR_TRUE;
+			break;
+		case NAME_SERVICE:
+			service_table_changed = OLSR_TRUE;
+			break;
+		case NAME_LATLON:
+			latlon_table_changed = OLSR_TRUE;
+			break;
+		default:
+			break;
+		}
+
+		free( to_delete->name );
+		to_delete->name = NULL;
+		free( to_delete );
+		to_delete = NULL;
+	}
+}
+
+
+/**
+ * we only allow names for IP addresses which we are
+ * responsible for: 
+ * so the IP must either be from one of the interfaces
+ * or inside a HNA which we have configured 
+ */
+olsr_bool
+allowed_ip(const union olsr_ip_addr *addr)
+{
+	struct ip_prefix_list *hna;
+	struct interface *iface;
+	union olsr_ip_addr tmp_ip, tmp_msk;
+	struct ipaddr_str strbuf;
+	
+	OLSR_PRINTF(6, "checking %s\n", olsr_ip_to_string(&strbuf, addr));
+	
+	for(iface = ifnet; iface; iface = iface->int_next)
+	{
+		OLSR_PRINTF(6, "interface %s\n", olsr_ip_to_string(&strbuf, &iface->ip_addr));
+		if (ipequal(&iface->ip_addr, addr)) {
+			OLSR_PRINTF(6, "MATCHED\n");
+			return OLSR_TRUE;
+		}
+	}
+	
+	if (olsr_cnf->ip_version == AF_INET) {
+		for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
+			union olsr_ip_addr netmask;
+			OLSR_PRINTF(6, "HNA %s/%d\n", 
+						olsr_ip_to_string(&strbuf, &hna->net.prefix),
+						hna->net.prefix_len);
+			if (hna->net.prefix_len == 0) {
+				continue;
+			}
+			olsr_prefix_to_netmask(&netmask, hna->net.prefix_len);
+			if ((addr->v4.s_addr & netmask.v4.s_addr) == hna->net.prefix.v4.s_addr) {
+				OLSR_PRINTF(6, "MATCHED\n");
+				return OLSR_TRUE;
+			}
+		}
+	} else {
+		for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next)
+		{
+			unsigned int i;
+			OLSR_PRINTF(6, "HNA %s/%d\n", 
+				olsr_ip_to_string(&strbuf, &hna->net.prefix),
+				hna->net.prefix_len);
+			if ( hna->net.prefix_len == 0 )
+				continue;
+			olsr_prefix_to_netmask(&tmp_msk, hna->net.prefix_len);
+			for (i = 0; i < sizeof(tmp_ip.v6.s6_addr); i++) {
+				tmp_ip.v6.s6_addr[i] = addr->v6.s6_addr[i] & tmp_msk.v6.s6_addr[i];
+			}
+			if (ipequal(&tmp_ip, &hna->net.prefix)) {
+				OLSR_PRINTF(6, "MATCHED\n");
+				return OLSR_TRUE;
+			}
+		}
+	}
+	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(const char *name) {
+	return regexec(&regex_t_name, name, 1, &regmatch_t_name, 0) == 0 ;
+}
+
+
+/**
+ * check if the service is in the right syntax and also that the hostname 
+ * or ip whithin the service is allowed
+ */
+olsr_bool
+allowed_service(const 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(const char *service_line, const regmatch_t *hostname_or_ip_match) 
+{
+	char *hostname_or_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_pton(olsr_cnf->ip_version, hostname_or_ip, &olsr_ip) > 0) {
+		if (allowed_ip(&olsr_ip)) {
+			struct ipaddr_str strbuf;
+			OLSR_PRINTF(2, "NAME PLUGIN: ip %s in service %s is OK\n", olsr_ip_to_string(&strbuf, &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(const char *service_line)
+{
+	return regexec(&regex_t_service, service_line, pmatch_service, regmatch_t_service, 0) == 0;
+}
+
+/**
+ * check if the latlot matches the syntax 
+ */
+olsr_bool
+is_latlon_wellformed(const char *latlon_line)
+{
+	int hna = -1;
+	float a = 0.0, b = 0.0;
+	sscanf(latlon_line, "%f,%f,%d", &a, &b, &hna);
+	return (a != 0.0 && b != 0.0 && -1 != hna);
+}
+
+/**
+ * Returns 1 if this olsrd announces inet
+ */
+olsr_bool get_isdefhna_latlon(void)
+{
+	struct ip_prefix_list *hna;
+	for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next){
+		if (hna->net.prefix_len == 0) {
+			return OLSR_TRUE;
+		}
+	}
+	return OLSR_FALSE;
+}
+
+/**
+ * Grabs the current HNA selected default route
+ */
+void lookup_defhna_latlon(union olsr_ip_addr *ip)
+{
+  struct rt_entry *rt;
+  struct avl_node *rt_tree_node;
+  struct olsr_ip_prefix prefix;
+
+  memset(ip, 0, sizeof(ip));
+  memset(&prefix, 0, sizeof(prefix));
+
+  if (NULL != (rt_tree_node = avl_find(&routingtree, &prefix))) {
+	rt = rt_tree2rt(rt_tree_node);
+    *ip = rt->rt_best->rtp_nexthop.gateway;
+  }
+}
+
+/**
+ * lookup a nodes name
+ */
+const char*
+lookup_name_latlon(union olsr_ip_addr *ip)
+{
+	int hash;
+	struct db_entry *entry;
+	struct list_node *list_head, *list_node;
+	struct name_entry *name;
+
+	for (hash = 0; hash < HASHSIZE; hash++) {
+		list_head = &name_list[hash];
+		for (list_node = list_head->next; list_node != list_head;
+			 list_node = list_node->next) {
+
+			entry = list2db(list_node);
+
+			for (name = entry->names; name != NULL; name = name->next) {
+				if (ipequal(&name->ip, ip)) return name->name;
+			}
+		}
+	}
+	return "";
+}
+
+#ifdef WIN32
+/**
+ * write latlon positions to a javascript file
+ */
+void
+write_latlon_file(void)
+{
+  FILE* fmap;
+  
+  if (!my_names || !latlon_table_changed) return;
+  
+  OLSR_PRINTF(2, "NAME PLUGIN: writing latlon file\n");
+
+  if (NULL == (fmap = fopen(my_latlon_file, "w"))) {
+    OLSR_PRINTF(0, "NAME PLUGIN: cant write latlon file\n");
+    return;
+  }
+  fprintf(fmap, "/* This file is overwritten regularly by olsrd */\n");
+  mapwrite_work(fmap);  
+  fclose(fmap);
+  latlon_table_changed = OLSR_FALSE;
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-indent-tabs-mode: t
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/nameservice.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/nameservice.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/nameservice.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/nameservice.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+ 
+/*
+ * Dynamic linked library for UniK OLSRd
+ */
+
+#ifndef _NAMESERVICE_PLUGIN
+#define _NAMESERVICE_PLUGIN
+
+#include <sys/time.h>
+#include <regex.h>
+
+#include "olsr_types.h"
+#include "interfaces.h"
+#include "olsr_protocol.h"
+#include "common/list.h"
+
+#include "olsrd_plugin.h"
+#include "nameservice_msg.h"
+#include "hashing.h"
+#include "mapwrite.h"
+#include "mantissa.h"
+
+#define PLUGIN_NAME	"OLSRD nameservice plugin"
+#define PLUGIN_VERSION	"0.3"
+#define PLUGIN_AUTHOR   "Bruno Randolf, Jens Nachtigall, Sven-Ola Tuecke"
+
+// 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 /* seconds */
+#define EMISSION_JITTER         25 /* percent */
+#define NAME_VALID_TIME		1800 /* seconds */
+#define NAMESERVER_COUNT        3
+
+#define NAME_PROTOCOL_VERSION	1
+
+#define MAX_NAME 127
+#define MAX_FILE 255
+#define MAX_SUFFIX 63
+
+#define MID_ENTRIES 1
+#define MID_MAXLEN 16
+#define MID_PREFIX "mid%i."
+
+/**
+ * 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)
+ * if type is NAME_LATLON, then name has 2 floats with lat and lon (and the ip is irrelevant)
+ */
+struct name_entry
+{
+	union olsr_ip_addr	ip;
+	olsr_u16_t		type;
+	olsr_u16_t		len;
+	char			*name;
+	struct name_entry	*next;		/* linked list */
+};
+
+/* *
+ * 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 */
+        struct timer_entry      *db_timer;      /* Validity time */
+	struct name_entry	*names;		/* list of names this originator declares */
+        struct list_node        db_list;        /* linked list of db entries per hash container */
+};
+
+/* inline to recast from db_list back to db_entry */
+LISTNODE2STRUCT(list2db, struct db_entry, db_list);
+
+#define OLSR_NAMESVC_DB_JITTER 5 /* percent */
+
+extern struct name_entry *my_names;
+extern struct list_node latlon_list[HASHSIZE];
+extern float my_lat, my_lon;
+
+void olsr_expire_write_file_timer(void *);
+void olsr_namesvc_delete_db_entry(struct db_entry *);
+
+/* Parser function to register with the sceduler */
+void
+olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+/* callback for periodic timer */
+void olsr_namesvc_gen(void *);
+
+int
+encap_namemsg(struct namemsg *);
+
+struct name_entry*
+add_name_to_list(struct name_entry *my_list, const char *value, int type, const union olsr_ip_addr *ip);
+
+struct name_entry*
+remove_nonvalid_names_from_list(struct name_entry *my_list, int type);
+
+void 
+free_all_list_entries(struct list_node *) ;
+
+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 *, struct list_node *,
+                        struct name *, olsr_bool *, olsr_reltime);
+
+olsr_bool
+allowed_hostname_or_ip_in_service(const char *service_line, const regmatch_t *hostname_or_ip);
+
+void
+update_name_entry(union olsr_ip_addr *, struct namemsg *, int, olsr_reltime);
+
+void
+write_hosts_file(void);
+
+void
+write_services_file(void);
+
+void
+write_resolv_file(void);
+
+int
+register_olsr_param(char *key, char *value);
+
+void 
+free_name_entry_list(struct name_entry **list);
+
+olsr_bool
+allowed_ip(const union olsr_ip_addr *addr);
+
+olsr_bool
+allowed_service(const char *service_line);
+
+olsr_bool
+is_name_wellformed(const char *service_line);
+
+olsr_bool
+is_service_wellformed(const char *service_line);
+
+olsr_bool
+is_service_wellformed(const char *service_line);
+
+olsr_bool
+is_latlon_wellformed(const char *latlon_line);
+
+olsr_bool
+get_isdefhna_latlon(void);
+
+void
+lookup_defhna_latlon(union olsr_ip_addr *ip);
+
+const char*
+lookup_name_latlon(union olsr_ip_addr *ip);
+
+void
+write_latlon_file(void);
+
+char*  
+create_packet(struct name *to, struct name_entry *from);
+
+void
+name_constructor(void);
+
+void
+name_destructor(void);
+
+int
+name_init(void);
+
+#endif
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/nameservice_msg.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/nameservice_msg.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/nameservice_msg.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/nameservice_msg.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+
+/*
+ * Dynamic linked library for UniK OLSRd
+ */
+ 
+#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_LATLON = 3,
+} 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 or service is written in plain text after this struct and padded to 4 byte
+	 */
+};
+
+
+struct namemsg
+{
+	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
+	 */
+};
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/src/olsrd_plugin.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+
+/*
+ * Dynamic linked library for olsr.org olsrd
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "olsrd_plugin.h"
+#include "nameservice.h"
+
+#define PLUGIN_NAME    "OLSRD nameservice plugin"
+#define PLUGIN_VERSION "0.3"
+#define PLUGIN_AUTHOR   "Bruno Randolf, Jens Nachtigall, Sven-Ola Tuecke"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION
+#define PLUGIN_INTERFACE_VERSION 5
+
+
+static void __attribute__ ((constructor)) 
+my_init(void);
+
+static void __attribute__ ((destructor)) 
+my_fini(void);
+
+int 
+olsrd_plugin_interface_version(void)
+{
+	return PLUGIN_INTERFACE_VERSION;
+}
+
+int
+olsrd_plugin_init(void)
+{
+	return name_init();
+}
+
+
+static void
+my_init(void)
+{
+	/* Print plugin info to stdout */
+	printf("%s\n", MOD_DESC);
+
+	name_constructor();
+  
+	return;
+}
+
+
+static void
+my_fini(void)
+{
+	name_destructor();
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/nameservice/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/nameservice/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,56 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_pgraph
+PLUGIN_VER =	1.1
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/README_PGRAPH ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/README_PGRAPH
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/README_PGRAPH	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/README_PGRAPH	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,69 @@
+README-OLSR
+Modified: 05/17/2005
+
+#========================================================================
+#  These programs NEVER meet your needs.  In fact, they can cause
+#  serious damages to your precious things, including, but not being
+#  limited to, time, money, effort, computer files, information,
+#  hardware, software, and other things that you value.
+#
+#  The author DOES NOT request or even suggest that you use any of these
+#  programs. You understand clearly that you are taking a big risk
+#  in using these programs and that you are completely (100%) liable
+#  for using them.
+#
+#  You further understand that although you can use these programs
+#  without paying the author or the employer of the author, you
+#  do not own them.  You will give proper credits to the
+#  author and his employer whenever you use them; i.e.,
+#  you will never pretend that you are the author of these programs.
+#  If you make any changes to them, you will send a copy
+#  of each modified programs to the author.  You will also NEVER
+#  sell or give any of them to anyone else without the approval of the
+#  author or his employer.
+
+
+Parser: OLSRConnect.py
+Description: This parser has been written to interface with a plugin for
+	     the version 4.9 OLSR from olsr.org.  The plugin can also be 
+	     found in this directory.  
+
+Parser for OLSR: 	OLSRConnect.py
+Plugin for OLSRv4.9:	olsr_v4.9-pgraph-plugin
+
+Usage:
+	1) Copy the "olsr_v4.9-pgraph-plugin" directory from this distribution
+	   to the "/<your OLSRv4.9 path>/lib/."
+
+	2) cd to the "/<your OLSRv4.9 path>/lib/." directory, 
+           run "make" and "make install"
+	   This will create the "olsrd_pgraph.so.1.1" file and install it. 
+
+	3) Modify the "/etc/olsrd.conf" file of the system you wish to
+	   monitor from to load the plugin. 
+	   Add the line: "LoadPlugin "olsrd_pgraph.so.1.1" {}"
+
+	4) The plugin actually allows any host to connect regardless of
+           what is specified in the olsrd.conf file.  This is currently 
+           done for testing purposes and due to the fact that the "Host" 
+           parameter in the olsrd.conf file never worked.  
+
+           # By default only localhost will be able to connect to the IPC
+	   # system of the olsrd process so if you are not going to be 
+	   # running pgraph locally, modify the "Host" variable of the 
+	   # "IpcConnect" structure in the "/etc/olsrd.conf" file to 
+	   # reflect the IP address of the host you will be connecting from. 
+
+	5) Start olsrd and make sure that the plugin has loaded correctly.
+
+	6) On the machine you will be running pgraph from, use the 
+	   "OLSRConnect.py" parser to connect to the olsrd plugin and pipe
+	   the output to pgraph. 
+
+Usage: (note the use of the backquote "`") 
+"python  OLSRConnect.py <ip of machine running plugin> 2004 | `python pgraph.py`"
+
+- Where the "2004" above is the default port that the plugin will be listening on.
+
+To kill pgraph when using the parser:
+- Hit "Ctl-C" in the terminal. 
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,413 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#include "olsrd_pgraph.h"
+#include "ipcalc.h"
+#include "socket_parser.h"
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+#include "net_olsr.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef WIN32
+#define close(x) closesocket(x)
+#endif
+
+#define PLUGIN_NAME    "OLSRD pgraph plugin"
+#define PLUGIN_VERSION "0.1"
+#define PLUGIN_AUTHOR   "Richard Gopaul"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+static union olsr_ip_addr ipc_accept_ip;
+static int ipc_port;
+
+static int ipc_socket;
+static int ipc_connection;
+
+void my_init(void) __attribute__((constructor));
+
+void my_fini(void) __attribute__((destructor));
+
+/*
+ * Defines the version of the plugin interface that is used
+ * THIS IS NOT THE VERSION OF YOUR PLUGIN!
+ * Do not alter unless you know what you are doing!
+ */
+int 
+olsrd_plugin_interface_version(void)
+{
+   return PLUGIN_INTERFACE_VERSION;
+}
+
+
+/**
+ *Constructor
+ */
+void
+my_init(void)
+{
+  /* Print plugin info to stdout */
+  printf("%s\n", MOD_DESC);
+
+  /* defaults for parameters */
+  ipc_port = 2004;
+  if (olsr_cnf->ip_version == AF_INET) {
+    ipc_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
+  } else {
+    ipc_accept_ip.v6 = in6addr_loopback;
+  }
+  ipc_socket = -1;
+  ipc_connection = -1;
+}
+
+/**
+ *Destructor
+ */
+void
+my_fini(void)
+{
+  if(ipc_socket >= 0) {
+    close(ipc_socket);
+    ipc_socket = -1;
+  }
+  if(ipc_connection >= 0) {
+    close(ipc_connection);
+    ipc_connection = -1;
+  }
+
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "port",   .set_plugin_parameter = &set_plugin_port,      .data = &ipc_port },
+    { .name = "accept", .set_plugin_parameter = &set_plugin_ipaddress, .data = &ipc_accept_ip },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/* Event function to register with the sceduler */
+static int pcf_event(int, int, int);
+
+static void ipc_action(int);
+
+static void ipc_print_neigh_link(struct neighbor_entry *neighbor);
+
+static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry);
+
+static int ipc_send(const char *, int);
+
+static void ipc_print_neigh_link(struct neighbor_entry *);
+
+static int plugin_ipc_init(void);
+
+
+static void ipc_print_neigh_link(struct neighbor_entry *neighbor)
+{
+  char buf[256];
+  int len;
+  struct ipaddr_str main_adr, adr;
+//  double etx=0.0;
+//  char* style = "solid";
+//  struct link_entry* link;
+
+  len = sprintf(buf,
+                "add link %s %s\n",
+                olsr_ip_to_string(&main_adr, &olsr_cnf->main_addr),
+                olsr_ip_to_string(&adr, &neighbor->neighbor_main_addr));
+  ipc_send(buf, len);
+  
+//  if (neighbor->status == 0) { // non SYM
+//  	style = "dashed";
+//  }
+//  else {
+    /* find best link to neighbor for the ETX */
+    //? why cant i just get it one time at fetch_olsrd_data??? (br1)
+//    if(olsr_plugin_io(GETD__LINK_SET, &link, sizeof(link)) && link)
+//    {
+//      link_set = link; // for olsr_neighbor_best_link    
+//      link = olsr_neighbor_best_link(&neighbor->neighbor_main_addr);
+//      if (link) {
+//        etx = olsr_calc_etx(link);
+//      }
+//    }
+//  }
+    
+  //len = sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
+  //len = sprintf( buf, "%s\n", adr );
+  //ipc_send(buf, len);
+  
+   //if (neighbor->is_mpr) {
+   //	len = sprintf( buf, "\"%s\"[shape=box];\n", adr );
+   //	ipc_send(buf, len);
+   //}
+}
+
+/**
+ *Do initialization here
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ */
+int olsrd_plugin_init(void)
+{
+
+  /* Initial IPC value */
+  ipc_socket = -1;
+
+  /* Register the "ProcessChanges" function */
+  register_pcf(&pcf_event);
+
+  return 1;
+}
+
+static int plugin_ipc_init(void)
+{
+  struct sockaddr_in sin;
+  olsr_u32_t yes = 1;
+
+  /* Init ipc socket */
+  if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+    {
+      olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
+      return 0;
+    }
+  else
+    {
+      if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
+      {
+	perror("SO_REUSEADDR failed");
+	return 0;
+      }
+
+#ifdef __FreeBSD__
+      if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) 
+      {
+	perror("SO_NOSIGPIPE 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) 
+	{
+	  olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
+	  return 0;
+	}
+      
+      /* show that we are willing to listen */
+      if (listen(ipc_socket, 1) == -1) 
+	{
+	  olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
+	  return 0;
+	}
+
+
+      /* Register with olsrd */
+      add_olsr_socket(ipc_socket, &ipc_action);
+    }
+
+  return 1;
+}
+
+static void ipc_action(int fd __attribute__((unused)))
+{
+  struct sockaddr_in pin;
+  socklen_t addrlen;
+  char *addr;  
+  char buf[256] ;
+  int len ;
+   
+  addrlen = sizeof(struct sockaddr_in);
+
+  if ((ipc_connection = accept(ipc_socket, (struct sockaddr *)  &pin, &addrlen)) == -1)
+    {
+      olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
+      exit(1);
+    }
+  else
+    {
+      struct ipaddr_str main_addr;
+      addr = inet_ntoa(pin.sin_addr);
+/*
+      if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
+	{
+	  olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
+	  close(ipc_connection);
+	  return;
+	}
+      else
+	{
+*/
+	  olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n",addr);
+          len = sprintf(buf, "add node %s\n", olsr_ip_to_string(&main_addr, &olsr_cnf->main_addr));
+  	  ipc_send(buf, len);
+	  pcf_event(1, 1, 1);
+//	}
+    }
+
+}
+
+/**
+ *Scheduled event
+ */
+static int pcf_event(int changes_neighborhood,
+                     int changes_topology,
+                     int changes_hna __attribute__((unused)))
+{
+  int res;
+  struct neighbor_entry *neighbor_table_tmp;
+  struct tc_entry *tc;
+  struct tc_edge_entry *tc_edge;
+
+  res = 0;
+
+  if (changes_neighborhood || changes_topology) {
+    /* Print tables to IPC socket */
+
+    //ipc_send("start ", strlen("start "));
+
+    /* Neighbors */
+    OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp) {
+      ipc_print_neigh_link( neighbor_table_tmp );
+    } OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor_table_tmp);
+
+    /* Topology */  
+    OLSR_FOR_ALL_TC_ENTRIES(tc) {
+      OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+        ipc_print_tc_link(tc, tc_edge);
+      } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+    } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+
+    ipc_send(" end ", strlen(" end "));
+
+    /* 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)
+//		{
+//		  ipc_print_net(&tmp_hna->A_gateway_addr, 
+//				&tmp_net->A_network_addr, 
+//				&tmp_net->A_netmask);
+//		  tmp_net = tmp_net->next;
+//		}
+//	      
+//	      tmp_hna = tmp_hna->next;
+//	    }
+//	}
+
+//      ipc_send("}\n\n", strlen("}\n\n"));
+
+    res = 1;
+  }
+
+  if (ipc_socket == -1) {
+    plugin_ipc_init();
+  }
+
+  return res;
+}
+
+static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry)
+{
+  char buf[256];
+  int len;
+  struct ipaddr_str main_adr, adr;
+//  double etx = olsr_calc_tc_etx(dst_entry);
+
+  len = sprintf( buf, "add link %s %s\n",
+                 olsr_ip_to_string(&main_adr, &entry->addr),
+                 olsr_ip_to_string(&adr, &dst_entry->T_dest_addr));
+  ipc_send(buf, len);
+}
+
+static int ipc_send(const char *data, int size)
+{
+  if(ipc_connection == -1)
+    return 0;
+
+#if defined __FreeBSD__ || defined __MacOSX__
+#define FLAG 0
+#else
+#define FLAG MSG_NOSIGNAL
+#endif
+  if (send(ipc_connection, data, size, FLAG) < 0) 
+    {
+      olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
+      close(ipc_connection);
+      ipc_connection = -1;
+      return -1;
+    }
+
+  return 1;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/src/olsrd_pgraph.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_PGRAPH_PLUGIN
+#define _OLSRD_PGRAPH_PLUGIN
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "olsrd_plugin.h"
+#include "olsr_types.h"
+
+#include "olsr.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "link_set.h"
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+
+int olsrd_plugin_interface_version(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/pgraph/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/pgraph/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/ChangeLog ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/ChangeLog
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/ChangeLog	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/ChangeLog	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,29 @@
+0.2.2: Immo 'FaUl' Wehrenberg <immo@chaostreff-dortmund.de>:
+	* make selected flag configurable (do not set it by default)
+	* configurable administrative distance now
+	* make it compile (and work) on *bsd (only tested on freebsd, please
+	  drop me a note if you test it on any other platform!)
+	* lot of bugfixes (now support for redistribute with
+	  ZEBRA_HEADER_MARKER), etc
+	* lot of code-cleanups improvements (most to the work of Acinonyx)
+	* updated plugin interface to version 5
+	* updated to new routing core (olsrd-0.5.4)
+
+
+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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/Contributors ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/Contributors
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/Contributors	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/Contributors	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,7 @@
+This file is to thank people contributing code or do a lot of testing 
+
+* Vassilis T. <acinonyxs@yahoo.gr> for a lot of cleanups and fixes
+* Johannes Joemann <5@free.de> for a lot of testing
+* Bernd Petrovitsch <bernd@firmix.at> for support and new plugin-interface
+* Hannes Gredler <hannes@gredler.at> for new routing-core
+* Sven Ola Tucke <mail2news@commando.de> for various bugfixes
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,69 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_quagga
+PLUGIN_VER =	0.2.2
+
+TOPDIR= ../..
+include $(TOPDIR)/Makefile.inc
+
+#CPPFLAGS +=-DMY_DEBUG 
+CFLAGS += -g
+CPPFLAGS +=-DUSE_UNIX_DOMAIN_SOCKET
+
+#uncomment the following line only if you are sure what you're doing, it will 
+#probably break things! 
+# CPPFLAGS +=-DZEBRA_HEADER_MARKER=255 
+
+ifeq ($(OS),win32)
+default_target install clean:
+	@echo "**** Quagga not supportet on Windows (so it would be pointless to build the Quagga Plugin)"
+else
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/README_QUAGGA ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/README_QUAGGA
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/README_QUAGGA	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/README_QUAGGA	2008-10-03 14:45:07.000000000 +0200
@@ -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 exported to quagga (normal behaviour) 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 the 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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/olsrd_plugin.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,141 @@
+/***************************************************************************
+ 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 "plugin_util.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "defs.h"
+#include "quagga.h"
+#include "kernel_routes.h"
+#include "net_olsr.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
+#define PLUGIN_INTERFACE_VERSION 5
+
+static void __attribute__ ((constructor)) my_init(void);
+static void __attribute__ ((destructor)) my_fini(void);
+
+static set_plugin_parameter set_redistribute;
+static set_plugin_parameter set_exportroutes;
+static set_plugin_parameter set_distance;
+static set_plugin_parameter set_localpref;
+
+static export_route_function orig_addroute_function;
+static export_route_function orig_delroute_function;
+
+int olsrd_plugin_interface_version (void) {
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+  { .name = "redistribute", .set_plugin_parameter = &set_redistribute, },
+  { .name = "ExportRoutes", .set_plugin_parameter = &set_exportroutes, },
+  { .name = "Distance",     .set_plugin_parameter = &set_distance,     },
+  { .name = "LocalPref",    .set_plugin_parameter = &set_localpref,    },
+};
+
+void olsrd_get_plugin_parameters (const struct olsrd_plugin_parameters **params,
+				  int *size) {
+  *params = plugin_parameters;
+  *size = sizeof plugin_parameters / sizeof *plugin_parameters;
+}
+
+static int set_redistribute (const char *value, 
+			     void *data __attribute__((unused)),
+			     set_plugin_parameter_addon addon __attribute__((unused))) {
+  const char *zebra_route_types[] = {"system","kernel","connect",
+					      "static","rip","ripng","ospf",
+					      "ospf6","isis","bgp","hsls"};
+  unsigned int i;
+
+  for (i = 0; i < ARRAYSIZE(zebra_route_types); i++) {
+    if (!strcmp(value, zebra_route_types[i])) {
+      zebra_redistribute(i);
+      return 0;
+    }
+  }
+  return 1;
+}
+
+static int set_exportroutes (const char *value, 
+			     void *data __attribute__((unused)),
+			     set_plugin_parameter_addon addon __attribute__((unused))) {
+  if (!strcmp(value, "only")) {
+    orig_addroute_function = NULL;
+    orig_delroute_function = NULL;
+    olsr_addroute_function = zebra_add_olsr_v4_route;
+    olsr_delroute_function = zebra_del_olsr_v4_route;
+    zebra_export_routes(1);
+  }
+  else if (!strcmp(value, "additional")) {
+    orig_addroute_function = olsr_addroute_function;
+    orig_delroute_function = olsr_delroute_function;
+    olsr_addroute_function = zebra_add_olsr_v4_route;
+    olsr_delroute_function = zebra_del_olsr_v4_route;
+    zebra_export_routes(1);
+  }
+  else zebra_export_routes(0);
+  return 0;
+}
+
+static int set_distance(const char *value, void *data __attribute__((unused)), 
+			set_plugin_parameter_addon addon __attribute__((unused))) {
+  int distance;
+
+  if (set_plugin_int(value, &distance, addon)) return 1;
+  if (distance < 0 || distance > 255) return 1;
+  zebra_olsr_distance(distance);
+  return 0;
+}
+ 
+static int set_localpref(const char *value, void *data __attribute__((unused)), 
+			 set_plugin_parameter_addon addon __attribute__((unused))) {
+  int b;
+
+  if (set_plugin_boolean(value, &b, addon)) return 1;
+  if (b) zebra_olsr_localpref();
+  return 0;
+}
+
+
+int olsrd_plugin_init(void) {
+  if(olsr_cnf->ip_version != AF_INET) {
+    fputs("see the source - ipv6 so far not supported\n" ,stderr);
+    return 1;
+  }
+
+  olsr_start_timer(1 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
+                   &zebra_check, NULL, 0);
+
+  return 0;
+}
+
+static void my_init(void) {
+  init_zebra();
+}
+
+static void my_fini(void) {
+  zebra_cleanup();
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga/zassert.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga/zassert.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga/zassert.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga/zassert.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,26 @@
+/*
+ */
+
+#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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga/zebra.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga/zebra.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga/zebra.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga/zebra.h	2008-10-03 14:45:07.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,852 @@
+/***************************************************************************
+ 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 <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+
+#include "quagga.h"
+#include "olsr.h"
+#include "log.h"
+#include "defs.h"
+#include "routing_table.h"
+
+#ifdef USE_UNIX_DOMAIN_SOCKET
+#include <sys/un.h>
+#define ZEBRA_SOCKET "/var/run/quagga/zserv.api"
+#endif
+
+#define ZEBRA_IPV4_ROUTE_ADD		7
+#define ZEBRA_IPV4_ROUTE_DELETE		8
+#define ZEBRA_REDISTRIBUTE_ADD		11
+#define ZEBRA_REDISTRIBUTE_DELETE	12
+#define ZEBRA_MESSAGE_MAX		23
+
+#define ZEBRA_ROUTE_OLSR		11
+#define ZEBRA_ROUTE_MAX			12
+
+#define ZEBRA_FLAG_SELECTED		0x10
+
+#define ZEBRA_NEXTHOP_IPV4		3
+#define ZEBRA_NEXTHOP_IPV4_IFINDEX	4
+
+#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
+#define OPTION_EXPORT 1
+
+static struct {
+  char status; // internal status
+  char options; // internal options
+  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 unsigned char *try_read (ssize_t *);
+static unsigned char* zebra_route_packet (struct ipv4_route r, ssize_t *);
+static int parse_interface_add (unsigned char *, size_t);
+static int parse_interface_delete (unsigned char *, size_t);
+static int parse_interface_up (unsigned char *, size_t);
+static int parse_interface_down (unsigned char *, size_t);
+static int parse_interface_address_add (unsigned char *, size_t);
+static int parse_interface_address_delete (unsigned char *, size_t);
+static int parse_ipv4_route (unsigned char *, size_t, struct ipv4_route *);
+static int ipv4_route_add (unsigned char *, size_t);
+static int ipv4_route_delete (unsigned char *, size_t);
+static int parse_ipv6_route_add (unsigned char*, size_t);
+static void zebra_reconnect (void);
+static void zebra_connect (void);
+
+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, "(QUAGGA) 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;
+}
+
+void init_zebra (void) {
+  zebra_connect();
+  if (!(zebra.status&STATUS_CONNECTED))
+    olsr_exit ("(QUAGGA) AIIIII, could not connect to zebra! is zebra running?", 
+	       EXIT_FAILURE);
+}
+
+void zebra_cleanup (void) {
+  int i;
+  struct rt_entry *tmp;
+  
+  if (zebra.options & OPTION_EXPORT) {
+    OLSR_FOR_ALL_RT_ENTRIES(tmp) {
+      zebra_del_olsr_v4_route(tmp);
+    } OLSR_FOR_ALL_RT_ENTRIES_END(tmp);
+  }
+
+  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+    if (zebra.redistribute[i]) zebra_disable_redistribute(i + 1);
+}
+
+
+static void zebra_reconnect (void) {
+  struct rt_entry *tmp;
+  int i;
+
+  zebra_connect();
+  if (!(zebra.status & STATUS_CONNECTED)) return; // try again next time
+
+  if (zebra.options & OPTION_EXPORT) {
+    OLSR_FOR_ALL_RT_ENTRIES(tmp) {
+      zebra_add_olsr_v4_route (tmp);
+    } OLSR_FOR_ALL_RT_ENTRIES_END(tmp);
+  }  
+
+  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+    if (zebra.redistribute[i]) zebra_redistribute(i + 1);
+  /* Zebra sends us all routes of type it knows after 
+     zebra_redistribute(type) */
+}
+
+
+
+/* Connect to the zebra-daemon, returns a socket */
+static void zebra_connect (void) {
+  
+  int ret;
+
+#ifndef USE_UNIX_DOMAIN_SOCKET
+  struct sockaddr_in i;
+  if (close (zebra.sock) < 0) olsr_exit ("(QUAGGA) Could not close socket!", EXIT_FAILURE);
+  
+
+  zebra.sock = socket (AF_INET,SOCK_STREAM, 0);
+#else
+  struct sockaddr_un i;
+  if (close (zebra.sock) < 0) olsr_exit ("(QUAGGA) Could not close socket!", EXIT_FAILURE);
+
+  zebra.sock = socket (AF_UNIX,SOCK_STREAM, 0);
+#endif
+
+  if (zebra.sock <0 )
+    olsr_exit("(QUAGGA) 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;
+  strscpy (i.sun_path, ZEBRA_SOCKET, sizeof(i.sun_path));
+#endif
+
+  ret = connect (zebra.sock, (struct sockaddr *)&i, sizeof i);
+  if  (ret < 0) zebra.status &= ~STATUS_CONNECTED;
+  else zebra.status |= STATUS_CONNECTED;
+}
+
+    
+/* Sends a command to zebra, command is 
+   the command defined in zebra.h, options is the packet-payload, 
+   optlen the length, of the payload */
+unsigned char zebra_send_command (unsigned char command, 
+                                  unsigned char *options, int optlen) {
+
+  char *p, *pnt;
+  uint16_t len;
+  int ret;
+
+#ifdef ZEBRA_HEADER_MARKER
+  uint16_t cmd;
+  uint16_t length = optlen + 6; /* length of option + command + packet_length +
+				   marker + zserv-version */
+#else
+  uint16_t length = optlen + 3;  // length of option + command + packet_length
+#endif  
+
+  if (!(zebra.status & STATUS_CONNECTED)) return 0;
+
+  p = olsr_malloc (length, "zebra_send_command");
+  pnt = p;
+  
+  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);
+#else
+  p[2] = command;
+#endif
+  memcpy (p + length-optlen, options, optlen);
+
+  errno = 0;
+
+  do {
+    ret = write (zebra.sock, p, length);
+    if (ret < 0) {
+      if (errno == EINTR) {
+	errno = 0;
+	continue;
+      }
+      else {
+	olsr_printf (1, "(QUAGGA) Disconnected from zebra\n");
+	zebra.status &= ~STATUS_CONNECTED;
+	free (pnt);
+	return -1;
+      }
+    }
+    p = p+ret;
+  } while ((length -= ret));
+  free (pnt);
+  return 0;
+}
+
+
+/* Creates a Route-Packet-Payload, needs address, netmask, nexthop, 
+   distance, and a pointer of an size_t */
+static unsigned char* zebra_route_packet (struct ipv4_route r, 
+                                          ssize_t *optlen) {
+
+  int count;
+
+  unsigned 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_DISTANCE)
+    *t++ = r.distance;
+  if (r.message & ZAPI_MESSAGE_METRIC) {
+    memcpy (t, &r.metric, sizeof r.metric);
+    t += sizeof r.metric;
+  }
+  return cmdopt;
+}
+
+
+/* adds a route to zebra-daemon */
+int zebra_add_v4_route (const struct ipv4_route r) {
+  
+  unsigned 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) {
+  
+  unsigned 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 __attribute__((unused))) {
+  unsigned char *data, *f;
+  ssize_t len, ret;
+
+  if (!(zebra.status & STATUS_CONNECTED)) {
+    zebra_reconnect();
+    return;
+  }
+  data = try_read (&len);
+  if (data) {
+    f = data;
+    do {
+      ret = zebra_parse_packet (f, len);
+      if (!ret) // something wired happened
+	olsr_exit ("(QUAGGA) Zero message length??? ", 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 unsigned char *try_read (ssize_t *len) {
+  unsigned 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) { // nothing more to read, packet is broken, discard!
+      free (buf);
+      return NULL;
+    }
+
+    if (ret < 0) {
+      if (errno != EAGAIN) { // oops - we got disconnected
+        olsr_printf (1, "(QUAGGA) Disconnected from zebra\n");
+        zebra.status &= ~STATUS_CONNECTED;
+      }
+      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 (unsigned char *packet, ssize_t maxlen) {
+
+  uint16_t command;
+  int skip;
+
+  /* Array of functions */
+  int (*foo[ZEBRA_MESSAGE_MAX]) (unsigned 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
+  };
+
+  uint16_t length;
+  int ret;
+
+#ifdef MY_DEBUG
+  puts ("DEBUG: zebra_parse_packet");
+#endif
+
+  memcpy (&length, packet, 2);
+  length = ntohs (length);
+  
+  if (maxlen < length) {
+    olsr_printf (1, "(QUAGGA) maxlen = %lu, packet_length = %d\n", (unsigned long)maxlen, length);
+    olsr_exit ("(QUAGGA) programmer is an idiot", EXIT_FAILURE);
+  }
+
+#ifdef ZEBRA_HEADER_MARKER
+  if (packet[2] == 255) { // found header marker!!
+    //packet[3] == ZSERV_VERSION: FIXME: HANDLE THIS!
+    memcpy (&command, packet + 4, sizeof command); // two bytes command now!
+    command = ntohs (command) - 1; 
+    skip = 6;
+  }
+#else
+  command = packet[2] - 1;
+  skip = 3;
+#endif
+
+  if (command < ZEBRA_MESSAGE_MAX && foo[command]) { 
+    if (!(ret = foo[command] (packet + skip, length - skip))) 
+      return length;
+    else olsr_printf (1, "(QUAGGA) Parse error: %d\n", ret);
+  }
+  else
+    olsr_printf (1, "(QUAGGA) Unknown packet type: %d\n", packet[2]);
+
+  olsr_printf (1, "(Quagga) RECIVED PACKET FROM ZEBRA THAT I CAN'T PARSE");
+
+  return length;
+}
+
+
+static int parse_interface_add (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_delete (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_address_add (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
+  
+  //todo
+  return 0;
+}
+
+static int parse_interface_up (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
+  
+  //todo
+  return 0;
+}
+
+static int parse_interface_down (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
+  
+  //todo
+  return 0;
+}
+
+
+static int parse_interface_address_delete (unsigned char *opt __attribute__((unused)), size_t  len __attribute__((unused))) {
+  //todo
+  return 0;
+}
+
+
+/* Parse an ipv4-route-packet recived from zebra
+ */
+static int parse_ipv4_route (unsigned 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 (unsigned char *opt, size_t len) {
+
+  struct ipv4_route r;
+  int f;
+    
+  f = parse_ipv4_route (opt, len, &r);
+  if (f < 0) return f;
+
+  return add_hna4_route (r);
+}
+
+static int ipv4_route_delete (unsigned 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 (unsigned char *opt __attribute__((unused)), size_t len __attribute__((unused))) {
+  //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);
+
+}
+  
+int add_hna4_route (struct ipv4_route r) {
+  union olsr_ip_addr net;
+  
+#ifdef MY_DEBUG
+  dump_ipv4_route(r, "add_hna4_route");
+#endif
+
+  net.v4.s_addr = r.prefix;
+
+  ip_prefix_list_add(&olsr_cnf->hna_entries, &net, r.prefixlen);
+  free_ipv4_route(r);
+  return 0;
+}
+
+int delete_hna4_route (struct ipv4_route r) {
+
+  union olsr_ip_addr net;
+
+#ifdef MY_DEBUG
+  dump_ipv4_route(r, "delete_hna4_route");
+#endif
+
+  net.v4.s_addr = r.prefix;
+
+  ip_prefix_list_remove(&olsr_cnf->hna_entries, &net, r.prefixlen) ? 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 (const 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 = r->rt_dst.prefix_len;
+  route.prefix = r->rt_dst.prefix.v4.s_addr;
+  if ((r->rt_best->rtp_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr && 
+       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_best->rtp_nexthop.iif_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_best->rtp_nexthop.gateway.v4.s_addr;
+  }
+
+  route.metric = r->rt_best->rtp_metric.hops;
+  route.metric = htonl(route.metric);
+
+  if (zebra.distance) {
+    route.message |= ZAPI_MESSAGE_DISTANCE;
+    route.distance = zebra.distance;
+  }
+
+  retval = zebra_add_v4_route(route);
+  free_ipv4_route (route);
+  return retval;
+}
+
+int zebra_del_olsr_v4_route (const 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 = r->rt_dst.prefix_len;
+  route.prefix = r->rt_dst.prefix.v4.s_addr;
+  if ((r->rt_nexthop.gateway.v4.s_addr == r->rt_dst.prefix.v4.s_addr && 
+       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_nexthop.iif_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_nexthop.gateway.v4.s_addr;
+  }
+  route.metric = 0;
+  
+  if (zebra.distance) {
+    route.message |= ZAPI_MESSAGE_DISTANCE;
+    route.distance = zebra.distance;
+  }
+
+  retval = zebra_delete_v4_route(route);
+
+  free_ipv4_route (route);
+  return retval;
+}
+
+void zebra_olsr_distance (unsigned char dist) {
+  zebra.distance = dist;
+}
+
+void zebra_olsr_localpref (void) {
+  zebra.flags &= ZEBRA_FLAG_SELECTED;
+}
+
+void zebra_export_routes (unsigned char t) {
+  if (t)
+    zebra.options |= OPTION_EXPORT;
+  else
+    zebra.options &= ~OPTION_EXPORT;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/src/quagga.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/src/quagga.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,70 @@
+/***************************************************************************
+ 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
+
+#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;
+  uint8_t distance;
+  struct ipv4_route *next;
+};
+
+void init_zebra (void);
+void zebra_cleanup (void);
+unsigned char zebra_send_command (unsigned char, unsigned char *, int );
+int zebra_add_v4_route (const struct ipv4_route r);
+int zebra_delete_v4_route (const struct ipv4_route r);
+void zebra_check (void*);
+int zebra_parse_packet (unsigned 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 (const struct rt_entry *);
+int zebra_del_olsr_v4_route (const struct rt_entry *);
+void zebra_olsr_localpref (void);
+void zebra_olsr_distance (unsigned char);
+void zebra_export_routes(unsigned char);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/test/foo.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/test/foo.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/test/foo.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/test/foo.c	2008-10-03 14:45:07.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/test/foo.pl ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/test/foo.pl
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/test/foo.pl	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/test/foo.pl	2008-10-03 14:45:07.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/test/quagga.try1.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/test/quagga.try1.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/test/quagga.try1.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/test/quagga.try1.c	2008-10-03 14:45:07.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/quagga/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/quagga/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/CHANGELOG ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/CHANGELOG
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/CHANGELOG	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/CHANGELOG	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,15 @@
+This changelog states changes from version 0.2
+
+0.5 - A local MD5 implementation can now be compiled
+      into the plugin so that no external library
+      is needed. Should be great for embedded systems.
+      MD5 might not be super-secure, but hey... it
+      still takes quite some effort to break ;)
+0.4 - Plugin now compiles under FreeBSD and win32.
+      To compile under win32(cygwin) you have to
+      make sure the openssl include directory
+      is present under /usr/include/mingw/
+      The plugin is not tested under win32.   
+0.3 - Only some minor fixes to make the plugin work
+      with olsrd 0.4.6.
+      Dynamic interface removal/addition supported.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,61 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_secure
+PLUGIN_VER =	0.5
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+ifdef USE_OPENSSL
+CPPFLAGS +=	-DUSE_OPENSSL
+LIBS +=		-lssl -lcrypto
+endif
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/README_SECURE ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/README_SECURE
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/README_SECURE	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/README_SECURE	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,64 @@
+
+
+Secure OLSR 0.4 implementation notes
+(c)Andreas Tønnesen 2004
+
+This document contains information on how to
+use the secure OLSR plugin with the UniK olsr daemon.
+It does _not_ cover secure OLSR protocol issues.
+
+Lines starting with '# ' indicates shell commands.
+
+NOTES
+
+  The plugin interface and olsrd output buffering was
+  heavily rewritten for the 0.4.8 release. The plugin
+  should work with this release - but has not been
+  tested much.
+
+COMPILING
+
+  To compile simply do:
+  # make
+  This compiles the local MD5 function and the plugin has
+  no external dependencies.
+  If you want the plugin to use SHA-1 using the openssl libs
+  do:
+  # make USE_OPENSSL=1
+
+INSTALLING
+
+  To install:
+  # make install
+
+  This will run ldconfig to update the dynamic linker.
+  It might take a while.
+
+USAGE
+
+  To make olsrd load the secure OLSR plugin add the
+  following in the olsrd configuration file:
+
+LoadPlugin "olsrd_secure.so.0.5"
+{
+    PlParam     "Keyfile"   "FILENAME"
+}
+
+  replacing FILENAME with the full path of the file
+  containing the shared key.
+
+  The plugin uses this shared secret key for signature
+  generation and verification. For nodes to participate 
+  in the OLSR routing domain they need to use the key 
+  used by the other nodes.
+  The key is 128-bits of size and is read from the
+  specified file from the config file or by default from:
+  /etc/olsrd.d/olsrd_secure_key
+
+  Copy the key to this file an all nodes. The plugin
+  will terminate olsrd if this file cannot be found.
+
+  Now start olsrd and the let the plugin do its
+  thing :)
+
+- Andreas
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/md5.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/md5.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/md5.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/md5.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,314 @@
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.  
+                                                                    
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.  
+                                                                    
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.  
+ */
+
+#include "md5.h"
+
+#include <string.h>
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static const unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+   Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+    (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+    (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+    (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+    (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+
+#if 0
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+static void MD5_memcpy (POINTER output, POINTER input, unsigned int len)
+{
+  unsigned int i;
+  
+  for (i = 0; i < len; i++)
+    output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (POINTER output, int value, unsigned int len)
+{
+  unsigned int i;
+  
+  for (i = 0; i < len; i++)
+    ((char *)output)[i] = (char)value;
+}
+#else
+#define MD5_memcpy(dst, src, len) memcpy((dst), (src), (len)) 
+#define MD5_memset(dst, val, len) memset((dst), (val), (len)) 
+#endif
+
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+     a multiple of 4.
+ */
+static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+    output[j] = (unsigned char)(input[i] & 0xff);
+    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+     a multiple of 4.
+ */
+static void Decode (UINT4 *output, const unsigned char *input, unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (UINT4 state[4], const unsigned char block[64])
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+  
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+  /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+  
+  /* Zeroize sensitive information.
+   */
+  MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (MD5_CTX *context)
+{
+  context->count[0] = context->count[1] = 0;
+
+  /* Load magic initialization constants.
+   */
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+     operation, processing another message block, and updating the
+     context.
+ */
+void MD5Update (MD5_CTX *context, const unsigned char *input, const unsigned int inputLen)
+{
+  unsigned int i, index, partLen;
+
+  /* Compute number of bytes mod 64 */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+      < ((UINT4)inputLen << 3))
+    context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+  
+  partLen = 64 - index;
+  
+  /* Transform as many times as possible.
+   */
+  if (inputLen >= partLen) {
+    MD5_memcpy
+      ((POINTER)&context->buffer[index], input, partLen);
+    MD5Transform (context->state, context->buffer);
+  
+    for (i = partLen; i + 63 < inputLen; i += 64)
+      MD5Transform (context->state, &input[i]);
+    
+    index = 0;
+  }
+  else
+    i = 0;
+  
+  /* Buffer remaining input */
+  MD5_memcpy 
+    ((POINTER)&context->buffer[index], &input[i],
+     inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+     the message digest and zeroizing the context.
+ */
+void MD5Final (unsigned char digest[16], MD5_CTX *context)
+{
+  unsigned char bits[8];
+  unsigned int index, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+   */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (index < 56) ? (56 - index) : (120 - index);
+  MD5Update (context, PADDING, padLen);
+  
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  /* Store state in digest */
+  Encode (digest, context->state, 16);
+  
+  /* Zeroize sensitive information.
+   */
+  MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/md5.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/md5.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/md5.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/md5.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,50 @@
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.  
+                                                                    
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.  
+                                                                    
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.  
+ */
+
+#ifndef _MD5_H_
+#define _MD5_H_
+
+#include <inttypes.h>
+
+/* POINTER defines a generic pointer type */
+typedef uint8_t *POINTER;
+/* UINT2 defines a two byte word */
+typedef uint16_t UINT2;
+/* UINT4 defines a four byte word */
+typedef uint32_t UINT4;
+
+/* MD5 context. */
+typedef struct {
+  UINT4 state[4];                                   /* state (ABCD) */
+  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+} MD5_CTX;
+
+void MD5Init(MD5_CTX *);
+void MD5Update(MD5_CTX *, const unsigned char *, const unsigned int);
+void MD5Final(unsigned char [16], MD5_CTX *);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/olsrd_plugin.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,129 @@
+/*
+ * Secure OLSR plugin
+ * http://www.olsr.org
+ *
+ * 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 olsrd, olsr.org 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.
+ *
+ */
+
+
+
+#include "olsrd_plugin.h"
+#include "olsrd_secure.h"
+#include <stdio.h>
+#include <string.h>
+
+
+#define PLUGIN_NAME    "OLSRD signature plugin"
+#define PLUGIN_VERSION "0.5"
+#define PLUGIN_AUTHOR   "Andreas TÃ¸nnesen"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+static void my_init(void) __attribute__ ((constructor));
+static void my_fini(void) __attribute__ ((destructor));
+
+/*
+ * Defines the version of the plugin interface that is used
+ * THIS IS NOT THE VERSION OF YOUR PLUGIN!
+ * Do not alter unless you know what you are doing!
+ */
+int olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+
+/**
+ *Constructor
+ */
+static void my_init(void)
+{
+  /* Print plugin info to stdout */
+  /* We cannot use olsr_printf yet! */
+  printf("%s\n", MOD_DESC);
+  printf("[ENC]Accepted parameter pairs: (\"Keyfile\" <FILENAME>)\n"); 
+}
+
+/**
+ *Destructor
+ */
+static void my_fini(void)
+{
+
+  /* Calls the destruction function
+   * olsr_plugin_exit()
+   * This function should be present in your
+   * sourcefile and all data destruction
+   * should happen there - NOT HERE!
+   */
+  secure_plugin_exit();
+}
+
+static int store_string(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  char *str = data;
+  snprintf(str, FILENAME_MAX+1, "%s", value);
+  return 0;
+}
+
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "keyfile", .set_plugin_parameter = &store_string, .data = keyfile },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+int olsrd_plugin_init(void) {
+  /* Calls the initialization function
+   * olsr_plugin_init()
+   * This function should be present in your
+   * sourcefile and all data initialization
+   * should happen there - NOT HERE!
+   */
+  if(!secure_plugin_init())
+    {
+      fprintf(stderr, "Could not initialize plugin!\n");
+      return 0;
+    }
+
+  if(!plugin_ipc_init())
+    {
+      fprintf(stderr, "Could not initialize plugin IPC!\n");
+      return 0;
+    }
+  return 1;
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/olsrd_secure.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/olsrd_secure.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/olsrd_secure.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/olsrd_secure.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1223 @@
+
+/*
+ * Secure OLSR plugin
+ * http://www.olsr.org
+ *
+ * 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 olsrd, olsr.org 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.
+ *
+ */
+
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#include "olsrd_secure.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef linux
+#include <linux/in_route.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "defs.h"
+#include "ipcalc.h"
+#include "olsr.h"
+#include "socket_parser.h"
+#include "parser.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+
+#ifdef USE_OPENSSL
+/* OpenSSL stuff */
+#include <openssl/sha.h>
+
+#define CHECKSUM SHA1
+#define SCHEME   SHA1_INCLUDING_KEY
+
+#else
+/* Homebrewn checksuming */
+#include "md5.h"
+
+static void
+MD5_checksum(const olsr_u8_t *data, const olsr_u16_t data_len, olsr_u8_t *hashbuf)
+{
+  MD5_CTX context;
+
+  MD5Init(&context);
+  MD5Update(&context, data, data_len);
+  MD5Final(hashbuf, &context);
+}
+
+#define CHECKSUM MD5_checksum
+#define SCHEME   MD5_INCLUDING_KEY
+
+#endif
+
+#ifdef OS
+#undef OS
+#endif
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define OS "Windows"
+#endif
+#ifdef linux
+#define OS "GNU/Linux"
+#endif
+#ifdef __FreeBSD__
+#define OS "FreeBSD"
+#endif
+
+#ifndef OS
+#define OS "Undefined"
+#endif
+
+static struct timeval now;
+
+/* Timestamp node */
+struct stamp
+{
+  union olsr_ip_addr addr;
+  /* Timestamp difference */
+  int diff;
+  olsr_u32_t challenge;
+  olsr_u8_t validated;
+  clock_t valtime; /* Validity time */
+  clock_t conftime; /* Reconfiguration time */
+  struct stamp *prev;
+  struct stamp *next;
+};
+
+/* Seconds to cache a valid timestamp entry */
+#define TIMESTAMP_HOLD_TIME 30
+/* Seconds to cache a not verified timestamp entry */
+#define EXCHANGE_HOLD_TIME 5
+
+static struct stamp timestamps[HASHSIZE];
+
+
+char keyfile[FILENAME_MAX+1];
+char aes_key[16];
+
+/* Event function to register with the sceduler */
+#if 0
+static void olsr_event(void);
+#endif
+static int send_challenge(struct interface *olsr_if, const union olsr_ip_addr *);
+static int send_cres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t, struct stamp *);
+static int send_rres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t);
+static int parse_challenge(struct interface *olsr_if, char *);
+static int parse_cres(struct interface *olsr_if, char *);
+static int parse_rres(char *);
+static int check_auth(struct interface *olsr_if, char *, int *);
+#if 0
+static int ipc_send(char *, int);
+#endif
+static int add_signature(olsr_u8_t *, int*);
+static int validate_packet(struct interface *olsr_if, const char *, int*);
+static char *secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length);
+static void timeout_timestamps(void*);
+static int check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *, time_t);
+static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
+static int read_key_from_file(const char *);
+
+/**
+ *Do initialization here
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ */
+
+int
+secure_plugin_init(void)
+{
+  int i;
+
+
+  /* Initialize the timestamp database */
+  for(i = 0; i < HASHSIZE; i++)
+    {
+      timestamps[i].next = &timestamps[i];
+      timestamps[i].prev = &timestamps[i];
+    }
+  olsr_printf(1, "Timestamp database initialized\n");
+
+  if(!strlen(keyfile))
+    strscpy(keyfile, KEYFILE, sizeof(keyfile));
+
+  i = read_key_from_file(keyfile);
+
+  if(i < 0)
+    {
+      olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
+      exit(1);
+    }
+  if(i == 0)
+    {
+      olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
+      exit(1);
+    }
+
+  /* Register the packet transform function */
+  add_ptf(&add_signature);
+
+  olsr_preprocessor_add_function(&secure_preprocessor);
+  
+  /* Register timeout - poll every 2 seconds */
+  olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
+                   &timeout_timestamps, NULL, 0);
+
+
+  return 1;
+}
+
+int
+plugin_ipc_init(void)
+{
+  return 1;
+}
+
+/*
+ * destructor - called at unload
+ */
+void
+secure_plugin_exit(void)
+{
+  olsr_preprocessor_remove_function(&secure_preprocessor);
+}
+
+
+#if 0
+/**
+ *Scheduled event
+ */
+static void
+olsr_event(void)
+{
+
+}
+#endif
+
+#if 0
+static int
+ipc_send(char *data __attribute__((unused)), int size __attribute__((unused)))
+{
+  return 1;
+}
+#endif
+
+static char *
+secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length)
+{
+  struct olsr *olsr = (struct olsr *)packet;
+  struct ipaddr_str buf;
+  
+  /*
+   * Check for challenge/response messages
+   */
+  check_auth(olsr_if, packet, length);
+
+  /*
+   * Check signature
+   */
+
+  if(!validate_packet(olsr_if, packet, length))
+  {
+    olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
+    return NULL;
+  }
+
+  olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
+
+  /* Fix OLSR packet header */
+  olsr->olsr_packlen = htons(*length);
+  return packet;
+}
+
+
+
+/**
+ * Check a incoming OLSR packet for
+ * challenge/responses.
+ * They need not be verified as they
+ * are signed in the message.
+ *
+ */
+static int
+check_auth(struct interface *olsr_if, char *pck, int *size __attribute__((unused)))
+{
+
+  olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
+
+  switch(pck[4])
+    {
+    case(TYPE_CHALLENGE):
+      parse_challenge(olsr_if, &pck[4]);
+      break;
+
+    case(TYPE_CRESPONSE):
+      parse_cres(olsr_if, &pck[4]);
+      break;
+
+    case(TYPE_RRESPONSE):
+      parse_rres(&pck[4]);
+      break;
+
+    default:
+      return 0;
+    }
+
+  return 1;
+}
+
+
+
+/**
+ * Packet transform function
+ * Build a SHA-1/MD5 hash of the original message
+ * + the signature message(-digest) + key
+ *
+ * Then add the signature message to the packet and
+ * increase the size
+ */
+int
+add_signature(olsr_u8_t *pck, int *size)
+{
+  struct s_olsrmsg *msg;
+#ifdef DEBUG
+  unsigned int i;
+  int j;
+  const olsr_u8_t *sigmsg;                                                                                        
+#endif
+  
+  olsr_printf(2, "[ENC]Adding signature for packet size %d\n", *size);
+  fflush(stdout);
+  
+  msg = (struct s_olsrmsg *)&pck[*size];
+  /* Update size */
+  ((struct olsr*)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
+  
+  /* Fill packet header */
+  msg->olsr_msgtype = MESSAGE_TYPE;
+  msg->olsr_vtime = 0;
+  msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
+  memcpy(&msg->originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+  msg->ttl = 1;
+  msg->hopcnt = 0;
+  msg->seqno = htons(get_msg_seqno());
+  
+  /* Fill subheader */
+  msg->sig.type = ONE_CHECKSUM;
+  msg->sig.algorithm = SCHEME;
+  memset(&msg->sig.reserved, 0, 2);
+  
+  /* Add timestamp */
+  msg->sig.timestamp = htonl(now.tv_sec);
+  olsr_printf(3, "[ENC]timestamp: %ld\n", now.tv_sec);
+  
+  /* Set the new size */
+  *size += sizeof(struct s_olsrmsg);
+  
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+  
+  /* Create the hash */
+  CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
+  } 
+
+#ifdef DEBUG
+  olsr_printf(1, "Signature message:\n");
+
+  j = 0;
+  sigmsg = (olsr_u8_t *)msg;
+
+  for(i = 0; i < sizeof(struct s_olsrmsg); i++)
+    {
+      olsr_printf(1, "  %3i", sigmsg[i]);
+      j++;
+      if(j == 4)
+	{
+	  olsr_printf(1, "\n");
+	  j = 0;
+	}
+    }
+#endif
+
+  olsr_printf(3, "[ENC] Message signed\n");
+
+  return 1;
+}
+
+
+
+static int
+validate_packet(struct interface *olsr_if, const char *pck, int *size)
+{
+  int packetsize;
+  olsr_u8_t sha1_hash[SIGNATURE_SIZE];
+  const struct s_olsrmsg *sig;
+  time_t rec_time;
+
+#ifdef DEBUG
+  unsigned int i;
+  int j;
+  const olsr_u8_t *sigmsg;
+#endif
+
+  /* Find size - signature message */
+  packetsize = *size - sizeof(struct s_olsrmsg);
+
+  if(packetsize < 4)
+    return 0;
+
+  sig = (const struct s_olsrmsg *)&pck[packetsize];
+
+  //olsr_printf(1, "Size: %d\n", packetsize);
+
+#ifdef DEBUG
+  olsr_printf(1, "Input message:\n");
+  
+  j = 0;
+  sigmsg = (const olsr_u8_t *)sig;
+
+  for(i = 0; i < sizeof(struct s_olsrmsg); i++)
+    {
+      olsr_printf(1, "  %3i", sigmsg[i]);
+      j++;
+      if(j == 4)
+	{
+	  olsr_printf(1, "\n");
+	  j = 0;
+	}
+    }
+#endif
+
+  /* Sanity check first */
+  if((sig->olsr_msgtype != MESSAGE_TYPE) || 
+     (sig->olsr_vtime != 0) ||
+     (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) ||
+     (sig->ttl != 1) ||
+     (sig->hopcnt != 0))
+    {
+      olsr_printf(1, "[ENC]Packet not sane!\n");
+      return 0;
+    }
+
+  /* Check scheme and type */
+  switch(sig->sig.type)
+    {
+    case(ONE_CHECKSUM):
+      switch(sig->sig.algorithm)
+	{
+	case(SCHEME):
+	  goto one_checksum_SHA; /* Ahhh... fix this */
+	  break;
+	  
+	}
+      break;
+
+    default:
+      olsr_printf(1, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
+      return 0;
+    }
+  //olsr_printf(1, "Packet sane...\n");
+
+ one_checksum_SHA:
+ 
+ {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+
+  /* generate SHA-1 */
+  CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
+ }
+
+#ifdef DEBUG
+  olsr_printf(1, "Recevied hash:\n");
+  
+  sigmsg = (const olsr_u8_t *)sig->sig.signature;
+
+  for(i = 0; i < SIGNATURE_SIZE; i++)
+    {
+      olsr_printf(1, " %3i", sigmsg[i]);
+    }
+  olsr_printf(1, "\n");
+
+  olsr_printf(1, "Calculated hash:\n");
+  
+  sigmsg = sha1_hash;
+
+  for(i = 0; i < SIGNATURE_SIZE; i++)
+    {
+      olsr_printf(1, " %3i", sigmsg[i]);
+    }
+  olsr_printf(1, "\n");
+#endif
+
+  if(memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0)
+    {
+      olsr_printf(1, "[ENC]Signature missmatch\n");
+      return 0;
+    }
+
+  /* Check timestamp */
+  rec_time = ntohl(sig->sig.timestamp);
+
+  if(!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time))
+    {
+      struct ipaddr_str buf;
+      olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
+		  olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
+      return 0;
+    }
+
+  olsr_printf(1, "[ENC]Received timestamp %ld diff: %ld\n", rec_time, now.tv_sec - rec_time);
+
+  /* Remove signature message */
+  *size = packetsize;
+  return 1;
+}
+
+
+int
+check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
+{
+  struct stamp *entry;
+  int diff;
+
+  entry = lookup_timestamp_entry(originator);
+
+  if(!entry)
+    {
+      /* Initiate timestamp negotiation */
+
+      send_challenge(olsr_if, originator);
+
+      return 0;
+    }
+
+  if(!entry->validated)
+    {
+      olsr_printf(1, "[ENC]Message from non-validated host!\n");
+      return 0;
+    }
+
+  diff = entry->diff - (now.tv_sec - tstamp);
+
+  olsr_printf(3, "[ENC]Timestamp slack: %d\n", diff);
+
+  if((diff > UPPER_DIFF) || (diff < LOWER_DIFF))
+    {
+      olsr_printf(1, "[ENC]Timestamp scew detected!!\n");
+      return 0;
+    }
+
+  /* ok - update diff */
+  entry->diff = ((now.tv_sec - tstamp) + entry->diff) ?
+    ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
+
+  olsr_printf(3, "[ENC]Diff set to : %d\n", entry->diff);
+
+  /* update validtime */
+
+  entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
+
+  return 1;
+}
+
+
+/**
+ * Create and send a timestamp
+ * challenge message to new_host
+ *
+ * The host is registered in the timestamps
+ * repository with valid=0
+ */
+
+int
+send_challenge(struct interface *olsr_if, const union olsr_ip_addr *new_host)
+{
+  struct challengemsg cmsg;
+  struct stamp *entry;
+  olsr_u32_t challenge, hash;
+  struct ipaddr_str buf;
+
+  olsr_printf(1, "[ENC]Building CHALLENGE message\n");
+
+  /* Set the size including OLSR packet size */
+
+
+  challenge = rand() << 16;
+  challenge |= rand();
+
+  /* Fill challengemessage */
+  cmsg.olsr_msgtype = TYPE_CHALLENGE;
+  cmsg.olsr_vtime = 0;
+  cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
+  memcpy(&cmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+  cmsg.ttl = 1;
+  cmsg.hopcnt = 0;
+  cmsg.seqno = htons(get_msg_seqno());
+
+  /* Fill subheader */
+  memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
+  cmsg.challenge = htonl(challenge);
+
+  olsr_printf(3, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, &cmsg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, 
+	   cmsg.signature);
+  }
+  olsr_printf(3, "[ENC]Sending timestamp request to %s challenge 0x%x\n", 
+	      olsr_ip_to_string(&buf, new_host),
+	      challenge);
+
+  /* Add to buffer */
+  net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
+
+  /* Send the request */
+  net_output(olsr_if);
+
+  /* Create new entry */
+  entry = malloc(sizeof(struct stamp));
+  
+  entry->diff = 0;
+  entry->validated = 0;
+  entry->challenge = challenge;
+
+  memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
+
+  /* update validtime - not validated */
+  entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
+
+  hash = olsr_ip_hashing(new_host);
+  
+  /* Queue */
+  timestamps[hash].next->prev = entry;
+  entry->next = timestamps[hash].next;
+  timestamps[hash].next = entry;
+  entry->prev = &timestamps[hash];
+
+
+  return 1;
+
+}
+
+int
+parse_cres(struct interface *olsr_if, char *in_msg)
+{
+  struct c_respmsg *msg;
+  olsr_u8_t sha1_hash[SIGNATURE_SIZE];
+  struct stamp *entry;
+  struct ipaddr_str buf;
+
+  msg = (struct c_respmsg *)in_msg;
+
+  olsr_printf(1, "[ENC]Challenge-response message received\n");
+  olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
+
+  if(if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL)
+    {
+      olsr_printf(3, "[ENC]Not for us...\n");
+      return 0;
+    }
+
+  olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
+
+  /* Check signature */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+  
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, 
+	   sha1_hash);
+  }
+  
+  if(memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0)
+    {
+      olsr_printf(1, "[ENC]Signature missmatch in challenge-response!\n");
+      return 0;
+    }
+
+  olsr_printf(3, "[ENC]Signature verified\n");
+
+
+  /* Now to check the digest from the emitted challenge */
+  if((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL)
+    {
+      struct ipaddr_str buf;
+      olsr_printf(1, "[ENC]Received challenge-response from non-registered node %s!\n",
+		  olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
+      return 0;
+    }
+
+  /* Generate the digest */
+  olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* First the challenge received */
+  memcpy(checksum_cache, &entry->challenge, 4);
+  /* Then the local IP */
+  memcpy(&checksum_cache[sizeof(olsr_u32_t)], &msg->originator, olsr_cnf->ipsize);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   sizeof(olsr_u32_t) + olsr_cnf->ipsize, 
+	   sha1_hash);
+  }
+
+  if(memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0)
+    {
+      struct ipaddr_str buf;
+      olsr_printf(1, "[ENC]Error in challenge signature from %s!\n",
+		  olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
+      
+      return 0;
+    }
+
+  olsr_printf(3, "[ENC]Challenge-response signature ok\n");
+
+  /* Update entry! */
+
+
+  entry->challenge = 0;
+  entry->validated = 1;
+  entry->diff = now.tv_sec - msg->timestamp;
+
+  /* update validtime - validated entry */
+  entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
+
+  olsr_printf(1, "[ENC]%s registered with diff %d!\n",
+	      olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
+	      entry->diff);
+
+  /* Send response-response */
+  send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator, 
+	    (union olsr_ip_addr *)&msg->destination, 
+	    ntohl(msg->challenge));
+
+  return 1;
+}
+
+
+int
+parse_rres(char *in_msg)
+{
+  struct r_respmsg *msg;
+  olsr_u8_t sha1_hash[SIGNATURE_SIZE];
+  struct stamp *entry;
+  struct ipaddr_str buf;
+
+  msg = (struct r_respmsg *)in_msg;
+
+  olsr_printf(1, "[ENC]Response-response message received\n");
+  olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
+
+  if(if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL)
+    {
+      olsr_printf(1, "[ENC]Not for us...\n");
+      return 0;
+    }
+
+  /* Check signature */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+  
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, 
+	   sha1_hash);
+  }
+  
+  if(memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0)
+    {
+      olsr_printf(1, "[ENC]Signature missmatch in response-response!\n");
+      return 0;
+    }
+
+  olsr_printf(3, "[ENC]Signature verified\n");
+
+
+  /* Now to check the digest from the emitted challenge */
+  if((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL)
+    {
+      struct ipaddr_str buf;
+      olsr_printf(1, "[ENC]Received response-response from non-registered node %s!\n",
+		  olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
+      return 0;
+    }
+
+  /* Generate the digest */
+  olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* First the challenge received */
+  memcpy(checksum_cache, &entry->challenge, 4);
+  /* Then the local IP */
+  memcpy(&checksum_cache[sizeof(olsr_u32_t)], &msg->originator, olsr_cnf->ipsize);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   sizeof(olsr_u32_t) + olsr_cnf->ipsize, 
+	   sha1_hash);
+  }
+
+  if(memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0)
+    {
+      struct ipaddr_str buf;
+      olsr_printf(1, "[ENC]Error in response signature from %s!\n",
+		  olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
+      
+      return 0;
+    }
+
+  olsr_printf(3, "[ENC]Challenge-response signature ok\n");
+
+  /* Update entry! */
+
+
+  entry->challenge = 0;
+  entry->validated = 1;
+  entry->diff = now.tv_sec - msg->timestamp;
+
+  /* update validtime - validated entry */
+  entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
+
+  olsr_printf(1, "[ENC]%s registered with diff %d!\n",
+	      olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
+	      entry->diff);
+
+  return 1;
+}
+
+
+int
+parse_challenge(struct interface *olsr_if, char *in_msg)
+{
+  struct challengemsg *msg;
+  olsr_u8_t sha1_hash[SIGNATURE_SIZE];
+  struct stamp *entry;
+  olsr_u32_t hash;
+  struct ipaddr_str buf;
+          
+  msg = (struct challengemsg *)in_msg;
+
+  olsr_printf(1, "[ENC]Challenge message received\n");
+  olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
+
+  if(if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL)
+    {
+      olsr_printf(1, "[ENC]Not for us...\n");
+      return 0;
+    }
+
+  /* Create entry if not registered */
+  if((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL)
+    {
+      entry = malloc(sizeof(struct stamp));
+      memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
+
+      hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
+  
+      /* Queue */
+      timestamps[hash].next->prev = entry;
+      entry->next = timestamps[hash].next;
+      timestamps[hash].next = entry;
+      entry->prev = &timestamps[hash];
+    }
+  else
+    {
+      /* Check configuration timeout */
+      if(!TIMED_OUT(entry->conftime))
+	{
+	  /* If registered - do not accept! */
+	  olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
+	  return 0;
+	}
+      else
+	{
+	  olsr_printf(1, "[ENC]Challenge from registered node...accepted!\n");
+	}
+    }
+
+  olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
+
+  /* Check signature */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+  
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, 
+	   sha1_hash);
+  }  
+  if(memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0)
+    {
+      olsr_printf(1, "[ENC]Signature missmatch in challenge!\n");
+      return 0;
+    }
+
+  olsr_printf(3, "[ENC]Signature verified\n");
+
+  
+  entry->diff = 0;
+  entry->validated = 0;
+
+  /* update validtime - not validated */
+  entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
+
+  /* Build and send response */
+
+  send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator, 
+	    (union olsr_ip_addr *)&msg->destination, 
+	    ntohl(msg->challenge),
+	    entry);
+
+  return 1;
+}
+
+
+
+
+
+/**
+ * Build and transmit a challenge response
+ * message.
+ *
+ */
+int
+send_cres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, olsr_u32_t chal_in, struct stamp *entry)
+{
+  struct c_respmsg crmsg;
+  olsr_u32_t challenge;
+  struct ipaddr_str buf;
+
+  olsr_printf(1, "[ENC]Building CRESPONSE message\n");
+
+  challenge = rand() << 16;
+  challenge |= rand();
+
+  entry->challenge = challenge;
+
+  olsr_printf(3, "[ENC]Challenge-response: 0x%x\n", challenge);
+
+  /* Fill challengemessage */
+  crmsg.olsr_msgtype = TYPE_CRESPONSE;
+  crmsg.olsr_vtime = 0;
+  crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
+  memcpy(&crmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+  crmsg.ttl = 1;
+  crmsg.hopcnt = 0;
+  crmsg.seqno = htons(get_msg_seqno());
+
+  /* set timestamp */
+  crmsg.timestamp = now.tv_sec;
+  olsr_printf(3, "[ENC]Timestamp %ld\n", crmsg.timestamp);
+
+  /* Fill subheader */
+  memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
+  crmsg.challenge = htonl(challenge);
+
+  /* Create digest of received challenge + IP */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the challenge received */
+  memcpy(checksum_cache, &chal_in, 4);
+  /* Then the local IP */
+  memcpy(&checksum_cache[sizeof(olsr_u32_t)], from, olsr_cnf->ipsize);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   sizeof(olsr_u32_t) + olsr_cnf->ipsize, 
+	   crmsg.res_sig);
+  }
+
+  /* Now create the digest of the message and the key */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, &crmsg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, 
+	   crmsg.signature);
+  }
+
+  olsr_printf(3, "[ENC]Sending challenge response to %s challenge 0x%x\n", 
+	      olsr_ip_to_string(&buf, to),
+	      challenge);
+
+  /* Add to buffer */
+  net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
+  /* Send the request */
+  net_output(olsr_if);
+
+  return 1;
+}
+
+
+
+
+
+
+/**
+ * Build and transmit a response response
+ * message.
+ *
+ */
+static int
+send_rres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, olsr_u32_t chal_in)
+{
+  struct r_respmsg rrmsg;
+  struct ipaddr_str buf;
+
+  olsr_printf(1, "[ENC]Building RRESPONSE message\n");
+
+
+  /* Fill challengemessage */
+  rrmsg.olsr_msgtype = TYPE_RRESPONSE;
+  rrmsg.olsr_vtime = 0;
+  rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
+  memcpy(&rrmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+  rrmsg.ttl = 1;
+  rrmsg.hopcnt = 0;
+  rrmsg.seqno = htons(get_msg_seqno());
+
+  /* set timestamp */
+  rrmsg.timestamp = now.tv_sec;
+  olsr_printf(3, "[ENC]Timestamp %ld\n", rrmsg.timestamp);
+
+  /* Fill subheader */
+  memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
+
+  /* Create digest of received challenge + IP */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the challenge received */
+  memcpy(checksum_cache, &chal_in, 4);
+  /* Then the local IP */
+  memcpy(&checksum_cache[sizeof(olsr_u32_t)], from, olsr_cnf->ipsize);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   sizeof(olsr_u32_t) + olsr_cnf->ipsize, 
+	   rrmsg.res_sig);
+  }
+
+  /* Now create the digest of the message and the key */
+
+  {
+  olsr_u8_t checksum_cache[512 + KEYLENGTH];
+  /* Create packet + key cache */
+  /* First the OLSR packet + signature message - digest */
+  memcpy(checksum_cache, &rrmsg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
+  /* Then the key */
+  memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
+
+  /* Create the hash */
+  CHECKSUM(checksum_cache, 
+	   (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, 
+	   rrmsg.signature);
+  }
+
+  olsr_printf(3, "[ENC]Sending response response to %s\n", 
+	      olsr_ip_to_string(&buf, to));
+
+  /* add to buffer */
+  net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
+
+  /* Send the request */
+  net_output(olsr_if);
+
+  return 1;
+}
+
+
+
+static struct stamp *
+lookup_timestamp_entry(const union olsr_ip_addr *adr)
+{
+  olsr_u32_t hash;
+  struct stamp *entry;
+  struct ipaddr_str buf;
+
+  hash = olsr_ip_hashing(adr);
+
+  for(entry = timestamps[hash].next;
+      entry != &timestamps[hash];
+      entry = entry->next)
+    {
+      if(memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0)
+	{
+	  olsr_printf(3, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
+	  return entry;
+	}
+    }
+
+  olsr_printf(1, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
+
+  return NULL;
+}
+
+
+
+/**
+ *Find timed out entries and delete them
+ *
+ *@return nada
+ */
+void
+timeout_timestamps(void* foo __attribute__((unused)))
+{
+  struct stamp *tmp_list;
+  struct stamp *entry_to_delete;
+  int index;
+
+  /* Update our local timestamp */
+  gettimeofday(&now, NULL);
+
+  for(index=0;index<HASHSIZE;index++)
+    {
+      tmp_list = timestamps[index].next;
+      /*Traverse MID list*/
+      while(tmp_list != &timestamps[index])
+	{
+	  /*Check if the entry is timed out*/
+	  if((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime)))
+	    {
+              struct ipaddr_str buf;
+	      entry_to_delete = tmp_list;
+	      tmp_list = tmp_list->next;
+
+	      olsr_printf(1, "[ENC]timestamp info for %s timed out.. deleting it\n", 
+			  olsr_ip_to_string(&buf, &entry_to_delete->addr));
+
+	      /*Delete it*/
+	      entry_to_delete->next->prev = entry_to_delete->prev;
+	      entry_to_delete->prev->next = entry_to_delete->next;
+
+	      free(entry_to_delete);
+	    }
+	  else
+	      tmp_list = tmp_list->next;
+	}
+    }
+
+  return;
+}
+
+
+
+static int
+read_key_from_file(const char *file)
+{
+  FILE *kf;
+  size_t keylen;
+
+  keylen = 16;
+  kf = fopen(file, "r");
+
+  olsr_printf(1, "[ENC]Reading key from file \"%s\"\n", file);
+
+  if(kf == NULL)
+    {
+      olsr_printf(1, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
+      return -1;
+    }
+
+  if(fread(aes_key, 1, keylen, kf) != keylen)
+    {
+      olsr_printf(1, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
+      fclose(kf);
+      return 0;
+    }
+
+
+  fclose(kf);
+  return 1;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/olsrd_secure.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/olsrd_secure.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/olsrd_secure.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/olsrd_secure.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,79 @@
+/*
+ * Secure OLSR plugin
+ * http://www.olsr.org
+ *
+ * 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 olsrd, olsr.org 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.
+ *
+ */
+
+/*
+ * Dynamic linked library example for UniK OLSRd
+ */
+
+#ifndef _OLSRD_PLUGIN_TEST
+#define _OLSRD_PLUGIN_TEST
+
+#include "secure_messages.h"
+
+#include "hashing.h"
+
+
+#define KEYFILE "/etc/olsrd.d/olsrd_secure_key"
+
+/* Schemes */
+#define ONE_CHECKSUM          1
+
+/* Algorithm definitions */
+#define SHA1_INCLUDING_KEY   1
+#define MD5_INCLUDING_KEY   2
+
+#ifdef USE_OPENSSL
+#define SIGNATURE_SIZE 20
+#else
+#define SIGNATURE_SIZE 16
+#endif
+
+#define KEYLENGTH      16
+
+#define UPPER_DIFF 3
+#define LOWER_DIFF -3
+
+extern char aes_key[16];
+/* Seconds of slack allowed */
+#define SLACK 3
+
+int secure_plugin_init(void);
+
+void secure_plugin_exit(void);
+
+int plugin_ipc_init(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/secure_messages.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/secure_messages.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/src/secure_messages.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/src/secure_messages.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,213 @@
+
+/*
+ * Secure OLSR plugin
+ * http://www.olsr.org
+ *
+ * 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 olsrd, olsr.org 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.
+ *
+ */
+
+
+/*
+ * olsr.org olsr daemon security plugin
+ */
+
+#ifndef _OLSRD_SECURE_MSG
+#define _OLSRD_SECURE_MSG
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "olsr_types.h"
+#include "interfaces.h"
+
+/* The type of message you will use */
+#define MESSAGE_TYPE 10
+
+/* The type of messages we will receive - can be set to promiscuous */
+#define PARSER_TYPE MESSAGE_TYPE
+
+#define TYPE_CHALLENGE 11
+#define TYPE_CRESPONSE 12
+#define TYPE_RRESPONSE 13
+
+
+extern char keyfile[FILENAME_MAX+1];
+
+
+#ifdef USE_OPENSSL
+#define SIGSIZE   20
+#else
+#define SIGSIZE   16
+#endif
+
+/****************************************************************************
+ *                            PACKET SECTION                                *
+ ****************************************************************************/
+
+struct sig_msg
+{
+  olsr_u8_t     type;
+  olsr_u8_t     algorithm;
+  olsr_u16_t    reserved;
+
+  time_t        timestamp;
+  olsr_u8_t     signature[SIGSIZE];
+};
+
+/*
+ * OLSR message (several can exist in one OLSR packet)
+ */
+
+struct s_olsrmsg
+{
+  olsr_u8_t     olsr_msgtype;
+  olsr_u8_t     olsr_vtime;
+  olsr_u16_t    olsr_msgsize;
+  olsr_u32_t    originator;
+  olsr_u8_t     ttl;
+  olsr_u8_t     hopcnt;
+  olsr_u16_t    seqno;
+
+  /* YOUR PACKET GOES HERE */
+  struct sig_msg sig;
+
+};
+
+
+/*
+ * Challenge response messages
+ */
+
+struct challengemsg
+{
+  olsr_u8_t     olsr_msgtype;
+  olsr_u8_t     olsr_vtime;
+  olsr_u16_t    olsr_msgsize;
+  olsr_u32_t    originator;
+  olsr_u8_t     ttl;
+  olsr_u8_t     hopcnt;
+  olsr_u16_t    seqno;
+
+  olsr_u32_t    destination;
+  olsr_u32_t    challenge;
+
+  olsr_u8_t     signature[SIGSIZE];
+
+};
+
+
+
+struct c_respmsg
+{
+  olsr_u8_t     olsr_msgtype;
+  olsr_u8_t     olsr_vtime;
+  olsr_u16_t    olsr_msgsize;
+  olsr_u32_t    originator;
+  olsr_u8_t     ttl;
+  olsr_u8_t     hopcnt;
+  olsr_u16_t    seqno;
+
+  olsr_u32_t    destination;
+  olsr_u32_t    challenge;
+  time_t        timestamp;
+
+  olsr_u8_t     res_sig[SIGSIZE];
+
+  olsr_u8_t     signature[SIGSIZE];
+};
+
+
+struct r_respmsg
+{
+  olsr_u8_t     olsr_msgtype;
+  olsr_u8_t     olsr_vtime;
+  olsr_u16_t    olsr_msgsize;
+  olsr_u32_t    originator;
+  olsr_u8_t     ttl;
+  olsr_u8_t     hopcnt;
+  olsr_u16_t    seqno;
+
+  olsr_u32_t    destination;
+  time_t        timestamp;
+
+  olsr_u8_t     res_sig[SIGSIZE];
+
+  olsr_u8_t     signature[SIGSIZE];
+};
+
+
+/*
+ *IPv6
+ */
+
+struct s_olsrmsg6
+{
+  olsr_u8_t        olsr_msgtype;
+  olsr_u8_t        olsr_vtime;
+  olsr_u16_t       olsr_msgsize;
+  struct in6_addr  originator;
+  olsr_u8_t        ttl;
+  olsr_u8_t        hopcnt;
+  olsr_u16_t       seqno;
+
+  /* YOUR PACKET GOES HERE */
+  struct sig_msg   sig;
+};
+
+/*
+ * Generic OLSR packet - DO NOT ALTER
+ */
+
+struct s_olsr 
+{
+  olsr_u16_t	  olsr_packlen;		/* packet length */
+  olsr_u16_t	  olsr_seqno;
+  struct s_olsrmsg  olsr_msg[1];          /* variable messages */
+};
+
+
+struct s_olsr6
+{
+  olsr_u16_t	    olsr_packlen;        /* packet length */
+  olsr_u16_t	    olsr_seqno;
+  struct s_olsrmsg6   olsr_msg[1];         /* variable messages */
+};
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/secure/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/secure/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/chat_head.lsp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/chat_head.lsp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/chat_head.lsp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/chat_head.lsp	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,30 @@
+<?lua
+
+ tas.keep_state()
+
+ tas.add_header_line("Refresh: 5");
+
+ if not channel or channel == "" then
+  channel = "Open"
+ end
+
+ if not nick or nick == "" then
+  nick = "OLSR User"
+ end
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+  <head>
+    <title>
+      OLSR Chat Head Window
+    </title>
+  </head>
+  <body>
+
+    <h2>User "<?lua tas.write(nick) ?>" in channel "<?lua tas.write(channel) ?>"</h2>
+
+  </body>
+</html>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/chat_recv.lsp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/chat_recv.lsp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/chat_recv.lsp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/chat_recv.lsp	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,103 @@
+<?lua
+
+ tas.keep_state()
+
+ tas.add_header_line("Refresh: 5");
+
+ if not channel or channel == "" then
+  channel = "Open"
+ end
+
+ if not nick or nick == "" then
+  nick = "OLSR User"
+ end
+
+ if not list then
+  list = {}
+ end
+
+ if not listLen then
+  listLen = 0
+ end
+
+ maxListLen = 25
+ httpPort = 1979
+
+ while true do
+  msg, from = tas.olsr_get_message("chat00")
+
+  if not msg then break end
+
+  msg = string.gsub(msg, "&", "&amp;")
+  msg = string.gsub(msg, "<", "&lt;")
+  msg = string.gsub(msg, ">", "&gt;")
+
+  if listLen == maxListLen then
+   for i = 0, maxListLen - 2 do
+    list[i] = list[i + 1]
+   end
+
+   listLen = listLen - 1
+  end
+
+  _, _, channel2, nick2, message = string.find(msg, "([^~]*)~([^~]*)~([^~]*)")
+
+  if string.lower(channel) == string.lower(channel2) then
+
+   list[listLen] = {}
+   list[listLen]["from"] = from
+   list[listLen]["channel"] = channel2
+   list[listLen]["nick"] = nick2
+   list[listLen]["message"] = message
+
+   listLen = listLen + 1
+
+  end
+
+ end
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+  <head>
+    <title>
+      OLSR Chat Receive Window
+    </title>
+  </head>
+  <body>
+
+<?lua
+
+ for i = 0, listLen - 1 do
+
+  if i == listLen - 1 then
+
+?>
+
+ <a name="bottom"></a>
+
+<?lua
+
+  end
+
+?>
+
+    <p>
+      <b><?lua tas.write(list[i]["nick"]) ?></b>
+      (<a href="http://<?lua tas.write(list[i]["from"]) ?>:<?lua tas.write(httpPort) ?>/pub/profile.html" target="_profile"><?lua tas.write(list[i]["from"]) ?></a>),
+      <?lua tas.write(list[i]["channel"]) ?>:
+      <?lua tas.write(list[i]["message"]) ?>
+    </p>
+
+<?lua
+
+ end
+
+?>
+
+    <form>
+
+  </body>
+</html>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/chat_send.lsp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/chat_send.lsp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/chat_send.lsp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/chat_send.lsp	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,64 @@
+<?lua
+
+ tas.keep_state()
+
+ para = tas.get_parameters()
+
+ message = para["message"]
+
+ if para["channel"] then
+  channel = para["channel"]
+ end
+
+ if para["nick"] then
+  nick = para["nick"]
+ end
+
+ if not channel or channel == "" then
+  channel = "Open"
+ end
+
+ if not nick or nick == "" then
+  nick = "OLSR User"
+ end 
+
+ if message and message ~= "" then
+  channel = string.gsub(channel, "~", "?")
+  nick = string.gsub(nick, "~", "?")
+  message = string.gsub(message, "~", "?")
+
+  payload = channel.."~"..nick.."~"..message
+
+  tas.olsr_send_message("chat00", payload)
+ end
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+  <head>
+    <title>
+      OLSR Chat Send Window
+    </title>
+  </head>
+  <body>
+    <form method="GET" action="chat_send.lsp">
+      <table>
+        <tr>
+          <td>Channel</td>
+          <td><input type="text" name="channel" size="20" value="<?lua tas.write(channel) ?>"></td>
+        </tr>
+        <tr>
+          <td>Nickname</td>
+          <td><input type="text" name="nick" size="20" value="<?lua tas.write(nick) ?>"></td>
+        </tr>
+        <tr>
+          <td>Message</td>
+          <td><input type="text" name="message" size="80" value=""></td>
+          <td><input type="submit" name="ok" value="OK"></td>
+        </tr>
+      </table>
+    </form>
+  </body>
+</html>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/index.html ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/index.html
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/index.html	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/index.html	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+  <head>
+    <title>
+      OLSR Chat
+    </title>
+  </head>
+  <frameset rows="10%, 70%, 20%">
+    <frame src="chat_head.lsp" name="Head">
+    <frame src="chat_recv.lsp#bottom" name="Receive">
+    <frame src="chat_send.lsp" name="Send">
+  </frameset>
+</html>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/pub/profile.html ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/pub/profile.html
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/pub/profile.html	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/pub/profile.html	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+  <head>
+    <title>
+      OLSR Chat
+    </title>
+  </head>
+  <body>
+    <p>
+      This could be your profile.
+    </p>
+  </body>
+</html>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/show.lsp ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/show.lsp
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/data/show.lsp	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/data/show.lsp	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,306 @@
+<?lua
+
+ olsr_state = tas.olsr_get_info()
+
+?>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+  <head>
+    <title>
+      OLSR State
+    </title>
+  </head>
+  <body>
+
+    <h2>Links</h2>
+
+    <table border="1">
+      <tr>
+        <td>
+          <b>Local</b>
+        </td>
+        <td>
+          <b>Remote</b>
+        </td>
+        <td>
+          <b>Main</b>
+        </td>
+        <td>
+          <b>Hysteresis</b>
+        </td>
+        <td>
+          <b>LQ</b>
+        </td>
+        <td>
+          <b>NLQ</b>
+        </td>
+        <td>
+          <b>ETX</b>
+        </td>
+      <tr>
+
+<?lua
+
+i = 0
+
+while olsr_state["links"][i] do
+
+?>
+
+      <tr>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["local"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["remote"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["main"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["hysteresis"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["lq"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["nlq"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["links"][i]["etx"]) ?>
+        </td>
+      </tr>
+
+<?lua
+
+i = i + 1
+
+end
+
+?>
+
+    </table>
+
+    <h2>Neighbors</h2>
+
+    <table border="1">
+      <tr>
+        <td>
+          <b>Main</b>
+        </td>
+        <td>
+          <b>Symmetric</b>
+        </td>
+        <td>
+          <b>MPR</b>
+        </td>
+        <td>
+          <b>MPRS</b>
+        </td>
+        <td>
+          <b>Willingness</b>
+        </td>
+        <td>
+          <b>2-Hop Neighbors</b>
+        </td>
+      <tr>
+
+<?lua
+
+i = 0
+
+while olsr_state["neighbors"][i] do
+
+?>
+
+      <tr>
+        <td>
+          <?lua tas.write(olsr_state["neighbors"][i]["main"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["neighbors"][i]["symmetric"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["neighbors"][i]["mpr"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["neighbors"][i]["mprs"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["neighbors"][i]["willingness"]) ?>
+        </td>
+        <td>
+
+          <?lua
+
+           k = 0
+
+           while olsr_state["neighbors"][i]["neighbors2"][k] do
+
+            tas.write(olsr_state["neighbors"][i]["neighbors2"][k])
+
+          ?>
+
+          <br>
+
+          <?lua
+
+            k = k + 1
+
+           end
+
+          ?>
+
+        </td>
+      </tr>
+
+<?lua
+
+i = i + 1
+
+end
+
+?>
+
+    </table>
+
+    <h2>Topology</h2>
+
+    <table border="1">
+      <tr>
+        <td>
+          <b>Main</b>
+        </td>
+        <td>
+          <b>Destination</b>
+        </td>
+        <td>
+          <b>ETX</b>
+        </td>
+      <tr>
+
+<?lua
+
+i = 0
+
+while olsr_state["topology"][i] do
+
+?>
+
+      <tr>
+        <td>
+          <?lua tas.write(olsr_state["topology"][i]["main"]) ?>
+        </td>
+        <td>
+
+          <?lua
+
+           k = 0
+
+           while olsr_state["topology"][i]["destinations"][k] do
+
+            tas.write(olsr_state["topology"][i]["destinations"][k]["address"])
+
+          ?>
+
+          <br>
+
+          <?lua
+
+            k = k + 1
+
+           end
+
+          ?>
+
+        </td>
+        <td>
+
+          <?lua
+
+           k = 0
+
+           while olsr_state["topology"][i]["destinations"][k] do
+
+            tas.write(olsr_state["topology"][i]["destinations"][k]["etx"])
+
+          ?>
+
+          <br>
+
+          <?lua
+
+            k = k + 1
+
+           end
+
+          ?>
+
+        </td>
+      </tr>
+
+<?lua
+
+i = i + 1
+
+end
+
+?>
+
+    </table>
+
+    <h2>Routes</h2>
+
+    <table border="1">
+      <tr>
+        <td>
+          <b>Destination</b>
+        </td>
+        <td>
+          <b>Gateway</b>
+        </td>
+        <td>
+          <b>Interface</b>
+        </td>
+        <td>
+          <b>Metric</b>
+        </td>
+      <tr>
+
+<?lua
+
+i = 0
+
+while olsr_state["routes"][i] do
+
+?>
+
+      <tr>
+        <td>
+          <?lua tas.write(olsr_state["routes"][i]["destination"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["routes"][i]["gateway"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["routes"][i]["interface"]) ?>
+        </td>
+        <td>
+          <?lua tas.write(olsr_state["routes"][i]["metric"]) ?>
+        </td>
+      </tr>
+
+<?lua
+
+i = i + 1
+
+end
+
+?>
+
+    </table>
+
+  </body>
+</html>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/lua-license.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/lua-license.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/lua-license.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/lua-license.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,22 @@
+/******************************************************************************
+* Copyright (C) 1994-2004 Tecgraf, PUC-Rio.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,75 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_tas
+PLUGIN_VER =	0.1
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+SRCS +=		$(wildcard src/lua/*.c)
+HDRS +=		$(wildcard src/lua/*.h)
+
+ifneq ($(OS),win32)
+LIBS +=		-lm
+endif
+
+ifneq ($(OS),linux)
+
+default_target install clean: 
+	@echo "*** TAS Plugin only supported on Linux, sorry!"
+
+else
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+# this is not nice but there is no nicer solution
+src/lua/lapi.o src/lua/ltable.o:  CFLAGS += -Wno-cast-qual
+
+install:	$(PLUGIN_FULLNAME)
+		$(STRIP) $(PLUGIN_FULLNAME)
+		$(INSTALL_LIB)
+
+clean:
+		rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
+
+endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,501 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "lua/lua.h"
+#include "lua/lauxlib.h"
+#include "lua/lualib.h"
+
+#include "link.h"
+#include "plugin.h"
+#include "lib.h"
+#include "os_unix.h"
+#include "http.h"
+#include "glua.h"
+#include "glua_ext.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static const char infoKey;
+static const char keepFlagKey;
+static const char argListKey;
+    
+int lspToLua(const char *rootDir, const char *lspFileName,
+             const char *workDir, const char *luaFileName)
+{
+  FILE *file;
+  int lspLen;
+  unsigned char *buff;
+  int start, code, i, k;
+  char *lspPath = fullPath(rootDir, lspFileName);
+  char *luaPath = fullPath(workDir, luaFileName);
+
+  if (fileIsNewer(lspPath, luaPath) == 0)
+  {
+    freeMem(lspPath);
+    freeMem(luaPath);
+    return 0;
+  }
+
+  file = fopen(lspPath, "r");
+
+  if (file == NULL)
+  {
+    error("cannot open %s\n", lspPath);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    return -1;
+  }
+
+  if (fseek(file, 0, SEEK_END) < 0)
+  {
+    error("cannot seek to end of %s\n", lspPath);
+    fclose(file);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    return -1;
+  }
+
+  lspLen = ftell(file);
+
+  if (lspLen < 0)
+  {
+    error("cannot determine length of %s\n", lspPath);
+    fclose(file);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    return -1;
+  }
+
+  if (fseek(file, 0, SEEK_SET) < 0)
+  {
+    error("cannot seek to beginning of %s\n", lspPath);
+    fclose(file);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    return -1;
+  }
+
+  buff = allocMem(lspLen);
+
+  if (fread(buff, lspLen, 1, file) != 1)
+  {
+    error("cannot read %s\n", lspPath);
+    fclose(file);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    freeMem(buff);
+    return -1;
+  }
+
+  fclose(file);
+
+  if (createAllDirs(luaPath) < 0)
+  {
+    error("cannot create required directories for %s\n",
+          luaPath);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    freeMem(buff);
+    return -1;
+  }
+
+  file = fopen(luaPath, "w");
+
+  if (file == NULL)
+  {
+    error("cannot open %s\n", luaPath);
+    freeMem(lspPath);
+    freeMem(luaPath);
+    freeMem(buff);
+    return -1;
+  }
+
+  start = 0;
+  code = 0;
+
+  i = 0;
+
+  for (;;)
+  {
+    if (code == 0 && (i == lspLen || strncmp((char *)(buff + i), "<?lua", 5) == 0))
+    {
+      fprintf(file, "tas.write(\"");
+
+      for (k = start; k < i; k++)
+      {
+        if (buff[k] == 13)
+          continue;
+
+        if (buff[k] == '\\' || buff[k] == '"' || buff[k] == 10)
+          fputc('\\', file);
+
+        fputc(buff[k], file);
+      }
+
+      fprintf(file, "\")\n");
+
+      if (i == lspLen)
+        break;
+
+      if (buff[i + 5] == '=')
+      {
+        i += 6;
+        code = 2;
+      }
+
+      else
+      {
+        i += 5;
+        code = 1;
+      }
+
+      start = i;
+
+      continue;
+    }
+
+    if (code > 0 && (i == lspLen || strncmp((char *)(buff + i), "?>", 2) == 0))
+    {
+      if (code > 1)
+        fprintf(file, "tas.write(");
+
+      for (k = start; k < i; k++)
+        if (buff[k] != 13)
+          fputc(buff[k], file);
+
+      if (code > 1)
+        fputc(')', file);
+
+      fputc('\n', file);
+
+      if (i == lspLen)
+        break;
+
+      i += 2;
+      start = i;
+
+      code = 0;
+
+      continue;
+    }
+
+    i++;
+  }
+
+  fclose(file);
+  freeMem(lspPath);
+  freeMem(luaPath);
+  freeMem(buff);
+  return 0;
+}
+
+static int luaWriter(lua_State *lua __attribute__((unused)), const void *buff, int len, FILE *file)
+{
+  return fwrite(buff, len, 1, file) == 1;
+}
+
+int luaToLex(char **errMsg, const char *workDir, const char *luaFileName,
+             const char *lexFileName)
+{
+  lua_State *lua;
+  int res;
+  FILE *file;
+  char *luaPath = fullPath(workDir, luaFileName);
+  char *lexPath = fullPath(workDir, lexFileName);
+
+  *errMsg = NULL;
+
+  if (fileIsNewer(luaPath, lexPath) == 0)
+  {
+    freeMem(luaPath);
+    freeMem(lexPath);
+    return 0;
+  }
+
+  lua = lua_open();
+
+  res = luaL_loadfile(lua, luaPath);
+
+  if (res != 0)
+  {
+    *errMsg = myStrdup(lua_tostring(lua, -1));
+    error("cannot load %s: %s\n", luaPath, *errMsg);
+    lua_close(lua);
+    freeMem(luaPath);
+    freeMem(lexPath);
+    return -1;
+  }
+
+  file = fopen(lexPath, "wb");
+
+  if (file == NULL)
+  {
+    error("cannot open %s\n", lexPath);
+    lua_close(lua);
+    freeMem(luaPath);
+    freeMem(lexPath);
+    return -1;
+  }
+
+  lua_dump(lua, (lua_Chunkwriter)luaWriter, file);
+
+  fclose(file);
+
+  lua_close(lua);
+  freeMem(luaPath);
+  freeMem(lexPath);
+  return 0;
+}
+
+static int tasWrite(lua_State *lua)
+{
+  int numArg = lua_gettop(lua);
+  const char *strConv;
+  int i;
+  struct connInfo *info;
+
+  lua_pushlightuserdata(lua, &infoKey);
+  lua_gettable(lua, LUA_REGISTRYINDEX);
+
+  info = lua_touserdata(lua, -1);
+
+  lua_getglobal(lua, "tostring");
+
+  for (i = 1; i <= numArg; i++)
+  {
+    lua_pushvalue(lua, -1);
+    lua_pushvalue(lua, i);
+
+    lua_call(lua, 1, 1);
+
+    strConv = lua_tostring(lua, -1);
+
+    if (strConv == NULL)
+      return luaL_error(lua, "cannot convert value to string");
+
+    writeBuff(&info->write[2], (const unsigned char *)strConv, strlen(strConv));
+
+    lua_pop(lua, 1);
+  }
+
+  return 0;
+}
+
+static int tasAddHeaderLine(lua_State *lua)
+{
+  struct connInfo *info;
+  char *line;
+
+  lua_pushlightuserdata(lua, &infoKey);
+  lua_gettable(lua, LUA_REGISTRYINDEX);
+
+  info = lua_touserdata(lua, -1);
+
+  line = myStrdup(luaL_checkstring(lua, 1));
+
+  chomp(line, strlen(line));
+
+  writeBuff(&info->write[1], (const unsigned char *)line, strlen(line));
+  writeBuff(&info->write[1], (const unsigned char *)"\r\n", 2);
+
+  freeMem(line);
+
+  return 0;
+}
+
+static int tasSetContentType(lua_State *lua)
+{
+  struct connInfo *info;
+  const char *contType;
+  char *s;
+
+  lua_pushlightuserdata(lua, &infoKey);
+  lua_gettable(lua, LUA_REGISTRYINDEX);
+
+  info = lua_touserdata(lua, -1);
+
+  contType = luaL_checkstring(lua, 1);
+
+  s = allocBuff(info, strlen(contType) + 1);
+  strcpy(s, contType);
+
+  return 0;
+}
+
+static int tasKeepState(lua_State *lua)
+{
+  int *keepFlag;
+
+  lua_pushlightuserdata(lua, &keepFlagKey);
+  lua_gettable(lua, LUA_REGISTRYINDEX);
+
+  keepFlag = lua_touserdata(lua, -1);
+
+  *keepFlag = 1;
+
+  return 0;
+}
+
+static int tasGetParameters(lua_State *lua)
+{
+  int i;
+  char **argList;
+
+  lua_pushlightuserdata(lua, &argListKey);
+  lua_gettable(lua, LUA_REGISTRYINDEX);
+
+  argList = lua_touserdata(lua, -1);
+
+  lua_newtable(lua);
+
+  if (argList == NULL)
+    return 1;
+  
+  for (i = 0; argList[i] != NULL; i += 2)
+  {
+    lua_pushstring(lua, argList[i]);
+    lua_pushstring(lua, argList[i + 1]);
+    lua_settable(lua, -3);
+  }
+
+  return 1;
+}
+
+static const struct luaL_reg tasLib[] =
+{
+  { "write", tasWrite },
+  { "set_content_type", tasSetContentType },
+  { "add_header_line", tasAddHeaderLine },
+  { "keep_state", tasKeepState },
+  { "get_parameters", tasGetParameters },
+#ifdef TAS_EXTRA_FUNCTIONS
+  TAS_EXTRA_FUNCTIONS
+#endif
+  { NULL, NULL }
+};
+
+static int luaopen_tas(lua_State *lua)
+{
+  luaL_openlib(lua, "tas", tasLib, 0);
+  return 1;
+}
+
+int runLua(char **errMsg, struct connInfo *info, const char *workDir,
+           const char *lexFileName, char **argList, void **session)
+{
+  lua_State *lua;
+  int res;
+  char *lexPath = fullPath(workDir, lexFileName);
+  int keepFlag = 0;
+
+  *errMsg = NULL;
+
+  if (*session == NULL)
+  {
+    lua = lua_open();
+
+    luaopen_base(lua);
+    luaopen_table(lua);
+    luaopen_io(lua);
+    luaopen_string(lua);
+    luaopen_math(lua);
+    luaopen_debug(lua);
+    luaopen_loadlib(lua);
+
+    luaopen_tas(lua);
+  }
+
+  else
+    lua = *session;
+
+  lua_pushlightuserdata(lua, &infoKey);
+  lua_pushlightuserdata(lua, info);
+  lua_settable(lua, LUA_REGISTRYINDEX);
+    
+  lua_pushlightuserdata(lua, &argListKey);
+  lua_pushlightuserdata(lua, argList);
+  lua_settable(lua, LUA_REGISTRYINDEX);
+    
+  lua_pushlightuserdata(lua, &keepFlagKey);
+  lua_pushlightuserdata(lua, &keepFlag);
+  lua_settable(lua, LUA_REGISTRYINDEX);
+
+  res = luaL_loadfile(lua, lexPath);
+
+  if (res != 0)
+  {
+    *errMsg = myStrdup(lua_tostring(lua, -1));
+    error("cannot load %s: %s\n", lexPath, *errMsg);
+    lua_close(lua);
+    freeMem(lexPath);
+    return -1;
+  }
+
+  res = lua_pcall(lua, 0, 0, 0);
+
+  if (res != 0)
+  {
+    *errMsg = myStrdup(lua_tostring(lua, -1));
+    error("cannot run %s: %s\n", lexPath, *errMsg);
+    lua_close(lua);
+    freeMem(lexPath);
+    return -1;
+  }
+
+  if (keepFlag == 0)
+  {
+    lua_close(lua);
+    *session = NULL;
+  }
+
+  else
+    *session = lua;
+
+
+  freeMem(lexPath);
+  return 0;
+}
+
+void freeLuaSession(void *session)
+{
+  lua_close(session);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua_ext.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua_ext.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua_ext.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua_ext.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,243 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "lua/lua.h"
+#include "lua/lauxlib.h"
+#include "lua/lualib.h"
+
+#include "link.h"
+#include "plugin.h"
+#include "lib.h"
+#include "os_unix.h"
+#include "http.h"
+#include "glua.h"
+#include "glua_ext.h"
+
+#include <string.h>
+
+static char *getToken(char **point)
+{
+  char *localPoint = *point;
+  char *start;
+
+  start = localPoint;
+
+  while (*localPoint != '~' && *localPoint != 0)
+    localPoint++;
+
+  if (*localPoint == 0)
+    return NULL;
+
+  *localPoint++ = 0;
+
+  *point = localPoint;
+
+  return start;
+}
+
+int tasOlsrSendMessage(lua_State *lua)
+{
+  const char *service;
+  const char *string;
+
+  service = luaL_checkstring(lua, 1);
+  string = luaL_checkstring(lua, 2);
+
+  sendMessage(service, string);
+  httpAddTasMessage(service, string, "localhost");
+
+  return 0;
+}
+
+int tasOlsrGetMessage(lua_State *lua)
+{
+  const char *service;
+  char *string;
+  char *from;
+
+  service = luaL_checkstring(lua, 1);
+
+  if (httpGetTasMessage(service, &string, &from) < 0)
+  {
+    lua_pushnil(lua);
+    lua_pushnil(lua);
+  }
+
+  else
+  {
+    lua_pushstring(lua, string);
+    lua_pushstring(lua, from);
+
+    freeMem(string);
+    freeMem(from);
+  }
+
+  return 2;
+}
+
+static void addSubTable(lua_State *lua, char **walker)
+{
+  char *token;
+  unsigned int val;
+
+  token = getToken(walker);
+
+  if (token == NULL)
+  {
+    error("premature end of buffer\n");
+    return;
+  }
+
+  if (stringToInt(&val, token) < 0)
+    lua_pushstring(lua, token);
+
+  else
+    lua_pushnumber(lua, val);
+
+  lua_newtable(lua);
+
+  while (**walker != 0)
+  {
+    token = getToken(walker);
+
+    if (token == NULL)
+    {
+      error("premature end of buffer\n");
+      return;
+    }
+
+    if (strcmp(token, "]") == 0)
+      return;
+
+    if (strcmp(token, "[") == 0)
+      addSubTable(lua, walker);
+
+    else
+    {
+      if (stringToInt(&val, token) < 0)
+        lua_pushstring(lua, token);
+
+      else
+        lua_pushnumber(lua, val);
+
+      token = getToken(walker);
+
+      if (token == NULL)
+      {
+        error("premature end of buffer\n");
+        return;
+      }
+
+      lua_pushstring(lua, token);
+    }
+
+    lua_settable(lua, -3);
+  }
+}
+
+static void addTable(lua_State *lua, const char *name, void (*init)(void),
+                     int (*next)(char *buff, int len))
+{
+  int i;
+  char buff[1024], *walker, *token;
+
+  lua_pushstring(lua, name);
+  lua_newtable(lua);
+
+  init();
+
+  i = 0;
+
+  while (next(buff, sizeof (buff)) >= 0)
+  {
+    walker = buff;
+
+    lua_pushnumber(lua, i++);
+    lua_newtable(lua);
+
+    while (*walker != 0)
+    {
+      token = getToken(&walker);
+
+      if (token == NULL)
+      {
+        error("premature end of buffer\n");
+        return;
+      }
+
+      if (strcmp(token, "[") == 0)
+        addSubTable(lua, &walker);
+
+      else
+      {
+        lua_pushstring(lua, token);
+
+        token = getToken(&walker);
+
+        if (token == NULL)
+        {
+          error("premature end of buffer\n");
+          return;
+        }
+
+        lua_pushstring(lua, token);
+      }
+
+      lua_settable(lua, -3);
+    }
+
+    lua_settable(lua, -3);
+  }
+
+  lua_settable(lua, -3);
+}
+
+int tasOlsrGetInfo(lua_State *lua)
+{
+  lua_newtable(lua);
+
+  addTable(lua, "routes", iterRouteTabInit, iterRouteTabNext);
+  addTable(lua, "links", iterLinkTabInit, iterLinkTabNext);
+  addTable(lua, "neighbors", iterNeighTabInit, iterNeighTabNext);
+  addTable(lua, "topology", iterTcTabInit, iterTcTabNext);
+
+  return 1;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua_ext.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua_ext.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua_ext.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua_ext.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,51 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "lua/lua.h"
+
+#define TAS_EXTRA_FUNCTIONS \
+  { "olsr_send_message", tasOlsrSendMessage }, \
+  { "olsr_get_message", tasOlsrGetMessage }, \
+  { "olsr_get_info", tasOlsrGetInfo },
+
+extern int tasOlsrSendMessage(lua_State *lua);
+extern int tasOlsrGetMessage(lua_State *lua);
+extern int tasOlsrGetInfo(lua_State *lua);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/glua.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/glua.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,48 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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.
+ *
+ */
+
+extern int lspToLua(const char *rootDir, const char *lspFileName,
+                    const char *workDir, const char *luaFileName);
+extern int luaToLex(char **errMsg, const char *workDir, const char *luaFileName,
+                    const char *lexFileName);
+extern int runLua(char **errMsg, struct connInfo *info, const char *workDir,
+                  const char *lexFileName, char **argList, void **session);
+extern void freeLuaSession(void *session);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/http.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/http.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/http.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/http.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1968 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "link.h"
+#include "plugin.h"
+#include "lib.h"
+#include "os_unix.h"
+#include "http.h"
+#include "glua.h"
+#include "glua_ext.h"
+
+#include <string.h>
+#include <stdarg.h>
+
+// #define TAS_BLOCK
+
+#define DEF_CONFIG_ROOT_DIR "/etc/tas"
+#define DEF_CONFIG_WORK_DIR "/var/run/tas"
+#define DEF_CONFIG_PORT 1979
+#define DEF_CONFIG_ADDR "127.0.0.1"
+#define DEF_CONFIG_INDEX_FILE "index.html"
+#define DEF_CONFIG_USER NULL
+#define DEF_CONFIG_PASSWORD NULL
+#define DEF_CONFIG_SESS_TIME 600
+#define DEF_CONFIG_PUB_DIR "pub"
+#define DEF_CONFIG_QUANTUM 30
+#define DEF_CONFIG_MESS_TIME 60
+#define DEF_CONFIG_MESS_LIMIT 100
+
+static struct ipAddr confAddr;
+static int confPort;
+static const char *confRootDir;
+static const char *confWorkDir;
+static const char *confIndexFile;
+static char *confUser;
+static char *confPassword;
+static int confSessTime;
+static const char *confPubDir;
+static int confQuantum;
+static int confMessTime;
+static int confMessLimit;
+
+static struct
+{
+  unsigned int sessId;
+  unsigned char key[16];
+} cookieStruct;
+
+#define MAX_CONN 5
+
+static int numConn;
+static struct connInfo *conn[MAX_CONN];
+
+struct sessInfo
+{
+  unsigned int id;
+  void *data;
+  struct timeStamp time;
+};
+
+#define MAX_SESS 10
+
+static int numSess;
+static struct sessInfo *sess[MAX_SESS];
+
+static struct extMap
+{
+  const char *ext;
+  const char *type;
+  int state;
+}
+extMap[] =
+{
+  { ".png", "image/png", STATE_FILE },
+  { ".gif", "image/gif", STATE_FILE },
+  { ".jpg", "image/jpg", STATE_FILE },
+  { ".lsp", "text/html; charset=iso-8859-1", STATE_LSP },
+  { ".html", "text/html; charset=iso-8859-1", STATE_FILE },
+  { ".htm", "text/html; charset=iso-8859-1", STATE_FILE },
+  { NULL, NULL, 0 }
+};
+
+struct tasMessage
+{
+  struct tasMessage *next;
+
+  struct timeStamp time;
+
+  char *service;
+  char *string;
+  char *from;
+};
+
+static struct tasMessage *firstTasMsg, *lastTasMsg;
+static int numTasMsg;
+
+static void rc4(unsigned char *buff, int len, unsigned char *key, int keyLen)
+{
+  int i, m, n;
+  unsigned char state[256];
+  unsigned char aux;
+	
+  for (i = 0; i < 256; i++)
+    state[i] = (unsigned char)i;
+	
+  m = 0;
+  n = 0;
+	
+  for (i = 0; i < 256; i++)
+  {
+    m = (m + key[n] + state[i]) & 255;
+		
+    aux = state[i];
+    state[i] = state[m];
+    state[m] = aux;
+
+    n = (n + 1) % keyLen;
+  }
+	
+  m = 0;
+  n = 0;
+	
+  for (i = 0; i < len; i++)
+  {
+    n = (n + 1) & 255;
+    m = (m + state[n]) & 255;
+		
+    aux = state[n];
+    state[n] = state[m];
+    state[m] = aux;
+		
+    buff[i] ^= state[(state[m] + state[n]) & 255];
+  }
+}
+
+static int mapHexDigit(int digit)
+{
+  if (digit >= 'A' && digit <= 'F')
+    return digit + 10 - 'A';
+
+  if (digit >= 'a' && digit <= 'f')
+    return digit + 10 - 'a';
+
+  if (digit >= '0' && digit <= '9')
+    return digit - '0';
+
+  return -1;
+}
+
+static int addHexDigit(int *val, int digit)
+{
+  digit = mapHexDigit(digit);
+
+  if (digit < 0)
+    return -1;
+
+  *val = (*val << 4) | digit;
+
+  return 0;
+}
+
+static void encHexString(char *hexString, unsigned char *hex, int len)
+{
+  static const char map[] = "0123456789ABCDEF";
+
+  while (len-- > 0)
+  {
+    *hexString++ = map[*hex >> 4];
+    *hexString++ = map[*hex++ & 15];
+  }
+
+  *hexString = 0;
+}
+
+static int decHexString(unsigned char *hex, char *hexString, int len)
+{
+  int val;
+
+  while (len-- > 0)
+  {
+    val = 0;
+
+    if (addHexDigit(&val, *hexString++) < 0 ||
+        addHexDigit(&val, *hexString++) < 0)
+      return -1;
+
+    *hex++ = (unsigned char)val;
+  }
+
+  return 0;
+}
+
+static int decBase64(unsigned char *out, char *in)
+{
+  static int map[256] =
+  {
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  };
+  int state;
+  unsigned int val;
+  int digit;
+
+  val = 0;
+  state = 0;
+
+  while (*in != 0 && *in != '=')
+  {
+    digit = map[(unsigned char)*in++];
+
+    if (digit < 0)
+      return -1;
+
+    val = (val << 6) | digit;
+
+    if (state == 1)
+      *out++ = (unsigned char)(val >> 4);
+
+    else if (state == 2)
+      *out++ = (unsigned char)(val >> 2);
+
+    else if (state == 3)
+      *out++ = (unsigned char)val;
+
+    state = (state + 1) & 3;
+  }
+
+  return 0;
+}
+
+static void initInOutBuff(struct inOutBuff *buff)
+{
+  buff->off = 0;
+  buff->len = 0;
+  buff->cont = 0;
+
+  buff->first = NULL;
+  buff->last = NULL;
+}
+
+static struct connInfo *newConnInfo(struct fileId *sockId, struct ipAddr *addr)
+{
+  struct connInfo *info = allocMem(sizeof (struct connInfo));
+
+  info->sockId = sockId;
+  info->addr = addr;
+
+  info->state = STATE_REQUEST;
+
+  initInOutBuff(&info->read);
+  initInOutBuff(&info->write[0]);
+  initInOutBuff(&info->write[1]);
+  initInOutBuff(&info->write[2]);
+
+  info->which = 0;
+
+  info->flags = FLAG_READ | FLAG_WRITE;
+
+  info->buff = NULL;
+
+  info->buffUsed = 0;
+  info->buffTotal = 0;
+
+  info->firstHead = NULL;
+  info->lastHead = NULL;
+
+  info->verb = NULL;
+  info->host = NULL;
+  info->path = NULL;
+  info->para = NULL;
+  info->proto = NULL;
+
+  info->contType = "text/html; charset=iso-8859-1";
+  info->contLen = -1;
+
+  info->newSess = NULL;
+
+  info->authUser = NULL;
+  info->authPass = NULL;
+
+  return info;
+}
+
+static void freeInOutBuff(struct inOutBuff *buff)
+{
+  struct chunk *walker, *next;
+
+  for (walker = buff->first; walker != NULL; walker = next)
+  {
+    next = walker->next;
+    freeMem(walker);
+  }
+}
+
+static void freeWorkBuff(struct workBuff *buff)
+{
+  struct workBuff *next;
+
+  while (buff != NULL)
+  {
+    next = buff->next;
+    freeMem(buff);
+    buff = next;
+  }
+}
+
+static void freeConnInfo(struct connInfo *info)
+{
+  freeMem(info->sockId);
+  freeMem(info->addr);
+
+  freeInOutBuff(&info->read);
+  freeInOutBuff(&info->write[0]);
+  freeInOutBuff(&info->write[1]);
+  freeInOutBuff(&info->write[2]);
+
+  freeWorkBuff(info->buff);
+
+  freeMem(info);
+}
+
+static struct sessInfo *newSessInfo(void)
+{
+  static unsigned int sessId = 0;
+  struct sessInfo *info;
+
+  info = allocMem(sizeof (struct sessInfo));
+
+  info->id = sessId++;
+  info->data = NULL;
+
+  os_now(&info->time);
+
+  debug(DEBUG_SESSION, "new session, id = %u\n", info->id);
+
+  return info;
+}
+
+void *allocBuff(struct connInfo *info, int len)
+{
+  struct workBuff *buff;
+  unsigned char *res;
+
+  debug(DEBUG_CONNECTION, "%d bytes of buffer space requested\n", len);
+
+  if (info->buff != NULL)
+    debug(DEBUG_CONNECTION,
+          "existing buffer, size = %d bytes, used = %d bytes, remaining = %d bytes\n",
+          info->buffTotal, info->buffUsed, info->buffTotal - info->buffUsed);
+
+  else
+    debug(DEBUG_CONNECTION, "no existing buffer\n");
+
+  if (info->buff == NULL || len > info->buffTotal - info->buffUsed)
+  {
+    info->buffTotal = (len > BUFF_SIZE) ? len : BUFF_SIZE;
+    info->buffUsed = 0;
+
+    debug(DEBUG_CONNECTION, "new buffer of %d bytes\n", info->buffTotal);
+
+    buff = allocMem(sizeof (struct workBuff) + info->buffTotal);
+
+    buff->data = (unsigned char *)(buff + 1);
+
+    buff->next = info->buff;
+    info->buff = buff;
+  }
+
+  res = info->buff->data + info->buffUsed;
+
+  info->buffUsed += len;
+
+  debug(DEBUG_CONNECTION, "used = %d bytes, remaining = %d bytes\n",
+        info->buffUsed, info->buffTotal - info->buffUsed);
+
+  return res;
+}
+
+void httpInit(void)
+{
+  parseIpAddr(&confAddr, DEF_CONFIG_ADDR);
+  confPort = DEF_CONFIG_PORT;
+  confRootDir = DEF_CONFIG_ROOT_DIR;
+  confWorkDir = DEF_CONFIG_WORK_DIR;
+  confIndexFile = DEF_CONFIG_INDEX_FILE;
+  confUser = DEF_CONFIG_USER;
+  confPassword = DEF_CONFIG_PASSWORD;
+  confSessTime = DEF_CONFIG_SESS_TIME;
+  confPubDir = DEF_CONFIG_PUB_DIR;
+  confQuantum = DEF_CONFIG_QUANTUM;
+  confMessTime = DEF_CONFIG_MESS_TIME;
+  confMessLimit = DEF_CONFIG_MESS_LIMIT;
+
+  getRandomBytes(cookieStruct.key, 16);
+}
+
+int httpSetAddress(const char *addrStr, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (parseIpAddr(&confAddr, addrStr) < 0)
+  {
+    error("invalid IP address: %s\n", addrStr);
+    return -1;
+  }
+
+  return 0;
+}
+
+int httpSetPort(const char *portStr, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  unsigned int port;
+
+  if (stringToInt(&port, portStr) < 0)
+  {
+    error("invalid port number: %s\n", portStr);
+    return -1;
+  }
+
+  if (port > 65535)
+  {
+    error("invalid port number: %u\n", port);
+    return -1;
+  }
+
+  confPort = port;
+
+  return 0;
+}
+
+int httpSetRootDir(const char *rootDir, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (checkAbsPath(rootDir) < 0)
+  {
+    error("root directory (%s) requires an absolute path\n", rootDir);
+    return -1;
+  }
+
+  confRootDir = myStrdup(rootDir);
+  return 0;
+}
+
+int httpSetWorkDir(const char *workDir, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (checkAbsPath(workDir) < 0)
+  {
+    error("work directory (%s) requires an absolute path\n", workDir);
+    return -1;
+  }
+
+  confWorkDir = myStrdup(workDir);
+  return 0;
+}
+
+int httpSetIndexFile(const char *indexFile, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  confIndexFile = myStrdup(indexFile);
+  return 0;
+}
+
+int httpSetUser(const char *user, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  confUser = myStrdup(user);
+  return 0;
+}
+
+int httpSetPassword(const char *password, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  confPassword = myStrdup(password);
+  return 0;
+}
+
+int httpSetSessTime(const char *timeStr, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  unsigned int time;
+
+  if (stringToInt(&time, timeStr) < 0)
+  {
+    error("invalid timeout: %s\n", timeStr);
+    return -1;
+  }
+
+  if (time > 86400)
+  {
+    error("invalid timeout: %u\n", time);
+    return -1;
+  }
+
+  confSessTime = time;
+
+  return 0;
+}
+
+int httpSetPubDir(const char *pubDir, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  confPubDir = myStrdup(pubDir);
+  return 0;
+}
+
+int httpSetQuantum(const char *quantumStr, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  unsigned int quantum;
+
+  if (stringToInt(&quantum, quantumStr) < 0)
+  {
+    error("invalid quantum: %s\n", quantumStr);
+    return -1;
+  }
+
+  if (quantum > 100)
+  {
+    error("invalid quantum: %u\n", quantum);
+    return -1;
+  }
+
+  confQuantum = quantum;
+
+  return 0;
+}
+
+int httpSetMessTime(const char *timeStr, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  unsigned int time;
+
+  if (stringToInt(&time, timeStr) < 0)
+  {
+    error("invalid timeout: %s\n", timeStr);
+    return -1;
+  }
+
+  if (time > 365 * 86400)
+  {
+    error("invalid timeout: %u\n", time);
+    return -1;
+  }
+
+  confMessTime = time;
+
+  return 0;
+}
+
+int httpSetMessLimit(const char *limitStr, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  unsigned int limit;
+
+  if (stringToInt(&limit, limitStr) < 0)
+  {
+    error("invalid limit: %s\n", limitStr);
+    return -1;
+  }
+
+  if (limit > 1000000)
+  {
+    error("invalid limit: %u\n", limit);
+    return -1;
+  }
+
+  confMessLimit = limit;
+
+  return 0;
+}
+
+int httpSetup(void)
+{
+  int i;
+
+  if (createMainSocket(&confAddr, confPort) < 0)
+  {
+    error("cannot create main socket\n");
+    return -1;
+  }
+
+  numConn = 0;
+
+  for (i = 0; i < MAX_CONN; i++)
+    conn[i] = NULL;
+
+  numSess = 0;
+
+  for (i = 0; i < MAX_SESS; i++)
+    sess[i] = NULL;
+
+  firstTasMsg = NULL;
+  lastTasMsg = NULL;
+
+  numTasMsg = 0;
+
+  return 0;
+}
+
+static int readConn(struct connInfo *info)
+{
+  struct inOutBuff *read = &info->read;
+  int readLen;
+  struct chunk *chunk;
+
+  for (;;)
+  {
+    if (read->last == NULL || read->len == CHUNK_SIZE)
+    {
+      chunk = allocMem(sizeof (struct chunk));
+
+      chunk->next = NULL;
+
+      if (read->last != NULL)
+        read->last->next = chunk;
+
+      read->last = chunk;
+
+      if (read->first == NULL)
+        read->first = chunk;
+
+      read->len = 0;
+    }
+
+    readLen = readFileOs(info->sockId, &read->last->data[read->len],
+                         CHUNK_SIZE - read->len);
+
+    if (readLen < 0)
+    {
+      error("cannot read from network connection\n");
+      return -1;
+    }
+
+    debug(DEBUG_CONNECTION, "read %d bytes from connection\n", readLen);
+
+    if (readLen == 0)
+      return 0;
+
+    read->len += readLen;
+    read->cont += readLen;
+  }
+}
+
+void writeBuff(struct inOutBuff *write, const unsigned char *data, int dataLen)
+{
+  int writeLen;
+  struct chunk *chunk;
+
+  while (dataLen > 0)
+  {
+    if (write->last == NULL || write->len == CHUNK_SIZE)
+    {
+      chunk = allocMem(sizeof (struct chunk));
+
+      chunk->next = NULL;
+
+      if (write->last != NULL)
+        write->last->next = chunk;
+
+      write->last = chunk;
+
+      if (write->first == NULL)
+        write->first = chunk;
+
+      write->len = 0;
+    }
+
+    writeLen = CHUNK_SIZE - write->len;
+
+    if (dataLen < writeLen)
+      writeLen = dataLen;
+
+    memcpy(&write->last->data[write->len], data, writeLen);
+
+    write->len += writeLen;
+    write->cont += writeLen;
+
+    dataLen -= writeLen;
+    data += writeLen;
+  }
+}
+
+static int lineLength(const struct inOutBuff *read)
+{
+  struct chunk *chunk;
+  int idx, len, off;
+  int count;
+
+  count = 0;
+
+  for (chunk = read->first; chunk != NULL; chunk = chunk->next)
+  {
+    len = (chunk == read->last) ? read->len : CHUNK_SIZE;
+    off = (chunk == read->first) ? read->off : 0;
+
+    for (idx = off; idx < len; idx++)
+    {
+      count++;
+
+      if (chunk->data[idx] == 10)
+        return count;
+    }
+  }
+
+  return -1;
+}
+
+static int readBuff(struct inOutBuff *read, unsigned char *data, int dataLen)
+{
+  int readLen;
+  struct chunk *chunk;
+  int len;
+
+  while (dataLen > 0)
+  {
+    if (read->first == NULL)
+      return -1;
+
+    len = (read->first == read->last) ? read->len : CHUNK_SIZE;
+
+    readLen = len - read->off;
+
+    if (dataLen < readLen)
+      readLen = dataLen;
+
+    memcpy(data, &read->first->data[read->off], readLen);
+
+    read->off += readLen;
+    read->cont -= readLen;
+
+    dataLen -= readLen;
+    data += readLen;
+
+    if (read->off == len)
+    {
+      chunk = read->first;
+
+      read->first = chunk->next;
+
+      if (read->first == NULL)
+        read->last = NULL;
+
+      freeMem(chunk);
+
+      read->off = 0;
+    }
+  }
+
+  return 0;
+}
+
+static int writeConn(struct connInfo *info)
+{
+  struct inOutBuff *write = &info->write[info->which];
+  int writeLen;
+  struct chunk *chunk;
+  int len;
+
+  for (;;)
+  {
+    if (write->first == NULL)
+      return 0;
+
+    len = (write->first == write->last) ? write->len : CHUNK_SIZE;
+
+    writeLen = writeFileOs(info->sockId, &write->first->data[write->off],
+                           len - write->off);
+
+    if (writeLen < 0)
+    {
+      error("cannot write to network connection\n");
+      return -1;
+    }
+
+    debug(DEBUG_CONNECTION, "wrote %d bytes to connection\n", writeLen);
+
+    if (writeLen == 0)
+      return 0;
+
+    write->off += writeLen;
+    write->cont -= writeLen;
+
+    if (write->off == len)
+    {
+      chunk = write->first;
+
+      write->first = chunk->next;
+
+      if (write->first == NULL)
+        write->last = NULL;
+
+      freeMem(chunk);
+
+      write->off = 0;
+    }
+  }
+}
+
+static char *getToken(char **point)
+{
+  char *localPoint = *point;
+  char *start;
+
+  while (*localPoint == 9 || *localPoint == 32)
+    localPoint++;
+
+  start = localPoint;
+
+  while (*localPoint != 9 && *localPoint != 32 && *localPoint != 0)
+    localPoint++;
+
+  if (localPoint == start)
+    return NULL;
+
+  if (*localPoint != 0)
+    *localPoint++ = 0;
+
+  *point = localPoint;
+
+  return start;
+}
+
+static void writeBuffString(struct inOutBuff *write, const char *string)
+{
+  writeBuff(write, (const unsigned char *)string, strlen(string));
+}
+
+static int cookieToSession(unsigned int *sessId, char *cookie)
+{
+  unsigned char mac1[16];
+  unsigned char mac2[16];
+
+  debug(DEBUG_SESSION, "cookie = %s\n", cookie);
+
+  if (decHexString((unsigned char *)&cookieStruct.sessId, cookie, 4) < 0)
+  {
+    debug(DEBUG_SESSION, "cannot decode session id\n");
+    return -1;
+  }
+
+  if (decHexString(mac1, cookie + 8, 16) < 0)
+  {
+    debug(DEBUG_SESSION, "cannot decode authenticator\n");
+    return -1;
+  }
+
+  memset(mac2, 0, 16);
+  rc4(mac2, 16, (unsigned char *)&cookieStruct, sizeof (cookieStruct));
+
+  if (memcmp(mac1, mac2, 16) != 0)
+  {
+    debug(DEBUG_SESSION, "invalid authenticator\n");
+    return -1;
+  }
+
+  *sessId = cookieStruct.sessId;
+
+  debug(DEBUG_SESSION, "session id = %u\n", *sessId);
+
+  return 0;
+}
+
+static char *sessionToCookie(unsigned int sessId)
+{
+  unsigned char mac[16];
+  static char buff[41];
+
+  debug(DEBUG_SESSION, "session id = %u\n", sessId);
+
+  cookieStruct.sessId = sessId;
+
+  memset(mac, 0, 16);
+  rc4(mac, 16, (unsigned char *)&cookieStruct, sizeof (cookieStruct));
+
+  encHexString(buff, (unsigned char *)&cookieStruct.sessId, 4);
+  encHexString(buff + 8, mac, 16);
+
+  debug(DEBUG_SESSION, "cookie = %s\n", buff);
+
+  return buff;
+}
+
+static void writeBuffInt(struct inOutBuff *write, unsigned int val)
+{
+  char buff[10];
+
+  writeBuffString(write, intToString(buff, val));
+}
+
+static void printBuff(struct inOutBuff *buff, const char *form, ...)
+{
+  int i = 0;
+  int start = 0;
+  char *strVal;
+  int intVal;
+
+  va_list args;
+
+  va_start(args, form);
+
+  for (;;)
+  {
+    start = i;
+
+    while (form[i] != '%' && form[i] != 0)
+      i++;
+
+    if (i > start)
+      writeBuff(buff, (const unsigned char *)(form + start), i - start);
+
+    if (form[i] == 0)
+      break;
+
+    if (form[i + 1] == '%')
+      writeBuff(buff, (const unsigned char *)"%", 1);
+
+    else if (form[i + 1] == 's')
+    {
+      strVal = va_arg(args, char *);
+      writeBuffString(buff, strVal);
+    }
+
+    else if (form[i + 1] == 'd')
+    {
+      intVal = va_arg(args, int);
+      writeBuffInt(buff, intVal);
+    }
+
+    i += 2;
+  }
+
+  va_end(args);
+}
+
+static const char *errNoToErrStr(int errNo)
+{
+  switch (errNo)
+  {
+  case 200:
+    return "OK";
+
+  case 400:
+    return "Bad Request";
+
+  case 401:
+    return "Unauthorized";
+
+  case 404:
+    return "Not Found";
+
+  case 500:
+    return "Internal Server Error";
+
+  case 501:
+    return "Not Implemented";
+
+  case 505:
+    return "HTTP Version Not Supported";
+
+  default:
+    return "For No Reason";
+  }
+}
+
+static int writeHeaders(struct connInfo *info, int errNo)
+{
+  printBuff(&info->write[0], "HTTP/1.1 %d %s\r\n", errNo,
+            errNoToErrStr(errNo));
+
+  printBuff(&info->write[0], "Server: TAS/0.1\r\n");
+
+  if (info->contType != NULL)
+    printBuff(&info->write[0], "Content-Type: %s\r\n", info->contType);
+
+  if (info->contLen >= 0)
+    printBuff(&info->write[0], "Content-Length: %d\r\n", info->contLen);
+
+  if (info->newSess != NULL)
+    printBuff(&info->write[0], "Set-Cookie: %s\r\n", sessionToCookie(info->newSess->id));
+
+  if (errNo == 401)
+    printBuff(&info->write[0], "WWW-Authenticate: Basic realm=\"TAS\"\r\n");
+
+  printBuff(&info->write[0], "Accept-Ranges: none\r\n");
+  printBuff(&info->write[0], "Connection: close\r\n");
+
+  printBuff(&info->write[0], "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n");
+  printBuff(&info->write[0], "Cache-Control: no-cache\r\n");
+  printBuff(&info->write[0], "Pragma: No-cache\r\n");
+
+  printBuff(&info->write[1], "\r\n");
+
+  return 0;
+}
+
+static void writeErrorMsg(struct connInfo *info, int errNo, char *errMsg)
+{
+  if (info->verb == NULL || strcmp(info->verb, "HEAD") != 0)
+  {
+    printBuff(&info->write[2], "<html>\r\n");
+    printBuff(&info->write[2], "<head><title>Error %d: %s</title></head>\r\n",
+              errNo, errNoToErrStr(errNo));
+    printBuff(&info->write[2], "<body>Error %d: %s (%s)</body>\r\n", errNo,
+              errNoToErrStr(errNo),
+              (errMsg == NULL) ? "Unknown Reason" : errMsg);
+    printBuff(&info->write[2], "</html>\r\n");
+
+    info->contLen = info->write[2].cont;
+  }
+
+  writeHeaders(info, errNo);
+
+  info->state = STATE_DRAIN;
+}
+
+static void writeError(struct connInfo *info, int errNo)
+{
+  writeErrorMsg(info, errNo, NULL);
+}
+
+static void toLower(char *string)
+{
+  while (*string != 0)
+  {
+    if (*string >= 'A' && *string <= 'Z')
+      *string += 32;
+
+    string++;
+  }
+}
+
+static void unescape(char *string)
+{
+  int i, k, val;
+
+  debug(DEBUG_REQUEST | DEBUG_LUA, "unescaped string = %s\n", string);
+
+  k = 0;
+
+  for (i = 0; string[i] != 0; i++)
+  {
+    if (string[i] == '%' && string[i + 1] != 0 && string[i + 2] != 0)
+    {
+      val = 0;
+
+      if (addHexDigit(&val, string[i + 1]) >= 0 &&
+          addHexDigit(&val, string[i + 2]) >= 0)
+      {
+        string[k++] = (char)val;
+        i += 2;
+        continue;
+      }
+    }
+
+    string[k++] = string[i];
+  }
+
+  string[k] = 0;
+
+  debug(DEBUG_REQUEST | DEBUG_LUA, "escaped string = %s\n", string);
+}
+
+static int serviceConn(struct connInfo *info)
+{
+  int i, k, len, len2;
+  char *line, *tmp, *tmp2;
+  struct httpHeader *head;
+  unsigned char fileBuff[8192];
+  char **argList;
+  char *errMsg;
+  unsigned int sessId;
+  struct sessInfo *currSess;
+  int pub;
+
+  switch (info->state)
+  {
+  case STATE_REQUEST:
+    debug(DEBUG_CONNECTION, "connection state is STATE_REQUEST\n");
+
+    len = lineLength(&info->read);
+
+    if (len <= 0)
+      return 0;
+
+    line = allocBuff(info, len);
+
+    readBuff(&info->read, (unsigned char *)line, len);
+    chomp(line, len);
+
+    debug(DEBUG_REQUEST, "request line is '%s'\n", line);
+
+    info->verb = getToken(&line);
+    tmp = getToken(&line);
+    info->proto = getToken(&line);
+
+    debug(DEBUG_REQUEST, "verb = %s, uri = %s, protocol = %s\n",
+          (info->verb == NULL) ? "none" : info->verb,
+          (tmp == NULL) ? "none" : tmp,
+          (info->proto == NULL) ? "none" : info->proto);
+
+    if (info->verb == NULL || tmp == NULL || info->proto == NULL)
+    {
+      error("request without verb (%s), URI (%s), or protocol (%s)\n",
+            (info->verb == NULL) ? "none" : info->verb,
+            (tmp == NULL) ? "none" : tmp,
+            (info->proto == NULL) ? "none" : info->proto);
+      writeError(info, 400);
+      return 0;
+    }
+
+    if (strcmp(info->verb, "GET") != 0 && strcmp(info->verb, "HEAD") != 0)
+    {
+      error("unsupported verb: %s\n", info->verb);
+      writeError(info, 501);
+      return 0;
+    }
+
+    if (strcmp(info->proto, "HTTP/1.1") != 0)
+    {
+      error("unsupported protocol version: %s\n", info->proto);
+      writeError(info, 505);
+      return 0;
+    }
+
+    if (strncmp(tmp, "http://", 7) == 0)
+    {
+      tmp += 7;
+
+      info->host = tmp;
+
+      while (*tmp != ':' && *tmp != '/' && *tmp != 0)
+        tmp++;
+
+      if (*tmp == 0)
+      {
+        error("URI host part does not end in ':' or '/'\n");
+        writeError(info, 400);
+        return 0;
+      }
+
+      if (*tmp == ':')
+      {
+        *tmp++ = 0;
+
+        while (*tmp != '/' && *tmp != 0)
+          tmp++;
+
+        if (*tmp == 0)
+        {
+          error("URI port part does not end in '/'\n");
+          writeError(info, 400);
+          return 0;
+        }
+
+        tmp++;
+      }
+
+      else
+        *tmp++ = 0;
+
+      debug(DEBUG_REQUEST, "host = %s\n", info->host);
+
+      info->path = tmp;
+    }
+
+    else if (tmp[0] == '/')
+      info->path = ++tmp;
+
+    else
+    {
+      error("URI path part is not an absolute path\n");
+      writeError(info, 400);
+      return 0;
+    }
+
+    while (*tmp != '?' && *tmp != 0)
+    {
+      if (tmp[0] == '.' && tmp[1] == '.')
+      {
+        error("URI path part contains '..'\n");
+        writeError(info, 400);
+        return 0;
+      }
+
+      tmp++;
+    }
+
+    if (*tmp == '?')
+    {
+      *tmp++ = 0;
+      info->para = tmp;
+    }
+
+    debug(DEBUG_REQUEST, "path = %s, parameters = %s\n", info->path,
+          (info->para == NULL) ? "none" : info->para);
+
+    info->state = STATE_HEADERS;
+    return 0;
+
+  case STATE_HEADERS:
+    debug(DEBUG_CONNECTION, "connection state is STATE_HEADERS\n");
+
+    len = lineLength(&info->read);
+
+    if (len <= 0)
+      return 0;
+
+    line = allocBuff(info, len);
+
+    readBuff(&info->read, (unsigned char *)line, len);
+    chomp(line, len);
+
+    debug(DEBUG_REQUEST, "header line is '%s'\n", line);
+
+    if (*line == 0)
+    {
+      if (info->host == NULL)
+        for (head = info->firstHead; head != NULL; head = head->next)
+          if (strcmp(head->name, "host") == 0)
+            info->host = head->value;
+
+      debug(DEBUG_REQUEST, "last header line, host = %s\n",
+            (info->host == NULL) ? "none" : info->host);
+
+      info->state = STATE_RESPONSE;
+      return 0;
+    }
+
+    if (*line == 9 || *line == 32)
+    {
+      debug(DEBUG_REQUEST, "continued header line\n");
+      
+      if (info->lastHead == NULL)
+      {
+        error("no previous header to continue\n");
+        writeError(info, 400);
+        return 0;
+      }
+
+      len2 = strlen(info->lastHead->value);
+
+      tmp = allocBuff(info, len2 + len);
+
+      memcpy(tmp, info->lastHead->value, len2);
+      memcpy(tmp + len2, line, len);
+
+      info->lastHead->value = tmp;
+
+      debug(DEBUG_REQUEST, "updated header, name = %s, value = '%s'\n",
+            info->lastHead->name, info->lastHead->value);
+    }
+
+    else
+    {
+      tmp = getToken(&line);
+
+      if (tmp == NULL)
+      {
+        error("header without name\n");
+        writeError(info, 400);
+        return 0;
+      }
+
+      for (i = 0; tmp[i] != ':' && tmp[i] != 0; i++);
+
+      if (tmp[i] != ':' || tmp[i + 1] != 0)
+      {
+        error("header name does not end in ':'\n");
+        writeError(info, 400);
+        return 0;
+      }
+
+      tmp[i] = 0;
+
+      toLower(tmp);
+
+      head = allocBuff(info, sizeof (struct httpHeader));
+
+      head->next = NULL;
+      head->name = tmp;
+      head->value = line;
+
+      if (info->lastHead == NULL)
+        info->firstHead = head;
+
+      else
+        info->lastHead->next = head;
+
+      info->lastHead = head;
+
+      debug(DEBUG_REQUEST, "new header, name = %s, value = '%s'\n",
+            info->lastHead->name, info->lastHead->value);
+    }
+
+    return 0;
+
+  case STATE_RESPONSE:
+    debug(DEBUG_CONNECTION, "connection state is STATE_RESPONSE\n");
+
+    unescape(info->path);
+
+    len = strlen(confPubDir);
+
+    pub = (len > 0 && strncmp(info->path, confPubDir, len) == 0 &&
+           (info->path[len] == 0 || info->path[len] == '/'));
+
+    debug(DEBUG_REQUEST, "%s path\n", (pub == 0) ? "protected" : "public");
+
+    if (pub == 0 && (confUser != NULL || confPassword != NULL))
+    {
+      debug(DEBUG_REQUEST, "authentication required\n");
+
+      for (head = info->firstHead; head != NULL; head = head->next)
+        if (memcmp(head->name, "authorization", 14) == 0)
+          break;
+
+      if (head == NULL)
+      {
+        debug(DEBUG_REQUEST, "no authorization header present\n");
+
+        writeError(info, 401);
+        return 0;
+      }
+
+      tmp = getToken(&head->value);
+
+      if (tmp == NULL || strcmp(tmp, "Basic") != 0)
+      {
+        error("\"Basic\" authorization info expected\n");
+        writeError(info, 401);
+        return 0;
+      }
+
+      tmp = getToken(&head->value);
+
+      if (tmp == NULL)
+      {
+        error("authorization info lacks base-64 encoded data\n");
+        writeError(info, 401);
+        return 0;
+      }
+
+      tmp2 = allocBuff(info, strlen(tmp) * 3 / 4 + 1);
+
+      if (decBase64((unsigned char *)tmp2, tmp) < 0)
+      {
+        error("base-64 decode failed\n");
+        writeError(info, 401);
+        return 0;
+      }
+
+      for (i = 0; tmp2[i] != ':' && tmp2[i] != 0; i++);
+
+      if (tmp2[i] == 0)
+      {
+        error("authorization info lacks ':'\n");
+        writeError(info, 401);
+        return 0;
+      }
+
+      tmp2[i++] = 0;
+
+      debug(DEBUG_REQUEST, "user = %s, password = %s\n", tmp2, tmp2 + i);
+
+      if ((confUser != NULL && strcmp(confUser, tmp2) != 0) ||
+          (confPassword != NULL && strcmp(confPassword, tmp2 + i) != 0))
+      {
+        error("user authentication failed\n");
+        writeError(info, 401);
+        return 0;
+      }     
+    }
+
+    if (isDirectory(confRootDir, info->path) > 0)
+    {
+      debug(DEBUG_REQUEST, "path is a directory\n");
+
+      tmp = fullPath(info->path, confIndexFile);
+
+      debug(DEBUG_REQUEST, "updated path = %s\n", tmp);
+
+      info->path = allocBuff(info, strlen(tmp) + 1);
+      strcpy(info->path, tmp);
+
+      freeMem(tmp);
+    }
+
+    if (openFile(&info->fileId, confRootDir, info->path) < 0)
+    {
+      error("cannot find resource %s in root directory %s\n", info->path,
+            confRootDir);
+      writeError(info, 404);
+      return 0;
+    }
+
+    for (i = 0; extMap[i].ext != NULL; i++)
+    {
+      len = strlen(extMap[i].ext);
+      len2 = strlen(info->path);
+
+      if (len2 >= len &&
+          memcmp(info->path + len2 - len, extMap[i].ext, len) == 0)
+        break;      
+    }
+
+    if (extMap[i].ext != NULL)
+    {
+      info->state = extMap[i].state;
+      info->contType = extMap[i].type;
+
+      debug(DEBUG_REQUEST,
+            "extension recognized, next state = %d, content type = %s\n",
+            info->state, info->contType);
+    }
+
+    else
+      info->state = STATE_FILE;
+
+    if (strcmp(info->verb, "HEAD") == 0)
+    {
+      closeFile(&info->fileId);
+
+      writeHeaders(info, 200);
+
+      info->state = STATE_DRAIN;
+    }
+
+    return 0;
+
+  case STATE_FILE:
+    debug(DEBUG_CONNECTION, "connection state is STATE_FILE\n");
+
+    for (;;)
+    {
+      len = readFileOs(&info->fileId, fileBuff, sizeof (fileBuff));
+
+      debug(DEBUG_CONNECTION, "read %d bytes from file\n", len);
+
+      if (len <= 0)
+      {
+        if (len < 0)
+        {
+          closeFile(&info->fileId);
+
+          info->contLen = info->write[2].cont;
+          writeHeaders(info, 200);
+
+          info->state = STATE_DRAIN;
+        }
+
+        break;
+      }
+
+      writeBuff(&info->write[2], fileBuff, len);
+    }
+    
+    return 0;
+
+  case STATE_LSP:
+    debug(DEBUG_CONNECTION, "connection state is STATE_LSP\n");
+
+    tmp = allocBuff(info, strlen(info->path) + 4 + 1);
+    setExtension(tmp, info->path, ".lua");
+
+    debug(DEBUG_LUA, "lua file name = %s\n", tmp);
+
+    if (lspToLua(confRootDir, info->path, confWorkDir, tmp) < 0)
+    {
+      error("cannot transform %s into %s\n", info->path, tmp);
+      writeError(info, 500);
+      return 0;
+    }
+
+    tmp2 = allocBuff(info, strlen(info->path) + 4 + 1);
+    setExtension(tmp2, info->path, ".lex");
+
+    debug(DEBUG_LUA, "lex file name = %s\n", tmp2);
+
+    if (luaToLex(&errMsg, confWorkDir, tmp, tmp2) < 0)
+    {
+      error("cannot transform %s into %s\n", tmp, tmp2);
+      writeErrorMsg(info, 500, errMsg);
+
+      if (errMsg != NULL)
+        freeMem(errMsg);
+
+      return 0;
+    }
+
+    tmp = info->para;
+
+    if (tmp != NULL)
+    {
+      len = 3 * sizeof (char *);
+
+      for (i = 0; tmp[i] != 0; i++)
+      {
+        if (tmp[i] == '+')
+          tmp[i] = ' ';
+
+        if (tmp[i] == '=' || tmp[i] == '&')
+          len += sizeof (char *);
+      }
+
+      argList = allocBuff(info, len);
+
+      i = 0;
+      k = 0;
+
+      while (tmp[i] != 0)
+      {
+        argList[k++] = tmp + i;
+
+        while (tmp[i] != 0 && tmp[i] != '=')
+          i++;
+
+        if (tmp[i] == 0)
+        {
+          error("end of parameters while looking for '='\n");
+          writeError(info, 400);
+          return 0;
+        }
+
+        tmp[i++] = 0;
+
+        debug(DEBUG_LUA, "parameter name = '%s'\n", argList[k - 1]);
+
+        argList[k++] = tmp + i;
+
+        while (tmp[i] != 0 && tmp[i] != '&')
+          i++;
+
+        if (tmp[i] != 0)
+          tmp[i++] = 0;
+
+        debug(DEBUG_LUA, "parameter value = '%s'\n", argList[k - 1]);
+      }
+
+      for (i = 0; i < k; i++)
+        unescape(argList[i]);
+
+      argList[k++] = NULL;
+      argList[k++] = NULL;
+    }
+
+    else
+      argList = NULL;
+
+    currSess = NULL;
+
+    for (head = info->firstHead; head != NULL; head = head->next)
+      if (memcmp(head->name, "cookie", 7) == 0 &&
+          cookieToSession(&sessId, head->value) >= 0)
+        break;
+
+    if (head != NULL)
+    {
+      debug(DEBUG_SESSION, "looking for existing session\n");
+
+      for (i = 0; i < numSess && sess[i]->id != sessId; i++);
+
+      if (i < numSess)
+      {
+        debug(DEBUG_SESSION, "existing session found\n");
+
+        currSess = sess[i];
+
+        os_now(&currSess->time);
+      }
+    }
+
+    if (currSess == NULL)
+    {
+      debug(DEBUG_SESSION, "no existing session\n");
+
+      info->newSess = newSessInfo();
+      currSess = info->newSess;
+    }
+
+    if (runLua(&errMsg, info, confWorkDir, tmp2, argList, &currSess->data) < 0)
+    {
+      error("cannot run %s\n", tmp2);
+
+      if (info->newSess != NULL)
+      {
+        debug(DEBUG_SESSION, "cleaning up newly created session\n");
+
+        if (info->newSess->data != NULL)
+        {
+          debug(DEBUG_SESSION, "freeing lua context\n");
+        
+          freeLuaSession(info->newSess->data);
+        }
+
+        freeMem(info->newSess);
+        info->newSess = NULL;
+      }
+
+      debug(DEBUG_SESSION, "purging io buffer\n");
+        
+      freeInOutBuff(&info->write[1]);
+      freeInOutBuff(&info->write[2]);
+
+      initInOutBuff(&info->write[1]);
+      initInOutBuff(&info->write[2]);
+
+      writeErrorMsg(info, 500, errMsg);
+
+      if (errMsg != NULL)
+        freeMem(errMsg);
+
+      return 0;
+    }
+
+    debug(DEBUG_SESSION, "lua code successfully executed\n");
+
+    if (info->newSess != NULL)
+    {
+      if (info->newSess->data == NULL)
+      {
+        debug(DEBUG_SESSION, "no session required\n");
+
+        freeMem(info->newSess);
+        info->newSess = NULL;
+      }
+
+      else
+      {
+        if (numSess == MAX_SESS)
+        {
+          error("session limit reached, deleting least recently used session %d\n",
+                sess[0]->id);
+          freeLuaSession(sess[0]->data);
+          freeMem(sess[0]);
+
+          for (i = 0; i < MAX_SESS - 1; i++)
+            sess[i] = sess[i + 1];
+
+          numSess--;
+        }
+
+        sess[numSess++] = info->newSess;
+
+        debug(DEBUG_SESSION, "session added\n");
+      }
+    }
+
+    else
+    {
+      debug(DEBUG_SESSION, "aging sessions\n");
+
+      for (i = 0; sess[i]->id != currSess->id; i++);
+
+      while (i < numSess - 1)
+      {
+        sess[i] = sess[i + 1];
+        i++;
+      }
+
+      if (currSess->data == NULL)
+      {
+        debug(DEBUG_SESSION, "session not required any longer\n");
+
+        sess[i] = NULL;
+        freeMem(currSess);
+
+        numSess--;
+      }
+
+      else
+      {
+        debug(DEBUG_SESSION, "session stored\n");
+
+        sess[i] = currSess;
+      }
+    }
+
+    info->contLen = info->write[2].cont;
+    writeHeaders(info, 200);
+
+    info->state = STATE_DRAIN;
+    return 0;
+
+  case STATE_DRAIN:
+    debug(DEBUG_CONNECTION, "connection state is STATE_DRAIN\n");
+    debug(DEBUG_CONNECTION, "which = %d\n", info->which);
+
+    if (info->write[info->which].first == NULL)
+      info->which++;
+
+    if (info->which == 3)
+      return -1;
+
+    return 0;
+  }
+
+  return 0;
+}
+
+int httpService(int freq)
+{
+  struct fileId *sockId;
+  struct ipAddr *addr;
+  int i, k;
+#ifdef TAS_BLOCK
+  struct fileId *waitIds[MAX_CONN];
+  int *waitFlags[MAX_CONN];
+#endif
+  unsigned int micro, microLimit;
+  struct tasMessage *tasMsg;
+
+  micro = getMicro();
+
+#ifdef TAS_BLOCK
+  for (i = 0; i < numConn; i++)
+  {
+    waitIds[i] = conn[i]->sockId;
+    waitFlags[i] = &conn[i]->flags;
+
+    conn[i]->flags = FLAG_READ;
+
+    if (conn[i]->firstWrite != NULL)
+      conn[i]->flags |= FLAG_WRITE;
+  }
+
+  if (waitForSockets(waitIds, waitFlags, numConn) < 0)
+    return 0;
+#endif
+
+  while (numConn < MAX_CONN)
+  {
+    if (acceptConn(&sockId, &addr) < 0)
+      break;
+
+    conn[numConn++] = newConnInfo(sockId, addr);
+  }
+
+  i = 0;
+
+  while (i < numConn)
+  {
+    if (((conn[i]->flags & FLAG_READ) != 0 && readConn(conn[i]) < 0) ||
+        ((conn[i]->flags & FLAG_WRITE) != 0 && writeConn(conn[i]) < 0) ||
+        serviceConn(conn[i]) < 0)
+    {
+      closeFile(conn[i]->sockId);
+
+      freeConnInfo(conn[i]);
+
+      for (k = i; k < numConn - 1; k++)
+        conn[k] = conn[k + 1];
+
+      conn[k] = NULL;
+
+      numConn--;
+    }
+
+    else
+      i++;
+  }
+
+  while (numSess > 0 && confSessTime > 0 &&
+         timedOut(&sess[0]->time, confSessTime) >= 0)
+  {
+    error("session %d timed out\n", sess[0]->id);
+
+    freeLuaSession(sess[0]->data);
+
+    freeMem(sess[0]);
+
+    for (i = 0; i < numSess - 1; i++)
+      sess[i] = sess[i + 1];
+
+    numSess--;
+
+    debug(DEBUG_SESSION, "%d sessions left\n", numSess);
+  }
+
+  while (numTasMsg > 0 && confMessTime > 0 &&
+         timedOut(&firstTasMsg->time, confMessTime) >= 0)
+  {
+    tasMsg = firstTasMsg;
+
+    debug(DEBUG_MESSAGE,
+          "message timed out, service ='%s', string = '%s', from = %s\n",
+          tasMsg->service, tasMsg->string, tasMsg->from);
+    
+    firstTasMsg = firstTasMsg->next;
+
+    if (lastTasMsg == tasMsg)
+      lastTasMsg = NULL;
+
+    freeMem(tasMsg->service);
+    freeMem(tasMsg->string);
+    freeMem(tasMsg->from);
+    freeMem(tasMsg);
+
+    numTasMsg--;
+
+    debug(DEBUG_MESSAGE, "%d messages left\n", numTasMsg);
+  }
+
+  micro = getMicro() - micro;
+  microLimit = (10000 * confQuantum) / freq;
+
+  debug(DEBUG_QUANTUM, "service time = %u us, limit = %u us\n",
+        micro, microLimit);
+
+  if (microLimit > 0 && micro > microLimit)
+    error("service took longer than expected (%u us, limit is %u us)\n",
+          micro, microLimit);
+
+  return 0;
+}
+
+void httpShutdown(void)
+{
+  closeMainSocket();
+}
+
+void httpAddTasMessage(const char *service, const char *string,
+                       const char *from)
+{
+  struct tasMessage *msg;
+
+  debug(DEBUG_MESSAGE, "adding message, service = %s, string = %s, from = %s\n",
+        service, string, from);
+
+  msg = allocMem(sizeof (struct tasMessage));
+
+  msg->next = NULL;
+
+  os_now(&msg->time);
+
+  msg->service = myStrdup(service);
+  msg->string = myStrdup(string);
+  msg->from = myStrdup(from);
+  
+  if (lastTasMsg != NULL)
+    lastTasMsg->next = msg;
+
+  else
+    firstTasMsg = msg;
+
+  lastTasMsg = msg;
+
+  numTasMsg++;
+
+  debug(DEBUG_MESSAGE, "new number of messages: %d\n", numTasMsg);
+  debug(DEBUG_MESSAGE, "limiting message queue length\n");
+
+  while (confMessLimit > 0 && numTasMsg > confMessLimit)
+  {
+    msg = firstTasMsg;
+
+    debug(DEBUG_MESSAGE,
+          "message removed, service ='%s', string = '%s', from = %s\n",
+          msg->service, msg->string, msg->from);
+    
+    firstTasMsg = firstTasMsg->next;
+
+    if (lastTasMsg == msg)
+      lastTasMsg = NULL;
+
+    freeMem(msg->service);
+    freeMem(msg->string);
+    freeMem(msg->from);
+    freeMem(msg);
+
+    numTasMsg--;
+  }
+
+  debug(DEBUG_MESSAGE, "%d messages left\n", numTasMsg);
+}
+
+int httpGetTasMessage(const char *service, char **string, char **from)
+{
+  struct tasMessage *msg, *prevMsg;
+
+  debug(DEBUG_MESSAGE, "getting message, service = %s\n", service);
+
+  prevMsg = NULL;
+
+  debug(DEBUG_MESSAGE, "walking through message queue\n");
+
+  for (msg = firstTasMsg; msg != NULL; msg = msg->next)
+  {
+    debug(DEBUG_MESSAGE, "  service = %s, string = %s\n",
+          msg->service, msg->string);
+
+    if (strcmp(msg->service, service) == 0)
+      break;
+
+    prevMsg = msg;
+  }
+
+  debug(DEBUG_MESSAGE, "walk finished\n");
+
+  if (msg == NULL)
+  {
+    debug(DEBUG_MESSAGE, "no message found\n");
+
+    return -1;
+  }
+
+  if (msg == firstTasMsg)
+    firstTasMsg = msg->next;
+
+  else
+    prevMsg->next = msg->next;
+
+  if (msg == lastTasMsg)
+    lastTasMsg = prevMsg;
+
+  *string = msg->string;
+  *from = msg->from;
+
+  freeMem(msg->service);
+  freeMem(msg);
+
+  numTasMsg--;
+
+  debug(DEBUG_MESSAGE, "%d messages left\n", numTasMsg);
+  debug(DEBUG_MESSAGE, "returning '%s' received from %s\n", *string, *from);
+
+  return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/http.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/http.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/http.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/http.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,143 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "olsrd_plugin.h" /* union set_plugin_parameter_addon */
+
+#define CHUNK_SIZE 1024
+
+struct chunk
+{
+  struct chunk *next;
+  unsigned char data[CHUNK_SIZE];
+};
+
+struct inOutBuff
+{
+  int off, len;
+  int cont;
+  struct chunk *first, *last;
+};
+
+#define BUFF_SIZE 1024
+
+struct workBuff
+{
+  struct workBuff *next;
+  unsigned char *data;
+};
+
+struct httpHeader
+{
+  struct httpHeader *next;
+  char *name;
+  char *value;
+};
+
+#define STATE_REQUEST 0
+#define STATE_HEADERS 1
+#define STATE_RESPONSE 2
+#define STATE_FILE 3
+#define STATE_LSP 4
+#define STATE_DRAIN 5
+
+struct connInfo
+{
+  struct fileId *sockId;
+  struct ipAddr *addr;
+
+  int state;
+
+  struct inOutBuff read;
+  struct inOutBuff write[3];
+
+  int which;
+
+  int flags;
+
+  struct workBuff *buff;
+
+  int buffUsed;
+  int buffTotal;
+
+  struct httpHeader *firstHead, *lastHead;
+
+  char *verb;
+  char *host;
+  char *path;
+  char *para;
+  char *proto;
+
+  const char *contType;
+  int contLen;
+
+  struct sessInfo *newSess;
+
+  struct fileId fileId;
+
+  char *authUser;
+  char *authPass;
+};
+
+extern void httpInit(void);
+
+extern int httpSetAddress(const char *addrStr, void *data, set_plugin_parameter_addon addon);
+extern int httpSetPort(const char *portStr, void *data, set_plugin_parameter_addon addon);
+extern int httpSetRootDir(const char *rootDir, void *data, set_plugin_parameter_addon addon);
+extern int httpSetWorkDir(const char *workDir, void *data, set_plugin_parameter_addon addon);
+extern int httpSetIndexFile(const char *indexFile, void *data, set_plugin_parameter_addon addon);
+extern int httpSetUser(const char *user, void *data, set_plugin_parameter_addon addon);
+extern int httpSetPassword(const char *password, void *data, set_plugin_parameter_addon addon);
+extern int httpSetSessTime(const char *timeStr, void *data, set_plugin_parameter_addon addon);
+extern int httpSetPubDir(const char *pref, void *data, set_plugin_parameter_addon addon);
+extern int httpSetQuantum(const char *quantumStr, void *data, set_plugin_parameter_addon addon);
+extern int httpSetMessTime(const char *timeStr, void *data, set_plugin_parameter_addon addon);
+extern int httpSetMessLimit(const char *limitStr, void *data, set_plugin_parameter_addon addon);
+
+extern int httpSetup(void);
+extern int httpService(int freq);
+extern void httpShutdown(void);
+extern void httpAddTasMessage(const char *service, const char *string,
+                              const char *from);
+extern int httpGetTasMessage(const char *service, char **string, char **from);
+
+extern void writeBuff(struct inOutBuff *write, const unsigned char *data,
+                      int dataLen);
+extern void *allocBuff(struct connInfo *info, int len);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,136 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "link.h"
+#include "plugin.h"
+#include "lib.h"
+#include "os_unix.h"
+#include "http.h"
+#include "glua.h"
+#include "glua_ext.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+static unsigned int debugMask = 0;
+
+void error(const char *form, ...)
+{
+  va_list args;
+
+  va_start(args, form);
+  vfprintf(stderr, form, args);
+  va_end(args);
+}
+
+void debug(int facility, const char *form, ...)
+{
+  va_list args;
+
+  if ((debugMask & facility) == 0)
+    return;
+
+  va_start(args, form);
+  vfprintf(stderr, form, args);
+  va_end(args);
+}
+
+char *strdupAdd(const char *string, int add)
+{
+  char *res = allocMem(strlen(string) + 1 + add);
+
+  strcpy(res, string);
+  return res;
+}
+
+char *myStrdup(const char *string)
+{
+  return strdupAdd(string, 0);
+}
+
+void chomp(char *line, int len)
+{
+  while (len-- > 0)
+  {
+    if (line[len] != 10 && line[len] != 13)
+      break;
+
+    line[len] = 0;
+  }
+}
+
+char *intToString(char *buff, unsigned int val)
+{
+  int i;
+
+  buff[9] = 0;
+
+  for (i = 8; i >= 0; i--)
+  {
+    buff[i] = (char)(val % 10 + '0');
+
+    val /= 10;
+
+    if (val == 0)
+      break;
+  }
+
+  return buff + i;
+}
+
+int stringToInt(unsigned int *val, const char *buff)
+{
+  *val = 0;
+
+  while (*buff != 0)
+  {
+    if (*buff < '0' || *buff > '9')
+      return -1;
+
+    else
+      *val = *val * 10 + *buff - '0';
+
+    buff++;
+  }
+
+  return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lib.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lib.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lib.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lib.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,60 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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_TAS_LIB_H
+#define _OLSRD_TAS_LIB_H
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_SESSION 2
+#define DEBUG_CONNECTION 4
+#define DEBUG_REQUEST 8
+#define DEBUG_LUA 16
+#define DEBUG_QUANTUM 32
+
+extern void error(const char *form, ...) __attribute__((format(printf,1,2)));
+extern void debug(int facility, const char *form, ...) __attribute__((format(printf,2,3)));
+extern char *strdupAdd(const char *string, int add);
+extern char *myStrdup(const char *string);
+extern void chomp(char *line, int len);
+extern char *intToString(char *buff, unsigned int val);
+extern int stringToInt(unsigned int *val, const char *buff);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/link.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/link.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/link.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/link.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,43 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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.
+ *
+ */
+
+#define FLAG_READ 1
+#define FLAG_WRITE 2
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lapi.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lapi.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lapi.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lapi.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,920 @@
+/*
+** Lua API
+** See Copyright Notice in lua.h
+*/
+
+
+#include <assert.h>
+#include <string.h>
+
+#define lapi_c
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+
+
+const char lua_ident[] =
+  "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
+  "$Authors: " LUA_AUTHORS " $\n"
+  "$URL: www.lua.org $\n";
+
+
+
+#ifndef api_check
+#define api_check(L, o)		/*{ assert(o); }*/
+#endif
+
+#define api_checknelems(L, n)	api_check(L, (n) <= (L->top - L->base))
+
+#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
+
+
+
+
+static TObject *negindex (lua_State *L, int idx) {
+  if (idx > LUA_REGISTRYINDEX) {
+    api_check(L, idx != 0 && -idx <= L->top - L->base);
+    return L->top+idx;
+  }
+  else switch (idx) {  /* pseudo-indices */
+    case LUA_REGISTRYINDEX: return registry(L);
+    case LUA_GLOBALSINDEX: return gt(L);
+    default: {
+      TObject *func = (L->base - 1);
+      idx = LUA_GLOBALSINDEX - idx;
+      lua_assert(iscfunction(func));
+      return (idx <= clvalue(func)->c.nupvalues)
+                ? &clvalue(func)->c.upvalue[idx-1]
+                : NULL;
+    }
+  }
+}
+
+
+static TObject *luaA_index (lua_State *L, int idx) {
+  if (idx > 0) {
+    api_check(L, idx <= L->top - L->base);
+    return L->base + idx - 1;
+  }
+  else {
+    TObject *o = negindex(L, idx);
+    api_check(L, o != NULL);
+    return o;
+  }
+}
+
+
+static TObject *luaA_indexAcceptable (lua_State *L, int idx) {
+  if (idx > 0) {
+    TObject *o = L->base+(idx-1);
+    api_check(L, idx <= L->stack_last - L->base);
+    if (o >= L->top) return NULL;
+    else return o;
+  }
+  else
+    return negindex(L, idx);
+}
+
+
+void luaA_pushobject (lua_State *L, const TObject *o) {
+  setobj2s(L->top, o);
+  incr_top(L);
+}
+
+
+LUA_API int lua_checkstack (lua_State *L, int size) {
+  int res;
+  lua_lock(L);
+  if ((L->top - L->base + size) > LUA_MAXCSTACK)
+    res = 0;  /* stack overflow */
+  else {
+    luaD_checkstack(L, size);
+    if (L->ci->top < L->top + size)
+      L->ci->top = L->top + size;
+    res = 1;
+  }
+  lua_unlock(L);
+  return res;
+}
+
+
+LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
+  int i;
+  lua_lock(to);
+  api_checknelems(from, n);
+  from->top -= n;
+  for (i = 0; i < n; i++) {
+    setobj2s(to->top, from->top + i);
+    api_incr_top(to);
+  }
+  lua_unlock(to);
+}
+
+
+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
+  lua_CFunction old;
+  lua_lock(L);
+  old = G(L)->panic;
+  G(L)->panic = panicf;
+  lua_unlock(L);
+  return old;
+}
+
+
+LUA_API lua_State *lua_newthread (lua_State *L) {
+  lua_State *L1;
+  lua_lock(L);
+  luaC_checkGC(L);
+  L1 = luaE_newthread(L);
+  setthvalue(L->top, L1);
+  api_incr_top(L);
+  lua_unlock(L);
+  lua_userstateopen(L1);
+  return L1;
+}
+
+
+
+/*
+** basic stack manipulation
+*/
+
+
+LUA_API int lua_gettop (lua_State *L) {
+  return (L->top - L->base);
+}
+
+
+LUA_API void lua_settop (lua_State *L, int idx) {
+  lua_lock(L);
+  if (idx >= 0) {
+    api_check(L, idx <= L->stack_last - L->base);
+    while (L->top < L->base + idx)
+      setnilvalue(L->top++);
+    L->top = L->base + idx;
+  }
+  else {
+    api_check(L, -(idx+1) <= (L->top - L->base));
+    L->top += idx+1;  /* `subtract' index (index is negative) */
+  }
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_remove (lua_State *L, int idx) {
+  StkId p;
+  lua_lock(L);
+  p = luaA_index(L, idx);
+  while (++p < L->top) setobjs2s(p-1, p);
+  L->top--;
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_insert (lua_State *L, int idx) {
+  StkId p;
+  StkId q;
+  lua_lock(L);
+  p = luaA_index(L, idx);
+  for (q = L->top; q>p; q--) setobjs2s(q, q-1);
+  setobjs2s(p, L->top);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_replace (lua_State *L, int idx) {
+  lua_lock(L);
+  api_checknelems(L, 1);
+  setobj(luaA_index(L, idx), L->top - 1);  /* write barrier */
+  L->top--;
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_pushvalue (lua_State *L, int idx) {
+  lua_lock(L);
+  setobj2s(L->top, luaA_index(L, idx));
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+
+/*
+** access functions (stack -> C)
+*/
+
+
+LUA_API int lua_type (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  return (o == NULL) ? LUA_TNONE : ttype(o);
+}
+
+
+LUA_API const char *lua_typename (lua_State *L, int t) {
+  UNUSED(L);
+  return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+}
+
+
+LUA_API int lua_iscfunction (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  return (o == NULL) ? 0 : iscfunction(o);
+}
+
+
+LUA_API int lua_isnumber (lua_State *L, int idx) {
+  TObject n;
+  const TObject *o = luaA_indexAcceptable(L, idx);
+  return (o != NULL && tonumber(o, &n));
+}
+
+
+LUA_API int lua_isstring (lua_State *L, int idx) {
+  int t = lua_type(L, idx);
+  return (t == LUA_TSTRING || t == LUA_TNUMBER);
+}
+
+
+LUA_API int lua_isuserdata (lua_State *L, int idx) {
+  const TObject *o = luaA_indexAcceptable(L, idx);
+  return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
+}
+
+
+LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
+  StkId o1 = luaA_indexAcceptable(L, index1);
+  StkId o2 = luaA_indexAcceptable(L, index2);
+  return (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
+                                    : luaO_rawequalObj(o1, o2);
+}
+
+
+LUA_API int lua_equal (lua_State *L, int index1, int index2) {
+  StkId o1, o2;
+  int i;
+  lua_lock(L);  /* may call tag method */
+  o1 = luaA_indexAcceptable(L, index1);
+  o2 = luaA_indexAcceptable(L, index2);
+  i = (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
+                                 : equalobj(L, o1, o2);
+  lua_unlock(L);
+  return i;
+}
+
+
+LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
+  StkId o1, o2;
+  int i;
+  lua_lock(L);  /* may call tag method */
+  o1 = luaA_indexAcceptable(L, index1);
+  o2 = luaA_indexAcceptable(L, index2);
+  i = (o1 == NULL || o2 == NULL) ? 0  /* index out-of-range */
+                                 : luaV_lessthan(L, o1, o2);
+  lua_unlock(L);
+  return i;
+}
+
+
+
+LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+  TObject n;
+  const TObject *o = luaA_indexAcceptable(L, idx);
+  if (o != NULL && tonumber(o, &n))
+    return nvalue(o);
+  else
+    return 0;
+}
+
+
+LUA_API int lua_toboolean (lua_State *L, int idx) {
+  const TObject *o = luaA_indexAcceptable(L, idx);
+  return (o != NULL) && !l_isfalse(o);
+}
+
+
+LUA_API const char *lua_tostring (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  if (o == NULL)
+    return NULL;
+  else if (ttisstring(o))
+    return svalue(o);
+  else {
+    const char *s;
+    lua_lock(L);  /* `luaV_tostring' may create a new string */
+    s = (luaV_tostring(L, o) ? svalue(o) : NULL);
+    luaC_checkGC(L);
+    lua_unlock(L);
+    return s;
+  }
+}
+
+
+LUA_API size_t lua_strlen (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  if (o == NULL)
+    return 0;
+  else if (ttisstring(o))
+    return tsvalue(o)->tsv.len;
+  else {
+    size_t l;
+    lua_lock(L);  /* `luaV_tostring' may create a new string */
+    l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0);
+    lua_unlock(L);
+    return l;
+  }
+}
+
+
+LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
+}
+
+
+LUA_API void *lua_touserdata (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  if (o == NULL) return NULL;
+  switch (ttype(o)) {
+    case LUA_TUSERDATA: return (uvalue(o) + 1);
+    case LUA_TLIGHTUSERDATA: return pvalue(o);
+    default: return NULL;
+  }
+}
+
+
+LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
+}
+
+
+LUA_API const void *lua_topointer (lua_State *L, int idx) {
+  StkId o = luaA_indexAcceptable(L, idx);
+  if (o == NULL) return NULL;
+  else {
+    switch (ttype(o)) {
+      case LUA_TTABLE: return hvalue(o);
+      case LUA_TFUNCTION: return clvalue(o);
+      case LUA_TTHREAD: return thvalue(o);
+      case LUA_TUSERDATA:
+      case LUA_TLIGHTUSERDATA:
+        return lua_touserdata(L, idx);
+      default: return NULL;
+    }
+  }
+}
+
+
+
+/*
+** push functions (C -> stack)
+*/
+
+
+LUA_API void lua_pushnil (lua_State *L) {
+  lua_lock(L);
+  setnilvalue(L->top);
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+  lua_lock(L);
+  setnvalue(L->top, n);
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+  lua_lock(L);
+  luaC_checkGC(L);
+  setsvalue2s(L->top, luaS_newlstr(L, s, len));
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_pushstring (lua_State *L, const char *s) {
+  if (s == NULL)
+    lua_pushnil(L);
+  else
+    lua_pushlstring(L, s, strlen(s));
+}
+
+
+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
+                                      va_list argp) {
+  const char *ret;
+  lua_lock(L);
+  luaC_checkGC(L);
+  ret = luaO_pushvfstring(L, fmt, argp);
+  lua_unlock(L);
+  return ret;
+}
+
+
+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
+  const char *ret;
+  va_list argp;
+  lua_lock(L);
+  luaC_checkGC(L);
+  va_start(argp, fmt);
+  ret = luaO_pushvfstring(L, fmt, argp);
+  va_end(argp);
+  lua_unlock(L);
+  return ret;
+}
+
+
+LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
+  Closure *cl;
+  lua_lock(L);
+  luaC_checkGC(L);
+  api_checknelems(L, n);
+  cl = luaF_newCclosure(L, n);
+  cl->c.f = fn;
+  L->top -= n;
+  while (n--)
+    setobj2n(&cl->c.upvalue[n], L->top+n);
+  setclvalue(L->top, cl);
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_pushboolean (lua_State *L, int b) {
+  lua_lock(L);
+  setbvalue(L->top, (b != 0));  /* ensure that true is 1 */
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlightuserdata (lua_State *L, const void *p) {
+  lua_lock(L);
+  setpvalue(L->top, (void *)p);
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+
+/*
+** get functions (Lua -> stack)
+*/
+
+
+LUA_API void lua_gettable (lua_State *L, int idx) {
+  StkId t;
+  lua_lock(L);
+  t = luaA_index(L, idx);
+  setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_rawget (lua_State *L, int idx) {
+  StkId t;
+  lua_lock(L);
+  t = luaA_index(L, idx);
+  api_check(L, ttistable(t));
+  setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
+  StkId o;
+  lua_lock(L);
+  o = luaA_index(L, idx);
+  api_check(L, ttistable(o));
+  setobj2s(L->top, luaH_getnum(hvalue(o), n));
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_newtable (lua_State *L) {
+  lua_lock(L);
+  luaC_checkGC(L);
+  sethvalue(L->top, luaH_new(L, 0, 0));
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+LUA_API int lua_getmetatable (lua_State *L, int objindex) {
+  const TObject *obj;
+  Table *mt = NULL;
+  int res;
+  lua_lock(L);
+  obj = luaA_indexAcceptable(L, objindex);
+  if (obj != NULL) {
+    switch (ttype(obj)) {
+      case LUA_TTABLE:
+        mt = hvalue(obj)->metatable;
+        break;
+      case LUA_TUSERDATA:
+        mt = uvalue(obj)->uv.metatable;
+        break;
+    }
+  }
+  if (mt == NULL || mt == hvalue(defaultmeta(L)))
+    res = 0;
+  else {
+    sethvalue(L->top, mt);
+    api_incr_top(L);
+    res = 1;
+  }
+  lua_unlock(L);
+  return res;
+}
+
+
+LUA_API void lua_getfenv (lua_State *L, int idx) {
+  StkId o;
+  lua_lock(L);
+  o = luaA_index(L, idx);
+  setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
+
+/*
+** set functions (stack -> Lua)
+*/
+
+
+LUA_API void lua_settable (lua_State *L, int idx) {
+  StkId t;
+  lua_lock(L);
+  api_checknelems(L, 2);
+  t = luaA_index(L, idx);
+  luaV_settable(L, t, L->top - 2, L->top - 1);
+  L->top -= 2;  /* pop index and value */
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_rawset (lua_State *L, int idx) {
+  StkId t;
+  lua_lock(L);
+  api_checknelems(L, 2);
+  t = luaA_index(L, idx);
+  api_check(L, ttistable(t));
+  setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1);  /* write barrier */
+  L->top -= 2;
+  lua_unlock(L);
+}
+
+
+LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
+  StkId o;
+  lua_lock(L);
+  api_checknelems(L, 1);
+  o = luaA_index(L, idx);
+  api_check(L, ttistable(o));
+  setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1);  /* write barrier */
+  L->top--;
+  lua_unlock(L);
+}
+
+
+LUA_API int lua_setmetatable (lua_State *L, int objindex) {
+  TObject *obj, *mt;
+  int res = 1;
+  lua_lock(L);
+  api_checknelems(L, 1);
+  obj = luaA_index(L, objindex);
+  mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L);
+  api_check(L, ttistable(mt));
+  switch (ttype(obj)) {
+    case LUA_TTABLE: {
+      hvalue(obj)->metatable = hvalue(mt);  /* write barrier */
+      break;
+    }
+    case LUA_TUSERDATA: {
+      uvalue(obj)->uv.metatable = hvalue(mt);  /* write barrier */
+      break;
+    }
+    default: {
+      res = 0;  /* cannot set */
+      break;
+    }
+  }
+  L->top--;
+  lua_unlock(L);
+  return res;
+}
+
+
+LUA_API int lua_setfenv (lua_State *L, int idx) {
+  StkId o;
+  int res = 0;
+  lua_lock(L);
+  api_checknelems(L, 1);
+  o = luaA_index(L, idx);
+  L->top--;
+  api_check(L, ttistable(L->top));
+  if (isLfunction(o)) {
+    res = 1;
+    clvalue(o)->l.g = *(L->top);
+  }
+  lua_unlock(L);
+  return res;
+}
+
+
+/*
+** `load' and `call' functions (run Lua code)
+*/
+
+LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
+  StkId func;
+  lua_lock(L);
+  api_checknelems(L, nargs+1);
+  func = L->top - (nargs+1);
+  luaD_call(L, func, nresults);
+  lua_unlock(L);
+}
+
+
+
+/*
+** Execute a protected call.
+*/
+struct CallS {  /* data to `f_call' */
+  StkId func;
+  int nresults;
+};
+
+
+static void f_call (lua_State *L, void *ud) {
+  struct CallS *c = cast(struct CallS *, ud);
+  luaD_call(L, c->func, c->nresults);
+}
+
+
+
+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
+  struct CallS c;
+  int status;
+  ptrdiff_t func;
+  lua_lock(L);
+  func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
+  c.func = L->top - (nargs+1);  /* function to be called */
+  c.nresults = nresults;
+  status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
+  lua_unlock(L);
+  return status;
+}
+
+
+/*
+** Execute a protected C call.
+*/
+struct CCallS {  /* data to `f_Ccall' */
+  lua_CFunction func;
+  void *ud;
+};
+
+
+static void f_Ccall (lua_State *L, void *ud) {
+  struct CCallS *c = cast(struct CCallS *, ud);
+  Closure *cl;
+  cl = luaF_newCclosure(L, 0);
+  cl->c.f = c->func;
+  setclvalue(L->top, cl);  /* push function */
+  incr_top(L);
+  setpvalue(L->top, c->ud);  /* push only argument */
+  incr_top(L);
+  luaD_call(L, L->top - 2, 0);
+}
+
+
+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
+  struct CCallS c;
+  int status;
+  lua_lock(L);
+  c.func = func;
+  c.ud = ud;
+  status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
+  lua_unlock(L);
+  return status;
+}
+
+
+LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
+                      const char *chunkname) {
+  ZIO z;
+  int status;
+  int c;
+  lua_lock(L);
+  if (!chunkname) chunkname = "?";
+  luaZ_init(&z, reader, data, chunkname);
+  c = luaZ_lookahead(&z);
+  status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]));
+  lua_unlock(L);
+  return status;
+}
+
+
+LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
+  int status;
+  TObject *o;
+  lua_lock(L);
+  api_checknelems(L, 1);
+  o = L->top - 1;
+  if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
+    luaU_dump(L, clvalue(o)->l.p, writer, data);
+    status = 1;
+  }
+  else
+    status = 0;
+  lua_unlock(L);
+  return status;
+}
+
+
+/*
+** Garbage-collection functions
+*/
+
+/* GC values are expressed in Kbytes: #bytes/2^10 */
+#define GCscalel(x)		((x)>>10)
+#define GCscale(x)		(cast(int, GCscalel(x)))
+#define GCunscale(x)		(cast(lu_mem, x)<<10)
+
+LUA_API int lua_getgcthreshold (lua_State *L) {
+  int threshold;
+  lua_lock(L);
+  threshold = GCscale(G(L)->GCthreshold);
+  lua_unlock(L);
+  return threshold;
+}
+
+LUA_API int lua_getgccount (lua_State *L) {
+  int count;
+  lua_lock(L);
+  count = GCscale(G(L)->nblocks);
+  lua_unlock(L);
+  return count;
+}
+
+LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
+  lua_lock(L);
+  if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
+    G(L)->GCthreshold = MAX_LUMEM;
+  else
+    G(L)->GCthreshold = GCunscale(newthreshold);
+  luaC_checkGC(L);
+  lua_unlock(L);
+}
+
+
+/*
+** miscellaneous functions
+*/
+
+
+LUA_API const char *lua_version (void) {
+  return LUA_VERSION;
+}
+
+
+LUA_API int lua_error (lua_State *L) {
+  lua_lock(L);
+  api_checknelems(L, 1);
+  luaG_errormsg(L);
+  lua_unlock(L);
+}
+
+
+LUA_API int lua_next (lua_State *L, int idx) {
+  StkId t;
+  int more;
+  lua_lock(L);
+  t = luaA_index(L, idx);
+  api_check(L, ttistable(t));
+  more = luaH_next(L, hvalue(t), L->top - 1);
+  if (more) {
+    api_incr_top(L);
+  }
+  else  /* no more elements */
+    L->top -= 1;  /* remove key */
+  lua_unlock(L);
+  return more;
+}
+
+
+LUA_API void lua_concat (lua_State *L, int n) {
+  lua_lock(L);
+  luaC_checkGC(L);
+  api_checknelems(L, n);
+  if (n >= 2) {
+    luaV_concat(L, n, L->top - L->base - 1);
+    L->top -= (n-1);
+  }
+  else if (n == 0) {  /* push empty string */
+    setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
+    api_incr_top(L);
+  }
+  /* else n == 1; nothing to do */
+  lua_unlock(L);
+}
+
+
+LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
+  Udata *u;
+  lua_lock(L);
+  luaC_checkGC(L);
+  u = luaS_newudata(L, size);
+  setuvalue(L->top, u);
+  api_incr_top(L);
+  lua_unlock(L);
+  return u + 1;
+}
+
+
+LUA_API int lua_pushupvalues (lua_State *L) {
+  Closure *func;
+  int n, i;
+  lua_lock(L);
+  api_check(L, iscfunction(L->base - 1));
+  func = clvalue(L->base - 1);
+  n = func->c.nupvalues;
+  luaD_checkstack(L, n + LUA_MINSTACK);
+  for (i=0; i<n; i++) {
+    setobj2s(L->top, &func->c.upvalue[i]);
+    L->top++;
+  }
+  lua_unlock(L);
+  return n;
+}
+
+
+static const char *aux_upvalue (lua_State *L, int funcindex, int n,
+                                TObject **val) {
+  Closure *f;
+  StkId fi = luaA_index(L, funcindex);
+  if (!ttisfunction(fi)) return NULL;
+  f = clvalue(fi);
+  if (f->c.isC) {
+    if (n > f->c.nupvalues) return NULL;
+    *val = &f->c.upvalue[n-1];
+    return "";
+  }
+  else {
+    Proto *p = f->l.p;
+    if (n > p->sizeupvalues) return NULL;
+    *val = f->l.upvals[n-1]->v;
+    return getstr(p->upvalues[n-1]);
+  }
+}
+
+
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
+  const char *name;
+  TObject *val;
+  lua_lock(L);
+  name = aux_upvalue(L, funcindex, n, &val);
+  if (name) {
+    setobj2s(L->top, val);
+    api_incr_top(L);
+  }
+  lua_unlock(L);
+  return name;
+}
+
+
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
+  const char *name;
+  TObject *val;
+  lua_lock(L);
+  api_checknelems(L, 1);
+  name = aux_upvalue(L, funcindex, n, &val);
+  if (name) {
+    L->top--;
+    setobj(val, L->top);  /* write barrier */
+  }
+  lua_unlock(L);
+  return name;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lapi.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lapi.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lapi.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lapi.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,15 @@
+/*
+** Auxiliary functions from Lua API
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lapi_h
+#define lapi_h
+
+
+#include "lobject.h"
+
+
+void luaA_pushobject (lua_State *L, const TObject *o);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,591 @@
+/*
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* This file uses only the official API of Lua.
+** Any function declared here could be written as an application function.
+*/
+
+#define lauxlib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+
+
+/* number of prereserved references (for internal use) */
+#define RESERVED_REFS	2
+
+/* reserved references */
+#define FREELIST_REF	1	/* free list of references */
+#define ARRAYSIZE_REF	2	/* array sizes */
+
+
+/* convert a stack index to positive */
+#define abs_index(L, i)		((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
+					lua_gettop(L) + (i) + 1)
+
+
+/*
+** {======================================================
+** Error-report functions
+** =======================================================
+*/
+
+
+LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
+  lua_Debug ar;
+  lua_getstack(L, 0, &ar);
+  lua_getinfo(L, "n", &ar);
+  if (strcmp(ar.namewhat, "method") == 0) {
+    narg--;  /* do not count `self' */
+    if (narg == 0)  /* error is in the self argument itself? */
+      luaL_error(L, "calling `%s' on bad self (%s)", ar.name, extramsg);
+  }
+  if (ar.name == NULL)
+    ar.name = "?";
+  luaL_error(L, "bad argument #%d to `%s' (%s)",
+                        narg, ar.name, extramsg);
+}
+
+
+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
+  const char *msg = lua_pushfstring(L, "%s expected, got %s",
+                                    tname, lua_typename(L, lua_type(L,narg)));
+  luaL_argerror(L, narg, msg);
+}
+
+
+static void tag_error (lua_State *L, int narg, int tag) __attribute__((noreturn));
+static void tag_error (lua_State *L, int narg, int tag) {
+  luaL_typerror(L, narg, lua_typename(L, tag)); 
+}
+
+
+LUALIB_API void luaL_where (lua_State *L, int level) {
+  lua_Debug ar;
+  if (lua_getstack(L, level, &ar)) {  /* check function at level */
+    lua_getinfo(L, "Snl", &ar);  /* get info about it */
+    if (ar.currentline > 0) {  /* is there info? */
+      lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
+      return;
+    }
+  }
+  lua_pushliteral(L, "");  /* else, no information available... */
+}
+
+
+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  luaL_where(L, 1);
+  lua_pushvfstring(L, fmt, argp);
+  va_end(argp);
+  lua_concat(L, 2);
+  lua_error(L);
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
+  int i;
+  for (i=0; list[i]; i++)
+    if (strcmp(list[i], name) == 0)
+      return i;
+  return -1;  /* name not found */
+}
+
+
+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
+  lua_pushstring(L, tname);
+  lua_rawget(L, LUA_REGISTRYINDEX);  /* get registry.name */
+  if (!lua_isnil(L, -1))  /* name already in use? */
+    return 0;  /* leave previous value on top, but return 0 */
+  lua_pop(L, 1);
+  lua_newtable(L);  /* create metatable */
+  lua_pushstring(L, tname);
+  lua_pushvalue(L, -2);
+  lua_rawset(L, LUA_REGISTRYINDEX);  /* registry.name = metatable */
+  lua_pushvalue(L, -1);
+  lua_pushstring(L, tname);
+  lua_rawset(L, LUA_REGISTRYINDEX);  /* registry[metatable] = name */
+  return 1;
+}
+
+
+LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname) {
+  lua_pushstring(L, tname);
+  lua_rawget(L, LUA_REGISTRYINDEX);
+}
+
+
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
+  const char *tn;
+  if (!lua_getmetatable(L, ud)) return NULL;  /* no metatable? */
+  lua_rawget(L, LUA_REGISTRYINDEX);  /* get registry[metatable] */
+  tn = lua_tostring(L, -1);
+  if (tn && (strcmp(tn, tname) == 0)) {
+    lua_pop(L, 1);
+    return lua_touserdata(L, ud);
+  }
+  else {
+    lua_pop(L, 1);
+    return NULL;
+  }
+}
+
+
+LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
+  if (!lua_checkstack(L, space))
+    luaL_error(L, "stack overflow (%s)", mes);
+}
+
+
+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
+  if (lua_type(L, narg) != t)
+    tag_error(L, narg, t);
+}
+
+
+LUALIB_API void luaL_checkany (lua_State *L, int narg) {
+  if (lua_type(L, narg) == LUA_TNONE)
+    luaL_argerror(L, narg, "value expected");
+}
+
+
+LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
+  const char *s = lua_tostring(L, narg);
+  if (!s) tag_error(L, narg, LUA_TSTRING);
+  if (len) *len = lua_strlen(L, narg);
+  return s;
+}
+
+
+LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
+                                        const char *def, size_t *len) {
+  if (lua_isnoneornil(L, narg)) {
+    if (len)
+      *len = (def ? strlen(def) : 0);
+    return def;
+  }
+  else return luaL_checklstring(L, narg, len);
+}
+
+
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
+  lua_Number d = lua_tonumber(L, narg);
+  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
+    tag_error(L, narg, LUA_TNUMBER);
+  return d;
+}
+
+
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
+  if (lua_isnoneornil(L, narg)) return def;
+  else return luaL_checknumber(L, narg);
+}
+
+
+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+  if (!lua_getmetatable(L, obj))  /* no metatable? */
+    return 0;
+  lua_pushstring(L, event);
+  lua_rawget(L, -2);
+  if (lua_isnil(L, -1)) {
+    lua_pop(L, 2);  /* remove metatable and metafield */
+    return 0;
+  }
+  else {
+    lua_remove(L, -2);  /* remove only metatable */
+    return 1;
+  }
+}
+
+
+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
+  obj = abs_index(L, obj);
+  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
+    return 0;
+  lua_pushvalue(L, obj);
+  lua_call(L, 1, 1);
+  return 1;
+}
+
+
+LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
+                              const luaL_reg *l, int nup) {
+  if (libname) {
+    lua_pushstring(L, libname);
+    lua_gettable(L, LUA_GLOBALSINDEX);  /* check whether lib already exists */
+    if (lua_isnil(L, -1)) {  /* no? */
+      lua_pop(L, 1);
+      lua_newtable(L);  /* create it */
+      lua_pushstring(L, libname);
+      lua_pushvalue(L, -2);
+      lua_settable(L, LUA_GLOBALSINDEX);  /* register it with given name */
+    }
+    lua_insert(L, -(nup+1));  /* move library table to below upvalues */
+  }
+  for (; l->name; l++) {
+    int i;
+    lua_pushstring(L, l->name);
+    for (i=0; i<nup; i++)  /* copy upvalues to the top */
+      lua_pushvalue(L, -(nup+1));
+    lua_pushcclosure(L, l->func, nup);
+    lua_settable(L, -(nup+3));
+  }
+  lua_pop(L, nup);  /* remove upvalues */
+}
+
+
+
+/*
+** {======================================================
+** getn-setn: size for arrays
+** =======================================================
+*/
+
+static int checkint (lua_State *L, int topop) {
+  int n = lua_tonumber(L, -1);
+  if (n == 0 && !lua_isnumber(L, -1)) n = -1;
+  lua_pop(L, topop);
+  return n;
+}
+
+
+static void getsizes (lua_State *L) {
+  lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);
+  if (lua_isnil(L, -1)) {  /* no `size' table? */
+    lua_pop(L, 1);  /* remove nil */
+    lua_newtable(L);  /* create it */
+    lua_pushvalue(L, -1);  /* `size' will be its own metatable */
+    lua_setmetatable(L, -2);
+    lua_pushliteral(L, "__mode");
+    lua_pushliteral(L, "k");
+    lua_rawset(L, -3);  /* metatable(N).__mode = "k" */
+    lua_pushvalue(L, -1);
+    lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);  /* store in register */
+  }
+}
+
+
+void luaL_setn (lua_State *L, int t, int n) {
+  t = abs_index(L, t);
+  lua_pushliteral(L, "n");
+  lua_rawget(L, t);
+  if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */
+    lua_pushliteral(L, "n");  /* use it */
+    lua_pushnumber(L, (lua_Number)n);
+    lua_rawset(L, t);
+  }
+  else {  /* use `sizes' */
+    getsizes(L);
+    lua_pushvalue(L, t);
+    lua_pushnumber(L, (lua_Number)n);
+    lua_rawset(L, -3);  /* sizes[t] = n */
+    lua_pop(L, 1);  /* remove `sizes' */
+  }
+}
+
+
+int luaL_getn (lua_State *L, int t) {
+  int n;
+  t = abs_index(L, t);
+  lua_pushliteral(L, "n");  /* try t.n */
+  lua_rawget(L, t);
+  if ((n = checkint(L, 1)) >= 0) return n;
+  getsizes(L);  /* else try sizes[t] */
+  lua_pushvalue(L, t);
+  lua_rawget(L, -2);
+  if ((n = checkint(L, 2)) >= 0) return n;
+  for (n = 1; ; n++) {  /* else must count elements */
+    lua_rawgeti(L, t, n);
+    if (lua_isnil(L, -1)) break;
+    lua_pop(L, 1);
+  }
+  lua_pop(L, 1);
+  return n - 1;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#define bufflen(B)	((B)->p - (B)->buffer)
+#define bufffree(B)	((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
+
+#define LIMIT	(LUA_MINSTACK/2)
+
+
+static int emptybuffer (luaL_Buffer *B) {
+  size_t l = bufflen(B);
+  if (l == 0) return 0;  /* put nothing on stack */
+  else {
+    lua_pushlstring(B->L, B->buffer, l);
+    B->p = B->buffer;
+    B->lvl++;
+    return 1;
+  }
+}
+
+
+static void adjuststack (luaL_Buffer *B) {
+  if (B->lvl > 1) {
+    lua_State *L = B->L;
+    int toget = 1;  /* number of levels to concat */
+    size_t toplen = lua_strlen(L, -1);
+    do {
+      size_t l = lua_strlen(L, -(toget+1));
+      if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
+        toplen += l;
+        toget++;
+      }
+      else break;
+    } while (toget < B->lvl);
+    lua_concat(L, toget);
+    B->lvl = B->lvl - toget + 1;
+  }
+}
+
+
+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
+  if (emptybuffer(B))
+    adjuststack(B);
+  return B->buffer;
+}
+
+
+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
+  while (l--)
+    luaL_putchar(B, *s++);
+}
+
+
+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
+  luaL_addlstring(B, s, strlen(s));
+}
+
+
+LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
+  emptybuffer(B);
+  lua_concat(B->L, B->lvl);
+  B->lvl = 1;
+}
+
+
+LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
+  lua_State *L = B->L;
+  size_t vl = lua_strlen(L, -1);
+  if (vl <= bufffree(B)) {  /* fit into buffer? */
+    memcpy(B->p, lua_tostring(L, -1), vl);  /* put it there */
+    B->p += vl;
+    lua_pop(L, 1);  /* remove from stack */
+  }
+  else {
+    if (emptybuffer(B))
+      lua_insert(L, -2);  /* put buffer before new value */
+    B->lvl++;  /* add new value into B stack */
+    adjuststack(B);
+  }
+}
+
+
+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
+  B->L = L;
+  B->p = B->buffer;
+  B->lvl = 0;
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_ref (lua_State *L, int t) {
+  int ref;
+  t = abs_index(L, t);
+  if (lua_isnil(L, -1)) {
+    lua_pop(L, 1);  /* remove from stack */
+    return LUA_REFNIL;  /* `nil' has a unique fixed reference */
+  }
+  lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
+  ref = lua_tonumber(L, -1);  /* ref = t[FREELIST_REF] */
+  lua_pop(L, 1);  /* remove it from stack */
+  if (ref != 0) {  /* any free element? */
+    lua_rawgeti(L, t, ref);  /* remove it from list */
+    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
+  }
+  else {  /* no free elements */
+    ref = luaL_getn(L, t);
+    if (ref < RESERVED_REFS)
+      ref = RESERVED_REFS;  /* skip reserved references */
+    ref++;  /* create new reference */
+    luaL_setn(L, t, ref);
+  }
+  lua_rawseti(L, t, ref);
+  return ref;
+}
+
+
+LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
+  if (ref >= 0) {
+    t = abs_index(L, t);
+    lua_rawgeti(L, t, FREELIST_REF);
+    lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
+    lua_pushnumber(L, (lua_Number)ref);
+    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
+  }
+}
+
+
+
+/*
+** {======================================================
+** Load functions
+** =======================================================
+*/
+
+typedef struct LoadF {
+  FILE *f;
+  char buff[LUAL_BUFFERSIZE];
+} LoadF;
+
+
+static const char *getF (lua_State *L, void *ud, size_t *size) {
+  LoadF *lf = (LoadF *)ud;
+  (void)L;
+  if (feof(lf->f)) return NULL;
+  *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f);
+  return (*size > 0) ? lf->buff : NULL;
+}
+
+
+static int errfile (lua_State *L, int fnameindex) {
+  const char *filename = lua_tostring(L, fnameindex) + 1;
+  lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno));
+  lua_remove(L, fnameindex);
+  return LUA_ERRFILE;
+}
+
+
+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
+  LoadF lf;
+  int status, readstatus;
+  int c;
+  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
+  if (filename == NULL) {
+    lua_pushliteral(L, "=stdin");
+    lf.f = stdin;
+  }
+  else {
+    lua_pushfstring(L, "@%s", filename);
+    lf.f = fopen(filename, "r");
+  }
+  if (lf.f == NULL) return errfile(L, fnameindex);  /* unable to open file */
+  c = ungetc(getc(lf.f), lf.f);
+  if (!(isspace(c) || isprint(c)) && lf.f != stdin) {  /* binary file? */
+    fclose(lf.f);
+    lf.f = fopen(filename, "rb");  /* reopen in binary mode */
+    if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */
+  }
+  status = lua_load(L, getF, &lf, lua_tostring(L, -1));
+  readstatus = ferror(lf.f);
+  if (lf.f != stdin) fclose(lf.f);  /* close file (even in case of errors) */
+  if (readstatus) {
+    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
+    return errfile(L, fnameindex);
+  }
+  lua_remove(L, fnameindex);
+  return status;
+}
+
+
+typedef struct LoadS {
+  const char *s;
+  size_t size;
+} LoadS;
+
+
+static const char *getS (lua_State *L, void *ud, size_t *size) {
+  LoadS *ls = (LoadS *)ud;
+  (void)L;
+  if (ls->size == 0) return NULL;
+  *size = ls->size;
+  ls->size = 0;
+  return ls->s;
+}
+
+
+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
+                                const char *name) {
+  LoadS ls;
+  ls.s = buff;
+  ls.size = size;
+  return lua_load(L, getS, &ls, name);
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** compatibility code
+** =======================================================
+*/
+
+
+static void callalert (lua_State *L, int status) {
+  if (status != 0) {
+    lua_getglobal(L, "_ALERT");
+    if (lua_isfunction(L, -1)) {
+      lua_insert(L, -2);
+      lua_call(L, 1, 0);
+    }
+    else {  /* no _ALERT function; print it on stderr */
+      fprintf(stderr, "%s\n", lua_tostring(L, -2));
+      lua_pop(L, 2);  /* remove error message and _ALERT */
+    }
+  }
+}
+
+
+static int aux_do (lua_State *L, int status) {
+  if (status == 0) {  /* parse OK? */
+    status = lua_pcall(L, 0, LUA_MULTRET, 0);  /* call main */
+  }
+  callalert(L, status);
+  return status;
+}
+
+
+LUALIB_API int lua_dofile (lua_State *L, const char *filename) {
+  return aux_do(L, luaL_loadfile(L, filename));
+}
+
+
+LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
+                          const char *name) {
+  return aux_do(L, luaL_loadbuffer(L, buff, size, name));
+}
+
+
+LUALIB_API int lua_dostring (lua_State *L, const char *str) {
+  return lua_dobuffer(L, str, strlen(str), str);
+}
+
+/* }====================================================== */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lauxlib.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,144 @@
+/*
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lauxlib_h
+#define lauxlib_h
+
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "lua.h"
+
+
+#ifndef LUALIB_API
+#define LUALIB_API	LUA_API
+#endif
+
+
+
+typedef struct luaL_reg {
+  const char *name;
+  lua_CFunction func;
+} luaL_reg;
+
+
+LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
+                               const luaL_reg *l, int nup);
+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e);
+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e);
+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) __attribute__((noreturn));
+LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg) __attribute__((noreturn));
+LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l);
+LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg,
+                                           const char *def, size_t *l);
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg);
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def);
+
+LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg);
+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t);
+LUALIB_API void luaL_checkany (lua_State *L, int narg);
+
+LUALIB_API int   luaL_newmetatable (lua_State *L, const char *tname);
+LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname);
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname);
+
+LUALIB_API void luaL_where (lua_State *L, int lvl);
+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) __attribute__((noreturn));
+
+LUALIB_API int luaL_findstring (const char *st, const char *const lst[]);
+
+LUALIB_API int luaL_ref (lua_State *L, int t);
+LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
+
+LUALIB_API int luaL_getn (lua_State *L, int t);
+LUALIB_API void luaL_setn (lua_State *L, int t, int n);
+
+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename);
+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz,
+                                const char *name);
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define luaL_argcheck(L, cond,numarg,extramsg) do { if (!(cond))         \
+            luaL_argerror(L, numarg,extramsg); } while (0)
+#define luaL_checkstring(L,n)	luaL_checklstring(L, (n), NULL)
+#define luaL_optstring(L,n,d)	luaL_optlstring(L, (n), (d), NULL)
+#define luaL_checkint(L,n)	luaL_checknumber(L, n)
+#define luaL_checklong(L,n)	luaL_checknumber(L, n)
+#define luaL_optint(L,n,d)	luaL_optnumber(L, n,(lua_Number)(d))
+#define luaL_optlong(L,n,d)	luaL_optnumber(L, n,(lua_Number)(d))
+
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#ifndef LUAL_BUFFERSIZE
+#define LUAL_BUFFERSIZE	  BUFSIZ
+#endif
+
+
+typedef struct luaL_Buffer {
+  char *p;			/* current position in buffer */
+  int lvl;  /* number of strings in the stack (level) */
+  lua_State *L;
+  char buffer[LUAL_BUFFERSIZE];
+} luaL_Buffer;
+
+#define luaL_putchar(B,c) \
+  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
+   (*(B)->p++ = (char)(c)))
+
+#define luaL_addsize(B,n)	((B)->p += (n))
+
+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B);
+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B);
+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s);
+LUALIB_API void luaL_addvalue (luaL_Buffer *B);
+LUALIB_API void luaL_pushresult (luaL_Buffer *B);
+
+
+/* }====================================================== */
+
+
+
+/*
+** Compatibility macros and functions
+*/
+
+LUALIB_API int   lua_dofile (lua_State *L, const char *filename);
+LUALIB_API int   lua_dostring (lua_State *L, const char *str);
+LUALIB_API int   lua_dobuffer (lua_State *L, const char *buff, size_t sz,
+                               const char *n);
+
+
+#define luaL_check_lstr 	luaL_checklstring
+#define luaL_opt_lstr 	luaL_optlstring 
+#define luaL_check_number 	luaL_checknumber 
+#define luaL_opt_number	luaL_optnumber
+#define luaL_arg_check	luaL_argcheck
+#define luaL_check_string	luaL_checkstring
+#define luaL_opt_string	luaL_optstring
+#define luaL_check_int	luaL_checkint
+#define luaL_check_long	luaL_checklong
+#define luaL_opt_int	luaL_optint
+#define luaL_opt_long	luaL_optlong
+
+
+#endif
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lbaselib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lbaselib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lbaselib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lbaselib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,674 @@
+/*
+** Basic library
+** See Copyright Notice in lua.h
+*/
+
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lbaselib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+
+/*
+** If your system does not support `stdout', you can just remove this function.
+** If you need, you can define your own `print' function, following this
+** model but changing `fputs' to put the strings at a proper place
+** (a console window or a log file, for instance).
+*/
+static int luaB_print (lua_State *L) {
+  int n = lua_gettop(L);  /* number of arguments */
+  int i;
+  lua_getglobal(L, "tostring");
+  for (i=1; i<=n; i++) {
+    const char *s;
+    lua_pushvalue(L, -1);  /* function to be called */
+    lua_pushvalue(L, i);   /* value to print */
+    lua_call(L, 1, 1);
+    s = lua_tostring(L, -1);  /* get result */
+    if (s == NULL)
+      return luaL_error(L, "`tostring' must return a string to `print'");
+    if (i>1) fputs("\t", stdout);
+    fputs(s, stdout);
+    lua_pop(L, 1);  /* pop result */
+  }
+  fputs("\n", stdout);
+  return 0;
+}
+
+
+static int luaB_tonumber (lua_State *L) {
+  int base = luaL_optint(L, 2, 10);
+  if (base == 10) {  /* standard conversion */
+    luaL_checkany(L, 1);
+    if (lua_isnumber(L, 1)) {
+      lua_pushnumber(L, lua_tonumber(L, 1));
+      return 1;
+    }
+  }
+  else {
+    const char *s1 = luaL_checkstring(L, 1);
+    char *s2;
+    unsigned long n;
+    luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+    n = strtoul(s1, &s2, base);
+    if (s1 != s2) {  /* at least one valid digit? */
+      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
+      if (*s2 == '\0') {  /* no invalid trailing characters? */
+        lua_pushnumber(L, (lua_Number)n);
+        return 1;
+      }
+    }
+  }
+  lua_pushnil(L);  /* else not a number */
+  return 1;
+}
+
+static int luaB_error (lua_State *L)  __attribute__((noreturn));
+static int luaB_error (lua_State *L) {
+  int level = luaL_optint(L, 2, 1);
+  luaL_checkany(L, 1);
+  if (!lua_isstring(L, 1) || level == 0)
+    lua_pushvalue(L, 1);  /* propagate error message without changes */
+  else {  /* add extra information */
+    luaL_where(L, level);
+    lua_pushvalue(L, 1);
+    lua_concat(L, 2);
+  }
+  lua_error(L);
+}
+
+
+static int luaB_getmetatable (lua_State *L) {
+  luaL_checkany(L, 1);
+  if (!lua_getmetatable(L, 1)) {
+    lua_pushnil(L);
+    return 1;  /* no metatable */
+  }
+  luaL_getmetafield(L, 1, "__metatable");
+  return 1;  /* returns either __metatable field (if present) or metatable */
+}
+
+
+static int luaB_setmetatable (lua_State *L) {
+  int t = lua_type(L, 2);
+  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+                    "nil or table expected");
+  if (luaL_getmetafield(L, 1, "__metatable"))
+    luaL_error(L, "cannot change a protected metatable");
+  lua_settop(L, 2);
+  lua_setmetatable(L, 1);
+  return 1;
+}
+
+
+static void getfunc (lua_State *L) {
+  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
+  else {
+    lua_Debug ar;
+    int level = luaL_optint(L, 1, 1);
+    luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
+    if (lua_getstack(L, level, &ar) == 0)
+      luaL_argerror(L, 1, "invalid level");
+    lua_getinfo(L, "f", &ar);
+    if (lua_isnil(L, -1))
+      luaL_error(L, "no function environment for tail call at level %d",
+                    level);
+  }
+}
+
+
+static int aux_getfenv (lua_State *L) {
+  lua_getfenv(L, -1);
+  lua_pushliteral(L, "__fenv");
+  lua_rawget(L, -2);
+  return !lua_isnil(L, -1);
+}
+
+
+static int luaB_getfenv (lua_State *L) {
+  getfunc(L);
+  if (!aux_getfenv(L))  /* __fenv not defined? */
+    lua_pop(L, 1);  /* remove it, to return real environment */
+  return 1;
+}
+
+
+static int luaB_setfenv (lua_State *L) {
+  luaL_checktype(L, 2, LUA_TTABLE);
+  getfunc(L);
+  if (aux_getfenv(L))  /* __fenv defined? */
+    luaL_error(L, "`setfenv' cannot change a protected environment");
+  else
+    lua_pop(L, 2);  /* remove __fenv and real environment table */
+  lua_pushvalue(L, 2);
+  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0)
+    lua_replace(L, LUA_GLOBALSINDEX);
+  else if (lua_setfenv(L, -2) == 0)
+    luaL_error(L, "`setfenv' cannot change environment of given function");
+  return 0;
+}
+
+
+static int luaB_rawequal (lua_State *L) {
+  luaL_checkany(L, 1);
+  luaL_checkany(L, 2);
+  lua_pushboolean(L, lua_rawequal(L, 1, 2));
+  return 1;
+}
+
+
+static int luaB_rawget (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkany(L, 2);
+  lua_rawget(L, 1);
+  return 1;
+}
+
+static int luaB_rawset (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkany(L, 2);
+  luaL_checkany(L, 3);
+  lua_rawset(L, 1);
+  return 1;
+}
+
+
+static int luaB_gcinfo (lua_State *L) {
+  lua_pushnumber(L, lua_getgccount(L));
+  lua_pushnumber(L, lua_getgcthreshold(L));
+  return 2;
+}
+
+
+static int luaB_collectgarbage (lua_State *L) {
+  lua_setgcthreshold(L, luaL_optint(L, 1, 0));
+  return 0;
+}
+
+
+static int luaB_type (lua_State *L) {
+  luaL_checkany(L, 1);
+  lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
+  return 1;
+}
+
+
+static int luaB_next (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
+  if (lua_next(L, 1))
+    return 2;
+  else {
+    lua_pushnil(L);
+    return 1;
+  }
+}
+
+
+static int luaB_pairs (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  lua_pushliteral(L, "next");
+  lua_rawget(L, LUA_GLOBALSINDEX);  /* return generator, */
+  lua_pushvalue(L, 1);  /* state, */
+  lua_pushnil(L);  /* and initial value */
+  return 3;
+}
+
+
+static int luaB_ipairs (lua_State *L) {
+  lua_Number i = lua_tonumber(L, 2);
+  luaL_checktype(L, 1, LUA_TTABLE);
+  if (i == 0 && lua_isnone(L, 2)) {  /* `for' start? */
+    lua_pushliteral(L, "ipairs");
+    lua_rawget(L, LUA_GLOBALSINDEX);  /* return generator, */
+    lua_pushvalue(L, 1);  /* state, */
+    lua_pushnumber(L, 0);  /* and initial value */
+    return 3;
+  }
+  else {  /* `for' step */
+    i++;  /* next value */
+    lua_pushnumber(L, i);
+    lua_rawgeti(L, 1, (int)i);
+    return (lua_isnil(L, -1)) ? 0 : 2;
+  }
+}
+
+
+static int load_aux (lua_State *L, int status) {
+  if (status == 0)  /* OK? */
+    return 1;
+  else {
+    lua_pushnil(L);
+    lua_insert(L, -2);  /* put before error message */
+    return 2;  /* return nil plus error message */
+  }
+}
+
+
+static int luaB_loadstring (lua_State *L) {
+  size_t l;
+  const char *s = luaL_checklstring(L, 1, &l);
+  const char *chunkname = luaL_optstring(L, 2, s);
+  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
+}
+
+
+static int luaB_loadfile (lua_State *L) {
+  const char *fname = luaL_optstring(L, 1, NULL);
+  return load_aux(L, luaL_loadfile(L, fname));
+}
+
+
+static int luaB_dofile (lua_State *L) {
+  const char *fname = luaL_optstring(L, 1, NULL);
+  int n = lua_gettop(L);
+  int status = luaL_loadfile(L, fname);
+  if (status != 0) lua_error(L);
+  lua_call(L, 0, LUA_MULTRET);
+  return lua_gettop(L) - n;
+}
+
+
+static int luaB_assert (lua_State *L) {
+  luaL_checkany(L, 1);
+  if (!lua_toboolean(L, 1))
+    return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
+  lua_settop(L, 1);
+  return 1;
+}
+
+
+static int luaB_unpack (lua_State *L) {
+  int n, i;
+  luaL_checktype(L, 1, LUA_TTABLE);
+  n = luaL_getn(L, 1);
+  luaL_checkstack(L, n, "table too big to unpack");
+  for (i=1; i<=n; i++)  /* push arg[1...n] */
+    lua_rawgeti(L, 1, i);
+  return n;
+}
+
+
+static int luaB_pcall (lua_State *L) {
+  int status;
+  luaL_checkany(L, 1);
+  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
+  lua_pushboolean(L, (status == 0));
+  lua_insert(L, 1);
+  return lua_gettop(L);  /* return status + all results */
+}
+
+
+static int luaB_xpcall (lua_State *L) {
+  int status;
+  luaL_checkany(L, 2);
+  lua_settop(L, 2);
+  lua_insert(L, 1);  /* put error function under function to be called */
+  status = lua_pcall(L, 0, LUA_MULTRET, 1);
+  lua_pushboolean(L, (status == 0));
+  lua_replace(L, 1);
+  return lua_gettop(L);  /* return status + all results */
+}
+
+
+static int luaB_tostring (lua_State *L) {
+  char buff[128];
+  luaL_checkany(L, 1);
+  if (luaL_callmeta(L, 1, "__tostring"))  /* is there a metafield? */
+    return 1;  /* use its value */
+  switch (lua_type(L, 1)) {
+    case LUA_TNUMBER:
+      lua_pushstring(L, lua_tostring(L, 1));
+      return 1;
+    case LUA_TSTRING:
+      lua_pushvalue(L, 1);
+      return 1;
+    case LUA_TBOOLEAN:
+      lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
+      return 1;
+    case LUA_TTABLE:
+      sprintf(buff, "table: %p", lua_topointer(L, 1));
+      break;
+    case LUA_TFUNCTION:
+      sprintf(buff, "function: %p", lua_topointer(L, 1));
+      break;
+    case LUA_TUSERDATA:
+    case LUA_TLIGHTUSERDATA:
+      sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
+      break;
+    case LUA_TTHREAD:
+      sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
+      break;
+    case LUA_TNIL:
+      lua_pushliteral(L, "nil");
+      return 1;
+  }
+  lua_pushstring(L, buff);
+  return 1;
+}
+
+
+static int luaB_newproxy (lua_State *L) {
+  lua_settop(L, 1);
+  lua_newuserdata(L, 0);  /* create proxy */
+  if (lua_toboolean(L, 1) == 0)
+    return 1;  /* no metatable */
+  else if (lua_isboolean(L, 1)) {
+    lua_newtable(L);  /* create a new metatable `m' ... */
+    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */
+    lua_pushboolean(L, 1);
+    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */
+  }
+  else {
+    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */
+    if (lua_getmetatable(L, 1)) {
+      lua_rawget(L, lua_upvalueindex(1));
+      validproxy = lua_toboolean(L, -1);
+      lua_pop(L, 1);  /* remove value */
+    }
+    luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
+    lua_getmetatable(L, 1);  /* metatable is valid; get it */
+  }
+  lua_setmetatable(L, 2);
+  return 1;
+}
+
+
+/*
+** {======================================================
+** `require' function
+** =======================================================
+*/
+
+
+/* name of global that holds table with loaded packages */
+#define REQTAB		"_LOADED"
+
+/* name of global that holds the search path for packages */
+#define LUA_PATH	"LUA_PATH"
+
+#ifndef LUA_PATH_SEP
+#define LUA_PATH_SEP	';'
+#endif
+
+#ifndef LUA_PATH_MARK
+#define LUA_PATH_MARK	'?'
+#endif
+
+#ifndef LUA_PATH_DEFAULT
+#define LUA_PATH_DEFAULT	"?;?.lua"
+#endif
+
+
+static const char *getpath (lua_State *L) {
+  const char *path;
+  lua_getglobal(L, LUA_PATH);  /* try global variable */
+  path = lua_tostring(L, -1);
+  lua_pop(L, 1);
+  if (path) return path;
+  path = getenv(LUA_PATH);  /* else try environment variable */
+  if (path) return path;
+  return LUA_PATH_DEFAULT;  /* else use default */
+}
+
+
+static const char *pushnextpath (lua_State *L, const char *path) {
+  const char *l;
+  if (*path == '\0') return NULL;  /* no more paths */
+  if (*path == LUA_PATH_SEP) path++;  /* skip separator */
+  l = strchr(path, LUA_PATH_SEP);  /* find next separator */
+  if (l == NULL) l = path+strlen(path);
+  lua_pushlstring(L, path, l - path);  /* directory name */
+  return l;
+}
+
+
+static void pushcomposename (lua_State *L) {
+  const char *path = lua_tostring(L, -1);
+  const char *wild;
+  int n = 1;
+  while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
+    /* is there stack space for prefix, name, and eventual last sufix? */
+    luaL_checkstack(L, 3, "too many marks in a path component");
+    lua_pushlstring(L, path, wild - path);  /* push prefix */
+    lua_pushvalue(L, 1);  /* push package name (in place of MARK) */
+    path = wild + 1;  /* continue after MARK */
+    n += 2;
+  }
+  lua_pushstring(L, path);  /* push last sufix (`n' already includes this) */
+  lua_concat(L, n);
+}
+
+
+static int luaB_require (lua_State *L) {
+  const char *path;
+  int status = LUA_ERRFILE;  /* not found (yet) */
+  luaL_checkstring(L, 1);
+  lua_settop(L, 1);
+  lua_getglobal(L, REQTAB);
+  if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
+  path = getpath(L);
+  lua_pushvalue(L, 1);  /* check package's name in book-keeping table */
+  lua_rawget(L, 2);
+  if (lua_toboolean(L, -1))  /* is it there? */
+    return 1;  /* package is already loaded; return its result */
+  else {  /* must load it */
+    while (status == LUA_ERRFILE) {
+      lua_settop(L, 3);  /* reset stack position */
+      if ((path = pushnextpath(L, path)) == NULL) break;
+      pushcomposename(L);
+      status = luaL_loadfile(L, lua_tostring(L, -1));  /* try to load it */
+    }
+  }
+  switch (status) {
+    case 0: {
+      lua_getglobal(L, "_REQUIREDNAME");  /* save previous name */
+      lua_insert(L, -2);  /* put it below function */
+      lua_pushvalue(L, 1);
+      lua_setglobal(L, "_REQUIREDNAME");  /* set new name */
+      lua_call(L, 0, 1);  /* run loaded module */
+      lua_insert(L, -2);  /* put result below previous name */
+      lua_setglobal(L, "_REQUIREDNAME");  /* reset to previous name */
+      if (lua_isnil(L, -1)) {  /* no/nil return? */
+        lua_pushboolean(L, 1);
+        lua_replace(L, -2);  /* replace to true */
+      }
+      lua_pushvalue(L, 1);
+      lua_pushvalue(L, -2);
+      lua_rawset(L, 2);  /* mark it as loaded */
+      return 1;  /* return value */
+    }
+    case LUA_ERRFILE: {  /* file not found */
+      return luaL_error(L, "could not load package `%s' from path `%s'",
+                            lua_tostring(L, 1), getpath(L));
+    }
+    default: {
+      return luaL_error(L, "error loading package `%s' (%s)",
+                           lua_tostring(L, 1), lua_tostring(L, -1));
+    }
+  }
+}
+
+/* }====================================================== */
+
+
+static const luaL_reg base_funcs[] = {
+  {"error", luaB_error},
+  {"getmetatable", luaB_getmetatable},
+  {"setmetatable", luaB_setmetatable},
+  {"getfenv", luaB_getfenv},
+  {"setfenv", luaB_setfenv},
+  {"next", luaB_next},
+  {"ipairs", luaB_ipairs},
+  {"pairs", luaB_pairs},
+  {"print", luaB_print},
+  {"tonumber", luaB_tonumber},
+  {"tostring", luaB_tostring},
+  {"type", luaB_type},
+  {"assert", luaB_assert},
+  {"unpack", luaB_unpack},
+  {"rawequal", luaB_rawequal},
+  {"rawget", luaB_rawget},
+  {"rawset", luaB_rawset},
+  {"pcall", luaB_pcall},
+  {"xpcall", luaB_xpcall},
+  {"collectgarbage", luaB_collectgarbage},
+  {"gcinfo", luaB_gcinfo},
+  {"loadfile", luaB_loadfile},
+  {"dofile", luaB_dofile},
+  {"loadstring", luaB_loadstring},
+  {"require", luaB_require},
+  {NULL, NULL}
+};
+
+
+/*
+** {======================================================
+** Coroutine library
+** =======================================================
+*/
+
+static int auxresume (lua_State *L, lua_State *co, int narg) {
+  int status;
+  if (!lua_checkstack(co, narg))
+    luaL_error(L, "too many arguments to resume");
+  lua_xmove(L, co, narg);
+  status = lua_resume(co, narg);
+  if (status == 0) {
+    int nres = lua_gettop(co);
+    if (!lua_checkstack(L, nres))
+      luaL_error(L, "too many results to resume");
+    lua_xmove(co, L, nres);  /* move yielded values */
+    return nres;
+  }
+  else {
+    lua_xmove(co, L, 1);  /* move error message */
+    return -1;  /* error flag */
+  }
+}
+
+
+static int luaB_coresume (lua_State *L) {
+  lua_State *co = lua_tothread(L, 1);
+  int r;
+  luaL_argcheck(L, co, 1, "coroutine expected");
+  r = auxresume(L, co, lua_gettop(L) - 1);
+  if (r < 0) {
+    lua_pushboolean(L, 0);
+    lua_insert(L, -2);
+    return 2;  /* return false + error message */
+  }
+  else {
+    lua_pushboolean(L, 1);
+    lua_insert(L, -(r + 1));
+    return r + 1;  /* return true + `resume' returns */
+  }
+}
+
+
+static int luaB_auxwrap (lua_State *L) {
+  lua_State *co = lua_tothread(L, lua_upvalueindex(1));
+  int r = auxresume(L, co, lua_gettop(L));
+  if (r < 0) {
+    if (lua_isstring(L, -1)) {  /* error object is a string? */
+      luaL_where(L, 1);  /* add extra info */
+      lua_insert(L, -2);
+      lua_concat(L, 2);
+    }
+    lua_error(L);  /* propagate error */
+  }
+  return r;
+}
+
+
+static int luaB_cocreate (lua_State *L) {
+  lua_State *NL = lua_newthread(L);
+  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
+    "Lua function expected");
+  lua_pushvalue(L, 1);  /* move function to top */
+  lua_xmove(L, NL, 1);  /* move function from L to NL */
+  return 1;
+}
+
+
+static int luaB_cowrap (lua_State *L) {
+  luaB_cocreate(L);
+  lua_pushcclosure(L, luaB_auxwrap, 1);
+  return 1;
+}
+
+
+static int luaB_yield (lua_State *L) {
+  return lua_yield(L, lua_gettop(L));
+}
+
+
+static int luaB_costatus (lua_State *L) {
+  lua_State *co = lua_tothread(L, 1);
+  luaL_argcheck(L, co, 1, "coroutine expected");
+  if (L == co) lua_pushliteral(L, "running");
+  else {
+    lua_Debug ar;
+    if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0)
+      lua_pushliteral(L, "dead");
+    else
+      lua_pushliteral(L, "suspended");
+  }
+  return 1;
+}
+
+
+static const luaL_reg co_funcs[] = {
+  {"create", luaB_cocreate},
+  {"wrap", luaB_cowrap},
+  {"resume", luaB_coresume},
+  {"yield", luaB_yield},
+  {"status", luaB_costatus},
+  {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+static void base_open (lua_State *L) {
+  lua_pushliteral(L, "_G");
+  lua_pushvalue(L, LUA_GLOBALSINDEX);
+  luaL_openlib(L, NULL, base_funcs, 0);  /* open lib into global table */
+  lua_pushliteral(L, "_VERSION");
+  lua_pushliteral(L, LUA_VERSION);
+  lua_rawset(L, -3);  /* set global _VERSION */
+  /* `newproxy' needs a weaktable as upvalue */
+  lua_pushliteral(L, "newproxy");
+  lua_newtable(L);  /* new table `w' */
+  lua_pushvalue(L, -1);  /* `w' will be its own metatable */
+  lua_setmetatable(L, -2);
+  lua_pushliteral(L, "__mode");
+  lua_pushliteral(L, "k");
+  lua_rawset(L, -3);  /* metatable(w).__mode = "k" */
+  lua_pushcclosure(L, luaB_newproxy, 1);
+  lua_rawset(L, -3);  /* set global `newproxy' */
+  lua_rawset(L, -1);  /* set global _G */
+}
+
+
+LUALIB_API int luaopen_base (lua_State *L) {
+  base_open(L);
+  luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
+  lua_newtable(L);
+  lua_setglobal(L, REQTAB);
+  return 0;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lcode.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lcode.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lcode.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lcode.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,713 @@
+/*
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+
+#define lcode_c
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "ltable.h"
+
+
+#define hasjumps(e)	((e)->t != (e)->f)
+
+
+void luaK_nil (FuncState *fs, int from, int n) {
+  Instruction *previous;
+  if (fs->pc > fs->lasttarget &&  /* no jumps to current position? */
+      GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) {
+    int pfrom = GETARG_A(*previous);
+    int pto = GETARG_B(*previous);
+    if (pfrom <= from && from <= pto+1) {  /* can connect both? */
+      if (from+n-1 > pto)
+        SETARG_B(*previous, from+n-1);
+      return;
+    }
+  }
+  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
+}
+
+
+int luaK_jump (FuncState *fs) {
+  int jpc = fs->jpc;  /* save list of jumps to here */
+  int j;
+  fs->jpc = NO_JUMP;
+  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
+  luaK_concat(fs, &j, jpc);  /* keep them on hold */
+  return j;
+}
+
+
+static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) {
+  luaK_codeABC(fs, op, A, B, C);
+  return luaK_jump(fs);
+}
+
+
+static void luaK_fixjump (FuncState *fs, int pc, int dest) {
+  Instruction *jmp = &fs->f->code[pc];
+  int offset = dest-(pc+1);
+  lua_assert(dest != NO_JUMP);
+  if (abs(offset) > MAXARG_sBx)
+    luaX_syntaxerror(fs->ls, "control structure too long");
+  SETARG_sBx(*jmp, offset);
+}
+
+
+/*
+** returns current `pc' and marks it as a jump target (to avoid wrong
+** optimizations with consecutive instructions not in the same basic block).
+*/
+int luaK_getlabel (FuncState *fs) {
+  fs->lasttarget = fs->pc;
+  return fs->pc;
+}
+
+
+static int luaK_getjump (FuncState *fs, int pc) {
+  int offset = GETARG_sBx(fs->f->code[pc]);
+  if (offset == NO_JUMP)  /* point to itself represents end of list */
+    return NO_JUMP;  /* end of list */
+  else
+    return (pc+1)+offset;  /* turn offset into absolute position */
+}
+
+
+static Instruction *getjumpcontrol (FuncState *fs, int pc) {
+  Instruction *pi = &fs->f->code[pc];
+  if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT))
+    return pi-1;
+  else
+    return pi;
+}
+
+
+/*
+** check whether list has any jump that do not produce a value
+** (or produce an inverted value)
+*/
+static int need_value (FuncState *fs, int list, int cond) {
+  for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
+    Instruction i = *getjumpcontrol(fs, list);
+    if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1;
+  }
+  return 0;  /* not found */
+}
+
+
+static void patchtestreg (Instruction *i, int reg) {
+  if (reg == NO_REG) reg = GETARG_B(*i);
+  SETARG_A(*i, reg);
+}
+
+
+static void luaK_patchlistaux (FuncState *fs, int list,
+          int ttarget, int treg, int ftarget, int freg, int dtarget) {
+  while (list != NO_JUMP) {
+    int next = luaK_getjump(fs, list);
+    Instruction *i = getjumpcontrol(fs, list);
+    if (GET_OPCODE(*i) != OP_TEST) {
+      lua_assert(dtarget != NO_JUMP);
+      luaK_fixjump(fs, list, dtarget);  /* jump to default target */
+    }
+    else {
+      if (GETARG_C(*i)) {
+        lua_assert(ttarget != NO_JUMP);
+        patchtestreg(i, treg);
+        luaK_fixjump(fs, list, ttarget);
+      }
+      else {
+        lua_assert(ftarget != NO_JUMP);
+        patchtestreg(i, freg);
+        luaK_fixjump(fs, list, ftarget);
+      }
+    }
+    list = next;
+  }
+}
+
+
+static void luaK_dischargejpc (FuncState *fs) {
+  luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc);
+  fs->jpc = NO_JUMP;
+}
+
+
+void luaK_patchlist (FuncState *fs, int list, int target) {
+  if (target == fs->pc)
+    luaK_patchtohere(fs, list);
+  else {
+    lua_assert(target < fs->pc);
+    luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target);
+  }
+}
+
+
+void luaK_patchtohere (FuncState *fs, int list) {
+  luaK_getlabel(fs);
+  luaK_concat(fs, &fs->jpc, list);
+}
+
+
+void luaK_concat (FuncState *fs, int *l1, int l2) {
+  if (l2 == NO_JUMP) return;
+  else if (*l1 == NO_JUMP)
+    *l1 = l2;
+  else {
+    int list = *l1;
+    int next;
+    while ((next = luaK_getjump(fs, list)) != NO_JUMP)  /* find last element */
+      list = next;
+    luaK_fixjump(fs, list, l2);
+  }
+}
+
+
+void luaK_checkstack (FuncState *fs, int n) {
+  int newstack = fs->freereg + n;
+  if (newstack > fs->f->maxstacksize) {
+    if (newstack >= MAXSTACK)
+      luaX_syntaxerror(fs->ls, "function or expression too complex");
+    fs->f->maxstacksize = cast(lu_byte, newstack);
+  }
+}
+
+
+void luaK_reserveregs (FuncState *fs, int n) {
+  luaK_checkstack(fs, n);
+  fs->freereg += n;
+}
+
+
+static void freereg (FuncState *fs, int reg) {
+  if (reg >= fs->nactvar && reg < MAXSTACK) {
+    fs->freereg--;
+    lua_assert(reg == fs->freereg);
+  }
+}
+
+
+static void freeexp (FuncState *fs, expdesc *e) {
+  if (e->k == VNONRELOC)
+    freereg(fs, e->info);
+}
+
+
+static int addk (FuncState *fs, TObject *k, TObject *v) {
+  const TObject *idx = luaH_get(fs->h, k);
+  if (ttisnumber(idx)) {
+    lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v));
+    return cast(int, nvalue(idx));
+  }
+  else {  /* constant not found; create a new entry */
+    Proto *f = fs->f;
+    luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
+                    MAXARG_Bx, "constant table overflow");
+    setobj2n(&f->k[fs->nk], v);
+    setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk));
+    return fs->nk++;
+  }
+}
+
+
+int luaK_stringK (FuncState *fs, TString *s) {
+  TObject o;
+  setsvalue(&o, s);
+  return addk(fs, &o, &o);
+}
+
+
+int luaK_numberK (FuncState *fs, lua_Number r) {
+  TObject o;
+  setnvalue(&o, r);
+  return addk(fs, &o, &o);
+}
+
+
+static int nil_constant (FuncState *fs) {
+  TObject k, v;
+  setnilvalue(&v);
+  sethvalue(&k, fs->h);  /* cannot use nil as key; instead use table itself */
+  return addk(fs, &k, &v);
+}
+
+
+void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
+  if (e->k == VCALL) {  /* expression is an open function call? */
+    SETARG_C(getcode(fs, e), nresults+1);
+    if (nresults == 1) {  /* `regular' expression? */
+      e->k = VNONRELOC;
+      e->info = GETARG_A(getcode(fs, e));
+    }
+  }
+}
+
+
+void luaK_dischargevars (FuncState *fs, expdesc *e) {
+  switch (e->k) {
+    case VLOCAL: {
+      e->k = VNONRELOC;
+      break;
+    }
+    case VUPVAL: {
+      e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0);
+      e->k = VRELOCABLE;
+      break;
+    }
+    case VGLOBAL: {
+      e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info);
+      e->k = VRELOCABLE;
+      break;
+    }
+    case VINDEXED: {
+      freereg(fs, e->aux);
+      freereg(fs, e->info);
+      e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux);
+      e->k = VRELOCABLE;
+      break;
+    }
+    case VCALL: {
+      luaK_setcallreturns(fs, e, 1);
+      break;
+    }
+    default: break;  /* there is one value available (somewhere) */
+  }
+}
+
+
+static int code_label (FuncState *fs, int A, int b, int jump) {
+  luaK_getlabel(fs);  /* those instructions may be jump targets */
+  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
+}
+
+
+static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
+  luaK_dischargevars(fs, e);
+  switch (e->k) {
+    case VNIL: {
+      luaK_nil(fs, reg, 1);
+      break;
+    }
+    case VFALSE:  case VTRUE: {
+      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
+      break;
+    }
+    case VK: {
+      luaK_codeABx(fs, OP_LOADK, reg, e->info);
+      break;
+    }
+    case VRELOCABLE: {
+      Instruction *pc = &getcode(fs, e);
+      SETARG_A(*pc, reg);
+      break;
+    }
+    case VNONRELOC: {
+      if (reg != e->info)
+        luaK_codeABC(fs, OP_MOVE, reg, e->info, 0);
+      break;
+    }
+    default: {
+      lua_assert(e->k == VVOID || e->k == VJMP);
+      return;  /* nothing to do... */
+    }
+  }
+  e->info = reg;
+  e->k = VNONRELOC;
+}
+
+
+static void discharge2anyreg (FuncState *fs, expdesc *e) {
+  if (e->k != VNONRELOC) {
+    luaK_reserveregs(fs, 1);
+    discharge2reg(fs, e, fs->freereg-1);
+  }
+}
+
+
+static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) {
+  discharge2reg(fs, e, reg);
+  if (e->k == VJMP)
+    luaK_concat(fs, &e->t, e->info);  /* put this jump in `t' list */
+  if (hasjumps(e)) {
+    int final;  /* position after whole expression */
+    int p_f = NO_JUMP;  /* position of an eventual LOAD false */
+    int p_t = NO_JUMP;  /* position of an eventual LOAD true */
+    if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) {
+      int fj = NO_JUMP;  /* first jump (over LOAD ops.) */
+      if (e->k != VJMP)
+        fj = luaK_jump(fs);
+      p_f = code_label(fs, reg, 0, 1);
+      p_t = code_label(fs, reg, 1, 0);
+      luaK_patchtohere(fs, fj);
+    }
+    final = luaK_getlabel(fs);
+    luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
+    luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
+  }
+  e->f = e->t = NO_JUMP;
+  e->info = reg;
+  e->k = VNONRELOC;
+}
+
+
+void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
+  luaK_dischargevars(fs, e);
+  freeexp(fs, e);
+  luaK_reserveregs(fs, 1);
+  luaK_exp2reg(fs, e, fs->freereg - 1);
+}
+
+
+int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
+  luaK_dischargevars(fs, e);
+  if (e->k == VNONRELOC) {
+    if (!hasjumps(e)) return e->info;  /* exp is already in a register */ 
+    if (e->info >= fs->nactvar) {  /* reg. is not a local? */
+      luaK_exp2reg(fs, e, e->info);  /* put value on it */
+      return e->info;
+    }
+  }
+  luaK_exp2nextreg(fs, e);  /* default */
+  return e->info;
+}
+
+
+void luaK_exp2val (FuncState *fs, expdesc *e) {
+  if (hasjumps(e))
+    luaK_exp2anyreg(fs, e);
+  else
+    luaK_dischargevars(fs, e);
+}
+
+
+int luaK_exp2RK (FuncState *fs, expdesc *e) {
+  luaK_exp2val(fs, e);
+  switch (e->k) {
+    case VNIL: {
+      if (fs->nk + MAXSTACK <= MAXARG_C) {  /* constant fit in argC? */
+        e->info = nil_constant(fs);
+        e->k = VK;
+        return e->info + MAXSTACK;
+      }
+      else break;
+    }
+    case VK: {
+      if (e->info + MAXSTACK <= MAXARG_C)  /* constant fit in argC? */
+        return e->info + MAXSTACK;
+      else break;
+    }
+    default: break;
+  }
+  /* not a constant in the right range: put it in a register */
+  return luaK_exp2anyreg(fs, e);
+}
+
+
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
+  switch (var->k) {
+    case VLOCAL: {
+      freeexp(fs, exp);
+      luaK_exp2reg(fs, exp, var->info);
+      return;
+    }
+    case VUPVAL: {
+      int e = luaK_exp2anyreg(fs, exp);
+      luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
+      break;
+    }
+    case VGLOBAL: {
+      int e = luaK_exp2anyreg(fs, exp);
+      luaK_codeABx(fs, OP_SETGLOBAL, e, var->info);
+      break;
+    }
+    case VINDEXED: {
+      int e = luaK_exp2RK(fs, exp);
+      luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
+      break;
+    }
+    default: {
+      lua_assert(0);  /* invalid var kind to store */
+      break;
+    }
+  }
+  freeexp(fs, exp);
+}
+
+
+void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
+  int func;
+  luaK_exp2anyreg(fs, e);
+  freeexp(fs, e);
+  func = fs->freereg;
+  luaK_reserveregs(fs, 2);
+  luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key));
+  freeexp(fs, key);
+  e->info = func;
+  e->k = VNONRELOC;
+}
+
+
+static void invertjump (FuncState *fs, expdesc *e) {
+  Instruction *pc = getjumpcontrol(fs, e->info);
+  lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
+             GET_OPCODE(*pc) != OP_TEST);
+  SETARG_A(*pc, !(GETARG_A(*pc)));
+}
+
+
+static int jumponcond (FuncState *fs, expdesc *e, int cond) {
+  if (e->k == VRELOCABLE) {
+    Instruction ie = getcode(fs, e);
+    if (GET_OPCODE(ie) == OP_NOT) {
+      fs->pc--;  /* remove previous OP_NOT */
+      return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond);
+    }
+    /* else go through */
+  }
+  discharge2anyreg(fs, e);
+  freeexp(fs, e);
+  return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond);
+}
+
+
+void luaK_goiftrue (FuncState *fs, expdesc *e) {
+  int pc;  /* pc of last jump */
+  luaK_dischargevars(fs, e);
+  switch (e->k) {
+    case VK: case VTRUE: {
+      pc = NO_JUMP;  /* always true; do nothing */
+      break;
+    }
+    case VFALSE: {
+      pc = luaK_jump(fs);  /* always jump */
+      break;
+    }
+    case VJMP: {
+      invertjump(fs, e);
+      pc = e->info;
+      break;
+    }
+    default: {
+      pc = jumponcond(fs, e, 0);
+      break;
+    }
+  }
+  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
+}
+
+
+void luaK_goiffalse (FuncState *fs, expdesc *e) {
+  int pc;  /* pc of last jump */
+  luaK_dischargevars(fs, e);
+  switch (e->k) {
+    case VNIL: case VFALSE: {
+      pc = NO_JUMP;  /* always false; do nothing */
+      break;
+    }
+    case VTRUE: {
+      pc = luaK_jump(fs);  /* always jump */
+      break;
+    }
+    case VJMP: {
+      pc = e->info;
+      break;
+    }
+    default: {
+      pc = jumponcond(fs, e, 1);
+      break;
+    }
+  }
+  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
+}
+
+
+static void codenot (FuncState *fs, expdesc *e) {
+  luaK_dischargevars(fs, e);
+  switch (e->k) {
+    case VNIL: case VFALSE: {
+      e->k = VTRUE;
+      break;
+    }
+    case VK: case VTRUE: {
+      e->k = VFALSE;
+      break;
+    }
+    case VJMP: {
+      invertjump(fs, e);
+      break;
+    }
+    case VRELOCABLE:
+    case VNONRELOC: {
+      discharge2anyreg(fs, e);
+      freeexp(fs, e);
+      e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0);
+      e->k = VRELOCABLE;
+      break;
+    }
+    default: {
+      lua_assert(0);  /* cannot happen */
+      break;
+    }
+  }
+  /* interchange true and false lists */
+  { int temp = e->f; e->f = e->t; e->t = temp; }
+}
+
+
+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
+  t->aux = luaK_exp2RK(fs, k);
+  t->k = VINDEXED;
+}
+
+
+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+  if (op == OPR_MINUS) {
+    luaK_exp2val(fs, e);
+    if (e->k == VK && ttisnumber(&fs->f->k[e->info]))
+      e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info]));
+    else {
+      luaK_exp2anyreg(fs, e);
+      freeexp(fs, e);
+      e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0);
+      e->k = VRELOCABLE;
+    }
+  }
+  else  /* op == NOT */
+    codenot(fs, e);
+}
+
+
+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
+  switch (op) {
+    case OPR_AND: {
+      luaK_goiftrue(fs, v);
+      luaK_patchtohere(fs, v->t);
+      v->t = NO_JUMP;
+      break;
+    }
+    case OPR_OR: {
+      luaK_goiffalse(fs, v);
+      luaK_patchtohere(fs, v->f);
+      v->f = NO_JUMP;
+      break;
+    }
+    case OPR_CONCAT: {
+      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */
+      break;
+    }
+    default: {
+      luaK_exp2RK(fs, v);
+      break;
+    }
+  }
+}
+
+
+static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
+                       int o1, int o2) {
+  if (op <= OPR_POW) {  /* arithmetic operator? */
+    OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD);  /* ORDER OP */
+    res->info = luaK_codeABC(fs, opc, 0, o1, o2);
+    res->k = VRELOCABLE;
+  }
+  else {  /* test operator */
+    static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE};
+    int cond = 1;
+    if (op >= OPR_GT) {  /* `>' or `>='? */
+      int temp;  /* exchange args and replace by `<' or `<=' */
+      temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
+    }
+    else if (op == OPR_NE) cond = 0;
+    res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2);
+    res->k = VJMP;
+  }
+}
+
+
+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
+  switch (op) {
+    case OPR_AND: {
+      lua_assert(e1->t == NO_JUMP);  /* list must be closed */
+      luaK_dischargevars(fs, e2);
+      luaK_concat(fs, &e1->f, e2->f);
+      e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t;
+      break;
+    }
+    case OPR_OR: {
+      lua_assert(e1->f == NO_JUMP);  /* list must be closed */
+      luaK_dischargevars(fs, e2);
+      luaK_concat(fs, &e1->t, e2->t);
+      e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f;
+      break;
+    }
+    case OPR_CONCAT: {
+      luaK_exp2val(fs, e2);
+      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
+        lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1);
+        freeexp(fs, e1);
+        SETARG_B(getcode(fs, e2), e1->info);
+        e1->k = e2->k; e1->info = e2->info;
+      }
+      else {
+        luaK_exp2nextreg(fs, e2);
+        freeexp(fs, e2);
+        freeexp(fs, e1);
+        e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info);
+        e1->k = VRELOCABLE;
+      }
+      break;
+    }
+    default: {
+      int o1 = luaK_exp2RK(fs, e1);
+      int o2 = luaK_exp2RK(fs, e2);
+      freeexp(fs, e2);
+      freeexp(fs, e1);
+      codebinop(fs, e1, op, o1, o2);
+    }
+  }
+}
+
+
+void luaK_fixline (FuncState *fs, int line) {
+  fs->f->lineinfo[fs->pc - 1] = line;
+}
+
+
+int luaK_code (FuncState *fs, Instruction i, int line) {
+  Proto *f = fs->f;
+  luaK_dischargejpc(fs);  /* `pc' will change */
+  /* put new instruction in code array */
+  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
+                  MAX_INT, "code size overflow");
+  f->code[fs->pc] = i;
+  /* save corresponding line information */
+  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
+                  MAX_INT, "code size overflow");
+  f->lineinfo[fs->pc] = line;
+  return fs->pc++;
+}
+
+
+int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
+  lua_assert(getOpMode(o) == iABC);
+  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
+}
+
+
+int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
+  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lcode.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lcode.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lcode.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lcode.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,73 @@
+/*
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lcode_h
+#define lcode_h
+
+#include "llex.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+
+
+/*
+** Marks the end of a patch list. It is an invalid value both as an absolute
+** address, and as a list link (would link an element to itself).
+*/
+#define NO_JUMP (-1)
+
+
+/*
+** grep "ORDER OPR" if you change these enums
+*/
+typedef enum BinOpr {
+  OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW,
+  OPR_CONCAT,
+  OPR_NE, OPR_EQ,
+  OPR_LT, OPR_LE, OPR_GT, OPR_GE,
+  OPR_AND, OPR_OR,
+  OPR_NOBINOPR
+} BinOpr;
+
+#define binopistest(op)	((op) >= OPR_NE)
+
+typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr;
+
+
+#define getcode(fs,e)	((fs)->f->code[(e)->info])
+
+#define luaK_codeAsBx(fs,o,A,sBx)	luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
+
+int luaK_code (FuncState *fs, Instruction i, int line);
+int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
+int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
+void luaK_fixline (FuncState *fs, int line);
+void luaK_nil (FuncState *fs, int from, int n);
+void luaK_reserveregs (FuncState *fs, int n);
+void luaK_checkstack (FuncState *fs, int n);
+int luaK_stringK (FuncState *fs, TString *s);
+int luaK_numberK (FuncState *fs, lua_Number r);
+void luaK_dischargevars (FuncState *fs, expdesc *e);
+int luaK_exp2anyreg (FuncState *fs, expdesc *e);
+void luaK_exp2nextreg (FuncState *fs, expdesc *e);
+void luaK_exp2val (FuncState *fs, expdesc *e);
+int luaK_exp2RK (FuncState *fs, expdesc *e);
+void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
+void luaK_goiftrue (FuncState *fs, expdesc *e);
+void luaK_goiffalse (FuncState *fs, expdesc *e);
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
+void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
+int luaK_jump (FuncState *fs);
+void luaK_patchlist (FuncState *fs, int list, int target);
+void luaK_patchtohere (FuncState *fs, int list);
+void luaK_concat (FuncState *fs, int *l1, int l2);
+int luaK_getlabel (FuncState *fs);
+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldblib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldblib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldblib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldblib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,298 @@
+/*
+** Interface from Lua to its debug API
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ldblib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+static void settabss (lua_State *L, const char *i, const char *v) {
+  lua_pushstring(L, i);
+  lua_pushstring(L, v);
+  lua_rawset(L, -3);
+}
+
+
+static void settabsi (lua_State *L, const char *i, int v) {
+  lua_pushstring(L, i);
+  lua_pushnumber(L, (lua_Number)v);
+  lua_rawset(L, -3);
+}
+
+
+static int getinfo (lua_State *L) {
+  lua_Debug ar;
+  const char *options = luaL_optstring(L, 2, "flnSu");
+  if (lua_isnumber(L, 1)) {
+    if (!lua_getstack(L, lua_tonumber(L, 1), &ar)) {
+      lua_pushnil(L);  /* level out of range */
+      return 1;
+    }
+  }
+  else if (lua_isfunction(L, 1)) {
+    lua_pushfstring(L, ">%s", options);
+    options = lua_tostring(L, -1);
+    lua_pushvalue(L, 1);
+  }
+  else
+    return luaL_argerror(L, 1, "function or level expected");
+  if (!lua_getinfo(L, options, &ar))
+    return luaL_argerror(L, 2, "invalid option");
+  lua_newtable(L);
+  for (; *options; options++) {
+    switch (*options) {
+      case 'S':
+        settabss(L, "source", ar.source);
+        settabss(L, "short_src", ar.short_src);
+        settabsi(L, "linedefined", ar.linedefined);
+        settabss(L, "what", ar.what);
+        break;
+      case 'l':
+        settabsi(L, "currentline", ar.currentline);
+        break;
+      case 'u':
+        settabsi(L, "nups", ar.nups);
+        break;
+      case 'n':
+        settabss(L, "name", ar.name);
+        settabss(L, "namewhat", ar.namewhat);
+        break;
+      case 'f':
+        lua_pushliteral(L, "func");
+        lua_pushvalue(L, -3);
+        lua_rawset(L, -3);
+        break;
+    }
+  }
+  return 1;  /* return table */
+}
+    
+
+static int getlocal (lua_State *L) {
+  lua_Debug ar;
+  const char *name;
+  if (!lua_getstack(L, luaL_checkint(L, 1), &ar))  /* level out of range? */
+    return luaL_argerror(L, 1, "level out of range");
+  name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
+  if (name) {
+    lua_pushstring(L, name);
+    lua_pushvalue(L, -2);
+    return 2;
+  }
+  else {
+    lua_pushnil(L);
+    return 1;
+  }
+}
+
+
+static int setlocal (lua_State *L) {
+  lua_Debug ar;
+  if (!lua_getstack(L, luaL_checkint(L, 1), &ar))  /* level out of range? */
+    return luaL_argerror(L, 1, "level out of range");
+  luaL_checkany(L, 3);
+  lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
+  return 1;
+}
+
+
+static int auxupvalue (lua_State *L, int get) {
+  const char *name;
+  int n = luaL_checkint(L, 2);
+  luaL_checktype(L, 1, LUA_TFUNCTION);
+  if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */
+  name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
+  if (name == NULL) return 0;
+  lua_pushstring(L, name);
+  lua_insert(L, -(get+1));
+  return get + 1;
+}
+
+
+static int getupvalue (lua_State *L) {
+  return auxupvalue(L, 1);
+}
+
+
+static int setupvalue (lua_State *L) {
+  luaL_checkany(L, 3);
+  return auxupvalue(L, 0);
+}
+
+
+
+static const char KEY_HOOK = 'h';
+
+
+static void hookf (lua_State *L, lua_Debug *ar) {
+  static const char *const hooknames[] =
+    {"call", "return", "line", "count", "tail return"};
+  lua_pushlightuserdata(L, &KEY_HOOK);
+  lua_rawget(L, LUA_REGISTRYINDEX);
+  if (lua_isfunction(L, -1)) {
+    lua_pushstring(L, hooknames[(int)ar->event]);
+    if (ar->currentline >= 0)
+      lua_pushnumber(L, (lua_Number)ar->currentline);
+    else lua_pushnil(L);
+    lua_assert(lua_getinfo(L, "lS", ar));
+    lua_call(L, 2, 0);
+  }
+  else
+    lua_pop(L, 1);  /* pop result from gettable */
+}
+
+
+static int makemask (const char *smask, int count) {
+  int mask = 0;
+  if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
+  if (strchr(smask, 'r')) mask |= LUA_MASKRET;
+  if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+  if (count > 0) mask |= LUA_MASKCOUNT;
+  return mask;
+}
+
+
+static char *unmakemask (int mask, char *smask) {
+  int i = 0;
+  if (mask & LUA_MASKCALL) smask[i++] = 'c';
+  if (mask & LUA_MASKRET) smask[i++] = 'r';
+  if (mask & LUA_MASKLINE) smask[i++] = 'l';
+  smask[i] = '\0';
+  return smask;
+}
+
+
+static int sethook (lua_State *L) {
+  if (lua_isnoneornil(L, 1)) {
+    lua_settop(L, 1);
+    lua_sethook(L, NULL, 0, 0);  /* turn off hooks */
+  }
+  else {
+    const char *smask = luaL_checkstring(L, 2);
+    int count = luaL_optint(L, 3, 0);
+    luaL_checktype(L, 1, LUA_TFUNCTION);
+    lua_sethook(L, hookf, makemask(smask, count), count);
+  }
+  lua_pushlightuserdata(L, &KEY_HOOK);
+  lua_pushvalue(L, 1);
+  lua_rawset(L, LUA_REGISTRYINDEX);  /* set new hook */
+  return 0;
+}
+
+
+static int gethook (lua_State *L) {
+  char buff[5];
+  int mask = lua_gethookmask(L);
+  lua_Hook hook = lua_gethook(L);
+  if (hook != NULL && hook != hookf)  /* external hook? */
+    lua_pushliteral(L, "external hook");
+  else {
+    lua_pushlightuserdata(L, &KEY_HOOK);
+    lua_rawget(L, LUA_REGISTRYINDEX);   /* get hook */
+  }
+  lua_pushstring(L, unmakemask(mask, buff));
+  lua_pushnumber(L, lua_gethookcount(L));
+  return 3;
+}
+
+
+static int debug (lua_State *L) {
+  for (;;) {
+    char buffer[250];
+    fputs("lua_debug> ", stderr);
+    if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
+        strcmp(buffer, "cont\n") == 0)
+      return 0;
+    lua_dostring(L, buffer);
+    lua_settop(L, 0);  /* remove eventual returns */
+  }
+}
+
+
+#define LEVELS1	12	/* size of the first part of the stack */
+#define LEVELS2	10	/* size of the second part of the stack */
+
+static int errorfb (lua_State *L) {
+  int level = 1;  /* skip level 0 (it's this function) */
+  int firstpart = 1;  /* still before eventual `...' */
+  lua_Debug ar;
+  if (lua_gettop(L) == 0)
+    lua_pushliteral(L, "");
+  else if (!lua_isstring(L, 1)) return 1;  /* no string message */
+  else lua_pushliteral(L, "\n");
+  lua_pushliteral(L, "stack traceback:");
+  while (lua_getstack(L, level++, &ar)) {
+    if (level > LEVELS1 && firstpart) {
+      /* no more than `LEVELS2' more levels? */
+      if (!lua_getstack(L, level+LEVELS2, &ar))
+        level--;  /* keep going */
+      else {
+        lua_pushliteral(L, "\n\t...");  /* too many levels */
+        while (lua_getstack(L, level+LEVELS2, &ar))  /* find last levels */
+          level++;
+      }
+      firstpart = 0;
+      continue;
+    }
+    lua_pushliteral(L, "\n\t");
+    lua_getinfo(L, "Snl", &ar);
+    lua_pushfstring(L, "%s:", ar.short_src);
+    if (ar.currentline > 0)
+      lua_pushfstring(L, "%d:", ar.currentline);
+    switch (*ar.namewhat) {
+      case 'g':  /* global */ 
+      case 'l':  /* local */
+      case 'f':  /* field */
+      case 'm':  /* method */
+        lua_pushfstring(L, " in function `%s'", ar.name);
+        break;
+      default: {
+        if (*ar.what == 'm')  /* main? */
+          lua_pushfstring(L, " in main chunk");
+        else if (*ar.what == 'C' || *ar.what == 't')
+          lua_pushliteral(L, " ?");  /* C function or tail call */
+        else
+          lua_pushfstring(L, " in function <%s:%d>",
+                             ar.short_src, ar.linedefined);
+      }
+    }
+    lua_concat(L, lua_gettop(L));
+  }
+  lua_concat(L, lua_gettop(L));
+  return 1;
+}
+
+
+static const luaL_reg dblib[] = {
+  {"getlocal", getlocal},
+  {"getinfo", getinfo},
+  {"gethook", gethook},
+  {"getupvalue", getupvalue},
+  {"sethook", sethook},
+  {"setlocal", setlocal},
+  {"setupvalue", setupvalue},
+  {"debug", debug},
+  {"traceback", errorfb},
+  {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_debug (lua_State *L) {
+  luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
+  lua_pushliteral(L, "_TRACEBACK");
+  lua_pushcfunction(L, errorfb);
+  lua_settable(L, LUA_GLOBALSINDEX);
+  return 1;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldebug.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldebug.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldebug.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldebug.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,583 @@
+/*
+** Debug Interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#define ldebug_c
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+static const char *getfuncname (CallInfo *ci, const char **name);
+
+
+#define isLua(ci)	(!((ci)->state & CI_C))
+
+
+static int currentpc (CallInfo *ci) {
+  if (!isLua(ci)) return -1;  /* function is not a Lua function? */
+  if (ci->state & CI_HASFRAME)  /* function has a frame? */
+    ci->u.l.savedpc = *ci->u.l.pc;  /* use `pc' from there */
+  /* function's pc is saved */
+  return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
+}
+
+
+static int currentline (CallInfo *ci) {
+  int pc = currentpc(ci);
+  if (pc < 0)
+    return -1;  /* only active lua functions have current-line information */
+  else
+    return getline(ci_func(ci)->l.p, pc);
+}
+
+
+void luaG_inithooks (lua_State *L) {
+  CallInfo *ci;
+  for (ci = L->ci; ci != L->base_ci; ci--)  /* update all `savedpc's */
+    currentpc(ci);
+  L->hookinit = 1;
+}
+
+
+/*
+** this function can be called asynchronous (e.g. during a signal)
+*/
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
+  if (func == NULL || mask == 0) {  /* turn off hooks? */
+    mask = 0;
+    func = NULL;
+  }
+  L->hook = func;
+  L->basehookcount = count;
+  resethookcount(L);
+  L->hookmask = cast(lu_byte, mask);
+  L->hookinit = 0;
+  return 1;
+}
+
+
+LUA_API lua_Hook lua_gethook (lua_State *L) {
+  return L->hook;
+}
+
+
+LUA_API int lua_gethookmask (lua_State *L) {
+  return L->hookmask;
+}
+
+
+LUA_API int lua_gethookcount (lua_State *L) {
+  return L->basehookcount;
+}
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
+  int status;
+  CallInfo *ci;
+  lua_lock(L);
+  for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
+    level--;
+    if (!(ci->state & CI_C))  /* Lua function? */
+      level -= ci->u.l.tailcalls;  /* skip lost tail calls */
+  }
+  if (level > 0 || ci == L->base_ci) status = 0;  /* there is no such level */
+  else if (level < 0) {  /* level is of a lost tail call */
+    status = 1;
+    ar->i_ci = 0;
+  }
+  else {
+    status = 1;
+    ar->i_ci = ci - L->base_ci;
+  }
+  lua_unlock(L);
+  return status;
+}
+
+
+static Proto *getluaproto (CallInfo *ci) {
+  return (isLua(ci) ? ci_func(ci)->l.p : NULL);
+}
+
+
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
+  const char *name;
+  CallInfo *ci;
+  Proto *fp;
+  lua_lock(L);
+  name = NULL;
+  ci = L->base_ci + ar->i_ci;
+  fp = getluaproto(ci);
+  if (fp) {  /* is a Lua function? */
+    name = luaF_getlocalname(fp, n, currentpc(ci));
+    if (name)
+      luaA_pushobject(L, ci->base+(n-1));  /* push value */
+  }
+  lua_unlock(L);
+  return name;
+}
+
+
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
+  const char *name;
+  CallInfo *ci;
+  Proto *fp;
+  lua_lock(L);
+  name = NULL;
+  ci = L->base_ci + ar->i_ci;
+  fp = getluaproto(ci);
+  L->top--;  /* pop new value */
+  if (fp) {  /* is a Lua function? */
+    name = luaF_getlocalname(fp, n, currentpc(ci));
+    if (!name || name[0] == '(')  /* `(' starts private locals */
+      name = NULL;
+    else
+      setobjs2s(ci->base+(n-1), L->top);
+  }
+  lua_unlock(L);
+  return name;
+}
+
+
+static void funcinfo (lua_Debug *ar, StkId func) {
+  Closure *cl = clvalue(func);
+  if (cl->c.isC) {
+    ar->source = "=[C]";
+    ar->linedefined = -1;
+    ar->what = "C";
+  }
+  else {
+    ar->source = getstr(cl->l.p->source);
+    ar->linedefined = cl->l.p->lineDefined;
+    ar->what = (ar->linedefined == 0) ? "main" : "Lua";
+  }
+  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+}
+
+
+static const char *travglobals (lua_State *L, const TObject *o) {
+  Table *g = hvalue(gt(L));
+  int i = sizenode(g);
+  while (i--) {
+    Node *n = gnode(g, i);
+    if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n)))
+      return getstr(tsvalue(gkey(n)));
+  }
+  return NULL;
+}
+
+
+static void info_tailcall (lua_State *L, lua_Debug *ar) {
+  ar->name = ar->namewhat = "";
+  ar->what = "tail";
+  ar->linedefined = ar->currentline = -1;
+  ar->source = "=(tail call)";
+  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+  ar->nups = 0;
+  setnilvalue(L->top);
+}
+
+
+static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
+                    StkId f, CallInfo *ci) {
+  int status = 1;
+  for (; *what; what++) {
+    switch (*what) {
+      case 'S': {
+        funcinfo(ar, f);
+        break;
+      }
+      case 'l': {
+        ar->currentline = (ci) ? currentline(ci) : -1;
+        break;
+      }
+      case 'u': {
+        ar->nups = clvalue(f)->c.nupvalues;
+        break;
+      }
+      case 'n': {
+        ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL;
+        if (ar->namewhat == NULL) {
+          /* try to find a global name */
+          if ((ar->name = travglobals(L, f)) != NULL)
+            ar->namewhat = "global";
+          else ar->namewhat = "";  /* not found */
+        }
+        break;
+      }
+      case 'f': {
+        setobj2s(L->top, f);
+        break;
+      }
+      default: status = 0;  /* invalid option */
+    }
+  }
+  return status;
+}
+
+
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
+  int status = 1;
+  lua_lock(L);
+  if (*what == '>') {
+    StkId f = L->top - 1;
+    if (!ttisfunction(f))
+      luaG_runerror(L, "value for `lua_getinfo' is not a function");
+    status = auxgetinfo(L, what + 1, ar, f, NULL);
+    L->top--;  /* pop function */
+  }
+  else if (ar->i_ci != 0) {  /* no tail call? */
+    CallInfo *ci = L->base_ci + ar->i_ci;
+    lua_assert(ttisfunction(ci->base - 1));
+    status = auxgetinfo(L, what, ar, ci->base - 1, ci);
+  }
+  else
+    info_tailcall(L, ar);
+  if (strchr(what, 'f')) incr_top(L);
+  lua_unlock(L);
+  return status;
+}
+
+
+/*
+** {======================================================
+** Symbolic Execution and code checker
+** =======================================================
+*/
+
+#define check(x)		if (!(x)) return 0;
+
+#define checkjump(pt,pc)	check(0 <= pc && pc < pt->sizecode)
+
+#define checkreg(pt,reg)	check((reg) < (pt)->maxstacksize)
+
+
+
+static int precheck (const Proto *pt) {
+  check(pt->maxstacksize <= MAXSTACK);
+  check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
+  lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize);
+  check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
+  return 1;
+}
+
+
+static int checkopenop (const Proto *pt, int pc) {
+  Instruction i = pt->code[pc+1];
+  switch (GET_OPCODE(i)) {
+    case OP_CALL:
+    case OP_TAILCALL:
+    case OP_RETURN: {
+      check(GETARG_B(i) == 0);
+      return 1;
+    }
+    case OP_SETLISTO: return 1;
+    default: return 0;  /* invalid instruction after an open call */
+  }
+}
+
+
+static int checkRK (const Proto *pt, int r) {
+  return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek));
+}
+
+
+static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
+  int pc;
+  int last;  /* stores position of last instruction that changed `reg' */
+  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */
+  check(precheck(pt));
+  for (pc = 0; pc < lastpc; pc++) {
+    const Instruction i = pt->code[pc];
+    OpCode op = GET_OPCODE(i);
+    int a = GETARG_A(i);
+    int b = 0;
+    int c = 0;
+    checkreg(pt, a);
+    switch (getOpMode(op)) {
+      case iABC: {
+        b = GETARG_B(i);
+        c = GETARG_C(i);
+        if (testOpMode(op, OpModeBreg)) {
+          checkreg(pt, b);
+        }
+        else if (testOpMode(op, OpModeBrk))
+          check(checkRK(pt, b));
+        if (testOpMode(op, OpModeCrk))
+          check(checkRK(pt, c));
+        break;
+      }
+      case iABx: {
+        b = GETARG_Bx(i);
+        if (testOpMode(op, OpModeK)) check(b < pt->sizek);
+        break;
+      }
+      case iAsBx: {
+        b = GETARG_sBx(i);
+        break;
+      }
+    }
+    if (testOpMode(op, OpModesetA)) {
+      if (a == reg) last = pc;  /* change register `a' */
+    }
+    if (testOpMode(op, OpModeT)) {
+      check(pc+2 < pt->sizecode);  /* check skip */
+      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
+    }
+    switch (op) {
+      case OP_LOADBOOL: {
+        check(c == 0 || pc+2 < pt->sizecode);  /* check its jump */
+        break;
+      }
+      case OP_LOADNIL: {
+        if (a <= reg && reg <= b)
+          last = pc;  /* set registers from `a' to `b' */
+        break;
+      }
+      case OP_GETUPVAL:
+      case OP_SETUPVAL: {
+        check(b < pt->nups);
+        break;
+      }
+      case OP_GETGLOBAL:
+      case OP_SETGLOBAL: {
+        check(ttisstring(&pt->k[b]));
+        break;
+      }
+      case OP_SELF: {
+        checkreg(pt, a+1);
+        if (reg == a+1) last = pc;
+        break;
+      }
+      case OP_CONCAT: {
+        /* `c' is a register, and at least two operands */
+        check(c < MAXSTACK && b < c);
+        break;
+      }
+      case OP_TFORLOOP:
+        checkreg(pt, a+c+5);
+        if (reg >= a) last = pc;  /* affect all registers above base */
+        /* go through */
+      case OP_FORLOOP:
+        checkreg(pt, a+2);
+        /* go through */
+      case OP_JMP: {
+        int dest = pc+1+b;
+	check(0 <= dest && dest < pt->sizecode);
+        /* not full check and jump is forward and do not skip `lastpc'? */
+        if (reg != NO_REG && pc < dest && dest <= lastpc)
+          pc += b;  /* do the jump */
+        break;
+      }
+      case OP_CALL:
+      case OP_TAILCALL: {
+        if (b != 0) {
+          checkreg(pt, a+b-1);
+        }
+        c--;  /* c = num. returns */
+        if (c == LUA_MULTRET) {
+          check(checkopenop(pt, pc));
+        }
+        else if (c != 0)
+          checkreg(pt, a+c-1);
+        if (reg >= a) last = pc;  /* affect all registers above base */
+        break;
+      }
+      case OP_RETURN: {
+        b--;  /* b = num. returns */
+        if (b > 0) checkreg(pt, a+b-1);
+        break;
+      }
+      case OP_SETLIST: {
+        checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1);
+        break;
+      }
+      case OP_CLOSURE: {
+        int nup;
+        check(b < pt->sizep);
+        nup = pt->p[b]->nups;
+        check(pc + nup < pt->sizecode);
+        for (; nup>0; nup--) {
+          OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
+          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
+        }
+        break;
+      }
+      default: break;
+    }
+  }
+  return pt->code[last];
+}
+
+#undef check
+#undef checkjump
+#undef checkreg
+
+/* }====================================================== */
+
+
+int luaG_checkcode (const Proto *pt) {
+  return luaG_symbexec(pt, pt->sizecode, NO_REG);
+}
+
+
+static const char *kname (Proto *p, int c) {
+  c = c - MAXSTACK;
+  if (c >= 0 && ttisstring(&p->k[c]))
+    return svalue(&p->k[c]);
+  else
+    return "?";
+}
+
+
+static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
+  if (isLua(ci)) {  /* a Lua function? */
+    Proto *p = ci_func(ci)->l.p;
+    int pc = currentpc(ci);
+    Instruction i;
+    *name = luaF_getlocalname(p, stackpos+1, pc);
+    if (*name)  /* is a local? */
+      return "local";
+    i = luaG_symbexec(p, pc, stackpos);  /* try symbolic execution */
+    lua_assert(pc != -1);
+    switch (GET_OPCODE(i)) {
+      case OP_GETGLOBAL: {
+        int g = GETARG_Bx(i);  /* global index */
+        lua_assert(ttisstring(&p->k[g]));
+        *name = svalue(&p->k[g]);
+        return "global";
+      }
+      case OP_MOVE: {
+        int a = GETARG_A(i);
+        int b = GETARG_B(i);  /* move from `b' to `a' */
+        if (b < a)
+          return getobjname(ci, b, name);  /* get name for `b' */
+        break;
+      }
+      case OP_GETTABLE: {
+        int k = GETARG_C(i);  /* key index */
+        *name = kname(p, k);
+        return "field";
+      }
+      case OP_SELF: {
+        int k = GETARG_C(i);  /* key index */
+        *name = kname(p, k);
+        return "method";
+      }
+      default: break;
+    }
+  }
+  return NULL;  /* no useful name found */
+}
+
+
+static const char *getfuncname (CallInfo *ci, const char **name) {
+  Instruction i;
+  if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1))
+    return NULL;  /* calling function is not Lua (or is unknown) */
+  ci--;  /* calling function */
+  i = ci_func(ci)->l.p->code[currentpc(ci)];
+  if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL)
+    return getobjname(ci, GETARG_A(i), name);
+  else
+    return NULL;  /* no useful name can be found */
+}
+
+
+/* only ANSI way to check whether a pointer points to an array */
+static int isinstack (CallInfo *ci, const TObject *o) {
+  StkId p;
+  for (p = ci->base; p < ci->top; p++)
+    if (o == p) return 1;
+  return 0;
+}
+
+
+void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
+  const char *name = NULL;
+  const char *t = luaT_typenames[ttype(o)];
+  const char *kind = (isinstack(L->ci, o)) ?
+                         getobjname(L->ci, o - L->base, &name) : NULL;
+  if (kind)
+    luaG_runerror(L, "attempt to %s %s `%s' (a %s value)",
+                op, kind, name, t);
+  else
+    luaG_runerror(L, "attempt to %s a %s value", op, t);
+}
+
+
+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
+  if (ttisstring(p1)) p1 = p2;
+  lua_assert(!ttisstring(p1));
+  luaG_typeerror(L, p1, "concatenate");
+}
+
+
+void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) {
+  TObject temp;
+  if (luaV_tonumber(p1, &temp) == NULL)
+    p2 = p1;  /* first operand is wrong */
+  luaG_typeerror(L, p2, "perform arithmetic on");
+}
+
+
+int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
+  const char *t1 = luaT_typenames[ttype(p1)];
+  const char *t2 = luaT_typenames[ttype(p2)];
+  if (t1[2] == t2[2])
+    luaG_runerror(L, "attempt to compare two %s values", t1);
+  else
+    luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
+}
+
+
+static void addinfo (lua_State *L, const char *msg) {
+  CallInfo *ci = L->ci;
+  if (isLua(ci)) {  /* is Lua code? */
+    char buff[LUA_IDSIZE];  /* add file:line information */
+    int line = currentline(ci);
+    luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
+    luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
+  }
+}
+
+
+void luaG_errormsg (lua_State *L) {
+  if (L->errfunc != 0) {  /* is there an error handling function? */
+    StkId errfunc = restorestack(L, L->errfunc);
+    if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
+    setobjs2s(L->top, L->top - 1);  /* move argument */
+    setobjs2s(L->top - 1, errfunc);  /* push function */
+    incr_top(L);
+    luaD_call(L, L->top - 2, 1);  /* call it */
+  }
+  luaD_throw(L, LUA_ERRRUN);
+}
+
+
+void luaG_runerror (lua_State *L, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  addinfo(L, luaO_pushvfstring(L, fmt, argp));
+  va_end(argp);
+  luaG_errormsg(L);
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldebug.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldebug.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldebug.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldebug.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,30 @@
+/*
+** Auxiliary functions from Debug Interface module
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldebug_h
+#define ldebug_h
+
+
+#include "lstate.h"
+
+
+#define pcRel(pc, p)	(cast(int, (pc) - (p)->code) - 1)
+
+#define getline(f,pc)	(((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
+
+#define resethookcount(L)	(L->hookcount = L->basehookcount)
+
+
+void luaG_inithooks (lua_State *L);
+void luaG_typeerror (lua_State *L, const TObject *o, const char *opname) __attribute__((noreturn));
+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) __attribute__((noreturn));
+void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) __attribute__((noreturn));
+int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) __attribute__((noreturn));
+void luaG_runerror (lua_State *L, const char *fmt, ...) __attribute__((noreturn));
+void luaG_errormsg (lua_State *L) __attribute__((noreturn));
+int luaG_checkcode (const Proto *pt);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldo.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldo.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldo.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldo.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,470 @@
+/*
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ldo_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+#include "lzio.h"
+
+
+
+
+/*
+** {======================================================
+** Error-recovery functions (based on long jumps)
+** =======================================================
+*/
+
+
+/* chain list of long jump buffers */
+struct lua_longjmp {
+  struct lua_longjmp *previous;
+  jmp_buf b;
+  volatile int status;  /* error code */
+};
+
+
+static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
+  switch (errcode) {
+    case LUA_ERRMEM: {
+      setsvalue2s(oldtop, luaS_new(L, MEMERRMSG));
+      break;
+    }
+    case LUA_ERRERR: {
+      setsvalue2s(oldtop, luaS_new(L, "error in error handling"));
+      break;
+    }
+    case LUA_ERRSYNTAX:
+    case LUA_ERRRUN: {
+      setobjs2s(oldtop, L->top - 1);  /* error message on current top */
+      break;
+    }
+  }
+  L->top = oldtop + 1;
+}
+
+
+void luaD_throw (lua_State *L, int errcode) {
+  if (L->errorJmp) {
+    L->errorJmp->status = errcode;
+    longjmp(L->errorJmp->b, 1);
+  }
+  else {
+    G(L)->panic(L);
+    exit(EXIT_FAILURE);
+  }
+}
+
+
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
+  struct lua_longjmp lj;
+  lj.status = 0;
+  lj.previous = L->errorJmp;  /* chain new error handler */
+  L->errorJmp = &lj;
+  if (setjmp(lj.b) == 0)
+    (*f)(L, ud);
+  L->errorJmp = lj.previous;  /* restore old error handler */
+  return lj.status;
+}
+
+
+static void restore_stack_limit (lua_State *L) {
+  L->stack_last = L->stack+L->stacksize-1;
+  if (L->size_ci > LUA_MAXCALLS) {  /* there was an overflow? */
+    int inuse = (L->ci - L->base_ci);
+    if (inuse + 1 < LUA_MAXCALLS)  /* can `undo' overflow? */
+      luaD_reallocCI(L, LUA_MAXCALLS);
+  }
+}
+
+/* }====================================================== */
+
+
+static void correctstack (lua_State *L, TObject *oldstack) {
+  CallInfo *ci;
+  GCObject *up;
+  L->top = (L->top - oldstack) + L->stack;
+  for (up = L->openupval; up != NULL; up = up->gch.next)
+    gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack;
+  for (ci = L->base_ci; ci <= L->ci; ci++) {
+    ci->top = (ci->top - oldstack) + L->stack;
+    ci->base = (ci->base - oldstack) + L->stack;
+  }
+  L->base = L->ci->base;
+}
+
+
+void luaD_reallocstack (lua_State *L, int newsize) {
+  TObject *oldstack = L->stack;
+  luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
+  L->stacksize = newsize;
+  L->stack_last = L->stack+newsize-1-EXTRA_STACK;
+  correctstack(L, oldstack);
+}
+
+
+void luaD_reallocCI (lua_State *L, int newsize) {
+  CallInfo *oldci = L->base_ci;
+  luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
+  L->size_ci = cast(unsigned short, newsize);
+  L->ci = (L->ci - oldci) + L->base_ci;
+  L->end_ci = L->base_ci + L->size_ci;
+}
+
+
+void luaD_growstack (lua_State *L, int n) {
+  if (n <= L->stacksize)  /* double size is enough? */
+    luaD_reallocstack(L, 2*L->stacksize);
+  else
+    luaD_reallocstack(L, L->stacksize + n + EXTRA_STACK);
+}
+
+
+static void luaD_growCI (lua_State *L) {
+  if (L->size_ci > LUA_MAXCALLS)  /* overflow while handling overflow? */
+    luaD_throw(L, LUA_ERRERR);
+  else {
+    luaD_reallocCI(L, 2*L->size_ci);
+    if (L->size_ci > LUA_MAXCALLS)
+      luaG_runerror(L, "stack overflow");
+  }
+}
+
+
+void luaD_callhook (lua_State *L, int event, int line) {
+  lua_Hook hook = L->hook;
+  if (hook && L->allowhook) {
+    ptrdiff_t top = savestack(L, L->top);
+    ptrdiff_t ci_top = savestack(L, L->ci->top);
+    lua_Debug ar;
+    ar.event = event;
+    ar.currentline = line;
+    if (event == LUA_HOOKTAILRET)
+      ar.i_ci = 0;  /* tail call; no debug information about it */
+    else
+      ar.i_ci = L->ci - L->base_ci;
+    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
+    L->ci->top = L->top + LUA_MINSTACK;
+    L->allowhook = 0;  /* cannot call hooks inside a hook */
+    lua_unlock(L);
+    (*hook)(L, &ar);
+    lua_lock(L);
+    lua_assert(!L->allowhook);
+    L->allowhook = 1;
+    L->ci->top = restorestack(L, ci_top);
+    L->top = restorestack(L, top);
+  }
+}
+
+
+static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
+  int i;
+  Table *htab;
+  TObject nname;
+  int actual = L->top - base;  /* actual number of arguments */
+  if (actual < nfixargs) {
+    luaD_checkstack(L, nfixargs - actual);
+    for (; actual < nfixargs; ++actual)
+      setnilvalue(L->top++);
+  }
+  actual -= nfixargs;  /* number of extra arguments */
+  htab = luaH_new(L, actual, 1);  /* create `arg' table */
+  for (i=0; i<actual; i++)  /* put extra arguments into `arg' table */
+    setobj2n(luaH_setnum(L, htab, i+1), L->top - actual + i);
+  /* store counter in field `n' */
+  setsvalue(&nname, luaS_newliteral(L, "n"));
+  setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual));
+  L->top -= actual;  /* remove extra elements from the stack */
+  sethvalue(L->top, htab);
+  incr_top(L);
+}
+
+
+static StkId tryfuncTM (lua_State *L, StkId func) {
+  const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
+  StkId p;
+  ptrdiff_t funcr = savestack(L, func);
+  if (!ttisfunction(tm))
+    luaG_typeerror(L, func, "call");
+  /* Open a hole inside the stack at `func' */
+  for (p = L->top; p > func; p--) setobjs2s(p, p-1);
+  incr_top(L);
+  func = restorestack(L, funcr);  /* previous call may change stack */
+  setobj2s(func, tm);  /* tag method is the new function to be called */
+  return func;
+}
+
+
+StkId luaD_precall (lua_State *L, StkId func) {
+  LClosure *cl;
+  ptrdiff_t funcr = savestack(L, func);
+  if (!ttisfunction(func)) /* `func' is not a function? */
+    func = tryfuncTM(L, func);  /* check the `function' tag method */
+  if (L->ci + 1 == L->end_ci) luaD_growCI(L);
+  else condhardstacktests(luaD_reallocCI(L, L->size_ci));
+  cl = &clvalue(func)->l;
+  if (!cl->isC) {  /* Lua function? prepare its call */
+    CallInfo *ci;
+    Proto *p = cl->p;
+    if (p->is_vararg)  /* varargs? */
+      adjust_varargs(L, p->numparams, func+1);
+    luaD_checkstack(L, p->maxstacksize);
+    ci = ++L->ci;  /* now `enter' new function */
+    L->base = L->ci->base = restorestack(L, funcr) + 1;
+    ci->top = L->base + p->maxstacksize;
+    ci->u.l.savedpc = p->code;  /* starting point */
+    ci->u.l.tailcalls = 0;
+    ci->state = CI_SAVEDPC;
+    while (L->top < ci->top)
+      setnilvalue(L->top++);
+    L->top = ci->top;
+    return NULL;
+  }
+  else {  /* if is a C function, call it */
+    CallInfo *ci;
+    int n;
+    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
+    ci = ++L->ci;  /* now `enter' new function */
+    L->base = L->ci->base = restorestack(L, funcr) + 1;
+    ci->top = L->top + LUA_MINSTACK;
+    ci->state = CI_C;  /* a C function */
+    if (L->hookmask & LUA_MASKCALL)
+      luaD_callhook(L, LUA_HOOKCALL, -1);
+    lua_unlock(L);
+#ifdef LUA_COMPATUPVALUES
+    lua_pushupvalues(L);
+#endif
+    n = (*clvalue(L->base - 1)->c.f)(L);  /* do the actual call */
+    lua_lock(L);
+    return L->top - n;
+  }
+}
+
+
+static StkId callrethooks (lua_State *L, StkId firstResult) {
+  ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */
+  luaD_callhook(L, LUA_HOOKRET, -1);
+  if (!(L->ci->state & CI_C)) {  /* Lua function? */
+    while (L->ci->u.l.tailcalls--)  /* call hook for eventual tail calls */
+      luaD_callhook(L, LUA_HOOKTAILRET, -1);
+  }
+  return restorestack(L, fr);
+}
+
+
+void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { 
+  StkId res;
+  if (L->hookmask & LUA_MASKRET)
+    firstResult = callrethooks(L, firstResult);
+  res = L->base - 1;  /* res == final position of 1st result */
+  L->ci--;
+  L->base = L->ci->base;  /* restore base */
+  /* move results to correct place */
+  while (wanted != 0 && firstResult < L->top) {
+    setobjs2s(res++, firstResult++);
+    wanted--;
+  }
+  while (wanted-- > 0)
+    setnilvalue(res++);
+  L->top = res;
+}
+
+
+/*
+** Call a function (C or Lua). The function to be called is at *func.
+** The arguments are on the stack, right after the function.
+** When returns, all the results are on the stack, starting at the original
+** function position.
+*/ 
+void luaD_call (lua_State *L, StkId func, int nResults) {
+  StkId firstResult;
+  lua_assert(!(L->ci->state & CI_CALLING));
+  if (++L->nCcalls >= LUA_MAXCCALLS) {
+    if (L->nCcalls == LUA_MAXCCALLS)
+      luaG_runerror(L, "C stack overflow");
+    else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3)))
+      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
+  }
+  firstResult = luaD_precall(L, func);
+  if (firstResult == NULL)  /* is a Lua function? */
+    firstResult = luaV_execute(L);  /* call it */
+  luaD_poscall(L, nResults, firstResult);
+  L->nCcalls--;
+  luaC_checkGC(L);
+}
+
+
+static void resume (lua_State *L, void *ud) {
+  StkId firstResult;
+  int nargs = *cast(int *, ud);
+  CallInfo *ci = L->ci;
+  if (ci == L->base_ci) {  /* no activation record? */
+    lua_assert(nargs < L->top - L->base);
+    luaD_precall(L, L->top - (nargs + 1));  /* start coroutine */
+  }
+  else {  /* inside a yield */
+    lua_assert(ci->state & CI_YIELD);
+    if (ci->state & CI_C) {  /* `common' yield? */
+      /* finish interrupted execution of `OP_CALL' */
+      int nresults;
+      lua_assert((ci-1)->state & CI_SAVEDPC);
+      lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
+                 GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
+      nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
+      luaD_poscall(L, nresults, L->top - nargs);  /* complete it */
+      if (nresults >= 0) L->top = L->ci->top;
+    }
+    else {  /* yielded inside a hook: just continue its execution */
+      ci->state &= ~CI_YIELD;
+    }
+  }
+  firstResult = luaV_execute(L);
+  if (firstResult != NULL)   /* return? */
+    luaD_poscall(L, LUA_MULTRET, firstResult);  /* finalize this coroutine */
+}
+
+
+static int resume_error (lua_State *L, const char *msg) {
+  L->top = L->ci->base;
+  setsvalue2s(L->top, luaS_new(L, msg));
+  incr_top(L);
+  lua_unlock(L);
+  return LUA_ERRRUN;
+}
+
+
+LUA_API int lua_resume (lua_State *L, int nargs) {
+  int status;
+  lu_byte old_allowhooks;
+  lua_lock(L);
+  if (L->ci == L->base_ci) {
+    if (nargs >= L->top - L->base)
+      return resume_error(L, "cannot resume dead coroutine");
+  }
+  else if (!(L->ci->state & CI_YIELD))  /* not inside a yield? */
+    return resume_error(L, "cannot resume non-suspended coroutine");
+  old_allowhooks = L->allowhook;
+  lua_assert(L->errfunc == 0 && L->nCcalls == 0);
+  status = luaD_rawrunprotected(L, resume, &nargs);
+  if (status != 0) {  /* error? */
+    L->ci = L->base_ci;  /* go back to initial level */
+    L->base = L->ci->base;
+    L->nCcalls = 0;
+    luaF_close(L, L->base);  /* close eventual pending closures */
+    seterrorobj(L, status, L->base);
+    L->allowhook = old_allowhooks;
+    restore_stack_limit(L);
+  }
+  lua_unlock(L);
+  return status;
+}
+
+
+LUA_API int lua_yield (lua_State *L, int nresults) {
+  CallInfo *ci;
+  lua_lock(L);
+  ci = L->ci;
+  if (L->nCcalls > 0)
+    luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
+  if (ci->state & CI_C) {  /* usual yield */
+    if ((ci-1)->state & CI_C)
+      luaG_runerror(L, "cannot yield a C function");
+    if (L->top - nresults > L->base) {  /* is there garbage in the stack? */
+      int i;
+      for (i=0; i<nresults; i++)  /* move down results */
+        setobjs2s(L->base + i, L->top - nresults + i);
+      L->top = L->base + nresults;
+    }
+  } /* else it's an yield inside a hook: nothing to do */
+  ci->state |= CI_YIELD;
+  lua_unlock(L);
+  return -1;
+}
+
+
+int luaD_pcall (lua_State *L, Pfunc func, void *u,
+                ptrdiff_t old_top, ptrdiff_t ef) {
+  int status;
+  unsigned short oldnCcalls = L->nCcalls;
+  ptrdiff_t old_ci = saveci(L, L->ci);
+  lu_byte old_allowhooks = L->allowhook;
+  ptrdiff_t old_errfunc = L->errfunc;
+  L->errfunc = ef;
+  status = luaD_rawrunprotected(L, func, u);
+  if (status != 0) {  /* an error occurred? */
+    StkId oldtop = restorestack(L, old_top);
+    luaF_close(L, oldtop);  /* close eventual pending closures */
+    seterrorobj(L, status, oldtop);
+    L->nCcalls = oldnCcalls;
+    L->ci = restoreci(L, old_ci);
+    L->base = L->ci->base;
+    L->allowhook = old_allowhooks;
+    restore_stack_limit(L);
+  }
+  L->errfunc = old_errfunc;
+  return status;
+}
+
+
+
+/*
+** Execute a protected parser.
+*/
+struct SParser {  /* data to `f_parser' */
+  ZIO *z;
+  Mbuffer buff;  /* buffer to be used by the scanner */
+  int bin;
+};
+
+static void f_parser (lua_State *L, void *ud) {
+  struct SParser *p;
+  Proto *tf;
+  Closure *cl;
+  luaC_checkGC(L);
+  p = cast(struct SParser *, ud);
+  tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff);
+  cl = luaF_newLclosure(L, 0, gt(L));
+  cl->l.p = tf;
+  setclvalue(L->top, cl);
+  incr_top(L);
+}
+
+
+int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
+  struct SParser p;
+  int status;
+  ptrdiff_t oldtopr = savestack(L, L->top);  /* save current top */
+  p.z = z; p.bin = bin;
+  luaZ_initbuffer(L, &p.buff);
+  status = luaD_rawrunprotected(L, f_parser, &p);
+  luaZ_freebuffer(L, &p.buff);
+  if (status != 0) {  /* error? */
+    StkId oldtop = restorestack(L, oldtopr);
+    seterrorobj(L, status, oldtop);
+  }
+  return status;
+}
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldo.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldo.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldo.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldo.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,59 @@
+/*
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldo_h
+#define ldo_h
+
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+/*
+** macro to control inclusion of some hard tests on stack reallocation
+*/ 
+#ifndef HARDSTACKTESTS
+#define condhardstacktests(x)	{ /* empty */ }
+#else
+#define condhardstacktests(x)	x
+#endif
+
+
+#define luaD_checkstack(L,n)	\
+  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \
+    luaD_growstack(L, n); \
+  else condhardstacktests(luaD_reallocstack(L, L->stacksize));
+
+
+#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
+
+#define savestack(L,p)		((char *)(p) - (char *)L->stack)
+#define restorestack(L,n)	((TObject *)((char *)L->stack + (n)))
+
+#define saveci(L,p)		((char *)(p) - (char *)L->base_ci)
+#define restoreci(L,n)		((CallInfo *)((char *)L->base_ci + (n)))
+
+
+/* type of protected functions, to be ran by `runprotected' */
+typedef void (*Pfunc) (lua_State *L, void *ud);
+
+void luaD_resetprotection (lua_State *L);
+int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
+void luaD_callhook (lua_State *L, int event, int line);
+StkId luaD_precall (lua_State *L, StkId func);
+void luaD_call (lua_State *L, StkId func, int nResults);
+int luaD_pcall (lua_State *L, Pfunc func, void *u,
+                ptrdiff_t oldtop, ptrdiff_t ef);
+void luaD_poscall (lua_State *L, int wanted, StkId firstResult);
+void luaD_reallocCI (lua_State *L, int newsize);
+void luaD_reallocstack (lua_State *L, int newsize);
+void luaD_growstack (lua_State *L, int n);
+
+void luaD_throw (lua_State *L, int errcode) __attribute__((noreturn));
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldump.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldump.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ldump.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ldump.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,169 @@
+/*
+** save bytecodes
+** See Copyright Notice in lua.h
+*/
+
+#include <stddef.h>
+
+#define ldump_c
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lundump.h"
+
+#define DumpVector(b,n,size,D)	DumpBlock(b,(n)*(size),D)
+#define DumpLiteral(s,D)	DumpBlock("" s,(sizeof(s))-1,D)
+
+typedef struct {
+ lua_State* L;
+ lua_Chunkwriter write;
+ void* data;
+} DumpState;
+
+static void DumpBlock(const void* b, size_t size, DumpState* D)
+{
+ lua_unlock(D->L);
+ (*D->write)(D->L,b,size,D->data);
+ lua_lock(D->L);
+}
+
+static void DumpByte(int y, DumpState* D)
+{
+ char x=(char)y;
+ DumpBlock(&x,sizeof(x),D);
+}
+
+static void DumpInt(int x, DumpState* D)
+{
+ DumpBlock(&x,sizeof(x),D);
+}
+
+static void DumpSize(size_t x, DumpState* D)
+{
+ DumpBlock(&x,sizeof(x),D);
+}
+
+static void DumpNumber(lua_Number x, DumpState* D)
+{
+ DumpBlock(&x,sizeof(x),D);
+}
+
+static void DumpString(TString* s, DumpState* D)
+{
+ if (s==NULL || getstr(s)==NULL)
+  DumpSize(0,D);
+ else
+ {
+  size_t size=s->tsv.len+1;		/* include trailing '\0' */
+  DumpSize(size,D);
+  DumpBlock(getstr(s),size,D);
+ }
+}
+
+static void DumpCode(const Proto* f, DumpState* D)
+{
+ DumpInt(f->sizecode,D);
+ DumpVector(f->code,f->sizecode,sizeof(*f->code),D);
+}
+
+static void DumpLocals(const Proto* f, DumpState* D)
+{
+ int i,n=f->sizelocvars;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+  DumpString(f->locvars[i].varname,D);
+  DumpInt(f->locvars[i].startpc,D);
+  DumpInt(f->locvars[i].endpc,D);
+ }
+}
+
+static void DumpLines(const Proto* f, DumpState* D)
+{
+ DumpInt(f->sizelineinfo,D);
+ DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D);
+}
+
+static void DumpUpvalues(const Proto* f, DumpState* D)
+{
+ int i,n=f->sizeupvalues;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
+}
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
+
+static void DumpConstants(const Proto* f, DumpState* D)
+{
+ int i,n;
+ DumpInt(n=f->sizek,D);
+ for (i=0; i<n; i++)
+ {
+  const TObject* o=&f->k[i];
+  DumpByte(ttype(o),D);
+  switch (ttype(o))
+  {
+   case LUA_TNUMBER:
+	DumpNumber(nvalue(o),D);
+	break;
+   case LUA_TSTRING:
+	DumpString(tsvalue(o),D);
+	break;
+   case LUA_TNIL:
+	break;
+   default:
+	lua_assert(0);			/* cannot happen */
+	break;
+  }
+ }
+ DumpInt(n=f->sizep,D);
+ for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
+}
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
+{
+ DumpString((f->source==p) ? NULL : f->source,D);
+ DumpInt(f->lineDefined,D);
+ DumpByte(f->nups,D);
+ DumpByte(f->numparams,D);
+ DumpByte(f->is_vararg,D);
+ DumpByte(f->maxstacksize,D);
+ DumpLines(f,D);
+ DumpLocals(f,D);
+ DumpUpvalues(f,D);
+ DumpConstants(f,D);
+ DumpCode(f,D);
+}
+
+static void DumpHeader(DumpState* D)
+{
+ DumpLiteral(LUA_SIGNATURE,D);
+ DumpByte(VERSION,D);
+ DumpByte(luaU_endianness(),D);
+ DumpByte(sizeof(int),D);
+ DumpByte(sizeof(size_t),D);
+ DumpByte(sizeof(Instruction),D);
+ DumpByte(SIZE_OP,D);
+ DumpByte(SIZE_A,D);
+ DumpByte(SIZE_B,D);
+ DumpByte(SIZE_C,D);
+ DumpByte(sizeof(lua_Number),D);
+ DumpNumber(TEST_NUMBER,D);
+}
+
+/*
+** dump function as precompiled chunk
+*/
+void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data)
+{
+ DumpState D;
+ D.L=L;
+ D.write=w;
+ D.data=data;
+ DumpHeader(&D);
+ DumpFunction(Main,NULL,&D);
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lfunc.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lfunc.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lfunc.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lfunc.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,134 @@
+/*
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+
+#define lfunc_c
+
+#include "lua.h"
+
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+#define sizeCclosure(n)	(cast(int, sizeof(CClosure)) + \
+                         cast(int, sizeof(TObject)*((n)-1)))
+
+#define sizeLclosure(n)	(cast(int, sizeof(LClosure)) + \
+                         cast(int, sizeof(TObject *)*((n)-1)))
+
+
+
+Closure *luaF_newCclosure (lua_State *L, int nelems) {
+  Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
+  luaC_link(L, valtogco(c), LUA_TFUNCTION);
+  c->c.isC = 1;
+  c->c.nupvalues = cast(lu_byte, nelems);
+  return c;
+}
+
+
+Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) {
+  Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
+  luaC_link(L, valtogco(c), LUA_TFUNCTION);
+  c->l.isC = 0;
+  c->l.g = *e;
+  c->l.nupvalues = cast(lu_byte, nelems);
+  return c;
+}
+
+
+UpVal *luaF_findupval (lua_State *L, StkId level) {
+  GCObject **pp = &L->openupval;
+  UpVal *p;
+  UpVal *v;
+  while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
+    if (p->v == level) return p;
+    pp = &p->next;
+  }
+  v = luaM_new(L, UpVal);  /* not found: create a new one */
+  v->tt = LUA_TUPVAL;
+  v->marked = 1;  /* open upvalues should not be collected */
+  v->v = level;  /* current value lives in the stack */
+  v->next = *pp;  /* chain it in the proper position */
+  *pp = valtogco(v);
+  return v;
+}
+
+
+void luaF_close (lua_State *L, StkId level) {
+  UpVal *p;
+  while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) {
+    setobj(&p->value, p->v);  /* save current value (write barrier) */
+    p->v = &p->value;  /* now current value lives here */
+    L->openupval = p->next;  /* remove from `open' list */
+    luaC_link(L, valtogco(p), LUA_TUPVAL);
+  }
+}
+
+
+Proto *luaF_newproto (lua_State *L) {
+  Proto *f = luaM_new(L, Proto);
+  luaC_link(L, valtogco(f), LUA_TPROTO);
+  f->k = NULL;
+  f->sizek = 0;
+  f->p = NULL;
+  f->sizep = 0;
+  f->code = NULL;
+  f->sizecode = 0;
+  f->sizelineinfo = 0;
+  f->sizeupvalues = 0;
+  f->nups = 0;
+  f->upvalues = NULL;
+  f->numparams = 0;
+  f->is_vararg = 0;
+  f->maxstacksize = 0;
+  f->lineinfo = NULL;
+  f->sizelocvars = 0;
+  f->locvars = NULL;
+  f->lineDefined = 0;
+  f->source = NULL;
+  return f;
+}
+
+
+void luaF_freeproto (lua_State *L, Proto *f) {
+  luaM_freearray(L, f->code, f->sizecode, Instruction);
+  luaM_freearray(L, f->p, f->sizep, Proto *);
+  luaM_freearray(L, f->k, f->sizek, TObject);
+  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
+  luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
+  luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
+  luaM_freelem(L, f);
+}
+
+
+void luaF_freeclosure (lua_State *L, Closure *c) {
+  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
+                          sizeLclosure(c->l.nupvalues);
+  luaM_free(L, c, size);
+}
+
+
+/*
+** Look for n-th local variable at line `line' in function `func'.
+** Returns NULL if not found.
+*/
+const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
+  int i;
+  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
+    if (pc < f->locvars[i].endpc) {  /* is variable active? */
+      local_number--;
+      if (local_number == 0)
+        return getstr(f->locvars[i].varname);
+    }
+  }
+  return NULL;  /* not found */
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lfunc.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lfunc.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lfunc.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lfunc.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,24 @@
+/*
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lfunc_h
+#define lfunc_h
+
+
+#include "lobject.h"
+
+
+Proto *luaF_newproto (lua_State *L);
+Closure *luaF_newCclosure (lua_State *L, int nelems);
+Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e);
+UpVal *luaF_findupval (lua_State *L, StkId level);
+void luaF_close (lua_State *L, StkId level);
+void luaF_freeproto (lua_State *L, Proto *f);
+void luaF_freeclosure (lua_State *L, Closure *c);
+
+const char *luaF_getlocalname (const Proto *func, int local_number, int pc);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lgc.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lgc.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lgc.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lgc.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,497 @@
+/*
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#include <string.h>
+
+#define lgc_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+typedef struct GCState {
+  GCObject *tmark;  /* list of marked objects to be traversed */
+  GCObject *wk;  /* list of traversed key-weak tables (to be cleared) */
+  GCObject *wv;  /* list of traversed value-weak tables */
+  GCObject *wkv;  /* list of traversed key-value weak tables */
+  global_State *g;
+} GCState;
+
+
+/*
+** some userful bit tricks
+*/
+#define setbit(x,b)	((x) |= (1<<(b)))
+#define resetbit(x,b)	((x) &= cast(lu_byte, ~(1<<(b))))
+#define testbit(x,b)	((x) & (1<<(b)))
+
+#define unmark(x)	resetbit((x)->gch.marked, 0)
+#define ismarked(x)	((x)->gch.marked & ((1<<4)|1))
+
+#define stringmark(s)	setbit((s)->tsv.marked, 0)
+
+
+#define isfinalized(u)		(!testbit((u)->uv.marked, 1))
+#define markfinalized(u)	resetbit((u)->uv.marked, 1)
+
+
+#define KEYWEAKBIT    1
+#define VALUEWEAKBIT  2
+#define KEYWEAK         (1<<KEYWEAKBIT)
+#define VALUEWEAK       (1<<VALUEWEAKBIT)
+
+
+
+#define markobject(st,o) { checkconsistency(o); \
+  if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); }
+
+#define condmarkobject(st,o,c) { checkconsistency(o); \
+  if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \
+    reallymarkobject(st,gcvalue(o)); }
+
+#define markvalue(st,t) { if (!ismarked(valtogco(t))) \
+		reallymarkobject(st, valtogco(t)); }
+
+
+
+static void reallymarkobject (GCState *st, GCObject *o) {
+  lua_assert(!ismarked(o));
+  setbit(o->gch.marked, 0);  /* mark object */
+  switch (o->gch.tt) {
+    case LUA_TUSERDATA: {
+      markvalue(st, gcotou(o)->uv.metatable);
+      break;
+    }
+    case LUA_TFUNCTION: {
+      gcotocl(o)->c.gclist = st->tmark;
+      st->tmark = o;
+      break;
+    }
+    case LUA_TTABLE: {
+      gcotoh(o)->gclist = st->tmark;
+      st->tmark = o;
+      break;
+    }
+    case LUA_TTHREAD: {
+      gcototh(o)->gclist = st->tmark;
+      st->tmark = o;
+      break;
+    }
+    case LUA_TPROTO: {
+      gcotop(o)->gclist = st->tmark;
+      st->tmark = o;
+      break;
+    }
+    default: lua_assert(o->gch.tt == LUA_TSTRING);
+  }
+}
+
+
+static void marktmu (GCState *st) {
+  GCObject *u;
+  for (u = st->g->tmudata; u; u = u->gch.next) {
+    unmark(u);  /* may be marked, if left from previous GC */
+    reallymarkobject(st, u);
+  }
+}
+
+
+/* move `dead' udata that need finalization to list `tmudata' */
+size_t luaC_separateudata (lua_State *L) {
+  size_t deadmem = 0;
+  GCObject **p = &G(L)->rootudata;
+  GCObject *curr;
+  GCObject *collected = NULL;  /* to collect udata with gc event */
+  GCObject **lastcollected = &collected;
+  while ((curr = *p) != NULL) {
+    lua_assert(curr->gch.tt == LUA_TUSERDATA);
+    if (ismarked(curr) || isfinalized(gcotou(curr)))
+      p = &curr->gch.next;  /* don't bother with them */
+
+    else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) {
+      markfinalized(gcotou(curr));  /* don't need finalization */
+      p = &curr->gch.next;
+    }
+    else {  /* must call its gc method */
+      deadmem += sizeudata(gcotou(curr)->uv.len);
+      *p = curr->gch.next;
+      curr->gch.next = NULL;  /* link `curr' at the end of `collected' list */
+      *lastcollected = curr;
+      lastcollected = &curr->gch.next;
+    }
+  }
+  /* insert collected udata with gc event into `tmudata' list */
+  *lastcollected = G(L)->tmudata;
+  G(L)->tmudata = collected;
+  return deadmem;
+}
+
+
+static void removekey (Node *n) {
+  setnilvalue(gval(n));  /* remove corresponding value ... */
+  if (iscollectable(gkey(n)))
+    setttype(gkey(n), LUA_TNONE);  /* dead key; remove it */
+}
+
+
+static void traversetable (GCState *st, Table *h) {
+  int i;
+  int weakkey = 0;
+  int weakvalue = 0;
+  const TObject *mode;
+  markvalue(st, h->metatable);
+  lua_assert(h->lsizenode || h->node == st->g->dummynode);
+  mode = gfasttm(st->g, h->metatable, TM_MODE);
+  if (mode && ttisstring(mode)) {  /* is there a weak mode? */
+    weakkey = (strchr(svalue(mode), 'k') != NULL);
+    weakvalue = (strchr(svalue(mode), 'v') != NULL);
+    if (weakkey || weakvalue) {  /* is really weak? */
+      GCObject **weaklist;
+      h->marked &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */
+      h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) |
+                                 (weakvalue << VALUEWEAKBIT));
+      weaklist = (weakkey && weakvalue) ? &st->wkv :
+                              (weakkey) ? &st->wk :
+                                          &st->wv;
+      h->gclist = *weaklist;  /* must be cleared after GC, ... */
+      *weaklist = valtogco(h);  /* ... so put in the appropriate list */
+    }
+  }
+  if (!weakvalue) {
+    i = h->sizearray;
+    while (i--)
+      markobject(st, &h->array[i]);
+  }
+  i = sizenode(h);
+  while (i--) {
+    Node *n = gnode(h, i);
+    if (!ttisnil(gval(n))) {
+      lua_assert(!ttisnil(gkey(n)));
+      condmarkobject(st, gkey(n), !weakkey);
+      condmarkobject(st, gval(n), !weakvalue);
+    }
+  }
+}
+
+
+static void traverseproto (GCState *st, Proto *f) {
+  int i;
+  stringmark(f->source);
+  for (i=0; i<f->sizek; i++) {  /* mark literal strings */
+    if (ttisstring(f->k+i))
+      stringmark(tsvalue(f->k+i));
+  }
+  for (i=0; i<f->sizeupvalues; i++)  /* mark upvalue names */
+    stringmark(f->upvalues[i]);
+  for (i=0; i<f->sizep; i++)  /* mark nested protos */
+    markvalue(st, f->p[i]);
+  for (i=0; i<f->sizelocvars; i++)  /* mark local-variable names */
+    stringmark(f->locvars[i].varname);
+  lua_assert(luaG_checkcode(f));
+}
+
+
+
+static void traverseclosure (GCState *st, Closure *cl) {
+  if (cl->c.isC) {
+    int i;
+    for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */
+      markobject(st, &cl->c.upvalue[i]);
+  }
+  else {
+    int i;
+    lua_assert(cl->l.nupvalues == cl->l.p->nups);
+    markvalue(st, hvalue(&cl->l.g));
+    markvalue(st, cl->l.p);
+    for (i=0; i<cl->l.nupvalues; i++) {  /* mark its upvalues */
+      UpVal *u = cl->l.upvals[i];
+      if (!u->marked) {
+        markobject(st, &u->value);
+        u->marked = 1;
+      }
+    }
+  }
+}
+
+
+static void checkstacksizes (lua_State *L, StkId max) {
+  int used = L->ci - L->base_ci;  /* number of `ci' in use */
+  if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
+    luaD_reallocCI(L, L->size_ci/2);  /* still big enough... */
+  else condhardstacktests(luaD_reallocCI(L, L->size_ci));
+  used = max - L->stack;  /* part of stack in use */
+  if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
+    luaD_reallocstack(L, L->stacksize/2);  /* still big enough... */
+  else condhardstacktests(luaD_reallocstack(L, L->stacksize));
+}
+
+
+static void traversestack (GCState *st, lua_State *L1) {
+  StkId o, lim;
+  CallInfo *ci;
+  markobject(st, gt(L1));
+  lim = L1->top;
+  for (ci = L1->base_ci; ci <= L1->ci; ci++) {
+    lua_assert(ci->top <= L1->stack_last);
+    lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC));
+    if (lim < ci->top)
+      lim = ci->top;
+  }
+  for (o = L1->stack; o < L1->top; o++)
+    markobject(st, o);
+  for (; o <= lim; o++)
+    setnilvalue(o);
+  checkstacksizes(L1, lim);
+}
+
+
+static void propagatemarks (GCState *st) {
+  while (st->tmark) {  /* traverse marked objects */
+    switch (st->tmark->gch.tt) {
+      case LUA_TTABLE: {
+        Table *h = gcotoh(st->tmark);
+        st->tmark = h->gclist;
+        traversetable(st, h);
+        break;
+      }
+      case LUA_TFUNCTION: {
+        Closure *cl = gcotocl(st->tmark);
+        st->tmark = cl->c.gclist;
+        traverseclosure(st, cl);
+        break;
+      }
+      case LUA_TTHREAD: {
+        lua_State *th = gcototh(st->tmark);
+        st->tmark = th->gclist;
+        traversestack(st, th);
+        break;
+      }
+      case LUA_TPROTO: {
+        Proto *p = gcotop(st->tmark);
+        st->tmark = p->gclist;
+        traverseproto(st, p);
+        break;
+      }
+      default: lua_assert(0);
+    }
+  }
+}
+
+
+static int valismarked (const TObject *o) {
+  if (ttisstring(o))
+    stringmark(tsvalue(o));  /* strings are `values', so are never weak */
+  return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0);
+}
+
+
+/*
+** clear collected keys from weaktables
+*/
+static void cleartablekeys (GCObject *l) {
+  while (l) {
+    Table *h = gcotoh(l);
+    int i = sizenode(h);
+    lua_assert(h->marked & KEYWEAK);
+    while (i--) {
+      Node *n = gnode(h, i);
+      if (!valismarked(gkey(n)))  /* key was collected? */
+        removekey(n);  /* remove entry from table */
+    }
+    l = h->gclist;
+  }
+}
+
+
+/*
+** clear collected values from weaktables
+*/
+static void cleartablevalues (GCObject *l) {
+  while (l) {
+    Table *h = gcotoh(l);
+    int i = h->sizearray;
+    lua_assert(h->marked & VALUEWEAK);
+    while (i--) {
+      TObject *o = &h->array[i];
+      if (!valismarked(o))  /* value was collected? */
+        setnilvalue(o);  /* remove value */
+    }
+    i = sizenode(h);
+    while (i--) {
+      Node *n = gnode(h, i);
+      if (!valismarked(gval(n)))  /* value was collected? */
+        removekey(n);  /* remove entry from table */
+    }
+    l = h->gclist;
+  }
+}
+
+
+static void freeobj (lua_State *L, GCObject *o) {
+  switch (o->gch.tt) {
+    case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break;
+    case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break;
+    case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break;
+    case LUA_TTABLE: luaH_free(L, gcotoh(o)); break;
+    case LUA_TTHREAD: {
+      lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread);
+      luaE_freethread(L, gcototh(o));
+      break;
+    }
+    case LUA_TSTRING: {
+      luaM_free(L, o, sizestring(gcotots(o)->tsv.len));
+      break;
+    }
+    case LUA_TUSERDATA: {
+      luaM_free(L, o, sizeudata(gcotou(o)->uv.len));
+      break;
+    }
+    default: lua_assert(0);
+  }
+}
+
+
+static int sweeplist (lua_State *L, GCObject **p, int limit) {
+  GCObject *curr;
+  int count = 0;  /* number of collected items */
+  while ((curr = *p) != NULL) {
+    if (curr->gch.marked > limit) {
+      unmark(curr);
+      p = &curr->gch.next;
+    }
+    else {
+      count++;
+      *p = curr->gch.next;
+      freeobj(L, curr);
+    }
+  }
+  return count;
+}
+
+
+static void sweepstrings (lua_State *L, int all) {
+  int i;
+  for (i=0; i<G(L)->strt.size; i++) {  /* for each list */
+    G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all);
+  }
+}
+
+
+static void checkSizes (lua_State *L, size_t deadmem) {
+  /* check size of string hash */
+  if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
+      G(L)->strt.size > MINSTRTABSIZE*2)
+    luaS_resize(L, G(L)->strt.size/2);  /* table is too big */
+  /* check size of buffer */
+  if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */
+    size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
+    luaZ_resizebuffer(L, &G(L)->buff, newsize);
+  }
+  G(L)->GCthreshold = 2*G(L)->nblocks - deadmem;  /* new threshold */
+}
+
+
+static void do1gcTM (lua_State *L, Udata *udata) {
+  const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC);
+  if (tm != NULL) {
+    setobj2s(L->top, tm);
+    setuvalue(L->top+1, udata);
+    L->top += 2;
+    luaD_call(L, L->top - 2, 0);
+  }
+}
+
+
+void luaC_callGCTM (lua_State *L) {
+  lu_byte oldah = L->allowhook;
+  L->allowhook = 0;  /* stop debug hooks during GC tag methods */
+  L->top++;  /* reserve space to keep udata while runs its gc method */
+  while (G(L)->tmudata != NULL) {
+    GCObject *o = G(L)->tmudata;
+    Udata *udata = gcotou(o);
+    G(L)->tmudata = udata->uv.next;  /* remove udata from `tmudata' */
+    udata->uv.next = G(L)->rootudata;  /* return it to `root' list */
+    G(L)->rootudata = o;
+    setuvalue(L->top - 1, udata);  /* keep a reference to it */
+    unmark(o);
+    markfinalized(udata);
+    do1gcTM(L, udata);
+  }
+  L->top--;
+  L->allowhook = oldah;  /* restore hooks */
+}
+
+
+void luaC_sweep (lua_State *L, int all) {
+  if (all) all = 256;  /* larger than any mark */
+  sweeplist(L, &G(L)->rootudata, all);
+  sweepstrings(L, all);
+  sweeplist(L, &G(L)->rootgc, all);
+}
+
+
+/* mark root set */
+static void markroot (GCState *st, lua_State *L) {
+  global_State *g = st->g;
+  markobject(st, defaultmeta(L));
+  markobject(st, registry(L));
+  traversestack(st, g->mainthread);
+  if (L != g->mainthread)  /* another thread is running? */
+    markvalue(st, L);  /* cannot collect it */
+}
+
+
+static size_t mark (lua_State *L) {
+  size_t deadmem;
+  GCState st;
+  GCObject *wkv;
+  st.g = G(L);
+  st.tmark = NULL;
+  st.wkv = st.wk = st.wv = NULL;
+  markroot(&st, L);
+  propagatemarks(&st);  /* mark all reachable objects */
+  cleartablevalues(st.wkv);
+  cleartablevalues(st.wv);
+  wkv = st.wkv;  /* keys must be cleared after preserving udata */
+  st.wkv = NULL;
+  st.wv = NULL;
+  deadmem = luaC_separateudata(L);  /* separate userdata to be preserved */
+  marktmu(&st);  /* mark `preserved' userdata */
+  propagatemarks(&st);  /* remark, to propagate `preserveness' */
+  cleartablekeys(wkv);
+  /* `propagatemarks' may resuscitate some weak tables; clear them too */
+  cleartablekeys(st.wk);
+  cleartablevalues(st.wv);
+  cleartablekeys(st.wkv);
+  cleartablevalues(st.wkv);
+  return deadmem;
+}
+
+
+void luaC_collectgarbage (lua_State *L) {
+  size_t deadmem = mark(L);
+  luaC_sweep(L, 0);
+  checkSizes(L, deadmem);
+  luaC_callGCTM(L);
+}
+
+
+void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
+  o->gch.next = G(L)->rootgc;
+  G(L)->rootgc = o;
+  o->gch.marked = 0;
+  o->gch.tt = tt;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lgc.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lgc.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lgc.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lgc.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,24 @@
+/*
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lgc_h
+#define lgc_h
+
+
+#include "lobject.h"
+
+
+#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \
+	if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); }
+
+
+size_t luaC_separateudata (lua_State *L);
+void luaC_callGCTM (lua_State *L);
+void luaC_sweep (lua_State *L, int all);
+void luaC_collectgarbage (lua_State *L);
+void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/liolib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/liolib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/liolib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/liolib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,755 @@
+/*
+** Standard I/O (and system) library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define liolib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+/*
+** by default, gcc does not get `tmpname'
+*/
+#ifndef USE_TMPNAME
+#ifdef __GNUC__
+#define USE_TMPNAME	0
+#else
+#define USE_TMPNAME	1
+#endif
+#endif
+
+
+/*
+** by default, posix systems get `popen'
+*/
+#ifndef USE_POPEN
+#ifdef _POSIX_C_SOURCE
+#if _POSIX_C_SOURCE >= 2
+#define USE_POPEN	1
+#endif
+#endif
+#endif
+
+#ifndef USE_POPEN
+#define USE_POPEN	0
+#endif
+
+
+
+static int io_exit (lua_State *L) __attribute__((noreturn));
+
+
+/*
+** {======================================================
+** FILE Operations
+** =======================================================
+*/
+
+
+#if !USE_POPEN
+#define pclose(f)    (-1)
+#endif
+
+
+#define FILEHANDLE		"FILE*"
+
+#define IO_INPUT		"_input"
+#define IO_OUTPUT		"_output"
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+  if (i) {
+    lua_pushboolean(L, 1);
+    return 1;
+  }
+  else {
+    lua_pushnil(L);
+    if (filename)
+      lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+    else
+      lua_pushfstring(L, "%s", strerror(errno));
+    lua_pushnumber(L, errno);
+    return 3;
+  }
+}
+
+
+static FILE **topfile (lua_State *L, int findex) {
+  FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE);
+  if (f == NULL) luaL_argerror(L, findex, "bad file");
+  return f;
+}
+
+
+static int io_type (lua_State *L) {
+  FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE);
+  if (f == NULL) lua_pushnil(L);
+  else if (*f == NULL)
+    lua_pushliteral(L, "closed file");
+  else
+    lua_pushliteral(L, "file");
+  return 1;
+}
+
+
+static FILE *tofile (lua_State *L, int findex) {
+  FILE **f = topfile(L, findex);
+  if (*f == NULL)
+    luaL_error(L, "attempt to use a closed file");
+  return *f;
+}
+
+
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static FILE **newfile (lua_State *L) {
+  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+  *pf = NULL;  /* file handle is currently `closed' */
+  luaL_getmetatable(L, FILEHANDLE);
+  lua_setmetatable(L, -2);
+  return pf;
+}
+
+
+/*
+** assumes that top of the stack is the `io' library, and next is
+** the `io' metatable
+*/
+static void registerfile (lua_State *L, FILE *f, const char *name,
+                                                 const char *impname) {
+  lua_pushstring(L, name);
+  *newfile(L) = f;
+  if (impname) {
+    lua_pushstring(L, impname);
+    lua_pushvalue(L, -2);
+    lua_settable(L, -6);  /* metatable[impname] = file */
+  }
+  lua_settable(L, -3);  /* io[name] = file */
+}
+
+
+static int aux_close (lua_State *L) {
+  FILE *f = tofile(L, 1);
+  if (f == stdin || f == stdout || f == stderr)
+    return 0;  /* file cannot be closed */
+  else {
+    int ok = (pclose(f) != -1) || (fclose(f) == 0);
+    if (ok)
+      *(FILE **)lua_touserdata(L, 1) = NULL;  /* mark file as closed */
+    return ok;
+  }
+}
+
+
+static int io_close (lua_State *L) {
+  if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) {
+    lua_pushstring(L, IO_OUTPUT);
+    lua_rawget(L, lua_upvalueindex(1));
+  }
+  return pushresult(L, aux_close(L), NULL);
+}
+
+
+static int io_gc (lua_State *L) {
+  FILE **f = topfile(L, 1);
+  if (*f != NULL)  /* ignore closed files */
+    aux_close(L);
+  return 0;
+}
+
+
+static int io_tostring (lua_State *L) {
+  char buff[128];
+  FILE **f = topfile(L, 1);
+  if (*f == NULL)
+    strcpy(buff, "closed");
+  else
+    sprintf(buff, "%p", lua_touserdata(L, 1));
+  lua_pushfstring(L, "file (%s)", buff);
+  return 1;
+}
+
+
+static int io_open (lua_State *L) {
+  const char *filename = luaL_checkstring(L, 1);
+  const char *mode = luaL_optstring(L, 2, "r");
+  FILE **pf = newfile(L);
+  *pf = fopen(filename, mode);
+  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+static int io_popen (lua_State *L) {
+#if !USE_POPEN
+  luaL_error(L, "`popen' not supported");
+  return 0;
+#else
+  const char *filename = luaL_checkstring(L, 1);
+  const char *mode = luaL_optstring(L, 2, "r");
+  FILE **pf = newfile(L);
+  *pf = popen(filename, mode);
+  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+#endif
+}
+
+
+static int io_tmpfile (lua_State *L) {
+  FILE **pf = newfile(L);
+  *pf = tmpfile();
+  return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
+}
+
+
+static FILE *getiofile (lua_State *L, const char *name) {
+  lua_pushstring(L, name);
+  lua_rawget(L, lua_upvalueindex(1));
+  return tofile(L, -1);
+}
+
+
+static int g_iofile (lua_State *L, const char *name, const char *mode) {
+  if (!lua_isnoneornil(L, 1)) {
+    const char *filename = lua_tostring(L, 1);
+    lua_pushstring(L, name);
+    if (filename) {
+      FILE **pf = newfile(L);
+      *pf = fopen(filename, mode);
+      if (*pf == NULL) {
+        lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+        luaL_argerror(L, 1, lua_tostring(L, -1));
+      }
+    }
+    else {
+      tofile(L, 1);  /* check that it's a valid file handle */
+      lua_pushvalue(L, 1);
+    }
+    lua_rawset(L, lua_upvalueindex(1));
+  }
+  /* return current value */
+  lua_pushstring(L, name);
+  lua_rawget(L, lua_upvalueindex(1));
+  return 1;
+}
+
+
+static int io_input (lua_State *L) {
+  return g_iofile(L, IO_INPUT, "r");
+}
+
+
+static int io_output (lua_State *L) {
+  return g_iofile(L, IO_OUTPUT, "w");
+}
+
+
+static int io_readline (lua_State *L);
+
+
+static void aux_lines (lua_State *L, int idx, int close) {
+  lua_pushliteral(L, FILEHANDLE);
+  lua_rawget(L, LUA_REGISTRYINDEX);
+  lua_pushvalue(L, idx);
+  lua_pushboolean(L, close);  /* close/not close file when finished */
+  lua_pushcclosure(L, io_readline, 3);
+}
+
+
+static int f_lines (lua_State *L) {
+  tofile(L, 1);  /* check that it's a valid file handle */
+  aux_lines(L, 1, 0);
+  return 1;
+}
+
+
+static int io_lines (lua_State *L) {
+  if (lua_isnoneornil(L, 1)) {  /* no arguments? */
+    lua_pushstring(L, IO_INPUT);
+    lua_rawget(L, lua_upvalueindex(1));  /* will iterate over default input */
+    return f_lines(L);
+  }
+  else {
+    const char *filename = luaL_checkstring(L, 1);
+    FILE **pf = newfile(L);
+    *pf = fopen(filename, "r");
+    luaL_argcheck(L, *pf, 1,  strerror(errno));
+    aux_lines(L, lua_gettop(L), 1);
+    return 1;
+  }
+}
+
+
+/*
+** {======================================================
+** READ
+** =======================================================
+*/
+
+
+static int read_number (lua_State *L, FILE *f) {
+  lua_Number d;
+  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+    lua_pushnumber(L, d);
+    return 1;
+  }
+  else return 0;  /* read fails */
+}
+
+
+static int test_eof (lua_State *L, FILE *f) {
+  int c = getc(f);
+  ungetc(c, f);
+  lua_pushlstring(L, NULL, 0);
+  return (c != EOF);
+}
+
+
+static int read_line (lua_State *L, FILE *f) {
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  for (;;) {
+    size_t l;
+    char *p = luaL_prepbuffer(&b);
+    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
+      luaL_pushresult(&b);  /* close buffer */
+      return (lua_strlen(L, -1) > 0);  /* check whether read something */
+    }
+    l = strlen(p);
+    if (p[l-1] != '\n')
+      luaL_addsize(&b, l);
+    else {
+      luaL_addsize(&b, l - 1);  /* do not include `eol' */
+      luaL_pushresult(&b);  /* close buffer */
+      return 1;  /* read at least an `eol' */
+    }
+  }
+}
+
+
+static int read_chars (lua_State *L, FILE *f, size_t n) {
+  size_t rlen;  /* how much to read */
+  size_t nr;  /* number of chars actually read */
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */
+  do {
+    char *p = luaL_prepbuffer(&b);
+    if (rlen > n) rlen = n;  /* cannot read more than asked */
+    nr = fread(p, sizeof(char), rlen, f);
+    luaL_addsize(&b, nr);
+    n -= nr;  /* still have to read `n' chars */
+  } while (n > 0 && nr == rlen);  /* until end of count or eof */
+  luaL_pushresult(&b);  /* close buffer */
+  return (n == 0 || lua_strlen(L, -1) > 0);
+}
+
+
+static int g_read (lua_State *L, FILE *f, int first) {
+  int nargs = lua_gettop(L) - 1;
+  int success;
+  int n;
+  if (nargs == 0) {  /* no arguments? */
+    success = read_line(L, f);
+    n = first+1;  /* to return 1 result */
+  }
+  else {  /* ensure stack space for all results and for auxlib's buffer */
+    luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+    success = 1;
+    for (n = first; nargs-- && success; n++) {
+      if (lua_type(L, n) == LUA_TNUMBER) {
+        size_t l = lua_tonumber(L, n);
+        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+      }
+      else {
+        const char *p = lua_tostring(L, n);
+        luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+        switch (p[1]) {
+          case 'n':  /* number */
+            success = read_number(L, f);
+            break;
+          case 'l':  /* line */
+            success = read_line(L, f);
+            break;
+          case 'a':  /* file */
+            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */
+            success = 1; /* always success */
+            break;
+          case 'w':  /* word */
+            return luaL_error(L, "obsolete option `*w' to `read'");
+          default:
+            return luaL_argerror(L, n, "invalid format");
+        }
+      }
+    }
+  }
+  if (!success) {
+    lua_pop(L, 1);  /* remove last result */
+    lua_pushnil(L);  /* push nil instead */
+  }
+  return n - first;
+}
+
+
+static int io_read (lua_State *L) {
+  return g_read(L, getiofile(L, IO_INPUT), 1);
+}
+
+
+static int f_read (lua_State *L) {
+  return g_read(L, tofile(L, 1), 2);
+}
+
+
+static int io_readline (lua_State *L) {
+  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
+  if (f == NULL)  /* file is already closed? */
+    luaL_error(L, "file is already closed");
+  if (read_line(L, f)) return 1;
+  else {  /* EOF */
+    if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
+      lua_settop(L, 0);
+      lua_pushvalue(L, lua_upvalueindex(2));
+      aux_close(L);  /* close it */
+    }
+    return 0;
+  }
+}
+
+/* }====================================================== */
+
+
+static int g_write (lua_State *L, FILE *f, int arg) {
+  int nargs = lua_gettop(L) - 1;
+  int status = 1;
+  for (; nargs--; arg++) {
+    if (lua_type(L, arg) == LUA_TNUMBER) {
+      /* optimization: could be done exactly as for strings */
+      status = status &&
+          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+    }
+    else {
+      size_t l;
+      const char *s = luaL_checklstring(L, arg, &l);
+      status = status && (fwrite(s, sizeof(char), l, f) == l);
+    }
+  }
+  return pushresult(L, status, NULL);
+}
+
+
+static int io_write (lua_State *L) {
+  return g_write(L, getiofile(L, IO_OUTPUT), 1);
+}
+
+
+static int f_write (lua_State *L) {
+  return g_write(L, tofile(L, 1), 2);
+}
+
+
+static int f_seek (lua_State *L) {
+  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+  static const char *const modenames[] = {"set", "cur", "end", NULL};
+  FILE *f = tofile(L, 1);
+  int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
+  long offset = luaL_optlong(L, 3, 0);
+  luaL_argcheck(L, op != -1, 2, "invalid mode");
+  op = fseek(f, offset, mode[op]);
+  if (op)
+    return pushresult(L, 0, NULL);  /* error */
+  else {
+    lua_pushnumber(L, ftell(f));
+    return 1;
+  }
+}
+
+
+static int io_flush (lua_State *L) {
+  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
+}
+
+
+static int f_flush (lua_State *L) {
+  return pushresult(L, fflush(tofile(L, 1)) == 0, NULL);
+}
+
+
+static const luaL_reg iolib[] = {
+  {"input", io_input},
+  {"output", io_output},
+  {"lines", io_lines},
+  {"close", io_close},
+  {"flush", io_flush},
+  {"open", io_open},
+  {"popen", io_popen},
+  {"read", io_read},
+  {"tmpfile", io_tmpfile},
+  {"type", io_type},
+  {"write", io_write},
+  {NULL, NULL}
+};
+
+
+static const luaL_reg flib[] = {
+  {"flush", f_flush},
+  {"read", f_read},
+  {"lines", f_lines},
+  {"seek", f_seek},
+  {"write", f_write},
+  {"close", io_close},
+  {"__gc", io_gc},
+  {"__tostring", io_tostring},
+  {NULL, NULL}
+};
+
+
+static void createmeta (lua_State *L) {
+  luaL_newmetatable(L, FILEHANDLE);  /* create new metatable for file handles */
+  /* file methods */
+  lua_pushliteral(L, "__index");
+  lua_pushvalue(L, -2);  /* push metatable */
+  lua_rawset(L, -3);  /* metatable.__index = metatable */
+  luaL_openlib(L, NULL, flib, 0);
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** Other O.S. Operations
+** =======================================================
+*/
+
+static int io_execute (lua_State *L) {
+  lua_pushnumber(L, system(luaL_checkstring(L, 1)));
+  return 1;
+}
+
+
+static int io_remove (lua_State *L) {
+  const char *filename = luaL_checkstring(L, 1);
+  return pushresult(L, remove(filename) == 0, filename);
+}
+
+
+static int io_rename (lua_State *L) {
+  const char *fromname = luaL_checkstring(L, 1);
+  const char *toname = luaL_checkstring(L, 2);
+  return pushresult(L, rename(fromname, toname) == 0, fromname);
+}
+
+
+#if !USE_TMPNAME
+static int io_tmpname (lua_State *L) __attribute__((noreturn));
+#else
+static int io_tmpname (lua_State *L);
+#endif
+
+static int io_tmpname (lua_State *L) {
+#if !USE_TMPNAME
+  luaL_error(L, "`tmpname' not supported");
+#else
+  char buff[L_tmpnam];
+  if (tmpnam(buff) != buff)
+    return luaL_error(L, "unable to generate a unique filename in `tmpname'");
+  lua_pushstring(L, buff);
+  return 1;
+#endif
+}
+
+
+static int io_getenv (lua_State *L) {
+  lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */
+  return 1;
+}
+
+
+static int io_clock (lua_State *L) {
+  lua_pushnumber(L, clock()/(lua_Number)CLOCKS_PER_SEC);
+  return 1;
+}
+
+
+/*
+** {======================================================
+** Time/Date operations
+** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+**   wday=%w+1, yday=%j, isdst=? }
+** =======================================================
+*/
+
+static void setfield (lua_State *L, const char *key, int value) {
+  lua_pushstring(L, key);
+  lua_pushnumber(L, value);
+  lua_rawset(L, -3);
+}
+
+static void setboolfield (lua_State *L, const char *key, int value) {
+  lua_pushstring(L, key);
+  lua_pushboolean(L, value);
+  lua_rawset(L, -3);
+}
+
+static int getboolfield (lua_State *L, const char *key) {
+  int res;
+  lua_pushstring(L, key);
+  lua_gettable(L, -2);
+  res = lua_toboolean(L, -1);
+  lua_pop(L, 1);
+  return res;
+}
+
+
+static int getfield (lua_State *L, const char *key, int d) {
+  int res;
+  lua_pushstring(L, key);
+  lua_gettable(L, -2);
+  if (lua_isnumber(L, -1))
+    res = lua_tonumber(L, -1);
+  else {
+    if (d == -2)
+      return luaL_error(L, "field `%s' missing in date table", key);
+    res = d;
+  }
+  lua_pop(L, 1);
+  return res;
+}
+
+
+static int io_date (lua_State *L) {
+  const char *s = luaL_optstring(L, 1, "%c");
+  time_t t = luaL_optnumber(L, 2, -1);
+  struct tm *stm;
+  if (t == (time_t)(-1))  /* no time given? */
+    t = time(NULL);  /* use current time */
+  if (*s == '!') {  /* UTC? */
+    stm = gmtime(&t);
+    s++;  /* skip `!' */
+  }
+  else
+    stm = localtime(&t);
+  if (stm == NULL)  /* invalid date? */
+    lua_pushnil(L);
+  else if (strcmp(s, "*t") == 0) {
+    lua_newtable(L);
+    setfield(L, "sec", stm->tm_sec);
+    setfield(L, "min", stm->tm_min);
+    setfield(L, "hour", stm->tm_hour);
+    setfield(L, "day", stm->tm_mday);
+    setfield(L, "month", stm->tm_mon+1);
+    setfield(L, "year", stm->tm_year+1900);
+    setfield(L, "wday", stm->tm_wday+1);
+    setfield(L, "yday", stm->tm_yday+1);
+    setboolfield(L, "isdst", stm->tm_isdst);
+  }
+  else {
+    char b[256];
+    if (strftime(b, sizeof(b), s, stm))
+      lua_pushstring(L, b);
+    else
+      return luaL_error(L, "`date' format too long");
+  }
+  return 1;
+}
+
+
+static int io_time (lua_State *L) {
+  if (lua_isnoneornil(L, 1))  /* called without args? */
+    lua_pushnumber(L, time(NULL));  /* return current time */
+  else {
+    time_t t;
+    struct tm ts;
+    luaL_checktype(L, 1, LUA_TTABLE);
+    lua_settop(L, 1);  /* make sure table is at the top */
+    ts.tm_sec = getfield(L, "sec", 0);
+    ts.tm_min = getfield(L, "min", 0);
+    ts.tm_hour = getfield(L, "hour", 12);
+    ts.tm_mday = getfield(L, "day", -2);
+    ts.tm_mon = getfield(L, "month", -2) - 1;
+    ts.tm_year = getfield(L, "year", -2) - 1900;
+    ts.tm_isdst = getboolfield(L, "isdst");
+    t = mktime(&ts);
+    if (t == (time_t)(-1))
+      lua_pushnil(L);
+    else
+      lua_pushnumber(L, t);
+  }
+  return 1;
+}
+
+
+static int io_difftime (lua_State *L) {
+  lua_pushnumber(L, difftime(luaL_checknumber(L, 1),
+                             luaL_optnumber(L, 2, 0)));
+  return 1;
+}
+
+/* }====================================================== */
+
+
+static int io_setloc (lua_State *L) {
+  static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
+                      LC_NUMERIC, LC_TIME};
+  static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
+     "numeric", "time", NULL};
+  const char *l = lua_tostring(L, 1);
+  int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames);
+  luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected");
+  luaL_argcheck(L, op != -1, 2, "invalid option");
+  lua_pushstring(L, setlocale(cat[op], l));
+  return 1;
+}
+
+
+static int io_exit (lua_State *L) {
+  exit(luaL_optint(L, 1, EXIT_SUCCESS));
+}
+
+static const luaL_reg syslib[] = {
+  {"clock",     io_clock},
+  {"date",      io_date},
+  {"difftime",  io_difftime},
+  {"execute",   io_execute},
+  {"exit",      io_exit},
+  {"getenv",    io_getenv},
+  {"remove",    io_remove},
+  {"rename",    io_rename},
+  {"setlocale", io_setloc},
+  {"time",      io_time},
+  {"tmpname",   io_tmpname},
+  {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_io (lua_State *L) {
+  luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
+  createmeta(L);
+  lua_pushvalue(L, -1);
+  luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
+  /* put predefined file handles into `io' table */
+  registerfile(L, stdin, "stdin", IO_INPUT);
+  registerfile(L, stdout, "stdout", IO_OUTPUT);
+  registerfile(L, stderr, "stderr", NULL);
+  return 1;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/llex.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/llex.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/llex.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/llex.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,415 @@
+/*
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <string.h>
+
+#define llex_c
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "llex.h"
+#include "lobject.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lzio.h"
+
+
+#define next(LS) (LS->current = zgetc(LS->z))
+
+static void luaX_error (LexState *ls, const char *s, const char *token) __attribute__((noreturn));
+static void luaX_lexerror (LexState *ls, const char *s, int token) __attribute__((noreturn));
+
+
+/* ORDER RESERVED */
+static const char *const token2string [] = {
+    "and", "break", "do", "else", "elseif",
+    "end", "false", "for", "function", "if",
+    "in", "local", "nil", "not", "or", "repeat",
+    "return", "then", "true", "until", "while", "*name",
+    "..", "...", "==", ">=", "<=", "~=",
+    "*number", "*string", "<eof>"
+};
+
+
+void luaX_init (lua_State *L) {
+  int i;
+  for (i=0; i<NUM_RESERVED; i++) {
+    TString *ts = luaS_new(L, token2string[i]);
+    luaS_fix(ts);  /* reserved words are never collected */
+    lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN);
+    ts->tsv.reserved = cast(lu_byte, i+1);  /* reserved word */
+  }
+}
+
+
+#define MAXSRC          80
+
+
+void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) {
+  if (val > limit) {
+    msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit);
+    luaX_syntaxerror(ls, msg);
+  }
+}
+
+void luaX_errorline (LexState *ls, const char *s, const char *token, int line) {
+  lua_State *L = ls->L;
+  char buff[MAXSRC];
+  luaO_chunkid(buff, getstr(ls->source), MAXSRC);
+  luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token); 
+  luaD_throw(L, LUA_ERRSYNTAX);
+}
+
+static void luaX_error (LexState *ls, const char *s, const char *token) {
+  luaX_errorline(ls, s, token, ls->linenumber);
+}
+
+
+void luaX_syntaxerror (LexState *ls, const char *msg) {
+  const char *lasttoken;
+  switch (ls->t.token) {
+    case TK_NAME:
+      lasttoken = getstr(ls->t.seminfo.ts);
+      break;
+    case TK_STRING:
+    case TK_NUMBER:
+      lasttoken = luaZ_buffer(ls->buff);
+      break;
+    default:
+      lasttoken = luaX_token2str(ls, ls->t.token);
+      break;
+  }
+  luaX_error(ls, msg, lasttoken);
+}
+
+
+const char *luaX_token2str (LexState *ls, int token) {
+  if (token < FIRST_RESERVED) {
+    lua_assert(token == (unsigned char)token);
+    return luaO_pushfstring(ls->L, "%c", token);
+  }
+  else
+    return token2string[token-FIRST_RESERVED];
+}
+
+
+static void luaX_lexerror (LexState *ls, const char *s, int token) {
+  if (token == TK_EOS)
+    luaX_error(ls, s, luaX_token2str(ls, token));
+  else
+    luaX_error(ls, s, luaZ_buffer(ls->buff));
+}
+
+
+static void inclinenumber (LexState *LS) {
+  next(LS);  /* skip `\n' */
+  ++LS->linenumber;
+  luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk");
+}
+
+
+void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
+  LS->L = L;
+  LS->lookahead.token = TK_EOS;  /* no look-ahead token */
+  LS->z = z;
+  LS->fs = NULL;
+  LS->linenumber = 1;
+  LS->lastline = 1;
+  LS->source = source;
+  next(LS);  /* read first char */
+  if (LS->current == '#') {
+    do {  /* skip first line */
+      next(LS);
+    } while (LS->current != '\n' && LS->current != EOZ);
+  }
+}
+
+
+
+/*
+** =======================================================
+** LEXICAL ANALYZER
+** =======================================================
+*/
+
+
+/* use buffer to store names, literal strings and numbers */
+
+/* extra space to allocate when growing buffer */
+#define EXTRABUFF	32
+
+/* maximum number of chars that can be read without checking buffer size */
+#define MAXNOCHECK	5
+
+#define checkbuffer(LS, len)	\
+    if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
+      luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
+
+#define save(LS, c, l) \
+	(luaZ_buffer((LS)->buff)[l++] = cast(char, c))
+#define save_and_next(LS, l)  (save(LS, LS->current, l), next(LS))
+
+
+static size_t readname (LexState *LS) {
+  size_t l = 0;
+  checkbuffer(LS, l);
+  do {
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
+  } while (isalnum(LS->current) || LS->current == '_');
+  save(LS, '\0', l);
+  return l-1;
+}
+
+
+/* LUA_NUMBER */
+static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
+  size_t l = 0;
+  checkbuffer(LS, l);
+  if (comma) save(LS, '.', l);
+  while (isdigit(LS->current)) {
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
+  }
+  if (LS->current == '.') {
+    save_and_next(LS, l);
+    if (LS->current == '.') {
+      save_and_next(LS, l);
+      save(LS, '\0', l);
+      luaX_lexerror(LS,
+                 "ambiguous syntax (decimal point x string concatenation)",
+                 TK_NUMBER);
+    }
+  }
+  while (isdigit(LS->current)) {
+    checkbuffer(LS, l);
+    save_and_next(LS, l);
+  }
+  if (LS->current == 'e' || LS->current == 'E') {
+    save_and_next(LS, l);  /* read `E' */
+    if (LS->current == '+' || LS->current == '-')
+      save_and_next(LS, l);  /* optional exponent sign */
+    while (isdigit(LS->current)) {
+      checkbuffer(LS, l);
+      save_and_next(LS, l);
+    }
+  }
+  save(LS, '\0', l);
+  if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r))
+    luaX_lexerror(LS, "malformed number", TK_NUMBER);
+}
+
+
+static void read_long_string (LexState *LS, SemInfo *seminfo) {
+  int cont = 0;
+  size_t l = 0;
+  checkbuffer(LS, l);
+  save(LS, '[', l);  /* save first `[' */
+  save_and_next(LS, l);  /* pass the second `[' */
+  if (LS->current == '\n')  /* string starts with a newline? */
+    inclinenumber(LS);  /* skip it */
+  for (;;) {
+    checkbuffer(LS, l);
+    switch (LS->current) {
+      case EOZ:
+        save(LS, '\0', l);
+        luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
+                                   "unfinished long comment", TK_EOS);
+        break;  /* to avoid warnings */
+      case '[':
+        save_and_next(LS, l);
+        if (LS->current == '[') {
+          cont++;
+          save_and_next(LS, l);
+        }
+        continue;
+      case ']':
+        save_and_next(LS, l);
+        if (LS->current == ']') {
+          if (cont == 0) goto endloop;
+          cont--;
+          save_and_next(LS, l);
+        }
+        continue;
+      case '\n':
+        save(LS, '\n', l);
+        inclinenumber(LS);
+        if (!seminfo) l = 0;  /* reset buffer to avoid wasting space */
+        continue;
+      default:
+        save_and_next(LS, l);
+    }
+  } endloop:
+  save_and_next(LS, l);  /* skip the second `]' */
+  save(LS, '\0', l);
+  if (seminfo)
+    seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
+}
+
+
+static void read_string (LexState *LS, int del, SemInfo *seminfo) {
+  size_t l = 0;
+  checkbuffer(LS, l);
+  save_and_next(LS, l);
+  while (LS->current != del) {
+    checkbuffer(LS, l);
+    switch (LS->current) {
+      case EOZ:
+        save(LS, '\0', l);
+        luaX_lexerror(LS, "unfinished string", TK_EOS);
+        break;  /* to avoid warnings */
+      case '\n':
+        save(LS, '\0', l);
+        luaX_lexerror(LS, "unfinished string", TK_STRING);
+        break;  /* to avoid warnings */
+      case '\\':
+        next(LS);  /* do not save the `\' */
+        switch (LS->current) {
+          case 'a': save(LS, '\a', l); next(LS); break;
+          case 'b': save(LS, '\b', l); next(LS); break;
+          case 'f': save(LS, '\f', l); next(LS); break;
+          case 'n': save(LS, '\n', l); next(LS); break;
+          case 'r': save(LS, '\r', l); next(LS); break;
+          case 't': save(LS, '\t', l); next(LS); break;
+          case 'v': save(LS, '\v', l); next(LS); break;
+          case '\n': save(LS, '\n', l); inclinenumber(LS); break;
+          case EOZ: break;  /* will raise an error next loop */
+          default: {
+            if (!isdigit(LS->current))
+              save_and_next(LS, l);  /* handles \\, \", \', and \? */
+            else {  /* \xxx */
+              int c = 0;
+              int i = 0;
+              do {
+                c = 10*c + (LS->current-'0');
+                next(LS);
+              } while (++i<3 && isdigit(LS->current));
+              if (c > UCHAR_MAX) {
+                save(LS, '\0', l);
+                luaX_lexerror(LS, "escape sequence too large", TK_STRING);
+              }
+              save(LS, c, l);
+            }
+          }
+        }
+        break;
+      default:
+        save_and_next(LS, l);
+    }
+  }
+  save_and_next(LS, l);  /* skip delimiter */
+  save(LS, '\0', l);
+  seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
+}
+
+
+int luaX_lex (LexState *LS, SemInfo *seminfo) {
+  for (;;) {
+    switch (LS->current) {
+
+      case '\n': {
+        inclinenumber(LS);
+        continue;
+      }
+      case '-': {
+        next(LS);
+        if (LS->current != '-') return '-';
+        /* else is a comment */
+        next(LS);
+        if (LS->current == '[' && (next(LS), LS->current == '['))
+          read_long_string(LS, NULL);  /* long comment */
+        else  /* short comment */
+          while (LS->current != '\n' && LS->current != EOZ)
+            next(LS);
+        continue;
+      }
+      case '[': {
+        next(LS);
+        if (LS->current != '[') return '[';
+        else {
+          read_long_string(LS, seminfo);
+          return TK_STRING;
+        }
+      }
+      case '=': {
+        next(LS);
+        if (LS->current != '=') return '=';
+        else { next(LS); return TK_EQ; }
+      }
+      case '<': {
+        next(LS);
+        if (LS->current != '=') return '<';
+        else { next(LS); return TK_LE; }
+      }
+      case '>': {
+        next(LS);
+        if (LS->current != '=') return '>';
+        else { next(LS); return TK_GE; }
+      }
+      case '~': {
+        next(LS);
+        if (LS->current != '=') return '~';
+        else { next(LS); return TK_NE; }
+      }
+      case '"':
+      case '\'': {
+        read_string(LS, LS->current, seminfo);
+        return TK_STRING;
+      }
+      case '.': {
+        next(LS);
+        if (LS->current == '.') {
+          next(LS);
+          if (LS->current == '.') {
+            next(LS);
+            return TK_DOTS;   /* ... */
+          }
+          else return TK_CONCAT;   /* .. */
+        }
+        else if (!isdigit(LS->current)) return '.';
+        else {
+          read_numeral(LS, 1, seminfo);
+          return TK_NUMBER;
+        }
+      }
+      case EOZ: {
+        return TK_EOS;
+      }
+      default: {
+        if (isspace(LS->current)) {
+          next(LS);
+          continue;
+        }
+        else if (isdigit(LS->current)) {
+          read_numeral(LS, 0, seminfo);
+          return TK_NUMBER;
+        }
+        else if (isalpha(LS->current) || LS->current == '_') {
+          /* identifier or reserved word */
+          size_t l = readname(LS);
+          TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
+          if (ts->tsv.reserved > 0)  /* reserved word? */
+            return ts->tsv.reserved - 1 + FIRST_RESERVED;
+          seminfo->ts = ts;
+          return TK_NAME;
+        }
+        else {
+          int c = LS->current;
+          if (iscntrl(c))
+            luaX_error(LS, "invalid control char",
+                           luaO_pushfstring(LS->L, "char(%d)", c));
+          next(LS);
+          return c;  /* single-char tokens (+ - / ...) */
+        }
+      }
+    }
+  }
+}
+
+#undef next
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/llex.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/llex.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/llex.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/llex.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,74 @@
+/*
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llex_h
+#define llex_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+
+#define FIRST_RESERVED	257
+
+/* maximum length of a reserved word */
+#define TOKEN_LEN	(sizeof("function")/sizeof(char))
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER RESERVED"
+*/
+enum RESERVED {
+  /* terminal symbols denoted by reserved words */
+  TK_AND = FIRST_RESERVED, TK_BREAK,
+  TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
+  TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
+  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+  /* other terminal symbols */
+  TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+  TK_STRING, TK_EOS
+};
+
+/* number of reserved words */
+#define NUM_RESERVED	(cast(int, TK_WHILE-FIRST_RESERVED+1))
+
+
+typedef union {
+  lua_Number r;
+  TString *ts;
+} SemInfo;  /* semantics information */
+
+
+typedef struct Token {
+  int token;
+  SemInfo seminfo;
+} Token;
+
+
+typedef struct LexState {
+  int current;  /* current character (charint) */
+  int linenumber;  /* input line counter */
+  int lastline;  /* line of last token `consumed' */
+  Token t;  /* current token */
+  Token lookahead;  /* look ahead token */
+  struct FuncState *fs;  /* `FuncState' is private to the parser */
+  struct lua_State *L;
+  ZIO *z;  /* input stream */
+  Mbuffer *buff;  /* buffer for tokens */
+  TString *source;  /* current source name */
+  int nestlevel;  /* level of nested non-terminals */
+} LexState;
+
+
+void luaX_init (lua_State *L);
+void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source);
+int luaX_lex (LexState *LS, SemInfo *seminfo);
+void luaX_checklimit (LexState *ls, int val, int limit, const char *msg);
+void luaX_syntaxerror (LexState *ls, const char *s) __attribute__((noreturn));
+void luaX_errorline (LexState *ls, const char *s, const char *token, int line) __attribute__((noreturn));
+const char *luaX_token2str (LexState *ls, int token);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/llimits.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/llimits.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/llimits.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/llimits.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,184 @@
+/*
+** Limits, basic types, and some other `installation-dependent' definitions
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llimits_h
+#define llimits_h
+
+
+#include <limits.h>
+#include <stddef.h>
+
+
+#include "lua.h"
+
+
+/*
+** try to find number of bits in an integer
+*/
+#ifndef BITS_INT
+/* avoid overflows in comparison */
+#if INT_MAX-20 < 32760
+#define	BITS_INT	16
+#else
+#if INT_MAX > 2147483640L
+/* machine has at least 32 bits */
+#define BITS_INT	32
+#else
+#error "you must define BITS_INT with number of bits in an integer"
+#endif
+#endif
+#endif
+
+
+/*
+** the following types define integer types for values that may not
+** fit in a `small int' (16 bits), but may waste space in a
+** `large long' (64 bits). The current definitions should work in
+** any machine, but may not be optimal.
+*/
+
+/* an unsigned integer to hold hash values */
+typedef unsigned long int lu_hash;
+/* its signed equivalent */
+typedef int ls_hash;
+
+/* an unsigned integer big enough to count the total memory used by Lua; */
+/* it should be at least as large as size_t */
+typedef unsigned long lu_mem;
+
+#define MAX_LUMEM	ULONG_MAX
+
+
+/* an integer big enough to count the number of strings in use */
+typedef long ls_nstr;
+
+/* chars used as small naturals (so that `char' is reserved for characters) */
+typedef unsigned char lu_byte;
+
+
+#define MAX_SIZET	((size_t)(~(size_t)0)-2)
+
+
+#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */
+
+/*
+** conversion of pointer to integer
+** this is for hashing only; there is no problem if the integer
+** cannot hold the whole pointer value
+*/
+#define IntPoint(p)  ((lu_hash)(p))
+
+
+
+/* type to ensure maximum alignment */
+#ifndef LUSER_ALIGNMENT_T
+typedef union { double u; void *s; long l; } L_Umaxalign;
+#else
+typedef LUSER_ALIGNMENT_T L_Umaxalign;
+#endif
+
+
+/* result of `usual argument conversion' over lua_Number */
+#ifndef LUA_UACNUMBER
+typedef double l_uacNumber;
+#else
+typedef LUA_UACNUMBER l_uacNumber;
+#endif
+
+
+#ifndef lua_assert
+#define lua_assert(c)		/* empty */
+#endif
+
+
+#ifndef check_exp
+#define check_exp(c,e)	(e)
+#endif
+
+
+#ifndef UNUSED
+#define UNUSED(x)	((void)(x))	/* to avoid warnings */
+#endif
+
+
+#ifndef cast
+#define cast(t, exp)	((t)(exp))
+#endif
+
+
+
+/*
+** type for virtual-machine instructions
+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+*/
+typedef unsigned long Instruction;
+
+
+/* maximum depth for calls (unsigned short) */
+#ifndef LUA_MAXCALLS
+#define LUA_MAXCALLS        4096
+#endif
+
+
+/*
+** maximum depth for C calls (unsigned short): Not too big, or may
+** overflow the C stack...
+*/
+
+#ifndef LUA_MAXCCALLS
+#define LUA_MAXCCALLS        200
+#endif
+
+
+/* maximum size for the C stack */
+#ifndef LUA_MAXCSTACK
+#define LUA_MAXCSTACK        2048
+#endif
+
+
+/* maximum stack for a Lua function */
+#define MAXSTACK	250
+
+
+/* maximum number of variables declared in a function */
+#ifndef MAXVARS
+#define MAXVARS 200           /* arbitrary limit (<MAXSTACK) */
+#endif
+
+
+/* maximum number of upvalues per function */
+#ifndef MAXUPVALUES
+#define MAXUPVALUES	32
+#endif
+
+
+/* maximum number of parameters in a function */
+#ifndef MAXPARAMS
+#define MAXPARAMS 100           /* arbitrary limit (<MAXLOCALS) */
+#endif
+
+
+/* minimum size for the string table (must be power of 2) */
+#ifndef MINSTRTABSIZE
+#define MINSTRTABSIZE	32
+#endif
+
+
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER	32
+#endif
+
+
+/*
+** maximum number of syntactical nested non-terminals: Not too big,
+** or may overflow the C stack...
+*/
+#ifndef LUA_MAXPARSERLEVEL
+#define LUA_MAXPARSERLEVEL	200
+#endif
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lmathlib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lmathlib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lmathlib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lmathlib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,245 @@
+/*
+** Standard mathematical library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+#include <math.h>
+
+#define lmathlib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#undef PI
+#define PI (3.14159265358979323846)
+#define RADIANS_PER_DEGREE (PI/180.0)
+
+
+
+/*
+** If you want Lua to operate in degrees (instead of radians),
+** define USE_DEGREES
+*/
+#ifdef USE_DEGREES
+#define FROMRAD(a)	((a)/RADIANS_PER_DEGREE)
+#define TORAD(a)	((a)*RADIANS_PER_DEGREE)
+#else
+#define FROMRAD(a)	(a)
+#define TORAD(a)	(a)
+#endif
+
+
+static int math_abs (lua_State *L) {
+  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_sin (lua_State *L) {
+  lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1))));
+  return 1;
+}
+
+static int math_cos (lua_State *L) {
+  lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1))));
+  return 1;
+}
+
+static int math_tan (lua_State *L) {
+  lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1))));
+  return 1;
+}
+
+static int math_asin (lua_State *L) {
+  lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1))));
+  return 1;
+}
+
+static int math_acos (lua_State *L) {
+  lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1))));
+  return 1;
+}
+
+static int math_atan (lua_State *L) {
+  lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1))));
+  return 1;
+}
+
+static int math_atan2 (lua_State *L) {
+  lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))));
+  return 1;
+}
+
+static int math_ceil (lua_State *L) {
+  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_floor (lua_State *L) {
+  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_mod (lua_State *L) {
+  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+  return 1;
+}
+
+static int math_sqrt (lua_State *L) {
+  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_pow (lua_State *L) {
+  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+  return 1;
+}
+
+static int math_log (lua_State *L) {
+  lua_pushnumber(L, log(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_log10 (lua_State *L) {
+  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_exp (lua_State *L) {
+  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_deg (lua_State *L) {
+  lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
+  return 1;
+}
+
+static int math_rad (lua_State *L) {
+  lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
+  return 1;
+}
+
+static int math_frexp (lua_State *L) {
+  int e;
+  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
+  lua_pushnumber(L, e);
+  return 2;
+}
+
+static int math_ldexp (lua_State *L) {
+  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+  return 1;
+}
+
+
+
+static int math_min (lua_State *L) {
+  int n = lua_gettop(L);  /* number of arguments */
+  lua_Number dmin = luaL_checknumber(L, 1);
+  int i;
+  for (i=2; i<=n; i++) {
+    lua_Number d = luaL_checknumber(L, i);
+    if (d < dmin)
+      dmin = d;
+  }
+  lua_pushnumber(L, dmin);
+  return 1;
+}
+
+
+static int math_max (lua_State *L) {
+  int n = lua_gettop(L);  /* number of arguments */
+  lua_Number dmax = luaL_checknumber(L, 1);
+  int i;
+  for (i=2; i<=n; i++) {
+    lua_Number d = luaL_checknumber(L, i);
+    if (d > dmax)
+      dmax = d;
+  }
+  lua_pushnumber(L, dmax);
+  return 1;
+}
+
+
+static int math_random (lua_State *L) {
+  /* the `%' avoids the (rare) case of r==1, and is needed also because on
+     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+  lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+  switch (lua_gettop(L)) {  /* check number of arguments */
+    case 0: {  /* no arguments */
+      lua_pushnumber(L, r);  /* Number between 0 and 1 */
+      break;
+    }
+    case 1: {  /* only upper limit */
+      int u = luaL_checkint(L, 1);
+      luaL_argcheck(L, 1<=u, 1, "interval is empty");
+      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */
+      break;
+    }
+    case 2: {  /* lower and upper limits */
+      int l = luaL_checkint(L, 1);
+      int u = luaL_checkint(L, 2);
+      luaL_argcheck(L, l<=u, 2, "interval is empty");
+      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */
+      break;
+    }
+    default: return luaL_error(L, "wrong number of arguments");
+  }
+  return 1;
+}
+
+
+static int math_randomseed (lua_State *L) {
+  srand(luaL_checkint(L, 1));
+  return 0;
+}
+
+
+static const luaL_reg mathlib[] = {
+  {"abs",   math_abs},
+  {"sin",   math_sin},
+  {"cos",   math_cos},
+  {"tan",   math_tan},
+  {"asin",  math_asin},
+  {"acos",  math_acos},
+  {"atan",  math_atan},
+  {"atan2", math_atan2},
+  {"ceil",  math_ceil},
+  {"floor", math_floor},
+  {"mod",   math_mod},
+  {"frexp", math_frexp},
+  {"ldexp", math_ldexp},
+  {"sqrt",  math_sqrt},
+  {"min",   math_min},
+  {"max",   math_max},
+  {"log",   math_log},
+  {"log10", math_log10},
+  {"exp",   math_exp},
+  {"deg",   math_deg},
+  {"pow",   math_pow},
+  {"rad",   math_rad},
+  {"random",     math_random},
+  {"randomseed", math_randomseed},
+  {NULL, NULL}
+};
+
+
+/*
+** Open math library
+*/
+LUALIB_API int luaopen_math (lua_State *L) {
+  luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0);
+  lua_pushliteral(L, "pi");
+  lua_pushnumber(L, PI);
+  lua_settable(L, -3);
+  lua_pushliteral(L, "__pow");
+  lua_pushcfunction(L, math_pow);
+  lua_settable(L, LUA_GLOBALSINDEX);
+  return 1;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lmem.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lmem.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lmem.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lmem.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,90 @@
+/*
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+
+#define lmem_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+/*
+** definition for realloc function. It must assure that l_realloc(NULL,
+** 0, x) allocates a new block (ANSI C assures that). (`os' is the old
+** block size; some allocators may use that.)
+*/
+#ifndef l_realloc
+#define l_realloc(b,os,s)	realloc(b,s)
+#endif
+
+/*
+** definition for free function. (`os' is the old block size; some
+** allocators may use that.)
+*/
+#ifndef l_free
+#define l_free(b,os)	free(b)
+#endif
+
+
+#define MINSIZEARRAY	4
+
+
+void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
+                    int limit, const char *errormsg) {
+  void *newblock;
+  int newsize = (*size)*2;
+  if (newsize < MINSIZEARRAY)
+    newsize = MINSIZEARRAY;  /* minimum size */
+  else if (*size >= limit/2) {  /* cannot double it? */
+    if (*size < limit - MINSIZEARRAY)  /* try something smaller... */
+      newsize = limit;  /* still have at least MINSIZEARRAY free places */
+    else luaG_runerror(L, errormsg);
+  }
+  newblock = luaM_realloc(L, block,
+                          cast(lu_mem, *size)*cast(lu_mem, size_elems),
+                          cast(lu_mem, newsize)*cast(lu_mem, size_elems));
+  *size = newsize;  /* update only when everything else is OK */
+  return newblock;
+}
+
+
+/*
+** generic allocation routine.
+*/
+void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
+  lua_assert((oldsize == 0) == (block == NULL));
+  if (size == 0) {
+    if (block != NULL) {
+      l_free(block, oldsize);
+      block = NULL;
+    }
+    else return NULL;  /* avoid `nblocks' computations when oldsize==size==0 */
+  }
+  else if (size >= MAX_SIZET)
+    luaG_runerror(L, "memory allocation error: block too big");
+  else {
+    block = l_realloc(block, oldsize, size);
+    if (block == NULL) {
+      if (L)
+        luaD_throw(L, LUA_ERRMEM);
+      else return NULL;  /* error before creating state! */
+    }
+  }
+  if (L) {
+    lua_assert(G(L) != NULL && G(L)->nblocks > 0);
+    G(L)->nblocks -= oldsize;
+    G(L)->nblocks += size;
+  }
+  return block;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lmem.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lmem.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lmem.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lmem.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,43 @@
+/*
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lmem_h
+#define lmem_h
+
+
+#include <stddef.h>
+
+#include "llimits.h"
+#include "lua.h"
+
+#define MEMERRMSG	"not enough memory"
+
+
+void *luaM_realloc (lua_State *L, void *oldblock, lu_mem oldsize, lu_mem size);
+
+void *luaM_growaux (lua_State *L, void *block, int *size, int size_elem,
+                    int limit, const char *errormsg);
+
+#define luaM_free(L, b, s)	luaM_realloc(L, (b), (s), 0)
+#define luaM_freelem(L, b)	luaM_realloc(L, (b), sizeof(*(b)), 0)
+#define luaM_freearray(L, b, n, t)	luaM_realloc(L, (b), \
+                                      cast(lu_mem, n)*cast(lu_mem, sizeof(t)), 0)
+
+#define luaM_malloc(L, t)	luaM_realloc(L, NULL, 0, (t))
+#define luaM_new(L, t)          cast(t *, luaM_malloc(L, sizeof(t)))
+#define luaM_newvector(L, n,t)  cast(t *, luaM_malloc(L, \
+                                         cast(lu_mem, n)*cast(lu_mem, sizeof(t))))
+
+#define luaM_growvector(L,v,nelems,size,t,limit,e) \
+          if (((nelems)+1) > (size)) \
+            ((v)=cast(t *, luaM_growaux(L,v,&(size),sizeof(t),limit,e)))
+
+#define luaM_reallocvector(L, v,oldn,n,t) \
+   ((v)=cast(t *, luaM_realloc(L, v,cast(lu_mem, oldn)*cast(lu_mem, sizeof(t)), \
+                                    cast(lu_mem, n)*cast(lu_mem, sizeof(t)))))
+
+
+#endif
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/loadlib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/loadlib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/loadlib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/loadlib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,204 @@
+/*
+** Dynamic library loader for Lua
+** See Copyright Notice in lua.h
+*
+* This  Lua library  exports a  single function,  called loadlib,  which is
+* called from Lua  as loadlib(lib,init), where lib is the  full name of the
+* library to be  loaded (including the complete path) and  init is the name
+* of a function  to be called after the library  is loaded. Typically, this
+* function will register other functions,  thus making the complete library
+* available  to Lua.  The init  function is  *not* automatically  called by
+* loadlib. Instead,  loadlib returns  the init function  as a  Lua function
+* that the client  can call when it  thinks is appropriate. In  the case of
+* errors,  loadlib  returns  nil  and two  strings  describing  the  error.
+* The  first string  is  supplied by  the operating  system;  it should  be
+* informative and useful  for error messages. The second  string is "open",
+* "init", or  "absent" to identify  the error and is  meant to be  used for
+* making  decisions without  having to  look into  the first  string (whose
+* format is system-dependent).
+*
+* This module contains  an implementation of loadlib for  Unix systems that
+* have dlfcn, an implementation for Windows,  and a stub for other systems.
+* See  the list  at  the end  of  this  file for  some  links to  available
+* implementations of dlfcn  and interfaces to other  native dynamic loaders
+* on top of which loadlib could be implemented.
+*
+*/
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#undef LOADLIB
+
+
+#ifdef USE_DLOPEN
+#define LOADLIB
+/*
+* This is an implementation of loadlib based on the dlfcn interface.
+* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+* NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
+* as an emulation layer on top of native functions.
+*/
+
+#include <dlfcn.h>
+
+static int loadlib(lua_State *L)
+{
+ const char *path=luaL_checkstring(L,1);
+ const char *init=luaL_checkstring(L,2);
+ void *lib=dlopen(path,RTLD_NOW);
+ if (lib!=NULL)
+ {
+  lua_CFunction f=(lua_CFunction) dlsym(lib,init);
+  if (f!=NULL)
+  {
+   lua_pushlightuserdata(L,lib);
+   lua_pushcclosure(L,f,1);
+   return 1;
+  }
+ }
+ /* else return appropriate error messages */
+ lua_pushnil(L);
+ lua_pushstring(L,dlerror());
+ lua_pushstring(L,(lib!=NULL) ? "init" : "open");
+ if (lib!=NULL) dlclose(lib);
+ return 3;
+}
+
+#endif
+
+
+
+/*
+** In Windows, default is to use dll; otherwise, default is not to use dll
+*/
+#ifndef USE_DLL
+#ifdef _WIN32
+#define USE_DLL	1
+#else
+#define USE_DLL	0
+#endif
+#endif
+
+
+#if USE_DLL
+#define LOADLIB
+/*
+* This is an implementation of loadlib for Windows using native functions.
+*/
+
+#include <windows.h>
+
+static void pusherror(lua_State *L)
+{
+ int error=GetLastError();
+ char buffer[128];
+ if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
+	0, error, 0, buffer, sizeof(buffer), 0))
+  lua_pushstring(L,buffer);
+ else
+  lua_pushfstring(L,"system error %d\n",error);
+}
+
+static int loadlib(lua_State *L)
+{
+ const char *path=luaL_checkstring(L,1);
+ const char *init=luaL_checkstring(L,2);
+ HINSTANCE lib=LoadLibrary(path);
+ if (lib!=NULL)
+ {
+  lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init);
+  if (f!=NULL)
+  {
+   lua_pushlightuserdata(L,lib);
+   lua_pushcclosure(L,f,1);
+   return 1;
+  }
+ }
+ lua_pushnil(L);
+ pusherror(L);
+ lua_pushstring(L,(lib!=NULL) ? "init" : "open");
+ if (lib!=NULL) FreeLibrary(lib);
+ return 3;
+}
+
+#endif
+
+
+
+#ifndef LOADLIB
+/* Fallback for other systems */
+
+/*
+** Those systems support dlopen, so they should have defined USE_DLOPEN.
+** The default (no)implementation gives them a special error message.
+*/
+#ifdef linux
+#define LOADLIB
+#endif
+
+#ifdef sun
+#define LOADLIB
+#endif
+
+#ifdef sgi
+#define LOADLIB
+#endif
+
+#ifdef BSD
+#define LOADLIB
+#endif
+
+#ifdef _WIN32
+#define LOADLIB
+#endif
+
+#ifdef LOADLIB
+#undef LOADLIB
+#define LOADLIB	"`loadlib' not installed (check your Lua configuration)"
+#else
+#define LOADLIB	"`loadlib' not supported"
+#endif
+
+static int loadlib(lua_State *L)
+{
+ lua_pushnil(L);
+ lua_pushliteral(L,LOADLIB);
+ lua_pushliteral(L,"absent");
+ return 3;
+}
+#endif
+
+LUALIB_API int luaopen_loadlib (lua_State *L)
+{
+ lua_register(L,"loadlib",loadlib);
+ return 0;
+}
+
+/*
+* Here are some links to available implementations of dlfcn and
+* interfaces to other native dynamic loaders on top of which loadlib
+* could be implemented. Please send contributions and corrections to us.
+*
+* AIX
+* Starting with AIX 4.2, dlfcn is included in the base OS.
+* There is also an emulation package available.
+* http://www.faqs.org/faqs/aix-faq/part4/section-21.html
+*
+* HPUX 
+* HPUX 11 has dlfcn. For HPUX 10 use shl_*.
+* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html
+* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
+*
+* Macintosh, Windows
+* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
+*
+* Mac OS X/Darwin
+* http://www.opendarwin.org/projects/dlcompat/
+*
+* GLIB has wrapper code for BeOS, OS2, Unix and Windows
+* http://cvs.gnome.org/lxr/source/glib/gmodule/
+*
+*/
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lobject.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lobject.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lobject.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lobject.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,194 @@
+/*
+** Some generic functions over Lua objects
+** See Copyright Notice in lua.h
+*/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lobject_c
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lvm.h"
+
+
+/* function to convert a string to a lua_Number */
+#ifndef lua_str2number
+#define lua_str2number(s,p)     strtod((s), (p))
+#endif
+
+
+const TObject luaO_nilobject = {LUA_TNIL, {NULL}};
+
+
+/*
+** converts an integer to a "floating point byte", represented as
+** (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm)
+*/
+int luaO_int2fb (unsigned int x) {
+  int m = 0;  /* mantissa */
+  while (x >= (1<<3)) {
+    x = (x+1) >> 1;
+    m++;
+  }
+  return (m << 3) | cast(int, x);
+}
+
+
+int luaO_log2 (unsigned int x) {
+  static const lu_byte log_8[255] = {
+    0,
+    1,1,
+    2,2,2,2,
+    3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+  };
+  if (x >= 0x00010000) {
+    if (x >= 0x01000000) return log_8[((x>>24) & 0xff) - 1]+24;
+    else return log_8[((x>>16) & 0xff) - 1]+16;
+  }
+  else {
+    if (x >= 0x00000100) return log_8[((x>>8) & 0xff) - 1]+8;
+    else if (x) return log_8[(x & 0xff) - 1];
+    return -1;  /* special `log' for 0 */
+  }
+}
+
+
+int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
+  if (ttype(t1) != ttype(t2)) return 0;
+  else switch (ttype(t1)) {
+    case LUA_TNIL:
+      return 1;
+    case LUA_TNUMBER:
+      return nvalue(t1) == nvalue(t2);
+    case LUA_TBOOLEAN:
+      return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */
+    case LUA_TLIGHTUSERDATA:
+      return pvalue(t1) == pvalue(t2);
+    default:
+      lua_assert(iscollectable(t1));
+      return gcvalue(t1) == gcvalue(t2);
+  }
+}
+
+
+int luaO_str2d (const char *s, lua_Number *result) {
+  char *endptr;
+  lua_Number res = lua_str2number(s, &endptr);
+  if (endptr == s) return 0;  /* no conversion */
+  while (isspace((unsigned char)(*endptr))) endptr++;
+  if (*endptr != '\0') return 0;  /* invalid trailing characters? */
+  *result = res;
+  return 1;
+}
+
+
+
+static void pushstr (lua_State *L, const char *str) {
+  setsvalue2s(L->top, luaS_new(L, str));
+  incr_top(L);
+}
+
+
+/* this function handles only `%d', `%c', %f, and `%s' formats */
+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
+  int n = 1;
+  pushstr(L, "");
+  for (;;) {
+    const char *e = strchr(fmt, '%');
+    if (e == NULL) break;
+    setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt));
+    incr_top(L);
+    switch (*(e+1)) {
+      case 's':
+        pushstr(L, va_arg(argp, char *));
+        break;
+      case 'c': {
+        char buff[2];
+        buff[0] = cast(char, va_arg(argp, int));
+        buff[1] = '\0';
+        pushstr(L, buff);
+        break;
+      }
+      case 'd':
+        setnvalue(L->top, cast(lua_Number, va_arg(argp, int)));
+        incr_top(L);
+        break;
+      case 'f':
+        setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber)));
+        incr_top(L);
+        break;
+      case '%':
+        pushstr(L, "%");
+        break;
+      default: lua_assert(0);
+    }
+    n += 2;
+    fmt = e+2;
+  }
+  pushstr(L, fmt);
+  luaV_concat(L, n+1, L->top - L->base - 1);
+  L->top -= n;
+  return svalue(L->top - 1);
+}
+
+
+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
+  const char *msg;
+  va_list argp;
+  va_start(argp, fmt);
+  msg = luaO_pushvfstring(L, fmt, argp);
+  va_end(argp);
+  return msg;
+}
+
+
+void luaO_chunkid (char *out, const char *source, int bufflen) {
+  if (*source == '=') {
+    strncpy(out, source+1, bufflen);  /* remove first char */
+    out[bufflen-1] = '\0';  /* ensures null termination */
+  }
+  else {  /* out = "source", or "...source" */
+    if (*source == '@') {
+      int l;
+      source++;  /* skip the `@' */
+      bufflen -= sizeof(" `...' ");
+      l = strlen(source);
+      strcpy(out, "");
+      if (l>bufflen) {
+        source += (l-bufflen);  /* get last part of file name */
+        strcat(out, "...");
+      }
+      strcat(out, source);
+    }
+    else {  /* out = [string "string"] */
+      int len = strcspn(source, "\n");  /* stop at first newline */
+      bufflen -= sizeof(" [string \"...\"] ");
+      if (len > bufflen) len = bufflen;
+      strcpy(out, "[string \"");
+      if (source[len] != '\0') {  /* must truncate? */
+        strncat(out, source, len);
+        strcat(out, "...");
+      }
+      else
+        strcat(out, source);
+      strcat(out, "\"]");
+    }
+  }
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lobject.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lobject.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lobject.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lobject.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,335 @@
+/*
+** Type definitions for Lua objects
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lobject_h
+#define lobject_h
+
+
+#include "llimits.h"
+#include "lua.h"
+
+
+/* tags for values visible from Lua */
+#define NUM_TAGS	LUA_TTHREAD
+
+
+/*
+** Extra tags for non-values
+*/
+#define LUA_TPROTO	(NUM_TAGS+1)
+#define LUA_TUPVAL	(NUM_TAGS+2)
+
+
+/*
+** Union of all collectable objects
+*/
+typedef union GCObject GCObject;
+
+
+/*
+** Common Header for all collectable objects (in macro form, to be
+** included in other objects)
+*/
+#define CommonHeader	GCObject *next; lu_byte tt; lu_byte marked
+
+
+/*
+** Common header in struct form
+*/
+typedef struct GCheader {
+  CommonHeader;
+} GCheader;
+
+
+
+
+/*
+** Union of all Lua values
+*/
+typedef union {
+  GCObject *gc;
+  void *p;
+  lua_Number n;
+  int b;
+} Value;
+
+
+/*
+** Lua values (or `tagged objects')
+*/
+typedef struct lua_TObject {
+  int tt;
+  Value value;
+} TObject;
+
+
+/* Macros to test type */
+#define ttisnil(o)	(ttype(o) == LUA_TNIL)
+#define ttisnumber(o)	(ttype(o) == LUA_TNUMBER)
+#define ttisstring(o)	(ttype(o) == LUA_TSTRING)
+#define ttistable(o)	(ttype(o) == LUA_TTABLE)
+#define ttisfunction(o)	(ttype(o) == LUA_TFUNCTION)
+#define ttisboolean(o)	(ttype(o) == LUA_TBOOLEAN)
+#define ttisuserdata(o)	(ttype(o) == LUA_TUSERDATA)
+#define ttisthread(o)	(ttype(o) == LUA_TTHREAD)
+#define ttislightuserdata(o)	(ttype(o) == LUA_TLIGHTUSERDATA)
+
+/* Macros to access values */
+#define ttype(o)	((o)->tt)
+#define gcvalue(o)	check_exp(iscollectable(o), (o)->value.gc)
+#define pvalue(o)	check_exp(ttislightuserdata(o), (o)->value.p)
+#define nvalue(o)	check_exp(ttisnumber(o), (o)->value.n)
+#define tsvalue(o)	check_exp(ttisstring(o), &(o)->value.gc->ts)
+#define uvalue(o)	check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define clvalue(o)	check_exp(ttisfunction(o), &(o)->value.gc->cl)
+#define hvalue(o)	check_exp(ttistable(o), &(o)->value.gc->h)
+#define bvalue(o)	check_exp(ttisboolean(o), (o)->value.b)
+#define thvalue(o)	check_exp(ttisthread(o), &(o)->value.gc->th)
+
+#define l_isfalse(o)	(ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
+
+/* Macros to set values */
+#define setnvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TNUMBER; i_o->value.n=(x); }
+
+#define chgnvalue(obj,x) \
+	check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x))
+
+#define setpvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TLIGHTUSERDATA; i_o->value.p=(x); }
+
+#define setbvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); }
+
+#define setsvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TSTRING; \
+    i_o->value.gc=cast(GCObject *, (x)); \
+    lua_assert(i_o->value.gc->gch.tt == LUA_TSTRING); }
+
+#define setuvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; \
+    i_o->value.gc=cast(GCObject *, (x)); \
+    lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); }
+
+#define setthvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \
+    i_o->value.gc=cast(GCObject *, (x)); \
+    lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); }
+
+#define setclvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \
+    i_o->value.gc=cast(GCObject *, (x)); \
+    lua_assert(i_o->value.gc->gch.tt == LUA_TFUNCTION); }
+
+#define sethvalue(obj,x) \
+  { TObject *i_o=(obj); i_o->tt=LUA_TTABLE; \
+    i_o->value.gc=cast(GCObject *, (x)); \
+    lua_assert(i_o->value.gc->gch.tt == LUA_TTABLE); }
+
+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+
+
+/*
+** for internal debug only
+*/
+#define checkconsistency(obj) \
+  lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
+
+
+#define setobj(obj1,obj2) \
+  { const TObject *o2=(obj2); TObject *o1=(obj1); \
+    checkconsistency(o2); \
+    o1->tt=o2->tt; o1->value = o2->value; }
+
+
+/*
+** different types of sets, according to destination
+*/
+
+/* from stack to (same) stack */
+#define setobjs2s	setobj
+/* to stack (not from same stack) */
+#define setobj2s	setobj
+#define setsvalue2s	setsvalue
+/* from table to same table */
+#define setobjt2t	setobj
+/* to table */
+#define setobj2t	setobj
+/* to new object */
+#define setobj2n	setobj
+#define setsvalue2n	setsvalue
+
+#define setttype(obj, tt) (ttype(obj) = (tt))
+
+
+#define iscollectable(o)	(ttype(o) >= LUA_TSTRING)
+
+
+
+typedef TObject *StkId;  /* index to stack elements */
+
+
+/*
+** String headers for string table
+*/
+typedef union TString {
+  L_Umaxalign dummy;  /* ensures maximum alignment for strings */
+  struct {
+    CommonHeader;
+    lu_byte reserved;
+    lu_hash hash;
+    size_t len;
+  } tsv;
+} TString;
+
+
+#define getstr(ts)	cast(const char *, (ts) + 1)
+#define svalue(o)       getstr(tsvalue(o))
+
+
+
+typedef union Udata {
+  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
+  struct {
+    CommonHeader;
+    struct Table *metatable;
+    size_t len;
+  } uv;
+} Udata;
+
+
+
+
+/*
+** Function Prototypes
+*/
+typedef struct Proto {
+  CommonHeader;
+  TObject *k;  /* constants used by the function */
+  Instruction *code;
+  struct Proto **p;  /* functions defined inside the function */
+  int *lineinfo;  /* map from opcodes to source lines */
+  struct LocVar *locvars;  /* information about local variables */
+  TString **upvalues;  /* upvalue names */
+  TString  *source;
+  int sizeupvalues;
+  int sizek;  /* size of `k' */
+  int sizecode;
+  int sizelineinfo;
+  int sizep;  /* size of `p' */
+  int sizelocvars;
+  int lineDefined;
+  GCObject *gclist;
+  lu_byte nups;  /* number of upvalues */
+  lu_byte numparams;
+  lu_byte is_vararg;
+  lu_byte maxstacksize;
+} Proto;
+
+
+typedef struct LocVar {
+  TString *varname;
+  int startpc;  /* first point where variable is active */
+  int endpc;    /* first point where variable is dead */
+} LocVar;
+
+
+
+/*
+** Upvalues
+*/
+
+typedef struct UpVal {
+  CommonHeader;
+  TObject *v;  /* points to stack or to its own value */
+  TObject value;  /* the value (when closed) */
+} UpVal;
+
+
+/*
+** Closures
+*/
+
+#define ClosureHeader \
+	CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist
+
+typedef struct CClosure {
+  ClosureHeader;
+  lua_CFunction f;
+  TObject upvalue[1];
+} CClosure;
+
+
+typedef struct LClosure {
+  ClosureHeader;
+  struct Proto *p;
+  TObject g;  /* global table for this closure */
+  UpVal *upvals[1];
+} LClosure;
+
+
+typedef union Closure {
+  CClosure c;
+  LClosure l;
+} Closure;
+
+
+#define iscfunction(o)	(ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
+#define isLfunction(o)	(ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
+
+
+/*
+** Tables
+*/
+
+typedef struct Node {
+  TObject i_key;
+  TObject i_val;
+  struct Node *next;  /* for chaining */
+} Node;
+
+
+typedef struct Table {
+  CommonHeader;
+  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ 
+  lu_byte lsizenode;  /* log2 of size of `node' array */
+  struct Table *metatable;
+  TObject *array;  /* array part */
+  Node *node;
+  Node *firstfree;  /* this position is free; all positions after it are full */
+  GCObject *gclist;
+  int sizearray;  /* size of `array' array */
+} Table;
+
+
+
+/*
+** `module' operation for hashing (size is always a power of 2)
+*/
+#define lmod(s,size) \
+	check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))
+
+
+#define twoto(x)	(1<<(x))
+#define sizenode(t)	(twoto((t)->lsizenode))
+
+
+
+extern const TObject luaO_nilobject;
+
+int luaO_log2 (unsigned int x);
+int luaO_int2fb (unsigned int x);
+#define fb2int(x)	(((x) & 7) << ((x) >> 3))
+
+int luaO_rawequalObj (const TObject *t1, const TObject *t2);
+int luaO_str2d (const char *s, lua_Number *result);
+
+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp);
+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+void luaO_chunkid (char *out, const char *source, int len);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,101 @@
+/*
+** extracted automatically from lopcodes.h by mkprint.lua
+** DO NOT EDIT
+** See Copyright Notice in lua.h
+*/
+
+
+#define lopcodes_c
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lopcodes.h"
+
+
+#ifdef LUA_OPNAMES
+
+const char *const luaP_opnames[] = {
+  "MOVE",
+  "LOADK",
+  "LOADBOOL",
+  "LOADNIL",
+  "GETUPVAL",
+  "GETGLOBAL",
+  "GETTABLE",
+  "SETGLOBAL",
+  "SETUPVAL",
+  "SETTABLE",
+  "NEWTABLE",
+  "SELF",
+  "ADD",
+  "SUB",
+  "MUL",
+  "DIV",
+  "POW",
+  "UNM",
+  "NOT",
+  "CONCAT",
+  "JMP",
+  "EQ",
+  "LT",
+  "LE",
+  "TEST",
+  "CALL",
+  "TAILCALL",
+  "RETURN",
+  "FORLOOP",
+  "TFORLOOP",
+  "TFORPREP",
+  "SETLIST",
+  "SETLISTO",
+  "CLOSE",
+  "CLOSURE"
+};
+
+#endif
+
+#define opmode(t,b,bk,ck,sa,k,m) (((t)<<OpModeT) | \
+   ((b)<<OpModeBreg) | ((bk)<<OpModeBrk) | ((ck)<<OpModeCrk) | \
+   ((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
+
+
+const lu_byte luaP_opmodes[NUM_OPCODES] = {
+/*       T  B Bk Ck sA  K  mode			   opcode    */
+  opmode(0, 1, 0, 0, 1, 0, iABC)		/* OP_MOVE */
+ ,opmode(0, 0, 0, 0, 1, 1, iABx)		/* OP_LOADK */
+ ,opmode(0, 0, 0, 0, 1, 0, iABC)		/* OP_LOADBOOL */
+ ,opmode(0, 1, 0, 0, 1, 0, iABC)		/* OP_LOADNIL */
+ ,opmode(0, 0, 0, 0, 1, 0, iABC)		/* OP_GETUPVAL */
+ ,opmode(0, 0, 0, 0, 1, 1, iABx)		/* OP_GETGLOBAL */
+ ,opmode(0, 1, 0, 1, 1, 0, iABC)		/* OP_GETTABLE */
+ ,opmode(0, 0, 0, 0, 0, 1, iABx)		/* OP_SETGLOBAL */
+ ,opmode(0, 0, 0, 0, 0, 0, iABC)		/* OP_SETUPVAL */
+ ,opmode(0, 0, 1, 1, 0, 0, iABC)		/* OP_SETTABLE */
+ ,opmode(0, 0, 0, 0, 1, 0, iABC)		/* OP_NEWTABLE */
+ ,opmode(0, 1, 0, 1, 1, 0, iABC)		/* OP_SELF */
+ ,opmode(0, 0, 1, 1, 1, 0, iABC)		/* OP_ADD */
+ ,opmode(0, 0, 1, 1, 1, 0, iABC)		/* OP_SUB */
+ ,opmode(0, 0, 1, 1, 1, 0, iABC)		/* OP_MUL */
+ ,opmode(0, 0, 1, 1, 1, 0, iABC)		/* OP_DIV */
+ ,opmode(0, 0, 1, 1, 1, 0, iABC)		/* OP_POW */
+ ,opmode(0, 1, 0, 0, 1, 0, iABC)		/* OP_UNM */
+ ,opmode(0, 1, 0, 0, 1, 0, iABC)		/* OP_NOT */
+ ,opmode(0, 1, 0, 1, 1, 0, iABC)		/* OP_CONCAT */
+ ,opmode(0, 0, 0, 0, 0, 0, iAsBx)		/* OP_JMP */
+ ,opmode(1, 0, 1, 1, 0, 0, iABC)		/* OP_EQ */
+ ,opmode(1, 0, 1, 1, 0, 0, iABC)		/* OP_LT */
+ ,opmode(1, 0, 1, 1, 0, 0, iABC)		/* OP_LE */
+ ,opmode(1, 1, 0, 0, 1, 0, iABC)		/* OP_TEST */
+ ,opmode(0, 0, 0, 0, 0, 0, iABC)		/* OP_CALL */
+ ,opmode(0, 0, 0, 0, 0, 0, iABC)		/* OP_TAILCALL */
+ ,opmode(0, 0, 0, 0, 0, 0, iABC)		/* OP_RETURN */
+ ,opmode(0, 0, 0, 0, 0, 0, iAsBx)		/* OP_FORLOOP */
+ ,opmode(1, 0, 0, 0, 0, 0, iABC)		/* OP_TFORLOOP */
+ ,opmode(0, 0, 0, 0, 0, 0, iAsBx)		/* OP_TFORPREP */
+ ,opmode(0, 0, 0, 0, 0, 0, iABx)		/* OP_SETLIST */
+ ,opmode(0, 0, 0, 0, 0, 0, iABx)		/* OP_SETLISTO */
+ ,opmode(0, 0, 0, 0, 0, 0, iABC)		/* OP_CLOSE */
+ ,opmode(0, 0, 0, 0, 1, 0, iABx)		/* OP_CLOSURE */
+};
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lopcodes.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,237 @@
+/*
+** Opcodes for Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lopcodes_h
+#define lopcodes_h
+
+#include "llimits.h"
+
+
+/*===========================================================================
+  We assume that instructions are unsigned numbers.
+  All instructions have an opcode in the first 6 bits.
+  Instructions can have the following fields:
+	`A' : 8 bits
+	`B' : 9 bits
+	`C' : 9 bits
+	`Bx' : 18 bits (`B' and `C' together)
+	`sBx' : signed Bx
+
+  A signed argument is represented in excess K; that is, the number
+  value is the unsigned value minus K. K is exactly the maximum value
+  for that argument (so that -max is represented by 0, and +max is
+  represented by 2*max), which is half the maximum for the corresponding
+  unsigned argument.
+===========================================================================*/
+
+
+enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
+
+
+/*
+** size and position of opcode arguments.
+*/
+#define SIZE_C		9
+#define SIZE_B		9
+#define SIZE_Bx		(SIZE_C + SIZE_B)
+#define SIZE_A		8
+
+#define SIZE_OP		6
+
+#define POS_C		SIZE_OP
+#define POS_B		(POS_C + SIZE_C)
+#define POS_Bx		POS_C
+#define POS_A		(POS_B + SIZE_B)
+
+
+/*
+** limits for opcode arguments.
+** we use (signed) int to manipulate most arguments,
+** so they must fit in BITS_INT-1 bits (-1 for sign)
+*/
+#if SIZE_Bx < BITS_INT-1
+#define MAXARG_Bx        ((1<<SIZE_Bx)-1)
+#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */
+#else
+#define MAXARG_Bx        MAX_INT
+#define MAXARG_sBx        MAX_INT
+#endif
+
+
+#define MAXARG_A        ((1<<SIZE_A)-1)
+#define MAXARG_B        ((1<<SIZE_B)-1)
+#define MAXARG_C        ((1<<SIZE_C)-1)
+
+
+/* creates a mask with `n' 1 bits at position `p' */
+#define MASK1(n,p)	((~((~(Instruction)0)<<n))<<p)
+
+/* creates a mask with `n' 0 bits at position `p' */
+#define MASK0(n,p)	(~MASK1(n,p))
+
+/*
+** the following macros help to manipulate instructions
+*/
+
+#define GET_OPCODE(i)	(cast(OpCode, (i)&MASK1(SIZE_OP,0)))
+#define SET_OPCODE(i,o)	((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o)))
+
+#define GETARG_A(i)	(cast(int, (i)>>POS_A))
+#define SETARG_A(i,u)	((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
+		((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
+
+#define GETARG_B(i)	(cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
+#define SETARG_B(i,b)	((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
+		((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
+
+#define GETARG_C(i)	(cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
+#define SETARG_C(i,b)	((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
+		((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
+
+#define GETARG_Bx(i)	(cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
+#define SETARG_Bx(i,b)	((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
+		((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
+
+#define GETARG_sBx(i)	(GETARG_Bx(i)-MAXARG_sBx)
+#define SETARG_sBx(i,b)	SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
+
+
+#define CREATE_ABC(o,a,b,c)	(cast(Instruction, o) \
+			| (cast(Instruction, a)<<POS_A) \
+			| (cast(Instruction, b)<<POS_B) \
+			| (cast(Instruction, c)<<POS_C))
+
+#define CREATE_ABx(o,a,bc)	(cast(Instruction, o) \
+			| (cast(Instruction, a)<<POS_A) \
+			| (cast(Instruction, bc)<<POS_Bx))
+
+
+
+
+/*
+** invalid register that fits in 8 bits
+*/
+#define NO_REG		MAXARG_A
+
+
+/*
+** R(x) - register
+** Kst(x) - constant (in constant table)
+** RK(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
+*/
+
+
+/*
+** grep "ORDER OP" if you change these enums
+*/
+
+typedef enum {
+/*----------------------------------------------------------------------
+name		args	description
+------------------------------------------------------------------------*/
+OP_MOVE,/*	A B	R(A) := R(B)					*/
+OP_LOADK,/*	A Bx	R(A) := Kst(Bx)					*/
+OP_LOADBOOL,/*	A B C	R(A) := (Bool)B; if (C) PC++			*/
+OP_LOADNIL,/*	A B	R(A) := ... := R(B) := nil			*/
+OP_GETUPVAL,/*	A B	R(A) := UpValue[B]				*/
+
+OP_GETGLOBAL,/*	A Bx	R(A) := Gbl[Kst(Bx)]				*/
+OP_GETTABLE,/*	A B C	R(A) := R(B)[RK(C)]				*/
+
+OP_SETGLOBAL,/*	A Bx	Gbl[Kst(Bx)] := R(A)				*/
+OP_SETUPVAL,/*	A B	UpValue[B] := R(A)				*/
+OP_SETTABLE,/*	A B C	R(A)[RK(B)] := RK(C)				*/
+
+OP_NEWTABLE,/*	A B C	R(A) := {} (size = B,C)				*/
+
+OP_SELF,/*	A B C	R(A+1) := R(B); R(A) := R(B)[RK(C)]		*/
+
+OP_ADD,/*	A B C	R(A) := RK(B) + RK(C)				*/
+OP_SUB,/*	A B C	R(A) := RK(B) - RK(C)				*/
+OP_MUL,/*	A B C	R(A) := RK(B) * RK(C)				*/
+OP_DIV,/*	A B C	R(A) := RK(B) / RK(C)				*/
+OP_POW,/*	A B C	R(A) := RK(B) ^ RK(C)				*/
+OP_UNM,/*	A B	R(A) := -R(B)					*/
+OP_NOT,/*	A B	R(A) := not R(B)				*/
+
+OP_CONCAT,/*	A B C	R(A) := R(B).. ... ..R(C)			*/
+
+OP_JMP,/*	sBx	PC += sBx					*/
+
+OP_EQ,/*	A B C	if ((RK(B) == RK(C)) ~= A) then pc++		*/
+OP_LT,/*	A B C	if ((RK(B) <  RK(C)) ~= A) then pc++  		*/
+OP_LE,/*	A B C	if ((RK(B) <= RK(C)) ~= A) then pc++  		*/
+
+OP_TEST,/*	A B C	if (R(B) <=> C) then R(A) := R(B) else pc++	*/ 
+
+OP_CALL,/*	A B C	R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_TAILCALL,/*	A B C	return R(A)(R(A+1), ... ,R(A+B-1))		*/
+OP_RETURN,/*	A B	return R(A), ... ,R(A+B-2)	(see note)	*/
+
+OP_FORLOOP,/*	A sBx	R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBx	*/
+
+OP_TFORLOOP,/*	A C	R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); 
+                        if R(A+2) ~= nil then pc++			*/
+OP_TFORPREP,/*	A sBx	if type(R(A)) == table then R(A+1):=R(A), R(A):=next;
+			PC += sBx					*/
+
+OP_SETLIST,/*	A Bx	R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1	*/
+OP_SETLISTO,/*	A Bx							*/
+
+OP_CLOSE,/*	A 	close all variables in the stack up to (>=) R(A)*/
+OP_CLOSURE/*	A Bx	R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/
+} OpCode;
+
+
+#define NUM_OPCODES	(cast(int, OP_CLOSURE+1))
+
+
+
+/*===========================================================================
+  Notes:
+  (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+      and can be 0: OP_CALL then sets `top' to last_result+1, so
+      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
+
+  (2) In OP_RETURN, if (B == 0) then return up to `top'
+
+  (3) For comparisons, B specifies what conditions the test should accept.
+
+  (4) All `skips' (pc++) assume that next instruction is a jump
+===========================================================================*/
+
+
+/*
+** masks for instruction properties
+*/  
+enum OpModeMask {
+  OpModeBreg = 2,       /* B is a register */
+  OpModeBrk,		/* B is a register/constant */
+  OpModeCrk,           /* C is a register/constant */
+  OpModesetA,           /* instruction set register A */
+  OpModeK,              /* Bx is a constant */
+  OpModeT		/* operator is a test */
+  
+};
+
+
+extern const lu_byte luaP_opmodes[NUM_OPCODES];
+
+#define getOpMode(m)            (cast(enum OpMode, luaP_opmodes[m] & 3))
+#define testOpMode(m, b)        (luaP_opmodes[m] & (1 << (b)))
+
+
+#ifdef LUA_OPNAMES
+extern const char *const luaP_opnames[];  /* opcode names */
+#endif
+
+
+
+/* number of list items to accumulate before a SETLIST instruction */
+/* (must be a power of 2) */
+#define LFIELDS_PER_FLUSH	32
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lparser.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lparser.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lparser.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lparser.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1333 @@
+/*
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lparser_c
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "lfunc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+
+
+
+
+#define getlocvar(fs, i)	((fs)->f->locvars[(fs)->actvar[i]])
+
+
+#define enterlevel(ls)	if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \
+		luaX_syntaxerror(ls, "too many syntax levels");
+#define leavelevel(ls)	((ls)->nestlevel--)
+
+
+/*
+** nodes for block list (list of active blocks)
+*/
+typedef struct BlockCnt {
+  struct BlockCnt *previous;  /* chain */
+  int breaklist;  /* list of jumps out of this loop */
+  int nactvar;  /* # active local variables outside the breakable structure */
+  int upval;  /* true if some variable in the block is an upvalue */
+  int isbreakable;  /* true if `block' is a loop */
+} BlockCnt;
+
+
+
+/*
+** prototypes for recursive non-terminal functions
+*/
+static void chunk (LexState *ls);
+static void expr (LexState *ls, expdesc *v);
+static void error_expected (LexState *ls, int token) __attribute__((noreturn));
+
+
+
+static void next (LexState *ls) {
+  ls->lastline = ls->linenumber;
+  if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */
+    ls->t = ls->lookahead;  /* use this one */
+    ls->lookahead.token = TK_EOS;  /* and discharge it */
+  }
+  else
+    ls->t.token = luaX_lex(ls, &ls->t.seminfo);  /* read next token */
+}
+
+
+static void lookahead (LexState *ls) {
+  lua_assert(ls->lookahead.token == TK_EOS);
+  ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo);
+}
+
+
+static void error_expected (LexState *ls, int token) {
+  luaX_syntaxerror(ls,
+         luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token)));
+}
+
+
+static int testnext (LexState *ls, int c) {
+  if (ls->t.token == c) {
+    next(ls);
+    return 1;
+  }
+  else return 0;
+}
+
+
+static void check (LexState *ls, int c) {
+  if (!testnext(ls, c))
+    error_expected(ls, c);
+}
+
+
+#define check_condition(ls,c,msg)	{ if (!(c)) luaX_syntaxerror(ls, msg); }
+
+
+
+static void check_match (LexState *ls, int what, int who, int where) {
+  if (!testnext(ls, what)) {
+    if (where == ls->linenumber)
+      error_expected(ls, what);
+    else {
+      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
+             "`%s' expected (to close `%s' at line %d)",
+              luaX_token2str(ls, what), luaX_token2str(ls, who), where));
+    }
+  }
+}
+
+
+static TString *str_checkname (LexState *ls) {
+  TString *ts;
+  check_condition(ls, (ls->t.token == TK_NAME), "<name> expected");
+  ts = ls->t.seminfo.ts;
+  next(ls);
+  return ts;
+}
+
+
+static void init_exp (expdesc *e, expkind k, int i) {
+  e->f = e->t = NO_JUMP;
+  e->k = k;
+  e->info = i;
+}
+
+
+static void codestring (LexState *ls, expdesc *e, TString *s) {
+  init_exp(e, VK, luaK_stringK(ls->fs, s));
+}
+
+
+static void checkname(LexState *ls, expdesc *e) {
+  codestring(ls, e, str_checkname(ls));
+}
+
+
+static int luaI_registerlocalvar (LexState *ls, TString *varname) {
+  FuncState *fs = ls->fs;
+  Proto *f = fs->f;
+  luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
+                  LocVar, MAX_INT, "");
+  f->locvars[fs->nlocvars].varname = varname;
+  return fs->nlocvars++;
+}
+
+
+static void new_localvar (LexState *ls, TString *name, int n) {
+  FuncState *fs = ls->fs;
+  luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "local variables");
+  fs->actvar[fs->nactvar+n] = luaI_registerlocalvar(ls, name);
+}
+
+
+static void adjustlocalvars (LexState *ls, int nvars) {
+  FuncState *fs = ls->fs;
+  fs->nactvar += nvars;
+  for (; nvars; nvars--) {
+    getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
+  }
+}
+
+
+static void removevars (LexState *ls, int tolevel) {
+  FuncState *fs = ls->fs;
+  while (fs->nactvar > tolevel)
+    getlocvar(fs, --fs->nactvar).endpc = fs->pc;
+}
+
+
+static void new_localvarstr (LexState *ls, const char *name, int n) {
+  new_localvar(ls, luaS_new(ls->L, name), n);
+}
+
+
+static void create_local (LexState *ls, const char *name) {
+  new_localvarstr(ls, name, 0);
+  adjustlocalvars(ls, 1);
+}
+
+
+static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
+  int i;
+  Proto *f = fs->f;
+  for (i=0; i<f->nups; i++) {
+    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) {
+      lua_assert(fs->f->upvalues[i] == name);
+      return i;
+    }
+  }
+  /* new one */
+  luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues");
+  luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues,
+                  TString *, MAX_INT, "");
+  fs->f->upvalues[f->nups] = name;
+  fs->upvalues[f->nups] = *v;
+  return f->nups++;
+}
+
+
+static int searchvar (FuncState *fs, TString *n) {
+  int i;
+  for (i=fs->nactvar-1; i >= 0; i--) {
+    if (n == getlocvar(fs, i).varname)
+      return i;
+  }
+  return -1;  /* not found */
+}
+
+
+static void markupval (FuncState *fs, int level) {
+  BlockCnt *bl = fs->bl;
+  while (bl && bl->nactvar > level) bl = bl->previous;
+  if (bl) bl->upval = 1;
+}
+
+
+static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
+  if (fs == NULL)  /* no more levels? */
+    init_exp(var, VGLOBAL, NO_REG);  /* default is global variable */
+  else {
+    int v = searchvar(fs, n);  /* look up at current level */
+    if (v >= 0) {
+      init_exp(var, VLOCAL, v);
+      if (!base)
+        markupval(fs, v);  /* local will be used as an upval */
+    }
+    else {  /* not found at current level; try upper one */
+      singlevaraux(fs->prev, n, var, 0);
+      if (var->k == VGLOBAL) {
+        if (base)
+          var->info = luaK_stringK(fs, n);  /* info points to global name */
+      }
+      else {  /* LOCAL or UPVAL */
+        var->info = indexupvalue(fs, n, var);
+        var->k = VUPVAL;  /* upvalue in this level */
+      }
+    }
+  }
+}
+
+
+static TString *singlevar (LexState *ls, expdesc *var, int base) {
+  TString *varname = str_checkname(ls);
+  singlevaraux(ls->fs, varname, var, base);
+  return varname;
+}
+
+
+static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
+  FuncState *fs = ls->fs;
+  int extra = nvars - nexps;
+  if (e->k == VCALL) {
+    extra++;  /* includes call itself */
+    if (extra <= 0) extra = 0;
+    else luaK_reserveregs(fs, extra-1);
+    luaK_setcallreturns(fs, e, extra);  /* call provides the difference */
+  }
+  else {
+    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */
+    if (extra > 0) {
+      int reg = fs->freereg;
+      luaK_reserveregs(fs, extra);
+      luaK_nil(fs, reg, extra);
+    }
+  }
+}
+
+
+static void code_params (LexState *ls, int nparams, int dots) {
+  FuncState *fs = ls->fs;
+  adjustlocalvars(ls, nparams);
+  luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters");
+  fs->f->numparams = cast(lu_byte, fs->nactvar);
+  fs->f->is_vararg = cast(lu_byte, dots);
+  if (dots)
+    create_local(ls, "arg");
+  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */
+}
+
+
+static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) {
+  bl->breaklist = NO_JUMP;
+  bl->isbreakable = isbreakable;
+  bl->nactvar = fs->nactvar;
+  bl->upval = 0;
+  bl->previous = fs->bl;
+  fs->bl = bl;
+  lua_assert(fs->freereg == fs->nactvar);
+}
+
+
+static void leaveblock (FuncState *fs) {
+  BlockCnt *bl = fs->bl;
+  fs->bl = bl->previous;
+  removevars(fs->ls, bl->nactvar);
+  if (bl->upval)
+    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+  lua_assert(bl->nactvar == fs->nactvar);
+  fs->freereg = fs->nactvar;  /* free registers */
+  luaK_patchtohere(fs, bl->breaklist);
+}
+
+
+static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
+  FuncState *fs = ls->fs;
+  Proto *f = fs->f;
+  int i;
+  luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
+                  MAXARG_Bx, "constant table overflow");
+  f->p[fs->np++] = func->f;
+  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+  for (i=0; i<func->f->nups; i++) {
+    OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
+    luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
+  }
+}
+
+
+static void open_func (LexState *ls, FuncState *fs) {
+  Proto *f = luaF_newproto(ls->L);
+  fs->f = f;
+  fs->prev = ls->fs;  /* linked list of funcstates */
+  fs->ls = ls;
+  fs->L = ls->L;
+  ls->fs = fs;
+  fs->pc = 0;
+  fs->lasttarget = 0;
+  fs->jpc = NO_JUMP;
+  fs->freereg = 0;
+  fs->nk = 0;
+  fs->h = luaH_new(ls->L, 0, 0);
+  fs->np = 0;
+  fs->nlocvars = 0;
+  fs->nactvar = 0;
+  fs->bl = NULL;
+  f->source = ls->source;
+  f->maxstacksize = 2;  /* registers 0/1 are always valid */
+}
+
+
+static void close_func (LexState *ls) {
+  lua_State *L = ls->L;
+  FuncState *fs = ls->fs;
+  Proto *f = fs->f;
+  removevars(ls, 0);
+  luaK_codeABC(fs, OP_RETURN, 0, 1, 0);  /* final return */
+  luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
+  f->sizecode = fs->pc;
+  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
+  f->sizelineinfo = fs->pc;
+  luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject);
+  f->sizek = fs->nk;
+  luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
+  f->sizep = fs->np;
+  luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
+  f->sizelocvars = fs->nlocvars;
+  luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
+  f->sizeupvalues = f->nups;
+  lua_assert(luaG_checkcode(f));
+  lua_assert(fs->bl == NULL);
+  ls->fs = fs->prev;
+}
+
+
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
+  struct LexState lexstate;
+  struct FuncState funcstate;
+  lexstate.buff = buff;
+  lexstate.nestlevel = 0;
+  luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
+  open_func(&lexstate, &funcstate);
+  next(&lexstate);  /* read first token */
+  chunk(&lexstate);
+  check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
+  close_func(&lexstate);
+  lua_assert(funcstate.prev == NULL);
+  lua_assert(funcstate.f->nups == 0);
+  lua_assert(lexstate.nestlevel == 0);
+  return funcstate.f;
+}
+
+
+
+/*============================================================*/
+/* GRAMMAR RULES */
+/*============================================================*/
+
+
+static void luaY_field (LexState *ls, expdesc *v) {
+  /* field -> ['.' | ':'] NAME */
+  FuncState *fs = ls->fs;
+  expdesc key;
+  luaK_exp2anyreg(fs, v);
+  next(ls);  /* skip the dot or colon */
+  checkname(ls, &key);
+  luaK_indexed(fs, v, &key);
+}
+
+
+static void luaY_index (LexState *ls, expdesc *v) {
+  /* index -> '[' expr ']' */
+  next(ls);  /* skip the '[' */
+  expr(ls, v);
+  luaK_exp2val(ls->fs, v);
+  check(ls, ']');
+}
+
+
+/*
+** {======================================================================
+** Rules for Constructors
+** =======================================================================
+*/
+
+
+struct ConsControl {
+  expdesc v;  /* last list item read */
+  expdesc *t;  /* table descriptor */
+  int nh;  /* total number of `record' elements */
+  int na;  /* total number of array elements */
+  int tostore;  /* number of array elements pending to be stored */
+};
+
+
+static void recfield (LexState *ls, struct ConsControl *cc) {
+  /* recfield -> (NAME | `['exp1`]') = exp1 */
+  FuncState *fs = ls->fs;
+  int reg = ls->fs->freereg;
+  expdesc key, val;
+  if (ls->t.token == TK_NAME) {
+    luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor");
+    cc->nh++;
+    checkname(ls, &key);
+  }
+  else  /* ls->t.token == '[' */
+    luaY_index(ls, &key);
+  check(ls, '=');
+  luaK_exp2RK(fs, &key);
+  expr(ls, &val);
+  luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key),
+                                             luaK_exp2RK(fs, &val));
+  fs->freereg = reg;  /* free registers */
+}
+
+
+static void closelistfield (FuncState *fs, struct ConsControl *cc) {
+  if (cc->v.k == VVOID) return;  /* there is no list item */
+  luaK_exp2nextreg(fs, &cc->v);
+  cc->v.k = VVOID;
+  if (cc->tostore == LFIELDS_PER_FLUSH) {
+    luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1);  /* flush */
+    cc->tostore = 0;  /* no more items pending */
+    fs->freereg = cc->t->info + 1;  /* free registers */
+  }
+}
+
+
+static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
+  if (cc->tostore == 0) return;
+  if (cc->v.k == VCALL) {
+    luaK_setcallreturns(fs, &cc->v, LUA_MULTRET);
+    luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1);
+  }
+  else {
+    if (cc->v.k != VVOID)
+      luaK_exp2nextreg(fs, &cc->v);
+    luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1);
+  }
+  fs->freereg = cc->t->info + 1;  /* free registers */
+}
+
+
+static void listfield (LexState *ls, struct ConsControl *cc) {
+  expr(ls, &cc->v);
+  luaX_checklimit(ls, cc->na, MAXARG_Bx, "items in a constructor");
+  cc->na++;
+  cc->tostore++;
+}
+
+
+static void constructor (LexState *ls, expdesc *t) {
+  /* constructor -> ?? */
+  FuncState *fs = ls->fs;
+  int line = ls->linenumber;
+  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
+  struct ConsControl cc;
+  cc.na = cc.nh = cc.tostore = 0;
+  cc.t = t;
+  init_exp(t, VRELOCABLE, pc);
+  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
+  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */
+  check(ls, '{');
+  do {
+    lua_assert(cc.v.k == VVOID || cc.tostore > 0);
+    testnext(ls, ';');  /* compatibility only */
+    if (ls->t.token == '}') break;
+    closelistfield(fs, &cc);
+    switch(ls->t.token) {
+      case TK_NAME: {  /* may be listfields or recfields */
+        lookahead(ls);
+        if (ls->lookahead.token != '=')  /* expression? */
+          listfield(ls, &cc);
+        else
+          recfield(ls, &cc);
+        break;
+      }
+      case '[': {  /* constructor_item -> recfield */
+        recfield(ls, &cc);
+        break;
+      }
+      default: {  /* constructor_part -> listfield */
+        listfield(ls, &cc);
+        break;
+      }
+    }
+  } while (testnext(ls, ',') || testnext(ls, ';'));
+  check_match(ls, '}', '{', line);
+  lastlistfield(fs, &cc);
+  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
+  SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1);  /* set initial table size */
+}
+
+/* }====================================================================== */
+
+
+
+static void parlist (LexState *ls) {
+  /* parlist -> [ param { `,' param } ] */
+  int nparams = 0;
+  int dots = 0;
+  if (ls->t.token != ')') {  /* is `parlist' not empty? */
+    do {
+      switch (ls->t.token) {
+        case TK_DOTS: dots = 1; next(ls); break;
+        case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break;
+        default: luaX_syntaxerror(ls, "<name> or `...' expected");
+      }
+    } while (!dots && testnext(ls, ','));
+  }
+  code_params(ls, nparams, dots);
+}
+
+
+static void body (LexState *ls, expdesc *e, int needself, int line) {
+  /* body ->  `(' parlist `)' chunk END */
+  FuncState new_fs;
+  open_func(ls, &new_fs);
+  new_fs.f->lineDefined = line;
+  check(ls, '(');
+  if (needself)
+    create_local(ls, "self");
+  parlist(ls);
+  check(ls, ')');
+  chunk(ls);
+  check_match(ls, TK_END, TK_FUNCTION, line);
+  close_func(ls);
+  pushclosure(ls, &new_fs, e);
+}
+
+
+static int explist1 (LexState *ls, expdesc *v) {
+  /* explist1 -> expr { `,' expr } */
+  int n = 1;  /* at least one expression */
+  expr(ls, v);
+  while (testnext(ls, ',')) {
+    luaK_exp2nextreg(ls->fs, v);
+    expr(ls, v);
+    n++;
+  }
+  return n;
+}
+
+
+static void funcargs (LexState *ls, expdesc *f) {
+  FuncState *fs = ls->fs;
+  expdesc args;
+  int base, nparams;
+  int line = ls->linenumber;
+  switch (ls->t.token) {
+    case '(': {  /* funcargs -> `(' [ explist1 ] `)' */
+      if (line != ls->lastline)
+        luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
+      next(ls);
+      if (ls->t.token == ')')  /* arg list is empty? */
+        args.k = VVOID;
+      else {
+        explist1(ls, &args);
+        luaK_setcallreturns(fs, &args, LUA_MULTRET);
+      }
+      check_match(ls, ')', '(', line);
+      break;
+    }
+    case '{': {  /* funcargs -> constructor */
+      constructor(ls, &args);
+      break;
+    }
+    case TK_STRING: {  /* funcargs -> STRING */
+      codestring(ls, &args, ls->t.seminfo.ts);
+      next(ls);  /* must use `seminfo' before `next' */
+      break;
+    }
+    default: {
+      luaX_syntaxerror(ls, "function arguments expected");
+      return;
+    }
+  }
+  lua_assert(f->k == VNONRELOC);
+  base = f->info;  /* base register for call */
+  if (args.k == VCALL)
+    nparams = LUA_MULTRET;  /* open call */
+  else {
+    if (args.k != VVOID)
+      luaK_exp2nextreg(fs, &args);  /* close last argument */
+    nparams = fs->freereg - (base+1);
+  }
+  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+  luaK_fixline(fs, line);
+  fs->freereg = base+1;  /* call remove function and arguments and leaves
+                            (unless changed) one result */
+}
+
+
+
+
+/*
+** {======================================================================
+** Expression parsing
+** =======================================================================
+*/
+
+
+static void prefixexp (LexState *ls, expdesc *v) {
+  /* prefixexp -> NAME | '(' expr ')' */
+  switch (ls->t.token) {
+    case '(': {
+      int line = ls->linenumber;
+      next(ls);
+      expr(ls, v);
+      check_match(ls, ')', '(', line);
+      luaK_dischargevars(ls->fs, v);
+      return;
+    }
+    case TK_NAME: {
+      singlevar(ls, v, 1);
+      return;
+    }
+#ifdef LUA_COMPATUPSYNTAX
+    case '%': {  /* for compatibility only */
+      TString *varname;
+      int line = ls->linenumber;
+      next(ls);  /* skip `%' */
+      varname = singlevar(ls, v, 1);
+      if (v->k != VUPVAL)
+        luaX_errorline(ls, "global upvalues are obsolete",
+                           getstr(varname), line);
+      return;
+    }
+#endif
+    default: {
+      luaX_syntaxerror(ls, "unexpected symbol");
+      return;
+    }
+  }
+}
+
+
+static void primaryexp (LexState *ls, expdesc *v) {
+  /* primaryexp ->
+        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+  FuncState *fs = ls->fs;
+  prefixexp(ls, v);
+  for (;;) {
+    switch (ls->t.token) {
+      case '.': {  /* field */
+        luaY_field(ls, v);
+        break;
+      }
+      case '[': {  /* `[' exp1 `]' */
+        expdesc key;
+        luaK_exp2anyreg(fs, v);
+        luaY_index(ls, &key);
+        luaK_indexed(fs, v, &key);
+        break;
+      }
+      case ':': {  /* `:' NAME funcargs */
+        expdesc key;
+        next(ls);
+        checkname(ls, &key);
+        luaK_self(fs, v, &key);
+        funcargs(ls, v);
+        break;
+      }
+      case '(': case TK_STRING: case '{': {  /* funcargs */
+        luaK_exp2nextreg(fs, v);
+        funcargs(ls, v);
+        break;
+      }
+      default: return;
+    }
+  }
+}
+
+
+static void simpleexp (LexState *ls, expdesc *v) {
+  /* simpleexp -> NUMBER | STRING | NIL | constructor | FUNCTION body
+               | primaryexp */
+  switch (ls->t.token) {
+    case TK_NUMBER: {
+      init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r));
+      next(ls);  /* must use `seminfo' before `next' */
+      break;
+    }
+    case TK_STRING: {
+      codestring(ls, v, ls->t.seminfo.ts);
+      next(ls);  /* must use `seminfo' before `next' */
+      break;
+    }
+    case TK_NIL: {
+      init_exp(v, VNIL, 0);
+      next(ls);
+      break;
+    }
+    case TK_TRUE: {
+      init_exp(v, VTRUE, 0);
+      next(ls);
+      break;
+    }
+    case TK_FALSE: {
+      init_exp(v, VFALSE, 0);
+      next(ls);
+      break;
+    }
+    case '{': {  /* constructor */
+      constructor(ls, v);
+      break;
+    }
+    case TK_FUNCTION: {
+      next(ls);
+      body(ls, v, 0, ls->linenumber);
+      break;
+    }
+    default: {
+      primaryexp(ls, v);
+      break;
+    }
+  }
+}
+
+
+static UnOpr getunopr (int op) {
+  switch (op) {
+    case TK_NOT: return OPR_NOT;
+    case '-': return OPR_MINUS;
+    default: return OPR_NOUNOPR;
+  }
+}
+
+
+static BinOpr getbinopr (int op) {
+  switch (op) {
+    case '+': return OPR_ADD;
+    case '-': return OPR_SUB;
+    case '*': return OPR_MULT;
+    case '/': return OPR_DIV;
+    case '^': return OPR_POW;
+    case TK_CONCAT: return OPR_CONCAT;
+    case TK_NE: return OPR_NE;
+    case TK_EQ: return OPR_EQ;
+    case '<': return OPR_LT;
+    case TK_LE: return OPR_LE;
+    case '>': return OPR_GT;
+    case TK_GE: return OPR_GE;
+    case TK_AND: return OPR_AND;
+    case TK_OR: return OPR_OR;
+    default: return OPR_NOBINOPR;
+  }
+}
+
+
+static const struct {
+  lu_byte left;  /* left priority for each binary operator */
+  lu_byte right; /* right priority */
+} priority[] = {  /* ORDER OPR */
+   {6, 6}, {6, 6}, {7, 7}, {7, 7},  /* arithmetic */
+   {10, 9}, {5, 4},                 /* power and concat (right associative) */
+   {3, 3}, {3, 3},                  /* equality */
+   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */
+   {2, 2}, {1, 1}                   /* logical (and/or) */
+};
+
+#define UNARY_PRIORITY	8  /* priority for unary operators */
+
+
+/*
+** subexpr -> (simplexep | unop subexpr) { binop subexpr }
+** where `binop' is any binary operator with a priority higher than `limit'
+*/
+static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
+  BinOpr op;
+  UnOpr uop;
+  enterlevel(ls);
+  uop = getunopr(ls->t.token);
+  if (uop != OPR_NOUNOPR) {
+    next(ls);
+    subexpr(ls, v, UNARY_PRIORITY);
+    luaK_prefix(ls->fs, uop, v);
+  }
+  else simpleexp(ls, v);
+  /* expand while operators have priorities higher than `limit' */
+  op = getbinopr(ls->t.token);
+  while (op != OPR_NOBINOPR && cast(int, priority[op].left) > limit) {
+    expdesc v2;
+    BinOpr nextop;
+    next(ls);
+    luaK_infix(ls->fs, op, v);
+    /* read sub-expression with higher priority */
+    nextop = subexpr(ls, &v2, cast(int, priority[op].right));
+    luaK_posfix(ls->fs, op, v, &v2);
+    op = nextop;
+  }
+  leavelevel(ls);
+  return op;  /* return first untreated operator */
+}
+
+
+static void expr (LexState *ls, expdesc *v) {
+  subexpr(ls, v, -1);
+}
+
+/* }==================================================================== */
+
+
+
+/*
+** {======================================================================
+** Rules for Statements
+** =======================================================================
+*/
+
+
+static int block_follow (int token) {
+  switch (token) {
+    case TK_ELSE: case TK_ELSEIF: case TK_END:
+    case TK_UNTIL: case TK_EOS:
+      return 1;
+    default: return 0;
+  }
+}
+
+
+static void block (LexState *ls) {
+  /* block -> chunk */
+  FuncState *fs = ls->fs;
+  BlockCnt bl;
+  enterblock(fs, &bl, 0);
+  chunk(ls);
+  lua_assert(bl.breaklist == NO_JUMP);
+  leaveblock(fs);
+}
+
+
+/*
+** structure to chain all variables in the left-hand side of an
+** assignment
+*/
+struct LHS_assign {
+  struct LHS_assign *prev;
+  expdesc v;  /* variable (global, local, upvalue, or indexed) */
+};
+
+
+/*
+** check whether, in an assignment to a local variable, the local variable
+** is needed in a previous assignment (to a table). If so, save original
+** local value in a safe place and use this safe copy in the previous
+** assignment.
+*/
+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
+  FuncState *fs = ls->fs;
+  int extra = fs->freereg;  /* eventual position to save local variable */
+  int conflict = 0;
+  for (; lh; lh = lh->prev) {
+    if (lh->v.k == VINDEXED) {
+      if (lh->v.info == v->info) {  /* conflict? */
+        conflict = 1;
+        lh->v.info = extra;  /* previous assignment will use safe copy */
+      }
+      if (lh->v.aux == v->info) {  /* conflict? */
+        conflict = 1;
+        lh->v.aux = extra;  /* previous assignment will use safe copy */
+      }
+    }
+  }
+  if (conflict) {
+    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->info, 0);  /* make copy */
+    luaK_reserveregs(fs, 1);
+  }
+}
+
+
+static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
+  expdesc e;
+  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
+                      "syntax error");
+  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */
+    struct LHS_assign nv;
+    nv.prev = lh;
+    primaryexp(ls, &nv.v);
+    if (nv.v.k == VLOCAL)
+      check_conflict(ls, lh, &nv.v);
+    assignment(ls, &nv, nvars+1);
+  }
+  else {  /* assignment -> `=' explist1 */
+    int nexps;
+    check(ls, '=');
+    nexps = explist1(ls, &e);
+    if (nexps != nvars) {
+      adjust_assign(ls, nvars, nexps, &e);
+      if (nexps > nvars)
+        ls->fs->freereg -= nexps - nvars;  /* remove extra values */
+    }
+    else {
+      luaK_setcallreturns(ls->fs, &e, 1);  /* close last expression */
+      luaK_storevar(ls->fs, &lh->v, &e);
+      return;  /* avoid default */
+    }
+  }
+  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */
+  luaK_storevar(ls->fs, &lh->v, &e);
+}
+
+
+static void cond (LexState *ls, expdesc *v) {
+  /* cond -> exp */
+  expr(ls, v);  /* read condition */
+  if (v->k == VNIL) v->k = VFALSE;  /* `falses' are all equal here */
+  luaK_goiftrue(ls->fs, v);
+  luaK_patchtohere(ls->fs, v->t);
+}
+
+
+/*
+** The while statement optimizes its code by coding the condition
+** after its body (and thus avoiding one jump in the loop).
+*/
+
+/*
+** maximum size of expressions for optimizing `while' code
+*/
+#ifndef MAXEXPWHILE
+#define MAXEXPWHILE	100
+#endif
+
+/*
+** the call `luaK_goiffalse' may grow the size of an expression by
+** at most this:
+*/
+#define EXTRAEXP	5
+
+static void whilestat (LexState *ls, int line) {
+  /* whilestat -> WHILE cond DO block END */
+  Instruction codeexp[MAXEXPWHILE + EXTRAEXP];
+  int lineexp;
+  int i;
+  int sizeexp;
+  FuncState *fs = ls->fs;
+  int whileinit, blockinit, expinit;
+  expdesc v;
+  BlockCnt bl;
+  next(ls);  /* skip WHILE */
+  whileinit = luaK_jump(fs);  /* jump to condition (which will be moved) */
+  expinit = luaK_getlabel(fs);
+  expr(ls, &v);  /* parse condition */
+  if (v.k == VK) v.k = VTRUE;  /* `trues' are all equal here */
+  lineexp = ls->linenumber;
+  luaK_goiffalse(fs, &v);
+  luaK_concat(fs, &v.f, fs->jpc);
+  fs->jpc = NO_JUMP;
+  sizeexp = fs->pc - expinit;  /* size of expression code */
+  if (sizeexp > MAXEXPWHILE) 
+    luaX_syntaxerror(ls, "`while' condition too complex");
+  for (i = 0; i < sizeexp; i++)  /* save `exp' code */
+    codeexp[i] = fs->f->code[expinit + i];
+  fs->pc = expinit;  /* remove `exp' code */
+  enterblock(fs, &bl, 1);
+  check(ls, TK_DO);
+  blockinit = luaK_getlabel(fs);
+  block(ls);
+  luaK_patchtohere(fs, whileinit);  /* initial jump jumps to here */
+  /* move `exp' back to code */
+  if (v.t != NO_JUMP) v.t += fs->pc - expinit;
+  if (v.f != NO_JUMP) v.f += fs->pc - expinit;
+  for (i=0; i<sizeexp; i++)
+    luaK_code(fs, codeexp[i], lineexp);
+  check_match(ls, TK_END, TK_WHILE, line);
+  leaveblock(fs);
+  luaK_patchlist(fs, v.t, blockinit);  /* true conditions go back to loop */
+  luaK_patchtohere(fs, v.f);  /* false conditions finish the loop */
+}
+
+
+static void repeatstat (LexState *ls, int line) {
+  /* repeatstat -> REPEAT block UNTIL cond */
+  FuncState *fs = ls->fs;
+  int repeat_init = luaK_getlabel(fs);
+  expdesc v;
+  BlockCnt bl;
+  enterblock(fs, &bl, 1);
+  next(ls);
+  block(ls);
+  check_match(ls, TK_UNTIL, TK_REPEAT, line);
+  cond(ls, &v);
+  luaK_patchlist(fs, v.f, repeat_init);
+  leaveblock(fs);
+}
+
+
+static int exp1 (LexState *ls) {
+  expdesc e;
+  int k;
+  expr(ls, &e);
+  k = e.k;
+  luaK_exp2nextreg(ls->fs, &e);
+  return k;
+}
+
+
+static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
+  BlockCnt bl;
+  FuncState *fs = ls->fs;
+  int prep, endfor;
+  adjustlocalvars(ls, nvars);  /* scope for all variables */
+  check(ls, TK_DO);
+  enterblock(fs, &bl, 1);  /* loop block */
+  prep = luaK_getlabel(fs);
+  block(ls);
+  luaK_patchtohere(fs, prep-1);
+  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
+                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
+  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */
+  luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);
+  leaveblock(fs);
+}
+
+
+static void fornum (LexState *ls, TString *varname, int line) {
+  /* fornum -> NAME = exp1,exp1[,exp1] DO body */
+  FuncState *fs = ls->fs;
+  int base = fs->freereg;
+  new_localvar(ls, varname, 0);
+  new_localvarstr(ls, "(for limit)", 1);
+  new_localvarstr(ls, "(for step)", 2);
+  check(ls, '=');
+  exp1(ls);  /* initial value */
+  check(ls, ',');
+  exp1(ls);  /* limit */
+  if (testnext(ls, ','))
+    exp1(ls);  /* optional step */
+  else {  /* default step = 1 */
+    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
+    luaK_reserveregs(fs, 1);
+  }
+  luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
+  luaK_jump(fs);
+  forbody(ls, base, line, 3, 1);
+}
+
+
+static void forlist (LexState *ls, TString *indexname) {
+  /* forlist -> NAME {,NAME} IN explist1 DO body */
+  FuncState *fs = ls->fs;
+  expdesc e;
+  int nvars = 0;
+  int line;
+  int base = fs->freereg;
+  new_localvarstr(ls, "(for generator)", nvars++);
+  new_localvarstr(ls, "(for state)", nvars++);
+  new_localvar(ls, indexname, nvars++);
+  while (testnext(ls, ','))
+    new_localvar(ls, str_checkname(ls), nvars++);
+  check(ls, TK_IN);
+  line = ls->linenumber;
+  adjust_assign(ls, nvars, explist1(ls, &e), &e);
+  luaK_checkstack(fs, 3);  /* extra space to call generator */
+  luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);
+  forbody(ls, base, line, nvars, 0);
+}
+
+
+static void forstat (LexState *ls, int line) {
+  /* forstat -> fornum | forlist */
+  FuncState *fs = ls->fs;
+  TString *varname;
+  BlockCnt bl;
+  enterblock(fs, &bl, 0);  /* block to control variable scope */
+  next(ls);  /* skip `for' */
+  varname = str_checkname(ls);  /* first variable name */
+  switch (ls->t.token) {
+    case '=': fornum(ls, varname, line); break;
+    case ',': case TK_IN: forlist(ls, varname); break;
+    default: luaX_syntaxerror(ls, "`=' or `in' expected");
+  }
+  check_match(ls, TK_END, TK_FOR, line);
+  leaveblock(fs);
+}
+
+
+static void test_then_block (LexState *ls, expdesc *v) {
+  /* test_then_block -> [IF | ELSEIF] cond THEN block */
+  next(ls);  /* skip IF or ELSEIF */
+  cond(ls, v);
+  check(ls, TK_THEN);
+  block(ls);  /* `then' part */
+}
+
+
+static void ifstat (LexState *ls, int line) {
+  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
+  FuncState *fs = ls->fs;
+  expdesc v;
+  int escapelist = NO_JUMP;
+  test_then_block(ls, &v);  /* IF cond THEN block */
+  while (ls->t.token == TK_ELSEIF) {
+    luaK_concat(fs, &escapelist, luaK_jump(fs));
+    luaK_patchtohere(fs, v.f);
+    test_then_block(ls, &v);  /* ELSEIF cond THEN block */
+  }
+  if (ls->t.token == TK_ELSE) {
+    luaK_concat(fs, &escapelist, luaK_jump(fs));
+    luaK_patchtohere(fs, v.f);
+    next(ls);  /* skip ELSE (after patch, for correct line info) */
+    block(ls);  /* `else' part */
+  }
+  else
+    luaK_concat(fs, &escapelist, v.f);
+  luaK_patchtohere(fs, escapelist);
+  check_match(ls, TK_END, TK_IF, line);
+}
+
+
+static void localfunc (LexState *ls) {
+  expdesc v, b;
+  FuncState *fs = ls->fs;
+  new_localvar(ls, str_checkname(ls), 0);
+  init_exp(&v, VLOCAL, fs->freereg);
+  luaK_reserveregs(fs, 1);
+  adjustlocalvars(ls, 1);
+  body(ls, &b, 0, ls->linenumber);
+  luaK_storevar(fs, &v, &b);
+  /* debug information will only see the variable after this point! */
+  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
+}
+
+
+static void localstat (LexState *ls) {
+  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
+  int nvars = 0;
+  int nexps;
+  expdesc e;
+  do {
+    new_localvar(ls, str_checkname(ls), nvars++);
+  } while (testnext(ls, ','));
+  if (testnext(ls, '='))
+    nexps = explist1(ls, &e);
+  else {
+    e.k = VVOID;
+    nexps = 0;
+  }
+  adjust_assign(ls, nvars, nexps, &e);
+  adjustlocalvars(ls, nvars);
+}
+
+
+static int funcname (LexState *ls, expdesc *v) {
+  /* funcname -> NAME {field} [`:' NAME] */
+  int needself = 0;
+  singlevar(ls, v, 1);
+  while (ls->t.token == '.')
+    luaY_field(ls, v);
+  if (ls->t.token == ':') {
+    needself = 1;
+    luaY_field(ls, v);
+  }
+  return needself;
+}
+
+
+static void funcstat (LexState *ls, int line) {
+  /* funcstat -> FUNCTION funcname body */
+  int needself;
+  expdesc v, b;
+  next(ls);  /* skip FUNCTION */
+  needself = funcname(ls, &v);
+  body(ls, &b, needself, line);
+  luaK_storevar(ls->fs, &v, &b);
+  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */
+}
+
+
+static void exprstat (LexState *ls) {
+  /* stat -> func | assignment */
+  FuncState *fs = ls->fs;
+  struct LHS_assign v;
+  primaryexp(ls, &v.v);
+  if (v.v.k == VCALL) {  /* stat -> func */
+    luaK_setcallreturns(fs, &v.v, 0);  /* call statement uses no results */
+  }
+  else {  /* stat -> assignment */
+    v.prev = NULL;
+    assignment(ls, &v, 1);
+  }
+}
+
+
+static void retstat (LexState *ls) {
+  /* stat -> RETURN explist */
+  FuncState *fs = ls->fs;
+  expdesc e;
+  int first, nret;  /* registers with returned values */
+  next(ls);  /* skip RETURN */
+  if (block_follow(ls->t.token) || ls->t.token == ';')
+    first = nret = 0;  /* return no values */
+  else {
+    nret = explist1(ls, &e);  /* optional return values */
+    if (e.k == VCALL) {
+      luaK_setcallreturns(fs, &e, LUA_MULTRET);
+      if (nret == 1) {  /* tail call? */
+        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
+        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
+      }
+      first = fs->nactvar;
+      nret = LUA_MULTRET;  /* return all values */
+    }
+    else {
+      if (nret == 1)  /* only one single value? */
+        first = luaK_exp2anyreg(fs, &e);
+      else {
+        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */
+        first = fs->nactvar;  /* return all `active' values */
+        lua_assert(nret == fs->freereg - first);
+      }
+    }
+  }
+  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
+}
+
+
+static void breakstat (LexState *ls) {
+  /* stat -> BREAK [NAME] */
+  FuncState *fs = ls->fs;
+  BlockCnt *bl = fs->bl;
+  int upval = 0;
+  next(ls);  /* skip BREAK */
+  while (bl && !bl->isbreakable) {
+    upval |= bl->upval;
+    bl = bl->previous;
+  }
+  if (!bl)
+    luaX_syntaxerror(ls, "no loop to break");
+  if (upval)
+    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+}
+
+
+static int statement (LexState *ls) {
+  int line = ls->linenumber;  /* may be needed for error messages */
+  switch (ls->t.token) {
+    case TK_IF: {  /* stat -> ifstat */
+      ifstat(ls, line);
+      return 0;
+    }
+    case TK_WHILE: {  /* stat -> whilestat */
+      whilestat(ls, line);
+      return 0;
+    }
+    case TK_DO: {  /* stat -> DO block END */
+      next(ls);  /* skip DO */
+      block(ls);
+      check_match(ls, TK_END, TK_DO, line);
+      return 0;
+    }
+    case TK_FOR: {  /* stat -> forstat */
+      forstat(ls, line);
+      return 0;
+    }
+    case TK_REPEAT: {  /* stat -> repeatstat */
+      repeatstat(ls, line);
+      return 0;
+    }
+    case TK_FUNCTION: {
+      funcstat(ls, line);  /* stat -> funcstat */
+      return 0;
+    }
+    case TK_LOCAL: {  /* stat -> localstat */
+      next(ls);  /* skip LOCAL */
+      if (testnext(ls, TK_FUNCTION))  /* local function? */
+        localfunc(ls);
+      else
+        localstat(ls);
+      return 0;
+    }
+    case TK_RETURN: {  /* stat -> retstat */
+      retstat(ls);
+      return 1;  /* must be last statement */
+    }
+    case TK_BREAK: {  /* stat -> breakstat */
+      breakstat(ls);
+      return 1;  /* must be last statement */
+    }
+    default: {
+      exprstat(ls);
+      return 0;  /* to avoid warnings */
+    }
+  }
+}
+
+
+static void chunk (LexState *ls) {
+  /* chunk -> { stat [`;'] } */
+  int islast = 0;
+  enterlevel(ls);
+  while (!islast && !block_follow(ls->t.token)) {
+    islast = statement(ls);
+    testnext(ls, ';');
+    lua_assert(ls->fs->freereg >= ls->fs->nactvar);
+    ls->fs->freereg = ls->fs->nactvar;  /* free registers */
+  }
+  leavelevel(ls);
+}
+
+/* }====================================================================== */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lparser.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lparser.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lparser.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lparser.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lparser_h
+#define lparser_h
+
+#include "llimits.h"
+#include "lobject.h"
+#include "ltable.h"
+#include "lzio.h"
+
+
+/*
+** Expression descriptor
+*/
+
+typedef enum {
+  VVOID,	/* no value */
+  VNIL,
+  VTRUE,
+  VFALSE,
+  VK,		/* info = index of constant in `k' */
+  VLOCAL,	/* info = local register */
+  VUPVAL,       /* info = index of upvalue in `upvalues' */
+  VGLOBAL,	/* info = index of table; aux = index of global name in `k' */
+  VINDEXED,	/* info = table register; aux = index register (or `k') */
+  VJMP,		/* info = instruction pc */
+  VRELOCABLE,	/* info = instruction pc */
+  VNONRELOC,	/* info = result register */
+  VCALL		/* info = result register */
+} expkind;
+
+typedef struct expdesc {
+  expkind k;
+  int info, aux;
+  int t;  /* patch list of `exit when true' */
+  int f;  /* patch list of `exit when false' */
+} expdesc;
+
+
+struct BlockCnt;  /* defined in lparser.c */
+
+
+/* state needed to generate code for a given function */
+typedef struct FuncState {
+  Proto *f;  /* current function header */
+  Table *h;  /* table to find (and reuse) elements in `k' */
+  struct FuncState *prev;  /* enclosing function */
+  struct LexState *ls;  /* lexical state */
+  struct lua_State *L;  /* copy of the Lua state */
+  struct BlockCnt *bl;  /* chain of current blocks */
+  int pc;  /* next position to code (equivalent to `ncode') */
+  int lasttarget;   /* `pc' of last `jump target' */
+  int jpc;  /* list of pending jumps to `pc' */
+  int freereg;  /* first free register */
+  int nk;  /* number of elements in `k' */
+  int np;  /* number of elements in `p' */
+  int nlocvars;  /* number of elements in `locvars' */
+  int nactvar;  /* number of active local variables */
+  expdesc upvalues[MAXUPVALUES];  /* upvalues */
+  int actvar[MAXVARS];  /* declared-variable stack */
+} FuncState;
+
+
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstate.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstate.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstate.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstate.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,219 @@
+/*
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+
+#define lstate_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+/*
+** macro to allow the inclusion of user information in Lua state
+*/
+#ifndef LUA_USERSTATE
+#define EXTRASPACE	0
+#else
+union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
+#define EXTRASPACE (sizeof(union UEXTRASPACE))
+#endif
+
+
+
+/*
+** you can change this function through the official API:
+** call `lua_setpanicf'
+*/
+static int default_panic (lua_State *L) {
+  UNUSED(L);
+  return 0;
+}
+
+
+static lua_State *mallocstate (lua_State *L) {
+  lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE);
+  if (block == NULL) return NULL;
+  else {
+    block += EXTRASPACE;
+    return cast(lua_State *, block);
+  }
+}
+
+
+static void freestate (lua_State *L, lua_State *L1) {
+  luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
+               sizeof(lua_State) + EXTRASPACE);
+}
+
+
+static void stack_init (lua_State *L1, lua_State *L) {
+  L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
+  L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
+  L1->top = L1->stack;
+  L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
+  L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
+  L1->ci = L1->base_ci;
+  L1->ci->state = CI_C;  /*  not a Lua function */
+  setnilvalue(L1->top++);  /* `function' entry for this `ci' */
+  L1->base = L1->ci->base = L1->top;
+  L1->ci->top = L1->top + LUA_MINSTACK;
+  L1->size_ci = BASIC_CI_SIZE;
+  L1->end_ci = L1->base_ci + L1->size_ci;
+}
+
+
+static void freestack (lua_State *L, lua_State *L1) {
+  luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
+  luaM_freearray(L, L1->stack, L1->stacksize, TObject);
+}
+
+
+/*
+** open parts that may cause memory-allocation errors
+*/
+static void f_luaopen (lua_State *L, void *ud) {
+  /* create a new global state */
+  global_State *g = luaM_new(NULL, global_State);
+  UNUSED(ud);
+  if (g == NULL) luaD_throw(L, LUA_ERRMEM);
+  L->l_G = g;
+  g->mainthread = L;
+  g->GCthreshold = 0;  /* mark it as unfinished state */
+  g->strt.size = 0;
+  g->strt.nuse = 0;
+  g->strt.hash = NULL;
+  setnilvalue(defaultmeta(L));
+  setnilvalue(registry(L));
+  luaZ_initbuffer(L, &g->buff);
+  g->panic = default_panic;
+  g->rootgc = NULL;
+  g->rootudata = NULL;
+  g->tmudata = NULL;
+  setnilvalue(gkey(g->dummynode));
+  setnilvalue(gval(g->dummynode));
+  g->dummynode->next = NULL;
+  g->nblocks = sizeof(lua_State) + sizeof(global_State);
+  stack_init(L, L);  /* init stack */
+  /* create default meta table with a dummy table, and then close the loop */
+  defaultmeta(L)->tt = LUA_TTABLE;
+  sethvalue(defaultmeta(L), luaH_new(L, 0, 0));
+  hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L));
+  sethvalue(gt(L), luaH_new(L, 0, 4));  /* table of globals */
+  sethvalue(registry(L), luaH_new(L, 4, 4));  /* registry */
+  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */
+  luaT_init(L);
+  luaX_init(L);
+  luaS_fix(luaS_newliteral(L, MEMERRMSG));
+  g->GCthreshold = 4*G(L)->nblocks;
+}
+
+
+static void preinit_state (lua_State *L) {
+  L->stack = NULL;
+  L->stacksize = 0;
+  L->errorJmp = NULL;
+  L->hook = NULL;
+  L->hookmask = L->hookinit = 0;
+  L->basehookcount = 0;
+  L->allowhook = 1;
+  resethookcount(L);
+  L->openupval = NULL;
+  L->size_ci = 0;
+  L->nCcalls = 0;
+  L->base_ci = L->ci = NULL;
+  L->errfunc = 0;
+  setnilvalue(gt(L));
+}
+
+
+static void close_state (lua_State *L) {
+  luaF_close(L, L->stack);  /* close all upvalues for this thread */
+  if (G(L)) {  /* close global state */
+    luaC_sweep(L, 1);  /* collect all elements */
+    lua_assert(G(L)->rootgc == NULL);
+    lua_assert(G(L)->rootudata == NULL);
+    luaS_freeall(L);
+    luaZ_freebuffer(L, &G(L)->buff);
+  }
+  freestack(L, L);
+  if (G(L)) {
+    lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State));
+    luaM_freelem(NULL, G(L));
+  }
+  freestate(NULL, L);
+}
+
+
+lua_State *luaE_newthread (lua_State *L) {
+  lua_State *L1 = mallocstate(L);
+  luaC_link(L, valtogco(L1), LUA_TTHREAD);
+  preinit_state(L1);
+  L1->l_G = L->l_G;
+  stack_init(L1, L);  /* init stack */
+  setobj2n(gt(L1), gt(L));  /* share table of globals */
+  return L1;
+}
+
+
+void luaE_freethread (lua_State *L, lua_State *L1) {
+  luaF_close(L1, L1->stack);  /* close all upvalues for this thread */
+  lua_assert(L1->openupval == NULL);
+  freestack(L, L1);
+  freestate(L, L1);
+}
+
+
+LUA_API lua_State *lua_open (void) {
+  lua_State *L = mallocstate(NULL);
+  if (L) {  /* allocation OK? */
+    L->tt = LUA_TTHREAD;
+    L->marked = 0;
+    L->next = L->gclist = NULL;
+    preinit_state(L);
+    L->l_G = NULL;
+    if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
+      /* memory allocation error: free partial state */
+      close_state(L);
+      L = NULL;
+    }
+  }
+  lua_userstateopen(L);
+  return L;
+}
+
+
+static void callallgcTM (lua_State *L, void *ud) {
+  UNUSED(ud);
+  luaC_callGCTM(L);  /* call GC metamethods for all udata */
+}
+
+
+LUA_API void lua_close (lua_State *L) {
+  lua_lock(L);
+  L = G(L)->mainthread;  /* only the main thread can be closed */
+  luaF_close(L, L->stack);  /* close all upvalues for this thread */
+  luaC_separateudata(L);  /* separate udata that have GC metamethods */
+  L->errfunc = 0;  /* no error function during GC metamethods */
+  do {  /* repeat until no more errors */
+    L->ci = L->base_ci;
+    L->base = L->top = L->ci->base;
+    L->nCcalls = 0;
+  } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
+  lua_assert(G(L)->tmudata == NULL);
+  close_state(L);
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstate.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstate.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstate.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstate.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,194 @@
+/*
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstate_h
+#define lstate_h
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "ltm.h"
+#include "lzio.h"
+
+
+/*
+** macros for thread synchronization inside Lua core machine:
+** all accesses to the global state and to global objects are synchronized.
+** Because threads can read the stack of other threads
+** (when running garbage collection),
+** a thread must also synchronize any write-access to its own stack.
+** Unsynchronized accesses are allowed only when reading its own stack,
+** or when reading immutable fields from global objects
+** (such as string values and udata values). 
+*/
+#ifndef lua_lock
+#define lua_lock(L)	((void) 0)
+#endif
+
+#ifndef lua_unlock
+#define lua_unlock(L)	((void) 0)
+#endif
+
+
+#ifndef lua_userstateopen
+#define lua_userstateopen(l)
+#endif
+
+
+
+struct lua_longjmp;  /* defined in ldo.c */
+
+
+/* default meta table (both for tables and udata) */
+#define defaultmeta(L)	(&G(L)->_defaultmeta)
+
+/* table of globals */
+#define gt(L)	(&L->_gt)
+
+/* registry */
+#define registry(L)	(&G(L)->_registry)
+
+
+/* extra stack space to handle TM calls and some other extras */
+#define EXTRA_STACK   5
+
+
+#define BASIC_CI_SIZE           8
+
+#define BASIC_STACK_SIZE        (2*LUA_MINSTACK)
+
+
+
+typedef struct stringtable {
+  GCObject **hash;
+  ls_nstr nuse;  /* number of elements */
+  int size;
+} stringtable;
+
+
+/*
+** informations about a call
+*/
+typedef struct CallInfo {
+  StkId base;  /* base for called function */
+  StkId	top;  /* top for this function */
+  int state;  /* bit fields; see below */
+  union {
+    struct {  /* for Lua functions */
+      const Instruction *savedpc;
+      const Instruction **pc;  /* points to `pc' variable in `luaV_execute' */
+      int tailcalls;  /* number of tail calls lost under this entry */
+    } l;
+    struct {  /* for C functions */
+      int dummy;  /* just to avoid an empty struct */
+    } c;
+  } u;
+} CallInfo;
+
+
+/*
+** bit fields for `CallInfo.state'
+*/
+#define CI_C		(1<<0)  /* 1 if function is a C function */
+/* 1 if (Lua) function has an active `luaV_execute' running it */
+#define CI_HASFRAME	(1<<1)
+/* 1 if Lua function is calling another Lua function (and therefore its
+   `pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */
+#define CI_CALLING	(1<<2)
+#define CI_SAVEDPC	(1<<3)  /* 1 if `savedpc' is updated */
+#define CI_YIELD	(1<<4)  /* 1 if thread is suspended */
+
+
+#define ci_func(ci)	(clvalue((ci)->base - 1))
+
+
+/*
+** `global state', shared by all threads of this state
+*/
+typedef struct global_State {
+  stringtable strt;  /* hash table for strings */
+  GCObject *rootgc;  /* list of (almost) all collectable objects */
+  GCObject *rootudata;   /* (separated) list of all userdata */
+  GCObject *tmudata;  /* list of userdata to be GC */
+  Mbuffer buff;  /* temporary buffer for string concatentation */
+  lu_mem GCthreshold;
+  lu_mem nblocks;  /* number of `bytes' currently allocated */
+  lua_CFunction panic;  /* to be called in unprotected errors */
+  TObject _registry;
+  TObject _defaultmeta;
+  struct lua_State *mainthread;
+  Node dummynode[1];  /* common node array for all empty tables */
+  TString *tmname[TM_N];  /* array with tag-method names */
+} global_State;
+
+
+/*
+** `per thread' state
+*/
+struct lua_State {
+  CommonHeader;
+  StkId top;  /* first free slot in the stack */
+  StkId base;  /* base of current function */
+  global_State *l_G;
+  CallInfo *ci;  /* call info for current function */
+  StkId stack_last;  /* last free slot in the stack */
+  StkId stack;  /* stack base */
+  int stacksize;
+  CallInfo *end_ci;  /* points after end of ci array*/
+  CallInfo *base_ci;  /* array of CallInfo's */
+  unsigned short size_ci;  /* size of array `base_ci' */
+  unsigned short nCcalls;  /* number of nested C calls */
+  lu_byte hookmask;
+  lu_byte allowhook;
+  lu_byte hookinit;
+  int basehookcount;
+  int hookcount;
+  lua_Hook hook;
+  TObject _gt;  /* table of globals */
+  GCObject *openupval;  /* list of open upvalues in this stack */
+  GCObject *gclist;
+  struct lua_longjmp *errorJmp;  /* current error recover point */
+  ptrdiff_t errfunc;  /* current error handling function (stack index) */
+};
+
+
+#define G(L)	(L->l_G)
+
+
+/*
+** Union of all collectable objects
+*/
+union GCObject {
+  GCheader gch;
+  union TString ts;
+  union Udata u;
+  union Closure cl;
+  struct Table h;
+  struct Proto p;
+  struct UpVal uv;
+  struct lua_State th;  /* thread */
+};
+
+
+/* macros to convert a GCObject into a specific value */
+#define gcotots(o)	check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#define gcotou(o)	check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
+#define gcotocl(o)	check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#define gcotoh(o)	check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
+#define gcotop(o)	check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
+#define gcotouv(o)	check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define ngcotouv(o) \
+	check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define gcototh(o)	check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+
+/* macro to convert any value into a GCObject */
+#define valtogco(v)	(cast(GCObject *, (v)))
+
+
+lua_State *luaE_newthread (lua_State *L);
+void luaE_freethread (lua_State *L, lua_State *L1);
+
+#endif
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstring.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstring.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstring.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstring.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,101 @@
+/*
+** String table (keeps all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lstring_c
+
+#include "lua.h"
+
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+
+
+
+void luaS_freeall (lua_State *L) {
+  lua_assert(G(L)->strt.nuse==0);
+  luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
+}
+
+
+void luaS_resize (lua_State *L, int newsize) {
+  GCObject **newhash = luaM_newvector(L, newsize, GCObject *);
+  stringtable *tb = &G(L)->strt;
+  int i;
+  for (i=0; i<newsize; i++) newhash[i] = NULL;
+  /* rehash */
+  for (i=0; i<tb->size; i++) {
+    GCObject *p = tb->hash[i];
+    while (p) {  /* for each node in the list */
+      GCObject *next = p->gch.next;  /* save next */
+      lu_hash h = gcotots(p)->tsv.hash;
+      int h1 = lmod(h, newsize);  /* new position */
+      lua_assert(cast(int, h%newsize) == lmod(h, newsize));
+      p->gch.next = newhash[h1];  /* chain it */
+      newhash[h1] = p;
+      p = next;
+    }
+  }
+  luaM_freearray(L, tb->hash, tb->size, TString *);
+  tb->size = newsize;
+  tb->hash = newhash;
+}
+
+
+static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
+  TString *ts = cast(TString *, luaM_malloc(L, sizestring(l)));
+  stringtable *tb;
+  ts->tsv.len = l;
+  ts->tsv.hash = h;
+  ts->tsv.marked = 0;
+  ts->tsv.tt = LUA_TSTRING;
+  ts->tsv.reserved = 0;
+  memcpy(ts+1, str, l*sizeof(char));
+  ((char *)(ts+1))[l] = '\0';  /* ending 0 */
+  tb = &G(L)->strt;
+  h = lmod(h, tb->size);
+  ts->tsv.next = tb->hash[h];  /* chain new entry */
+  tb->hash[h] = valtogco(ts);
+  tb->nuse++;
+  if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2)
+    luaS_resize(L, tb->size*2);  /* too crowded */
+  return ts;
+}
+
+
+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
+  GCObject *o;
+  lu_hash h = (lu_hash)l;  /* seed */
+  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */
+  size_t l1;
+  for (l1=l; l1>=step; l1-=step)  /* compute hash */
+    h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1]));
+  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
+       o != NULL;
+       o = o->gch.next) {
+    TString *ts = gcotots(o);
+    if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0))
+      return ts;
+  }
+  return newlstr(L, str, l, h);  /* not found */
+}
+
+
+Udata *luaS_newudata (lua_State *L, size_t s) {
+  Udata *u;
+  u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
+  u->uv.marked = (1<<1);  /* is not finalized */
+  u->uv.tt = LUA_TUSERDATA;
+  u->uv.len = s;
+  u->uv.metatable = hvalue(defaultmeta(L));
+  /* chain it on udata list */
+  u->uv.next = G(L)->rootudata;
+  G(L)->rootudata = valtogco(u);
+  return u;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstring.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstring.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstring.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstring.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,32 @@
+/*
+** String table (keep all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstring_h
+#define lstring_h
+
+
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+#define sizestring(l)	(cast(lu_mem, sizeof(union TString))+ \
+                         (cast(lu_mem, l)+1)*sizeof(char))
+
+#define sizeudata(l)	(cast(lu_mem, sizeof(union Udata))+(l))
+
+#define luaS_new(L, s)	(luaS_newlstr(L, s, strlen(s)))
+#define luaS_newliteral(L, s)	(luaS_newlstr(L, "" s, \
+                                 (sizeof(s)/sizeof(char))-1))
+
+#define luaS_fix(s)	((s)->tsv.marked |= (1<<4))
+
+void luaS_resize (lua_State *L, int newsize);
+Udata *luaS_newudata (lua_State *L, size_t s);
+void luaS_freeall (lua_State *L);
+TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstrlib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstrlib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lstrlib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lstrlib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,771 @@
+/*
+** Standard library for string operations and pattern-matching
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lstrlib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* macro to `unsign' a character */
+#ifndef uchar
+#define uchar(c)        ((unsigned char)(c))
+#endif
+
+
+typedef long sint32;	/* a signed version for size_t */
+
+
+static int str_len (lua_State *L) {
+  size_t l;
+  luaL_checklstring(L, 1, &l);
+  lua_pushnumber(L, (lua_Number)l);
+  return 1;
+}
+
+
+static sint32 posrelat (sint32 pos, size_t len) {
+  /* relative string position: negative means back from end */
+  return (pos>=0) ? pos : (sint32)len+pos+1;
+}
+
+
+static int str_sub (lua_State *L) {
+  size_t l;
+  const char *s = luaL_checklstring(L, 1, &l);
+  sint32 start = posrelat(luaL_checklong(L, 2), l);
+  sint32 end = posrelat(luaL_optlong(L, 3, -1), l);
+  if (start < 1) start = 1;
+  if (end > (sint32)l) end = (sint32)l;
+  if (start <= end)
+    lua_pushlstring(L, s+start-1, end-start+1);
+  else lua_pushliteral(L, "");
+  return 1;
+}
+
+
+static int str_lower (lua_State *L) {
+  size_t l;
+  size_t i;
+  luaL_Buffer b;
+  const char *s = luaL_checklstring(L, 1, &l);
+  luaL_buffinit(L, &b);
+  for (i=0; i<l; i++)
+    luaL_putchar(&b, tolower(uchar(s[i])));
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+static int str_upper (lua_State *L) {
+  size_t l;
+  size_t i;
+  luaL_Buffer b;
+  const char *s = luaL_checklstring(L, 1, &l);
+  luaL_buffinit(L, &b);
+  for (i=0; i<l; i++)
+    luaL_putchar(&b, toupper(uchar(s[i])));
+  luaL_pushresult(&b);
+  return 1;
+}
+
+static int str_rep (lua_State *L) {
+  size_t l;
+  luaL_Buffer b;
+  const char *s = luaL_checklstring(L, 1, &l);
+  int n = luaL_checkint(L, 2);
+  luaL_buffinit(L, &b);
+  while (n-- > 0)
+    luaL_addlstring(&b, s, l);
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+static int str_byte (lua_State *L) {
+  size_t l;
+  const char *s = luaL_checklstring(L, 1, &l);
+  sint32 pos = posrelat(luaL_optlong(L, 2, 1), l);
+  if (pos <= 0 || (size_t)(pos) > l)  /* index out of range? */
+    return 0;  /* no answer */
+  lua_pushnumber(L, uchar(s[pos-1]));
+  return 1;
+}
+
+
+static int str_char (lua_State *L) {
+  int n = lua_gettop(L);  /* number of arguments */
+  int i;
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  for (i=1; i<=n; i++) {
+    int c = luaL_checkint(L, i);
+    luaL_argcheck(L, uchar(c) == c, i, "invalid value");
+    luaL_putchar(&b, uchar(c));
+  }
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+static int writer (lua_State *L, const void* b, size_t size, void* B) {
+  (void)L;
+  luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+  return 1;
+}
+
+
+static int str_dump (lua_State *L) {
+  luaL_Buffer b;
+  luaL_checktype(L, 1, LUA_TFUNCTION);
+  luaL_buffinit(L,&b);
+  if (!lua_dump(L, writer, &b))
+    luaL_error(L, "unable to dump given function");
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+
+/*
+** {======================================================
+** PATTERN MATCHING
+** =======================================================
+*/
+
+#ifndef MAX_CAPTURES
+#define MAX_CAPTURES 32  /* arbitrary limit */
+#endif
+
+
+#define CAP_UNFINISHED	(-1)
+#define CAP_POSITION	(-2)
+
+typedef struct MatchState {
+  const char *src_init;  /* init of source string */
+  const char *src_end;  /* end (`\0') of source string */
+  lua_State *L;
+  int level;  /* total number of captures (finished or unfinished) */
+  struct {
+    const char *init;
+    sint32 len;
+  } capture[MAX_CAPTURES];
+} MatchState;
+
+
+#define ESC		'%'
+#define SPECIALS	"^$*+?.([%-"
+
+
+static int check_capture (MatchState *ms, int l) {
+  l -= '1';
+  if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
+    return luaL_error(ms->L, "invalid capture index");
+  return l;
+}
+
+
+static int capture_to_close (MatchState *ms) {
+  int level = ms->level;
+  for (level--; level>=0; level--)
+    if (ms->capture[level].len == CAP_UNFINISHED) return level;
+  return luaL_error(ms->L, "invalid pattern capture");
+}
+
+
+static const char *luaI_classend (MatchState *ms, const char *p) {
+  switch (*p++) {
+    case ESC: {
+      if (*p == '\0')
+        luaL_error(ms->L, "malformed pattern (ends with `%')");
+      return p+1;
+    }
+    case '[': {
+      if (*p == '^') p++;
+      do {  /* look for a `]' */
+        if (*p == '\0')
+          luaL_error(ms->L, "malformed pattern (missing `]')");
+        if (*(p++) == ESC && *p != '\0')
+          p++;  /* skip escapes (e.g. `%]') */
+      } while (*p != ']');
+      return p+1;
+    }
+    default: {
+      return p;
+    }
+  }
+}
+
+
+static int match_class (int c, int cl) {
+  int res;
+  switch (tolower(cl)) {
+    case 'a' : res = isalpha(c); break;
+    case 'c' : res = iscntrl(c); break;
+    case 'd' : res = isdigit(c); break;
+    case 'l' : res = islower(c); break;
+    case 'p' : res = ispunct(c); break;
+    case 's' : res = isspace(c); break;
+    case 'u' : res = isupper(c); break;
+    case 'w' : res = isalnum(c); break;
+    case 'x' : res = isxdigit(c); break;
+    case 'z' : res = (c == 0); break;
+    default: return (cl == c);
+  }
+  return (islower(cl) ? res : !res);
+}
+
+
+static int matchbracketclass (int c, const char *p, const char *ec) {
+  int sig = 1;
+  if (*(p+1) == '^') {
+    sig = 0;
+    p++;  /* skip the `^' */
+  }
+  while (++p < ec) {
+    if (*p == ESC) {
+      p++;
+      if (match_class(c, *p))
+        return sig;
+    }
+    else if ((*(p+1) == '-') && (p+2 < ec)) {
+      p+=2;
+      if (uchar(*(p-2)) <= c && c <= uchar(*p))
+        return sig;
+    }
+    else if (uchar(*p) == c) return sig;
+  }
+  return !sig;
+}
+
+
+static int luaI_singlematch (int c, const char *p, const char *ep) {
+  switch (*p) {
+    case '.': return 1;  /* matches any char */
+    case ESC: return match_class(c, *(p+1));
+    case '[': return matchbracketclass(c, p, ep-1);
+    default:  return (uchar(*p) == c);
+  }
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p);
+
+
+static const char *matchbalance (MatchState *ms, const char *s,
+                                   const char *p) {
+  if (*p == 0 || *(p+1) == 0)
+    luaL_error(ms->L, "unbalanced pattern");
+  if (*s != *p) return NULL;
+  else {
+    int b = *p;
+    int e = *(p+1);
+    int cont = 1;
+    while (++s < ms->src_end) {
+      if (*s == e) {
+        if (--cont == 0) return s+1;
+      }
+      else if (*s == b) cont++;
+    }
+  }
+  return NULL;  /* string ends out of balance */
+}
+
+
+static const char *max_expand (MatchState *ms, const char *s,
+                                 const char *p, const char *ep) {
+  sint32 i = 0;  /* counts maximum expand for item */
+  while ((s+i)<ms->src_end && luaI_singlematch(uchar(*(s+i)), p, ep))
+    i++;
+  /* keeps trying to match with the maximum repetitions */
+  while (i>=0) {
+    const char *res = match(ms, (s+i), ep+1);
+    if (res) return res;
+    i--;  /* else didn't match; reduce 1 repetition to try again */
+  }
+  return NULL;
+}
+
+
+static const char *min_expand (MatchState *ms, const char *s,
+                                 const char *p, const char *ep) {
+  for (;;) {
+    const char *res = match(ms, s, ep+1);
+    if (res != NULL)
+      return res;
+    else if (s<ms->src_end && luaI_singlematch(uchar(*s), p, ep))
+      s++;  /* try with one more repetition */
+    else return NULL;
+  }
+}
+
+
+static const char *start_capture (MatchState *ms, const char *s,
+                                    const char *p, int what) {
+  const char *res;
+  int level = ms->level;
+  if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures");
+  ms->capture[level].init = s;
+  ms->capture[level].len = what;
+  ms->level = level+1;
+  if ((res=match(ms, s, p)) == NULL)  /* match failed? */
+    ms->level--;  /* undo capture */
+  return res;
+}
+
+
+static const char *end_capture (MatchState *ms, const char *s,
+                                  const char *p) {
+  int l = capture_to_close(ms);
+  const char *res;
+  ms->capture[l].len = s - ms->capture[l].init;  /* close capture */
+  if ((res = match(ms, s, p)) == NULL)  /* match failed? */
+    ms->capture[l].len = CAP_UNFINISHED;  /* undo capture */
+  return res;
+}
+
+
+static const char *match_capture (MatchState *ms, const char *s, int l) {
+  size_t len;
+  l = check_capture(ms, l);
+  len = ms->capture[l].len;
+  if ((size_t)(ms->src_end-s) >= len &&
+      memcmp(ms->capture[l].init, s, len) == 0)
+    return s+len;
+  else return NULL;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p) {
+  init: /* using goto's to optimize tail recursion */
+  switch (*p) {
+    case '(': {  /* start capture */
+      if (*(p+1) == ')')  /* position capture? */
+        return start_capture(ms, s, p+2, CAP_POSITION);
+      else
+        return start_capture(ms, s, p+1, CAP_UNFINISHED);
+    }
+    case ')': {  /* end capture */
+      return end_capture(ms, s, p+1);
+    }
+    case ESC: {
+      switch (*(p+1)) {
+        case 'b': {  /* balanced string? */
+          s = matchbalance(ms, s, p+2);
+          if (s == NULL) return NULL;
+          p+=4; goto init;  /* else return match(ms, s, p+4); */
+        }
+        case 'f': {  /* frontier? */
+          const char *ep; char previous;
+          p += 2;
+          if (*p != '[')
+            luaL_error(ms->L, "missing `[' after `%%f' in pattern");
+          ep = luaI_classend(ms, p);  /* points to what is next */
+          previous = (s == ms->src_init) ? '\0' : *(s-1);
+          if (matchbracketclass(uchar(previous), p, ep-1) ||
+             !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
+          p=ep; goto init;  /* else return match(ms, s, ep); */
+        }
+        default: {
+          if (isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */
+            s = match_capture(ms, s, *(p+1));
+            if (s == NULL) return NULL;
+            p+=2; goto init;  /* else return match(ms, s, p+2) */
+          }
+          goto dflt;  /* case default */
+        }
+      }
+    }
+    case '\0': {  /* end of pattern */
+      return s;  /* match succeeded */
+    }
+    case '$': {
+      if (*(p+1) == '\0')  /* is the `$' the last char in pattern? */
+        return (s == ms->src_end) ? s : NULL;  /* check end of string */
+      else goto dflt;
+    }
+    default: dflt: {  /* it is a pattern item */
+      const char *ep = luaI_classend(ms, p);  /* points to what is next */
+      int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep);
+      switch (*ep) {
+        case '?': {  /* optional */
+          const char *res;
+          if (m && ((res=match(ms, s+1, ep+1)) != NULL))
+            return res;
+          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */
+        }
+        case '*': {  /* 0 or more repetitions */
+          return max_expand(ms, s, p, ep);
+        }
+        case '+': {  /* 1 or more repetitions */
+          return (m ? max_expand(ms, s+1, p, ep) : NULL);
+        }
+        case '-': {  /* 0 or more repetitions (minimum) */
+          return min_expand(ms, s, p, ep);
+        }
+        default: {
+          if (!m) return NULL;
+          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */
+        }
+      }
+    }
+  }
+}
+
+
+
+static const char *lmemfind (const char *s1, size_t l1,
+                               const char *s2, size_t l2) {
+  if (l2 == 0) return s1;  /* empty strings are everywhere */
+  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */
+  else {
+    const char *init;  /* to search for a `*s2' inside `s1' */
+    l2--;  /* 1st char will be checked by `memchr' */
+    l1 = l1-l2;  /* `s2' cannot be found after that */
+    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
+      init++;   /* 1st char is already checked */
+      if (memcmp(init, s2+1, l2) == 0)
+        return init-1;
+      else {  /* correct `l1' and `s1' to try again */
+        l1 -= init-s1;
+        s1 = init;
+      }
+    }
+    return NULL;  /* not found */
+  }
+}
+
+
+static void push_onecapture (MatchState *ms, int i) {
+  int l = ms->capture[i].len;
+  if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+  if (l == CAP_POSITION)
+    lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1));
+  else
+    lua_pushlstring(ms->L, ms->capture[i].init, l);
+}
+
+
+static int push_captures (MatchState *ms, const char *s, const char *e) {
+  int i;
+  luaL_checkstack(ms->L, ms->level, "too many captures");
+  if (ms->level == 0 && s) {  /* no explicit captures? */
+    lua_pushlstring(ms->L, s, e-s);  /* return whole match */
+    return 1;
+  }
+  else {  /* return all captures */
+    for (i=0; i<ms->level; i++)
+      push_onecapture(ms, i);
+    return ms->level;  /* number of strings pushed */
+  }
+}
+
+
+static int str_find (lua_State *L) {
+  size_t l1, l2;
+  const char *s = luaL_checklstring(L, 1, &l1);
+  const char *p = luaL_checklstring(L, 2, &l2);
+  sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1;
+  if (init < 0) init = 0;
+  else if ((size_t)(init) > l1) init = (sint32)l1;
+  if (lua_toboolean(L, 4) ||  /* explicit request? */
+      strpbrk(p, SPECIALS) == NULL) {  /* or no special characters? */
+    /* do a plain search */
+    const char *s2 = lmemfind(s+init, l1-init, p, l2);
+    if (s2) {
+      lua_pushnumber(L, (lua_Number)(s2-s+1));
+      lua_pushnumber(L, (lua_Number)(s2-s+l2));
+      return 2;
+    }
+  }
+  else {
+    MatchState ms;
+    int anchor = (*p == '^') ? (p++, 1) : 0;
+    const char *s1=s+init;
+    ms.L = L;
+    ms.src_init = s;
+    ms.src_end = s+l1;
+    do {
+      const char *res;
+      ms.level = 0;
+      if ((res=match(&ms, s1, p)) != NULL) {
+        lua_pushnumber(L, (lua_Number)(s1-s+1));  /* start */
+        lua_pushnumber(L, (lua_Number)(res-s));   /* end */
+        return push_captures(&ms, NULL, 0) + 2;
+      }
+    } while (s1++<ms.src_end && !anchor);
+  }
+  lua_pushnil(L);  /* not found */
+  return 1;
+}
+
+
+static int gfind_aux (lua_State *L) {
+  MatchState ms;
+  const char *s = lua_tostring(L, lua_upvalueindex(1));
+  size_t ls = lua_strlen(L, lua_upvalueindex(1));
+  const char *p = lua_tostring(L, lua_upvalueindex(2));
+  unsigned int idx3 = lua_tonumber(L, lua_upvalueindex(3));
+  const char *src;
+  ms.L = L;
+  ms.src_init = s;
+  ms.src_end = s+ls;
+  for (src = s + idx3;
+       src <= ms.src_end;
+       src++) {
+    const char *e;
+    ms.level = 0;
+    if ((e = match(&ms, src, p)) != NULL) {
+      int newstart = e-s;
+      if (e == src) newstart++;  /* empty match? go at least one position */
+      lua_pushnumber(L, (lua_Number)newstart);
+      lua_replace(L, lua_upvalueindex(3));
+      return push_captures(&ms, src, e);
+    }
+  }
+  return 0;  /* not found */
+}
+
+
+static int gfind (lua_State *L) {
+  luaL_checkstring(L, 1);
+  luaL_checkstring(L, 2);
+  lua_settop(L, 2);
+  lua_pushnumber(L, 0);
+  lua_pushcclosure(L, gfind_aux, 3);
+  return 1;
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b,
+                   const char *s, const char *e) {
+  lua_State *L = ms->L;
+  if (lua_isstring(L, 3)) {
+    const char *news = lua_tostring(L, 3);
+    size_t l = lua_strlen(L, 3);
+    size_t i;
+    for (i=0; i<l; i++) {
+      if (news[i] != ESC)
+        luaL_putchar(b, news[i]);
+      else {
+        i++;  /* skip ESC */
+        if (!isdigit(uchar(news[i])))
+          luaL_putchar(b, news[i]);
+        else {
+          int level = check_capture(ms, news[i]);
+          push_onecapture(ms, level);
+          luaL_addvalue(b);  /* add capture to accumulated result */
+        }
+      }
+    }
+  }
+  else {  /* is a function */
+    int n;
+    lua_pushvalue(L, 3);
+    n = push_captures(ms, s, e);
+    lua_call(L, n, 1);
+    if (lua_isstring(L, -1))
+      luaL_addvalue(b);  /* add return to accumulated result */
+    else
+      lua_pop(L, 1);  /* function result is not a string: pop it */
+  }
+}
+
+
+static int str_gsub (lua_State *L) {
+  size_t srcl;
+  const char *src = luaL_checklstring(L, 1, &srcl);
+  const char *p = luaL_checkstring(L, 2);
+  int max_s = luaL_optint(L, 4, srcl+1);
+  int anchor = (*p == '^') ? (p++, 1) : 0;
+  int n = 0;
+  MatchState ms;
+  luaL_Buffer b;
+  luaL_argcheck(L,
+    lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
+    3, "string or function expected");
+  luaL_buffinit(L, &b);
+  ms.L = L;
+  ms.src_init = src;
+  ms.src_end = src+srcl;
+  while (n < max_s) {
+    const char *e;
+    ms.level = 0;
+    e = match(&ms, src, p);
+    if (e) {
+      n++;
+      add_s(&ms, &b, src, e);
+    }
+    if (e && e>src) /* non empty match? */
+      src = e;  /* skip it */
+    else if (src < ms.src_end)
+      luaL_putchar(&b, *src++);
+    else break;
+    if (anchor) break;
+  }
+  luaL_addlstring(&b, src, ms.src_end-src);
+  luaL_pushresult(&b);
+  lua_pushnumber(L, (lua_Number)n);  /* number of substitutions */
+  return 2;
+}
+
+/* }====================================================== */
+
+
+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
+#define MAX_ITEM	512
+/* maximum size of each format specification (such as '%-099.99d') */
+#define MAX_FORMAT	20
+
+
+static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+  size_t l;
+  const char *s = luaL_checklstring(L, arg, &l);
+  luaL_putchar(b, '"');
+  while (l--) {
+    switch (*s) {
+      case '"': case '\\': case '\n': {
+        luaL_putchar(b, '\\');
+        luaL_putchar(b, *s);
+        break;
+      }
+      case '\0': {
+        luaL_addlstring(b, "\\000", 4);
+        break;
+      }
+      default: {
+        luaL_putchar(b, *s);
+        break;
+      }
+    }
+    s++;
+  }
+  luaL_putchar(b, '"');
+}
+
+
+static const char *scanformat (lua_State *L, const char *strfrmt,
+                                 char *form, int *hasprecision) {
+  const char *p = strfrmt;
+  while (strchr("-+ #0", *p)) p++;  /* skip flags */
+  if (isdigit(uchar(*p))) p++;  /* skip width */
+  if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */
+  if (*p == '.') {
+    p++;
+    *hasprecision = 1;
+    if (isdigit(uchar(*p))) p++;  /* skip precision */
+    if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */
+  }
+  if (isdigit(uchar(*p)))
+    luaL_error(L, "invalid format (width or precision too long)");
+  if (p-strfrmt+2 > MAX_FORMAT)  /* +2 to include `%' and the specifier */
+    luaL_error(L, "invalid format (too long)");
+  form[0] = '%';
+  strncpy(form+1, strfrmt, p-strfrmt+1);
+  form[p-strfrmt+2] = 0;
+  return p;
+}
+
+
+static int str_format (lua_State *L) {
+  int arg = 1;
+  size_t sfl;
+  const char *strfrmt = luaL_checklstring(L, arg, &sfl);
+  const char *strfrmt_end = strfrmt+sfl;
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  while (strfrmt < strfrmt_end) {
+    if (*strfrmt != '%')
+      luaL_putchar(&b, *strfrmt++);
+    else if (*++strfrmt == '%')
+      luaL_putchar(&b, *strfrmt++);  /* %% */
+    else { /* format item */
+      char form[MAX_FORMAT];  /* to store the format (`%...') */
+      char buff[MAX_ITEM];  /* to store the formatted item */
+      int hasprecision = 0;
+      if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$')
+        return luaL_error(L, "obsolete option (d$) to `format'");
+      arg++;
+      strfrmt = scanformat(L, strfrmt, form, &hasprecision);
+      switch (*strfrmt++) {
+        case 'c':  case 'd':  case 'i': {
+          sprintf(buff, form, luaL_checkint(L, arg));
+          break;
+        }
+        case 'o':  case 'u':  case 'x':  case 'X': {
+          const unsigned int n = luaL_checknumber(L, arg);
+          sprintf(buff, form, n);
+          break;
+        }
+        case 'e':  case 'E': case 'f':
+        case 'g': case 'G': {
+          sprintf(buff, form, luaL_checknumber(L, arg));
+          break;
+        }
+        case 'q': {
+          luaI_addquoted(L, &b, arg);
+          continue;  /* skip the `addsize' at the end */
+        }
+        case 's': {
+          size_t l;
+          const char *s = luaL_checklstring(L, arg, &l);
+          if (!hasprecision && l >= 100) {
+            /* no precision and string is too long to be formatted;
+               keep original string */
+            lua_pushvalue(L, arg);
+            luaL_addvalue(&b);
+            continue;  /* skip the `addsize' at the end */
+          }
+          else {
+            sprintf(buff, form, s);
+            break;
+          }
+        }
+        default: {  /* also treat cases `pnLlh' */
+          return luaL_error(L, "invalid option to `format'");
+        }
+      }
+      luaL_addlstring(&b, buff, strlen(buff));
+    }
+  }
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+static const luaL_reg strlib[] = {
+  {"len", str_len},
+  {"sub", str_sub},
+  {"lower", str_lower},
+  {"upper", str_upper},
+  {"char", str_char},
+  {"rep", str_rep},
+  {"byte", str_byte},
+  {"format", str_format},
+  {"dump", str_dump},
+  {"find", str_find},
+  {"gfind", gfind},
+  {"gsub", str_gsub},
+  {NULL, NULL}
+};
+
+
+/*
+** Open string library
+*/
+LUALIB_API int luaopen_string (lua_State *L) {
+  luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
+  return 1;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltable.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltable.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltable.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltable.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,508 @@
+/*
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+
+/*
+** Implementation of tables (aka arrays, objects, or hash tables).
+** Tables keep its elements in two parts: an array part and a hash part.
+** Non-negative integer keys are all candidates to be kept in the array
+** part. The actual size of the array is the largest `n' such that at
+** least half the slots between 0 and n are in use.
+** Hash uses a mix of chained scatter table with Brent's variation.
+** A main invariant of these tables is that, if an element is not
+** in its main position (i.e. the `original' position that its hash gives
+** to it), then the colliding element is in its own main position.
+** In other words, there are collisions only when two elements have the
+** same main position (i.e. the same hash values for that table size).
+** Because of that, the load factor of these tables can be 100% without
+** performance penalties.
+*/
+
+#include <string.h>
+
+#define ltable_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "ltable.h"
+
+
+/*
+** max size of array part is 2^MAXBITS
+*/
+#if BITS_INT > 26
+#define MAXBITS		24
+#else
+#define MAXBITS		(BITS_INT-2)
+#endif
+
+/* check whether `x' < 2^MAXBITS */
+#define toobig(x)	((((x)-1) >> MAXBITS) != 0)
+
+
+/* function to convert a lua_Number to int (with any rounding method) */
+#ifndef lua_number2int
+#define lua_number2int(i,n)	((i)=(int)(n))
+#endif
+
+
+#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))
+  
+#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
+#define hashboolean(t,p)        hashpow2(t, p)
+
+
+/*
+** for some types, it is better to avoid modulus by power of 2, as
+** they tend to have many 2 factors.
+*/
+#define hashmod(t,n)	(gnode(t, ((n) % ((sizenode(t)-1)|1))))
+
+
+#define hashpointer(t,p)	hashmod(t, IntPoint(p))
+
+
+/*
+** number of ints inside a lua_Number
+*/
+#define numints		cast(int, sizeof(lua_Number)/sizeof(int))
+
+
+/*
+** hash for lua_Numbers
+*/
+static Node *hashnum (const Table *t, lua_Number n) {
+  unsigned int a[numints];
+  int i;
+  n += 1;  /* normalize number (avoid -0) */
+  lua_assert(sizeof(a) <= sizeof(n));
+  memcpy(a, &n, sizeof(a));
+  for (i = 1; i < numints; i++) a[0] += a[i];
+  return hashmod(t, cast(lu_hash, a[0]));
+}
+
+
+
+/*
+** returns the `main' position of an element in a table (that is, the index
+** of its hash value)
+*/
+Node *luaH_mainposition (const Table *t, const TObject *key) {
+  switch (ttype(key)) {
+    case LUA_TNUMBER:
+      return hashnum(t, nvalue(key));
+    case LUA_TSTRING:
+      return hashstr(t, tsvalue(key));
+    case LUA_TBOOLEAN:
+      return hashboolean(t, bvalue(key));
+    case LUA_TLIGHTUSERDATA:
+      return hashpointer(t, pvalue(key));
+    default:
+      return hashpointer(t, gcvalue(key));
+  }
+}
+
+
+/*
+** returns the index for `key' if `key' is an appropriate key to live in
+** the array part of the table, -1 otherwise.
+*/
+static int arrayindex (const TObject *key) {
+  if (ttisnumber(key)) {
+    int k;
+    lua_number2int(k, (nvalue(key)));
+    if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k))
+      return k;
+  }
+  return -1;  /* `key' did not match some condition */
+}
+
+
+/*
+** returns the index of a `key' for table traversals. First goes all
+** elements in the array part, then elements in the hash part. The
+** beginning and end of a traversal are signalled by -1.
+*/
+static int luaH_index (lua_State *L, Table *t, StkId key) {
+  int i;
+  if (ttisnil(key)) return -1;  /* first iteration */
+  i = arrayindex(key);
+  if (0 <= i && i <= t->sizearray) {  /* is `key' inside array part? */
+    return i-1;  /* yes; that's the index (corrected to C) */
+  }
+  else {
+    const TObject *v = luaH_get(t, key);
+    if (v == &luaO_nilobject)
+      luaG_runerror(L, "invalid key for `next'");
+    i = cast(int, (cast(const lu_byte *, v) -
+                   cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node));
+    return i + t->sizearray;  /* hash elements are numbered after array ones */
+  }
+}
+
+
+int luaH_next (lua_State *L, Table *t, StkId key) {
+  int i = luaH_index(L, t, key);  /* find original element */
+  for (i++; i < t->sizearray; i++) {  /* try first array part */
+    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */
+      setnvalue(key, cast(lua_Number, i+1));
+      setobj2s(key+1, &t->array[i]);
+      return 1;
+    }
+  }
+  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */
+    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */
+      setobj2s(key, gkey(gnode(t, i)));
+      setobj2s(key+1, gval(gnode(t, i)));
+      return 1;
+    }
+  }
+  return 0;  /* no more elements */
+}
+
+
+/*
+** {=============================================================
+** Rehash
+** ==============================================================
+*/
+
+
+static void computesizes  (int nums[], int ntotal, int *narray, int *nhash) {
+  int i;
+  int a = nums[0];  /* number of elements smaller than 2^i */
+  int na = a;  /* number of elements to go to array part */
+  int n = (na == 0) ? -1 : 0;  /* (log of) optimal size for array part */
+  for (i = 1; a < *narray && *narray >= twoto(i-1); i++) {
+    if (nums[i] > 0) {
+      a += nums[i];
+      if (a >= twoto(i-1)) {  /* more than half elements in use? */
+        n = i;
+        na = a;
+      }
+    }
+  }
+  lua_assert(na <= *narray && *narray <= ntotal);
+  *nhash = ntotal - na;
+  *narray = (n == -1) ? 0 : twoto(n);
+  lua_assert(na <= *narray && na >= *narray/2);
+}
+
+
+static void numuse (const Table *t, int *narray, int *nhash) {
+  int nums[MAXBITS+1];
+  int i, lg;
+  int totaluse = 0;
+  /* count elements in array part */
+  for (i=0, lg=0; lg<=MAXBITS; lg++) {  /* for each slice [2^(lg-1) to 2^lg) */
+    int ttlg = twoto(lg);  /* 2^lg */
+    if (ttlg > t->sizearray) {
+      ttlg = t->sizearray;
+      if (i >= ttlg) break;
+    }
+    nums[lg] = 0;
+    for (; i<ttlg; i++) {
+      if (!ttisnil(&t->array[i])) {
+        nums[lg]++;
+        totaluse++;
+      }
+    }
+  }
+  for (; lg<=MAXBITS; lg++) nums[lg] = 0;  /* reset other counts */
+  *narray = totaluse;  /* all previous uses were in array part */
+  /* count elements in hash part */
+  i = sizenode(t);
+  while (i--) {
+    Node *n = &t->node[i];
+    if (!ttisnil(gval(n))) {
+      int k = arrayindex(gkey(n));
+      if (k >= 0) {  /* is `key' an appropriate array index? */
+        nums[luaO_log2(k-1)+1]++;  /* count as such */
+        (*narray)++;
+      }
+      totaluse++;
+    }
+  }
+  computesizes(nums, totaluse, narray, nhash);
+}
+
+
+static void setarrayvector (lua_State *L, Table *t, int size) {
+  int i;
+  luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
+  for (i=t->sizearray; i<size; i++)
+     setnilvalue(&t->array[i]);
+  t->sizearray = size;
+}
+
+
+static void setnodevector (lua_State *L, Table *t, int lsize) {
+  int i;
+  int size = twoto(lsize);
+  if (lsize > MAXBITS)
+    luaG_runerror(L, "table overflow");
+  if (lsize == 0) {  /* no elements to hash part? */
+    t->node = G(L)->dummynode;  /* use common `dummynode' */
+    lua_assert(ttisnil(gkey(t->node)));  /* assert invariants: */
+    lua_assert(ttisnil(gval(t->node)));
+    lua_assert(t->node->next == NULL);  /* (`dummynode' must be empty) */
+  }
+  else {
+    t->node = luaM_newvector(L, size, Node);
+    for (i=0; i<size; i++) {
+      t->node[i].next = NULL;
+      setnilvalue(gkey(gnode(t, i)));
+      setnilvalue(gval(gnode(t, i)));
+    }
+  }
+  t->lsizenode = cast(lu_byte, lsize);
+  t->firstfree = gnode(t, size-1);  /* first free position to be used */
+}
+
+
+static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
+  int i;
+  int oldasize = t->sizearray;
+  int oldhsize = t->lsizenode;
+  Node *nold;
+  Node temp[1];
+  if (oldhsize)
+    nold = t->node;  /* save old hash ... */
+  else {  /* old hash is `dummynode' */
+    lua_assert(t->node == G(L)->dummynode);
+    temp[0] = t->node[0];  /* copy it to `temp' */
+    nold = temp;
+    setnilvalue(gkey(G(L)->dummynode));  /* restate invariant */
+    setnilvalue(gval(G(L)->dummynode));
+    lua_assert(G(L)->dummynode->next == NULL);
+  }
+  if (nasize > oldasize)  /* array part must grow? */
+    setarrayvector(L, t, nasize);
+  /* create new hash part with appropriate size */
+  setnodevector(L, t, nhsize);  
+  /* re-insert elements */
+  if (nasize < oldasize) {  /* array part must shrink? */
+    t->sizearray = nasize;
+    /* re-insert elements from vanishing slice */
+    for (i=nasize; i<oldasize; i++) {
+      if (!ttisnil(&t->array[i]))
+        setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
+    }
+    /* shrink array */
+    luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
+  }
+  /* re-insert elements in hash part */
+  for (i = twoto(oldhsize) - 1; i >= 0; i--) {
+    Node *old = nold+i;
+    if (!ttisnil(gval(old)))
+      setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
+  }
+  if (oldhsize)
+    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
+}
+
+
+static void rehash (lua_State *L, Table *t) {
+  int nasize, nhsize;
+  numuse(t, &nasize, &nhsize);  /* compute new sizes for array and hash parts */
+  resize(L, t, nasize, luaO_log2(nhsize)+1);
+}
+
+
+
+/*
+** }=============================================================
+*/
+
+
+Table *luaH_new (lua_State *L, int narray, int lnhash) {
+  Table *t = luaM_new(L, Table);
+  luaC_link(L, valtogco(t), LUA_TTABLE);
+  t->metatable = hvalue(defaultmeta(L));
+  t->flags = cast(lu_byte, ~0);
+  /* temporary values (kept only if some malloc fails) */
+  t->array = NULL;
+  t->sizearray = 0;
+  t->lsizenode = 0;
+  t->node = NULL;
+  setarrayvector(L, t, narray);
+  setnodevector(L, t, lnhash);
+  return t;
+}
+
+
+void luaH_free (lua_State *L, Table *t) {
+  if (t->lsizenode)
+    luaM_freearray(L, t->node, sizenode(t), Node);
+  luaM_freearray(L, t->array, t->sizearray, TObject);
+  luaM_freelem(L, t);
+}
+
+
+#if 0
+/*
+** try to remove an element from a hash table; cannot move any element
+** (because gc can call `remove' during a table traversal)
+*/
+void luaH_remove (Table *t, Node *e) {
+  Node *mp = luaH_mainposition(t, gkey(e));
+  if (e != mp) {  /* element not in its main position? */
+    while (mp->next != e) mp = mp->next;  /* find previous */
+    mp->next = e->next;  /* remove `e' from its list */
+  }
+  else {
+    if (e->next != NULL) ??
+  }
+  lua_assert(ttisnil(gval(node)));
+  setnilvalue(gkey(e));  /* clear node `e' */
+  e->next = NULL;
+}
+#endif
+
+
+/*
+** inserts a new key into a hash table; first, check whether key's main 
+** position is free. If not, check whether colliding node is in its main 
+** position or not: if it is not, move colliding node to an empty place and 
+** put new key in its main position; otherwise (colliding node is in its main 
+** position), new key goes to an empty position. 
+*/
+static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
+  TObject *val;
+  Node *mp = luaH_mainposition(t, key);
+  if (!ttisnil(gval(mp))) {  /* main position is not free? */
+    Node *othern = luaH_mainposition(t, gkey(mp));  /* `mp' of colliding node */
+    Node *n = t->firstfree;  /* get a free place */
+    if (othern != mp) {  /* is colliding node out of its main position? */
+      /* yes; move colliding node into free position */
+      while (othern->next != mp) othern = othern->next;  /* find previous */
+      othern->next = n;  /* redo the chain with `n' in place of `mp' */
+      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
+      mp->next = NULL;  /* now `mp' is free */
+      setnilvalue(gval(mp));
+    }
+    else {  /* colliding node is in its own main position */
+      /* new node will go into free position */
+      n->next = mp->next;  /* chain new position */
+      mp->next = n;
+      mp = n;
+    }
+  }
+  setobj2t(gkey(mp), key);  /* write barrier */
+  lua_assert(ttisnil(gval(mp)));
+  for (;;) {  /* correct `firstfree' */
+    if (ttisnil(gkey(t->firstfree)))
+      return gval(mp);  /* OK; table still has a free place */
+    else if (t->firstfree == t->node) break;  /* cannot decrement from here */
+    else (t->firstfree)--;
+  }
+  /* no more free places; must create one */
+  setbvalue(gval(mp), 0);  /* avoid new key being removed */
+  rehash(L, t);  /* grow table */
+  val = cast(TObject *, luaH_get(t, key));  /* get new position */
+  lua_assert(ttisboolean(val));
+  setnilvalue(val);
+  return val;
+}
+
+
+/*
+** generic search function
+*/
+static const TObject *luaH_getany (Table *t, const TObject *key) {
+  if (ttisnil(key)) return &luaO_nilobject;
+  else {
+    Node *n = luaH_mainposition(t, key);
+    do {  /* check whether `key' is somewhere in the chain */
+      if (luaO_rawequalObj(gkey(n), key)) return gval(n);  /* that's it */
+      else n = n->next;
+    } while (n);
+    return &luaO_nilobject;
+  }
+}
+
+
+/*
+** search function for integers
+*/
+const TObject *luaH_getnum (Table *t, int key) {
+  if (1 <= key && key <= t->sizearray)
+    return &t->array[key-1];
+  else {
+    lua_Number nk = cast(lua_Number, key);
+    Node *n = hashnum(t, nk);
+    do {  /* check whether `key' is somewhere in the chain */
+      if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk)
+        return gval(n);  /* that's it */
+      else n = n->next;
+    } while (n);
+    return &luaO_nilobject;
+  }
+}
+
+
+/*
+** search function for strings
+*/
+const TObject *luaH_getstr (Table *t, TString *key) {
+  Node *n = hashstr(t, key);
+  do {  /* check whether `key' is somewhere in the chain */
+    if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key)
+      return gval(n);  /* that's it */
+    else n = n->next;
+  } while (n);
+  return &luaO_nilobject;
+}
+
+
+/*
+** main search function
+*/
+const TObject *luaH_get (Table *t, const TObject *key) {
+  switch (ttype(key)) {
+    case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
+    case LUA_TNUMBER: {
+      int k;
+      lua_number2int(k, (nvalue(key)));
+      if (cast(lua_Number, k) == nvalue(key))  /* is an integer index? */
+        return luaH_getnum(t, k);  /* use specialized version */
+      /* else go through */
+    }
+    default: return luaH_getany(t, key);
+  }
+}
+
+
+TObject *luaH_set (lua_State *L, Table *t, const TObject *key) {
+  const TObject *p = luaH_get(t, key);
+  t->flags = 0;
+  if (p != &luaO_nilobject)
+    return cast(TObject *, p);
+  else {
+    if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+    else if (ttisnumber(key) && nvalue(key) != nvalue(key))
+      luaG_runerror(L, "table index is NaN");
+    return newkey(L, t, key);
+  }
+}
+
+
+TObject *luaH_setnum (lua_State *L, Table *t, int key) {
+  const TObject *p = luaH_getnum(t, key);
+  if (p != &luaO_nilobject)
+    return cast(TObject *, p);
+  else {
+    TObject k;
+    setnvalue(&k, cast(lua_Number, key));
+    return newkey(L, t, &k);
+  }
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltable.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltable.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltable.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltable.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,30 @@
+/*
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltable_h
+#define ltable_h
+
+#include "lobject.h"
+
+
+#define gnode(t,i)	(&(t)->node[i])
+#define gkey(n)		(&(n)->i_key)
+#define gval(n)		(&(n)->i_val)
+
+
+const TObject *luaH_getnum (Table *t, int key);
+TObject *luaH_setnum (lua_State *L, Table *t, int key);
+const TObject *luaH_getstr (Table *t, TString *key);
+const TObject *luaH_get (Table *t, const TObject *key);
+TObject *luaH_set (lua_State *L, Table *t, const TObject *key);
+Table *luaH_new (lua_State *L, int narray, int lnhash);
+void luaH_free (lua_State *L, Table *t);
+int luaH_next (lua_State *L, Table *t, StkId key);
+
+/* exported only for debugging */
+Node *luaH_mainposition (const Table *t, const TObject *key);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltablib.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltablib.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltablib.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltablib.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,249 @@
+/*
+** Library for Table Manipulation
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define ltablib_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#define aux_getn(L,n)	(luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
+
+
+static int luaB_foreachi (lua_State *L) {
+  int i;
+  int n = aux_getn(L, 1);
+  luaL_checktype(L, 2, LUA_TFUNCTION);
+  for (i=1; i<=n; i++) {
+    lua_pushvalue(L, 2);  /* function */
+    lua_pushnumber(L, (lua_Number)i);  /* 1st argument */
+    lua_rawgeti(L, 1, i);  /* 2nd argument */
+    lua_call(L, 2, 1);
+    if (!lua_isnil(L, -1))
+      return 1;
+    lua_pop(L, 1);  /* remove nil result */
+  }
+  return 0;
+}
+
+
+static int luaB_foreach (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checktype(L, 2, LUA_TFUNCTION);
+  lua_pushnil(L);  /* first key */
+  for (;;) {
+    if (lua_next(L, 1) == 0)
+      return 0;
+    lua_pushvalue(L, 2);  /* function */
+    lua_pushvalue(L, -3);  /* key */
+    lua_pushvalue(L, -3);  /* value */
+    lua_call(L, 2, 1);
+    if (!lua_isnil(L, -1))
+      return 1;
+    lua_pop(L, 2);  /* remove value and result */
+  }
+}
+
+
+static int luaB_getn (lua_State *L) {
+  lua_pushnumber(L, (lua_Number)aux_getn(L, 1));
+  return 1;
+}
+
+
+static int luaB_setn (lua_State *L) {
+  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_setn(L, 1, luaL_checkint(L, 2));
+  return 0;
+}
+
+
+static int luaB_tinsert (lua_State *L) {
+  int v = lua_gettop(L);  /* number of arguments */
+  int n = aux_getn(L, 1) + 1;
+  int pos;  /* where to insert new element */
+  if (v == 2)  /* called with only 2 arguments */
+    pos = n;  /* insert new element at the end */
+  else {
+    pos = luaL_checkint(L, 2);  /* 2nd argument is the position */
+    if (pos > n) n = pos;  /* `grow' array if necessary */
+    v = 3;  /* function may be called with more than 3 args */
+  }
+  luaL_setn(L, 1, n);  /* new size */
+  while (--n >= pos) {  /* move up elements */
+    lua_rawgeti(L, 1, n);
+    lua_rawseti(L, 1, n+1);  /* t[n+1] = t[n] */
+  }
+  lua_pushvalue(L, v);
+  lua_rawseti(L, 1, pos);  /* t[pos] = v */
+  return 0;
+}
+
+
+static int luaB_tremove (lua_State *L) {
+  int n = aux_getn(L, 1);
+  int pos = luaL_optint(L, 2, n);
+  if (n <= 0) return 0;  /* table is `empty' */
+  luaL_setn(L, 1, n-1);  /* t.n = n-1 */
+  lua_rawgeti(L, 1, pos);  /* result = t[pos] */
+  for ( ;pos<n; pos++) {
+    lua_rawgeti(L, 1, pos+1);
+    lua_rawseti(L, 1, pos);  /* t[pos] = t[pos+1] */
+  }
+  lua_pushnil(L);
+  lua_rawseti(L, 1, n);  /* t[n] = nil */
+  return 1;
+}
+
+
+static int str_concat (lua_State *L) {
+  luaL_Buffer b;
+  size_t lsep;
+  const char *sep = luaL_optlstring(L, 2, "", &lsep);
+  int i = luaL_optint(L, 3, 1);
+  int n = luaL_optint(L, 4, 0);
+  luaL_checktype(L, 1, LUA_TTABLE);
+  if (n == 0) n = luaL_getn(L, 1);
+  luaL_buffinit(L, &b);
+  for (; i <= n; i++) {
+    lua_rawgeti(L, 1, i);
+    luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
+    luaL_addvalue(&b);
+    if (i != n)
+      luaL_addlstring(&b, sep, lsep);
+  }
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+
+/*
+** {======================================================
+** Quicksort
+** (based on `Algorithms in MODULA-3', Robert Sedgewick;
+**  Addison-Wesley, 1993.)
+*/
+
+
+static void set2 (lua_State *L, int i, int j) {
+  lua_rawseti(L, 1, i);
+  lua_rawseti(L, 1, j);
+}
+
+static int sort_comp (lua_State *L, int a, int b) {
+  if (!lua_isnil(L, 2)) {  /* function? */
+    int res;
+    lua_pushvalue(L, 2);
+    lua_pushvalue(L, a-1);  /* -1 to compensate function */
+    lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */
+    lua_call(L, 2, 1);
+    res = lua_toboolean(L, -1);
+    lua_pop(L, 1);
+    return res;
+  }
+  else  /* a < b? */
+    return lua_lessthan(L, a, b);
+}
+
+static void auxsort (lua_State *L, int l, int u) {
+  while (l < u) {  /* for tail recursion */
+    int i, j;
+    /* sort elements a[l], a[(l+u)/2] and a[u] */
+    lua_rawgeti(L, 1, l);
+    lua_rawgeti(L, 1, u);
+    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */
+      set2(L, l, u);  /* swap a[l] - a[u] */
+    else
+      lua_pop(L, 2);
+    if (u-l == 1) break;  /* only 2 elements */
+    i = (l+u)/2;
+    lua_rawgeti(L, 1, i);
+    lua_rawgeti(L, 1, l);
+    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */
+      set2(L, i, l);
+    else {
+      lua_pop(L, 1);  /* remove a[l] */
+      lua_rawgeti(L, 1, u);
+      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */
+        set2(L, i, u);
+      else
+        lua_pop(L, 2);
+    }
+    if (u-l == 2) break;  /* only 3 elements */
+    lua_rawgeti(L, 1, i);  /* Pivot */
+    lua_pushvalue(L, -1);
+    lua_rawgeti(L, 1, u-1);
+    set2(L, i, u-1);
+    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
+    i = l; j = u-1;
+    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */
+      /* repeat ++i until a[i] >= P */
+      while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
+        if (i>u) luaL_error(L, "invalid order function for sorting");
+        lua_pop(L, 1);  /* remove a[i] */
+      }
+      /* repeat --j until a[j] <= P */
+      while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
+        if (j<l) luaL_error(L, "invalid order function for sorting");
+        lua_pop(L, 1);  /* remove a[j] */
+      }
+      if (j<i) {
+        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */
+        break;
+      }
+      set2(L, i, j);
+    }
+    lua_rawgeti(L, 1, u-1);
+    lua_rawgeti(L, 1, i);
+    set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */
+    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
+    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
+    if (i-l < u-i) {
+      j=l; i=i-1; l=i+2;
+    }
+    else {
+      j=i+1; i=u; u=j-2;
+    }
+    auxsort(L, j, i);  /* call recursively the smaller one */
+  }  /* repeat the routine for the larger one */
+}
+
+static int luaB_sort (lua_State *L) {
+  int n = aux_getn(L, 1);
+  luaL_checkstack(L, 40, "");  /* assume array is smaller than 2^40 */
+  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
+    luaL_checktype(L, 2, LUA_TFUNCTION);
+  lua_settop(L, 2);  /* make sure there is two arguments */
+  auxsort(L, 1, n);
+  return 0;
+}
+
+/* }====================================================== */
+
+
+static const luaL_reg tab_funcs[] = {
+  {"concat", str_concat},
+  {"foreach", luaB_foreach},
+  {"foreachi", luaB_foreachi},
+  {"getn", luaB_getn},
+  {"setn", luaB_setn},
+  {"sort", luaB_sort},
+  {"insert", luaB_tinsert},
+  {"remove", luaB_tremove},
+  {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_table (lua_State *L) {
+  luaL_openlib(L, LUA_TABLIBNAME, tab_funcs, 0);
+  return 1;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltests.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltests.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltests.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltests.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,851 @@
+/*
+** Internal Module for Debugging of the Lua Implementation
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ltests_c
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lauxlib.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "lualib.h"
+
+
+
+/*
+** The whole module only makes sense with LUA_DEBUG on
+*/
+#ifdef LUA_DEBUG
+
+
+#define lua_pushintegral(L,i)	lua_pushnumber(L, cast(lua_Number, (i)))
+
+
+static lua_State *lua_state = NULL;
+
+int islocked = 0;
+
+
+#define func_at(L,k)	(L->ci->base+(k) - 1)
+
+
+static void setnameval (lua_State *L, const char *name, int val) {
+  lua_pushstring(L, name);
+  lua_pushintegral(L, val);
+  lua_settable(L, -3);
+}
+
+
+/*
+** {======================================================================
+** Controlled version for realloc.
+** =======================================================================
+*/
+
+#define MARK		0x55  /* 01010101 (a nice pattern) */
+
+#ifndef EXTERNMEMCHECK
+/* full memory check */
+#define HEADER	(sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
+#define MARKSIZE	16  /* size of marks after each block */
+#define blockhead(b)	(cast(char *, b) - HEADER)
+#define setsize(newblock, size)	(*cast(size_t *, newblock) = size)
+#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
+#define fillmem(mem,size)	memset(mem, -MARK, size)
+#else
+/* external memory check: don't do it twice */
+#define HEADER		0
+#define MARKSIZE	0
+#define blockhead(b)	(b)
+#define setsize(newblock, size)	/* empty */
+#define checkblocksize(b,size)	(1)
+#define fillmem(mem,size)	/* empty */
+#endif
+
+unsigned long memdebug_numblocks = 0;
+unsigned long memdebug_total = 0;
+unsigned long memdebug_maxmem = 0;
+unsigned long memdebug_memlimit = ULONG_MAX;
+
+
+static void *checkblock (void *block, size_t size) {
+  void *b = blockhead(block);
+  int i;
+  for (i=0;i<MARKSIZE;i++)
+    lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
+  return b;
+}
+
+
+static void freeblock (void *block, size_t size) {
+  if (block) {
+    lua_assert(checkblocksize(block, size));
+    block = checkblock(block, size);
+    fillmem(block, size+HEADER+MARKSIZE);  /* erase block */
+    free(block);  /* free original block */
+    memdebug_numblocks--;
+    memdebug_total -= size;
+  }
+}
+
+
+void *debug_realloc (void *block, size_t oldsize, size_t size) {
+  lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
+  /* ISO does not specify what realloc(NULL, 0) does */
+  lua_assert(block != NULL || size > 0);
+  if (size == 0) {
+    freeblock(block, oldsize);
+    return NULL;
+  }
+  else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit)
+    return NULL;  /* to test memory allocation errors */
+  else {
+    void *newblock;
+    int i;
+    size_t realsize = HEADER+size+MARKSIZE;
+    size_t commonsize = (oldsize < size) ? oldsize : size;
+    if (realsize < size) return NULL;  /* overflow! */
+    newblock = malloc(realsize);  /* alloc a new block */
+    if (newblock == NULL) return NULL;
+    if (block) {
+      memcpy(cast(char *, newblock)+HEADER, block, commonsize);
+      freeblock(block, oldsize);  /* erase (and check) old copy */
+    }
+    /* initialize new part of the block with something `weird' */
+    fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
+    memdebug_total += size;
+    if (memdebug_total > memdebug_maxmem)
+      memdebug_maxmem = memdebug_total;
+    memdebug_numblocks++;
+    setsize(newblock, size);
+    for (i=0;i<MARKSIZE;i++)
+      *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
+    return cast(char *, newblock)+HEADER;
+  }
+}
+
+
+/* }====================================================================== */
+
+
+
+/*
+** {======================================================
+** Disassembler
+** =======================================================
+*/
+
+
+static char *buildop (Proto *p, int pc, char *buff) {
+  Instruction i = p->code[pc];
+  OpCode o = GET_OPCODE(i);
+  const char *name = luaP_opnames[o];
+  int line = getline(p, pc);
+  sprintf(buff, "(%4d) %4d - ", line, pc);
+  switch (getOpMode(o)) {  
+    case iABC:
+      sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name,
+              GETARG_A(i), GETARG_B(i), GETARG_C(i));
+      break;
+    case iABx:
+      sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
+      break;
+    case iAsBx:
+      sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
+      break;
+  }
+  return buff;
+}
+
+
+#if 0
+void luaI_printcode (Proto *pt, int size) {
+  int pc;
+  for (pc=0; pc<size; pc++) {
+    char buff[100];
+    printf("%s\n", buildop(pt, pc, buff));
+  }
+  printf("-------\n");
+}
+#endif
+
+
+static int listcode (lua_State *L) {
+  int pc;
+  Proto *p;
+  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+                 1, "Lua function expected");
+  p = clvalue(func_at(L, 1))->l.p;
+  lua_newtable(L);
+  setnameval(L, "maxstack", p->maxstacksize);
+  setnameval(L, "numparams", p->numparams);
+  for (pc=0; pc<p->sizecode; pc++) {
+    char buff[100];
+    lua_pushintegral(L, pc+1);
+    lua_pushstring(L, buildop(p, pc, buff));
+    lua_settable(L, -3);
+  }
+  return 1;
+}
+
+
+static int listk (lua_State *L) {
+  Proto *p;
+  int i;
+  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+                 1, "Lua function expected");
+  p = clvalue(func_at(L, 1))->l.p;
+  lua_newtable(L);
+  for (i=0; i<p->sizek; i++) {
+    lua_pushintegral(L, i+1);
+    luaA_pushobject(L, p->k+i);
+    lua_settable(L, -3);
+  }
+  return 1;
+}
+
+
+static int listlocals (lua_State *L) {
+  Proto *p;
+  int pc = luaL_checkint(L, 2) - 1;
+  int i = 0;
+  const char *name;
+  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+                 1, "Lua function expected");
+  p = clvalue(func_at(L, 1))->l.p;
+  while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
+    lua_pushstring(L, name);
+  return i-1;
+}
+
+/* }====================================================== */
+
+
+
+
+static int get_limits (lua_State *L) {
+  lua_newtable(L);
+  setnameval(L, "BITS_INT", BITS_INT);
+  setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
+  setnameval(L, "MAXVARS", MAXVARS);
+  setnameval(L, "MAXPARAMS", MAXPARAMS);
+  setnameval(L, "MAXSTACK", MAXSTACK);
+  setnameval(L, "MAXUPVALUES", MAXUPVALUES);
+  return 1;
+}
+
+
+static int mem_query (lua_State *L) {
+  if (lua_isnone(L, 1)) {
+    lua_pushintegral(L, memdebug_total);
+    lua_pushintegral(L, memdebug_numblocks);
+    lua_pushintegral(L, memdebug_maxmem);
+    return 3;
+  }
+  else {
+    memdebug_memlimit = luaL_checkint(L, 1);
+    return 0;
+  }
+}
+
+
+static int hash_query (lua_State *L) {
+  if (lua_isnone(L, 2)) {
+    luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
+    lua_pushintegral(L, tsvalue(func_at(L, 1))->tsv.hash);
+  }
+  else {
+    TObject *o = func_at(L, 1);
+    Table *t;
+    luaL_checktype(L, 2, LUA_TTABLE);
+    t = hvalue(func_at(L, 2));
+    lua_pushintegral(L, luaH_mainposition(t, o) - t->node);
+  }
+  return 1;
+}
+
+
+static int stacklevel (lua_State *L) {
+  unsigned long a = 0;
+  lua_pushintegral(L, (int)(L->top - L->stack));
+  lua_pushintegral(L, (int)(L->stack_last - L->stack));
+  lua_pushintegral(L, (int)(L->ci - L->base_ci));
+  lua_pushintegral(L, (int)(L->end_ci - L->base_ci));
+  lua_pushintegral(L, (unsigned long)&a);
+  return 5;
+}
+
+
+static int table_query (lua_State *L) {
+  const Table *t;
+  int i = luaL_optint(L, 2, -1);
+  luaL_checktype(L, 1, LUA_TTABLE);
+  t = hvalue(func_at(L, 1));
+  if (i == -1) {
+    lua_pushintegral(L, t->sizearray);
+    lua_pushintegral(L, sizenode(t));
+    lua_pushintegral(L, t->firstfree - t->node);
+  }
+  else if (i < t->sizearray) {
+    lua_pushintegral(L, i);
+    luaA_pushobject(L, &t->array[i]);
+    lua_pushnil(L); 
+  }
+  else if ((i -= t->sizearray) < sizenode(t)) {
+    if (!ttisnil(gval(gnode(t, i))) ||
+        ttisnil(gkey(gnode(t, i))) ||
+        ttisnumber(gkey(gnode(t, i)))) {
+      luaA_pushobject(L, gkey(gnode(t, i)));
+    }
+    else
+      lua_pushstring(L, "<undef>");
+    luaA_pushobject(L, gval(gnode(t, i)));
+    if (t->node[i].next)
+      lua_pushintegral(L, t->node[i].next - t->node);
+    else
+      lua_pushnil(L);
+  }
+  return 3;
+}
+
+
+static int string_query (lua_State *L) {
+  stringtable *tb = &G(L)->strt;
+  int s = luaL_optint(L, 2, 0) - 1;
+  if (s==-1) {
+    lua_pushintegral(L ,tb->nuse);
+    lua_pushintegral(L ,tb->size);
+    return 2;
+  }
+  else if (s < tb->size) {
+    GCObject *ts;
+    int n = 0;
+    for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
+      setsvalue2s(L->top, gcotots(ts));
+      incr_top(L);
+      n++;
+    }
+    return n;
+  }
+  return 0;
+}
+
+
+static int tref (lua_State *L) {
+  int level = lua_gettop(L);
+  int lock = luaL_optint(L, 2, 1);
+  luaL_checkany(L, 1);
+  lua_pushvalue(L, 1);
+  lua_pushintegral(L, lua_ref(L, lock));
+  assert(lua_gettop(L) == level+1);  /* +1 for result */
+  return 1;
+}
+
+static int getref (lua_State *L) {
+  int level = lua_gettop(L);
+  lua_getref(L, luaL_checkint(L, 1));
+  assert(lua_gettop(L) == level+1);
+  return 1;
+}
+
+static int unref (lua_State *L) {
+  int level = lua_gettop(L);
+  lua_unref(L, luaL_checkint(L, 1));
+  assert(lua_gettop(L) == level);
+  return 0;
+}
+
+static int metatable (lua_State *L) {
+  luaL_checkany(L, 1);
+  if (lua_isnone(L, 2)) {
+    if (lua_getmetatable(L, 1) == 0)
+      lua_pushnil(L);
+  }
+  else {
+    lua_settop(L, 2);
+    luaL_checktype(L, 2, LUA_TTABLE);
+    lua_setmetatable(L, 1);
+  }
+  return 1;
+}
+
+
+static int upvalue (lua_State *L) {
+  int n = luaL_checkint(L, 2);
+  luaL_checktype(L, 1, LUA_TFUNCTION);
+  if (lua_isnone(L, 3)) {
+    const char *name = lua_getupvalue(L, 1, n);
+    if (name == NULL) return 0;
+    lua_pushstring(L, name);
+    return 2;
+  }
+  else {
+    const char *name = lua_setupvalue(L, 1, n);
+    lua_pushstring(L, name);
+    return 1;
+  }
+}
+
+
+static int newuserdata (lua_State *L) {
+  size_t size = luaL_checkint(L, 1);
+  char *p = cast(char *, lua_newuserdata(L, size));
+  while (size--) *p++ = '\0';
+  return 1;
+}
+
+
+static int pushuserdata (lua_State *L) {
+  lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
+  return 1;
+}
+
+
+static int udataval (lua_State *L) {
+  lua_pushintegral(L, cast(int, lua_touserdata(L, 1)));
+  return 1;
+}
+
+
+static int doonnewstack (lua_State *L) {
+  lua_State *L1 = lua_newthread(L);
+  size_t l;
+  const char *s = luaL_checklstring(L, 1, &l);
+  int status = luaL_loadbuffer(L1, s, l, s);
+  if (status == 0)
+    status = lua_pcall(L1, 0, 0, 0);
+  lua_pushintegral(L, status);
+  return 1;
+}
+
+
+static int s2d (lua_State *L) {
+  lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
+  return 1;
+}
+
+static int d2s (lua_State *L) {
+  double d = luaL_checknumber(L, 1);
+  lua_pushlstring(L, cast(char *, &d), sizeof(d));
+  return 1;
+}
+
+
+static int newstate (lua_State *L) {
+  lua_State *L1 = lua_open();
+  if (L1) {
+    lua_userstateopen(L1);  /* init lock */
+    lua_pushintegral(L, (unsigned long)L1);
+  }
+  else
+    lua_pushnil(L);
+  return 1;
+}
+
+
+static int loadlib (lua_State *L) {
+  static const luaL_reg libs[] = {
+    {"mathlibopen", luaopen_math},
+    {"strlibopen", luaopen_string},
+    {"iolibopen", luaopen_io},
+    {"tablibopen", luaopen_table},
+    {"dblibopen", luaopen_debug},
+    {"baselibopen", luaopen_base},
+    {NULL, NULL}
+  };
+  lua_State *L1 = cast(lua_State *,
+                       cast(unsigned long, luaL_checknumber(L, 1)));
+  lua_pushvalue(L1, LUA_GLOBALSINDEX);
+  luaL_openlib(L1, NULL, libs, 0);
+  return 0;
+}
+
+static int closestate (lua_State *L) {
+  lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
+  lua_close(L1);
+  lua_unlock(L);  /* close cannot unlock that */
+  return 0;
+}
+
+static int doremote (lua_State *L) {
+  lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
+  size_t lcode;
+  const char *code = luaL_checklstring(L, 2, &lcode);
+  int status;
+  lua_settop(L1, 0);
+  status = luaL_loadbuffer(L1, code, lcode, code);
+  if (status == 0)
+    status = lua_pcall(L1, 0, LUA_MULTRET, 0);
+  if (status != 0) {
+    lua_pushnil(L);
+    lua_pushintegral(L, status);
+    lua_pushstring(L, lua_tostring(L1, -1));
+    return 3;
+  }
+  else {
+    int i = 0;
+    while (!lua_isnone(L1, ++i))
+      lua_pushstring(L, lua_tostring(L1, i));
+    lua_pop(L1, i-1);
+    return i-1;
+  }
+}
+
+
+static int log2_aux (lua_State *L) {
+  lua_pushintegral(L, luaO_log2(luaL_checkint(L, 1)));
+  return 1;
+}
+
+static int int2fb_aux (lua_State *L) {
+  int b = luaO_int2fb(luaL_checkint(L, 1));
+  lua_pushintegral(L, b);
+  lua_pushintegral(L, fb2int(b));
+  return 2;
+}
+
+
+static int test_do (lua_State *L) {
+  const char *p = luaL_checkstring(L, 1);
+  if (*p == '@')
+    lua_dofile(L, p+1);
+  else
+    lua_dostring(L, p);
+  return lua_gettop(L);
+}
+
+
+
+/*
+** {======================================================
+** function to test the API with C. It interprets a kind of assembler
+** language with calls to the API, so the test can be driven by Lua code
+** =======================================================
+*/
+
+static const char *const delimits = " \t\n,;";
+
+static void skip (const char **pc) {
+  while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++;
+}
+
+static int getnum_aux (lua_State *L, const char **pc) {
+  int res = 0;
+  int sig = 1;
+  skip(pc);
+  if (**pc == '.') {
+    res = cast(int, lua_tonumber(L, -1));
+    lua_pop(L, 1);
+    (*pc)++;
+    return res;
+  }
+  else if (**pc == '-') {
+    sig = -1;
+    (*pc)++;
+  }
+  while (isdigit(cast(int, **pc))) res = res*10 + (*(*pc)++) - '0';
+  return sig*res;
+}
+  
+static const char *getname_aux (char *buff, const char **pc) {
+  int i = 0;
+  skip(pc);
+  while (**pc != '\0' && !strchr(delimits, **pc))
+    buff[i++] = *(*pc)++;
+  buff[i] = '\0';
+  return buff;
+}
+
+
+#define EQ(s1)	(strcmp(s1, inst) == 0)
+
+#define getnum	(getnum_aux(L, &pc))
+#define getname	(getname_aux(buff, &pc))
+
+
+static int testC (lua_State *L) {
+  char buff[30];
+  const char *pc = luaL_checkstring(L, 1);
+  for (;;) {
+    const char *inst = getname;
+    if EQ("") return 0;
+    else if EQ("isnumber") {
+      lua_pushintegral(L, lua_isnumber(L, getnum));
+    }
+    else if EQ("isstring") {
+      lua_pushintegral(L, lua_isstring(L, getnum));
+    }
+    else if EQ("istable") {
+      lua_pushintegral(L, lua_istable(L, getnum));
+    }
+    else if EQ("iscfunction") {
+      lua_pushintegral(L, lua_iscfunction(L, getnum));
+    }
+    else if EQ("isfunction") {
+      lua_pushintegral(L, lua_isfunction(L, getnum));
+    }
+    else if EQ("isuserdata") {
+      lua_pushintegral(L, lua_isuserdata(L, getnum));
+    }
+    else if EQ("isudataval") {
+      lua_pushintegral(L, lua_islightuserdata(L, getnum));
+    }
+    else if EQ("isnil") {
+      lua_pushintegral(L, lua_isnil(L, getnum));
+    }
+    else if EQ("isnull") {
+      lua_pushintegral(L, lua_isnone(L, getnum));
+    }
+    else if EQ("tonumber") {
+      lua_pushnumber(L, lua_tonumber(L, getnum));
+    }
+    else if EQ("tostring") {
+      const char *s = lua_tostring(L, getnum);
+      lua_pushstring(L, s);
+    }
+    else if EQ("strlen") {
+      lua_pushintegral(L, lua_strlen(L, getnum));
+    }
+    else if EQ("tocfunction") {
+      lua_pushcfunction(L, lua_tocfunction(L, getnum));
+    }
+    else if EQ("return") {
+      return getnum;
+    }
+    else if EQ("gettop") {
+      lua_pushintegral(L, lua_gettop(L));
+    }
+    else if EQ("settop") {
+      lua_settop(L, getnum);
+    }
+    else if EQ("pop") {
+      lua_pop(L, getnum);
+    }
+    else if EQ("pushnum") {
+      lua_pushintegral(L, getnum);
+    }
+    else if EQ("pushnil") {
+      lua_pushnil(L);
+    }
+    else if EQ("pushbool") {
+      lua_pushboolean(L, getnum);
+    }
+    else if EQ("tobool") {
+      lua_pushintegral(L, lua_toboolean(L, getnum));
+    }
+    else if EQ("pushvalue") {
+      lua_pushvalue(L, getnum);
+    }
+    else if EQ("pushcclosure") {
+      lua_pushcclosure(L, testC, getnum);
+    }
+    else if EQ("pushupvalues") {
+      lua_pushupvalues(L);
+    }
+    else if EQ("remove") {
+      lua_remove(L, getnum);
+    }
+    else if EQ("insert") {
+      lua_insert(L, getnum);
+    }
+    else if EQ("replace") {
+      lua_replace(L, getnum);
+    }
+    else if EQ("gettable") {
+      lua_gettable(L, getnum);
+    }
+    else if EQ("settable") {
+      lua_settable(L, getnum);
+    }
+    else if EQ("next") {
+      lua_next(L, -2);
+    }
+    else if EQ("concat") {
+      lua_concat(L, getnum);
+    }
+    else if EQ("lessthan") {
+      int a = getnum;
+      lua_pushboolean(L, lua_lessthan(L, a, getnum));
+    }
+    else if EQ("equal") {
+      int a = getnum;
+      lua_pushboolean(L, lua_equal(L, a, getnum));
+    }
+    else if EQ("rawcall") {
+      int narg = getnum;
+      int nres = getnum;
+      lua_call(L, narg, nres);
+    }
+    else if EQ("call") {
+      int narg = getnum;
+      int nres = getnum;
+      lua_pcall(L, narg, nres, 0);
+    }
+    else if EQ("loadstring") {
+      size_t sl;
+      const char *s = luaL_checklstring(L, getnum, &sl);
+      luaL_loadbuffer(L, s, sl, s);
+    }
+    else if EQ("loadfile") {
+      luaL_loadfile(L, luaL_checkstring(L, getnum));
+    }
+    else if EQ("setmetatable") {
+      lua_setmetatable(L, getnum);
+    }
+    else if EQ("getmetatable") {
+      if (lua_getmetatable(L, getnum) == 0)
+        lua_pushnil(L);
+    }
+    else if EQ("type") {
+      lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
+    }
+    else if EQ("getn") {
+      int i = getnum;
+      lua_pushintegral(L, luaL_getn(L, i));
+    }
+    else if EQ("setn") {
+      int i = getnum;
+      int n = cast(int, lua_tonumber(L, -1));
+      luaL_setn(L, i, n);
+      lua_pop(L, 1);
+    }
+    else luaL_error(L, "unknown instruction %s", buff);
+  }
+  return 0;
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** tests for yield inside hooks
+** =======================================================
+*/
+
+static void yieldf (lua_State *L, lua_Debug *ar) {
+  lua_yield(L, 0);
+}
+
+static int setyhook (lua_State *L) {
+  if (lua_isnoneornil(L, 1))
+    lua_sethook(L, NULL, 0, 0);  /* turn off hooks */
+  else {
+    const char *smask = luaL_checkstring(L, 1);
+    int count = luaL_optint(L, 2, 0);
+    int mask = 0;
+    if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+    if (count > 0) mask |= LUA_MASKCOUNT;
+    lua_sethook(L, yieldf, mask, count);
+  }
+  return 0;
+}
+
+
+static int coresume (lua_State *L) {
+  int status;
+  lua_State *co = lua_tothread(L, 1);
+  luaL_argcheck(L, co, 1, "coroutine expected");
+  status = lua_resume(co, 0);
+  if (status != 0) {
+    lua_pushboolean(L, 0);
+    lua_insert(L, -2);
+    return 2;  /* return false + error message */
+  }
+  else {
+    lua_pushboolean(L, 1);
+    return 1;
+  }
+}
+
+/* }====================================================== */
+
+
+
+static const struct luaL_reg tests_funcs[] = {
+  {"hash", hash_query},
+  {"limits", get_limits},
+  {"listcode", listcode},
+  {"listk", listk},
+  {"listlocals", listlocals},
+  {"loadlib", loadlib},
+  {"stacklevel", stacklevel},
+  {"querystr", string_query},
+  {"querytab", table_query},
+  {"doit", test_do},
+  {"testC", testC},
+  {"ref", tref},
+  {"getref", getref},
+  {"unref", unref},
+  {"d2s", d2s},
+  {"s2d", s2d},
+  {"metatable", metatable},
+  {"upvalue", upvalue},
+  {"newuserdata", newuserdata},
+  {"pushuserdata", pushuserdata},
+  {"udataval", udataval},
+  {"doonnewstack", doonnewstack},
+  {"newstate", newstate},
+  {"closestate", closestate},
+  {"doremote", doremote},
+  {"log2", log2_aux},
+  {"int2fb", int2fb_aux},
+  {"totalmem", mem_query},
+  {"resume", coresume},
+  {"setyhook", setyhook},
+  {NULL, NULL}
+};
+
+
+static void fim (void) {
+  if (!islocked)
+    lua_close(lua_state);
+  lua_assert(memdebug_numblocks == 0);
+  lua_assert(memdebug_total == 0);
+}
+
+
+static int l_panic (lua_State *L) {
+  UNUSED(L);
+  fprintf(stderr, "unable to recover; exiting\n");
+  return 0;
+}
+
+
+int luaB_opentests (lua_State *L) {
+  lua_atpanic(L, l_panic);
+  lua_userstateopen(L);  /* init lock */
+  lua_state = L;  /* keep first state to be opened */
+  luaL_openlib(L, "T", tests_funcs, 0);
+  atexit(fim);
+  return 0;
+}
+
+
+#undef main
+int main (int argc, char *argv[]) {
+  char *limit = getenv("MEMLIMIT");
+  if (limit)
+    memdebug_memlimit = strtoul(limit, NULL, 10);
+  l_main(argc, argv);
+  return 0;
+}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,69 @@
+/*
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define ltm_c
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+
+const char *const luaT_typenames[] = {
+  "nil", "boolean", "userdata", "number",
+  "string", "table", "function", "userdata", "thread"
+};
+
+
+void luaT_init (lua_State *L) {
+  static const char *const luaT_eventname[] = {  /* ORDER TM */
+    "__index", "__newindex",
+    "__gc", "__mode", "__eq",
+    "__add", "__sub", "__mul", "__div",
+    "__pow", "__unm", "__lt", "__le",
+    "__concat", "__call"
+  };
+  int i;
+  for (i=0; i<TM_N; i++) {
+    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
+    luaS_fix(G(L)->tmname[i]);  /* never collect these names */
+  }
+}
+
+
+/*
+** function to be used with macro "fasttm": optimized for absence of
+** tag methods
+*/
+const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
+  const TObject *tm = luaH_getstr(events, ename);
+  lua_assert(event <= TM_EQ);
+  if (ttisnil(tm)) {  /* no tag method? */
+    events->flags |= cast(lu_byte, 1u<<event);  /* cache this fact */
+    return NULL;
+  }
+  else return tm;
+}
+
+
+const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) {
+  TString *ename = G(L)->tmname[event];
+  switch (ttype(o)) {
+    case LUA_TTABLE:
+      return luaH_getstr(hvalue(o)->metatable, ename);
+    case LUA_TUSERDATA:
+      return luaH_getstr(uvalue(o)->uv.metatable, ename);
+    default:
+      return &luaO_nilobject;
+  }
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltm.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltm.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/ltm.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/ltm.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,50 @@
+/*
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltm_h
+#define ltm_h
+
+
+#include "lobject.h"
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER TM"
+*/
+typedef enum {
+  TM_INDEX,
+  TM_NEWINDEX,
+  TM_GC,
+  TM_MODE,
+  TM_EQ,  /* last tag method with `fast' access */
+  TM_ADD,
+  TM_SUB,
+  TM_MUL,
+  TM_DIV,
+  TM_POW,
+  TM_UNM,
+  TM_LT,
+  TM_LE,
+  TM_CONCAT,
+  TM_CALL,
+  TM_N		/* number of elements in the enum */
+} TMS;
+
+
+
+#define gfasttm(g,et,e) \
+  (((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+
+#define fasttm(l,et,e)	gfasttm(G(l), et, e)
+
+
+const TObject *luaT_gettm (Table *events, TMS event, TString *ename);
+const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event);
+void luaT_init (lua_State *L);
+
+extern const char *const luaT_typenames[];
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lua.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lua.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lua.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lua.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,390 @@
+/*
+** Lua - An Extensible Extension Language
+** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
+** http://www.lua.org	mailto:info@lua.org
+** See Copyright Notice at the end of this file
+*/
+
+
+#ifndef lua_h
+#define lua_h
+
+#include <stdarg.h>
+#include <stddef.h>
+
+
+#define LUA_VERSION	"Lua 5.0.2"
+#define LUA_COPYRIGHT	"Copyright (C) 1994-2004 Tecgraf, PUC-Rio"
+#define LUA_AUTHORS 	"R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+
+/* option for multiple returns in `lua_pcall' and `lua_call' */
+#define LUA_MULTRET	(-1)
+
+
+/*
+** pseudo-indices
+*/
+#define LUA_REGISTRYINDEX	(-10000)
+#define LUA_GLOBALSINDEX	(-10001)
+#define lua_upvalueindex(i)	(LUA_GLOBALSINDEX-(i))
+
+
+/* error codes for `lua_load' and `lua_pcall' */
+#define LUA_ERRRUN	1
+#define LUA_ERRFILE	2
+#define LUA_ERRSYNTAX	3
+#define LUA_ERRMEM	4
+#define LUA_ERRERR	5
+
+
+typedef struct lua_State lua_State;
+
+typedef int (*lua_CFunction) (lua_State *L);
+
+
+/*
+** functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Chunkwriter) (lua_State *L, const void* p,
+                                size_t sz, void* ud);
+
+
+/*
+** basic types
+*/
+#define LUA_TNONE	(-1)
+
+#define LUA_TNIL	0
+#define LUA_TBOOLEAN	1
+#define LUA_TLIGHTUSERDATA	2
+#define LUA_TNUMBER	3
+#define LUA_TSTRING	4
+#define LUA_TTABLE	5
+#define LUA_TFUNCTION	6
+#define LUA_TUSERDATA	7
+#define LUA_TTHREAD	8
+
+
+/* minimum Lua stack available to a C function */
+#define LUA_MINSTACK	20
+
+
+/*
+** generic extra include file
+*/
+#ifdef LUA_USER_H
+#include LUA_USER_H
+#endif
+
+
+/* type of numbers in Lua */
+#ifndef LUA_NUMBER
+typedef double lua_Number;
+#else
+typedef LUA_NUMBER lua_Number;
+#endif
+
+
+/* mark for all API functions */
+#ifndef LUA_API
+#define LUA_API		extern
+#endif
+
+
+/*
+** state manipulation
+*/
+LUA_API lua_State *lua_open (void);
+LUA_API void       lua_close (lua_State *L);
+LUA_API lua_State *lua_newthread (lua_State *L);
+
+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
+
+
+/*
+** basic stack manipulation
+*/
+LUA_API int   lua_gettop (lua_State *L);
+LUA_API void  lua_settop (lua_State *L, int idx);
+LUA_API void  lua_pushvalue (lua_State *L, int idx);
+LUA_API void  lua_remove (lua_State *L, int idx);
+LUA_API void  lua_insert (lua_State *L, int idx);
+LUA_API void  lua_replace (lua_State *L, int idx);
+LUA_API int   lua_checkstack (lua_State *L, int sz);
+
+LUA_API void  lua_xmove (lua_State *from, lua_State *to, int n);
+
+
+/*
+** access functions (stack -> C)
+*/
+
+LUA_API int             lua_isnumber (lua_State *L, int idx);
+LUA_API int             lua_isstring (lua_State *L, int idx);
+LUA_API int             lua_iscfunction (lua_State *L, int idx);
+LUA_API int             lua_isuserdata (lua_State *L, int idx);
+LUA_API int             lua_type (lua_State *L, int idx);
+LUA_API const char     *lua_typename (lua_State *L, int tp);
+
+LUA_API int            lua_equal (lua_State *L, int idx1, int idx2);
+LUA_API int            lua_rawequal (lua_State *L, int idx1, int idx2);
+LUA_API int            lua_lessthan (lua_State *L, int idx1, int idx2);
+
+LUA_API lua_Number      lua_tonumber (lua_State *L, int idx);
+LUA_API int             lua_toboolean (lua_State *L, int idx);
+LUA_API const char     *lua_tostring (lua_State *L, int idx);
+LUA_API size_t          lua_strlen (lua_State *L, int idx);
+LUA_API lua_CFunction   lua_tocfunction (lua_State *L, int idx);
+LUA_API void	       *lua_touserdata (lua_State *L, int idx);
+LUA_API lua_State      *lua_tothread (lua_State *L, int idx);
+LUA_API const void     *lua_topointer (lua_State *L, int idx);
+
+
+/*
+** push functions (C -> stack)
+*/
+LUA_API void  lua_pushnil (lua_State *L);
+LUA_API void  lua_pushnumber (lua_State *L, lua_Number n);
+LUA_API void  lua_pushlstring (lua_State *L, const char *s, size_t l);
+LUA_API void  lua_pushstring (lua_State *L, const char *s);
+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
+                                                    va_list argp);
+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
+LUA_API void  lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
+LUA_API void  lua_pushboolean (lua_State *L, int b);
+LUA_API void  lua_pushlightuserdata (lua_State *L, const void *p);
+
+
+/*
+** get functions (Lua -> stack)
+*/
+LUA_API void  lua_gettable (lua_State *L, int idx);
+LUA_API void  lua_rawget (lua_State *L, int idx);
+LUA_API void  lua_rawgeti (lua_State *L, int idx, int n);
+LUA_API void  lua_newtable (lua_State *L);
+LUA_API void *lua_newuserdata (lua_State *L, size_t sz);
+LUA_API int   lua_getmetatable (lua_State *L, int objindex);
+LUA_API void  lua_getfenv (lua_State *L, int idx);
+
+
+/*
+** set functions (stack -> Lua)
+*/
+LUA_API void  lua_settable (lua_State *L, int idx);
+LUA_API void  lua_rawset (lua_State *L, int idx);
+LUA_API void  lua_rawseti (lua_State *L, int idx, int n);
+LUA_API int   lua_setmetatable (lua_State *L, int objindex);
+LUA_API int   lua_setfenv (lua_State *L, int idx);
+
+
+/*
+** `load' and `call' functions (load and run Lua code)
+*/
+LUA_API void  lua_call (lua_State *L, int nargs, int nresults);
+LUA_API int   lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
+LUA_API int   lua_load (lua_State *L, lua_Chunkreader reader, void *dt,
+                        const char *chunkname);
+
+LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data);
+
+
+/*
+** coroutine functions
+*/
+LUA_API int  lua_yield (lua_State *L, int nresults);
+LUA_API int  lua_resume (lua_State *L, int narg);
+
+/*
+** garbage-collection functions
+*/
+LUA_API int   lua_getgcthreshold (lua_State *L);
+LUA_API int   lua_getgccount (lua_State *L);
+LUA_API void  lua_setgcthreshold (lua_State *L, int newthreshold);
+
+/*
+** miscellaneous functions
+*/
+
+LUA_API const char *lua_version (void);
+
+LUA_API int   lua_error (lua_State *L) __attribute__((noreturn));
+
+LUA_API int   lua_next (lua_State *L, int idx);
+
+LUA_API void  lua_concat (lua_State *L, int n);
+
+
+
+/* 
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define lua_boxpointer(L,u) \
+	(*(void **)(lua_newuserdata(L, sizeof(void *))) = (u))
+
+#define lua_unboxpointer(L,i)	(*(void **)(lua_touserdata(L, i)))
+
+#define lua_pop(L,n)		lua_settop(L, -(n)-1)
+
+#define lua_register(L,n,f) \
+	(lua_pushstring(L, n), \
+	 lua_pushcfunction(L, f), \
+	 lua_settable(L, LUA_GLOBALSINDEX))
+
+#define lua_pushcfunction(L,f)	lua_pushcclosure(L, f, 0)
+
+#define lua_isfunction(L,n)	(lua_type(L,n) == LUA_TFUNCTION)
+#define lua_istable(L,n)	(lua_type(L,n) == LUA_TTABLE)
+#define lua_islightuserdata(L,n)	(lua_type(L,n) == LUA_TLIGHTUSERDATA)
+#define lua_isnil(L,n)		(lua_type(L,n) == LUA_TNIL)
+#define lua_isboolean(L,n)	(lua_type(L,n) == LUA_TBOOLEAN)
+#define lua_isnone(L,n)		(lua_type(L,n) == LUA_TNONE)
+#define lua_isnoneornil(L, n)	(lua_type(L,n) <= 0)
+
+#define lua_pushliteral(L, s)	\
+	lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+
+
+
+/*
+** compatibility macros and functions
+*/
+
+
+LUA_API int lua_pushupvalues (lua_State *L);
+
+#define lua_getregistry(L)	lua_pushvalue(L, LUA_REGISTRYINDEX)
+#define lua_setglobal(L,s)	\
+   (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX))
+
+#define lua_getglobal(L,s)	\
+		(lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX))
+
+
+/* compatibility with ref system */
+
+/* pre-defined references */
+#define LUA_NOREF	(-2)
+#define LUA_REFNIL	(-1)
+
+#define lua_ref(L,lock)	((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
+      (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
+
+#define lua_unref(L,ref)	luaL_unref(L, LUA_REGISTRYINDEX, (ref))
+
+#define lua_getref(L,ref)	lua_rawgeti(L, LUA_REGISTRYINDEX, ref)
+
+
+
+/*
+** {======================================================================
+** useful definitions for Lua kernel and libraries
+** =======================================================================
+*/
+
+/* formats for Lua numbers */
+#ifndef LUA_NUMBER_SCAN
+#define LUA_NUMBER_SCAN		"%lf"
+#endif
+
+#ifndef LUA_NUMBER_FMT
+#define LUA_NUMBER_FMT		"%.14g"
+#endif
+
+/* }====================================================================== */
+
+
+/*
+** {======================================================================
+** Debug API
+** =======================================================================
+*/
+
+
+/*
+** Event codes
+*/
+#define LUA_HOOKCALL	0
+#define LUA_HOOKRET	1
+#define LUA_HOOKLINE	2
+#define LUA_HOOKCOUNT	3
+#define LUA_HOOKTAILRET 4
+
+
+/*
+** Event masks
+*/
+#define LUA_MASKCALL	(1 << LUA_HOOKCALL)
+#define LUA_MASKRET	(1 << LUA_HOOKRET)
+#define LUA_MASKLINE	(1 << LUA_HOOKLINE)
+#define LUA_MASKCOUNT	(1 << LUA_HOOKCOUNT)
+
+typedef struct lua_Debug lua_Debug;  /* activation record */
+
+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API lua_Hook lua_gethook (lua_State *L);
+LUA_API int lua_gethookmask (lua_State *L);
+LUA_API int lua_gethookcount (lua_State *L);
+
+
+#define LUA_IDSIZE	60
+
+struct lua_Debug {
+  int event;
+  const char *name;	/* (n) */
+  const char *namewhat;	/* (n) `global', `local', `field', `method' */
+  const char *what;	/* (S) `Lua', `C', `main', `tail' */
+  const char *source;	/* (S) */
+  int currentline;	/* (l) */
+  int nups;		/* (u) number of upvalues */
+  int linedefined;	/* (S) */
+  char short_src[LUA_IDSIZE]; /* (S) */
+  /* private part */
+  int i_ci;  /* active function */
+};
+
+/* }====================================================================== */
+
+
+/******************************************************************************
+* Copyright (C) 1994-2004 Tecgraf, PUC-Rio.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lualib.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lualib.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lualib.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lualib.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,55 @@
+/*
+** Lua standard libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lualib_h
+#define lualib_h
+
+#include "lua.h"
+
+
+#ifndef LUALIB_API
+#define LUALIB_API	LUA_API
+#endif
+
+
+#define LUA_COLIBNAME	"coroutine"
+LUALIB_API int luaopen_base (lua_State *L);
+
+#define LUA_TABLIBNAME	"table"
+LUALIB_API int luaopen_table (lua_State *L);
+
+#define LUA_IOLIBNAME	"io"
+#define LUA_OSLIBNAME	"os"
+LUALIB_API int luaopen_io (lua_State *L);
+
+#define LUA_STRLIBNAME	"string"
+LUALIB_API int luaopen_string (lua_State *L);
+
+#define LUA_MATHLIBNAME	"math"
+LUALIB_API int luaopen_math (lua_State *L);
+
+#define LUA_DBLIBNAME	"debug"
+LUALIB_API int luaopen_debug (lua_State *L);
+
+
+LUALIB_API int luaopen_loadlib (lua_State *L);
+
+
+/* to help testing the libraries */
+#ifndef lua_assert
+#define lua_assert(c)		/* empty */
+#endif
+
+
+/* compatibility code */
+#define lua_baselibopen	luaopen_base
+#define lua_tablibopen	luaopen_table
+#define lua_iolibopen	luaopen_io
+#define lua_strlibopen	luaopen_string
+#define lua_mathlibopen	luaopen_math
+#define lua_dblibopen	luaopen_debug
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lundump.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lundump.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lundump.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lundump.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,287 @@
+/*
+** load pre-compiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#define lundump_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lopcodes.h"
+#include "lstring.h"
+#include "lundump.h"
+#include "lzio.h"
+
+#define	LoadByte	(lu_byte) ezgetc
+
+typedef struct {
+ lua_State* L;
+ ZIO* Z;
+ Mbuffer* b;
+ int swap;
+ const char* name;
+} LoadState;
+
+static void unexpectedEOZ (LoadState* S) __attribute__((noreturn));
+
+static void unexpectedEOZ (LoadState* S)
+{
+ luaG_runerror(S->L,"unexpected end of file in %s",S->name);
+}
+
+static int ezgetc (LoadState* S)
+{
+ int c=zgetc(S->Z);
+ if (c==EOZ) unexpectedEOZ(S);
+ return c;
+}
+
+static void ezread (LoadState* S, void* b, int n)
+{
+ int r=luaZ_read(S->Z,b,n);
+ if (r!=0) unexpectedEOZ(S);
+}
+
+static void LoadBlock (LoadState* S, void* b, size_t size)
+{
+ if (S->swap)
+ {
+  char* p=(char*) b+size-1;
+  int n=size;
+  while (n--) *p--=(char)ezgetc(S);
+ }
+ else
+  ezread(S,b,size);
+}
+
+static void LoadVector (LoadState* S, void* b, int m, size_t size)
+{
+ if (S->swap)
+ {
+  char* q=(char*) b;
+  while (m--)
+  {
+   char* p=q+size-1;
+   int n=size;
+   while (n--) *p--=(char)ezgetc(S);
+   q+=size;
+  }
+ }
+ else
+  ezread(S,b,m*size);
+}
+
+static int LoadInt (LoadState* S)
+{
+ int x;
+ LoadBlock(S,&x,sizeof(x));
+ if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name);
+ return x;
+}
+
+static size_t LoadSize (LoadState* S)
+{
+ size_t x;
+ LoadBlock(S,&x,sizeof(x));
+ return x;
+}
+
+static lua_Number LoadNumber (LoadState* S)
+{
+ lua_Number x;
+ LoadBlock(S,&x,sizeof(x));
+ return x;
+}
+
+static TString* LoadString (LoadState* S)
+{
+ size_t size=LoadSize(S);
+ if (size==0)
+  return NULL;
+ else
+ {
+  char* s=luaZ_openspace(S->L,S->b,size);
+  ezread(S,s,size);
+  return luaS_newlstr(S->L,s,size-1);		/* remove trailing '\0' */
+ }
+}
+
+static void LoadCode (LoadState* S, Proto* f)
+{
+ int size=LoadInt(S);
+ f->code=luaM_newvector(S->L,size,Instruction);
+ f->sizecode=size;
+ LoadVector(S,f->code,size,sizeof(*f->code));
+}
+
+static void LoadLocals (LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->locvars=luaM_newvector(S->L,n,LocVar);
+ f->sizelocvars=n;
+ for (i=0; i<n; i++)
+ {
+  f->locvars[i].varname=LoadString(S);
+  f->locvars[i].startpc=LoadInt(S);
+  f->locvars[i].endpc=LoadInt(S);
+ }
+}
+
+static void LoadLines (LoadState* S, Proto* f)
+{
+ int size=LoadInt(S);
+ f->lineinfo=luaM_newvector(S->L,size,int);
+ f->sizelineinfo=size;
+ LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
+}
+
+static void LoadUpvalues (LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ if (n!=0 && n!=f->nups) 
+  luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d",
+		S->name,n,f->nups);
+ f->upvalues=luaM_newvector(S->L,n,TString*);
+ f->sizeupvalues=n;
+ for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
+}
+
+static Proto* LoadFunction (LoadState* S, TString* p);
+
+static void LoadConstants (LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->k=luaM_newvector(S->L,n,TObject);
+ f->sizek=n;
+ for (i=0; i<n; i++)
+ {
+  TObject* o=&f->k[i];
+  int t=LoadByte(S);
+  switch (t)
+  {
+   case LUA_TNUMBER:
+	setnvalue(o,LoadNumber(S));
+	break;
+   case LUA_TSTRING:
+	setsvalue2n(o,LoadString(S));
+	break;
+   case LUA_TNIL:
+   	setnilvalue(o);
+	break;
+   default:
+	luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name);
+	break;
+  }
+ }
+ n=LoadInt(S);
+ f->p=luaM_newvector(S->L,n,Proto*);
+ f->sizep=n;
+ for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
+}
+
+static Proto* LoadFunction (LoadState* S, TString* p)
+{
+ Proto* f=luaF_newproto(S->L);
+ f->source=LoadString(S); if (f->source==NULL) f->source=p;
+ f->lineDefined=LoadInt(S);
+ f->nups=LoadByte(S);
+ f->numparams=LoadByte(S);
+ f->is_vararg=LoadByte(S);
+ f->maxstacksize=LoadByte(S);
+ LoadLines(S,f);
+ LoadLocals(S,f);
+ LoadUpvalues(S,f);
+ LoadConstants(S,f);
+ LoadCode(S,f);
+#ifndef TRUST_BINARIES
+ if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name);
+#endif
+ return f;
+}
+
+static void LoadSignature (LoadState* S)
+{
+ const char* s=LUA_SIGNATURE;
+ while (*s!=0 && ezgetc(S)==*s)
+  ++s;
+ if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name);
+}
+
+static void TestSize (LoadState* S, int s, const char* what)
+{
+ int r=LoadByte(S);
+ if (r!=s)
+  luaG_runerror(S->L,"virtual machine mismatch in %s: "
+	"size of %s is %d but read %d",S->name,what,s,r);
+}
+
+#define TESTSIZE(s,w)	TestSize(S,s,w)
+#define V(v)		v/16,v%16
+
+static void LoadHeader (LoadState* S)
+{
+ int version;
+ lua_Number x,tx=TEST_NUMBER;
+ LoadSignature(S);
+ version=LoadByte(S);
+ if (version>VERSION)
+  luaG_runerror(S->L,"%s too new: "
+	"read version %d.%d; expected at most %d.%d",
+	S->name,V(version),V(VERSION));
+ if (version<VERSION0)				/* check last major change */
+  luaG_runerror(S->L,"%s too old: "
+	"read version %d.%d; expected at least %d.%d",
+	S->name,V(version),V(VERSION0));
+ S->swap=(luaU_endianness()!=LoadByte(S));	/* need to swap bytes? */
+ TESTSIZE(sizeof(int),"int");
+ TESTSIZE(sizeof(size_t), "size_t");
+ TESTSIZE(sizeof(Instruction), "Instruction");
+ TESTSIZE(SIZE_OP, "OP");
+ TESTSIZE(SIZE_A, "A");
+ TESTSIZE(SIZE_B, "B");
+ TESTSIZE(SIZE_C, "C");
+ TESTSIZE(sizeof(lua_Number), "number");
+ x=LoadNumber(S);
+ if ((long)x!=(long)tx)		/* disregard errors in last bits of fraction */
+  luaG_runerror(S->L,"unknown number format in %s",S->name);
+}
+
+static Proto* LoadChunk (LoadState* S)
+{
+ LoadHeader(S);
+ return LoadFunction(S,NULL);
+}
+
+/*
+** load precompiled chunk
+*/
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
+{
+ LoadState S;
+ const char* s=zname(Z);
+ if (*s=='@' || *s=='=')
+  S.name=s+1;
+ else if (*s==LUA_SIGNATURE[0])
+  S.name="binary string";
+ else
+  S.name=s;
+ S.L=L;
+ S.Z=Z;
+ S.b=buff;
+ return LoadChunk(&S);
+}
+
+/*
+** find byte order
+*/
+int luaU_endianness (void)
+{
+ int x=1;
+ return *(char*)&x;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lundump.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lundump.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lundump.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lundump.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,33 @@
+/*
+** load pre-compiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lundump_h
+#define lundump_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+/* load one chunk; from lundump.c */
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff);
+
+/* find byte order; from lundump.c */
+int luaU_endianness (void);
+
+/* dump one chunk; from ldump.c */
+void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data);
+
+/* print one chunk; from print.c */
+void luaU_print (const Proto* Main);
+
+/* definitions for headers of binary files */
+#define	LUA_SIGNATURE	"\033Lua"	/* binary files start with "<esc>Lua" */
+#define	VERSION		0x50		/* last format change was in 5.0 */
+#define	VERSION0	0x50		/* last major  change was in 5.0 */
+
+/* a multiple of PI for testing native format */
+/* multiplying by 1E7 gives non-trivial integer values */
+#define	TEST_NUMBER	((lua_Number)3.14159265358979323846E7)
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lvm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lvm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lvm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lvm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,780 @@
+/*
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* needed only when `lua_number2str' uses `sprintf' */
+#include <stdio.h>
+
+#define lvm_c
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+/* function to convert a lua_Number to a string */
+#ifndef lua_number2str
+#define lua_number2str(s,n)     sprintf((s), LUA_NUMBER_FMT, (n))
+#endif
+
+
+/* limit for table tag-method chains (to avoid loops) */
+#define MAXTAGLOOP	100
+
+
+const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
+  lua_Number num;
+  if (ttisnumber(obj)) return obj;
+  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+    setnvalue(n, num);
+    return n;
+  }
+  else
+    return NULL;
+}
+
+
+int luaV_tostring (lua_State *L, StkId obj) {
+  if (!ttisnumber(obj))
+    return 0;
+  else {
+    char s[32];  /* 16 digits, sign, point and \0  (+ some extra...) */
+    lua_number2str(s, nvalue(obj));
+    setsvalue2s(obj, luaS_new(L, s));
+    return 1;
+  }
+}
+
+
+static void traceexec (lua_State *L) {
+  lu_byte mask = L->hookmask;
+  if (mask & LUA_MASKCOUNT) {  /* instruction-hook set? */
+    if (L->hookcount == 0) {
+      resethookcount(L);
+      luaD_callhook(L, LUA_HOOKCOUNT, -1);
+      return;
+    }
+  }
+  if (mask & LUA_MASKLINE) {
+    CallInfo *ci = L->ci;
+    Proto *p = ci_func(ci)->l.p;
+    int newline = getline(p, pcRel(*ci->u.l.pc, p));
+    if (!L->hookinit) {
+      luaG_inithooks(L);
+      return;
+    }
+    lua_assert(ci->state & CI_HASFRAME);
+    if (pcRel(*ci->u.l.pc, p) == 0)  /* tracing may be starting now? */
+      ci->u.l.savedpc = *ci->u.l.pc;  /* initialize `savedpc' */
+    /* calls linehook when enters a new line or jumps back (loop) */
+    if (*ci->u.l.pc <= ci->u.l.savedpc ||
+        newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
+      luaD_callhook(L, LUA_HOOKLINE, newline);
+      ci = L->ci;  /* previous call may reallocate `ci' */
+    }
+    ci->u.l.savedpc = *ci->u.l.pc;
+  }
+}
+
+
+static void callTMres (lua_State *L, const TObject *f,
+                       const TObject *p1, const TObject *p2) {
+  setobj2s(L->top, f);  /* push function */
+  setobj2s(L->top+1, p1);  /* 1st argument */
+  setobj2s(L->top+2, p2);  /* 2nd argument */
+  luaD_checkstack(L, 3);  /* cannot check before (could invalidate p1, p2) */
+  L->top += 3;
+  luaD_call(L, L->top - 3, 1);
+  L->top--;  /* result will be in L->top */
+}
+
+
+
+static void callTM (lua_State *L, const TObject *f,
+                    const TObject *p1, const TObject *p2, const TObject *p3) {
+  setobj2s(L->top, f);  /* push function */
+  setobj2s(L->top+1, p1);  /* 1st argument */
+  setobj2s(L->top+2, p2);  /* 2nd argument */
+  setobj2s(L->top+3, p3);  /* 3th argument */
+  luaD_checkstack(L, 4);  /* cannot check before (could invalidate p1...p3) */
+  L->top += 4;
+  luaD_call(L, L->top - 4, 0);
+}
+
+
+static const TObject *luaV_index (lua_State *L, const TObject *t,
+                                  TObject *key, int loop) {
+  const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
+  if (tm == NULL) return &luaO_nilobject;  /* no TM */
+  if (ttisfunction(tm)) {
+    callTMres(L, tm, t, key);
+    return L->top;
+  }
+  else return luaV_gettable(L, tm, key, loop);
+}
+
+static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
+                                       TObject *key, int loop) {
+  const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
+  if (ttisnil(tm))
+    luaG_typeerror(L, t, "index");
+  if (ttisfunction(tm)) {
+    callTMres(L, tm, t, key);
+    return L->top;
+  }
+  else return luaV_gettable(L, tm, key, loop);
+}
+
+
+/*
+** Function to index a table.
+** Receives the table at `t' and the key at `key'.
+** leaves the result at `res'.
+*/
+const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
+                              int loop) {
+  if (loop > MAXTAGLOOP)
+    luaG_runerror(L, "loop in gettable");
+  if (ttistable(t)) {  /* `t' is a table? */
+    Table *h = hvalue(t);
+    const TObject *v = luaH_get(h, key);  /* do a primitive get */
+    if (!ttisnil(v)) return v;
+    else return luaV_index(L, t, key, loop+1);
+  }
+  else return luaV_getnotable(L, t, key, loop+1);
+}
+
+
+/*
+** Receives table at `t', key at `key' and value at `val'.
+*/
+void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
+  const TObject *tm;
+  int loop = 0;
+  do {
+    if (ttistable(t)) {  /* `t' is a table? */
+      Table *h = hvalue(t);
+      TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
+      if (!ttisnil(oldval) ||  /* result is no nil? */
+          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
+        setobj2t(oldval, val);  /* write barrier */
+        return;
+      }
+      /* else will try the tag method */
+    }
+    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+      luaG_typeerror(L, t, "index");
+    if (ttisfunction(tm)) {
+      callTM(L, tm, t, key, val);
+      return;
+    }
+    t = tm;  /* else repeat with `tm' */ 
+  } while (++loop <= MAXTAGLOOP);
+  luaG_runerror(L, "loop in settable");
+}
+
+
+static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
+                       StkId res, TMS event) {
+  ptrdiff_t result = savestack(L, res);
+  const TObject *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
+  if (ttisnil(tm))
+    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
+  if (!ttisfunction(tm)) return 0;
+  callTMres(L, tm, p1, p2);
+  res = restorestack(L, result);  /* previous call may change stack */
+  setobjs2s(res, L->top);
+  return 1;
+}
+
+
+static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+                                  TMS event) {
+  const TObject *tm1 = fasttm(L, mt1, event);
+  const TObject *tm2;
+  if (tm1 == NULL) return NULL;  /* no metamethod */
+  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
+  tm2 = fasttm(L, mt2, event);
+  if (tm2 == NULL) return NULL;  /* no metamethod */
+  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */
+    return tm1;
+  return NULL;
+}
+
+
+static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,
+                         TMS event) {
+  const TObject *tm1 = luaT_gettmbyobj(L, p1, event);
+  const TObject *tm2;
+  if (ttisnil(tm1)) return -1;  /* no metamethod? */
+  tm2 = luaT_gettmbyobj(L, p2, event);
+  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */
+    return -1;
+  callTMres(L, tm1, p1, p2);
+  return !l_isfalse(L->top);
+}
+
+
+static int luaV_strcmp (const TString *ls, const TString *rs) {
+  const char *l = getstr(ls);
+  size_t ll = ls->tsv.len;
+  const char *r = getstr(rs);
+  size_t lr = rs->tsv.len;
+  for (;;) {
+    int temp = strcoll(l, r);
+    if (temp != 0) return temp;
+    else {  /* strings are equal up to a `\0' */
+      size_t len = strlen(l);  /* index of first `\0' in both strings */
+      if (len == lr)  /* r is finished? */
+        return (len == ll) ? 0 : 1;
+      else if (len == ll)  /* l is finished? */
+        return -1;  /* l is smaller than r (because r is not finished) */
+      /* both strings longer than `len'; go on comparing (after the `\0') */
+      len++;
+      l += len; ll -= len; r += len; lr -= len;
+    }
+  }
+}
+
+
+int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
+  int res;
+  if (ttype(l) != ttype(r))
+    return luaG_ordererror(L, l, r);
+  else if (ttisnumber(l))
+    return nvalue(l) < nvalue(r);
+  else if (ttisstring(l))
+    return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
+  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+    return res;
+  return luaG_ordererror(L, l, r);
+}
+
+
+static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
+  int res;
+  if (ttype(l) != ttype(r))
+    return luaG_ordererror(L, l, r);
+  else if (ttisnumber(l))
+    return nvalue(l) <= nvalue(r);
+  else if (ttisstring(l))
+    return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
+  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */
+    return res;
+  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */
+    return !res;
+  return luaG_ordererror(L, l, r);
+}
+
+
+int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
+  const TObject *tm;
+  lua_assert(ttype(t1) == ttype(t2));
+  switch (ttype(t1)) {
+    case LUA_TNIL: return 1;
+    case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
+    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
+    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
+    case LUA_TUSERDATA: {
+      if (uvalue(t1) == uvalue(t2)) return 1;
+      tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,
+                         TM_EQ);
+      break;  /* will try TM */
+    }
+    case LUA_TTABLE: {
+      if (hvalue(t1) == hvalue(t2)) return 1;
+      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+      break;  /* will try TM */
+    }
+    default: return gcvalue(t1) == gcvalue(t2);
+  }
+  if (tm == NULL) return 0;  /* no TM? */
+  callTMres(L, tm, t1, t2);  /* call TM */
+  return !l_isfalse(L->top);
+}
+
+
+void luaV_concat (lua_State *L, int total, int last) {
+  do {
+    StkId top = L->base + last + 1;
+    int n = 2;  /* number of elements handled in this pass (at least 2) */
+    if (!tostring(L, top-2) || !tostring(L, top-1)) {
+      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
+        luaG_concaterror(L, top-2, top-1);
+    } else if (tsvalue(top-1)->tsv.len > 0) {  /* if len=0, do nothing */
+      /* at least two string values; get as many as possible */
+      lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) +
+                  cast(lu_mem, tsvalue(top-2)->tsv.len);
+      char *buffer;
+      int i;
+      while (n < total && tostring(L, top-n-1)) {  /* collect total length */
+        tl += tsvalue(top-n-1)->tsv.len;
+        n++;
+      }
+      if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
+      buffer = luaZ_openspace(L, &G(L)->buff, tl);
+      tl = 0;
+      for (i=n; i>0; i--) {  /* concat all strings */
+        size_t l = tsvalue(top-i)->tsv.len;
+        memcpy(buffer+tl, svalue(top-i), l);
+        tl += l;
+      }
+      setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
+    }
+    total -= n-1;  /* got `n' strings to create 1 new */
+    last -= n-1;
+  } while (total > 1);  /* repeat until only 1 result left */
+}
+
+
+static void Arith (lua_State *L, StkId ra,
+                   const TObject *rb, const TObject *rc, TMS op) {
+  TObject tempb, tempc;
+  const TObject *b, *c;
+  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+      (c = luaV_tonumber(rc, &tempc)) != NULL) {
+    switch (op) {
+      case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break;
+      case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break;
+      case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
+      case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
+      case TM_POW: {
+        const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
+        ptrdiff_t res = savestack(L, ra);
+        if (!ttisfunction(f))
+          luaG_runerror(L, "`__pow' (`^' operator) is not a function");
+        callTMres(L, f, b, c);
+        ra = restorestack(L, res);  /* previous call may change stack */
+        setobjs2s(ra, L->top);
+        break;
+      }
+      default: lua_assert(0); break;
+    }
+  }
+  else if (!call_binTM(L, rb, rc, ra, op))
+    luaG_aritherror(L, rb, rc);
+}
+
+
+
+/*
+** some macros for common tasks in `luaV_execute'
+*/
+
+#define runtime_check(L, c)	{ if (!(c)) return 0; }
+
+#define RA(i)	(base+GETARG_A(i))
+/* to be used after possible stack reallocation */
+#define XRA(i)	(L->base+GETARG_A(i))
+#define RB(i)	(base+GETARG_B(i))
+#define RKB(i)	((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
+#define RC(i)	(base+GETARG_C(i))
+#define RKC(i)	((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
+#define KBx(i)	(k+GETARG_Bx(i))
+
+
+#define dojump(pc, i)	((pc) += (i))
+
+
+StkId luaV_execute (lua_State *L) {
+  LClosure *cl;
+  TObject *k;
+  const Instruction *pc;
+ callentry:  /* entry point when calling new functions */
+  if (L->hookmask & LUA_MASKCALL) {
+    L->ci->u.l.pc = &pc;
+    luaD_callhook(L, LUA_HOOKCALL, -1);
+  }
+ retentry:  /* entry point when returning to old functions */
+  L->ci->u.l.pc = &pc;
+  lua_assert(L->ci->state == CI_SAVEDPC ||
+             L->ci->state == (CI_SAVEDPC | CI_CALLING));
+  L->ci->state = CI_HASFRAME;  /* activate frame */
+  pc = L->ci->u.l.savedpc;
+  cl = &clvalue(L->base - 1)->l;
+  k = cl->p->k;
+  /* main loop of interpreter */
+  for (;;) {
+    const Instruction i = *pc++;
+    StkId base, ra;
+    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
+        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
+      traceexec(L);
+      if (L->ci->state & CI_YIELD) {  /* did hook yield? */
+        L->ci->u.l.savedpc = pc - 1;
+        L->ci->state = CI_YIELD | CI_SAVEDPC;
+        return NULL;
+      }
+    }
+    /* warning!! several calls may realloc the stack and invalidate `ra' */
+    base = L->base;
+    ra = RA(i);
+    lua_assert(L->ci->state & CI_HASFRAME);
+    lua_assert(base == L->ci->base);
+    lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
+    lua_assert(L->top == L->ci->top ||
+         GET_OPCODE(i) == OP_CALL ||   GET_OPCODE(i) == OP_TAILCALL ||
+         GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
+    switch (GET_OPCODE(i)) {
+      case OP_MOVE: {
+        setobjs2s(ra, RB(i));
+        break;
+      }
+      case OP_LOADK: {
+        setobj2s(ra, KBx(i));
+        break;
+      }
+      case OP_LOADBOOL: {
+        setbvalue(ra, GETARG_B(i));
+        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
+        break;
+      }
+      case OP_LOADNIL: {
+        TObject *rb = RB(i);
+        do {
+          setnilvalue(rb--);
+        } while (rb >= ra);
+        break;
+      }
+      case OP_GETUPVAL: {
+        int b = GETARG_B(i);
+        setobj2s(ra, cl->upvals[b]->v);
+        break;
+      }
+      case OP_GETGLOBAL: {
+        TObject *rb = KBx(i);
+        const TObject *v;
+        lua_assert(ttisstring(rb) && ttistable(&cl->g));
+        v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
+        if (!ttisnil(v)) { setobj2s(ra, v); }
+        else
+          setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
+        break;
+      }
+      case OP_GETTABLE: {
+        StkId rb = RB(i);
+        TObject *rc = RKC(i);
+        if (ttistable(rb)) {
+          const TObject *v = luaH_get(hvalue(rb), rc);
+          if (!ttisnil(v)) { setobj2s(ra, v); }
+          else
+            setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
+        }
+        else
+          setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
+        break;
+      }
+      case OP_SETGLOBAL: {
+        lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
+        luaV_settable(L, &cl->g, KBx(i), ra);
+        break;
+      }
+      case OP_SETUPVAL: {
+        int b = GETARG_B(i);
+        setobj(cl->upvals[b]->v, ra);  /* write barrier */
+        break;
+      }
+      case OP_SETTABLE: {
+        luaV_settable(L, ra, RKB(i), RKC(i));
+        break;
+      }
+      case OP_NEWTABLE: {
+        int b = GETARG_B(i);
+        b = fb2int(b);
+        sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
+        luaC_checkGC(L);
+        break;
+      }
+      case OP_SELF: {
+        StkId rb = RB(i);
+        TObject *rc = RKC(i);
+        runtime_check(L, ttisstring(rc));
+        setobjs2s(ra+1, rb);
+        if (ttistable(rb)) {
+          const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
+          if (!ttisnil(v)) { setobj2s(ra, v); }
+          else
+            setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
+        }
+        else
+          setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
+        break;
+      }
+      case OP_ADD: {
+        TObject *rb = RKB(i);
+        TObject *rc = RKC(i);
+        if (ttisnumber(rb) && ttisnumber(rc)) {
+          setnvalue(ra, nvalue(rb) + nvalue(rc));
+        }
+        else
+          Arith(L, ra, rb, rc, TM_ADD);
+        break;
+      }
+      case OP_SUB: {
+        TObject *rb = RKB(i);
+        TObject *rc = RKC(i);
+        if (ttisnumber(rb) && ttisnumber(rc)) {
+          setnvalue(ra, nvalue(rb) - nvalue(rc));
+        }
+        else
+          Arith(L, ra, rb, rc, TM_SUB);
+        break;
+      }
+      case OP_MUL: {
+        TObject *rb = RKB(i);
+        TObject *rc = RKC(i);
+        if (ttisnumber(rb) && ttisnumber(rc)) {
+          setnvalue(ra, nvalue(rb) * nvalue(rc));
+        }
+        else
+          Arith(L, ra, rb, rc, TM_MUL);
+        break;
+      }
+      case OP_DIV: {
+        TObject *rb = RKB(i);
+        TObject *rc = RKC(i);
+        if (ttisnumber(rb) && ttisnumber(rc)) {
+          setnvalue(ra, nvalue(rb) / nvalue(rc));
+        }
+        else
+          Arith(L, ra, rb, rc, TM_DIV);
+        break;
+      }
+      case OP_POW: {
+        Arith(L, ra, RKB(i), RKC(i), TM_POW);
+        break;
+      }
+      case OP_UNM: {
+        const TObject *rb = RB(i);
+        TObject temp;
+        if (tonumber(rb, &temp)) {
+          setnvalue(ra, -nvalue(rb));
+        }
+        else {
+          setnilvalue(&temp);
+          if (!call_binTM(L, RB(i), &temp, ra, TM_UNM))
+            luaG_aritherror(L, RB(i), &temp);
+        }
+        break;
+      }
+      case OP_NOT: {
+        int res = l_isfalse(RB(i));  /* next assignment may change this value */
+        setbvalue(ra, res);
+        break;
+      }
+      case OP_CONCAT: {
+        int b = GETARG_B(i);
+        int c = GETARG_C(i);
+        luaV_concat(L, c-b+1, c);  /* may change `base' (and `ra') */
+        base = L->base;
+        setobjs2s(RA(i), base+b);
+        luaC_checkGC(L);
+        break;
+      }
+      case OP_JMP: {
+        dojump(pc, GETARG_sBx(i));
+        break;
+      }
+      case OP_EQ: {
+        if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
+        else dojump(pc, GETARG_sBx(*pc) + 1);
+        break;
+      }
+      case OP_LT: {
+        if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
+        else dojump(pc, GETARG_sBx(*pc) + 1);
+        break;
+      }
+      case OP_LE: {
+        if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
+        else dojump(pc, GETARG_sBx(*pc) + 1);
+        break;
+      }
+      case OP_TEST: {
+        TObject *rb = RB(i);
+        if (l_isfalse(rb) == GETARG_C(i)) pc++;
+        else {
+          setobjs2s(ra, rb);
+          dojump(pc, GETARG_sBx(*pc) + 1);
+        }
+        break;
+      }
+      case OP_CALL:
+      case OP_TAILCALL: {
+        StkId firstResult;
+        int b = GETARG_B(i);
+        int nresults;
+        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
+        nresults = GETARG_C(i) - 1;
+        firstResult = luaD_precall(L, ra);
+        if (firstResult) {
+          if (firstResult > L->top) {  /* yield? */
+            lua_assert(L->ci->state == (CI_C | CI_YIELD));
+            (L->ci - 1)->u.l.savedpc = pc;
+            (L->ci - 1)->state = CI_SAVEDPC;
+            return NULL;
+          }
+          /* it was a C function (`precall' called it); adjust results */
+          luaD_poscall(L, nresults, firstResult);
+          if (nresults >= 0) L->top = L->ci->top;
+        }
+        else {  /* it is a Lua function */
+          if (GET_OPCODE(i) == OP_CALL) {  /* regular call? */
+            (L->ci-1)->u.l.savedpc = pc;  /* save `pc' to return later */
+            (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING);
+          }
+          else {  /* tail call: put new frame in place of previous one */
+            int aux;
+            base = (L->ci - 1)->base;  /* `luaD_precall' may change the stack */
+            ra = RA(i);
+            if (L->openupval) luaF_close(L, base);
+            for (aux = 0; ra+aux < L->top; aux++)  /* move frame down */
+              setobjs2s(base+aux-1, ra+aux);
+            (L->ci - 1)->top = L->top = base+aux;  /* correct top */
+            lua_assert(L->ci->state & CI_SAVEDPC);
+            (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
+            (L->ci - 1)->u.l.tailcalls++;  /* one more call lost */
+            (L->ci - 1)->state = CI_SAVEDPC;
+            L->ci--;  /* remove new frame */
+            L->base = L->ci->base;
+          }
+          goto callentry;
+        }
+        break;
+      }
+      case OP_RETURN: {
+        CallInfo *ci = L->ci - 1;  /* previous function frame */
+        int b = GETARG_B(i);
+        if (b != 0) L->top = ra+b-1;
+        lua_assert(L->ci->state & CI_HASFRAME);
+        if (L->openupval) luaF_close(L, base);
+        L->ci->state = CI_SAVEDPC;  /* deactivate current function */
+        L->ci->u.l.savedpc = pc;
+        /* previous function was running `here'? */
+        if (!(ci->state & CI_CALLING)) {
+          lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
+          return ra;  /* no: return */
+        }
+        else {  /* yes: continue its execution */
+          int nresults;
+          lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
+          lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
+          nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
+          luaD_poscall(L, nresults, ra);
+          if (nresults >= 0) L->top = L->ci->top;
+          goto retentry;
+        }
+      }
+      case OP_FORLOOP: {
+        lua_Number step, idx, limit;
+        const TObject *plimit = ra+1;
+        const TObject *pstep = ra+2;
+        if (!ttisnumber(ra))
+          luaG_runerror(L, "`for' initial value must be a number");
+        if (!tonumber(plimit, ra+1))
+          luaG_runerror(L, "`for' limit must be a number");
+        if (!tonumber(pstep, ra+2))
+          luaG_runerror(L, "`for' step must be a number");
+        step = nvalue(pstep);
+        idx = nvalue(ra) + step;  /* increment index */
+        limit = nvalue(plimit);
+        if (step > 0 ? idx <= limit : idx >= limit) {
+          dojump(pc, GETARG_sBx(i));  /* jump back */
+          chgnvalue(ra, idx);  /* update index */
+        }
+        break;
+      }
+      case OP_TFORLOOP: {
+        int nvar = GETARG_C(i) + 1;
+        StkId cb = ra + nvar + 2;  /* call base */
+        setobjs2s(cb, ra);
+        setobjs2s(cb+1, ra+1);
+        setobjs2s(cb+2, ra+2);
+        L->top = cb+3;  /* func. + 2 args (state and index) */
+        luaD_call(L, cb, nvar);
+        L->top = L->ci->top;
+        ra = XRA(i) + 2;  /* final position of first result */
+        cb = ra + nvar;
+        do {  /* move results to proper positions */
+          nvar--;
+          setobjs2s(ra+nvar, cb+nvar);
+        } while (nvar > 0);
+        if (ttisnil(ra))  /* break loop? */
+          pc++;  /* skip jump (break loop) */
+        else
+          dojump(pc, GETARG_sBx(*pc) + 1);  /* jump back */
+        break;
+      }
+      case OP_TFORPREP: {  /* for compatibility only */
+        if (ttistable(ra)) {
+          setobjs2s(ra+1, ra);
+          setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
+        }
+        dojump(pc, GETARG_sBx(i));
+        break;
+      }
+      case OP_SETLIST:
+      case OP_SETLISTO: {
+        int bc;
+        int n;
+        Table *h;
+        runtime_check(L, ttistable(ra));
+        h = hvalue(ra);
+        bc = GETARG_Bx(i);
+        if (GET_OPCODE(i) == OP_SETLIST)
+          n = (bc&(LFIELDS_PER_FLUSH-1)) + 1;
+        else {
+          n = L->top - ra - 1;
+          L->top = L->ci->top;
+        }
+        bc &= ~(LFIELDS_PER_FLUSH-1);  /* bc = bc - bc%FPF */
+        for (; n > 0; n--)
+          setobj2t(luaH_setnum(L, h, bc+n), ra+n);  /* write barrier */
+        break;
+      }
+      case OP_CLOSE: {
+        luaF_close(L, ra);
+        break;
+      }
+      case OP_CLOSURE: {
+        Proto *p;
+        Closure *ncl;
+        int nup, j;
+        p = cl->p->p[GETARG_Bx(i)];
+        nup = p->nups;
+        ncl = luaF_newLclosure(L, nup, &cl->g);
+        ncl->l.p = p;
+        for (j=0; j<nup; j++, pc++) {
+          if (GET_OPCODE(*pc) == OP_GETUPVAL)
+            ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
+          else {
+            lua_assert(GET_OPCODE(*pc) == OP_MOVE);
+            ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
+          }
+        }
+        setclvalue(ra, ncl);
+        luaC_checkGC(L);
+        break;
+      }
+    }
+  }
+}
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lvm.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lvm.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lvm.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lvm.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,34 @@
+/*
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lvm_h
+#define lvm_h
+
+
+#include "ldo.h"
+#include "lobject.h"
+#include "ltm.h"
+
+
+#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+
+#define tonumber(o,n)	(ttype(o) == LUA_TNUMBER || \
+                         (((o) = luaV_tonumber(o,n)) != NULL))
+
+#define equalobj(L,o1,o2) \
+	(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
+
+
+int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
+int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
+const TObject *luaV_tonumber (const TObject *obj, TObject *n);
+int luaV_tostring (lua_State *L, StkId obj);
+const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
+                              int loop);
+void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val);
+StkId luaV_execute (lua_State *L);
+void luaV_concat (lua_State *L, int total, int last);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lzio.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lzio.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lzio.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lzio.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,80 @@
+/*
+** a generic input stream interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lzio_c
+
+#include "lua.h"
+
+#include "llimits.h"
+#include "lmem.h"
+#include "lzio.h"
+
+
+int luaZ_fill (ZIO *z) {
+  size_t size;
+  const char *buff = z->reader(NULL, z->data, &size);
+  if (buff == NULL || size == 0) return EOZ;
+  z->n = size - 1;
+  z->p = buff;
+  return char2int(*(z->p++));
+}
+
+
+int luaZ_lookahead (ZIO *z) {
+  if (z->n == 0) {
+    int c = luaZ_fill(z);
+    if (c == EOZ) return c;
+    z->n++;
+    z->p--;
+  }
+  return char2int(*z->p);
+}
+
+
+void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) {
+  z->reader = reader;
+  z->data = data;
+  z->name = name;
+  z->n = 0;
+  z->p = NULL;
+}
+
+
+/* --------------------------------------------------------------- read --- */
+size_t luaZ_read (ZIO *z, void *b, size_t n) {
+  while (n) {
+    size_t m;
+    if (z->n == 0) {
+      if (luaZ_fill(z) == EOZ)
+        return n;  /* return number of missing bytes */
+      else {
+        ++z->n;  /* filbuf removed first byte; put back it */
+        --z->p;
+      }
+    }
+    m = (n <= z->n) ? n : z->n;  /* min. between n and z->n */
+    memcpy(b, z->p, m);
+    z->n -= m;
+    z->p += m;
+    b = (char *)b + m;
+    n -= m;
+  }
+  return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+  if (n > buff->buffsize) {
+    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+    luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
+    buff->buffsize = n;
+  }
+  return buff->buffer;
+}
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lzio.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lzio.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/lua/lzio.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/lua/lzio.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,63 @@
+/*
+** Buffered streams
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lzio_h
+#define lzio_h
+
+#include "lua.h"
+
+
+#define EOZ	(-1)			/* end of stream */
+
+typedef struct Zio ZIO;
+
+
+#define char2int(c)	cast(int, cast(unsigned char, (c)))
+
+#define zgetc(z)  (((z)->n--)>0 ?  char2int(*(z)->p++) : luaZ_fill(z))
+
+#define zname(z)	((z)->name)
+
+void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name);
+size_t luaZ_read (ZIO* z, void* b, size_t n);	/* read next n bytes */
+int luaZ_lookahead (ZIO *z);
+
+
+
+typedef struct Mbuffer {
+  char *buffer;
+  size_t buffsize;
+} Mbuffer;
+
+
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
+
+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define luaZ_sizebuffer(buff)	((buff)->buffsize)
+#define luaZ_buffer(buff)	((buff)->buffer)
+
+#define luaZ_resizebuffer(L, buff, size) \
+	(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+	(buff)->buffsize = size)
+
+#define luaZ_freebuffer(L, buff)	luaZ_resizebuffer(L, buff, 0)
+
+
+/* --------- Private Part ------------------ */
+
+struct Zio {
+  size_t n;			/* bytes still unread */
+  const char *p;		/* current position in buffer */
+  lua_Chunkreader reader;
+  void* data;			/* additional data */
+  const char *name;
+};
+
+
+int luaZ_fill (ZIO *z);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/os_unix.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/os_unix.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/os_unix.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/os_unix.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,636 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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.
+ *
+ */
+
+#if defined linux
+
+#include "link.h"
+#include "plugin.h"
+#include "lib.h"
+#include "os_unix.h"
+#include "http.h"
+#include "glua.h"
+#include "glua_ext.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+
+static int mainSocket;
+
+void getRandomBytes(unsigned char *buff, int len)
+{
+  int file;
+  int readLen;
+
+  memset(buff, 0, len);
+
+  file = open("/dev/random", O_RDONLY);
+
+  if (file < 0)
+  {
+    fprintf(stderr, "warning: cannot open /dev/random\n");
+    return;
+  }
+
+  while (len > 0)
+  {
+    readLen = read(file, buff, len);
+
+    if (readLen < 0)
+    {
+      fprintf(stderr, "warning: cannot read from /dev/random\n");
+      close(file);
+      return;
+    }
+
+    buff += readLen;
+    len -= readLen;
+  }
+
+  close(file);
+}
+
+int addrLen(int family)
+{
+  return (family == AF_INET) ? sizeof (struct in_addr) :
+    sizeof (struct in6_addr);
+}
+
+void os_now(struct timeStamp *timeStamp)
+{
+  timeStamp->time = time(NULL);
+}
+
+int timedOut(struct timeStamp *timeStamp, int sec)
+{
+  time_t now;
+
+  time(&now);
+
+  if ((time_t)(timeStamp->time + sec) > now)
+    return -1;
+
+  return 0;
+}
+
+unsigned int getMicro(void)
+{
+  struct timeval timeVal;
+  static struct timeval timeValPrev;
+  static int firstTime = 1;
+
+  gettimeofday(&timeVal, NULL);
+
+  if (firstTime == 0 &&
+      timeValPrev.tv_sec == timeVal.tv_sec &&
+      timeValPrev.tv_usec >= timeVal.tv_usec)
+    return timeValPrev.tv_sec * 1000000 + timeValPrev.tv_usec;
+
+  firstTime = 0;
+
+  timeValPrev.tv_sec = timeVal.tv_sec;
+  timeValPrev.tv_usec = timeVal.tv_usec;
+
+  return timeVal.tv_sec * 1000000 + timeVal.tv_usec;
+}
+
+void *allocMem(int len)
+{
+  void *res;
+
+  res = malloc(len);
+
+  if (res == NULL)
+  {
+    fprintf(stderr, "cannot allocate %d bytes\n", len);
+    exit(0);
+  }
+
+  memset(res, 0, len);
+
+  return res;
+}
+
+void freeMem(void *mem)
+{
+  free(mem);
+}
+
+int writeFileOs(const struct fileId *fileId, const unsigned char *data, int len)
+{
+  int writeLen;
+
+  if (len == 0)
+    return 0;
+
+  do
+    writeLen = write(fileId->fileDesc, data, len);
+  while (writeLen < 0 && errno == EINTR);
+
+  if (writeLen < 0)
+  {
+    if (errno == EAGAIN)
+      return 0;
+
+    error("cannot write to file descriptor: %s\n", strerror(errno));
+    return -1;
+  }
+
+  return writeLen;
+}
+
+int readFileOs(const struct fileId *fileId, unsigned char *data, int len)
+{
+  int readLen;
+
+  if (len == 0)
+    return 0;
+
+  do
+    readLen = read(fileId->fileDesc, data, len);
+  while (readLen < 0 && errno == EINTR);
+
+  if (readLen < 0)
+  {
+    if (errno == EAGAIN)
+      return 0;
+
+    error("cannot read from file descriptor: %s\n", strerror(errno));
+    return -1;
+  }
+
+  if (readLen == 0)
+    return -1;
+
+  return readLen;
+}
+
+int checkAbsPath(const char *path)
+{
+  if (path[0] != '/')
+    return -1;
+
+  return 0;
+}
+
+char *fullPath(const char *dir, const char *path)
+{
+  int dirLen = strlen(dir);
+  int pathLen = strlen(path);
+  char *buff = allocMem(dirLen + pathLen + 2);
+
+  memcpy(buff, dir, dirLen);
+
+  if (dirLen == 0 || buff[dirLen - 1] == '/')
+    dirLen--;
+
+  else
+    buff[dirLen] = '/';
+
+  memcpy(buff + dirLen + 1, path, pathLen + 1);
+
+  return buff;
+}
+
+void setExtension(char *res, const char *path, const char *ext)
+{
+  int i;
+  int len = strlen(path);
+
+  for (i = len - 1; i >= 0 && path[i] != '.' && path[i] != '/'; i--);
+
+  if (path[i] == '.')
+    len = i;
+
+  memcpy(res, path, len);
+  memcpy(res + len, ext, strlen(ext) + 1);
+}
+
+int isDirectory(const char *rootDir, const char *path)
+{
+  char *full = fullPath(rootDir, path);
+  struct stat statBuff;
+  int res;
+
+  res = stat(full, &statBuff);
+
+  freeMem(full);
+
+  if (res < 0)
+    return -1;
+
+  return S_ISDIR(statBuff.st_mode);
+}
+
+int openFile(struct fileId *fileId, const char *rootDir, const char *path)
+{
+  int fileDesc;
+  char *full = fullPath(rootDir, path);
+
+  fileDesc = open(full, O_RDONLY | O_NONBLOCK);
+
+  if (fileDesc < 0)
+  {
+    error("cannot open file %s: %s\n", full, strerror(errno));
+    freeMem(full);
+    return -1;
+  }
+
+  fileId->fileDesc = fileDesc;
+
+  freeMem(full);
+  return 0;
+}
+
+void closeFile(const struct fileId *fileId)
+{
+  close(fileId->fileDesc);
+}
+
+int fileIsNewer(const char *fileName1, const char *fileName2)
+{
+  struct stat stat1, stat2;
+
+  if (stat(fileName1, &stat1) < 0)
+  {
+    error("cannot stat %s: %s\n", fileName1, strerror(errno));
+    return -1;
+  }
+
+  if (stat(fileName2, &stat2) < 0)
+  {
+    if (errno != ENOENT)
+      error("cannot stat %s: %s\n", fileName2, strerror(errno));
+
+    return -1;
+  }
+
+  return stat1.st_mtime > stat2.st_mtime;    
+}
+
+int createAllDirs(char *path)
+{
+  int i;
+  int fail;
+
+  for (i = 0; path[i] != 0; i++)
+  {
+    if (path[i] == '/' && i > 0)
+    {
+      path[i] = 0;
+
+      fail = (mkdir(path, 0755) < 0 && errno != EEXIST);
+
+      path[i] = '/';
+
+      if (fail)
+        return -1;
+    }
+  }
+
+  return 0;
+}
+
+int parseIpAddr(struct ipAddr *addr, const char *addrStr)
+{
+  memset(addr, 0, sizeof (struct ipAddr));
+
+  if (inet_pton(AF_INET, addrStr, &addr->addr.v4) > 0)
+  {
+    addr->domain = PF_INET;
+    return 0;
+  }
+
+  if (inet_pton(AF_INET6, addrStr, &addr->addr.v6) > 0)
+  {
+    addr->domain = PF_INET6;
+    return 0;
+  }
+
+  fprintf(stderr, "cannot parse IP address\n");
+  return -1;
+}
+
+char *ipAddrToString(struct ipAddr *addr)
+{
+  static char buff[8][40];
+  static int i = 0;
+  char *res;
+
+  res = buff[i];
+
+  if (addr->domain == PF_INET)
+    inet_ntop(AF_INET, &addr->addr.v4, res, 40);
+
+  else
+    inet_ntop(AF_INET6, &addr->addr.v6, res, 40);
+
+  i = (i + 1) & 7;
+
+  return res;
+}
+
+char *rawIpAddrToString(void *rawAddr, int len)
+{
+  struct ipAddr addr;
+
+  if (len == 4)
+  {
+    memcpy(&addr.addr.v4, rawAddr, 4);
+    addr.domain = PF_INET;
+  }
+
+  else
+  {
+    memcpy(&addr.addr.v6, rawAddr, 16);
+    addr.domain = PF_INET6;
+  }
+
+  return ipAddrToString(&addr);
+}
+
+static int createSockAddr(struct sockaddr *sockAddr,
+                          const struct ipAddr *addr, int port)
+{
+  struct sockaddr_in *sockAddr4;
+  struct sockaddr_in6 *sockAddr6;
+
+  memset(sockAddr, 0, sizeof (struct sockaddr));
+
+  if (addr->domain == PF_INET)
+  {
+    sockAddr4 = (struct sockaddr_in *)sockAddr;
+
+    sockAddr4->sin_family = AF_INET;
+    sockAddr4->sin_port = htons((short)port);
+    sockAddr4->sin_addr.s_addr = addr->addr.v4.s_addr;
+
+    return 0;
+  }
+
+  if (addr->domain == PF_INET6)
+  {
+    sockAddr6 = (struct sockaddr_in6 *)sockAddr;
+
+    sockAddr6->sin6_family = AF_INET6;
+    sockAddr6->sin6_port = htons((short)port);
+    memcpy(&sockAddr6->sin6_addr, &addr->addr.v6, sizeof (struct in6_addr));
+
+    return 0;
+  }
+
+  fprintf(stderr, "invalid protocol family: %d\n", addr->domain);
+  return -1;
+}
+
+static int addrFromSockAddr(struct ipAddr *addr, const struct sockaddr *sockAddr)
+{
+  const struct sockaddr_in *sockAddr4 = (const struct sockaddr_in *)sockAddr;
+  const struct sockaddr_in6 *sockAddr6 = (const struct sockaddr_in6 *)sockAddr;
+
+  memset(addr, 0, sizeof (struct ipAddr));
+
+  if (sockAddr4->sin_family == AF_INET)
+  {
+    addr->domain = PF_INET;
+    addr->addr.v4.s_addr = sockAddr4->sin_addr.s_addr;
+    return 0;
+  }
+
+  if (sockAddr6->sin6_family == AF_INET6)
+  {
+    addr->domain = PF_INET6;
+    memcpy(&addr->addr.v6, &sockAddr6->sin6_addr, sizeof (struct in6_addr));
+    return 0;
+  }
+
+  fprintf(stderr, "invalid address family: %d\n", sockAddr4->sin_family);
+  return -1;
+}
+
+int createMainSocket(const struct ipAddr *addr, int port)
+{
+  struct sockaddr sockAddr;
+  static int truePara = 1;
+  int flags;
+
+  if (createSockAddr(&sockAddr, addr, port) < 0)
+  {
+    fprintf(stderr, "cannot create socket address\n");
+    return -1;
+  }
+
+  mainSocket = socket(addr->domain, SOCK_STREAM, IPPROTO_TCP);
+
+  if (mainSocket < 0)
+  {
+    error("cannot create main socket: %s\n", strerror(errno));
+    return -1;
+  }
+
+  if (setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, &truePara,
+                 sizeof (truePara)) < 0)
+  {
+    error("cannot set SO_REUSEADDR socket option: %s\n", strerror(errno));
+    close(mainSocket);
+    return -1;
+  }
+
+  flags = fcntl(mainSocket, F_GETFL);
+
+  if (flags < 0)
+  {
+    error("cannot get flags : %s\n", strerror(errno));
+    close(mainSocket);
+    return -1;
+  }
+
+  if (fcntl(mainSocket, F_SETFL, flags | O_NONBLOCK) < 0)
+  {
+    error("cannot set flags: %s\n", strerror(errno));
+    close(mainSocket);
+    return -1;
+  }
+
+  if (bind(mainSocket, &sockAddr, sizeof (struct sockaddr)) < 0)
+  {
+    error("cannot bind main socket: %s\n", strerror(errno));
+    close(mainSocket);
+    return -1;
+  }
+
+  if (listen(mainSocket, 10) < 0)
+  {
+    error("cannot listen on main socket: %s\n", strerror(errno));
+    close(mainSocket);
+    return -1;
+  }
+
+  return 0;
+}
+
+int acceptConn(struct fileId **sockId, struct ipAddr **addr)
+{
+  struct sockaddr sockAddr;
+  socklen_t len;
+  int sock;
+  int flags;
+
+  do
+  {
+    len = sizeof (struct sockaddr);
+
+    sock = accept(mainSocket, &sockAddr, &len);
+  }
+  while (sock < 0 && errno == EINTR);
+
+  if (sock < 0)
+  {
+    if (errno != EAGAIN)
+      error("accept failed: %s\n", strerror(errno));
+
+    return -1;
+  }
+
+  flags = fcntl(sock, F_GETFL);
+
+  if (flags < 0)
+  {
+    error("cannot get flags : %s\n", strerror(errno));
+    close(sock);
+    return -1;
+  }
+
+  if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
+  {
+    error("cannot set flags: %s\n", strerror(errno));
+    close(sock);
+    return -1;
+  }
+
+  *addr = allocMem(sizeof (struct ipAddr));
+
+  if (addrFromSockAddr(*addr, &sockAddr) < 0)
+  {
+    error("cannot convert socket address\n");
+    freeMem(addr);
+    close(sock);
+    return -1;
+  }
+
+  *sockId = allocMem(sizeof (struct fileId));
+
+  (*sockId)->fileDesc = sock;
+
+  return 0;
+}
+
+void closeMainSocket(void)
+{
+  close(mainSocket);
+}
+
+int waitForSockets(struct fileId *sockIds[], int *flags[], int num)
+{
+  fd_set readSet, writeSet;
+  int i;
+  int fileDesc;
+  int max;
+  int res;
+
+  FD_ZERO(&readSet);
+  FD_ZERO(&writeSet);
+
+  FD_SET(mainSocket, &readSet);
+
+  max = mainSocket;
+
+  for (i = 0; i < num; i++)
+  {
+    fileDesc = sockIds[i]->fileDesc;
+
+    if (fileDesc > max)
+      max = fileDesc;
+
+    if ((*flags[i] & FLAG_READ) != 0)
+      FD_SET(fileDesc, &readSet);
+
+    if ((*flags[i] & FLAG_WRITE) != 0)
+      FD_SET(fileDesc, &writeSet);
+  }
+
+  do
+    res = select(max + 1, &readSet, &writeSet, NULL, NULL);
+  while (res < 0 && errno == EINTR);
+
+  if (res < 0)
+  {
+    error("cannot select: %s\n", strerror(errno));
+    return -1;
+  }
+
+  for (i = 0; i < num; i++)
+  {
+    *flags[i] = 0;
+
+    fileDesc = sockIds[i]->fileDesc;
+
+    if (FD_ISSET(fileDesc, &readSet))
+      *flags[i] |= FLAG_READ;
+
+    if (FD_ISSET(fileDesc, &writeSet))
+      *flags[i] |= FLAG_WRITE;
+  }
+
+  return 0;
+}
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/os_unix.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/os_unix.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/os_unix.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/os_unix.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,100 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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.
+ *
+ */
+
+#if defined linux
+
+#include <netinet/in.h>
+
+struct ipAddr
+{
+  int domain;
+
+  union
+  {
+    struct in_addr v4;
+    struct in6_addr v6;
+  }
+  addr;
+};
+
+struct fileId
+{
+  int fileDesc;
+};
+
+struct timeStamp
+{
+  unsigned int time;
+};
+
+extern void getRandomBytes(unsigned char *buff, int len);
+
+extern int addrLen(int family);
+
+extern void os_now(struct timeStamp *timeStamp);
+extern int timedOut(struct timeStamp *timeStamp, int sec);
+
+extern unsigned int getMicro(void);
+
+extern void *allocMem(int len);
+extern void freeMem(void *mem);
+
+extern int writeFileOs(const struct fileId *sockId, const unsigned char *data,
+                       int len);
+extern int readFileOs(const struct fileId *sockId, unsigned char *data, int len);
+extern int checkAbsPath(const char *path);
+extern char *fullPath(const char *dir, const char *path);
+extern void setExtension(char *res, const char *path, const char *ext);
+extern int isDirectory(const char *rootDir, const char *path);
+extern int openFile(struct fileId *fileId, const char *rootDir, const char *path);
+extern void closeFile(const struct fileId *sockId);
+extern int fileIsNewer(const char *fileName1, const char *fileName2);
+extern int createAllDirs(char *path);
+
+extern int parseIpAddr(struct ipAddr *addr, const char *addrStr);
+extern char *ipAddrToString(struct ipAddr *addr);
+extern char *rawIpAddrToString(void *rawAddr, int len);
+extern int createMainSocket(const struct ipAddr *addr, int port);
+extern int acceptConn(struct fileId **sockId, struct ipAddr **addr);
+extern void closeMainSocket(void);
+extern int waitForSockets(struct fileId *sockIds[], int *flags[], int num);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/plugin.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,503 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 <string.h>
+#include <time.h> // clock_t required by olsrd includes
+
+#include "link.h"
+#include "plugin.h"
+#include "lib.h"
+#include "os_unix.h"
+#include "http.h"
+#include "glua.h"
+#include "glua_ext.h"
+#include "olsrd_plugin.h"
+#include "net_olsr.h"
+
+#include <defs.h>
+#include <olsr.h>
+#include <scheduler.h>
+#include <parser.h>
+#include <link_set.h>
+#include <neighbor_table.h>
+#include <two_hop_neighbor_table.h>
+#include <mid_set.h>
+#include <tc_set.h>
+#include <hna_set.h>
+#include <routing_table.h>
+#include <olsr_protocol.h>
+#include <mpr_selector_set.h>
+#include <duplicate_set.h>
+#include <lq_plugin.h>
+
+#define PLUGIN_INTERFACE_VERSION 5
+
+#define MESSAGE_TYPE 129
+
+int olsrd_plugin_interface_version(void);
+int olsrd_plugin_register_param(char *name, char *value);
+int olsrd_plugin_init(void);
+
+static int ipAddrLen;
+static union olsr_ip_addr *mainAddr;
+
+static struct interface *intTab = NULL;
+static struct neighbor_entry *neighTab = NULL;
+static struct mid_entry *midTab = NULL;
+static struct hna_entry *hnaTab = NULL;
+static struct olsrd_config *config = NULL;
+
+static int iterIndex;
+#if 0
+/* not used */
+static struct interface *iterIntTab = NULL;
+static struct mid_entry *iterMidTab = NULL;
+static struct hna_entry *iterHnaTab = NULL;
+#endif
+
+static struct link_entry *iterLinkTab = NULL;
+static struct neighbor_entry *iterNeighTab = NULL;
+static struct tc_entry *iterTcTab = NULL;
+static struct rt_entry *iterRouteTab = NULL;
+
+static void __attribute__((constructor)) banner(void)
+{
+  printf("Tiny Application Server 0.1 by olsr.org\n");
+}
+
+int iterLinkTabNext(char *buff, int len)
+{
+  struct list_node *link_node;
+  struct lqtextbuffer lqbuffer;
+  
+  if (iterLinkTab == NULL)
+    return -1;
+
+  snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%f~cost~%s~",
+           rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen),
+           rawIpAddrToString(&iterLinkTab->neighbor_iface_addr, ipAddrLen),
+           rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen),
+           iterLinkTab->L_link_quality,
+           get_linkcost_text(iterLinkTab->linkcost, OLSR_FALSE, &lqbuffer));
+
+
+  link_node = iterLinkTab->link_list.next;
+  if (link_node != &link_entry_head) {
+    iterLinkTab = list2link(link_node);
+  } else {
+    iterLinkTab = NULL;
+  }
+
+  return 0;
+}
+
+void iterLinkTabInit(void)
+{
+  struct list_node *link_node;
+
+  link_node = link_entry_head.next;
+  if (link_node != &link_entry_head) {
+    iterLinkTab = list2link(link_node);
+  } else {
+    iterLinkTab = NULL;
+  }
+}
+
+int iterNeighTabNext(char *buff, int len)
+{
+  int res;
+  int i;
+  struct neighbor_2_list_entry *neigh2;
+  
+  if (iterNeighTab == NULL)
+    return -1;
+
+  res = snprintf(buff, len,
+                 "main~%s~symmetric~%s~mpr~%s~mprs~%s~willingness~%d~[~neighbors2~",
+                 rawIpAddrToString(&iterNeighTab->neighbor_main_addr, ipAddrLen),
+                 iterNeighTab->status == SYM ? "true" : "false",
+                 iterNeighTab->is_mpr != 0 ? "true" : "false",
+                 olsr_lookup_mprs_set(&iterNeighTab->neighbor_main_addr) != NULL ?
+                 "true" : "false",
+                 iterNeighTab->willingness);
+
+  i = 0;
+
+  len -= res;
+  buff += res;
+
+  len -= 2;
+
+  for (neigh2 = iterNeighTab->neighbor_2_list.next;
+       neigh2 != &iterNeighTab->neighbor_2_list;
+       neigh2 = neigh2->next)
+  {
+    res = snprintf(buff, len, "%d~%s~", i,
+                   rawIpAddrToString(&neigh2->neighbor_2->neighbor_2_addr,
+                                     ipAddrLen));
+
+    if (res < len)
+      buff += res;
+
+    len -= res;
+
+    if (len <= 0)
+      break;
+
+    i++;
+  }
+
+  strcpy(buff, "]~");
+
+  iterNeighTab = iterNeighTab->next;
+
+  if (iterNeighTab == &neighTab[iterIndex])
+  {
+    iterNeighTab = NULL;
+    
+    while (++iterIndex < HASHSIZE)
+      if (neighTab[iterIndex].next != &neighTab[iterIndex])
+      {
+        iterNeighTab = neighTab[iterIndex].next;
+        break;
+      }
+  }
+
+  return 0;
+}
+
+void iterNeighTabInit(void)
+{
+  iterNeighTab = NULL;
+
+  if (neighTab == NULL)
+    return;
+
+  for (iterIndex = 0; iterIndex < HASHSIZE; iterIndex++)
+    if (neighTab[iterIndex].next != &neighTab[iterIndex])
+    {
+      iterNeighTab = neighTab[iterIndex].next;
+      break;
+    }
+}
+
+int iterRouteTabNext(char *buff, int len)
+{
+  struct avl_node *rt_tree_node;
+
+  if (iterRouteTab == NULL)
+    return -1;
+
+  snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
+           rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen),
+           rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
+           if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index),
+           iterRouteTab->rt_best->rtp_metric.hops);
+
+  rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
+  if (rt_tree_node) {
+      iterRouteTab = rt_tree2rt(rt_tree_node);
+  } else {
+      iterRouteTab = NULL;
+  }
+
+  return 0;
+}
+
+void iterRouteTabInit(void)
+{
+  struct avl_node *node;
+
+  avl_init(&routingtree, avl_comp_prefix_default);
+  routingtree_version = 0;
+
+  node = avl_walk_first(&routingtree);
+  iterRouteTab = node ? rt_tree2rt(node) : NULL;
+
+}
+
+/**
+ * Grab the next topology entry.
+ *
+ * @param adr the address to look for
+ * @return the entry found or NULL
+ */
+static struct tc_entry *
+tas_getnext_tc_entry(struct tc_entry *tc)
+{
+  struct avl_node *node = avl_walk_next(&tc->vertex_node);
+
+  return (node ? vertex_tree2tc(node) : NULL);
+}
+
+int iterTcTabNext(char *buff, int len)
+{
+  int res;
+  int i;
+  struct tc_edge_entry *tc_edge;
+  struct lqtextbuffer lqbuffer;
+  
+  if (iterTcTab == NULL)
+    return -1;
+
+  res = snprintf(buff, len,
+                 "main~%s~[~destinations~",
+                 rawIpAddrToString(&iterTcTab->addr, ipAddrLen));
+
+  len -= res;
+  buff += res;
+
+  len -= 2;
+  i = 0;
+
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(iterTcTab, tc_edge) {
+
+    res = snprintf(buff, len, "[~%d~address~%s~cost~%s~]~", i,
+                   rawIpAddrToString(&tc_edge->T_dest_addr, ipAddrLen),
+                   get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer));
+
+    if (res < len)
+      buff += res;
+
+    len -= res;
+
+    if (len <= 0)
+      break;
+
+    i++;
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(iterTcTab, tc_edge);
+  
+  strcpy(buff, "]~");
+
+  iterTcTab = tas_getnext_tc_entry(iterTcTab);
+
+  return 0;
+}
+
+void iterTcTabInit(void)
+{
+  struct avl_node *node;
+  
+  avl_init(&tc_tree, avl_comp_default);
+
+  node = avl_walk_first(&tc_tree);
+  iterTcTab = (node ? vertex_tree2tc(node) : NULL);
+}
+
+static void parserFunc(union olsr_message *msg,
+                       struct interface *inInt __attribute__((unused)),
+                       union olsr_ip_addr *neighIntAddr)
+{
+  char *mess = (char *)msg;
+  union olsr_ip_addr *orig = (union olsr_ip_addr *)(mess + 4);
+  int len = (mess[2] << 8) | mess[3];
+  char *service, *string;
+  int i;
+
+  if (memcmp(orig, mainAddr, ipAddrLen) == 0)
+    return;
+
+  if (check_neighbor_link(neighIntAddr) != SYM_LINK)
+  {
+    error("TAS message not from symmetric neighbour\n");
+    return;
+  }
+
+  if (len < ipAddrLen + 8 + 2)
+  {
+    error("short TAS message received (%d bytes)\n", len);
+    return;
+  }
+
+    len -= ipAddrLen + 8;
+    service = mess + ipAddrLen + 8;
+
+    for (i = 0; i < len && service[i] != 0; i++);
+
+    if (i++ == len)
+    {
+      error("TAS message has unterminated service string\n");
+      return;
+    }
+
+    if (i == len)
+    {
+      error("TAS message lacks payload string\n");
+      return;
+    }
+
+    string = service + i;
+    len -= i;
+
+    for (i = 0; i < len && string[i] != 0; i++);
+
+    if (i == len)
+    {
+      error("TAS message has unterminated payload string\n");
+      return;
+    }
+
+    httpAddTasMessage(service, string, rawIpAddrToString(orig, ipAddrLen));
+
+  olsr_forward_message(msg, neighIntAddr);
+}
+
+void sendMessage(const char *service, const char *string)
+{
+  unsigned char *mess, *walker;
+  int len, pad;
+  unsigned short seqNo;
+  struct interface *inter;
+
+  pad = len = ipAddrLen + 8 + strlen(service) + 1 + strlen(string) + 1;
+
+  len = 1 + ((len - 1) | 3);
+
+  pad = len - pad;
+
+  walker = mess = allocMem(len);
+
+  seqNo = get_msg_seqno();
+
+  *walker++ = MESSAGE_TYPE;
+  *walker++ = 0;
+  *walker++ = (unsigned char)(len >> 8);
+  *walker++ = (unsigned char)len;
+
+  memcpy(walker, mainAddr, ipAddrLen);
+  walker += ipAddrLen;
+
+  *walker++ = 255;
+  *walker++ = 0;
+  *walker++ = (unsigned char)(seqNo >> 8);
+  *walker++ = (unsigned char)seqNo;
+
+  while (*service != 0)
+    *walker++ = *service++;
+
+  *walker++ = 0;
+
+  while (*string != 0)
+    *walker++ = *string++;
+
+  *walker++ = 0;
+
+  while (pad-- > 0)
+    *walker++ = 0;
+
+  for (inter = intTab; inter != NULL; inter = inter->int_next)
+  {
+    if (net_outbuffer_push(inter, mess, len) != len)
+    {
+      net_output(inter);
+      net_outbuffer_push(inter, mess, len);
+    }
+  }
+}
+
+static void serviceFunc(void *context __attribute__((unused)))
+{
+  static int up = 0;
+
+  if (up == 0)
+  {
+    if (httpSetup() < 0)
+      return;
+
+    up = 1;
+  }
+
+  if (up != 0)
+    httpService((int)(1.0 / config->pollrate));
+}
+
+int olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+int olsrd_plugin_init(void)
+{
+  ipAddrLen = olsr_cnf->ipsize;
+  mainAddr = &olsr_cnf->main_addr;
+
+  intTab = ifnet;
+  neighTab = neighbortable;
+  midTab = mid_set;
+  hnaTab = hna_set;
+  config = olsr_cnf;
+
+  httpInit();
+  
+  olsr_start_timer(OLSR_TAS_SERVICE_INT, 0, OLSR_TIMER_PERIODIC,
+                   &serviceFunc, NULL, 0);
+
+  olsr_parser_add_function(parserFunc, MESSAGE_TYPE, 1);
+
+  return 0;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "address",   .set_plugin_parameter = &httpSetAddress,   .data = NULL },
+    { .name = "port",      .set_plugin_parameter = &httpSetPort,      .data = NULL },
+    { .name = "rootdir",   .set_plugin_parameter = &httpSetRootDir,   .data = NULL },
+    { .name = "workdir",   .set_plugin_parameter = &httpSetWorkDir,   .data = NULL },
+    { .name = "indexfile", .set_plugin_parameter = &httpSetIndexFile, .data = NULL },
+    { .name = "user",      .set_plugin_parameter = &httpSetUser,      .data = NULL },
+    { .name = "password",  .set_plugin_parameter = &httpSetPassword,  .data = NULL },
+    { .name = "sesstime",  .set_plugin_parameter = &httpSetSessTime,  .data = NULL },
+    { .name = "pubdir",    .set_plugin_parameter = &httpSetPubDir,    .data = NULL },
+    { .name = "quantum",   .set_plugin_parameter = &httpSetQuantum,   .data = NULL },
+    { .name = "messtime",  .set_plugin_parameter = &httpSetMessTime,  .data = NULL },
+    { .name = "messlimit", .set_plugin_parameter = &httpSetMessLimit, .data = NULL },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/plugin.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/plugin.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/src/plugin.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/src/plugin.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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.
+ *
+ */
+
+#define OLSR_TAS_SERVICE_INT 100 /* msec */
+
+extern void sendMessage(const char *service, const char *string);
+extern void iterLinkTabInit(void);
+extern int iterLinkTabNext(char *buff, int len);
+extern void iterRouteTabInit(void);
+extern int iterRouteTabNext(char *buff, int len);
+extern void iterNeighTabInit(void);
+extern int iterNeighTabNext(char *buff, int len);
+extern void iterTcTabInit(void);
+extern int iterTcTabNext(char *buff, int len);
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/tas.conf ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/tas.conf
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/tas.conf	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/tas.conf	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,15 @@
+LoadPlugin "olsrd_tas.so.0.1"
+{
+	PlParam	"address"	"0.0.0.0"
+	PlParam	"port"		"1979"
+	PlParam	"rootdir"	"/etc/tas"
+	PlParam "workdir"	"/var/run/tas"
+	PlParam "indexfile"	"index.html"
+#	PlParam	"user"		"test"
+#	PlParam "password"	"test"
+	PlParam	"sesstime"	"600"
+	PlParam	"pubdir"	"pub"
+	PlParam "quantum"	"30"
+	PlParam	"messtime"	"60"
+	PlParam "messlimit"	"50"
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/test.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/test.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/test.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/test.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,286 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ *
+ * Copyright (c) 2004, Thomas Lopatic (thomas@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 "src/link.h"
+#include "src/plugin.h"
+#include "src/lib.h"
+#include "src/os_unix.h"
+#include "src/http.h"
+#include "src/glua.h"
+#include "src/glua_ext.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void sigHand(int sig) __attribute__((noreturn));
+static void sigHand(int sig __attribute__((unused)))
+{
+  httpShutdown();
+  exit(0);
+}
+
+static void usage(void)
+{
+  fprintf(stderr, "usage: tas [--address ip-address] [--port port-number]\n");
+  fprintf(stderr, "           [--work-dir work-directory] [--root-dir root-directory]\n");
+  fprintf(stderr, "           [--password password] [--user user] [--sess-time session-timeout]\n");
+  fprintf(stderr, "           [--index-file index-file] [--pub-dir public-directory]\n");
+  fprintf(stderr, "           [--quantum quantum] [--mess-time message-timeout]\n");
+  fprintf(stderr, "           [--mess-limit message-queue-limit]\n");
+}
+
+int main(int ac, char *av[])
+{
+  int i;
+
+  httpInit();
+
+  for (i = 1; i < ac; i++)
+  {
+    if (strcmp(av[i], "--address") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing address parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetAddress(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set address\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--port") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing port parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetPort(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set port\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--work-dir") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing work directory parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetWorkDir(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set work directory\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--root-dir") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing root directory parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetRootDir(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set root directory\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--index-file") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing index file parameter\n");
+        usage();
+        return 1;
+      }
+
+      httpSetIndexFile(av[i], NULL, (set_plugin_parameter_addon){0});
+    }
+
+    else if (strcmp(av[i], "--user") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing user parameter\n");
+        usage();
+        return 1;
+      }
+
+      httpSetUser(av[i], NULL, (set_plugin_parameter_addon){0});
+    }
+
+    else if (strcmp(av[i], "--password") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing password parameter\n");
+        usage();
+        return 1;
+      }
+
+      httpSetPassword(av[i], NULL, (set_plugin_parameter_addon){0});
+    }
+
+    else if (strcmp(av[i], "--sess-time") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing timeout parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetSessTime(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set session timeout\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--pub-dir") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing public directory parameter\n");
+        usage();
+        return 1;
+      }
+
+      httpSetPubDir(av[i], NULL, (set_plugin_parameter_addon){0});
+    }
+
+    else if (strcmp(av[i], "--quantum") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing quantum parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetQuantum(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set quantum\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--mess-time") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing timeout parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetMessTime(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set message timeout\n");
+        return 1;
+      }
+    }
+
+    else if (strcmp(av[i], "--mess-limit") == 0)
+    {
+      if (++i == ac)
+      {
+        fprintf(stderr, "missing limit parameter\n");
+        usage();
+        return 1;
+      }
+
+      if (httpSetMessLimit(av[i], NULL, (set_plugin_parameter_addon){0}) < 0)
+      {
+        fprintf(stderr, "cannot set message queue limit\n");
+        return 1;
+      }
+    }
+
+    else
+    {
+      fprintf(stderr, "invalid argument: %s\n", av[i]);
+      usage();
+      return 1;
+    }
+  }
+
+  signal(SIGINT, sigHand);
+  signal(SIGTERM, sigHand);
+
+  if (httpSetup() < 0)
+  {
+    fprintf(stderr, "cannot set up HTTP server\n");
+    return 1;
+  }
+
+  while (1)
+  {
+    if (httpService(10) < 0)
+    {
+      fprintf(stderr, "cannot run HTTP server\n");
+      return 1;
+    }
+
+    usleep(100000);
+  }
+
+  return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/tas/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/tas/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,56 @@
+# 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.
+#
+
+OLSRD_PLUGIN =	true
+PLUGIN_NAME =	olsrd_txtinfo
+PLUGIN_VER =	0.1
+
+TOPDIR =	../..
+include $(TOPDIR)/Makefile.inc
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+		$(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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/README_TXTINFO ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/README_TXTINFO
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/README_TXTINFO	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/README_TXTINFO	2008-10-03 14:45:07.000000000 +0200
@@ -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 ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/src/olsrd_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/src/olsrd_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/src/olsrd_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/src/olsrd_plugin.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * 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"
+#include "defs.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 5
+
+
+union olsr_ip_addr ipc_accept_ip;
+int ipc_port;
+int nompr;
+
+static void my_init(void) __attribute__ ((constructor));
+static void my_fini(void) __attribute__ ((destructor));
+
+/**
+ *Constructor
+ */
+static void my_init(void)
+{
+    /* Print plugin info to stdout */
+    printf("%s\n", MOD_DESC);
+
+    /* defaults for parameters */
+    ipc_port = 2006;
+    if (olsr_cnf->ip_version == AF_INET) {
+        ipc_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
+    } else {
+        ipc_accept_ip.v6 = in6addr_loopback;
+    }
+
+    /* highlite neighbours by default */
+    nompr = 0;
+}
+
+/**
+ *Destructor
+ */
+static void my_fini(void)
+{
+    /* 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(void)
+{
+    return PLUGIN_INTERFACE_VERSION;
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+    { .name = "port",   .set_plugin_parameter = &set_plugin_port,      .data = &ipc_port },
+    { .name = "accept", .set_plugin_parameter = &set_plugin_ipaddress, .data = &ipc_accept_ip },
+};
+
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+    *params = plugin_parameters;
+    *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,569 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+ 
+#include <sys/types.h>
+#include <sys/socket.h>
+#if !defined WIN32
+#include <sys/select.h>
+#endif
+#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 "ipcalc.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 "net_olsr.h"
+#include "lq_plugin.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 send_what);
+
+static void ipc_action(int);
+
+static void ipc_print_neigh(void);
+
+static void ipc_print_link(void);
+
+static void ipc_print_routes(void);
+
+static void ipc_print_topology(void);
+
+static void ipc_print_hna(void);
+
+static void ipc_print_mid(void);
+
+#define TXT_IPC_BUFSIZE 256
+
+#define SIW_ALL 0
+#define SIW_NEIGH 1
+#define SIW_LINK 2
+#define SIW_ROUTE 3
+#define SIW_HNA 4
+#define SIW_MID 5
+#define SIW_TOPO 6
+#define SIW_NEIGHLINK 7
+
+static int ipc_sendf(const char* format, ...) __attribute__((format(printf, 1, 2)));
+
+/**
+ *Do initialization here
+ *
+ *This function is called by the my_init
+ *function in uolsrd_plugin.c
+ */
+int
+olsrd_plugin_init(void)
+{
+    /* Initial IPC value */
+    ipc_open = 0;
+    ipc_socket_up = 0;
+
+    plugin_ipc_init();
+    return 1;
+}
+
+
+/**
+ * destructor - called at unload
+ */
+void olsr_plugin_exit(void)
+{
+    if(ipc_open)
+        close(ipc_socket);
+}
+
+
+
+static int
+plugin_ipc_init(void)
+{
+    struct sockaddr_storage sst;
+    struct sockaddr_in *sin;
+    struct sockaddr_in6 *sin6;
+    olsr_u32_t yes = 1;
+    socklen_t addrlen;
+
+    /* Init ipc socket */
+    if ((ipc_socket = socket(olsr_cnf->ip_version, 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(&sst, 0, sizeof(sst));
+        if (olsr_cnf->ip_version == AF_INET) {
+           sin = (struct sockaddr_in *)&sst;
+           sin->sin_family = AF_INET;
+           addrlen = sizeof(struct sockaddr_in);
+#ifdef SIN6_LEN
+           sin->sin_len = addrlen;
+#endif
+           sin->sin_addr.s_addr = INADDR_ANY;
+           sin->sin_port = htons(ipc_port);
+        } else {
+           sin6 = (struct sockaddr_in6 *)&sst;
+           sin6->sin6_family = AF_INET6;
+           addrlen = sizeof(struct sockaddr_in6);
+#ifdef SIN6_LEN
+           sin6->sin6_len = addrlen;
+#endif
+           sin6->sin6_addr = in6addr_any;
+           sin6->sin6_port = htons(ipc_port);
+        }
+      
+        /* bind the socket to the port number */
+        if (bind(ipc_socket, (struct sockaddr *) &sst, addrlen) == -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_storage pin;
+    struct sockaddr_in *sin4;
+    struct sockaddr_in6 *sin6;
+    char addr[INET6_ADDRSTRLEN];
+    fd_set rfds;
+    struct timeval tv;
+    int send_what = 0;
+
+    socklen_t addrlen = sizeof(struct sockaddr_storage);
+
+    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
+        return;
+    }
+
+    tv.tv_sec = tv.tv_usec = 0;
+    if (olsr_cnf->ip_version == AF_INET) {
+        sin4 = (struct sockaddr_in *)&pin;
+        if (inet_ntop(olsr_cnf->ip_version, &sin4->sin_addr, addr,
+           INET6_ADDRSTRLEN) == NULL)
+             addr[0] = '\0';
+        if (!ip4equal(&sin4->sin_addr, &ipc_accept_ip.v4)) {
+            olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
+            close(ipc_connection);
+            return;
+        }
+    } else {
+        sin6 = (struct sockaddr_in6 *)&pin;
+        if (inet_ntop(olsr_cnf->ip_version, &sin6->sin6_addr, addr,
+           INET6_ADDRSTRLEN) == NULL)
+             addr[0] = '\0';
+       /* Use in6addr_any (::) in olsr.conf to allow anybody. */
+        if (!ip6equal(&in6addr_any, &ipc_accept_ip.v6) &&
+           !ip6equal(&sin6->sin6_addr, &ipc_accept_ip.v6)) {
+            olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
+            close(ipc_connection);
+            return;
+        }
+    }
+    ipc_open = 1;
+#ifndef NODEBUG
+    olsr_printf(2, "(TXTINFO) Connect from %s\n",addr);
+#endif
+      
+    /* purge read buffer to prevent blocking on linux*/
+    FD_ZERO(&rfds);
+    FD_SET((unsigned int)ipc_connection, &rfds); /* Win32 needs the cast here */
+    if(0 <= select(ipc_connection+1, &rfds, NULL, NULL, &tv)) {
+        char requ[128];
+        ssize_t s = recv(ipc_connection, (void*)&requ, sizeof(requ), 0); /* Win32 needs the cast here */
+        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.
+             */
+            if (0 != strstr(requ, "/neighbours")) send_what=SIW_NEIGHLINK;
+            else if (0 != strstr(requ, "/neigh")) send_what=SIW_NEIGH;
+            else if (0 != strstr(requ, "/link")) send_what=SIW_LINK;
+            else if (0 != strstr(requ, "/route")) send_what=SIW_ROUTE;
+            else if (0 != strstr(requ, "/hna")) send_what=SIW_HNA;
+            else if (0 != strstr(requ, "/mid")) send_what=SIW_MID;
+            else if (0 != strstr(requ, "/topo")) send_what=SIW_TOPO;
+        }
+    }
+
+	send_info(send_what);
+	  
+    close(ipc_connection);
+    ipc_open = 0;
+}
+
+static void ipc_print_neigh(void)
+{
+    struct ipaddr_str buf1;
+    struct neighbor_entry *neigh;
+    struct neighbor_2_list_entry *list_2;
+    int thop_cnt;
+
+    ipc_sendf("Table: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWill.\t2 Hop Neighbors\n");
+
+    /* Neighbors */
+    OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
+        ipc_sendf("%s\t%s\t%s\t%s\t%d\t", 
+                  olsr_ip_to_string(&buf1, &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(&buf1, &list_2->neighbor_2->neighbor_2_addr));
+            thop_cnt ++;
+        }
+        ipc_sendf("%d\n", thop_cnt);
+    } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
+    ipc_sendf("\n");
+}
+
+static void ipc_print_link(void)
+{
+    struct ipaddr_str buf1, buf2;
+    struct lqtextbuffer lqbuffer1, lqbuffer2;
+
+    struct link_entry *link = NULL;
+
+    ipc_sendf("Table: Links\nLocal IP\tRemote IP\tHyst.\tLQ\tNLQ\tCost\n");
+
+    /* Link set */
+    OLSR_FOR_ALL_LINK_ENTRIES(link) {
+	ipc_sendf( "%s\t%s\t%0.2f\t%s\t%s\t\n",
+                   olsr_ip_to_string(&buf1, &link->local_iface_addr),
+                   olsr_ip_to_string(&buf2, &link->neighbor_iface_addr),
+                   link->L_link_quality, 
+                   get_link_entry_text(link, '\t', &lqbuffer1),
+                   get_linkcost_text(link->linkcost, OLSR_FALSE, &lqbuffer2));
+    } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+
+    ipc_sendf("\n");
+}
+
+static void ipc_print_routes(void)
+{
+    struct ipaddr_str buf1, buf2;
+    struct rt_entry *rt;
+    struct lqtextbuffer lqbuffer;
+    
+    ipc_sendf("Table: Routes\nDestination\tGateway IP\tMetric\tETX\tInterface\n");
+
+    /* Walk the route table */
+    OLSR_FOR_ALL_RT_ENTRIES(rt) {
+        ipc_sendf( "%s/%d\t%s\t%d\t%s\t%s\t\n",
+                   olsr_ip_to_string(&buf1, &rt->rt_dst.prefix),
+                   rt->rt_dst.prefix_len,
+                   olsr_ip_to_string(&buf2, &rt->rt_best->rtp_nexthop.gateway),
+                   rt->rt_best->rtp_metric.hops,
+                   get_linkcost_text(rt->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer),
+                   if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
+    } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
+
+    ipc_sendf("\n");
+
+}
+
+static void ipc_print_topology(void)
+{
+    struct tc_entry *tc;
+    
+    ipc_sendf("Table: Topology\nDest. IP\tLast hop IP\tLQ\tNLQ\tCost\n");
+
+    /* Topology */  
+    OLSR_FOR_ALL_TC_ENTRIES(tc) {
+        struct tc_edge_entry *tc_edge;
+        OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+        	if (tc_edge->edge_inv)  {
+            struct ipaddr_str dstbuf, addrbuf;
+            struct lqtextbuffer lqbuffer1, lqbuffer2;
+            ipc_sendf( "%s\t%s\t%s\t%s\n", 
+                       olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
+                       olsr_ip_to_string(&addrbuf, &tc->addr), 
+                       get_tc_edge_entry_text(tc_edge, '\t', &lqbuffer1),
+                       get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2));
+        	}
+        } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+    } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+
+    ipc_sendf("\n");
+}
+
+static void ipc_print_hna(void)
+{
+    int size;
+    struct ip_prefix_list *hna;
+    struct hna_entry *tmp_hna;
+    struct hna_net *tmp_net;
+    struct ipaddr_str addrbuf, mainaddrbuf;
+
+    size = 0;
+
+    ipc_sendf("Table: HNA\nDestination\tGateway\n");
+
+    /* Announced HNA entries */
+    if (olsr_cnf->ip_version == AF_INET) {
+        for(hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
+            struct ipaddr_str addrbuf, mainaddrbuf;
+            ipc_sendf("%s/%d\t%s\n",
+                      olsr_ip_to_string(&addrbuf, &hna->net.prefix),
+                      hna->net.prefix_len,
+                      olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
+        }
+    } else {
+        for(hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
+            struct ipaddr_str addrbuf, mainaddrbuf;
+            ipc_sendf("%s/%d\t%s\n",
+                      olsr_ip_to_string(&addrbuf, &hna->net.prefix),
+                      hna->net.prefix_len,
+                      olsr_ip_to_string(&mainaddrbuf, &olsr_cnf->main_addr));
+        }
+    }
+
+    /* HNA entries */
+    OLSR_FOR_ALL_HNA_ENTRIES(tmp_hna) {
+
+        /* Check all networks */
+        for (tmp_net = tmp_hna->networks.next;
+             tmp_net != &tmp_hna->networks;
+             tmp_net = tmp_net->next) {
+
+            ipc_sendf("%s/%d\t%s\n",
+                      olsr_ip_to_string(&addrbuf, &tmp_net->A_network_addr),
+                      tmp_net->prefixlen,
+                      olsr_ip_to_string(&mainaddrbuf, &tmp_hna->A_gateway_addr));
+        }
+    } OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
+
+    ipc_sendf("\n");
+}
+
+static void ipc_print_mid(void)
+{
+    int index;
+    unsigned short is_first;
+    struct mid_entry *entry;
+    struct mid_address *alias;
+
+    ipc_sendf("Table: MID\nIP address\tAliases\n");
+
+    /* MID */
+    for(index = 0; index < HASHSIZE; index++) {
+        entry = mid_set[index].next;
+        
+        while( entry != &mid_set[index] ) {
+            struct ipaddr_str buf;
+            ipc_sendf( olsr_ip_to_string(&buf,  &entry->main_addr ) );
+            alias = entry->aliases;
+            is_first = 1;
+
+            while( alias ) {
+                ipc_sendf( "%s%s",
+                           ( is_first ? "\t" : ";" ),
+                           olsr_ip_to_string(&buf,  &alias->alias )
+                           );
+
+                alias = alias->next_alias;
+                is_first = 0;
+            }
+            entry = entry->next;
+            ipc_sendf("\n");
+        }
+    }
+    ipc_sendf("\n");
+}
+
+
+static void  send_info(int send_what)
+{
+    /* 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 */
+    if ((send_what==SIW_ALL)||(send_what==SIW_NEIGHLINK)||(send_what==SIW_LINK)) ipc_print_link();
+
+    if ((send_what==SIW_ALL)||(send_what==SIW_NEIGHLINK)||(send_what==SIW_NEIGH)) ipc_print_neigh();
+	
+    /* topology */
+    if ((send_what==SIW_ALL)||(send_what==SIW_TOPO)) ipc_print_topology();
+	
+    /* hna */
+    if ((send_what==SIW_ALL)||(send_what==SIW_HNA)) ipc_print_hna();
+
+    /* mid */
+    if ((send_what==SIW_ALL)||(send_what==SIW_MID)) ipc_print_mid();
+
+    /* routes */
+    if ((send_what==SIW_ALL)||(send_what==SIW_ROUTE)) 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;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/src/olsrd_txtinfo.h	2008-10-03 14:45:07.000000000 +0200
@@ -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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_TXTINFO
+#define _OLSRD_TXTINFO
+
+#include "olsr_types.h"
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+
+extern union olsr_ip_addr ipc_accept_ip;
+extern int ipc_port;
+extern int nompr;
+
+int olsrd_plugin_interface_version(void);
+int olsrd_plugin_init(void);
+void olsr_plugin_exit(void);
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/lib/txtinfo/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/lib/txtinfo/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/license.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/license.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/license.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/license.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,32 @@
+
+The olsr.org Optimized Link-State Routing daemon(olsrd)
+Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+                    Thomas Lopatic(thomas@lopatic.de)
+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.
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/list-excludes.sh ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/list-excludes.sh
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/list-excludes.sh	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/list-excludes.sh	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+#
+# LÃ–ist the to be excluded files
+#
+
+find -name ".cvsignore" -print | while read f
+do
+  d=${f%.cvsignore}
+  d=${d#./}
+  while read l
+  do
+    echo "$d$l"
+  done < $f
+done
+echo 'CVS'
+echo '*~'
+echo '#*#'
+echo '.#*'
+echo '*.o'
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/guess_os.sh ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/guess_os.sh
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/guess_os.sh	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/guess_os.sh	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+if test -n "$OS"; then
+	echo $OS;
+	exit;
+else
+	# OS not specified.
+	# get it from uname
+	arch=`uname -s | tr '[A-Z]' '[a-z]'`
+	case "$arch" in
+		linux)		arch=linux ;;
+		freebsd*)	arch=fbsd ;;
+		netbsd*)	arch=nbsd ;;
+		openbsd*)	arch=obsd ;;
+		darwin*)	arch=osx ;;
+		cygwin_*)	arch=win32 ;;
+		Windows_*)	arch=win32 ;;
+		*)		arch="UNKNOWN" ;;
+	esac
+	echo $arch
+fi
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.fbsd ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.fbsd
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.fbsd	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.fbsd	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,45 @@
+#
+# FREEBSD SPECIFIC CONFIGURATION
+#
+
+PREFIX ?= /usr/local
+SBINDIR = $(PREFIX)/sbin
+ETCDIR = $(PREFIX)/etc
+LIBDIR = $(PREFIX)/lib
+DOCDIR = $(PREFIX)/share/doc
+MANDIR = $(PREFIX)/man
+
+SRCS +=		$(wildcard src/bsd/*.c) $(wildcard src/unix/*.c)
+HDRS +=		$(wildcard src/bsd/*.h) $(wildcard src/unix/*.h)
+
+LIBS =
+
+CPPFLAGS +=	-DOLSRD_GLOBAL_CONF_FILE=\"$(CFGFILE)\"
+
+ifdef NO_80211
+CPPFLAGS +=	-DFBSD_NO_80211=1
+endif
+
+ifdef LIBNET
+
+CPPFLAGS +=	-DSPOOF -I$(PREFIX)/include
+LIBS +=		-L$(PREFIX)/lib -lnet
+
+endif
+
+ifdef OLSRD_PLUGIN
+CFLAGS +=	-fPIC
+LDFLAGS +=	-fPIC
+endif
+
+PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
+INSTALL_LIB =	install -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME); \
+		/sbin/ldconfig
+
+OS_LIB_PTHREAD = -pthread
+OS_CFLAG_PTHREAD = -pthread
+OS_LIB_DYNLOAD =
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.linux ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.linux
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.linux	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.linux	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,37 @@
+#
+# LINUX SPECIFIC CONFIGURATION
+#
+
+ARCH := $(shell uname -m)
+DESTDIR ?=
+LIBDIR =	$(DESTDIR)$(shell if [ "$(ARCH)" = "x86_64" -a -d "/usr/lib64" ]; then echo "/usr/lib64"; else echo "/usr/lib"; fi)
+
+SRCS += 	$(wildcard src/linux/*.c src/unix/*.c)
+HDRS +=		$(wildcard src/linux/*.h src/unix/*.h)
+
+CPPFLAGS += 	-Dlinux
+LIBS +=		
+
+PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
+INSTALL_LIB =	install -D -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME); \
+		/sbin/ldconfig -n $(LIBDIR)
+
+ifdef OLSRD_PLUGIN
+GENERATE_PIC = true
+endif
+ifeq ($(filter-out alpha x86_64 parisc64 ia64, $(ARCH)),)
+GENERATE_PIC = true
+endif
+
+ifdef GENERATE_PIC
+CFLAGS +=	-fPIC
+LDFLAGS +=	-fPIC
+endif
+
+OS_LIB_PTHREAD = -lpthread
+OS_CFLAG_PTHREAD = -pthread
+OS_LIB_DYNLOAD = -ldl
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.nbsd ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.nbsd
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.nbsd	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.nbsd	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,29 @@
+#
+# NETBSD SPECIFIC CONFIGURATION
+#
+
+DESTDIR ?=
+LIBDIR =	$(DESTDIR)/usr/lib
+
+SRCS +=		$(wildcard src/bsd/*.c src/unix/*.c)
+HDRS +=		$(wildcard src/bsd/*.h src/unix/*.h)
+
+CPPFLAGS +=	-D__NetBSD__
+LIBS +=		
+
+PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
+INSTALL_LIB =	install -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME); \
+		/sbin/ldconfig
+
+ifdef OLSRD_PLUGIN
+CFLAGS +=	-fPIC
+LDFLAGS +=	-fPIC
+endif
+
+OS_LIB_PTHREAD = 
+OS_CFLAG_PTHREAD =
+OS_LIB_DYNLOAD =
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.obsd ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.obsd
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.obsd	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.obsd	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,29 @@
+#
+# OPENBSD SPECIFIC CONFIGURATION
+#
+
+DESTDIR ?=
+LIBDIR =	$(DESTDIR)/usr/lib
+
+SRCS +=		$(wildcard src/bsd/*.c src/unix/*.c)
+HDRS +=		$(wildcard src/bsd/*.h src/unix/*.h)
+
+CPPFLAGS +=	-D__OpenBSD__
+LIBS +=		
+
+PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
+INSTALL_LIB =	install -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME); \
+		/sbin/ldconfig
+
+ifdef OLSRD_PLUGIN
+CFLAGS +=	-fPIC
+LDFLAGS +=	-fPIC
+endif
+
+OS_LIB_PTHREAD =
+OS_CFLAG_PTHREAD =
+OS_LIB_DYNLOAD =
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.osx ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.osx
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.osx	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.osx	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,33 @@
+#
+# MAC OSX SPECIFIC CONFIGURATION
+#
+
+# don't strip executables and bundles for now until we figure out the proper way
+# to do it (flags).
+STRIP = \#
+
+DESTDIR ?=
+LIBDIR =	$(DESTDIR)/usr/lib
+
+SRCS +=		$(wildcard src/bsd/*.c src/unix/*.c)
+HDRS +=		$(wildcard src/bsd/*.h src/unix/*.h)
+
+CPPFLAGS +=	-D__MacOSX__
+LIBS +=		
+
+PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
+INSTALL_LIB =	install -m 755 $(PLUGIN_FULLNAME) $(LIBDIR)/$(PLUGIN_FULLNAME)
+
+ifdef OLSRD_PLUGIN
+LDFLAGS = -bundle -flat_namespace -undefined suppress
+else
+LDFLAGS = -dynamic
+endif
+
+OS_LIB_PTHREAD =
+OS_CFLAG_PTHREAD =
+OS_LIB_DYNLOAD =
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.win32 ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.win32
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.win32	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.win32	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,138 @@
+#
+# WINDOWS32 SPECIFIC CONFIGURATION
+#
+
+DESTDIR ?=
+EXENAME = olsrd.exe
+
+SRCS +=		$(wildcard src/win32/*.c)
+HDRS +=		$(wildcard src/win32/*.h)
+
+CPPFLAGS +=	-DWIN32 -D_WIN32_WINNT=0x0600
+LIBS +=		-mno-cygwin -lws2_32 -liphlpapi
+CPPFLAGS += 	-I$(TOPDIR)/src/win32
+CFLAGS +=	-mno-cygwin
+
+PLUGIN_FULLNAME ?= $(PLUGIN_NAME).dll
+INSTALL_LIB =	cp $(PLUGIN_FULLNAME) ../..
+
+ifdef OLSRD_PLUGIN
+LDFLAGS +=	-L$(TOPDIR)
+#LIBS += 	$(TOPDIR)/src/win32/compat.o
+LIBS +=		-lolsrd
+endif
+
+OS_LIB_PTHREAD =
+OS_CFLAG_PTHREAD =
+OS_LIB_DYNLOAD =
+
+# Notes for compiling olsrd under Windows
+# ---------------------------------------
+# You need at least Cygwin installed. Start the Cygwin setup and select
+# flex,bison,make,mingw-core. Then run "make all libs" to compile olsrd.exe
+# and the plugin DLLs. To compile the GUI, you need MSVC6, PlatformSDK and
+# the NSIS installer. Adapt the path names below and run "make win32setup".
+# Alternatively, set environment vars e.g. in the Windows registry under
+# HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment e.g.
+#
+# set PATH=C:\PROGRA~1\MICROS~4\VC98\BIN;C:\PROGRA~1\MIFD68~1\BIN;C:\PROGRA~1\NSIS;%PATH%
+# set LIB=C:\PROGRA~1\MIFD68~1\LIB;C:\PROGRA~1\MICROS~4\VC98\LIB;C:\PROGRA~1\MICROS~4\VC98\MFC\LIB
+# set INCLUDE=C:\PROGRA~1\MIFD68~1\INCLUDE;C:\PROGRA~1\MICROS~4\VC98\INCLUDE;C:\PROGRA~1\MICROS~4\VC98\MFC\INCLUDE
+#
+# You can install Cygwin under Wine. Then "wineconsole make all libs win32lib"
+# does it's job (slowly), but there may be issues while re-invoking MSVC from
+# bash.exe during "wineconsole win32setup". Note, that Wine on EXT2/EXT3 prevents
+# the Cygwin "!<symlink>" files from working somehow. You may need to install Cygwin
+# under Windows to get a correct gcc/mingw setup, then copy to your Linux
+# box, then replace all "!<symlink>" files by real symlinks, e.g.
+#
+# cd ~/.wine/drive_c/Programme/cygwin
+# for src in $(grep '!<symlink>' . -rl 2>&-);do
+#  if [ $(stat -c "%s" $src) -lt 100 ];then
+#   dst=$(sed -e's/^\!<symlink>//' $src)
+#   echo "ln -sf $dst $src"
+#  fi
+# done
+#
+# Required software versions:
+# MSVC6 GUI (with MFC!) runs under Wine (copy MFC42.DLL & MSVCP60.DLL)
+# Platform SDK, search for "February 2003 SDK"
+# Cygwin 1.5.x and Wine-1.1.0 or above
+
+PROGDIR = c:/Programme
+PROGCYG = /cygdrive/c/Programme
+PSDKDIR = $(PROGDIR)/Microsoft SDK
+PSDKCYG = $(PROGCYG)/Microsoft\ SDK
+MSVCDIR = $(PROGDIR)/Microsoft Visual Studio
+MSVCCYG = $(PROGCYG)/Microsoft\ Visual\ Studio
+NSISDIR = $(PROGDIR)/NSIS
+NSISCYG = $(PROGCYG)/NSIS
+
+# Necessary for running cygwin under wine. Both the "-C" option and MAKELEVEL>0 will oops...
+MAKE := sh -c 'cmd=$$0;while [ 0 -lt $$\# ];do case $$1 in -C) cmd="cd $$2 && $$cmd";shift 2;; *) cmd="$$cmd \"$$1\"";shift;;esac;done;sh -c "export MAKELEVEL=0 && $$cmd"' $(MAKE)
+
+gui/win32/Shim/Release/shim.obj: gui/win32/Shim/shim.c
+		test -d $(dir $@) || mkdir -p $(dir $@)
+		PATH=$(MSVCCYG)/VC98/Bin:$$PATH && CL.EXE \
+			/I"$(PSDKDIR)/Include" /I"$(MSVCDIR)/VC98/Include" \
+			/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" \
+			/Fp"$(dir $@)/Shim.pch" /YX /Fo"$(dir $@)/" /Fd"$(dir $@)/" /FD /c "$<"
+
+gui/win32/Shim/Release/Shim.exe: gui/win32/Shim/Release/shim.obj
+		PATH=$(MSVCCYG)/VC98/Bin:$$PATH && LINK.EXE \
+			/LIBPATH:"$(PSDKDIR)/Lib" /LIBPATH:"$(MSVCDIR)/VC98/Lib" \
+			kernel32.lib user32.lib \
+			/nologo /subsystem:console /incremental:no /machine:I386 /out:"$@" "$^"
+
+WIN32FILES+=Frontend
+WIN32FILES+=FrontendDlg
+WIN32FILES+=HnaEntry
+WIN32FILES+=MidEntry
+WIN32FILES+=MprEntry
+WIN32FILES+=MyDialog1
+WIN32FILES+=MyDialog2
+WIN32FILES+=MyDialog3
+WIN32FILES+=MyDialog4
+WIN32FILES+=MyEdit
+WIN32FILES+=MyTabCtrl
+WIN32FILES+=NodeEntry
+WIN32FILES+=StdAfx
+WIN32FILES+=TrayIcon
+
+WIN32CPPFILES=$(addprefix gui/win32/Main/, $(addsuffix .cpp,  $(WIN32FILES)))
+WIN32OBJFILES=$(addprefix gui/win32/Main/Release/, $(addsuffix .obj,  $(WIN32FILES)))
+
+gui/win32/Main/Release/Frontend.res: gui/win32/Main/Frontend.rc
+		test -d $(dir $@) || mkdir -p $(dir $@)
+		PATH=$(PSDKCYG)/Bin:$(MSVCCYG)/Common/MSDev98/Bin:$$PATH && RC.EXE \
+			/l 0x407 /i"$(PSDKDIR)/Include" /i"$(MSVCDIR)/VC98/MFC/Include" /fo"$@" /d NDEBUG "$<"
+
+gui/win32/Main/Release/Switch.exe: gui/win32/Main/olsrd_cfgparser.lib gui/win32/Main/Release/Frontend.res $(WIN32CPPFILES)
+		test -d $(dir $@) || mkdir -p $(dir $@)
+		PATH=$(MSVCCYG)/VC98/Bin:$$PATH && CL.EXE \
+			/I"$(PSDKDIR)/Include" /I"$(MSVCDIR)/VC98/Include" /I"$(MSVCDIR)/VC98/MFC/Include" /I"src" \
+			/nologo /MT /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" \
+			/Fp"$(dir $@)/Frontend.pch" /YX"stdafx.h" /Fo"$(dir $@)/" /Fd"$(dir $@)/" /FD /c \
+			$(WIN32CPPFILES)
+		PATH=$(MSVCCYG)/VC98/Bin:$$PATH && LINK.EXE \
+			/LIBPATH:"$(PSDKDIR)/Lib" /LIBPATH:"$(MSVCDIR)/VC98/Lib" /LIBPATH:"$(MSVCDIR)/VC98/MFC/Lib" \
+			ws2_32.lib iphlpapi.lib \
+			gui/win32/Main/olsrd_cfgparser.lib gui/win32/Main/Release/Frontend.res \
+			/nologo /subsystem:windows /incremental:no /machine:I386 /out:"$@" \
+			$(WIN32OBJFILES)
+
+win32setup: gui/win32/Inst/installer.nsi default_target libs gui/win32/Shim/Release/Shim.exe gui/win32/Main/Release/Switch.exe
+		PATH=$(NSISCYG):$$PATH && makensis.exe $<
+
+win32lib: gui/win32/Main/olsrd_cfgparser.lib
+
+gui/win32/Main/olsrd_cfgparser.lib: cfgparser
+		@# Using the cygwin dlltool does not work (missing functions hooks)
+		@# dlltool --input-def src/cfgparser/olsrd_cfgparser.def --dllname src/cfgparser/olsrd_cfgparser.dll --output-lib $@
+		@# Use the Microsoft Lib Tool instead
+		PATH=$(MSVCCYG)/VC98/Bin:$$PATH && LIB.EXE \
+			/machine:i386 /def:src/cfgparser/olsrd_cfgparser.def /out:gui/win32/Main/olsrd_cfgparser.lib
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.wince ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.wince
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/Makefile.wince	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/Makefile.wince	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,27 @@
+#
+# WINDOWS CE SPECIFIC CONFIGURATION
+#
+
+DESTDIR ?=
+LIBDIR =	$(DESTDIR)/usr/lib
+
+SRCS +=		$(wildcard src/win32/*.c)
+HDRS +=		$(wildcard src/win32/*.h)
+
+CPPFLAGS +=	-DWIN32 -DWINCE
+LIBS +=		-lwinsock -liphlpapi
+
+CPPFLAGS += 	-Isrc/win32 -Isrc/win32/ce
+
+ifdef OLSRD_PLUGIN
+CFLAGS +=	
+LDFLAGS +=	-lolsrd
+endif
+
+OS_LIB_PTHREAD =
+OS_CFLAG_PTHREAD =
+OS_LIB_DYNLOAD =
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/makewine.cmd ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/makewine.cmd
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/make/makewine.cmd	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/make/makewine.cmd	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,24 @@
+rem @echo off
+
+REM "make win32setup" does not work under Wine+Cygwin
+REM Compile with this: "wine cmd /c make/makewine.cmd"
+
+SET PRGS=C:\Programme
+SET PSDK=%PRGS%\Microsoft SDK
+SET MSVC=%PRGS%\Microsoft Visual Studio
+SET PATH=%MSVC%\VC98\BIN;%PSDK%\BIN;%PRGS%\NSIS;%PATH%
+SET LIB=%PSDK%\LIB;%MSVC%\VC98\LIB;%MSVC%\VC98\MFC\LIB
+SET INCLUDE=%PSDK%\INCLUDE;%MSVC%\VC98\INCLUDE;%MSVC%\VC98\MFC\INCLUDE
+
+IF NOT EXIST gui\win32\Shim\Release\*.* MKDIR gui\win32\Shim\Release
+
+CL.EXE /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"gui\win32\Shim\Release\Shim.pch" /YX /Fo"gui\win32\Shim\Release\\" /Fd"gui\win32\Shim\Release\\" /FD /c "gui\win32\Shim\shim.c"
+LINK.EXE kernel32.lib user32.lib /nologo /subsystem:console /incremental:no /machine:I386 /out:"gui\win32\Shim\Release\Shim.exe" "gui\win32\Shim\Release\shim.obj"
+
+IF NOT EXIST gui\win32\Main\Release\*.* MKDIR gui\win32\Main\Release
+
+RC.EXE /l 0x407 /fo"gui\win32\Main\Release\Frontend.res" /d NDEBUG "gui\win32\Main\Frontend.rc"
+CL.EXE /I"src" /nologo /MT /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"gui\win32\Main\Release\Frontend.pch" /YX"stdafx.h" /Fo"gui\win32\Main\Release\\" /Fd"gui\win32\Main\Release\\" /FD /c "gui\win32\Main\Frontend.cpp" "gui\win32\Main\FrontendDlg.cpp" "gui\win32\Main\HnaEntry.cpp" "gui\win32\Main\MidEntry.cpp" "gui\win32\Main\MprEntry.cpp" "gui\win32\Main\MyDialog1.cpp" "gui\win32\Main\MyDialog2.cpp" "gui\win32\Main\MyDialog3.cpp" "gui\win32\Main\MyDialog4.cpp" "gui\win32\Main\MyEdit.cpp" "gui\win32\Main\MyTabCtrl.cpp" "gui\win32\Main\NodeEntry.cpp" "gui\win32\Main\StdAfx.cpp" "gui\win32\Main\TrayIcon.cpp"
+LINK.EXE ws2_32.lib iphlpapi.lib gui/win32/Main/olsrd_cfgparser.lib gui/win32/Main/Release/Frontend.res /nologo /subsystem:windows /incremental:no /machine:I386 /out:"gui\win32\Main\Release\Switch.exe" "gui\win32\Main\Release\Frontend.obj" "gui\win32\Main\Release\FrontendDlg.obj" "gui\win32\Main\Release\HnaEntry.obj" "gui\win32\Main\Release\MidEntry.obj" "gui\win32\Main\Release\MprEntry.obj" "gui\win32\Main\Release\MyDialog1.obj" "gui\win32\Main\Release\MyDialog2.obj" "gui\win32\Main\Release\MyDialog3.obj" "gui\win32\Main\Release\MyDialog4.obj" "gui\win32\Main\Release\MyEdit.obj" "gui\win32\Main\Release\MyTabCtrl.obj" "gui\win32\Main\Release\NodeEntry.obj" "gui\win32\Main\Release\StdAfx.obj" "gui\win32\Main\Release\TrayIcon.obj"
+
+MAKENSIS.EXE gui\win32\Inst\installer.nsi
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/Makefile	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,229 @@
+# 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.
+#
+
+# Please also write a new version to:
+# gui/win32/Main/Frontend.rc (line 71, around "CAPTION [...]")
+# gui/win32/Inst/installer.nsi (line 57, around "MessageBox MB_YESNO [...]")
+VERS =		0.5.6-r2
+
+TOPDIR = .
+include Makefile.inc
+
+# pass generated variables to save time
+MAKECMD = $(MAKE) OS="$(OS)" WARNINGS="$(WARNINGS)"
+
+LIBS +=		$(OS_LIB_DYNLOAD)
+
+ifeq ($(OS), win32)
+LDFLAGS +=	-Wl,--out-implib=libolsrd.a
+LDFLAGS +=	-Wl,--export-all-symbols
+endif
+
+SWITCHDIR =	src/olsr_switch
+CFGDIR =	src/cfgparser
+include $(CFGDIR)/local.mk
+TAG_SRCS =	$(SRCS) $(HDRS) $(wildcard $(CFGDIR)/*.[ch] $(SWITCHDIR)/*.[ch])
+
+.PHONY: default_target switch
+default_target: $(EXENAME)
+
+$(EXENAME):	$(OBJS) src/builddata.o
+		$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+cfgparser:	$(CFGDEPS) src/builddata.o
+		$(MAKE) -C $(CFGDIR)
+
+switch:		
+	$(MAKECMD) -C $(SWITCHDIR)
+
+# generate it always
+.PHONY: src/builddata.c
+src/builddata.c:
+	@$(RM) "$@"
+	@echo "#include \"defs.h\"" >> "$@" 
+	@echo "const char olsrd_version[] = \"olsr.org - $(VERS)\";" >> "$@" 
+	@date +"const char build_date[] = \"%Y-%m-%d %H:%M:%S\";" >> "$@" 
+	@echo "const char build_host[] = \"$(shell hostname)\";" >> "$@" 
+
+
+.PHONY: help libs clean_libs libs_clean clean uberclean install_libs libs_install install_bin install_olsrd install build_all install_all clean_all 
+
+clean:
+	-rm -f $(OBJS) $(SRCS:%.c=%.d) $(EXENAME) $(EXENAME).exe src/builddata.c $(TMPFILES)
+ifeq ($(OS), win32)
+	-rm -f libolsrd.a
+	-rm -f gui/win32/Main/olsrd_cfgparser.lib
+	-rm -f olsr-setup.exe
+	-rm -fr gui/win32/Main/Release
+	-rm -fr gui/win32/Shim/Release
+endif
+
+uberclean:	clean clean_libs
+	-rm -f $(TAGFILE)
+#	BSD-xargs has no "--no-run-if-empty" aka "-r"
+	find . \( -name '*.[od]' -o -name '*~' \) -not -path "*/.hg*" -print0 | xargs -0 rm -f
+	$(MAKECMD) -C $(SWITCHDIR) clean
+	$(MAKECMD) -C $(CFGDIR) clean
+
+install: install_olsrd
+
+install_bin:
+		mkdir -p $(SBINDIR)
+		install -m 755 $(EXENAME) $(SBINDIR)
+		$(STRIP) $(SBINDIR)/$(EXENAME)
+
+install_olsrd:	install_bin
+		@echo ========= C O N F I G U R A T I O N - F I L E ============
+		@echo $(EXENAME) uses the configfile $(CFGFILE)
+		@echo a default configfile. A sample RFC-compliance aimed
+		@echo configfile can be found in olsrd.conf.default.rfc.
+		@echo However none of the larger OLSRD using networks use that
+		@echo so install a configfile with activated link quality exstensions
+		@echo per default.
+		@echo can be found at files/olsrd.conf.default.lq
+		@echo ==========================================================
+		mkdir -p $(ETCDIR)
+		-cp -i files/olsrd.conf.default.lq $(CFGFILE)
+		@echo -------------------------------------------
+		@echo Edit $(CFGFILE) before running olsrd!!
+		@echo -------------------------------------------
+		@echo Installing manpages $(EXENAME)\(8\) and $(CFGNAME)\(5\)
+		mkdir -p $(MANDIR)/man8/
+		cp files/olsrd.8.gz $(MANDIR)/man8/$(EXENAME).8.gz
+		mkdir -p $(MANDIR)/man5/
+		cp files/olsrd.conf.5.gz $(MANDIR)/man5/$(CFGNAME).5.gz
+
+tags:
+		$(TAGCMD) -o $(TAGFILE) $(TAG_SRCS)
+
+rpm:
+		@$(RM) olsrd-current.tar.bz2
+		@echo "Creating olsrd-current.tar.bz2 ..."
+		@./list-excludes.sh | tar  --exclude-from=- --exclude="olsrd-current.tar.bz2" -C .. -cjf olsrd-current.tar.bz2 olsrd-current
+		@echo "Building RPMs..."
+		@rpmbuild -ta olsrd-current.tar.bz2
+#
+# PLUGINS
+#
+
+# This is quite ugly but at least it works
+ifeq ($(OS),linux)
+SUBDIRS = $(notdir $(shell find lib -maxdepth 2 -name Makefile -not -path lib/Makefile -printf "%h\n"|sort))
+else
+ifeq ($(OS),win32)
+SUBDIRS := dot_draw httpinfo mini pgraph secure txtinfo
+else
+SUBDIRS := bmf dot_draw dyn_gw dyn_gw_plain httpinfo mini nameservice pgraph secure txtinfo
+endif
+endif
+
+libs:
+		set -e;for dir in $(SUBDIRS);do $(MAKECMD) -C lib/$$dir LIBDIR=$(LIBDIR);done
+
+libs_clean clean_libs:
+		-for dir in $(SUBDIRS);do $(MAKECMD) -C lib/$$dir LIBDIR=$(LIBDIR) clean;done
+ifeq ($(OS), win32)
+		-rm -f lib/pgraph/olsrd_pgraph.dll
+		-rm -f lib/txtinfo/olsrd_txtinfo.dll
+		-rm -f lib/httpinfo/olsrd_httpinfo.dll
+		-rm -f lib/secure/olsrd_secure.dll
+		-rm -f lib/dot_draw/olsrd_dot_draw.dll
+		-rm -f lib/mini/olsrd_mini.dll
+endif
+
+libs_install install_libs:
+		set -e;for dir in $(SUBDIRS);do $(MAKECMD) -C lib/$$dir LIBDIR=$(LIBDIR) install;done
+
+httpinfo:
+		$(MAKECMD) -C lib/httpinfo clean
+		$(MAKECMD) -C lib/httpinfo 
+		$(MAKECMD) -C lib/httpinfo DESTDIR=$(DESTDIR) install 
+
+tas:
+		$(MAKECMD) -C lib/tas clean
+		$(MAKECMD) -C lib/tas
+		$(MAKECMD) -C lib/tas DESTDIR=$(DESTDIR) install
+
+dot_draw:
+		$(MAKECMD) -C lib/dot_draw clean
+		$(MAKECMD) -C lib/dot_draw
+		$(MAKECMD) -C lib/dot_draw DESTDIR=$(DESTDIR) install
+
+nameservice:
+		$(MAKECMD) -C lib/nameservice clean
+		$(MAKECMD) -C lib/nameservice
+		$(MAKECMD) -C lib/nameservice DESTDIR=$(DESTDIR) install
+
+dyn_gw:
+		$(MAKECMD) -C lib/dyn_gw clean
+		$(MAKECMD) -C lib/dyn_gw
+		$(MAKECMD) -C lib/dyn_gw DESTDIR=$(DESTDIR) install
+
+dyn_gw_plain:
+		$(MAKECMD) -C lib/dyn_gw_plain clean
+		$(MAKECMD) -C lib/dyn_gw_plain
+		$(MAKECMD) -C lib/dyn_gw_plain DESTDIR=$(DESTDIR) install
+
+secure:
+		$(MAKECMD) -C lib/secure clean
+		$(MAKECMD) -C lib/secure
+		$(MAKECMD) -C lib/secure DESTDIR=$(DESTDIR) install
+
+pgraph:
+		$(MAKECMD) -C lib/pgraph clean
+		$(MAKECMD) -C lib/pgraph 
+		$(MAKECMD) -C lib/pgraph DESTDIR=$(DESTDIR) install 
+
+bmf:
+		$(MAKECMD) -C lib/bmf clean
+		$(MAKECMD) -C lib/bmf 
+		$(MAKECMD) -C lib/bmf DESTDIR=$(DESTDIR) install 
+
+quagga:
+		$(MAKECMD) -C lib/quagga clean
+		$(MAKECMD) -C lib/quagga 
+		$(MAKECMD) -C lib/quagga DESTDIR=$(DESTDIR) install 
+
+txtinfo:
+		$(MAKECMD) -C lib/txtinfo clean
+		$(MAKECMD) -C lib/txtinfo 
+		$(MAKECMD) -C lib/txtinfo DESTDIR=$(DESTDIR) install 
+
+build_all:	all switch libs
+install_all:	install install_libs
+clean_all:	uberclean clean_libs
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/Makefile.inc ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/Makefile.inc
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/Makefile.inc	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/Makefile.inc	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,240 @@
+######################
+#
+# Highlevel configuration options for all
+#
+#
+
+# activate debugging with 1 or deactivate with 0
+DEBUG ?= 0
+
+# compile OLSR_PRINTF out
+NO_DEBUG_MESSAGES ?= 0
+
+# the optimize option to be set for gcc
+OPTIMIZE ?= 
+
+# enable mudflap with 1 or deactivate with 0
+# you need a recent enough gcc and the libmudflap installed
+MUDFLAP ?= 0
+
+
+######################
+#
+# Lowlevel options and rules
+#
+
+# programs
+CCACHE ?=       $(shell IFS=:; for i in $$PATH;do test -x "$$i/ccache" && echo "$$i/ccache" && break; done)
+ifeq ($(origin CC),default)
+CC = 		$(CCACHE) gcc
+else
+CC ?= 		$(CCACHE) gcc
+endif
+ifeq ($(DEBUG),0)
+STRIP ?=	strip
+else
+STRIP ?=	:
+endif
+BISON ?=	bison
+FLEX ?=		flex
+TAGCMD ?=	etags
+
+# target directories and names
+DESTDIR ?=
+SBINDIR ?= $(DESTDIR)/usr/sbin
+ETCDIR  ?= $(DESTDIR)/etc
+LIBDIR  ?= $(DESTDIR)/usr/lib
+DOCDIR  ?= $(DESTDIR)/usr/share/doc
+MANDIR  ?= $(DESTDIR)/usr/share/man
+EXENAME ?= olsrd
+CFGNAME ?= $(EXENAME).conf
+CFGFILE ?= $(ETCDIR)/$(CFGNAME)
+
+CPPFLAGS =	-Isrc
+ifneq ($(TOPDIR),.)
+CPPFLAGS +=	-I$(TOPDIR)/src
+endif
+
+# add gcc warnings and optimizations if CFLAGS not set
+ifndef CFLAGS
+ifndef WARNINGS
+WARNINGS +=	-Wall
+WARNINGS +=	-Wextra
+WARNINGS +=	-Wold-style-definition
+WARNINGS +=	-Wdeclaration-after-statement
+WARNINGS +=	-Wmissing-prototypes
+WARNINGS +=	-Wstrict-prototypes
+WARNINGS +=	-Wmissing-declarations
+WARNINGS +=	-Wsign-compare
+WARNINGS +=	-Waggregate-return
+WARNINGS +=	-Wmissing-noreturn
+WARNINGS +=	-Wmissing-format-attribute
+WARNINGS +=	-Wno-multichar
+WARNINGS +=	-Wno-deprecated-declarations
+WARNINGS +=	-Wendif-labels
+WARNINGS +=	-Wwrite-strings
+WARNINGS +=	-Wbad-function-cast
+WARNINGS +=	-Wpointer-arith
+WARNINGS +=	-Wcast-qual
+# the following 5 do not work yet and need more work on it
+#WARNINGS +=	-Wshadow
+#WARNINGS +=	-Wpointer-arith
+#WARNINGS +=	-Wcast-align
+#WARNINGS +=	-Wconversion
+#WARNINGS +=	-Wredundant-decls
+ifeq ($(MUDFLAP),0)
+# work around a bug in gcc-4.*
+WARNINGS +=	-Wnested-externs
+endif
+# Alas, htons() triggers this so we can't seriously activate it.
+#WARNINGS +=	-Wunreachable-code
+WARNINGS +=	-Winline
+WARNINGS +=	-Wdisabled-optimization
+#WARNINGS +=	-Werror
+WARNINGS +=	-finline-functions-called-once
+WARNINGS +=	-fearly-inlining
+ifeq ($(DEBUG),0)
+WARNINGS +=	-fomit-frame-pointer
+endif
+# we have small inline functions in src/lq_route.h which should always be inlined
+WARNINGS +=	-finline-limit=350
+# These tell gcc to put each function and global variable in a separate section.
+# The linker can than remove all unreferenced section. But in the olsrd binary
+# unused doesn't imply unused at all since the function may be used by plugins,
+# e.g. the ones in src/plugin_utils.c.
+# So we can use that featuer at most to identify unused functions and remove them
+# from the source by hand.
+#WARNINGS +=	-ffunction-sections
+#WARNINGS +=	-fdata-sections
+WARNINGS :=	$(shell CC="$(CC)" $(TOPDIR)/gcc-warnings $(WARNINGS))
+endif
+CFLAGS +=	$(WARNINGS)
+CFLAGS +=	$(OPTIMIZE)
+CFLAGS +=	$(EXTRA_CFLAGS)
+
+# Must be specified along with -lpthread on linux
+CPPFLAGS +=	$(OS_CFLAG_PTHREAD)
+endif
+ifneq ($(MUDFLAP),0)
+CFLAGS +=	-fmudflapth
+endif
+
+ifdef OLSRD_PLUGIN
+# c and ld flags for libraries (plugins)
+CPPFLAGS +=	-DOLSR_PLUGIN
+LDFLAGS +=	-shared
+LDFLAGS +=	-Wl,-soname,$(PLUGIN_NAME)
+LDFLAGS +=	-Wl,--version-script=version-script.txt 
+else
+# c and ld flags for main
+LDFLAGS +=	-Wl,-export-dynamic 
+LDFLAGS +=	-Wl,-rpath,$(LIBDIR)
+endif
+# LDFLAGS for all 
+LDFLAGS +=	-Wl,--warn-common
+# See above at "-ffunction-sections" for an explanation (and why it is disabled).
+#LDOPTS +=	-Wl,--gc-sections
+#LDOPTS +=	-Wl,--print-gc-sections
+#LDFLAGS +=	$(shell CC="$(CC)" $(TOPDIR)/ld-warnings $(LDOPTS))
+ifneq ($(MUDFLAP),0)
+LIBS +=		-lmudflapth
+endif
+LIBS +=		$(OS_LIB_PTHREAD)
+
+# extra options from the outside
+CPPFLAGS +=	$(EXTRA_CPPFLAGS)
+
+###################################
+#
+# options to save space on small systems
+
+# we have plugins with the old interface
+#CPPFLAGS +=	-DSUPPORT_OLD_PLUGIN_VERSIONS=1
+
+# use the new fixed point math stuff
+CPPFLAGS +=     -DUSE_FPM
+
+# search sources and headers in current dir and in src/
+SRCS +=		$(wildcard src/common/*.c src/*.c *.c)
+HDRS +=		$(wildcard src/common/*.h src/*.h *.h)
+
+# OS detection
+ifeq ($(OS),Windows_NT)
+OS := win32
+endif
+ifeq ($(OS),)
+OS := $(shell sh $(TOPDIR)/make/guess_os.sh)
+endif
+ifeq ($(OS),UNKNOWN)
+all: help
+else
+# include OS specifics
+all: default_target
+include $(TOPDIR)/make/Makefile.$(OS)
+endif
+
+# one object for each source file
+OBJS +=		$(SRCS:%.c=%.o)
+
+# debugging or non-debugging flags
+ifeq ($(DEBUG),1)
+CPPFLAGS +=	-DDEBUG
+CFLAGS +=	-ggdb
+else
+CPPFLAGS +=	-DNDEBUG
+endif
+ifeq ($(NO_DEBUG_MESSAGES),1)
+CPPFLAGS +=	-DNODEBUG
+endif
+
+# a make function to quote "/" and "."
+quote = $(subst .,\.,$(subst /,\/,$1))
+
+# fully automatic and working dependency generation
+%.d: %.c
+	@$(filter-out $(CCACHE),$(CC)) -M $(strip $(CPPFLAGS)) "$<" | sed -e '1s/\($(call quote,$(*F))\.o\)[ :]*/$(call quote,$(*D)/\1 $@: Makefile $(TOPDIR)$(if $(TOPDIR),/)Makefile.inc) /g' >"$@"
+
+# we always need the includes and defines
+# for legacy since now
+CPPFLAGS += $(INCLUDES) $(DEFINES)
+ifneq ($(INCLUDES),)
+$(warning Use CPPFLAGS instead of INCLUDES for -I)
+endif
+ifneq ($(DEFINES),)
+$(warning Use CPPFLAGS instead of DEFINES for -D)
+endif
+
+TAGFILE ?=	src/TAGS
+
+help:
+	@echo 
+	@echo '***** olsr.org olsr daemon Make ****'
+	@echo ' Automatic detection of your OS     '
+	@echo ' failed!                            '
+	@echo ' You can provide a valid target OS  '
+	@echo ' by setting the OS variable! Valid  '
+	@echo ' target OSes are:                   '
+	@echo ' ---------------------------------  '
+	@echo ' linux - GNU/Linux                  '
+	@echo ' win32 - MS Windows                 '
+	@echo ' fbsd  - FreeBSD                    '
+	@echo ' nbsd  - NetBSD                     '
+	@echo ' obsd  - OpenBSD                    '
+	@echo ' osx   - Mac OS X                   '
+	@echo ' ---------------------------------  '
+	@echo ' Example - build for windows:       '
+	@echo ' make OS=win32                      '
+	@echo ' If you are developing olsrd code,  '
+	@echo ' exporting the OS variable might    '
+	@echo ' be a good idea :-) Have fun!       '
+	@echo '************************************'
+	@echo
+
+ifeq ($(filter clean% %clean, $(MAKECMDGOALS)),)
+# include dependencies - we don't need any dependency for a everytime generated files
+-include $(filter-out src/builddata.%,$(SRCS:%.c=%.d))
+endif
+
+# Local Variables:
+# mode: makefile
+# End:
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,474 @@
+
++====================================================================+
+| README - olsr.org OLSR daemon 0.5.4, 21.10.2007                    |
++====================================================================+
+
+Authors:
+Andreas Tonnesen(andreto@olsr.org)
+Thomas Lopatic  (thomas@lopatic.de)
+Aaron Kaplan (aaron@lo-res.org)
+
+
+http://www.olsr.org
+
+
+CONTENTS:
+
+I.   - GENERAL INFORMATION
+     * ABOUT
+     * GETTING HOLD OF OLSRD
+     * RELEASE NOTES
+     * RFC COMPLIANCE
+     * PLUGINS
+     * LINK QUALITY ROUTING
+     * KNOWN PROBLEMS
+     * FUTURE WORK
+
+II.  - BUILDING AND RUNNING OLSRD
+     * GENERAL INFORMATION
+     * PLUGINS
+     * GUI FRONTENDS
+
+     * LINUX
+     * WINDOWS
+     * FREEBSD
+     * OSX
+  
+
+
+----------------------------------------------------------------------
+ I.   - GENERAL INFORMATION
+----------------------------------------------------------------------
+
+=========
+ * ABOUT
+=========
+
+The olsr.org OLSR daemon is an implementation of the Optimized Link State
+routing protocol. The protocol is documented in RFC3626. The website
+of olsrd is http://www.olsr.org
+
+Olsrd is designed to be a modular an extensible implementation. It features
+a plugin interface, allowing for developers to extend OLSR operation without
+interfering with the core code. It also features a experimental link quality
+routing scheme.
+
+To ask questions or make comments, join up with the mailing lists:
+olsr-dev@olsr.org   - development discussion
+olsr-users@olsr.org - usage discussion
+
+A bug tracker is also available at the sourceforge project site
+http://sourceforge.net/projects/olsrd/
+
+Olsrd source or binaries can be downloaded from olsr.org. CVS is available
+for the cutting edge features ;-)
+
+The current Olsrd work is done via http://olsr.funkfeuer.at/ in the OLSR-NG
+project.
+
+
+=================
+ * RELEASE NOTES
+=================
+
+
+
+==================
+ * RFC COMPLIANCE
+==================
+
+If olsrd is ran without using link-quality routing/MPR selection it is RFC3626
+compliant in that it will inter-operate with other RFC3626 implementations.
+Internally there are a few things that are solved differently that proposed 
+in the RFC. Check out the "Conclusions" section of the "Implementing And
+Extending The Optimized Link State routing Protocol" thesis available at
+olsr.org.
+
+
+===========
+ * PLUGINS
+===========
+
+Olsrd supports dynamic loading of plugins (dynamically loaded libraries) for 
+functions like generation and processing of private package types, setting
+olsrd configurations in run-time and much more. This design is chosen for
+amongst others, the following reasons:
+
+ * No need to change any code in the olsr daemon to add custom packages or 
+   functionality.
+ * Users are free to implement olsrd plugins and license them under whatever 
+   terms they like.
+ * The plugins can be written in any language that can be compiled as 
+   a dynamic library. Linux even allows scripts!
+ * No need for people with extended OLSR versions to rely on heavy patching 
+   to maintain functionality when new olsrd versions are released.
+
+OLSR provides a default forwarding algorithm that allows for forwarding of OLSR 
+messages of unknown types. This is really neat - because it means that even if 
+only a subset of the nodes in the network actually known how to interpret 
+a certain message type - all nodes will forward them according to the MPR 
+pragma. A user may want to use the optimized flooding technique in OLSR to 
+broadcast certain information, routing related or not, to all nodes that knows 
+how to handle this message. Services that needs to broadcast/multicast data can 
+encapsulate data in a private OLSR message type using a olsrd plugin. 
+
+The design of the various entities of OLSR allows one to easily add special 
+functionality into most aspects of OLSR. One can both register functions and 
+unregister them with the socket parser, packet parser, scheduler and HNA set etc. 
+This opens up for possibilities like intercepting current operation and replacing 
+it with custom actions.
+
+  Plugins that are part of this release(can be found in the lib/ directory):
+
+  - Tiny Application Server (TAS).
+
+  - HttpInfo. This plugin implements a simple HTTP server that serves dynamic
+    pages with lots of information about the running olsrd process.
+
+  - TxtInfo. This delivers output similar to the above. However, it is intended
+    for external tools to use the output.
+
+  - Mini.
+
+  - Nameservice.
+
+  - Dynamic Internet gateway. A plugin that dynamically adds and removes Internet
+    HNA transmissions based on if there exists a default gateway to Internet
+    with hop count = 0(non OLSR gateway). It has been extended to be able to
+    ping Internet nodes to check for connectivity as well.
+
+  - Dot draw. A plugin that produces output in the dot format representing
+    the network topology.
+
+  - Secure OLSR plugin. This plugin adds a signature to all messages
+    to ensure data integrity. This way only nodes with access to the
+    shared key can participate in the routing.
+    You need to have the OpenSSL libs installed to use this plugin.
+
+
+
+========================
+ * LINK QUALITY ROUTING
+========================
+
+Release 0.4.8 is the first version of olsrd that implements the ETX
+link quality metric. This enables olsrd to prefer routes that have a
+superior overall quality to routes that are worse but consist of less
+hops. Have a look at the README-Link-Quality.html file for details.
+
+==================
+ * KNOWN PROBLEMS
+==================
+
+There is no synchronization concept (and thus - and for Gods sake -  no
+code). Some plugins use threads for concurrency so this should be solved.
+ATM the bmf plugin is the only one using threads.
+
+===============
+ * FUTURE WORK
+===============
+
+Future work concentrates on reduction of ressource (ab)use and to make
+it more scalable. Of course additional useful plugins are always
+appreciated.
+
+The current track of development is documented in the OLSR-NG 
+project: http://olsr.funkfeuer.at
+
+
+----------------------------------------------------------------------
+ II.  - BUILDING AND RUNNING OLSRD
+----------------------------------------------------------------------
+
+=======================
+ * GENERAL INFORMATION
+=======================
+
+Olsrd is implemented in pure C with very few dependencies. Olsrd is 
+known to run on various hardware like:
+ * x86    - your regular PC
+ * PPC    - Macintosh hardware
+ * MIPSEL - Embedded systems like the LinkSys WRT54g
+ * ARM    - Embedded systems like Compaq/HP iPaq
+A binary tarball featuring x86, MIPSEL and ARM binaries is available
+for download at olsr.org
+
+Ports exist for all major operating systems:
+- Linux
+- Mac OS X
+- NetBSD/OpenBSD/FreeBSD: ATM the main development occurs on Linux with
+         GNU tools so occasionally it needs some minor tweaks to compile
+         it on *BSD. Please send patches if you fix problems there.
+- Win32: You need (the relevant parts of) cygwin to compile the daemon
+         as such. The installer and GUI needs VisualC++ though.
+         Win32 is the least supported port. Feel free to send patches!
+
+Packages for the operating systems and various distributions are available
+at olsr.org. Feel free to package it and announce it on the mailing lists.
+
+
+===========
+ * PLUGINS
+===========
+
+All the available plugins are also implemented in C and requires gcc/libc
+to build. the dot_draw plugin compiles for Windows and GNU/Linux. the rest
+of the plugins will only compile for GNU/Linux.
+Building the plugins are just a matter of executing:
+make
+while installing requires(as root):
+make install
+in the plugins top directory (i.e. "lib/$plugin/").
+To use the plugins add them to the olsrd configuration file.
+
+=====================
+ * OS SUPPORT STATUS
+=====================
+
+COMPONENT/OS	Linux	Win32	FreeBSD	NetBSD	OpenBSD	OSX
+------------------------------------------------------------
+olsrd		+/+	+/+	+/+	+/+	+/+	?
+olsr_switch	+/+	+/+	+/+	+/+	+/+	?
+------------------------------------------------------------
+PLUGINS
+bmf		+/+	+/?	+/+	+/+	+/+	-
+dot_draw	+/+	+/?	+/+	+/+	+/+	+/+
+dyn_gw		+/+	+/?	+/-	+/-	+/-	+/+
+dyn_gw_plain	+/+	+/?	+/-	+/-	+/-	+/+
+httpinfo	+/+	+/+	+/+	+/+	+/+	+/+
+mini		+/+	+/?	+/+	+/+	+/+	+/+
+nameservice	+/+	+/?	+/+	+/+	+/+	+/+
+pgraph		+/+	+/+	+/+	+/+	+/+	+/+
+quagga		+/+	-/-	+/+	+/+	+/+	?
+secure		+/+	+/+	+/+	+/+	+/+	+/+
+tas		+/+	-	-	-	-	?
+txtinfo		+/+	+/+	+/+	+/+	+/+	+/+
+------------------------------------------------------------
+
+LEGEND:   +/+ = compiles/runs
+          +/- = compiles/does not work
+          -   = does not compile
+          ?   = unknown
+
+=================
+ * GUI FRONTENDS
+=================
+
+A GUI front end for GNU/Linux using GTK is available in the gui/ 
+directory. This implementation is no longer supported, and might
+not work any more. It will be completly removed in a future release.
+
+There currently is, however, a native MFC-based Windows GUI. Unlike
+olsrd the GUI has to be compiled with Visual C++ 6. It can be found in
+the gui/win32/ directory. Simply open the "Frontend.dsw" workspace in
+the Visual C++ 6 IDE. Then compile "Frontend" and "Shim", which
+creates "Switch.exe" and "Shim.exe".
+
+To run the Windows GUI simply make sure that "Switch.exe", "Shim.exe",
+"olsrd.exe", "olsrd_cfgparser.dll", and "Default.olsr" are located in
+the same directory and run "Switch.exe". "Shim.exe" is just an
+auxiliary console application that is required by "Switch.exe".
+
+The GUI is pretty self-explanatory. The three buttons on the lower
+right of the GUI window start the OLSR server, stop the OLSR server,
+and exit the GUI.
+
+Use the "Settings" tab to specify the options that the GUI uses to run
+the OLSR server "olsrd.exe". When you click "Start" the GUI generates
+a temporary configuration file from the information given by the
+"Settings" tab. This temporary configuration file is passed to the
+OLSR server via its "-f" option.
+
+"Offer Internet connection" is only available if you have an Internet
+connection, i.e. if you have a default route configured. If you tick
+this option an HNA entry for the default route is added to the
+temporary configuration file, allowing other nodes in the OLSR network
+to use your Internet connection.
+
+IP version 6 cannot currently be selected, as support for IPv6 is not
+yet complete in the Windows version.
+
+"Enable ETX link quality" tells the OLSR server to detect the quality
+of its links to its neighbors using a variant of the ETX
+metric. "Window size" specifies the number of most recent packets to
+be used when calculating the packet loss. If, for example, this
+parameter is set to 10, then the OLSR server will calculate the packet
+loss among the most recent 10 OLSR packets received from each
+neighbor. If "For MPR selection only" is active, the link quality
+information is only used to select MPRs that offer the best paths to
+your two-hop neighbors. If "For MPR selection and routing" is active,
+the link quality is additionally used to create the routing table.
+
+WARNING - Enabling ETX breaks compliance with the OLSR
+standard. ETX-enabled nodes do not inter-operate with nodes that have
+ETX switched off. DO NOT USE NODES WITH DIFFERENT ETX SETTINGS IN A
+SINGLE NETWORK!
+
+The three buttons on the lower right of the "Settings" tab open
+previously saved settings, save the current settings to a
+configuration file, and reset the current settings to default values.
+
+If you start the GUI with the path to a configuration file as the only
+command line argument, the GUI opens the given configuration file and
+runs the OLSR server with this configuration. So, saving a
+configuration file with a ".olsr" extension, for example, and making
+"Switch.exe" the handler for ".olsr" files enables you to run the OLSR
+server with a simple double click on the configuration file.
+
+The "Output" tab shows the output of the currently running OLSR
+server. The output is limited to 1000 lines. The 1001st line will make
+the first line disappear and so on. When you click "Start" The GUI
+simply invokes the OLSR server "olsrd.exe" and intercepts its console
+output. Use the four buttons on the upper right of the tab to freeze
+the output, resume frozen output, save the output to a file, or clear
+the output.
+
+The "Nodes" tab contains information about the nodes that the OLSR
+server currently knows about. If you click on the address of a node in
+the "Node list" list box, the GUI populates the three "Node
+information" list boxes on the right with the multi-point relays of
+the selected node (MPR), the interfaces of the selected node (MID),
+and the non-OLSR networks accessible via the selected node (HNA).
+
+The "Routes" tab shows the routes that the currently running OLSR
+server has added.
+
+The default settings for the "Settings" tab are taken from the
+"Default.olsr" file. The configuration of the last interface in this
+file is used to populate the per-interface settings (HELLO interval,
+etc.) in the "Settings" tab. If you do not want to specify any
+interface in "Default.olsr", the problem arises that you do not have
+such a last interface. In this case simply create an interface with
+the special name of "GUI". This tells the GUI to use the configuration
+of the interface for the per-interface settings and to forget about
+this interface afterward. See the comments in the "Default.olsr" file
+for details.
+
+
+=========
+ * LINUX
+=========
+
+To build olsrd you need to have all the regular development tools 
+installed. This includes gcc, make, glibc, makedep etc.
+To install to a directory different from /(/etc, /usr/bin) use 
+DESTDIR=targetdir. To use other compilers set CC=yourcompiler.
+
+To build:
+ make
+To install(as root):
+ make install
+To delete object files run:
+ make clean
+Optionally, to clean all generated files:
+ make uberclean
+
+Before running olsrd you must edit the default configuration file 
+/etc/olsrd.conf adding at least what interfaces olsrd is to run on. 
+Options in the config file can also be overridden by command line 
+options. See the manual pages olsrd(8) and olsrd.conf(5) for details.
+The binary is named 'olsrd' and is installed in (PREFIX)/usr/sbin. 
+You must have root privileges to run olsrd!
+To run olsrd just type:
+olsrd
+
+If debug level is set to 0 olsrd will detach and run in the background, 
+if not it will keep running in your shell.
+
+===========
+ * WINDOWS
+===========
+
+*** COMPILING
+
+To compile the Windows version of the OLSR server or the dot_draw
+plugin you need a Cygwin installation with a current version of GCC
+and Mingw32. Simply use
+
+  make
+
+to build the olsrd executable. Building the dot_draw plugin works
+slightly different, we do not yet have a unified makefile for all
+architectures here. Switch to the dot_draw directory lib/dot_draw/ and
+generate the Windows makefile by saying
+
+  ./mkmf.sh
+
+This will generate "Makefile.win32" by adding dependencies to
+"Makefile.win32.in". Then just say
+
+  make -f Makefile.win32
+
+to build the dot_draw plugin. However, make sure that you have build
+olsrd before that, as the dot_draw plugin requires some object files
+that are only generated when olsrd is built.
+
+*** INTERFACE NAMING
+
+On Linux network interfaces have nice names like "eth0". In contrast,
+Windows internally identifies network interfaces by pretty awkward
+names, for example:
+
+  "{EECD2AB6-C2FC-4826-B92E-CAA53B29D67C}"
+
+Hence, the Windows version implements its own naming scheme that maps
+each internal name to a made-up name like "if03", which is easier to
+memorize. Simply invoke the OLSR server as follows to obtain its view
+of your interfaces:
+
+  olsrd.exe -int
+
+This lists the made-up interface names along with their current IP
+addresses to enable you to find out which made-up interface name
+corresponds to which of your physical interfaces.
+
+"+" in front of the IP addresses means that the OLSR server has
+identified the interface as a WLAN interface. "-" indicates that the
+OLSR server considers this interface to be a wired interface. "?"
+means "no idea". Detection currently only works on NT, 2000, and
+XP. Windows 9x and ME will always display "?".
+
+For techies: The made-up names consist of the string "if" followed by
+a two-digit hex representation of the least significant byte of the
+Windows-internal interface index, which should be different for each
+interface and thus make each made-up name unique. Again, this is
+undocumented and this assumption may be wrong in certain cases. So, if
+the "-int" option reports two interfaces that have the same name,
+please do let me know.
+
+*** CONFIGURATION FILE
+
+If you do not specify a configuration file, the OLSR server
+("olsrd.exe") by default attempts to use "olsrd.conf" in your Windows
+directory, e.g. "C:\WINDOWS\olsrd.conf".
+
+
+=========================
+ * FREEBSD/NETBSD/OPENBSD
+=========================
+
+The FreeBSD port should be relativley stable at this point.
+The OpenBSD and NetBSD versions are pretty much untested. They have 
+not been extensively tested beyond "doesn't core dump and it looks 
+like it adds routes". In order to build it, you need GNU make. Then 
+use:
+
+  gmake
+
+to build the olsrd executable. Then do:
+
+  gmake install
+
+to install the executable, the default configuration file, and the
+manual pages. So, basically it's the same as on Linux. Have a look at
+the Linux section for details.
+
+=======
+ * OSX
+=======
+
+The OS X port is a direct descendant of the FreeBSD port. So, the same
+limitations with respect to testing and maturity apply. Building and
+installing works in the same was as on FreeBSD.
+
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-FreeBSD-libnet ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-FreeBSD-libnet
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-FreeBSD-libnet	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-FreeBSD-libnet	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,35 @@
+Instructions for FreeBSD libnet build
+spoggle@gmail.com
+
+libnet URL: http://www.packetfactory.net/libnet/
+FreeBSD Ports: /usr/ports/net/libnet-devel/
+
+
+The BSD networking is missing features that prevent the use of
+multiple interfaces with olsrd.  By using libnet we can get around
+the problem and support this feature.
+
+1) From the FreeBSD ports collection install libnet-devel, plain
+   libnet is NOT sufficient!
+
+  % cd /usr/ports/net/libnet-devel
+  % make install
+
+   Additionally, you must have gmake installed (/usr/ports/devel/gmake)
+
+2) If you're reading this, you have the proper olsrd distribution.  So
+   I won't bore you with getting that.
+
+3) Change into the main directory of the olsrd source and build the
+   daemon:
+
+  % cd <blah>
+  % gmake OS=fbsd-ll
+
+4) If that succeeds, then just follow all the other documentation on
+   the use of olsrd.
+
+The code is pretty ugly right now and I know there are some efficiency
+things I can do to make it better.  Bug reports, better ways to do
+this are welcomed.
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-Link-Quality-Fish-Eye.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-Link-Quality-Fish-Eye.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-Link-Quality-Fish-Eye.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-Link-Quality-Fish-Eye.txt	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,163 @@
++=====================================================================+
+|        Link Quality Fish Eye Mechanism   December 3th 2005          |
+|								      |	
+|	     	 	    olsrd-0.4.10			      |
++=====================================================================+
+
+	Corinna 'Elektra' Aichele   (onelektra at gmx.net)
+
+---------------
+I. Introduction
+---------------
+
+Link Quality Fish Eye is a new (experimental) algorithm introduced in
+olsrd 0.4.10. To increase stability in a mesh, TC messages should be
+sent quite frequently. However, the network would then suffer from the
+resulting overhead. The idea is to frequently send TC messages to
+adjacent nodes, i.e. nodes that are likely to be involved in routing
+loops, without flooding the whole mesh with each sent TC message.
+
+OLSR packets carry a Time To Live (TTL) that specifies the maximal
+number of hops that the packets is allowed to travel in the mesh. The
+Link Quality Fish Eye mechanism generates TC messages not only with
+the default TTL of 255, but with different TTLs, namely 1, 2, 3, and
+255, restricting the distribution of TC messages to nodes 1, 2, 3, and
+255 hops away. A TC message with a TTL of 1 will just travel to all
+one-hop neighbours, a message with a TTL of 2 will in addition reach
+all two-hop neighbours, etc.
+
+TC messages with small TTLs are sent more frequently than TC messages
+with higher TTLs, such that immediate neighbours are more up to date
+with respect to our links than the rest of the mesh. We hope that this
+reduces the likelihood of routing loops.
+
+--------------
+II. How to use
+--------------
+
+The Fish Eye algorithm can be enabled in the configuration file
+/etc/olsrd.conf with the following lines:
+
+	# Fish Eye mechanism for TC messages 0 = off, 1 = on
+
+	LinkQualityFishEye 1
+
+Fish Eye should be used together with a small TcInterval setting as
+follows:
+
+	# TC interval in seconds (float)
+
+        TcInterval 0.5
+
+If olsrd is started with debug-level 3 it will print out a message
+every time a TC message is issued or dropped.
+
+The following sequence of TTL values is used by olsrd.
+
+        255 3 2 1 2 1 1 3 2 1 2 1 1
+
+Hence, a TC interval of 0.5 seconds leads to the following TC
+broadcast scheme.
+
+  * Out of 13 TC messages, all 13 are seen by one-hop neighbours (TTL
+    1, 2, 3, or 255), i.e. a one-hop neighbour sees a TC message every
+    0.5 seconds.
+
+  * Two-hop neighbours (TTL 2, 3, or 255) see 7 out of 13 TC messages,
+    i.e. about one message per 0.9 seconds.
+
+  * Three-hop neighbours (TTL 3 or 255) see 3 out of 13 TC messages,
+    i.e. about one message per 2.2 seconds.
+
+  * All other nodes in the mesh (TTL 255) see 1 out of 13 TC messages,
+    i.e. one message per 6.5 seconds.
+
+The sequence of TTL values is hardcoded in lq_packet.c and can be
+altered easily for further experiments.
+
+The Link Quality Fish Eye algorithm is compatible with earlier
+versions of olsrd or nodes that do not have the Fish Eye feature
+enabled.
+
+A default configuration file with the Link Quality Fish Eye mechanism
+and ETX enabled is located in ./files/olsrd.conf.default.lq-fisheye
+
+---------------
+III. Background
+---------------
+
+A major problem of a proactive routing algorithm is keeping topology
+control information in sync. If topology information is not in sync
+routing loops may occur. Usually routing loops happen in a local area
+in the mesh - within a few hops.
+
+It may happen that node A assumes that the best way to send packets to
+node C is by forwarding them to node B, while node B thinks that the
+best route to C is via node A. So A sends the packet to node B, and B
+returns it to A - we have a loop. This can of course also happen with
+more than two nodes involved in the loop, but it is unlikely that a
+routing loop involves more than a few nodes.
+
+Routing information like all data traffic gets lost on radio links
+with weak signal-to-noise ratio (SNR) or if collisions occur. Setting
+fragmentation and RTS (request-to-send) to conservative values on
+wireless interfaces is a must in a mesh to deal with hidden nodes,
+interference and collisions. A mesh that utilizes only one channel has
+to deal with many collisions between packets and a lot of
+self-generated interference. While a radio interface may have a range
+of only 300 meters its signals can disturb receivers that are more
+than 1000 meters away. The data traffic of a node in the distance is
+not readable, but it's signals add to the noise floor in receivers,
+reducing signal-to-noise ratio of local links.
+
+When a route is saturated with traffic the transmitters involved
+introduce permanent interference into the mesh, causing packet loss on
+other links in the neighbourhood. OLSR messages get lost, causing
+confusion. While the timeout values of MID messages or HNA messages
+can be increased to increase stability without a big tradeoff, TC
+messages that are up to date and arrive in time are critical. It is
+also critical to have MPR information in sync if the MPR algorithm is
+used, but in the author's opinion this optimization doesn't do any
+good anyway. The MPR algorithm introduces a new source of failure and
+reduces TC message redundancy, so it should be switched off in the
+configuration file /etc/olsrd.conf with these lines:
+
+        TcRedundancy 2
+        MprCoverage  7
+
+olsrd with LQ Extension attempts to know the best routes all over the
+whole mesh cloud, but it is likely that it never will be able to
+achieve this in a mesh that has more than a handful of nodes. TC
+information is likely to be lost on its way through the whole
+mesh. And this likelyhood increases with the number of hops.
+
+But this fact doesn't necessarily harm the routing of traffic on a
+long multihop path. A node at one end of a mesh cloud may have the
+illusion to know the exact and best path along which its packets
+travel when communicating with a node that is several hops away. But
+this information may be pretty outdated and incomplete.
+
+In fact all that the algorithm has to achieve is a reasonable choice
+for the next two or three hops. If the routing path is 8 hops, for
+example, nodes that are 5 hops away from the node initiating traffic
+and closer to the destination have better and more accurate
+information about the best path. They don't know what a node that
+initiates traffic thinks about the path that its packets should take,
+they have more accurate routing information and will look into their
+routing table and make a choice based on their knowledge.
+
+Someone that sends a snail mail parcel from Europe to India doesn't
+have to write the name of the Indian postman on the paket that is
+supposed to hand it over to the recipient or the brand of bicycle he
+is supposed to ride when transporting the parcel. He doesn't have to
+decide the path that the postman has to take in the recipient's
+village. The postman knows better than the sender.
+
+It should be sufficient if nodes have a vague idea about the topology
+of the mesh in the distance and who is out there. If only a few TC
+messages out of many TC packets that are broadcast make it over the
+whole mesh this should be sufficient.
+
+Have fun!
+
+Elektra
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-Link-Quality.html ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-Link-Quality.html
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-Link-Quality.html	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-Link-Quality.html	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,745 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML>
+  <HEAD>
+    <TITLE>olsrd Link Quality Extensions</TITLE>
+
+    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+
+    <STYLE TYPE="text/css">
+      body {
+        font-family: verdana,arial,sans-serif;
+        font-size: 10pt;
+        background-color: #ffffff;
+        color: #000000;
+      }
+
+      :link { color: #123e80 }
+      :visited { color: #123e80 }
+      :active { color: #123e80 }
+    </STYLE>
+  </HEAD>
+
+  <BODY>
+    <H2>olsrd Link Quality Extensions</H2>
+
+    <P>
+    </P>
+
+    <H3>Credits</H3>
+
+    <P>
+      The way in which the ETX metric is applied to OLSR owes its
+      existence to ideas conceived by the wonderful folks at
+      <A HREF="http://www.c-base.org">c-base</A>
+      and
+      <A HREF="http://www.freifunk.net">freifunk.net</A>.
+      Any implementation bugs are solely Thomas's fault, though.
+    </P>
+
+    <P>
+      Guys, also thanks a lot for your hospitality, for your valuable
+      input, for being brave enough to test early releases of olsrd,
+      for supplying a great testbed in Berlin, and for being
+      you!
+    </P>
+
+    <H3>Changes</H3>
+
+    <UL>
+      <LI>
+        <P>
+          0.4.9 - Documented the <EM>LinkQualityMult</EM>
+          configuration directive.
+        </P>
+      </LI>
+    </UL>
+      
+    <H3>Theory</H3>
+
+    <P>
+      Release 0.4.8 of olsrd offers an experimental implementation of
+      an ETX-like metric. When calculating a routing table for us,
+      pure RFC-compliant OLSR simply minimizes the number of hops
+      between ourselves and the other nodes in the MANET, even if this
+      means that a route via a single very bad link will be preferred
+      to a route via two excellent links, although the latter would
+      probably have been the better choice.
+    </P>
+
+    <P>
+      To solve this problem, we have to teach olsrd how to tell good
+      links from bad links. We have done so by measuring the packet
+      loss for OLSR packets that we receive from our neighbors. As we
+      periodically receive HELLO messages from our neighbors (by
+      default every 2 seconds), we have enough packets to determine
+      the packet loss for packets that each of our neighbors sends to
+      us.
+    </P>
+
+    <P>
+      If, for example, 3 out of 10 packets are lost on their way from
+      our neighbor to ourselves, we have a packet loss of 3/10 = 0.3 =
+      30%. At the same time 7 of the 10 packets that the neighbor sent
+      went through. Hence, the probability for a successful packet
+      transmission from this neighbor to ourselves is 7/10 = 0.7 =
+      70%. This probability is what we call the <EM>Link
+      Quality</EM>. So the Link Quality says how good a given link
+      between a neighbor and ourselves is in the direction from the
+      neighbor to ourselves. It does so by saying how likely it is
+      that a packet that we send is successfully received by our
+      neighbor.
+    </P>
+
+    <P>
+      However, it is also important to know the quality of the link in
+      the opposite direction, i.e. how many of the packets that we
+      send out are received by each of our neighbors. So, we are not
+      only interested in the Link Quality of a given link, but also in
+      the corresponding neighbor's idea of the Link Quality. That's
+      what we call the <EM>Neighbor Link Quality</EM>. The Neighbor
+      Link Quality says how good a given link between a neighbor and
+      ourselves is in the direction from ourselves to the neighbor.
+    </P>
+
+    <P>
+      The Link Quality and the Neighbor Link Quality are values
+      between 0 and 1 or, which is equivalent, between 0 and
+      100%. They represent the probability that a packet that our
+      neighbor sends actually makes it to us (Link Quality) and that
+      a packet that we send actually makes it to our neighbor
+      (Neighbor Link Quality).
+    </P>
+
+    <P>
+      Let's now look at the probability for a successful packet round
+      trip, i.e. the probability that we successfully send a packet to
+      our neighbor and, on receiving it, our neighbor successfully
+      replies with a response packet. For a successful round trip both
+      packets must get through, the packet that we've sent and the
+      response packet that our neighbor has sent. So, the success
+      probability is NLQ x LQ, where NLQ is the Neighbor Link Quality
+      of the link and LQ is its link quality. For example, if we have
+      a NLQ of 60% and a LQ of 70%, the probability of a successful
+      round trip is 60% x 70% = 0.6 x 0.7 = 0.42 = 42%.
+    </P>
+
+    <P>
+      In wireless networks each recipient of a packet acknowledges
+      packet reception by sending back an acknowledgment packet to
+      the sender. So, when does a retransmission of a packet happen? 
+      It happens, if the sender does not receive an
+      acknowledgment. And in which cases does the sender not receive
+      an acknowledgment? If either the packet that it sent is lost or
+      if the corresponding acknowledgment packet is lost. So, what is
+      the probability for a retransmission to <EM>not</EM> take place? 
+      Well, as the sender's packet has to get through in one direction
+      and the recipient's acknowledgment has to get through in the
+      opposite direction, too, this is exactly the probability for a
+      successful packet round trip, i.e. NLQ x LQ.
+    </P>
+
+    <P>
+      We can now answer the question of how many transmission attempts
+      it will typically take to get a packet from us to a neighbor or
+      from the neighbor to us. It is 1 / (NLQ x LQ). So, in the above
+      case of NLQ x LQ = 42%, we expect on average 1 / 0.42 = 2.38
+      transmission attempts for a packet until it gets through.
+    </P>
+
+    <P>
+      Note that this number is valid for both directions of the link,
+      as in both cases we have to look at the probability for a
+      successful packet round trip. For packets that we send to our
+      neighbor, the packet goes from us to the neighbor and the
+      acknowledgment travels the other way around. For packets that
+      our neighbor sends to us, the packet goes from the neighbor to
+      us and the acknowledgment travels from us to the neighbor. In
+      both cases a packet is sent in each direction and retransmission
+      occurs if either packet is lost.
+    </P>
+
+    <P>
+      The value 1 / (NLQ x LQ) is called the <EM>Expected Transmission
+      Count</EM> or <EM>ETX</EM>. For those interested in a more
+      in-depth discussion, there's a
+      <a href="http://pdos.csail.mit.edu/papers/grid:mobicom03/">
+      scientific paper</a> by the people who invented all this, and
+      for those who would like to know still more, there's
+      <a href="http://pdos.csail.mit.edu/papers/grid:decouto-phd/thesis.pdf">
+      Doug's PhD</a> thesis.
+    </P>
+
+    <P>
+      Let's assume that we have a route from ourselves via two nodes A
+      and B to a node C. What is the ETX for the total route, i.e. how
+      often is our packet retransmitted on its way from us to C? Well,
+      we know how many attempts we need on average to successfully
+      transmit a packet from us to A. Let's call this value ETX1. So,
+      we already have ETX1 attempts just to reach A. The packet would
+      then take an additional number of attempts to hop from A to
+      B. Let's call this second value ETX2. Finally, a further number
+      of attempts is required to hop from B to C. Let's call this
+      third value ETX3. Let's now have a look at the total number of
+      transmissions that have happened to get our packet from us to
+      C. This number is simply ETX1 + ETX2 + ETX3.
+    </P>
+
+    <H3>Protocol</H3>
+
+    <P>
+      In order to calculate the ETX for a link to a neighbor, we need
+      to know the neighbor's idea of the link quality, i.e. the NLQ,
+      as we can only determine the LQ ourselves, but we want to know
+      ETX = 1 / (NLQ * LQ). So the link quality extensions to olsrd
+      introduce a new kind of HELLO messages, which we call <EM>LQ
+      HELLO</EM> messages. For each link listed in such a message, the
+      originator of the messages also tells us the link quality. So,
+      each neighbor puts the LQ values that it has determined in the
+      message, which from our perspective are NLQ values. So, owing to
+      the LQ HELLOs we now have all the information to calculate the
+      ETX for each link between ourselves and one of our neighbors.
+    </P>
+
+    <P>
+      Let's again have a look at the total number of transmissions
+      required for a route that consists of more than one hop,
+      i.e. that is not a route to one of our neighbors. If we stick
+      with the above example, we know ETX1 from the LQ HELLOs. But how
+      do we learn ETX2 and ETX3? For this the link quality extensions
+      to olsrd introduce a new kind of TC messages. TC messages are
+      used in OLSR to tell the world, i.e. all other nodes in the
+      MANET, which neighbors we have. We have extended TC messages to
+      additionally carry information on how good the links to our
+      neighbors are. We call this extended variant of TCs,
+      analogously to LQ HELLOS, <EM>LQ TC</EM> messages.
+    </P>
+
+    <P>
+      So, with LQ HELLO messages we find out which neighbors we have
+      and how good our links to them are and with LQ TC messages, we
+      share this knowledge with all other nodes and all other nodes
+      share their knowledge with us.
+    </P>
+
+    <P>
+      In this way each node in the network ends up knowing which links
+      each other node in the MANET has and how good they are. Well,
+      actually, it's a bit more complex than that, because of an
+      optimization called multi-point relaying. But this is beyond the
+      scope of this introductory text.
+    </P>
+
+    <H3>Warning</H3>
+
+    <P>
+      LQ HELLO messages and LQ TC messages are not compatible with
+      RFC-compliant HELLO and TC messages. So make sure that you
+      either switch <EM>all</EM> nodes of your network to link quality
+      or <EM>none</EM> of your nodes. A mixed configuration will
+      probably result in an unpredictable mess.
+    </P>
+
+    <H3>Practice</H3>
+
+    <H4>New Configuration Parameters</H4>
+
+    <H5>LinkQualityLevel</H5>
+
+    <P>
+      Let's now have a look at how we would use the link quality
+      extensions. The configuration parameter that controls link
+      quality is <EM>LinkQualityLevel</EM>, as it sets the level to
+      which link quality is used, i.e. for which purposes olsrd looks
+      at the link quality information.
+    </P>
+    <UL>
+      <LI>
+        <P>
+          Setting this parameter to 0 disables the link quality
+          extensions. olsrd then works in exactly the same way as
+          before, i.e. it is RFC-compliant, uses HELLO and TC
+          messages, and calculates routes by minimizing the hop count.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          Setting this parameter to 1 enable the link quality
+          extensions and tells olsrd to select MPRs based on the link
+          quality information. A neighbor is selected as an MPR, if
+          it has the best route to any 2-hop neighbor. Suppose that
+          ETX1 is the expected number of transmissions between us and
+          a neighbor N and that ETX2 is the expected number of
+          transmissions between N and a two-hop neighbor N2. For each
+          of our two-hop neighbors we then select the neighbor N as
+          an MPR that results in the lowest possible total ETX of ETX1
+          + ETX2.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          Setting this parameter to 2 not only selects MPRs based on
+          the link quality but also considers link quality information
+          when calculating the routing table. For a given destination
+          node D we select the route that has the minimal total ETX of
+          ETX1 + ETX2 + ... + ETXn, where ETX1 is the expected number
+          of transmissions from us to our neighbor, ETX2 is the
+          expected number of transmissions from our neighbor to the
+          next node, and ETXn is the expected number of transmissions
+          from our destination's neighbor to the destination. This is
+          the recommended setting.
+        </P>
+      </LI>
+    </UL>
+
+    <P>
+      <B>IMPORTANT:</B> Remember to set <EM>all</EM> nodes of your
+      MANET to the same link quality level. Even if levels 2 and 3 use
+      the same kind of messages, i.e. LQ HELLOs and LQ TCs, they use a
+      different algorithm for calculating the routing table. This can
+      also mess up your routing!
+    </P>
+
+    <H5>LinkQualityWinSize</H5>
+
+    <P>
+      The second configuration parameter related to link quality is
+      <EM>LinkQualityWinSize</EM>. When determining the packet loss of
+      the packets received from a neighbor, olsrd only looks at the
+      <EM>n</EM> most recent packets. By default <EM>n</EM> is set to
+      10, so olsrd looks at the ten most recent packets received (or
+      not received) from a neighbor and then determines the packet
+      loss. Let's assume that of the 10 packets we have received 7,
+      then we have missed 3, which corresponds to a packet loss of
+      3/10 = 0.3 = 30%. The corresponding Link Quality is 7/10 = 0.7 =
+      70%.
+    </P>
+
+    <P>
+      Let's have a look at what the default value means. Let's for the
+      moment only think of LQ HELLO messages and neglect other message
+      types. By default LQ HELLOs are sent every 2 seconds. So, we
+      calculate the packet loss over the past 20 seconds. So, changes
+      in the link quality are accounted for relatively fast. For
+      longer intervals just increase this value.
+    </P>
+
+    <H5>LinkQualityMult</H5>
+
+    <P>
+      Version 0.4.9 supports a third configuration parameter,
+      <EM>LinkQualityMult</EM>. This is a per-interface parameter, so
+      it may only appear in an interface configuration block. This
+      parameter can be used to alter the LQ values that we announce,
+      which will then result in an altered ETX for links between us
+      and our neighbors - remember that ETX = 1 / (NLQ x LQ).
+    </P>
+
+    <P>
+      The idea is to enable us to make certain links that we have
+      artificially appear better or worse than they actually are. In
+      this way we can manually affect the routing decisions made by
+      the OLSR network.
+    </P>
+    
+    <P>
+      The <EM>LinkQualityMult</EM> parameter is followed by an IP
+      address and a number, the multiplier. The IP address specifies
+      the IP address of the neighbor interface address of the link
+      that we want to manipulate. The LQ values that we determine for
+      this link are then multiplied by the given multiplier.
+    </P>
+
+    <P>
+      If the word <EM>default</EM> is specified in lieu of an IP
+      address, then this multiplier applies to all links via the
+      interface that we're configuring. Note, however, that a
+      multiplier linked to a real IP address has priority over the
+      default multiplier. So, we're looking for the most specific
+      match.
+    </P>
+
+    <H4>Old Configuration Parameters</H4>
+
+    <P>
+      The link quality extensions do not work very well with
+      hysteresis. Hysteresis basically acts as a sort of barrier that
+      only links that are "good enough" can cross. If a link is too
+      flaky, hysteresis will make olsrd consider the link as
+      non-existent. So, this is a binary thing. Either a link is able
+      to cross the barrier, or it is not. There's nothing in
+      between. However, we want olsrd to consider <EM>every</EM> link
+      there is, without any barrier, because then we can leave it to
+      the link quality extensions to judge how good the link actually
+      is and how much we trust the link.
+    </P>
+
+    <P>
+      If a link with an ETX value of 50 is the only way of
+      reaching a node, then we want to use this link, as there is no
+      better way.
+    </P>
+
+    <P>
+      In addition, in contrast to only saying "good enough" or "not
+      good enough" like hysteresis, the link quality extensions offer
+      a much more detailed view of the world by saying something like
+      "75% good enough, 25% not good enough".
+    </P>
+
+    <P>
+      The second mechanism that could interfere with the link quality
+      extensions is the link detection scheme. By default, if olsrd
+      misses three (LQ) HELLO messages in a row from a neighbor, the
+      link is considered broken. However, we'd prefer the link to just
+      expose a lower quality. So, setting the HELLO validity time to
+      the HELLO interval multiplied by the link quality window size is
+      probably a good rule of thumb. In this way the link will be
+      removed not before the link quality extensions have had enough
+      time to gradually reduce the link quality to zero.
+    </P>
+
+    <H4>Sample Configuration</H4>
+
+    <P>
+      A minimal configuration that leaves everything at the default
+      and just makes the changes required for the link quality
+      extension to work properly could look as follows. Note the
+      <EM>ClearScreen</EM> directive that causes the screen to be
+      cleared before updated debug information is printed. This makes
+      the debug output more readable in many cases.
+    </P>
+
+    <PRE>
+DebugLevel              2
+ClearScreen             yes
+LinkQualityLevel        2
+LinkQualityWinSize      12
+UseHysteresis           no
+
+Interface "if03"
+{
+  HelloInterval         2.0
+  HelloValidityTime     20.0
+}
+    </PRE>
+
+    <P>
+      Let's assume that we would like to use the
+      <EM>LinkQualityMult</EM> directive to multiply the LQ value that
+      we report for the link between our local interface <EM>if03</EM>
+      and an interface of one of our neighbors that has an IP address
+      of 192.168.0.1. Say, we'd like to multiply the LQ value by
+      0.5. We would then simply add the following line to the
+      <EM>Interface</EM> section of the above configuration file.
+    </P>
+
+    <PRE>
+  LinkQualityMult 192.168.0.1 0.5
+    </PRE>
+
+    <P>
+      Suppose that we would further like to multiply the LQ values
+      that we report for all other links between our local interface
+      <EM>if03</EM> and a neighbor interface by 0.8. We would then
+      add a second, default <EM>LinkQualityMult</EM> statement and we
+      would end up with the following two lines.
+    </P>
+
+    <PRE>
+  LinkQualityMult 192.168.0.1 0.5
+  LinkQualityMult default 0.8
+    </PRE>
+
+    <P>
+      For the link to 192.168.0.1 the first line would have precedence
+      over the second (default) line and 0.5 would be used as the
+      multiplier. For all other links the default multiplier of 0.8
+      would be used, as there isn't any better match.
+    </P>
+
+    <H3>Debug Output</H3>
+    
+    <P>
+      0.4.8 also introduces significant changes in the debug
+      output. Let's have a look at what happens at debug level 2, which
+      is the recommended default for the link quality extensions.
+    </P>
+
+    <PRE>
+--- 14:28:56.80 ---------------------------------------------------- LINKS
+
+IP address       hyst   LQ     lost   total  NLQ    ETX
+192.168.0.1      0.000  1.000  0      10     1.000  1.00
+    </PRE>
+
+    <P>
+      This table contains the links to our neighbors. It contains the
+      following columns.
+    </P>
+
+    <UL>
+      <LI>
+        <P>
+          <EM>IP address</EM> - the IP address of the interface via
+          which we have contact to the neighbor.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>hyst</EM> - the current hysteresis value for this link.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>LQ</EM> - the quality of the link determined at our
+          end. This is what we have previously called the Link
+          Quality.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>lost</EM> - the number of lost packets among the
+          <EM>n</EM> packets most recently sent by our neighbor via
+          this link. <EM>n</EM> is the link quality window size.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>total</EM> - the total number of packets received up to
+          now. This value starts at 0 immediately after a link has
+          come to life and then counts each packet. It is capped at
+          the link quality window size.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>NLQ</EM> - this is our neighbor's view of the link
+          quality. Previously we have called this the Neighbor Link
+          Quality. This value is extracted from LQ HELLO messages
+          received from our neighbors. NB: If a neighbor stops
+          sending packets completely, we do not have any means of
+          updating this value. However, in this case the LQ value will
+          decrease and the link thus be detected as becoming worse.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>ETX</EM> - this is the ETX for this link, i.e. 1 / (NLQ
+          x LQ).
+        </P>
+      </LI>
+    </UL>
+
+    <PRE>
+--- 14:28:56.80 ------------------------------------------------ NEIGHBORS
+
+IP address       LQ     NLQ    SYM   MPR   MPRS  will
+10.0.0.6         1.000  1.000  YES   YES   NO    6
+    </PRE>
+
+    <P>
+      This table contains a list of all our neighbors. It is closely
+      related to the link table in that we are connected to a
+      neighbor via one or more links. The table has the following
+      columns.
+    </P>
+      
+    <UL>
+      <LI>
+        <P>
+          <EM>IP address</EM> - the main IP address of the neighbor.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>LQ</EM> and <EM>NLQ</EM> - the LQ and NLQ values of the
+          best link that we have with this neighbor. (In
+          multi-interface configurations we can have more than one
+          link with a neighbor.)
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>SYM</EM> - this states whether the link to this
+          neighbor is considered symmetric by olsrd's link detection
+          mechanism.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>MPR</EM> (multi-point relay) - this indicates whether we
+          have selected this neighbor to act as an MPR for us.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>MPRS</EM> (multi-point relay selector) - this indicates
+          whether the neighbor node has selected us to act as an MPR
+          for it.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>will</EM> - the neighbor's willingness.
+        </P>
+      </LI>
+    </UL>
+
+    <PRE>
+--- 14:28:56.80 ------------------------------------------------- TOPOLOGY
+
+Source IP addr   Dest IP addr     LQ     ILQ    ETX
+10.0.0.6         192.168.0.2      1.000  1.000  1.00
+10.0.0.6         10.0.0.5         1.000  1.000  1.00
+    </PRE>
+
+    <P>
+      This table displays the topology information that olsrd has
+      gathered from LQ TC messages. It states which nodes in the
+      network report links to which other nodes and which quality
+      these links have. So, it's olsrd's view of the world beyond its
+      immediate neighbor nodes, i.e. its view of the nodes that it
+      cannot reach directly. This table has the following columns.
+    </P>
+
+    <UL>
+      <LI>
+        <P>
+          <EM>Source IP addr</EM> - the node that reports a link.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>Dest IP addr</EM> - the node to which the source node
+          reports the link.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>LQ</EM> (link quality) - the quality of the link as
+          determined by the source node. For the source node this is
+          the Link Quality. For the destination node this is the
+          Neighbor Link Quality.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>ILQ</EM> (inverse link quality) - the quality of the
+          link as determined by the destination node. For the source
+          node this is the Neighbor Link Quality. For the destination
+          node this is the Link Quality. We just did not want to name
+          it "NLQ", as we use NLQ only for the link quality reported
+          by our neighbors. But functionally this is equivalent to
+          the NLQ we know from the link and neighbor tables.
+        </P>
+      </LI>
+      <LI>
+        <P>
+          <EM>ETX</EM> - the ETX value for this link, calculated by
+          ETX = 1 / (ILQ x LQ).
+        </P>
+      </LI>
+    </UL>
+
+    <PRE>
+--- 14:28:56.80 ------------------------------------------------- DIJKSTRA
+
+10.0.0.6:1.00 (one-hop)
+10.0.0.5:2.00 <- 10.0.0.6:1.00 (one-hop)
+    </PRE>
+
+    <P>
+      This table displays the best routes that olsrd could find for
+      each destination that it knows about. The leftmost IP address
+      given on each line is the destination of a route. The remaining
+      IP addresses in a line specify the nodes on the route between
+      ourselves and the destination address. Moving from the
+      destination address to the right, address by address, moves us
+      closer from the destination to ourselves, hop by hop.
+    </P>
+
+    <P>
+      In the above case we see routes to two nodes, 10.0.0.6 and
+      10.0.0.5. In the first line, there aren't any intermediate nodes
+      between us and the destination, the destination address is the
+      only IP address in this line. In the second line we have one
+      intermediate node, 10.0.0.6. So, the second line describes a
+      route to 10.0.0.5 via 10.0.0.6.
+    </P>
+
+    <P>
+      The number after the colon following an IP address in the table
+      is the total ETX of the route up to this IP address, i.e. the
+      sum of the ETX values of all hops between ourselves and this IP
+      address.
+    </P>
+
+    <P>
+      In the above example the first line represents a path with an
+      ETX value of 1.00 to 10.0.0.6. As we've seen in the neighbor
+      table above 10.0.0.6 is our neighbor, so the route to it
+      consists only of a single hop, which has an ETX of 1.00, hence
+      the 1.00 in this line.
+    </P>
+
+    <P>
+      In the second line, 10.0.0.5 is not a neighbor of ours. However,
+      10.0.0.6 is and from the topology table above we can tell that
+      10.0.0.6 reports a link to 10.0.0.5. So, we can reach 10.0.0.5
+      via 10.0.0.6. This is what this line says. Remember that each
+      line represents a route by first giving the IP address of the
+      destination (10.0.0.5) and that moving to the right means moving
+      towards ourselves until one of our (one-hop) neighbor is
+      reached. If we move from 10.0.0.5 to the right, we find
+      10.0.0.6, which is our (one-hop) neighbor. So we have a route.
+    </P>
+    
+    <P>
+      If we would like to know which path a packet takes that we send
+      to 10.0.0.5, we have to read the line backwards. We then see
+      that the packet first travels to our (one-hop) neighbor 10.0.0.6
+      via a link that has an ETX of 1.00 (which we can confirm by
+      looking at the neighbor table above). From there it is forwarded
+      to 10.0.0.5 via another link that also has an ETX of 1.00 (which
+      we can confirm by means of the topology table above), resulting
+      in a total ETX of 1.00 + 1.00 = 2.00, which is the number that
+      follows 10.0.0.5. Remember that the ETX value given for an IP
+      address is the cumulative ETX for the complete route up to this
+      IP address.
+    </P>
+
+    <P>
+      If olsrd is able to find a route between us and the destination,
+      the last IP address in the line is one of our neighbors. In this
+      case, "(one-hop)" is appended to the line to illustrate that the
+      last IP address is one of our (one-hop) neighbors. However,
+      let's assume that we've just switched on olsrd. In this case, it
+      does not know about all links in the network, yet, as it hasn't
+      received LQ TC messages from all nodes. So, it may know that a
+      node exists (as it has already received LQ TC messages from it)
+      but it does not necessarily know how to reach it (as it may not
+      have received LQ TC messages from nodes between it and
+      ourselves, yet). In this case the last IP address is the last
+      node that is reachable from the destination and the line ends
+      with the word "FAILED".
+    </P>
+
+    <P>
+      The same is true for neighbors to which we do not have a
+      symmetric link. We know that they're there, but we do not have a
+      link to them, hence olsrd cannot find a route, which results in
+      "FAILED".
+    </P>
+
+    <H3>Remarks</H3>
+
+    <P>
+      If you have any questions on using olsrd or if you would like to
+      know more about the link quality extension, it's probably best
+      to subscribe to the mailing lists and ask your question
+      there. Information on the mailing lists is available at
+      <A HREF="http://www.olsr.org">http://www.olsr.org</A>.
+    </P>
+
+  </BODY>
+</HTML>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-Olsr-Switch.html ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-Olsr-Switch.html
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/README-Olsr-Switch.html	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/README-Olsr-Switch.html	2008-10-03 14:45:06.000000000 +0200
@@ -0,0 +1,489 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+        <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+	<TITLE>Olsr Switch</TITLE>
+	<STYLE>
+	<!--
+		H1 { color: #000000 }
+		P { color: #000000; font-family: "verdana", "arial", sans-serif; font-size: 10pt }
+		H2 { color: #000000 }
+		H3 { color: #000000 }
+		PRE { color: #000000 }
+	-->
+	</STYLE>
+</HEAD>
+<BODY>
+<H1>Olsr_Switch network simulation</H1>
+</P>
+<H2>Summary</H2>
+<P>This document gives a brief introduction to the <A HREF="http://www.olsr.org/">olsr.org</A>
+OLSR daemon network simulation extentions and tools. The network
+simulation tool olsr_switch provides olsrd processes running in a
+special <I>host-emultion</I> mode with access to a virtual network.
+Multiple such processes can run on a host. This network can be freely
+manipulated by the user allowing for simulation of dynamic
+large-scale networks. 
+</P>
+<P>Only IPv4 is supported for now. 
+</P>
+<H2>Background</H2>
+<P>olsr_switch was inspired by the uml_switch used to communicate
+between <A HREF="http://user-mode-linux.sourceforge.net/">UML</A>
+instances, which I have used for olsrd testing. Also I remember
+seeing that the guys at LRI working on the <A HREF="http://qolsr.lri.fr/">qolsr</A>
+project has done something similar. 
+</P>
+<P>The target users for this kind of things are probably mainly
+developers and researchers. But it might come in handy for others as
+well. 
+</P>
+<H2>Description</H2>
+<H3>olsr.org</H3>
+<P>The olsr.org OLSR daemon is an implementation of the <A HREF="http://ietf.org/rfc/rfc3626.txt">Optimized
+Link State Routing protocol</A> a IP routing protocol for mobile
+ad-hoc networks. Multiple interesting extensions are available for
+the implementation. Read more at <A HREF="http://www.olsr.org/">olsr.org</A>.
+</P>
+<H3>olsr_switch</H3>
+<P>The application, called olsr_switch, is really a traffic router
+that will allow multiple olsrd instances to connect and communicate
+over TCP via the loopback interface. Connecting to olsr_switch on
+remote hosts will be possible, but it is not implemented at the
+current time. 
+</P>
+<P>Basically olsr_switch works on two datasets - clients and links. A
+client is a connected olsrd process and there are two uni-directional
+link between all nodes(A-&gt;B and B-&gt;A) that can be manipulated
+independently. When receiving traffic from a olsrd client the switch
+will forward this traffic to all other clients to which it has a
+valid link. Links can be set to three different &quot;modes&quot;
+based on the <I>quality</I> set on the link: 
+</P>
+<UL>
+	<LI><P STYLE="margin-bottom: 0in"><B>Open</B>(quality 100) - all
+	traffic will be forwarded over this link. 
+	</P>
+	<LI><P STYLE="margin-bottom: 0in"><B>Closed</B>(quality 0) - no
+	traffic will be forwarded over this link. 
+	</P>
+	<LI><P><B>Lossy</B>(quality 1-99) - in this mode the quality
+	constraint is used as the chance in percentage, for traffic to be
+	forwarded over the link. So if quality is set to 25 there will in
+	average be 75% packet loss. 
+	</P>
+</UL>
+<P>The application provides the user with a prompt/shell where
+various commands for topology manipulation or data retrieval are
+available. A help command is provided for the users convenience. This
+help command will also provide the user with specific help on all
+available commands. More on this later. 
+</P>
+<H3>olsrd host-emulation clients</H3>
+<P>The communication interface against olsr_switch can naturally not
+be 100% transparent for the olsrd process which normally runs on
+UDP/698 on &quot;real&quot; network interfaces. Olsrd itself had to
+be modified to set up a virtual interface connecting to olsr_switch.
+This virtual interface is transparent to all overlying functionality.
+This means that that olsrd host-emulation can run in both RFC and LQ
+mode, and that plugins can be loaded normally etc. But no routes are
+added by the olsrd process. Later on route information might be
+signaled from the olsrd instance to olsr_switch so that a centralized
+route database is available to the user. As of now, you can watch the
+olsrd debug output or easier yet, run one node with the httpinfo
+plugin to get the route/topology/link information. 
+</P>
+<P>Currently olsrd cannot run on both real and host-emulation
+interfaces, but this might change in the future if I get convinced
+that it is useful. No routes can be added by the host-emulating olsrd
+instances, so 
+</P>
+<H2>Building and running</H2>
+<P>As of yet, olsr_switch builds and runs on GNU/Linux and FreeBSD
+systems. 
+</P>
+<H3>Building</H3>
+<P>The olsr.org olsrd source code and pre-compiled packages can be
+downloaded from the olsr.org <A HREF="http://www.olsr.org/index.cgi?action=download">download</A>
+section. But as of now you need the CVS version if you want the
+olsr_switch code. To check out the current snapshot do: 
+</P>
+<PRE>cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/olsrd login
+
+cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/olsrd co olsrd-current</PRE><P>
+Now enter the olsrd source directory and do: 
+</P>
+<PRE STYLE="margin-bottom: 0.2in">olsrd-current# make</PRE><P>
+to build olsrd itself, and: 
+</P>
+<PRE STYLE="margin-bottom: 0.2in">olsrd-current# make switch</PRE><P>
+to build olsr_switch. If no error messages occurred, you should now
+have the two executables <I>olsrd</I> and <I>olsr_switch</I>
+available in the current directory. 
+</P>
+<H3>Running</H3>
+<P>Before starting any olsrd host-emu clients the switch must be
+started. This is done using the command <I>olsr_switch</I> and the
+application will initiate the communication socket and provide the
+user with a prompt for input: 
+</P>
+<PRE>olsrd-current# ./olsr_switch
+olsrd host-switch daemon version 0.1 starting
+Initiating socket TCP port 10150
+OHS command interpreter reading from STDIN
+&gt;</PRE><P>
+<BR><BR>
+</P>
+<P>olsrd_switch has a buildt-in command for starting and
+stopping local olsrd instances and we will learn more about 
+this later. But olsrd can also be ran in host-emulation mode
+from the command line. To start olsrd in host-emulation mode do: 
+</P>
+<PRE STYLE="margin-bottom: 0.2in">./olsrd -hemu <B>IP-ADDRESS</B></PRE><P>
+Here <I>IP-ADDRESS</I> will be the IP address that the process will
+set as its main address in the emulation mode. This address has no
+connection to the real IP-stack and can be chosen freely. Of cause,
+no two instances can run using the same IP.<BR>It might be wise to
+have a separate olsrd configuration file for host-emulation. In that
+case issue: 
+</P>
+<PRE STYLE="margin-bottom: 0.2in">./olsrd -f <B>FILENAME</B> -hemu <B>IP-ADDRESS</B></PRE><P>
+As of now there is no emulated destination address used. All traffic
+will be passed on regardless of the network address used. Olsrd
+communicates using broadcast/multicast so that multiple &quot;overlapping&quot;
+networks might exist. 
+</P>
+<H2>Command-line interface</H2>
+<P>Blah blah blah 
+</P>
+<H3>help</H3>
+<P>Type 'help cmd' for help on a specific command 
+</P>
+<PRE>&gt; help
+Olsrd host switch version 0.1
+Available commands:
+        help - Help on shell commands
+        exit - Exits olsr host switch
+        log - Displays or sets log bits
+        list - List all connected clients or links
+        link - Manipulate links</PRE><H3>
+list</H3>
+<P>The <I>list</I> command is used for client and link listing. The
+help page states: 
+</P>
+<PRE>&gt; help list
+Usage: <B>list &lt;clients|links&gt;</B>
+Description:
+<I>This command will list all the clients or all the links registered </I>
+<I>by olsr_switch. By default clients are listed.</I></PRE><H3>
+link</H3>
+<P>The <I>link</I> command is used for manipulating links. Here is
+the help page for this command: 
+</P>
+<PRE>&gt; help link
+Usage: <B>link &lt;bi&gt; [srcIP|*] [dstIP|*] [0-100]</B>
+Description:
+<I>This command is used for manipulating olsr links. The link quality </I>
+<I>is a number between 0-100 representing the chance in percentage </I>
+<I>for a packet to be forwarded</I>
+<I>on the link.</I>
+To make the link between 10.0.0.1 and 10.0.0.2 have 50% packetloss do:
+ link 10.0.0.1 10.0.0.2 50
+Note that this will only effect the unidirectional link 
+10.0.0.1 -&gt; 10.0.0.2. To make the changes affect traffic 
+in both directions do:
+ link bi 10.0.0.1 10.0.0.2 50
+To completely block a link do:
+ link 10.0.0.1 10.0.0.2 0
+To make all traffic pass(delete the entry) do:
+ link 10.0.0.1 10.0.0.2 100
+Note that &quot;bi&quot; can be used in all these examples.
+Wildcard source and/or destinations are also supported.
+To block all traffic from a node do:
+link 10.0.0.1 * 0
+To set 50% packetloss on all links to 10.0.0.2 do:
+ link * 10.0.0.2 50
+To delete all links do:
+ link * * 100
+Wildcards can also be used in combination with 'bi'.
+To list all manipulated links use 'list links'.</PRE>
+<H3>olsrd</H3>
+<P>The <I>olsrd</I> command is used for manipulating links. Here is
+the help page for this command: 
+</P>
+<PRE>
+> help olsrd
+Usage: <B>olsrd [start|stop|show|setb|seta] [IP|path|args]</B>
+Description:
+<I>This command is used for managing local olsrd instances from within olsr_switch.</I>
+<I>The command can be configured in runtime using the setb and seta sub-commands.</I>
+To show the current olsrd command-configuration do:
+ olsrd show
+To set the olsrd binary path do:
+ olsrd setb /full/path/to/olsrd
+To start a olsrd instance with a IP address of 10.0.0.1, do:
+ olsrd start 10.0.0.1
+To stop that same instance do:
+ olsrd stop 10.0.0.1
+</PRE>
+<H3>others</H3>
+<P>Two other commands are available: 
+</P>
+<UL>
+	<LI><P STYLE="margin-bottom: 0in"><B>exit</B> - terminates
+	olsr_switch. 
+	</P>
+	<LI><P><B>log</B> - sets the log level. 
+	</P>
+</UL>
+<P>Read the help pages for details. 
+</P>
+<H2>Running olsrd in host-emulation mode</H2>
+<P>Now for a real world example of connecting olsrd instances. Let's
+assume we have a modified configuration file, <I>/etc/olsrd.emu.conf</I>
+that we use for host-emu instances. We'll choose the 10.0.0.0/24 IP
+address space for our clients.<BR>First start the olsr_switch in one
+terminal: 
+</P>
+<PRE STYLE="margin-bottom: 0.2in">./olsr_switch</PRE><P>
+Now start the olsrd instances in other terminal(s). If you want to
+follow olsrd operation you should use a debug value &gt; 0. To easen
+CPU usage and terminal count you can start multiple instances that
+will run in the background using the <I>-d 0</I> option. In this
+example we'll run our olsrd instances in the foreground using debug
+level 1. Start them off(in separate terminals) using: 
+</P>
+<PRE STYLE="margin-bottom: 0.2in">./olsrd -f /etc/olsrd.emu.conf -hemu 10.0.0.x -d 1</PRE><P>
+where x is 1-8(we'll run 8 instances). The <A HREF="http://www.gnu.org/software/screen/">screen</A>
+terminal multiplexer application is <I>highly</I> recomended for
+making your life easier if working on multiple terminals. 
+</P>
+<P>Here is the output form the 10.0.0.1 instance of olsrd after some
+time: 
+</P>
+<PRE>       *** olsr.org - 0.4.10-pre (May 30 2005) ***
+
+--- 20:53:26.58 ---------------------------------------------------- LINKS
+
+IP address       hyst   LQ     lost   total  NLQ    ETX
+10.0.0.8         0.000  1.000  0      10     1.000  1.00
+10.0.0.7         0.000  1.000  0      10     1.000  1.00
+10.0.0.6         0.000  1.000  0      10     1.000  1.00
+10.0.0.5         0.000  1.000  0      10     1.000  1.00
+10.0.0.4         0.000  1.000  0      10     1.000  1.00
+10.0.0.3         0.000  1.000  0      10     1.000  1.00
+10.0.0.2         0.000  1.000  0      10     1.000  1.00
+
+--- 20:53:26.58 ------------------------------------------------ NEIGHBORS
+
+IP address       LQ     NLQ    SYM   MPR   MPRS  will
+10.0.0.2         1.000  1.000  YES   NO    NO    3
+10.0.0.3         1.000  1.000  YES   NO    NO    3
+10.0.0.4         1.000  1.000  YES   NO    NO    3
+10.0.0.5         1.000  1.000  YES   NO    NO    3
+10.0.0.6         1.000  1.000  YES   NO    NO    3
+10.0.0.7         1.000  1.000  YES   NO    NO    3
+10.0.0.8         1.000  1.000  YES   NO    NO    3
+
+--- 20:53:26.58 ------------------------------------------------- TOPOLOGY
+
+Source IP addr   Dest IP addr     LQ     ILQ    ETX
+</PRE><P>
+We now have our own virtual network! Notice that you can
+start olsrd instances from olsr_switch using the <i>olsrd</i>
+command. The equvivalent of the above command line statement
+would be:
+<PRE>
+olsrd start 10.0.0.x
+</PRE>
+<P>
+Given that the olsrd command is configured properly
+(see olsrd show, setb and seta).
+</P>
+<P>
+At our switch prompt the command
+<I>list</I> yields the following output: 
+</P>
+<PRE>All connected clients:
+        10.0.0.8 - Rx: 647 Tx: 89 LinkCnt: 0
+        10.0.0.7 - Rx: 752 Tx: 105 LinkCnt: 0
+        10.0.0.6 - Rx: 790 Tx: 120 LinkCnt: 0
+        10.0.0.5 - Rx: 809 Tx: 112 LinkCnt: 0
+        10.0.0.4 - Rx: 811 Tx: 125 LinkCnt: 0
+        10.0.0.3 - Rx: 804 Tx: 138 LinkCnt: 0
+        10.0.0.2 - Rx: 805 Tx: 140 LinkCnt: 0
+        10.0.0.1 - Rx: 829 Tx: 119 LinkCnt: 0</PRE><P>
+Hey - everything is running a-ok! 
+</P>
+<H2>Manipulating links</H2>
+<P>So lets create some link trouble. This introduction has become too
+long already, so we'll introduce two simple example conditions: 
+</P>
+<UL>
+	<LI><P STYLE="margin-bottom: 0in">We want 10.0.0.1 only to have a
+	link to 10.0.0.2 and no one else. 
+	</P>
+	<LI><P>We want 10.0.0.8 only to have 25% chance of getting direct
+	traffic trough to 10.0.0.2,3,4 
+	</P>
+</UL>
+<P>Here's what we need to do: 
+</P>
+<PRE>&gt; link bi 10.0.0.1 * 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.8 quality 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.7 quality 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.6 quality 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.5 quality 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.4 quality 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.3 quality 0
+Setting bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.2 quality 0
+
+
+&gt; link bi 10.0.0.1 10.0.0.2 100
+Removing bidirectional link(s) 10.0.0.1 &lt;=&gt; 10.0.0.2 quality 100
+
+&gt; list links
+All configured links:
+        10.0.0.8 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.7 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.6 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.5 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.4 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.3 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.3 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.4 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.5 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.6 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.7 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.8 Quality: 0
+</PRE><P>
+Now our first condition is met. First all bidirectional links from
+10.0.0.1 was blocked and then the bidirectional link to 10.0.0.2 was
+opened. Now 10.0.0.1 can only see 10.0.0.2 as a neighbor. Note that
+only manipulated links are listed when issuing 'list links'. olsrd at
+10.0.0.1 now shows: 
+</P>
+<PRE>       *** olsr.org - 0.4.10-pre (May 30 2005) ***
+
+--- 21:17:46.06 ---------------------------------------------------- LINKS
+
+IP address       hyst   LQ     lost   total  NLQ    ETX
+10.0.0.2         0.000  1.000  0      10     1.000  1.00
+
+--- 21:17:46.06 ------------------------------------------------ NEIGHBORS
+
+IP address       LQ     NLQ    SYM   MPR   MPRS  will
+10.0.0.2         1.000  1.000  YES   YES   NO    3
+
+--- 21:17:46.06 ------------------------------------------------- TOPOLOGY
+
+Source IP addr   Dest IP addr     LQ     ILQ    ETX
+10.0.0.2         10.0.0.1         1.000  1.000  1.00
+10.0.0.2         10.0.0.3         1.000  1.000  1.00
+10.0.0.2         10.0.0.4         1.000  1.000  1.00
+10.0.0.2         10.0.0.5         1.000  1.000  1.00
+10.0.0.2         10.0.0.6         1.000  1.000  1.00
+10.0.0.2         10.0.0.7         1.000  1.000  1.00
+10.0.0.2         10.0.0.8         1.000  1.000  1.00</PRE><P>
+works like a charm. Now let's make sure we can meet condition two: 
+</P>
+<PRE>&gt; link bi 10.0.0.8 10.0.0.2 25
+Setting bidirectional link(s) 10.0.0.8 &lt;=&gt; 10.0.0.2 quality 25
+
+&gt; link bi 10.0.0.8 10.0.0.3 25
+Setting bidirectional link(s) 10.0.0.8 &lt;=&gt; 10.0.0.3 quality 25
+
+&gt; link bi 10.0.0.8 10.0.0.4 25
+Setting bidirectional link(s) 10.0.0.8 &lt;=&gt; 10.0.0.4 quality 25
+
+&gt; list links
+All configured links:
+        10.0.0.8 =&gt; 10.0.0.4 Quality: 25
+        10.0.0.8 =&gt; 10.0.0.3 Quality: 25
+        10.0.0.8 =&gt; 10.0.0.2 Quality: 25
+        10.0.0.8 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.7 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.6 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.5 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.4 =&gt; 10.0.0.8 Quality: 25
+        10.0.0.4 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.3 =&gt; 10.0.0.8 Quality: 25
+        10.0.0.3 =&gt; 10.0.0.1 Quality: 0
+        10.0.0.2 =&gt; 10.0.0.8 Quality: 25
+        10.0.0.1 =&gt; 10.0.0.3 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.4 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.5 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.6 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.7 Quality: 0
+        10.0.0.1 =&gt; 10.0.0.8 Quality: 0
+</PRE><P>
+Now for a look at olsrd 10.0.0.8s output: 
+</P>
+<PRE>       *** olsr.org - 0.4.10-pre (May 30 2005) ***
+
+--- 21:23:00.35 ---------------------------------------------------- LINKS
+
+IP address       hyst   LQ     lost   total  NLQ    ETX
+10.0.0.7         0.000  1.000  0      10     1.000  1.00
+10.0.0.5         0.000  1.000  0      10     1.000  1.00
+10.0.0.6         0.000  1.000  0      10     1.000  1.00
+10.0.0.2         0.000  0.800  2      10     0.498  2.51
+10.0.0.3         0.000  0.600  4      10     0.498  3.35
+10.0.0.4         0.000  0.900  1      10     0.800  1.39
+
+--- 21:23:00.35 ------------------------------------------------ NEIGHBORS
+
+IP address       LQ     NLQ    SYM   MPR   MPRS  will
+10.0.0.2         0.800  0.498  YES   YES   NO    3
+10.0.0.3         0.600  0.498  NO    NO    NO    3
+10.0.0.4         0.900  0.800  YES   NO    NO    3
+10.0.0.5         1.000  1.000  YES   NO    NO    3
+10.0.0.6         1.000  1.000  YES   YES   NO    3
+10.0.0.7         1.000  1.000  YES   YES   NO    3
+
+--- 21:23:00.35 ------------------------------------------------- TOPOLOGY
+
+Source IP addr   Dest IP addr     LQ     ILQ    ETX
+10.0.0.2         10.0.0.1         1.000  1.000  1.00
+10.0.0.2         10.0.0.3         1.000  1.000  1.00
+10.0.0.2         10.0.0.4         1.000  1.000  1.00
+10.0.0.2         10.0.0.5         1.000  1.000  1.00
+10.0.0.2         10.0.0.6         1.000  1.000  1.00
+10.0.0.2         10.0.0.7         1.000  1.000  1.00
+10.0.0.2         10.0.0.8         0.898  0.498  2.24
+10.0.0.5         10.0.0.4         1.000  1.000  1.00
+10.0.0.6         10.0.0.8         1.000  1.000  1.00
+10.0.0.7         10.0.0.2         1.000  1.000  1.00
+10.0.0.7         10.0.0.3         1.000  1.000  1.00
+10.0.0.7         10.0.0.8         1.000  1.000  1.00
+</PRE><P>
+Yes, there most certainly are some very weak links here. 
+</P>
+<P>Well, lets leave it at that :-) The command line interface is
+meant to be used by applications as well as humans, so if somebody
+wants to create a GUI front-end that should not be to much work. 
+</P>
+<H2>Performance</H2>
+<P>Regarding CPU load I have not done any real testing, but I did try
+seeing how far I could get on my 1.3Ghz/512MB-RAM desktop system
+running LQ olsrd instances in the background initiated from olsrd_switch. 
+When reaching a certain amount (15+) the cPU load is very high for 
+neighbor detection, but as soon as links stabelize the CPU is almost
+idle again. I have ran with 30+ nodes with no problem. But do not start
+to many instances at the same time.
+</P>
+<P>
+Note that, this
+was only using a idle network(no topology changes except new nodes joining). 
+But as soon as olsrd instances can connect from other hosts one can 
+distribute the load. Also the application will be subject to various future
+optimizations.
+</P>
+<P>
+Network load measurement tools will also be on the to-do list.
+</P>
+<HR>
+<P><I>by <A HREF="mailto:andreto--at--olsr.org">Andreas T&oslash;nnesen</A></I>
+</P>
+</BODY>
+</HTML>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/redhat/olsrd.spec ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/redhat/olsrd.spec
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/redhat/olsrd.spec	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/redhat/olsrd.spec	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,211 @@
+Summary:   OLSR Daemon
+Name:      olsrd
+Version:   current
+Release:   1
+License:   BSD
+Packager:  roarbr@tihlde.org
+Group:     System Environment/Daemons
+Source:    http://www.olsr.org/releases/0.5/olsrd-%{version}.tar.bz2
+URL:       http://www.olsr.org/
+BuildRoot: %{_tmppath}/%{name}-root
+Provides:  olsrd
+
+%description
+olsrd is an implementation of the Ad Hoc routing protocol OLSR (RFC3626).
+OLSRD provides (multihop) routing in a dynamic, changing Ad Hoc network,
+wired or wireless.
+This version supports both IPv4 and IPv6.
+See http://www.olsr.org/ for more info.
+
+%prep
+%setup
+
+
+%{__cat} << 'EOF' > %{name}.init
+#!/bin/bash
+#
+# Startup script for the OLSR Daemon
+#
+# chkconfig: 235 16 84
+# description: This script starts OLSRD (Ad Hoc routing protocol)
+#
+# processname: olsrd
+# config: %{_sysconfdir}/olsrd.conf
+# pidfile: %{_localstatedir}/run/olsrd.pid
+
+source %{_initrddir}/functions
+source %{_sysconfdir}/sysconfig/network
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+[ -x %{_sbindir}/olsrd ] || exit 1
+[ -r %{_sysconfdir}/olsrd.conf ] || exit 1
+
+RETVAL=0
+prog="olsrd"
+desc="Ad Hoc routing protocol"
+
+start() {
+        echo -n $"Starting $desc ($prog): "
+	daemon $prog -d 0 
+        RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && touch %{_localstatedir}/lock/subsys/$prog
+        return $RETVAL
+}
+
+stop() {
+        echo -n $"Shutting down $desc ($prog): "
+        killproc $prog
+        RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && rm -f %{_localstatedir}/lock/subsys/$prog
+        return $RETVAL
+}
+
+reload() {
+        echo -n $"Reloading $desc ($prog): "
+        killproc $prog -HUP
+        RETVAL=$?
+        echo
+        return $RETVAL
+}
+
+restart() {
+        stop
+        start
+}
+
+case "$1" in
+  start)
+        start
+        ;;
+  stop)
+        stop
+        ;;
+  restart)
+        restart
+        ;;
+  reload)
+        reload
+        ;;
+  condrestart)
+        [ -e %{_localstatedir}/lock/subsys/$prog ] && restart
+        RETVAL=$?
+        ;;
+  status)
+	status olsrd
+	;;
+  *)
+        echo $"Usage $0 {start|stop|restart|reload|condrestart|status}"
+        RETVAL=1
+esac
+
+exit $RETVAL
+EOF
+
+
+%build
+make %{?_smp_mflags}
+make %{?_smp_mflags} libs
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/sbin/
+mkdir -p %{buildroot}/usr/lib/
+mkdir -p %{buildroot}%{_initrddir}
+mkdir -p %{buildroot}/usr/share/man/man8
+make DESTDIR=%{buildroot} install
+make DESTDIR=%{buildroot} install_libs
+%{__install} -m0755 olsrd.init %{buildroot}%{_initrddir}/olsrd
+
+
+%clean
+rm -rf %{buildroot}
+
+%preun
+/etc/init.d/olsrd stop
+/sbin/chkconfig --del olsrd
+
+%post
+#/sbin/chkconfig --add olsrd
+# Default to not start olsrd automatic
+/sbin/chkconfig olsrd off
+echo "Now please edit /etc/olsrd.conf and run 'service olsrd start' or '/etc/init.d/olsrd start' to start olsrd"
+echo "Run 'chkconfig olsrd on' to enable automatic starting of olsrd"
+
+%files
+%defattr(-, root, root, 0755)
+%doc README CHANGELOG
+%doc lib/*/*README*
+
+%config(noreplace) %{_sysconfdir}/olsrd.conf
+%config %{_initrddir}/olsrd
+/usr/sbin/olsrd
+# Wildchar to cover all installed plugins
+/usr/lib/olsrd_*so*
+/usr/share/man/man8/olsrd.8.gz
+/usr/share/man/man5/olsrd.conf.5.gz
+
+%changelog
+* Tue Jul 17 2007 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Created spec-file for 0.5.2
+
+* Mon Jul 09 2007 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Created spec-file for 0.5.1
+
+* Tue Apr 03 2007 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Created spec-file for 0.5.0
+- Changed from INSTALL_PREFIX to DESTDIR
+
+* Wed Jan 04 2006 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Created spec-file for 0.4.10
+- Removed OS=linux option to make
+- Updated plugin file list, added wildchar for plugins
+
+* Tue Apr 05 2005 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Created spec-file for 0.4.9
+
+* Tue Mar 29 2005 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Increased version number for nameservice and secure plugin
+
+* Tue Dec 07 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Changed spec file for olsrd-0.4.8
+- Removed frontend GUI inclusion
+- Removed references to Unik
+- Changed licence to BSD
+
+* Tue Jun 29 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Changed spec file for unik-olsrd-0.4.5
+- Remover ROOT-prefix patch as INSTALL_PREFIX is added to Makefile in 0.4.5
+- Added INSTALL_PREFIX patch for front-end/Makefile
+- Included plugins dot_draw and secure
+- Added documentation for the plugins dyn_gw, powerinfo, dot_draw and secure
+
+* Tue May 25 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Changed spec file for unik-olsrd-0.4.4
+- Added man-page for olsrd
+- Removed documentation olsrd-plugin-howto.pdf as it is no longer part of source package
+
+* Tue Mar 02 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Changed spec file for unik-olsrd-0.4.3
+- Added OLSRD plugins olsrd_dyn_gw and olsrd_power to package
+- Added documentation olsrd-plugin-howto.pdf
+
+* Tue Mar 02 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Renamed package from uolsrd to unik-olsrd to use the same name as the .deb-package
+- Start olsrd daemon with option "-d 0" to start without debugging and in daemon mode
+  even if debugging is enabled in olsrd.conf.
+
+* Mon Mar 01 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Included init-script to start uolsrd daemon (installs as %{_initrddir}/uolsrd).
+
+* Wed Feb 25 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Changed Group from Applications/System to System Environment/Daemons.
+- Included olsrd-gui (forgotten in first release)
+- Renamed spec file from unik-olsrd-0.4.0.spec to uolsrd-0.4.0.spec
+
+* Wed Feb 25 2004 Roar Bjørgum Rotvik <roarbr@tihlde.org>
+- Created first version of this spec-file
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/scripts/mk-tarball.sh ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/scripts/mk-tarball.sh
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/scripts/mk-tarball.sh	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/scripts/mk-tarball.sh	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,62 @@
+#!/bin/sh
+# 
+# The olsr.org Optimized Link-State Routing daemon(olsrd)
+# Copyright (c) 2008, Hannes Gredler (hannes@gredler.at)
+# 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.
+# 
+#
+# mk-tarball.sh 
+# Create a release tarball based on the current VERS variable in the Makefile.
+#
+
+# first determine the tarball name
+NAME=`grep -E "^VERS" ../Makefile | sed 's/^VERS..../olsrd-/;s/ *$//'`
+#empty the directory in case it exists already
+rm -rf /tmp/$NAME
+mkdir /tmp/$NAME
+# clean stuff up first
+cd ..;make uberclean
+# sync the stuff to a working directory
+rsync -a . /tmp/$NAME/ --exclude=.hg* --exclude=*.rej --delete
+cd /tmp/
+echo "### creating /tmp/$NAME.tar.gz"
+tar -czf /tmp/$NAME.tar.gz $NAME
+md5sum /tmp/$NAME.tar.gz
+echo "### creating /tmp/$NAME.tar.bz2"
+tar -cjf /tmp/$NAME.tar.bz2 $NAME
+md5sum /tmp/$NAME.tar.bz2
+#clean up
+rm -rf /tmp/$NAME
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/apm.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/apm.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/apm.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/apm.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,73 @@
+/*
+ * 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 _OLSR_APM
+#define _OLSR_APM
+
+/*
+ * Interface to OS dependent power management information
+ */
+
+#define OLSR_BATTERY_POWERED  0
+#define OLSR_AC_POWERED       1
+
+struct olsr_apm_info
+{
+  int ac_line_status;
+  int battery_percentage;
+  int battery_time_left; /* Time left in minutes */
+};
+
+
+int apm_init(void);
+
+void apm_printinfo(struct olsr_apm_info *);
+
+/* 
+ * This function should return 0 if no powerinfo
+ * is available. If returning 1 the function must
+ * fill the provided olsr_apm_info struct with
+ * the current power status.
+ */
+
+int apm_read(struct olsr_apm_info *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/bsd/apm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/bsd/apm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/bsd/apm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/bsd/apm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,58 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "apm.h"
+#include "defs.h"
+#include <stdio.h>
+#include <string.h>
+
+int apm_init(void)
+{
+  return -1;
+}
+
+void apm_printinfo(struct olsr_apm_info *ApmInfo __attribute__((unused)))
+{
+}
+
+int apm_read(struct olsr_apm_info *ApmInfo __attribute__((unused)))
+{
+  return -1;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/bsd/kernel_routes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/bsd/kernel_routes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/bsd/kernel_routes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/bsd/kernel_routes.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,406 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "kernel_routes.h"
+#include "olsr.h"
+#include "defs.h"
+#include "process_routes.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+
+#include <net/if_dl.h>
+#include <ifaddrs.h>
+
+#ifdef _WRS_KERNEL
+#include <wrn/coreip/net/route.h>
+#include <m2Lib.h>
+#define OLSR_PID taskIdSelf ()
+#else
+#define OLSR_PID getpid ()
+#endif
+
+static unsigned int seq = 0;
+
+/*
+ * Sends an add or delete message via the routing socket.
+ * The message consists of:
+ *  - a header i.e. struct rt_msghdr
+ *  - 0-8 socket address structures
+ */
+static int
+add_del_route(const struct rt_entry *rt, int add)
+{
+  struct rt_msghdr *rtm;	       /* message to configure a route */
+                                       /* contains data to be written to the
+                                          routing socket */
+  unsigned char buff[512];
+  unsigned char *walker;	       /* points within the buffer */
+  struct sockaddr_in sin;	       /* internet style sockaddr */
+  struct sockaddr_dl *sdl;	       /* link level sockaddr */
+  struct ifaddrs *addrs;
+  struct ifaddrs *awalker;
+  const struct rt_nexthop *nexthop;
+  union olsr_ip_addr mask;	       /* netmask as ip address */
+  int sin_size, sdl_size;              /* size of addresses - e.g. destination
+                                          (payload of the message) */
+  int len;                             /* message size written to routing socket */
+
+  if (add) {
+    OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
+  } else {
+    OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
+  }
+
+  memset(buff, 0, sizeof(buff));
+  memset(&sin, 0, sizeof(sin));
+
+  sin.sin_len = sizeof(sin);
+  sin.sin_family = AF_INET;
+
+  sin_size = 1 + ((sizeof(struct sockaddr_in) - 1) | 3);
+  sdl_size = 1 + ((sizeof(struct sockaddr_dl) - 1) | 3);
+
+  /**********************************************************************
+   *                  FILL THE ROUTING MESSAGE HEADER
+   **********************************************************************/
+
+  /* position header to the beginning of the buffer */
+  rtm = (struct rt_msghdr *)buff;
+
+  rtm->rtm_version = RTM_VERSION;
+  rtm->rtm_type = add ? RTM_ADD : RTM_DELETE;
+  rtm->rtm_index = 0;		/* is ignored in outgoing messages */
+  /* RTF_UP [and RTF_HOST and/or RTF_GATEWAY] */
+  rtm->rtm_flags = olsr_rt_flags(rt);
+  rtm->rtm_pid = OLSR_PID;
+  rtm->rtm_seq = ++seq;
+
+  /* walk to the end of the header */
+  walker = buff + sizeof(struct rt_msghdr);
+
+  /**********************************************************************
+   *                  SET  DESTINATION OF THE ROUTE
+   **********************************************************************/
+
+  rtm->rtm_addrs = RTA_DST;	/* part of the header */
+
+  sin.sin_addr = rt->rt_dst.prefix.v4;
+  OLSR_PRINTF(8, "\t- Destination of the route: %s\n", inet_ntoa(sin.sin_addr));
+
+  /* change proto or tos here */
+#ifdef CODE_IS_FIXED_ON_FBSD
+  OLSR_PRINTF(8, "\t- Setting Protocol: 0\n");
+  ((struct sockaddr_rt *)(&sin))->srt_proto = 0;
+  OLSR_PRINTF(8, "\t- Setting TOS: 0\n");
+  ((struct sockaddr_rt *)(&sin))->srt_tos = 0;
+#endif
+
+  memcpy(walker, &sin, sizeof(sin));
+  walker += sin_size;
+
+  /**********************************************************************
+   *                  SET GATEWAY OF THE ROUTE
+   **********************************************************************/
+
+  if (add || (rtm->rtm_addrs & RTF_GATEWAY)) {
+    rtm->rtm_addrs |= RTA_GATEWAY;	/* part of the header */
+    nexthop = olsr_get_nh(rt);
+
+    if ((rtm->rtm_flags & RTF_GATEWAY)) {	/* GATEWAY */
+      sin.sin_addr = nexthop->gateway.v4;
+
+      memcpy(walker, &sin, sizeof(sin));
+      walker += sin_size;
+
+      OLSR_PRINTF(8, "\t- Gateway of the route: %s\n", inet_ntoa(sin.sin_addr));
+    }
+    /* NO GATEWAY - destination is directly reachable */
+    else {
+      rtm->rtm_flags |= RTF_CLONING;	/* part of the header! */
+
+      /*
+       * Host is directly reachable, so add the output interface MAC address.
+       */
+      if (getifaddrs(&addrs)) {
+	fprintf(stderr, "\ngetifaddrs() failed\n");
+	return -1;
+      }
+
+      for (awalker = addrs; awalker != NULL; awalker = awalker->ifa_next)
+	if (awalker->ifa_addr->sa_family == AF_LINK &&
+	    strcmp(awalker->ifa_name,
+		   if_ifwithindex_name(nexthop->iif_index)) == 0)
+	  break;
+
+      if (awalker == NULL) {
+	fprintf(stderr, "\nInterface %s not found\n",
+		if_ifwithindex_name(nexthop->iif_index));
+	freeifaddrs(addrs);
+	return -1;
+      }
+
+      /* sdl is "struct sockaddr_dl" */
+      sdl = (struct sockaddr_dl *)awalker->ifa_addr;
+#ifdef DEBUG
+      OLSR_PRINTF(8,"\t- Link layer address of the non gateway route: %s\n",
+                  LLADDR(sdl));
+#endif
+
+      memcpy(walker, sdl, sdl->sdl_len);
+      walker += sdl_size;
+
+      freeifaddrs(addrs);
+    }
+  } else {
+    /* Route with no gateway is deleted */
+  }
+
+  /**********************************************************************
+   *                         SET  NETMASK
+   **********************************************************************/
+
+  if ((rtm->rtm_flags & RTF_HOST)) {
+    OLSR_PRINTF(8, "\t- No netmask needed for a host route.\n");
+  } else {			/* NO! hoste route */
+
+    rtm->rtm_addrs |= RTA_NETMASK; /* part of the header */
+
+    if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
+      return -1;
+    }
+    sin.sin_addr = mask.v4;
+
+    memcpy(walker, &sin, sizeof(sin));
+    walker += sin_size;
+
+    OLSR_PRINTF(8, "\t- Netmask of the route: %s\n", inet_ntoa(sin.sin_addr));
+  }
+
+  /**********************************************************************
+   *           WRITE CONFIGURATION MESSAGE TO THE ROUTING SOCKET
+   **********************************************************************/
+
+  rtm->rtm_msglen = (unsigned short)(walker - buff);
+
+  len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
+  OLSR_PRINTF(8, "\nWrote %d bytes to rts socket (FD=%d)\n", len,
+	      olsr_cnf->rts);
+
+  if (0 != rtm->rtm_errno || len < rtm->rtm_msglen) {
+    fprintf(stderr,
+	    "\nCannot write to routing socket: (rtm_errno= 0x%x) (last error message: %s)\n",
+	    rtm->rtm_errno, strerror(errno));
+  }
+
+  OLSR_PRINTF(8,
+	      "\nWriting the following information to routing socket (message header):"
+	      "\n\trtm_msglen: %u" "\n\trtm_version: %u" "\n\trtm_type: %u"
+	      "\n\trtm_index: %u" "\n\trtm_flags: 0x%x" "\n\trtm_addrs: %u"
+	      "\n\trtm_pid: 0x%x" "\n\trtm_seq: %u" "\n\trtm_errno: 0x%x"
+	      "\n\trtm_use %u" "\n\trtm_inits: %u\n",
+	      (unsigned int)rtm->rtm_msglen, (unsigned int)rtm->rtm_version,
+	      (unsigned int)rtm->rtm_type, (unsigned int)rtm->rtm_index,
+	      (unsigned int)rtm->rtm_flags, (unsigned int)rtm->rtm_addrs,
+	      (unsigned int)rtm->rtm_pid, (unsigned int)rtm->rtm_seq,
+	      (unsigned int)rtm->rtm_errno, (unsigned int)rtm->rtm_use,
+	      (unsigned int)rtm->rtm_inits);
+
+  return 0;
+}
+
+int
+olsr_ioctl_add_route(const struct rt_entry *rt)
+{
+  return add_del_route(rt, 1);
+}
+
+int
+olsr_ioctl_del_route(const struct rt_entry *rt)
+{
+  return add_del_route(rt, 0);
+}
+
+static int
+add_del_route6(const struct rt_entry *rt, int add)
+{
+  struct rt_msghdr *rtm;
+  unsigned char buff[512];
+  unsigned char *walker;
+  struct sockaddr_in6 sin6;
+  struct sockaddr_dl sdl;
+  const struct rt_nexthop *nexthop;
+  int step, step_dl;
+  int len;
+
+  if (add) {
+    OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
+  } else {
+    OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
+  }
+
+  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 = olsr_rt_flags(rt);
+  rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
+  rtm->rtm_seq = ++seq;
+
+  walker = buff + sizeof(struct rt_msghdr);
+
+  memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6,
+	 sizeof(struct in6_addr));
+
+  memcpy(walker, &sin6, sizeof(sin6));
+  walker += step;
+
+  nexthop = olsr_get_nh(rt);
+  if ((rtm->rtm_flags & RTF_GATEWAY) != 0) {
+    memcpy(&sin6.sin6_addr.s6_addr, &nexthop->gateway.v6,
+	   sizeof(struct in6_addr));
+
+    memset(&sin6.sin6_addr.s6_addr, 0, 8);
+    sin6.sin6_addr.s6_addr[0] = 0xfe;
+    sin6.sin6_addr.s6_addr[1] = 0x80;
+    sin6.sin6_scope_id = nexthop->iif_index;
+#ifdef __KAME__
+    *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
+    sin6.sin6_scope_id = 0;
+#endif
+    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, &rt->rt_dst.prefix.v6,
+	   sizeof(struct in6_addr));
+    memset(&sin6.sin6_addr.s6_addr, 0, 8);
+    sin6.sin6_addr.s6_addr[0] = 0xfe;
+    sin6.sin6_addr.s6_addr[1] = 0x80;
+    sin6.sin6_scope_id = nexthop->iif_index;
+#ifdef __KAME__
+    *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
+    sin6.sin6_scope_id = 0;
+#endif
+
+    memcpy(walker, &sin6, sizeof(sin6));
+    walker += step;
+    rtm->rtm_flags |= RTF_GATEWAY;
+  }
+
+  if ((rtm->rtm_flags & RTF_HOST) == 0) {
+    olsr_prefix_to_netmask((union olsr_ip_addr *)&sin6.sin6_addr,
+			   rt->rt_dst.prefix_len);
+    memcpy(walker, &sin6, sizeof(sin6));
+    walker += step;
+    rtm->rtm_addrs |= RTA_NETMASK;
+  }
+
+  rtm->rtm_msglen = (unsigned short)(walker - buff);
+
+  len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
+  if (len < 0 && !(errno == EEXIST || errno == ESRCH))
+    fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
+
+  /* If we get an EEXIST error while adding, delete and retry. */
+  if (len < 0 && errno == EEXIST && rtm->rtm_type == RTM_ADD) {
+    struct rt_msghdr *drtm;
+    unsigned char dbuff[512];
+
+    memset(dbuff, 0, sizeof(dbuff));
+    drtm = (struct rt_msghdr *)dbuff;
+    drtm->rtm_version = RTM_VERSION;
+    drtm->rtm_type = RTM_DELETE;
+    drtm->rtm_addrs = RTA_DST;
+    drtm->rtm_index = 0;
+    drtm->rtm_flags = olsr_rt_flags(rt);
+    drtm->rtm_seq = ++seq;
+
+    walker = dbuff + sizeof(struct rt_msghdr);
+    memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6,
+	   sizeof(struct in6_addr));
+    memcpy(walker, &sin6, sizeof(sin6));
+    walker += step;
+    drtm->rtm_msglen = (unsigned short)(walker - dbuff);
+    len = write(olsr_cnf->rts, dbuff, drtm->rtm_msglen);
+    if (len < 0)
+      fprintf(stderr, "cannot delete route: %s\n", strerror(errno));
+    rtm->rtm_seq = ++seq;
+    len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
+    if (len < 0)
+      fprintf(stderr, "still cannot add route: %s\n", strerror(errno));
+  }
+
+  return 0;
+}
+
+int
+olsr_ioctl_add_route6(const struct rt_entry *rt)
+{
+  return add_del_route6(rt, 1);
+}
+
+int
+olsr_ioctl_del_route6(const struct rt_entry *rt)
+{
+  return add_del_route6(rt, 0);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/bsd/net.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/bsd/net.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/bsd/net.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/bsd/net.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,847 @@
+
+/*
+ * 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 "../defs.h"
+#include "../net_os.h"
+#include "../ipcalc.h"
+#include "../parser.h"		/* dnc: needed for call to packet_parser() */
+#include "../olsr_protocol.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#ifdef _WRS_KERNEL
+#include <vxWorks.h>
+#include "wrn/coreip/netinet6/in6_var.h"
+#include <sockLib.h>
+#include <sys/socket.h>
+#include "wrn/coreip/net/ifaddrs.h"
+#include <selectLib.h>
+#include <logLib.h>
+#define syslog(a, b) fdprintf(a, b);
+#else
+#include <sys/param.h>
+#endif
+
+
+#ifdef __NetBSD__
+#include <net/if_ether.h>
+#endif
+
+#ifdef __OpenBSD__
+#include <netinet/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <netinet/icmp6.h>
+#include <netinet6/in6_var.h>	/* For struct in6_ifreq */
+#include <ifaddrs.h>
+#include <sys/uio.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_ioctl.h>
+#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>
+#endif
+#endif
+
+#ifdef __MacOSX__
+#include <ifaddrs.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <netinet/in_var.h>
+#endif
+
+#include <net/if_dl.h>
+#ifdef SPOOF
+#include <libnet.h>
+#endif /* SPOOF */
+
+#if 0
+#define	SIOCGIFGENERIC	_IOWR('i', 58, struct ifreq)	/* generic IF get op */
+#define SIOCGWAVELAN SIOCGIFGENERIC
+#endif
+
+#include <sys/sysctl.h>
+
+static int ignore_redir;
+static int send_redir;
+static int gateway;
+
+static int
+set_sysctl_int(const char *name, int new)
+{
+  int old;
+#if __MacOSX__ || __OpenBSD__
+  size_t len = sizeof(old);
+#else
+  unsigned int len = sizeof(old);
+#endif
+
+#ifdef __OpenBSD__
+  int mib[4];
+
+  /* Set net.inet.ip.forwarding by default. */
+  mib[0] = CTL_NET;
+  mib[1] = PF_INET;
+  mib[2] = IPPROTO_IP;
+  mib[3] = IPCTL_FORWARDING;
+
+  if (!strcmp(name, "net.inet6.ip6.forwarding")) {
+    mib[1] = PF_INET6;
+    mib[2] = IPPROTO_IPV6;
+  } else if (!strcmp(name, "net.inet.icmp.rediraccept")) {
+    mib[2] = IPPROTO_ICMP;
+    mib[3] = ICMPCTL_REDIRACCEPT;
+  } else if (!strcmp(name, "net.inet6.icmp6.rediraccept")) {
+    mib[2] = IPPROTO_ICMPV6;
+    mib[3] = ICMPV6CTL_REDIRACCEPT;
+  } else if (!strcmp(name, "net.inet.ip.redirect")) {
+    mib[3] = IPCTL_SENDREDIRECTS;
+  } else if (!strcmp(name, "net.inet6.ip6.redirect")) {
+    mib[1] = PF_INET6;
+    mib[2] = IPPROTO_IPV6;
+    mib[3] = IPCTL_SENDREDIRECTS;
+  }
+
+  if (sysctl(mib, 4, &old, &len, &new, sizeof(new)) < 0)
+    return -1;
+#else
+
+  if (sysctlbyname((const char *)name, &old, &len, &new, sizeof(new)) < 0)
+    return -1;
+#endif
+
+  return old;
+}
+
+int
+enable_ip_forwarding(int version)
+{
+  const char *name =
+    version == AF_INET ? "net.inet.ip.forwarding" : "net.inet6.ip6.forwarding";
+
+  gateway = set_sysctl_int(name, 1);
+  if (gateway < 0) {
+    fprintf(stderr,
+	    "Cannot enable IP forwarding. Please enable IP forwarding manually."
+            " Continuing in 3 seconds...\n");
+    sleep(3);
+  }
+
+  return 1;
+}
+
+int
+disable_redirects_global(int version)
+{
+  const char *name;
+
+  /* do not accept ICMP redirects */
+
+#ifdef __OpenBSD__
+  if (version == AF_INET)
+    name = "net.inet.icmp.rediraccept";
+  else
+    name = "net.inet6.icmp6.rediraccept";
+
+  ignore_redir = set_sysctl_int(name, 0);
+#elif defined __FreeBSD__ || defined __MacOSX__
+  if (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 (version == AF_INET)
+    name = "net.inet.icmp.drop_redirect";
+  else
+    name = "net.inet6.icmp6.drop_redirect";
+
+  ignore_redir = set_sysctl_int(name, 1);
+#endif
+
+  if (ignore_redir < 0) {
+    fprintf(stderr,
+	    "Cannot disable incoming ICMP redirect messages. "
+            "Please disable them manually. Continuing in 3 seconds...\n");
+    sleep(3);
+  }
+
+  /* do not send ICMP redirects */
+
+  if (version == AF_INET)
+    name = "net.inet.ip.redirect";
+  else
+    name = "net.inet6.ip6.redirect";
+
+  send_redir = set_sysctl_int(name, 0);
+  if (send_redir < 0) {
+    fprintf(stderr,
+	    "Cannot disable outgoing ICMP redirect messages. "
+            "Please disable them manually. Continuing in 3 seconds...\n");
+    sleep(3);
+  }
+
+  return 1;
+}
+
+int
+disable_redirects(const char *if_name
+		  __attribute__ ((unused)), struct interface *iface
+		  __attribute__ ((unused)), int version
+		  __attribute__ ((unused)))
+{
+  /*
+   *  this function gets called for each interface olsrd uses; however,
+   * FreeBSD can only globally control ICMP redirects, and not on a
+   * per-interface basis; hence, only disable ICMP redirects in the "global"
+   * function
+   */
+  return 1;
+}
+
+int
+deactivate_spoof(const char *if_name
+		 __attribute__ ((unused)), struct interface *iface
+		 __attribute__ ((unused)), int version __attribute__ ((unused)))
+{
+  return 1;
+}
+
+int
+restore_settings(int version)
+{
+  /* reset IP forwarding */
+  const char *name =
+    version == AF_INET ? "net.inet.ip.forwarding" : "net.inet6.ip6.forwarding";
+
+  set_sysctl_int(name, gateway);
+
+  /* reset incoming ICMP redirects */
+
+#ifdef __OpenBSD__
+  name =
+    version ==
+    AF_INET ? "net.inet.icmp.rediraccept" : "net.inet6.icmp6.rediraccept";
+#elif defined __FreeBSD__ || defined __MacOSX__
+  name =
+    version ==
+    AF_INET ? "net.inet.icmp.drop_redirect" : "net.inet6.icmp6.rediraccept";
+#else
+  name =
+    version ==
+    AF_INET ? "net.inet.icmp.drop_redirect" : "net.inet6.icmp6.drop_redirect";
+#endif
+  set_sysctl_int(name, ignore_redir);
+
+  /* reset outgoing ICMP redirects */
+  name = version == AF_INET ? "net.inet.ip.redirect" : "net.inet6.ip6.redirect";
+  set_sysctl_int(name, send_redir);
+  return 1;
+}
+
+
+/**
+ *Creates a nonblocking broadcast socket.
+ *@param sa sockaddr struct. Used for bind(2).
+ *@return the FD of the socket or -1 on error.
+ */
+int
+gethemusocket(struct sockaddr_in *pin)
+{
+  int sock, on = 1;
+
+  OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
+
+
+  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+    perror("hcsocket");
+    syslog(LOG_ERR, "hcsocket: %m");
+    return (-1);
+  }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) {
+    perror("SO_REUSEADDR failed");
+    close(sock);
+    return (-1);
+  }
+  /* connect to PORT on HOST */
+  if (connect(sock, (struct sockaddr *)pin, sizeof(*pin)) < 0) {
+    printf("FAILED\n");
+    fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+    printf("connection refused\n");
+    close(sock);
+    return (-1);
+  }
+
+  printf("OK\n");
+
+  /* Keep TCP socket blocking */
+  return (sock);
+}
+
+
+int
+getsocket(int bufspace, char *int_name __attribute__ ((unused)))
+{
+  struct sockaddr_in sin;
+  int on;
+  int sock = socket(AF_INET, SOCK_DGRAM, 0);
+  if (sock < 0) {
+    perror("socket");
+    syslog(LOG_ERR, "socket: %m");
+    return -1;
+  }
+
+  on = 1;
+  if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) {
+    perror("setsockopt");
+    syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+    close(sock);
+    return -1;
+  }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) {
+    perror("SO_REUSEADDR failed");
+    close(sock);
+    return -1;
+  }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on)) < 0) {
+    perror("SO_REUSEPORT failed");
+    close(sock);
+    return -1;
+  }
+
+  if (setsockopt(sock, IPPROTO_IP, IP_RECVIF, (char *)&on, sizeof(on)) < 0) {
+    perror("IP_RECVIF failed");
+    close(sock);
+    return -1;
+  }
+
+  for (on = bufspace;; on -= 1024) {
+    if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&on, sizeof(on)) == 0)
+      break;
+    if (on <= 8 * 1024) {
+      perror("setsockopt");
+      syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+      break;
+    }
+  }
+
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(OLSRPORT);
+  sin.sin_addr.s_addr = INADDR_ANY;
+  if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+    perror("bind");
+    syslog(LOG_ERR, "bind: %m");
+    close(sock);
+    return -1;
+  }
+
+  on = fcntl(sock, F_GETFL);
+  if (on == -1) {
+    syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
+  } else {
+    if (fcntl(sock, F_SETFL, on | O_NONBLOCK) == -1) {
+      syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
+    }
+  }
+  return (sock);
+}
+
+int
+getsocket6(int bufspace, char *int_name __attribute__ ((unused)))
+{
+  struct sockaddr_in6 sin;
+  int on;
+  int sock = socket(AF_INET6, SOCK_DGRAM, 0);
+
+  if (sock < 0) {
+    perror("socket");
+    syslog(LOG_ERR, "socket: %m");
+    return -1;
+  }
+
+  for (on = bufspace;; on -= 1024) {
+    if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&on, sizeof(on)) == 0)
+      break;
+    if (on <= 8 * 1024) {
+      perror("setsockopt");
+      syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+      break;
+    }
+  }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) {
+    perror("SO_REUSEADDR failed");
+    close(sock);
+    return -1;
+  }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on)) < 0) {
+    perror("SO_REUSEPORT failed");
+    close(sock);
+    return -1;
+  }
+#ifdef IPV6_RECVPKTINFO
+  if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on, sizeof(on))
+      < 0) {
+    perror("IPV6_RECVPKTINFO failed");
+    close(sock);
+    return -1;
+  }
+#elif defined IPV6_PKTINFO
+  if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on, sizeof(on)) < 0) {
+    perror("IPV6_PKTINFO failed");
+    close(sock);
+    return -1;
+  }
+#endif
+
+  memset(&sin, 0, sizeof(sin));
+  sin.sin6_family = AF_INET6;
+  sin.sin6_port = htons(OLSRPORT);
+  if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+    perror("bind");
+    syslog(LOG_ERR, "bind: %m");
+    close(sock);
+    return -1;
+  }
+
+  on = fcntl(sock, F_GETFL);
+  if (on == -1) {
+    syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
+  } else {
+    if (fcntl(sock, F_SETFL, on | O_NONBLOCK) == -1) {
+      syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
+    }
+  }
+  return sock;
+}
+
+
+
+int
+join_mcast(struct interface *ifs, int sock)
+{
+  /* See netinet6/in6.h */
+  struct ipaddr_str addrstr;
+  struct ipv6_mreq mcastreq;
+
+  mcastreq.ipv6mr_multiaddr = ifs->int6_multaddr.sin6_addr;
+  mcastreq.ipv6mr_interface = ifs->if_index;
+
+  OLSR_PRINTF(3, "Interface %s joining multicast %s...", ifs->int_name,
+	      olsr_ip_to_string(&addrstr,
+				(union olsr_ip_addr *)&ifs->int6_multaddr.
+				sin6_addr));
+
+  /* rfc 3493 */
+#ifdef IPV6_JOIN_GROUP
+  /* Join reciever group */
+  if (setsockopt(sock,
+		 IPPROTO_IPV6,
+		 IPV6_JOIN_GROUP, (char *)&mcastreq, sizeof(struct ipv6_mreq))
+      < 0)
+#else /* rfc 2133, obsoleted */
+  /* Join receiver group */
+  if (setsockopt(sock,
+		 IPPROTO_IPV6,
+		 IPV6_ADD_MEMBERSHIP,
+		 (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0)
+#endif
+  {
+    perror("Join multicast send");
+    return -1;
+  }
+
+
+  if (setsockopt(sock,
+		 IPPROTO_IPV6,
+		 IPV6_MULTICAST_IF,
+		 (char *)&mcastreq.ipv6mr_interface,
+		 sizeof(mcastreq.ipv6mr_interface)) < 0) {
+    perror("Set multicast if");
+    return -1;
+  }
+
+
+  OLSR_PRINTF(3, "OK\n");
+  return 0;
+}
+
+
+
+
+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;
+      strscpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
+      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, (int)&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;
+}
+
+
+
+
+/**
+ * Wrapper for sendto(2)
+ */
+
+#ifdef SPOOF
+static u_int16_t ip_id = 0;
+#endif /* SPOOF */
+
+ssize_t
+olsr_sendto(int s,
+	    const void *buf,
+	    size_t len,
+	    int flags __attribute__ ((unused)),
+	    const struct sockaddr *to, socklen_t tolen)
+{
+#ifdef SPOOF
+  /* IPv4 for now! */
+
+  libnet_t *context;
+  char errbuf[LIBNET_ERRBUF_SIZE];
+  libnet_ptag_t udp_tag, ip_tag, ether_tag;
+  unsigned char enet_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+  int status;
+  struct sockaddr_in *to_in = (struct sockaddr_in *)to;
+  u_int32_t destip;
+  struct interface *iface;
+
+  udp_tag = ip_tag = ether_tag = 0;
+  destip = to_in->sin_addr.s_addr;
+  iface = if_ifwithsock(s);
+
+  /* initialize libnet */
+  context = libnet_init(LIBNET_LINK, iface->int_name, errbuf);
+  if (context == NULL) {
+    OLSR_PRINTF(1, "libnet init: %s\n", libnet_geterror(context));
+    return (0);
+  }
+
+  /* initialize IP ID field if necessary */
+  if (ip_id == 0) {
+    ip_id = (u_int16_t) (arc4random() & 0xffff);
+  }
+
+  udp_tag = libnet_build_udp(698,	/* src port */
+			     698,	/* dest port */
+			     LIBNET_UDP_H + len,	/* length */
+			     0,	/* checksum */
+			     buf,	/* payload */
+			     len,	/* payload size */
+			     context,	/* context */
+			     udp_tag);	/* pblock */
+  if (udp_tag == -1) {
+    OLSR_PRINTF(1, "libnet UDP header: %s\n", libnet_geterror(context));
+    return (0);
+  }
+
+  ip_tag = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_UDP_H + len,	/* len */
+			     0,	/* TOS */
+			     ip_id++,	/* IP id */
+			     0,	/* IP frag */
+			     1,	/* IP TTL */
+			     IPPROTO_UDP,	/* protocol */
+			     0,	/* checksum */
+			     libnet_get_ipaddr4(context),	/* src IP */
+			     destip,	/* dest IP */
+			     NULL,	/* payload */
+			     0,	/* payload len */
+			     context,	/* context */
+			     ip_tag);	/* pblock */
+  if (ip_tag == -1) {
+    OLSR_PRINTF(1, "libnet IP header: %s\n", libnet_geterror(context));
+    return (0);
+  }
+
+  ether_tag = libnet_build_ethernet(enet_broadcast,	/* ethernet dest */
+				    libnet_get_hwaddr(context),	/* ethernet source */
+				    ETHERTYPE_IP,	/* protocol type */
+				    NULL,	/* payload */
+				    0,	/* payload size */
+				    context,	/* libnet handle */
+				    ether_tag);	/* pblock tag */
+  if (ether_tag == -1) {
+    OLSR_PRINTF(1, "libnet ethernet header: %s\n", libnet_geterror(context));
+    return (0);
+  }
+
+  status = libnet_write(context);
+  if (status == -1) {
+    OLSR_PRINTF(1, "libnet packet write: %s\n", libnet_geterror(context));
+    return (0);
+  }
+
+  libnet_destroy(context);
+
+  return (len);
+
+#else
+  return sendto(s, buf, len, flags, (const struct sockaddr *)to,
+		tolen);
+#endif
+}
+
+
+/**
+ * Wrapper for recvfrom(2)
+ */
+
+ssize_t
+olsr_recvfrom(int s,
+	      void *buf,
+	      size_t len,
+	      int flags __attribute__ ((unused)),
+	      struct sockaddr *from, socklen_t * fromlen)
+{
+  struct msghdr mhdr;
+  struct iovec iov;
+  union {
+    struct cmsghdr cmsg;
+    unsigned char chdr[4096];
+  } cmu;
+  struct cmsghdr *cm;
+  struct sockaddr_dl *sdl;
+  struct sockaddr_in *sin = (struct sockaddr_in *)from;
+  struct sockaddr_in6 *sin6;
+  struct in6_addr *iaddr6;
+  struct in6_pktinfo *pkti;
+  struct interface *ifc;
+  char addrstr[INET6_ADDRSTRLEN];
+  char iname[IFNAMSIZ];
+  int count;
+
+  memset(&mhdr, 0, sizeof(mhdr));
+  memset(&iov, 0, sizeof(iov));
+
+  mhdr.msg_name = (caddr_t) from;
+  mhdr.msg_namelen = *fromlen;
+  mhdr.msg_iov = &iov;
+  mhdr.msg_iovlen = 1;
+  mhdr.msg_control = (caddr_t) & cmu;
+  mhdr.msg_controllen = sizeof(cmu);
+
+  iov.iov_len = len;
+  iov.iov_base = buf;
+
+  count = recvmsg(s, &mhdr, MSG_DONTWAIT);
+  if (count <= 0) {
+    return (count);
+  }
+
+  /* this needs to get communicated back to caller */
+  *fromlen = mhdr.msg_namelen;
+  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 = &cmu.cmsg;
+    sdl = (struct sockaddr_dl *)CMSG_DATA(cm);
+    memset(iname, 0, 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, inet_ntop(olsr_cnf->ip_version,
+			       olsr_cnf->ip_version ==
+			       AF_INET6 ? (char *)&sin6->
+			       sin6_addr : (char *)&sin->sin_addr, addrstr,
+			       sizeof(addrstr)), ifc->int_name, iname);
+
+  if (strcmp(ifc->int_name, iname) != 0) {
+    return (0);
+  }
+
+  return (count);
+}
+
+/**
+ * Wrapper for select(2)
+ */
+
+int
+olsr_select(int nfds,
+	    fd_set * readfds,
+	    fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
+{
+  return select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+
+int
+check_wireless_interface(char *ifname)
+{
+#if defined __FreeBSD__ &&  !defined FBSD_NO_80211
+
+/* From FreeBSD ifconfig/ifieee80211.c ieee80211_status() */
+  struct ieee80211req ireq;
+  u_int8_t data[32];
+
+  memset(&ireq, 0, sizeof(ireq));
+  strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
+  ireq.i_data = &data;
+  ireq.i_type = IEEE80211_IOC_SSID;
+  ireq.i_val = -1;
+  return (ioctl(olsr_cnf->ioctl_s, SIOCG80211, &ireq) >= 0) ? 1 : 0;
+#elif defined __OpenBSD__
+  struct ieee80211_nodereq nr;
+  bzero(&nr, sizeof(nr));
+  strlcpy(nr.nr_ifname, ifname, sizeof(nr.nr_ifname));
+  return (ioctl(olsr_cnf->ioctl_s, SIOCG80211FLAGS, &nr) >= 0) ? 1 : 0;
+#else
+  ifname = NULL;		/* squelsh compiler warning */
+  return 0;
+#endif
+}
+
+#include <sys/sockio.h>
+
+int
+calculate_if_metric(char *ifname)
+{
+  if (check_wireless_interface(ifname)) {
+    /* Wireless */
+    return 1;
+  } else {
+    /* Ethernet */
+#if 0
+    /* Andreas: Perhaps SIOCGIFMEDIA is the way to do this? */
+    struct ifmediareq ifm;
+
+    memset(&ifm, 0, sizeof(ifm));
+    strlcpy(ifm.ifm_name, ifname, sizeof(ifm.ifm_name));
+
+    if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMEDIA, &ifm) < 0) {
+      OLSR_PRINTF(1, "Error SIOCGIFMEDIA(%s)\n", ifm.ifm_name);
+      return WEIGHT_ETHERNET_DEFAULT;
+    }
+
+    OLSR_PRINTF(1, "%s: STATUS 0x%08x\n", ifm.ifm_name, ifm.ifm_status);
+#endif
+    return WEIGHT_ETHERNET_DEFAULT;
+  }
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/build_msg.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/build_msg.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/build_msg.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/build_msg.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1222 @@
+/*
+ * 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 "build_msg.h"
+#include "ipcalc.h"
+#include "olsr.h"
+#include "log.h"
+#include "mantissa.h"
+#include "net_olsr.h"
+
+#define BMSG_DBGLVL 5
+
+#define OLSR_IPV4_HDRSIZE          12
+#define OLSR_IPV6_HDRSIZE          24
+
+#define OLSR_HELLO_IPV4_HDRSIZE    (OLSR_IPV4_HDRSIZE + 4)   
+#define OLSR_HELLO_IPV6_HDRSIZE    (OLSR_IPV6_HDRSIZE + 4)
+#define OLSR_TC_IPV4_HDRSIZE       (OLSR_IPV4_HDRSIZE + 4)
+#define OLSR_TC_IPV6_HDRSIZE       (OLSR_IPV6_HDRSIZE + 4)
+#define OLSR_MID_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
+#define OLSR_MID_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
+#define OLSR_HNA_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
+#define OLSR_HNA_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
+
+static void
+check_buffspace(int msgsize, int buffsize, const char *type);
+
+/* All these functions share this buffer */
+
+static olsr_u8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
+
+static clock_t send_empty_tc; /* TC empty message sending */
+
+/* Prototypes for internal functions */
+
+/* IPv4 */
+
+static olsr_bool
+serialize_hello4(struct hello_message *, struct interface *);
+
+static olsr_bool
+serialize_tc4(struct tc_message *, struct interface *);
+
+static olsr_bool
+serialize_mid4(struct interface *);
+
+static olsr_bool
+serialize_hna4(struct interface *);
+
+/* IPv6 */
+
+static olsr_bool
+serialize_hello6(struct hello_message *, struct interface *);
+
+static olsr_bool
+serialize_tc6(struct tc_message *, struct interface *);
+
+static olsr_bool
+serialize_mid6(struct interface *);
+
+static olsr_bool
+serialize_hna6(struct interface *);
+
+/**
+ * Set the timer that controls the generation of
+ * empty TC messages
+ */
+void
+set_empty_tc_timer(clock_t empty_tc_new)
+{
+  send_empty_tc = empty_tc_new;
+}
+
+/**
+ * Get the timer that controls the generation of
+ * empty TC messages
+ */
+clock_t
+get_empty_tc_timer(void)
+{
+  return send_empty_tc;
+}
+
+/**
+ * Generate HELLO packet with the contents of the parameter "message".
+ * If this won't fit in one packet, chop it up into several.
+ * Send the packet if the size of the data contained in the output buffer
+ * reach maxmessagesize. Can generate an empty HELLO packet if the 
+ * neighbor table is empty. 
+ *
+ *
+ *@param message the hello_message struct containing the info
+ *to build the hello message from.
+ *@param ifp the interface to send the message on
+ *
+ *@return nada
+ */
+
+olsr_bool
+queue_hello(struct hello_message *message, struct interface *ifp)
+{
+#ifdef DEBUG
+  OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name);
+#endif
+
+  switch(olsr_cnf->ip_version)
+    {
+    case(AF_INET):
+      return serialize_hello4(message, ifp);
+    case(AF_INET6):
+      return serialize_hello6(message, ifp);
+    }
+  return OLSR_FALSE;
+}
+
+
+/*
+ * Generate TC packet with the contents of the parameter "message".
+ * If this won't fit in one packet, chop it up into several.
+ * Send the packet if the size of the data contained in the output buffer
+ * reach maxmessagesize. 
+ *
+ *@param message the tc_message struct containing the info
+ *to send
+ *@param ifp the interface to send the message on
+ *
+ *@return nada
+ */
+
+olsr_bool
+queue_tc(struct tc_message *message, struct interface *ifp)           
+{
+#ifdef DEBUG
+  OLSR_PRINTF(BMSG_DBGLVL, "Building TC on %s\n-------------------\n", ifp->int_name);
+#endif
+
+  switch(olsr_cnf->ip_version)
+    {
+    case(AF_INET):
+      return serialize_tc4(message, ifp);
+    case(AF_INET6):
+      return serialize_tc6(message, ifp);
+    }
+  return OLSR_FALSE;
+}
+
+
+/**
+ *Build a MID message to the outputbuffer
+ *
+ *<b>NO INTERNAL BUFFER</b>
+ *@param ifn use this interfaces address as main address
+ *@return 1 on success
+ */
+
+olsr_bool
+queue_mid(struct interface *ifp)
+{
+#ifdef DEBUG
+  OLSR_PRINTF(BMSG_DBGLVL, "Building MID on %s\n-------------------\n", ifp->int_name);
+#endif
+
+  switch(olsr_cnf->ip_version)
+    {
+    case(AF_INET):
+      return serialize_mid4(ifp);
+    case(AF_INET6):
+      return serialize_mid6(ifp);
+    }
+  return OLSR_FALSE;
+}
+
+
+/**
+ *Builds a HNA message in the outputbuffer
+ *<b>NB! Not internal packetformat!</b>
+ *
+ *@param ifp the interface to send on
+ *@return nada
+ */
+olsr_bool
+queue_hna(struct interface *ifp)
+{
+#ifdef DEBUG
+  OLSR_PRINTF(BMSG_DBGLVL, "Building HNA on %s\n-------------------\n", ifp->int_name);
+#endif
+
+  switch(olsr_cnf->ip_version)
+    {
+    case(AF_INET):
+      return serialize_hna4(ifp);
+    case(AF_INET6):
+      return serialize_hna6(ifp);
+    }
+  return OLSR_FALSE;
+}
+
+/*
+ * Protocol specific versions
+ */
+
+
+static void
+check_buffspace(int msgsize, int buffsize, const char *type)
+{
+  if(msgsize > buffsize)
+    {
+      OLSR_PRINTF(1, "%s build, outputbuffer to small(%d/%u)!\n", type, msgsize, buffsize);
+      olsr_syslog(OLSR_LOG_ERR, "%s build, outputbuffer to small(%d/%u)!\n", type, msgsize, buffsize);
+      olsr_exit(__func__, EXIT_FAILURE);
+    }
+}
+
+
+/**
+ * IP version 4
+ *
+ *@param message the hello_message struct containing the info
+ *to build the hello message from.
+ *@param ifp the interface to send the message on
+ *
+ *@return nada
+ */
+
+static olsr_bool
+serialize_hello4(struct hello_message *message, struct interface *ifp)
+{
+  olsr_u16_t remainsize, curr_size;
+  struct hello_neighbor *nb;
+  union olsr_message *m;
+  struct hellomsg *h;
+  struct hellinfo *hinfo;
+  union olsr_ip_addr *haddr;
+  int i, j;
+  olsr_bool first_entry;
+
+  if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
+    return OLSR_FALSE;
+
+  remainsize = net_outbuffer_bytes_left(ifp);
+
+  m = (union olsr_message *)msg_buffer;
+
+  curr_size = OLSR_HELLO_IPV4_HDRSIZE;
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  /* Sanity check */
+  check_buffspace(curr_size, remainsize, "HELLO");
+
+  h = &m->v4.message.hello;
+  hinfo = h->hell_info;
+  haddr = (union olsr_ip_addr *)hinfo->neigh_addr;
+  
+  /* Fill message header */
+  m->v4.ttl = message->ttl;
+  m->v4.hopcnt = 0;
+  m->v4.olsr_msgtype = HELLO_MESSAGE;
+  /* Set source(main) addr */
+  m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
+
+  m->v4.olsr_vtime = ifp->valtimes.hello;
+
+  /* Fill HELLO header */
+  h->willingness = message->willingness; 
+  h->htime = reltime_to_me(ifp->hello_etime);
+
+  memset(&h->reserved, 0, sizeof(olsr_u16_t));
+  
+
+  /*
+   *Loops trough all possible neighbor statuses
+   *The negbor list is grouped by status
+   *
+   */
+  /* Nighbor statuses */
+  for (i = 0; i <= MAX_NEIGH; i++) 
+    {
+      /* Link statuses */
+      for(j = 0; j <= MAX_LINK; j++)
+	{
+#ifdef DEBUG
+          struct ipaddr_str buf;
+#endif
+
+	  /* HYSTERESIS - Not adding neighbors with link type HIDE */
+	  
+	  if(j == HIDE_LINK)
+	      continue;
+
+	  first_entry = OLSR_TRUE;
+
+	  /* Looping trough neighbors */
+	  for (nb = message->neighbors; nb != NULL; nb = nb->next) 
+	    {	  
+	      if ((nb->status != i) || (nb->link != j))
+		continue;
+
+#ifdef DEBUG
+	      OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&buf, &nb->address));
+	      OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i);
+#endif
+	      /*
+	       * If there is not enough room left 
+	       * for the data in the outputbuffer
+	       * we must send a partial HELLO and
+	       * continue building the rest of the
+	       * data in a new HELLO message
+	       *
+	       * If this is the first neighbor in 
+	       * a group, we must check for an extra
+	       * 4 bytes
+	       */
+	      if((curr_size + olsr_cnf->ipsize + (first_entry ? 4 : 0)) > remainsize)
+		{
+		  /* Only send partial HELLO if it contains data */
+		  if(curr_size > OLSR_HELLO_IPV4_HDRSIZE)
+		    {
+#ifdef DEBUG
+		      OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+		      /* Complete the headers */
+		      m->v4.seqno = htons(get_msg_seqno());
+		      m->v4.olsr_msgsize = htons(curr_size);
+		      
+		      hinfo->size = htons((char *)haddr - (char *)hinfo);
+		      
+		      /* Send partial packet */
+		      net_outbuffer_push(ifp, msg_buffer, curr_size);
+		      
+		      curr_size = OLSR_HELLO_IPV4_HDRSIZE;
+		      
+		      h = &m->v4.message.hello;
+		      hinfo = h->hell_info;
+		      haddr = (union olsr_ip_addr *)hinfo->neigh_addr;			  
+		      /* Make sure typeheader is added */
+		      first_entry = OLSR_TRUE;
+		    }
+		  
+		  net_output(ifp);			  
+		  /* Reset size and pointers */
+		  remainsize = net_outbuffer_bytes_left(ifp);
+		  
+		  /* Sanity check */
+		  check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2");
+		}
+	      
+	      if (first_entry)
+		{
+		  memset(&hinfo->reserved, 0, sizeof(olsr_u8_t));
+		  /* Set link and status for this group of neighbors (this is the first) */
+		  hinfo->link_code = CREATE_LINK_CODE(i, j);
+		  curr_size += 4; /* HELLO type section header */
+		}
+	      
+	      *haddr = nb->address;
+	      
+	      /* Point to next address */
+	      haddr = (union olsr_ip_addr *)&haddr->v6.s6_addr[4];
+	      curr_size += olsr_cnf->ipsize; /* IP address added */
+
+	      first_entry = OLSR_FALSE;
+	    }
+    
+	  if(!first_entry)
+	    {
+	      hinfo->size = htons((char *)haddr - (char *)hinfo);
+	      hinfo = (struct hellinfo *)((char *)haddr);
+	      haddr = (union olsr_ip_addr *)&hinfo->neigh_addr;
+	    }
+	} /* for j */
+    } /* for i*/
+     
+  m->v4.seqno = htons(get_msg_seqno());
+  m->v4.olsr_msgsize = htons(curr_size);
+  
+  net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+  /* HELLO will always be generated */
+  return OLSR_TRUE;
+}
+
+
+
+
+/**
+ * IP version 6
+ *
+ *@param message the hello_message struct containing the info
+ *to build the hello message from.
+ *@param ifp the interface to send the message on
+ *
+ *@return nada
+ */
+
+
+static olsr_bool
+serialize_hello6(struct hello_message *message, struct interface *ifp)
+{
+  olsr_u16_t remainsize, curr_size;
+  struct hello_neighbor *nb;
+  union olsr_message *m;
+  struct hellomsg6 *h6;
+  struct hellinfo6 *hinfo6;
+  union olsr_ip_addr *haddr;
+  int i, j;
+  olsr_bool first_entry;
+
+  if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
+    return OLSR_FALSE;
+
+  remainsize = net_outbuffer_bytes_left(ifp);
+  m = (union olsr_message *)msg_buffer;
+
+  curr_size = OLSR_HELLO_IPV6_HDRSIZE; /* OLSR message header */
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO");
+
+  h6 = &m->v6.message.hello;
+  hinfo6 = h6->hell_info;
+  haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
+
+
+  /* Fill message header */
+  m->v6.ttl = message->ttl;
+  m->v6.hopcnt = 0;
+  /* Set source(main) addr */
+  m->v6.originator = olsr_cnf->main_addr.v6;
+  m->v6.olsr_msgtype = HELLO_MESSAGE;
+
+  m->v6.olsr_vtime = ifp->valtimes.hello;
+  
+  /* Fill packet header */
+  h6->willingness = message->willingness; 
+  h6->htime = reltime_to_me(ifp->hello_etime);
+  memset(&h6->reserved, 0, sizeof(olsr_u16_t));
+
+  /*
+   *Loops trough all possible neighbor statuses
+   *The negbor list is grouped by status
+   */
+
+  for (i = 0; i <= MAX_NEIGH; i++) 
+    {
+      for(j = 0; j <= MAX_LINK; j++)
+	{
+#ifdef DEBUG
+          struct ipaddr_str buf;
+#endif
+	  first_entry = OLSR_TRUE;
+	  	  
+	  /*
+	   *Looping trough neighbors
+	   */
+	  for (nb = message->neighbors; nb != NULL; nb = nb->next) 
+	    {	      
+	      if ((nb->status != i) || (nb->link != j))
+		continue;
+
+#ifdef DEBUG
+	      OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&buf, &nb->address));
+	      OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i);
+#endif
+
+
+	      /*
+	       * If there is not enough room left 
+	       * for the data in the outputbuffer
+	       * we must send a partial HELLO and
+	       * continue building the rest of the
+	       * data in a new HELLO message
+	       *
+	       * If this is the first neighbor in 
+	       * a group, we must check for an extra
+	       * 4 bytes
+	       */
+	      if((curr_size + olsr_cnf->ipsize + (first_entry ? 4 : 0)) > remainsize)
+		{
+		  /* Only send partial HELLO if it contains data */
+		  if(curr_size > OLSR_HELLO_IPV6_HDRSIZE)
+		    {
+#ifdef DEBUG
+		      OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+		      /* Complete the headers */
+		      m->v6.seqno = htons(get_msg_seqno());
+		      m->v6.olsr_msgsize = htons(curr_size);
+			  
+		      hinfo6->size = (char *)haddr - (char *)hinfo6;
+		      hinfo6->size = htons(hinfo6->size);
+			  
+		      /* Send partial packet */
+		      net_outbuffer_push(ifp, msg_buffer, curr_size);
+		      curr_size = OLSR_HELLO_IPV6_HDRSIZE;
+			  
+		      h6 = &m->v6.message.hello;
+		      hinfo6 = h6->hell_info;
+		      haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
+		      /* Make sure typeheader is added */
+		      first_entry = OLSR_TRUE;
+		    }
+		  net_output(ifp);
+		  /* Reset size and pointers */
+		  remainsize = net_outbuffer_bytes_left(ifp);
+
+		  check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2");
+		      
+		}
+
+	      if(first_entry)
+		{
+		  memset(&hinfo6->reserved, 0, sizeof(olsr_u8_t));
+		  /* Set link and status for this group of neighbors (this is the first) */
+		  hinfo6->link_code = CREATE_LINK_CODE(i, j);
+		  curr_size += 4; /* HELLO type section header */
+		}
+		  
+	      *haddr = nb->address;
+		  
+	      /* Point to next address */
+	      haddr++;
+	      curr_size += olsr_cnf->ipsize; /* IP address added */ 
+		  
+	      first_entry = OLSR_FALSE;
+	    }/* looping trough neighbors */
+	  
+	  
+	  if (!first_entry)
+	    {
+	      hinfo6->size = htons((char *)haddr - (char *)hinfo6);
+	      hinfo6 = (struct hellinfo6 *)((char *)haddr);
+	      haddr = (union olsr_ip_addr *)&hinfo6->neigh_addr;
+	    }
+	  
+	} /* for j */
+    } /* for i */
+
+  m->v6.seqno = htons(get_msg_seqno());
+  m->v6.olsr_msgsize = htons(curr_size);
+
+  net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+  /* HELLO is always buildt */
+  return OLSR_TRUE;
+}
+
+
+
+/**
+ *IP version 4
+ *
+ *@param message the tc_message struct containing the info
+ *to send
+ *@param ifp the interface to send the message on
+ *
+ *@return nada
+ */
+
+static olsr_bool
+serialize_tc4(struct tc_message *message, struct interface *ifp)           
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  olsr_u16_t remainsize, curr_size;
+  struct tc_mpr_addr *mprs;
+  union olsr_message *m;
+  struct olsr_tcmsg *tc;
+  struct neigh_info *mprsaddr; 
+  olsr_bool found = OLSR_FALSE, partial_sent = OLSR_FALSE;
+
+  if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
+    return OLSR_FALSE;
+
+  remainsize = net_outbuffer_bytes_left(ifp);
+
+  m = (union olsr_message *)msg_buffer;
+
+  tc = &m->v4.message.tc;
+
+
+  mprsaddr = tc->neigh;
+  curr_size = OLSR_TC_IPV4_HDRSIZE;
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size, remainsize, "TC");
+
+  /* Fill header */
+  m->v4.olsr_vtime = ifp->valtimes.tc;
+  m->v4.olsr_msgtype = TC_MESSAGE;
+  m->v4.hopcnt = message->hop_count;
+  m->v4.ttl = message->ttl;
+  m->v4.originator = message->originator.v4.s_addr;
+
+  /* Fill TC header */
+  tc->ansn = htons(message->ansn);
+  tc->reserved = 0;
+  
+
+  /*Looping trough MPR selectors */
+  for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) 
+    {
+      /*If packet is to be chomped */
+      if((curr_size + olsr_cnf->ipsize) > remainsize)
+	{
+
+	  /* Only add TC message if it contains data */
+	  if(curr_size > OLSR_TC_IPV4_HDRSIZE)
+	    {
+#ifdef DEBUG
+	      OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+
+	      m->v4.olsr_msgsize = htons(curr_size);
+	      m->v4.seqno = htons(get_msg_seqno());
+
+	      net_outbuffer_push(ifp, msg_buffer, curr_size);
+	      
+	      /* Reset stuff */
+	      mprsaddr = tc->neigh;
+	      curr_size = OLSR_TC_IPV4_HDRSIZE;
+	      found = OLSR_FALSE;
+	      partial_sent = OLSR_TRUE;
+	    }
+
+	  net_output(ifp);
+	  remainsize = net_outbuffer_bytes_left(ifp);
+	  check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2");
+
+	}
+      found = OLSR_TRUE;
+#ifdef DEBUG
+	  OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", 
+		      olsr_ip_to_string(&buf, &mprs->address));
+#endif 
+      mprsaddr->addr = mprs->address.v4.s_addr;
+      curr_size += olsr_cnf->ipsize;
+      mprsaddr++;
+    }
+
+  if (found)
+    {
+	    
+      m->v4.olsr_msgsize = htons(curr_size);
+      m->v4.seqno = htons(get_msg_seqno());
+      
+      net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+    }
+  else
+    {
+      if((!partial_sent) && (!TIMED_OUT(send_empty_tc)))
+	{
+	  if(!TIMED_OUT(send_empty_tc))
+	    OLSR_PRINTF(1, "TC: Sending empty package - (%d/%d/%d/%d)\n", partial_sent, (int)send_empty_tc, (int)now_times, (int)((send_empty_tc) - now_times));
+
+	  m->v4.olsr_msgsize = htons(curr_size);
+	  m->v4.seqno = htons(get_msg_seqno());
+
+	  net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+	  found = OLSR_TRUE;
+	}
+    }
+
+  return found;	
+}
+
+
+
+/**
+ *IP version 6
+ *
+ *@param message the tc_message struct containing the info
+ *to send
+ *@param ifp the interface to send the message on
+ *
+ *@return nada
+ */
+
+static olsr_bool
+serialize_tc6(struct tc_message *message, struct interface *ifp)           
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  olsr_u16_t remainsize, curr_size;
+  struct tc_mpr_addr *mprs;
+  union olsr_message *m;
+  struct olsr_tcmsg6 *tc6;
+  struct neigh_info6 *mprsaddr6; 
+  olsr_bool found = OLSR_FALSE, partial_sent = OLSR_FALSE;
+
+  if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
+    return OLSR_FALSE;
+
+  remainsize = net_outbuffer_bytes_left(ifp);
+
+  m = (union olsr_message *)msg_buffer;
+
+  tc6 = &m->v6.message.tc;
+
+  mprsaddr6 = tc6->neigh;
+  curr_size = OLSR_TC_IPV6_HDRSIZE;
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size, remainsize, "TC");
+
+  /* Fill header */
+  m->v6.olsr_vtime = ifp->valtimes.tc;
+  m->v6.olsr_msgtype = TC_MESSAGE;
+  m->v6.hopcnt = message->hop_count;
+  m->v6.ttl = message->ttl;
+  m->v6.originator = message->originator.v6;
+
+  /* Fill TC header */
+  tc6->ansn = htons(message->ansn);
+  tc6->reserved = 0;
+  
+
+  /*Looping trough MPR selectors */
+  for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) 
+    {
+	    
+      /*If packet is to be chomped */
+      if((curr_size + olsr_cnf->ipsize) > remainsize)
+	{
+	  /* Only add TC message if it contains data */
+	  if(curr_size > OLSR_TC_IPV6_HDRSIZE)
+	    {
+#ifdef DEBUG
+	      OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+	      m->v6.olsr_msgsize = htons(curr_size);
+	      m->v6.seqno = htons(get_msg_seqno());
+
+	      net_outbuffer_push(ifp, msg_buffer, curr_size);
+	      mprsaddr6 = tc6->neigh;
+	      curr_size = OLSR_TC_IPV6_HDRSIZE;
+	      found = OLSR_FALSE;
+	      partial_sent = OLSR_TRUE;
+	    }
+	  net_output(ifp);
+	  remainsize = net_outbuffer_bytes_left(ifp);
+	  check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2");
+
+	}
+      found = OLSR_TRUE;
+#ifdef DEBUG
+	  OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", 
+		      olsr_ip_to_string(&buf, &mprs->address));
+#endif
+      mprsaddr6->addr = mprs->address.v6;
+      curr_size += olsr_cnf->ipsize;
+
+      mprsaddr6++;
+    }
+	
+  if (found)
+    {
+      m->v6.olsr_msgsize = htons(curr_size);
+      m->v6.seqno = htons(get_msg_seqno());
+
+      net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+    }
+  else
+    {
+      if((!partial_sent) && (!TIMED_OUT(send_empty_tc)))
+	{
+	  OLSR_PRINTF(1, "TC: Sending empty package\n");
+	    
+	  m->v6.olsr_msgsize = htons(curr_size);
+	  m->v6.seqno = htons(get_msg_seqno());
+
+	  net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+	  found = OLSR_TRUE;
+	}
+    }
+
+  return found;	
+}
+
+
+
+
+/**
+ *IP version 4
+ *
+ *<b>NO INTERNAL BUFFER</b>
+ *@param ifp use this interfaces address as main address
+ *@return 1 on success
+ */
+
+static olsr_bool
+serialize_mid4(struct interface *ifp)
+{
+  olsr_u16_t remainsize, curr_size;
+  /* preserve existing data in output buffer */
+  union olsr_message *m;
+  struct midaddr *addrs;
+  struct interface *ifs;  
+
+  if((olsr_cnf->ip_version != AF_INET) || (!ifp) || (ifnet == NULL || ifnet->int_next == NULL))
+    return OLSR_FALSE;
+
+
+  remainsize = net_outbuffer_bytes_left(ifp);
+
+  m = (union olsr_message *)msg_buffer;
+
+  curr_size = OLSR_MID_IPV4_HDRSIZE;
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size, remainsize, "MID");
+
+  /* Fill header */
+  m->v4.hopcnt = 0;
+  m->v4.ttl = MAX_TTL;
+  /* Set main(first) address */
+  m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
+  m->v4.olsr_msgtype = MID_MESSAGE;
+  m->v4.olsr_vtime = ifp->valtimes.mid;
+ 
+  addrs = m->v4.message.mid.mid_addr;
+
+  /* Don't add the main address... it's already there */
+  for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
+    {
+      if(!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr))
+	{
+#ifdef DEBUG
+          struct ipaddr_str buf;
+#endif
+
+	  if((curr_size + olsr_cnf->ipsize) > remainsize)
+	    {
+	      /* Only add MID message if it contains data */
+	      if(curr_size > OLSR_MID_IPV4_HDRSIZE)
+		{
+#ifdef DEBUG
+		  OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+		  /* set size */
+		  m->v4.olsr_msgsize = htons(curr_size);
+		  m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
+		  
+		  net_outbuffer_push(ifp, msg_buffer, curr_size);
+		  curr_size = OLSR_MID_IPV4_HDRSIZE;
+		  addrs = m->v4.message.mid.mid_addr;
+		}
+	      net_output(ifp);
+	      remainsize = net_outbuffer_bytes_left(ifp);
+	      check_buffspace(curr_size, remainsize, "MID2");
+	    }
+#ifdef DEBUG
+	  OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", 
+		      olsr_ip_to_string(&buf, &ifs->ip_addr), 
+		      ifs->int_name);
+#endif
+	  
+          addrs->addr = ifs->ip_addr.v4.s_addr;
+	  addrs++;
+	  curr_size += olsr_cnf->ipsize;
+	}
+    }
+
+
+  m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
+  m->v4.olsr_msgsize = htons(curr_size);
+
+  //printf("Sending MID (%d bytes)...\n", outputsize);
+  if(curr_size > OLSR_MID_IPV4_HDRSIZE)
+    net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+
+  return OLSR_TRUE;
+}
+
+
+
+/**
+ *IP version 6
+ *
+ *<b>NO INTERNAL BUFFER</b>
+ *@param ifp use this interfaces address as main address
+ *@return 1 on success
+ */
+
+static olsr_bool
+serialize_mid6(struct interface *ifp)
+{
+  olsr_u16_t remainsize, curr_size;
+  /* preserve existing data in output buffer */
+  union olsr_message *m;
+  struct midaddr6 *addrs6;
+  struct interface *ifs;
+
+  //printf("\t\tGenerating mid on %s\n", ifn->int_name);
+
+
+  if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL || ifnet->int_next == NULL))
+    return OLSR_FALSE;
+
+  remainsize = net_outbuffer_bytes_left(ifp);
+
+  curr_size = OLSR_MID_IPV6_HDRSIZE;
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size, remainsize, "MID");
+
+  m = (union olsr_message *)msg_buffer;
+    
+  /* Build header */
+  m->v6.hopcnt = 0;
+  m->v6.ttl = MAX_TTL;      
+  m->v6.olsr_msgtype = MID_MESSAGE;
+  m->v6.olsr_vtime = ifp->valtimes.mid;
+  /* Set main(first) address */
+  m->v6.originator = olsr_cnf->main_addr.v6;
+
+  addrs6 = m->v6.message.mid.mid_addr;
+
+  /* Don't add the main address... it's already there */
+  for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
+    {
+      if(!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr))
+	{
+#ifdef DEBUG
+          struct ipaddr_str buf;
+#endif
+	  if((curr_size + olsr_cnf->ipsize) > remainsize)
+	    {
+	      /* Only add MID message if it contains data */
+	      if(curr_size > OLSR_MID_IPV6_HDRSIZE)
+		{
+#ifdef DEBUG
+		  OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+		  /* set size */
+		  m->v6.olsr_msgsize = htons(curr_size);
+		  m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
+		  
+		  net_outbuffer_push(ifp, msg_buffer, curr_size);
+		  curr_size = OLSR_MID_IPV6_HDRSIZE;
+		  addrs6 = m->v6.message.mid.mid_addr;
+		}
+	      net_output(ifp);
+	      remainsize = net_outbuffer_bytes_left(ifp);
+	      check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
+	    }
+#ifdef DEBUG
+		  OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", 
+			      olsr_ip_to_string(&buf, &ifs->ip_addr), 
+			      ifs->int_name);
+#endif
+
+          addrs6->addr = ifs->ip_addr.v6;
+	  addrs6++;
+	  curr_size += olsr_cnf->ipsize;
+	}
+    }
+
+  m->v6.olsr_msgsize = htons(curr_size);
+  m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
+
+  //printf("Sending MID (%d bytes)...\n", outputsize);
+  if(curr_size > OLSR_MID_IPV6_HDRSIZE)
+    net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+  return OLSR_TRUE;
+}
+
+
+
+
+/**
+ *IP version 4
+ *
+ *@param ifp the interface to send on
+ *@return nada
+ */
+static olsr_bool
+serialize_hna4(struct interface *ifp)
+{
+  olsr_u16_t remainsize, curr_size;
+  /* preserve existing data in output buffer */
+  union olsr_message *m;
+  struct hnapair *pair;
+  struct ip_prefix_list *h;
+
+  /* No hna nets */
+  if (ifp == NULL) {
+    return OLSR_FALSE;
+  }
+  if (olsr_cnf->ip_version != AF_INET) {
+    return OLSR_FALSE;
+  }
+  h = olsr_cnf->hna_entries;
+  if (h == NULL) {
+    return OLSR_FALSE;
+  }
+    
+  remainsize = net_outbuffer_bytes_left(ifp);
+  
+  curr_size = OLSR_HNA_IPV4_HDRSIZE;
+  
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size, remainsize, "HNA");
+
+  m = (union olsr_message *)msg_buffer;
+  
+  
+  /* Fill header */
+  m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
+  m->v4.hopcnt = 0;
+  m->v4.ttl = MAX_TTL;
+  m->v4.olsr_msgtype = HNA_MESSAGE;
+  m->v4.olsr_vtime = ifp->valtimes.hna;
+  
+
+  pair = m->v4.message.hna.hna_net;
+  
+  for (; h != NULL; h = h->next) {
+      union olsr_ip_addr ip_addr;
+      if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
+	{
+	  /* Only add HNA message if it contains data */
+	  if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
+	    {
+#ifdef DEBUG
+	      OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+	      m->v4.seqno = htons(get_msg_seqno());
+	      m->v4.olsr_msgsize = htons(curr_size);
+	      net_outbuffer_push(ifp, msg_buffer, curr_size);
+	      curr_size = OLSR_HNA_IPV4_HDRSIZE;
+	      pair = m->v4.message.hna.hna_net;
+	    }
+	  net_output(ifp);
+	  remainsize = net_outbuffer_bytes_left(ifp);
+	  check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
+	}
+#ifdef DEBUG
+      OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
+#endif
+      pair->addr = h->net.prefix.v4.s_addr;
+      olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
+      pair->netmask = ip_addr.v4.s_addr;
+      pair++;
+      curr_size += (2 * olsr_cnf->ipsize);    
+  }
+
+  m->v4.seqno = htons(get_msg_seqno());
+  m->v4.olsr_msgsize = htons(curr_size);
+
+  net_outbuffer_push(ifp, msg_buffer, curr_size);
+
+  //printf("Sending HNA (%d bytes)...\n", outputsize);
+  return OLSR_FALSE;
+}
+
+
+/**
+ *IP version 6
+ *
+ *@param ifp the interface to send on
+ *@return nada
+ */
+static olsr_bool
+serialize_hna6(struct interface *ifp)
+{
+  olsr_u16_t remainsize, curr_size;
+  /* preserve existing data in output buffer */
+  union olsr_message *m;
+  struct hnapair6 *pair6;
+  union olsr_ip_addr tmp_netmask;
+  struct ip_prefix_list *h = olsr_cnf->hna_entries;
+  
+  /* No hna nets */
+  if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || h == NULL)
+    return OLSR_FALSE;
+
+    
+  remainsize = net_outbuffer_bytes_left(ifp);
+
+  curr_size = OLSR_HNA_IPV6_HDRSIZE;
+
+  /* Send pending packet if not room in buffer */
+  if(curr_size > remainsize)
+    {
+      net_output(ifp);
+      remainsize = net_outbuffer_bytes_left(ifp);
+    }
+  check_buffspace(curr_size, remainsize, "HNA");
+
+  m = (union olsr_message *)msg_buffer;   
+
+  /* Fill header */
+  m->v6.originator = olsr_cnf->main_addr.v6;
+  m->v6.hopcnt = 0;
+  m->v6.ttl = MAX_TTL;
+  m->v6.olsr_msgtype = HNA_MESSAGE;
+  m->v6.olsr_vtime = ifp->valtimes.hna;
+
+  pair6 = m->v6.message.hna.hna_net;
+
+
+  while(h)
+    {
+      if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize)
+	{
+	  /* Only add HNA message if it contains data */
+	  if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
+	    {
+#ifdef DEBUG
+	      OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
+#endif
+	      m->v6.seqno = htons(get_msg_seqno());
+	      m->v6.olsr_msgsize = htons(curr_size);
+	      net_outbuffer_push(ifp, msg_buffer, curr_size);
+	      curr_size = OLSR_HNA_IPV6_HDRSIZE;
+	      pair6 = m->v6.message.hna.hna_net;
+	    }
+	  net_output(ifp);
+	  remainsize = net_outbuffer_bytes_left(ifp);
+	  check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
+	}
+#ifdef DEBUG
+      OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
+#endif
+      pair6->addr = h->net.prefix.v6;
+      olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
+      pair6->netmask = tmp_netmask.v6;
+      pair6++;
+      curr_size += (2 * olsr_cnf->ipsize);
+      h = h->next;
+    }
+  
+  m->v6.olsr_msgsize = htons(curr_size);
+  m->v6.seqno = htons(get_msg_seqno());
+  
+  net_outbuffer_push(ifp, msg_buffer, curr_size);
+#if 0
+  printf("Sending HNA (%d bytes)...\n", outputsize);
+#endif
+  return OLSR_FALSE;
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/build_msg.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/build_msg.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/build_msg.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/build_msg.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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 _BUILD_MSG_H
+#define _BUILD_MSG_H
+
+#include "packet.h"
+#include "olsr_protocol.h"
+#include <time.h> /* For clock_t */
+
+void
+set_empty_tc_timer(clock_t);
+
+clock_t
+get_empty_tc_timer(void);
+
+olsr_bool
+queue_hello(struct hello_message *, struct interface *);
+
+olsr_bool
+queue_tc(struct tc_message *, struct interface *);
+
+olsr_bool
+queue_mid(struct interface *);
+
+olsr_bool
+queue_hna(struct interface *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/cfgfile_gen.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/cfgfile_gen.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/cfgfile_gen.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/cfgfile_gen.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,637 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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 "olsrd_conf.h"
+#include "../ipcalc.h"
+#include "../net_olsr.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+int
+olsrd_write_cnf(struct olsrd_config *cnf, const char *fname)
+{
+  struct ip_prefix_list   *h  = cnf->hna_entries;
+  struct olsr_if           *in = cnf->interfaces;
+  struct plugin_entry      *pe = cnf->plugins;
+  struct plugin_param      *pp;
+  struct ip_prefix_list    *ie = cnf->ipc_nets;
+  struct olsr_lq_mult      *mult;
+
+  char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
+
+  FILE *fd;
+
+  fd = fopen(fname, "w");
+
+  if(fd == NULL)
+    {
+      fprintf(stderr, "Could not open file %s for writing\n%s\n", fname, strerror(errno));
+      return -1;
+    }
+
+  printf("Writing config to file \"%s\".... ", fname);
+
+  fprintf(fd, "#\n# Configuration file for s%s\n# automatically generated by olsrd-cnf parser v. %s\n#\n\n", olsrd_version, PARSER_VERSION);
+
+  /* Debug level */
+  fprintf(fd, "# Debug level(0-9)\n# If set to 0 the daemon runs in the background\n\nDebugLevel\t%d\n\n", cnf->debug_level);
+
+  /* IP version */
+  fprintf(fd, "# IP version to use (4 or 6)\n\nIpVersion\t%d\n\n", cnf->ip_version == AF_INET ? 4 : 6);
+
+  /* FIB Metric */
+  fprintf(fd, "# FIBMetric (\"%s\", \"%s\", or \"%s\")\n\nFIBMetric\t\"%s\"\n\n", CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX,
+    FIBM_FLAT == cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
+
+  /* HNA IPv4/IPv6 */
+  fprintf(fd, "# HNA IPv%d routes\n# syntax: netaddr/prefix\n\nHna%d {\n", cnf->ip_version == AF_INET ? 4 : 6, cnf->ip_version == AF_INET ? 4 : 6);
+  while(h) {
+    struct ipaddr_str strbuf;
+    fprintf(fd, "    %s/%d\n", olsr_ip_to_string(&strbuf, &h->net.prefix), h->net.prefix_len);
+    h = h->next;
+  }
+  fprintf(fd, "}\n\n");
+
+  /* No interfaces */
+  fprintf(fd, "# Should olsrd keep on running even if there are\n# no interfaces available? This is a good idea\n# for a PCMCIA/USB hotswap environment.\n# \"yes\" OR \"no\"\n\nAllowNoInt\t");
+  if(cnf->allow_no_interfaces)
+    fprintf(fd, "yes\n\n");
+  else
+    fprintf(fd, "no\n\n");
+
+  /* TOS */
+  fprintf(fd, "# TOS(type of service) to use. Default is 16\n\n");
+  fprintf(fd, "TosValue\t%d\n\n", cnf->tos);
+
+  /* RtTable */
+  fprintf(fd, "# Policy Routing Table to use. Default is 254\n\n");
+  fprintf(fd, "RtTable\t\t%d\n\n", cnf->rttable);
+
+  /* RtTableDefault */
+  fprintf(fd, "# Policy Routing Table to use for the default Route. Default is 0 (Take the same table as specified by RtTable)\n\n");
+  fprintf(fd, "RtTableDefault\t\t%d\n\n", cnf->rttable_default);
+
+  /* Willingness */
+  fprintf(fd, "# The fixed willingness to use(0-7)\n# If not set willingness will be calculated\n# dynammically based on battery/power status\n\n");
+  if(cnf->willingness_auto)
+    fprintf(fd, "#Willingness\t4\n\n");
+  else
+    fprintf(fd, "Willingness\t%d\n\n", cnf->willingness);
+
+  /* IPC */
+  fprintf(fd, "# Allow processes like the GUI front-end\n# to connect to the daemon.\n\n");
+  fprintf(fd, "IpcConnect {\n");
+  fprintf(fd, "    MaxConnections\t%d\n", cnf->ipc_connections);
+
+  while(ie)
+    {
+      struct ipaddr_str strbuf;
+      if (ie->net.prefix_len == olsr_cnf->maxplen) {
+          fprintf(fd, "    Host\t\t%s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
+      } else {
+          fprintf(fd, "    Net\t\t\t%s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
+      }
+      ie = ie->next;
+    }
+
+  fprintf(fd, "}\n\n");
+
+  /* Hysteresis */
+  fprintf(fd, "# Hysteresis adds more robustness to the\n# link sensing.\n# Used by default. 'yes' or 'no'\n\n");
+
+  if(cnf->use_hysteresis)
+    {
+      fprintf(fd, "UseHysteresis\tyes\n\n");
+      fprintf(fd, "# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
+      fprintf(fd, "HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
+      fprintf(fd, "HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
+      fprintf(fd, "HystThrLow\t%0.2f\n\n", cnf->hysteresis_param.thr_low);
+    }
+  else
+    {
+      fprintf(fd, "UseHysteresis\tno\n\n");
+      fprintf(fd, "# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
+      fprintf(fd, "#HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
+      fprintf(fd, "#HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
+      fprintf(fd, "#HystThrLow\t%0.2f\n\n", cnf->hysteresis_param.thr_low);
+    }
+
+  /* Pollrate */
+  fprintf(fd, "# Polling rate in seconds(float).\n# Auto uses default value 0.05 sec\n\n");
+  fprintf(fd, "Pollrate\t%0.2f\n", cnf->pollrate);
+
+  /* NIC Changes Pollrate */
+  fprintf(fd, "# Interval to poll network interfaces for configuration\n# changes. Defaults to 2.5 seconds\n");
+  fprintf(fd, "NicChgsPollInt\t%0.2f\n", cnf->nic_chgs_pollrate);
+
+  /* TC redundancy */
+  fprintf(fd, "# TC redundancy\n# Specifies how much neighbor info should\n# be sent in TC messages\n# Possible values are:\n# 0 - only send MPR selectors\n# 1 - send MPR selectors and MPRs\n# 2 - send all neighbors\n#\n# defaults to 0\n\n");
+  fprintf(fd, "TcRedundancy\t%d\n\n", cnf->tc_redundancy);
+
+  /* MPR coverage */
+  fprintf(fd, "# MPR coverage\n# Specifies how many MPRs a node should\n# try select to reach every 2 hop neighbor\n# Can be set to any integer >0\n# defaults to 1\n\n");
+
+  fprintf(fd, "MprCoverage\t%d\n\n", cnf->mpr_coverage);
+
+  fprintf(fd, "# Link quality level\n# 0 = do not use link quality\n# 1 = use link quality for MPR selection\n# 2 = use link quality for MPR selection and routing\n\n");
+  fprintf(fd, "LinkQualityLevel\t%d\n\n", cnf->lq_level);
+
+  fprintf(fd, "# Fish Eye algorithm\n# 0 = do not use fish eye\n# 1 = use fish eye\n\n");
+  fprintf(fd, "LinkQualityFishEye\t%d\n\n", cnf->lq_fish);
+
+  fprintf(fd, "# Link quality aging factor\n\n");
+  fprintf(fd, "LinkQualityAging\t%f\n\n", cnf->lq_aging);
+
+  fprintf(fd, "# NAT threshold\n\n");
+  fprintf(fd, "NatThreshold\t%f\n\n", cnf->lq_nat_thresh);
+
+  fprintf(fd, "# Clear screen when printing debug output?\n\n");
+  fprintf(fd, "ClearScreen\t%s\n\n", cnf->clear_screen ? "yes" : "no");
+
+  /* Plugins */
+  fprintf(fd, "# Olsrd plugins to load\n# This must be the absolute path to the file\n# or the loader will use the following scheme:\n# - Try the paths in the LD_LIBRARY_PATH \n#   environment variable.\n# - The list of libraries cached in /etc/ld.so.cache\n# - /lib, followed by /usr/lib\n\n");
+  if(pe)
+    {
+      while(pe)
+	{
+	  fprintf(fd, "LoadPlugin \"%s\" {\n", pe->name);
+          pp = pe->params;
+          while(pp)
+            {
+              fprintf(fd, "    PlParam \"%s\"\t\"%s\"\n", pp->key, pp->value);
+              pp = pp->next;
+            }
+	  fprintf(fd, "}\n");
+	  pe = pe->next;
+	}
+    }
+  fprintf(fd, "\n");
+
+  
+  
+
+  /* Interfaces */
+  fprintf(fd, "# Interfaces\n# Multiple interfaces with the same configuration\n# can shar the same config block. Just list the\n# interfaces(e.g. Interface \"eth0\" \"eth2\"\n\n");
+  /* Interfaces */
+  if(in)
+    {
+      while(in)
+	{
+	  fprintf(fd, "Interface \"%s\" {\n", in->name);
+	  fprintf(fd, "\n");
+      
+	  fprintf(fd, "    # IPv4 broadcast address to use. The\n    # one usefull example would be 255.255.255.255\n    # If not defined the broadcastaddress\n    # every card is configured with is used\n\n");
+
+
+	  if(in->cnf->ipv4_broadcast.v4.s_addr)
+	    {
+	      fprintf(fd, "    Ip4Broadcast\t%s\n\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
+	    }
+	  else
+	    {
+	      fprintf(fd, "    #Ip4Broadcast\t255.255.255.255\n\n");
+	    }
+	  
+	  
+	  fprintf(fd, "    # IPv6 address scope to use.\n    # Must be 'site-local' or 'global'\n\n");
+	  if(in->cnf->ipv6_addrtype)
+	    fprintf(fd, "    Ip6AddrType \tsite-local\n\n");
+	  else
+	    fprintf(fd, "    Ip6AddrType \tglobal\n\n");
+	  
+	  fprintf(fd, "    # IPv6 multicast address to use when\n    # using site-local addresses.\n    # If not defined, ff05::15 is used\n");
+	  fprintf(fd, "    Ip6MulticastSite\t%s\n\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
+	  fprintf(fd, "    # IPv6 multicast address to use when\n    # using global addresses\n    # If not defined, ff0e::1 is used\n");
+	  fprintf(fd, "    Ip6MulticastGlobal\t%s\n\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
+	  
+	  
+          fprintf(fd, "    # Olsrd can autodetect changes in\n    # interface configurations. Enabled by default\n    # turn off to save CPU.\n    AutoDetectChanges: %s\n", in->cnf->autodetect_chg ? "yes" : "no");
+
+	  fprintf(fd, "    # Emission and validity intervals.\n    # If not defined, RFC proposed values will\n    # in most cases be used.\n\n");
+	  
+	  
+	  if(in->cnf->hello_params.emission_interval != HELLO_INTERVAL)
+	    fprintf(fd, "    HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
+	  else
+	    fprintf(fd, "    #HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
+	  if(in->cnf->hello_params.validity_time != NEIGHB_HOLD_TIME)
+	    fprintf(fd, "    HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
+	  else
+	    fprintf(fd, "    #HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
+	  if(in->cnf->tc_params.emission_interval != TC_INTERVAL)
+	    fprintf(fd, "    TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
+	  else
+	    fprintf(fd, "    #TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
+	  if(in->cnf->tc_params.validity_time != TOP_HOLD_TIME)
+	    fprintf(fd, "    TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
+	  else
+	    fprintf(fd, "    #TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
+	  if(in->cnf->mid_params.emission_interval != MID_INTERVAL)
+	    fprintf(fd, "    MidInterval\t\t%0.2f\n", in->cnf->mid_params.emission_interval);
+	  else
+	    fprintf(fd, "    #MidInterval\t%0.2f\n", in->cnf->mid_params.emission_interval);
+	  if(in->cnf->mid_params.validity_time != MID_HOLD_TIME)
+	    fprintf(fd, "    MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
+	  else
+	    fprintf(fd, "    #MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
+	  if(in->cnf->hna_params.emission_interval != HNA_INTERVAL)
+	    fprintf(fd, "    HnaInterval\t\t%0.2f\n", in->cnf->hna_params.emission_interval);
+	  else
+	    fprintf(fd, "    #HnaInterval\t%0.2f\n", in->cnf->hna_params.emission_interval);
+	  if(in->cnf->hna_params.validity_time != HNA_HOLD_TIME)
+	    fprintf(fd, "    HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);	  
+	  else
+	    fprintf(fd, "    #HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);	  
+	  
+          mult = in->cnf->lq_mult;
+
+          if (mult == NULL)
+	    {
+	      fprintf(fd, "    #LinkQualityMult\tdefault 1.0\n");
+	    }
+          else
+	    {
+	      while (mult != NULL)
+		{
+		  fprintf(fd, "    LinkQualityMult\t%s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof(ipv6_buf)), (float)(mult->value) / 65536.0);
+		  mult = mult->next;
+		}
+	    }
+
+         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);
+	    }
+	  else
+	    {
+	      fprintf(fd, "    #Weight\t 0\n\n");
+	    }
+
+	  
+	  fprintf(fd, "}\n\n");
+	  in = in->next;
+	}
+
+    }
+
+
+  fprintf(fd, "\n# END AUTOGENERATED CONFIG\n");
+
+  fclose(fd);
+  printf("DONE\n");
+
+  return 1;
+}
+
+#define MAX_LINESIZE 250
+
+#define WRITE_TO_BUF(fmt, args...)                                      \
+    do {                                                                \
+        if((bufsize - size) < MAX_LINESIZE) {                           \
+            return -1;                                                  \
+        }                                                               \
+        size += snprintf(&buf[size], MAX_LINESIZE, fmt, ##args);        \
+    } while (0)
+
+int
+olsrd_write_cnf_buf(struct olsrd_config *cnf, char *buf, olsr_u32_t bufsize)
+{
+  struct ip_prefix_list   *h  = cnf->hna_entries;
+  struct olsr_if           *in = cnf->interfaces;
+  struct plugin_entry      *pe = cnf->plugins;
+  struct plugin_param      *pp;
+  struct ip_prefix_list    *ie = cnf->ipc_nets;
+  struct olsr_lq_mult      *mult;
+
+  int size = 0;
+
+  char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
+
+#if 0
+  printf("\n\n\n\nolsrd_write_cnf_buf bufsize  %d\n\n\n\n\n", bufsize);
+#endif
+  if (buf == NULL || bufsize < MAX_LINESIZE) {
+      return -1;
+  }
+
+  WRITE_TO_BUF("#\n# Configuration file for olsr.org olsrd\n# automatically generated by olsrd-cnf %s\n#\n\n\n", PARSER_VERSION);
+
+  /* Debug level */
+  WRITE_TO_BUF("# Debug level(0-9)\n# If set to 0 the daemon runs in the background\n\nDebugLevel\t%d\n\n", cnf->debug_level);
+
+  /* IP version */
+  WRITE_TO_BUF("# IP version to use (4 or 6)\n\nIpVersion\t%d\n\n", cnf->ip_version == AF_INET ? 4 : 6);
+
+  /* FIB Metric */
+  WRITE_TO_BUF("# FIBMetric (\"%s\", \"%s\", or \"%s\")\n\nFIBMetric\t\"%s\"\n\n", CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX,
+    FIBM_FLAT == cnf->fib_metric ? CFG_FIBM_FLAT : FIBM_CORRECT == cnf->fib_metric ? CFG_FIBM_CORRECT : CFG_FIBM_APPROX);
+
+  /* HNA IPv4/IPv6 */
+  WRITE_TO_BUF("# HNA IPv%1$d routes\n# syntax: netaddr netmask\n\nHna%1$d {\n", cnf->ip_version == AF_INET ? 4 : 6);
+  while(h) {
+    struct ipaddr_str strbuf;
+    WRITE_TO_BUF("    %s/%d\n", olsr_ip_to_string(&strbuf, &h->net.prefix), h->net.prefix_len);
+    h = h->next;
+  }
+  WRITE_TO_BUF("}\n\n");
+
+  /* No interfaces */
+  WRITE_TO_BUF("# Should olsrd keep on running even if there are\n# no interfaces available? This is a good idea\n# for a PCMCIA/USB hotswap environment.\n# \"yes\" OR \"no\"\n\nAllowNoInt\t");
+  if(cnf->allow_no_interfaces)
+    WRITE_TO_BUF("yes\n\n");
+  else
+    WRITE_TO_BUF("no\n\n");
+
+  /* TOS */
+  WRITE_TO_BUF("# TOS(type of service) to use. Default is 16\n\n");
+  WRITE_TO_BUF("TosValue\t%d\n\n", cnf->tos);
+
+  /* RtTable */
+  WRITE_TO_BUF("# Policy Routing Tableto use. Default is 254\n\n");
+  WRITE_TO_BUF("RtTable\t\t%d\n\n", cnf->rttable);
+
+  /* Willingness */
+  WRITE_TO_BUF("# The fixed willingness to use(0-7)\n# If not set willingness will be calculated\n# dynammically based on battery/power status\n\n");
+  if(cnf->willingness_auto)
+    WRITE_TO_BUF("#Willingness\t4\n\n");
+  else
+    WRITE_TO_BUF("Willingness\t%d\n\n", cnf->willingness);
+
+  /* IPC */
+  WRITE_TO_BUF("# Allow processes like the GUI front-end\n# to connect to the daemon.\n\n");
+  WRITE_TO_BUF("IpcConnect {\n");
+  WRITE_TO_BUF("    MaxConnections\t%d\n", cnf->ipc_connections);
+  while(ie)
+    {
+      struct ipaddr_str strbuf;
+      if (ie->net.prefix_len == olsr_cnf->maxplen) {
+          WRITE_TO_BUF("    Host\t\t%s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
+      } else {
+          WRITE_TO_BUF("    Net\t\t\t%s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
+      }
+      ie = ie->next;
+    }
+
+  WRITE_TO_BUF("}\n\n");
+
+
+
+  /* Hysteresis */
+  WRITE_TO_BUF("# Hysteresis adds more robustness to the\n# link sensing.\n# Used by default. 'yes' or 'no'\n\n");
+
+  if(cnf->use_hysteresis)
+    {
+      WRITE_TO_BUF("UseHysteresis\tyes\n\n");
+      WRITE_TO_BUF("# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
+      WRITE_TO_BUF("HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
+      WRITE_TO_BUF("HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
+      WRITE_TO_BUF("HystThrLow\t%0.2f\n\n", cnf->hysteresis_param.thr_low);
+    }
+  else
+    {
+      WRITE_TO_BUF("UseHysteresis\tno\n\n");
+      WRITE_TO_BUF("# Hysteresis parameters\n# Do not alter these unless you know \n# what you are doing!\n# Set to auto by default. Allowed\n# values are floating point values\n# in the interval 0,1\n# THR_LOW must always be lower than\n# THR_HIGH!!\n\n");
+      WRITE_TO_BUF("#HystScaling\t%0.2f\n", cnf->hysteresis_param.scaling);
+      WRITE_TO_BUF("#HystThrHigh\t%0.2f\n", cnf->hysteresis_param.thr_high);
+      WRITE_TO_BUF("#HystThrLow\t%0.2f\n\n", cnf->hysteresis_param.thr_low);
+    }
+
+  /* Pollrate */
+  WRITE_TO_BUF("# Polling rate in seconds(float).\n# Auto uses default value 0.05 sec\n\n");
+  WRITE_TO_BUF("Pollrate\t%0.2f\n", cnf->pollrate);
+
+  /* TC redundancy */
+  WRITE_TO_BUF("# TC redundancy\n# Specifies how much neighbor info should\n# be sent in TC messages\n# Possible values are:\n# 0 - only send MPR selectors\n# 1 - send MPR selectors and MPRs\n# 2 - send all neighbors\n#\n# defaults to 0\n\n");
+  WRITE_TO_BUF("TcRedundancy\t%d\n\n", cnf->tc_redundancy);
+
+  /* MPR coverage */
+  WRITE_TO_BUF("# MPR coverage\n# Specifies how many MPRs a node should\n# try select to reach every 2 hop neighbor\n# Can be set to any integer >0\n# defaults to 1\n\n");
+
+  WRITE_TO_BUF("MprCoverage\t%d\n\n", cnf->mpr_coverage);
+
+  WRITE_TO_BUF("# Link quality level\n# 0 = do not use link quality\n# 1 = use link quality for MPR selection\n# 2 = use link quality for MPR selection and routing\n\n");
+  WRITE_TO_BUF("LinkQualityLevel\t%d\n\n", cnf->lq_level);
+
+  WRITE_TO_BUF("# Link quality aging factor\n\n");
+  WRITE_TO_BUF("LinkQualityAging\t%f\n\n", cnf->lq_aging);
+
+  WRITE_TO_BUF("# NAT threshold\n\n");
+  WRITE_TO_BUF("NatThreshold\t%f\n\n", cnf->lq_nat_thresh);
+
+  WRITE_TO_BUF("# Clear screen when printing debug output?\n\n");
+  WRITE_TO_BUF("ClearScreen\t%s\n\n", cnf->clear_screen ? "yes" : "no");
+
+  /* Plugins */
+  WRITE_TO_BUF("# Olsrd plugins to load\n# This must be the absolute path to the file\n# or the loader will use the following scheme:\n");
+  WRITE_TO_BUF("# - Try the paths in the LD_LIBRARY_PATH \n#   environment variable.\n# - The list of libraries cached in /etc/ld.so.cache\n# - /lib, followed by /usr/lib\n\n");
+  if(pe)
+    {
+      while(pe)
+	{
+	  WRITE_TO_BUF("LoadPlugin \"%s\" {\n", pe->name);
+          pp = pe->params;
+          while(pp)
+            {
+              WRITE_TO_BUF("    PlParam \"%s\"\t\"%s\"\n", pp->key, pp->value);
+              pp = pp->next;
+            }
+	  WRITE_TO_BUF("}\n");
+	  pe = pe->next;
+	}
+    }
+  WRITE_TO_BUF("\n");
+
+  
+  
+
+  /* Interfaces */
+  WRITE_TO_BUF("# Interfaces\n# Multiple interfaces with the same configuration\n");
+  WRITE_TO_BUF("# can shar the same config block. Just list the\n# interfaces(e.g. Interface \"eth0\" \"eth2\"\n\n");
+  /* Interfaces */
+  if(in)
+    {
+      olsr_bool first = OLSR_TRUE;
+      while(in)
+	{
+	  WRITE_TO_BUF("Interface \"%s\" {\n", in->name);
+
+          if(first)
+	     WRITE_TO_BUF("    # IPv4 broadcast address to use. The\n    # one usefull example would be 255.255.255.255\n    # If not defined the broadcastaddress\n    # every card is configured with is used\n\n");
+
+
+	  if(in->cnf->ipv4_broadcast.v4.s_addr)
+	    {
+	      WRITE_TO_BUF("    Ip4Broadcast\t%s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
+	    }
+	  else
+	    {
+	      if(first)
+    	        WRITE_TO_BUF("    #Ip4Broadcast\t255.255.255.255\n");
+	    }
+	  
+          if(first) WRITE_TO_BUF("\n");
+
+          if(first)
+	      WRITE_TO_BUF("    # IPv6 address scope to use.\n    # Must be 'site-local' or 'global'\n\n");
+	  if(in->cnf->ipv6_addrtype)
+	    WRITE_TO_BUF("    Ip6AddrType \tsite-local\n");
+	  else
+	    WRITE_TO_BUF("    Ip6AddrType \tglobal\n");
+
+          if(first) WRITE_TO_BUF("\n");
+
+          if(first)
+	    WRITE_TO_BUF("    # IPv6 multicast address to use when\n    # using site-local addresses.\n    # If not defined, ff05::15 is used\n");
+	  WRITE_TO_BUF("    Ip6MulticastSite\t%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
+          if(first) WRITE_TO_BUF("\n");
+          if(first)
+	    WRITE_TO_BUF("    # IPv6 multicast address to use when\n    # using global addresses\n    # If not defined, ff0e::1 is used\n");
+	  WRITE_TO_BUF("    Ip6MulticastGlobal\t%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
+          if(first) WRITE_TO_BUF("\n");
+	  
+	  
+          if(first)
+            WRITE_TO_BUF("    # Emission and validity intervals.\n    # If not defined, RFC proposed values will\n    # in most cases be used.\n\n");
+	  
+	  
+	  if(in->cnf->hello_params.emission_interval != HELLO_INTERVAL)
+	    WRITE_TO_BUF("    HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
+          else if(first)
+	    WRITE_TO_BUF("    #HelloInterval\t%0.2f\n", in->cnf->hello_params.emission_interval);
+	  if(in->cnf->hello_params.validity_time != NEIGHB_HOLD_TIME)
+	    WRITE_TO_BUF("    HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
+          else if(first)
+	    WRITE_TO_BUF("    #HelloValidityTime\t%0.2f\n", in->cnf->hello_params.validity_time);
+	  if(in->cnf->tc_params.emission_interval != TC_INTERVAL)
+	    WRITE_TO_BUF("    TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
+          else if(first)
+	    WRITE_TO_BUF("    #TcInterval\t\t%0.2f\n", in->cnf->tc_params.emission_interval);
+	  if(in->cnf->tc_params.validity_time != TOP_HOLD_TIME)
+	    WRITE_TO_BUF("    TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
+          else if(first)
+	    WRITE_TO_BUF("    #TcValidityTime\t%0.2f\n", in->cnf->tc_params.validity_time);
+	  if(in->cnf->mid_params.emission_interval != MID_INTERVAL)
+	    WRITE_TO_BUF("    MidInterval\t\t%0.2f\n", in->cnf->mid_params.emission_interval);
+          else if(first)
+	    WRITE_TO_BUF("    #MidInterval\t%0.2f\n", in->cnf->mid_params.emission_interval);
+	  if(in->cnf->mid_params.validity_time != MID_HOLD_TIME)
+	    WRITE_TO_BUF("    MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
+          else if(first)
+	    WRITE_TO_BUF("    #MidValidityTime\t%0.2f\n", in->cnf->mid_params.validity_time);
+	  if(in->cnf->hna_params.emission_interval != HNA_INTERVAL)
+	    WRITE_TO_BUF("    HnaInterval\t\t%0.2f\n", in->cnf->hna_params.emission_interval);
+          else if(first)
+	    WRITE_TO_BUF("    #HnaInterval\t%0.2f\n", in->cnf->hna_params.emission_interval);
+	  if(in->cnf->hna_params.validity_time != HNA_HOLD_TIME)
+	    WRITE_TO_BUF("    HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);	  
+          else if(first)
+	    WRITE_TO_BUF("    #HnaValidityTime\t%0.2f\n", in->cnf->hna_params.validity_time);	  
+	  
+          mult = in->cnf->lq_mult;
+
+          if (mult == NULL)
+	    {
+              if(first)
+	        WRITE_TO_BUF("    #LinkQualityMult\tdefault 1.0\n");
+	    }
+          else
+	    {
+	      while (mult != NULL)
+		{
+		  WRITE_TO_BUF("    LinkQualityMult\t%s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof (ipv6_buf)), (float)(mult->value) / 65536.0);
+		  mult = mult->next;
+		}
+	    }
+
+	  if(first)
+	    {
+             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);
+	    }
+	  else
+	    {
+              if(first)
+       	        WRITE_TO_BUF("    #Weight\t 0\n\n");
+	    }
+
+	  
+	  WRITE_TO_BUF("}\n\n");
+	  in = in->next;
+	  first = OLSR_FALSE;
+	}
+
+    }
+
+
+  WRITE_TO_BUF("\n# END AUTOGENERATED CONFIG\n");
+
+  return size;
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/local.mk ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/local.mk
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/local.mk	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/local.mk	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,77 @@
+
+# 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.
+#
+
+# avoid the $(if) everywhere
+C=$(if $(CFGDIR),$(CFGDIR)/)
+
+# add the variables as we may have others already there
+SRCS += $(foreach file,olsrd_conf oparse oscan cfgfile_gen,$(C)$(file).c)
+OBJS += $(foreach file,olsrd_conf oparse oscan cfgfile_gen,$(C)$(file).o)
+HDRS += $(foreach file,olsrd_conf oparse,$(C)$(file).h)
+
+$(C)oscan.c: $(C)oscan.lex $(C)Makefile
+	$(FLEX) -Cem -o"$@-tmp" "$<"
+	sed	-e '/^static/s/yy_get_next_buffer[\(][\)]/yy_get_next_buffer(void)/' \
+		-e '/^static/s/yy_get_previous_state[\(][\)]/yy_get_previous_state(void)/' \
+		-e '/^static/s/yygrowstack[\(][\)]/yygrowstack(void)/' \
+		-e '/^static/s/input[\(][\)]/input(void)/' \
+		-e '/^static  *void  *yy_fatal_error/s/^\(.*)\);$$/\1 __attribute__((noreturn));/' \
+		-e 's/register //' \
+		-e '/^#line/s/$(call quote,$@-tmp)/$(call quote,$@)/' \
+		< "$@-tmp" >"$@"
+	$(RM) "$@-tmp"
+
+# we need a dependency to generate oparse before we compile oscan.c
+$(C)oscan.o: $(C)oparse.c
+$(C)oscan.o: CFLAGS := $(filter-out -Wunreachable-code -Wsign-compare,$(CFLAGS)) -Wno-sign-compare
+# we need potentially another -I directory
+$(C)oscan.o: CPPFLAGS += $(if $(CFGDIR),-I$(CFGDIR))
+
+$(C)oparse.c: $(C)oparse.y $(C)olsrd_conf.h $(C)Makefile
+	$(BISON) -d -o "$@-tmp" "$<"
+	sed	-e 's/register //' \
+		-e '/^#line/s/$(call quote,$@-tmp)/$(call quote,$@)/' \
+		< "$@-tmp" >"$@"
+	mv "$(subst .c,.h,$@-tmp)" "$(subst .c,.h,$@)"
+	$(RM) "$@-tmp" "$(subst .c,.h,$@-tmp)"
+
+$(C)oparse.o: CFLAGS := $(filter-out -Wunreachable-code,$(CFLAGS))
+
+# and a few files to be cleaned
+TMPFILES += $(foreach pat,oscan.c oparse.c oparse.h,$(C)$(pat) $(C)$(pat)-tmp)
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,101 @@
+
+# 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.
+#
+
+TOPDIR=../..
+include $(TOPDIR)/Makefile.inc
+
+# delete the variables from above
+SRCS =
+HDRS =
+
+include local.mk
+
+ifeq ($(OS), win32)
+
+LIBNAME ?=	olsrd_cfgparser.dll
+BINNAME ?=	olsrd_cfgparser.exe
+OBJS +=		../win32/compat.o ../ipcalc.o ../builddata.o
+
+else
+
+LIBNAME ?=	olsrd_cfgparser.so.0.1
+BINNAME ?=	olsrd_cfgparser
+endif
+
+
+ifdef MAKEBIN
+
+CPPFLAGS +=	-DMAKEBIN 
+NAME =		$(BINNAME)
+
+else 
+
+# build lib per default
+
+ifeq (${OS}, osx)
+LDFLAGS +=	-dynamiclib -single_module
+else
+LDFLAGS +=	-shared -Wl,-soname,$(LIBNAME)
+endif
+
+ifeq (${OS}, win32)
+LDFLAGS +=	-Wl,--out-implib=libolsrd_cfgparser.a -Wl,--export-all-symbols
+endif
+
+CPPFLAGS +=	-DMAKELIB
+NAME =		$(LIBNAME)
+
+endif
+
+.PHONY: install clean uberclean
+
+# Targets
+default_target: $(NAME)
+
+$(NAME):	$(OBJS)
+		$(CC) $(LDFLAGS) -o "$@" $^ $(LIBS)
+
+install:
+		install -D -m 755 $(NAME) $(LIBDIR)/$(NAME)
+		/sbin/ldconfig -n $(LIBDIR)
+
+clean:
+		rm -f *.[od~] $(LIBNAME) $(BINNAME) $(TMPFILES)
+
+uberclean:	clean
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd_cfgparser.def ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd_cfgparser.def
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd_cfgparser.def	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd_cfgparser.def	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,12 @@
+EXPORTS
+	olsrd_parse_cnf
+	olsrd_sanity_check_cnf
+	olsrd_free_cnf
+	olsrd_print_cnf
+	olsrd_write_cnf
+	olsrd_write_cnf_buf
+	get_default_if_config
+	olsrd_get_default_cnf
+	win32_stdio_hack
+	win32_olsrd_malloc
+	win32_olsrd_free
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd_conf.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd_conf.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd_conf.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd_conf.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,778 @@
+/*
+ * 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 "olsrd_conf.h"
+#include "ipcalc.h"
+#include "olsr_cfg.h"
+#include "defs.h"
+#include "net_olsr.h"
+#include "olsr.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+extern FILE *yyin;
+extern int yyparse(void);
+
+static char copyright_string[] __attribute__((unused)) = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org) All rights reserved.";
+
+int current_line;
+
+/* Global stuff externed in defs.h */
+FILE *debug_handle;             /* Where to send debug(defaults to stdout) */
+struct olsrd_config *olsr_cnf;  /* The global configuration */
+
+#ifdef MAKEBIN
+
+/* Build as standalone binary */
+int 
+main(int argc, char *argv[])
+{
+  struct olsrd_config *cnf;
+
+  if(argc == 1)
+    {
+      fprintf(stderr, "Usage: olsrd_cfgparser [filename] -print\n\n");
+      exit(EXIT_FAILURE);
+    }
+
+  if((cnf = olsrd_parse_cnf(argv[1])) != NULL)
+    {
+      if((argc > 2) && (!strcmp(argv[2], "-print")))
+	{
+	  olsrd_print_cnf(cnf);  
+	  olsrd_write_cnf(cnf, "./out.conf");
+	}
+      else
+        printf("Use -print to view parsed values\n");
+      printf("Configfile parsed OK\n");
+    }
+  else
+    {
+      printf("Failed parsing \"%s\"\n", argv[1]);
+    }
+
+  return 0;
+}
+
+#else
+
+/* Build as part of olsrd */
+
+
+#endif
+
+struct olsrd_config *
+olsrd_parse_cnf(const char *filename)
+{
+  struct olsr_if *in, *new_ifqueue;
+  int rc;
+
+  /* Initialize the global varibles - oparse.y needs it there */
+  olsr_cnf = malloc(sizeof(*olsr_cnf));
+  if (olsr_cnf == NULL) {
+    fprintf(stderr, "Out of memory %s\n", __func__);
+    return NULL;
+  }
+
+  set_default_cnf(olsr_cnf);
+
+  printf("Parsing file: \"%s\"\n", filename);
+
+  yyin = fopen(filename, "r");
+  if (yyin == NULL) {
+    fprintf(stderr, "Cannot open configuration file '%s': %s.\n",
+            filename, strerror(errno));
+    olsrd_free_cnf(olsr_cnf);
+    olsr_cnf = NULL;
+    return NULL;
+  }
+
+  current_line = 1;
+  rc = yyparse();
+  fclose(yyin);
+  if (rc != 0) {
+    olsrd_free_cnf(olsr_cnf);
+    olsr_cnf = NULL;
+    return NULL;
+  }
+
+  /* Reverse the queue (added by user request) */
+  in = olsr_cnf->interfaces;
+  new_ifqueue = NULL;
+
+  while(in) {
+    struct olsr_if *in_tmp = in; 
+    in = in->next;
+
+    in_tmp->next = new_ifqueue;
+    new_ifqueue = in_tmp;
+  }
+
+  olsr_cnf->interfaces = new_ifqueue;
+
+  for (in = olsr_cnf->interfaces; in != NULL; in = in->next) {
+      /* set various stuff */
+      in->configured = OLSR_FALSE;
+      in->interf = NULL;
+      in->host_emul = OLSR_FALSE;
+  }
+  return olsr_cnf;
+}
+
+
+int
+olsrd_sanity_check_cnf(struct olsrd_config *cnf)
+{
+  struct olsr_if           *in = cnf->interfaces;
+  struct if_config_options *io;
+
+  /* Debug level */
+  if(cnf->debug_level < MIN_DEBUGLVL ||
+     cnf->debug_level > MAX_DEBUGLVL)
+    {
+      fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level);
+      return -1;
+    }
+
+  /* IP version */
+  if(cnf->ip_version != AF_INET &&
+     cnf->ip_version != AF_INET6)
+    {
+      fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version);
+      return -1;
+    }
+
+  /* TOS */
+  if(//cnf->tos < MIN_TOS ||
+     cnf->tos > MAX_TOS)
+    {
+      fprintf(stderr, "TOS %d is not allowed\n", cnf->tos);
+      return -1;
+    }
+
+  if(cnf->willingness_auto == OLSR_FALSE &&
+     (cnf->willingness > MAX_WILLINGNESS))
+    {
+      fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness);
+      return -1;
+    }
+
+  /* Hysteresis */
+  if(cnf->use_hysteresis == OLSR_TRUE)
+    {
+      if(cnf->hysteresis_param.scaling < MIN_HYST_PARAM ||
+	 cnf->hysteresis_param.scaling > MAX_HYST_PARAM)
+	{
+	  fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", cnf->hysteresis_param.scaling);
+	  return -1;
+	}
+
+      if(cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low)
+	{
+	  fprintf(stderr, "Hyst upper(%0.2f) thr must be bigger than lower(%0.2f) threshold!\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
+	  return -1;
+	}
+
+      if(cnf->hysteresis_param.thr_high < MIN_HYST_PARAM ||
+	 cnf->hysteresis_param.thr_high > MAX_HYST_PARAM)
+	{
+	  fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_high);
+	  return -1;
+	}
+
+      if(cnf->hysteresis_param.thr_low < MIN_HYST_PARAM ||
+	 cnf->hysteresis_param.thr_low > MAX_HYST_PARAM)
+	{
+	  fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_low);
+	  return -1;
+	}
+    }
+
+  /* Check Link quality dijkstra limit */
+  if (olsr_cnf->lq_dinter < cnf->pollrate && olsr_cnf->lq_dlimit != 255) {
+  	fprintf(stderr, "Link quality dijkstra limit must be higher than pollrate\n");
+  	return -1;
+  }
+  
+  /* Pollrate */
+
+  if(cnf->pollrate < MIN_POLLRATE ||
+     cnf->pollrate > MAX_POLLRATE)
+    {
+      fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate);
+      return -1;
+    }
+
+  /* NIC Changes Pollrate */
+
+  if(cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT ||
+     cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT)
+    {
+      fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate);
+      return -1;
+    }
+
+  /* TC redundancy */
+
+  if(//cnf->tc_redundancy < MIN_TC_REDUNDANCY ||
+     cnf->tc_redundancy > MAX_TC_REDUNDANCY)
+    {
+      fprintf(stderr, "TC redundancy %d is not allowed\n", cnf->tc_redundancy);
+      return -1;
+    }
+
+  /* MPR coverage */
+  if(cnf->mpr_coverage < MIN_MPR_COVERAGE ||
+     cnf->mpr_coverage > MAX_MPR_COVERAGE)
+    {
+      fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage);
+      return -1;
+    }
+
+  /* Link Q and hysteresis cannot be activated at the same time */
+  if(cnf->use_hysteresis == OLSR_TRUE && cnf->lq_level)
+    {
+      fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n");
+      return -1;
+    }
+
+  /* Link quality level */
+
+  if(cnf->lq_level > MAX_LQ_LEVEL)
+    {
+      fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level);
+      return -1;
+    }
+
+  /* Link quality window size */
+  if(cnf->lq_level && (cnf->lq_aging < MIN_LQ_AGING || cnf->lq_aging > MAX_LQ_AGING))
+    {
+      fprintf(stderr, "LQ aging factor %f is not allowed\n", cnf->lq_aging);
+      return -1;
+    }
+
+  /* NAT threshold value */
+  if(cnf->lq_level && (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0))
+    {
+      fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh);
+      return -1;
+    }
+
+  if(in == NULL)
+    {
+      fprintf(stderr, "No interfaces configured!\n");
+      return -1;
+    }
+
+  /* Interfaces */
+  while(in)
+    {
+      io = in->cnf;
+
+      if(in->name == NULL || !strlen(in->name))
+	{
+	  fprintf(stderr, "Interface has no name!\n");
+	  return -1;
+	}
+
+      if(io == NULL)
+	{
+	  fprintf(stderr, "Interface %s has no configuration!\n", in->name);
+	  return -1;
+	}
+	
+      /* HELLO interval */
+
+      if (io->hello_params.validity_time < 0.0)
+      {
+        if (cnf->lq_level == 0)
+          io->hello_params.validity_time = NEIGHB_HOLD_TIME;
+
+        else
+          io->hello_params.validity_time = (int)(REFRESH_INTERVAL / cnf->lq_aging);
+      }
+
+      if(io->hello_params.emission_interval < cnf->pollrate ||
+	 io->hello_params.emission_interval > io->hello_params.validity_time)
+	{
+	  fprintf(stderr, "Bad HELLO parameters! (em: %0.2f, vt: %0.2f)\n", io->hello_params.emission_interval, io->hello_params.validity_time);
+	  return -1;
+	}
+
+      /* TC interval */
+      if(io->tc_params.emission_interval < cnf->pollrate ||
+	 io->tc_params.emission_interval > io->tc_params.validity_time)
+	{
+	  fprintf(stderr, "Bad TC parameters! (em: %0.2f, vt: %0.2f)\n", io->tc_params.emission_interval, io->tc_params.validity_time);
+	  return -1;
+	}
+
+      /* MID interval */
+      if(io->mid_params.emission_interval < cnf->pollrate ||
+	 io->mid_params.emission_interval > io->mid_params.validity_time)
+	{
+	  fprintf(stderr, "Bad MID parameters! (em: %0.2f, vt: %0.2f)\n", io->mid_params.emission_interval, io->mid_params.validity_time);
+	  return -1;
+	}
+
+      /* HNA interval */
+      if(io->hna_params.emission_interval < cnf->pollrate ||
+	 io->hna_params.emission_interval > io->hna_params.validity_time)
+	{
+	  fprintf(stderr, "Bad HNA parameters! (em: %0.2f, vt: %0.2f)\n", io->hna_params.emission_interval, io->hna_params.validity_time);
+	  return -1;
+	}
+
+      in = in->next;
+    }
+
+  return 0;
+}
+
+
+void
+olsrd_free_cnf(struct olsrd_config *cnf)
+{
+  struct ip_prefix_list   *hd,   *h = cnf->hna_entries;
+  struct olsr_if           *ind, *in = cnf->interfaces;
+  struct plugin_entry      *ped, *pe = cnf->plugins;
+  struct olsr_lq_mult      *mult, *next_mult;
+  
+  while(h)
+    {
+      hd = h;
+      h = h->next;
+      free(hd);
+    }
+
+  while(in)
+    {
+      for (mult = in->cnf->lq_mult; mult != NULL; mult = next_mult)
+      {
+        next_mult = mult->next;
+        free(mult);
+      }
+
+      free(in->cnf);
+      ind = in;
+      in = in->next;
+      free(ind->name);
+      free(ind->config);
+      free(ind);
+    }
+
+  while(pe)
+    {
+      ped = pe;
+      pe = pe->next;
+      free(ped->name);
+      free(ped);
+    }
+
+  return;
+}
+
+
+
+struct olsrd_config *
+olsrd_get_default_cnf(void)
+{
+  struct olsrd_config *c = malloc(sizeof(struct olsrd_config));
+  if (c == NULL) {
+    fprintf(stderr, "Out of memory %s\n", __func__);
+    return NULL;
+  }
+
+  set_default_cnf(c);
+  return c;
+}
+
+
+
+
+void
+set_default_cnf(struct olsrd_config *cnf)
+{
+    memset(cnf, 0, sizeof(*cnf));
+    
+    cnf->debug_level = DEF_DEBUGLVL;
+    cnf->no_fork = OLSR_FALSE;
+    cnf->host_emul = OLSR_FALSE;
+    cnf->ip_version  = AF_INET;
+    cnf->ipsize = sizeof(struct in_addr);
+    cnf->maxplen = 32;
+    cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
+    cnf->tos = DEF_TOS;
+    cnf->rttable = 254;
+    cnf->rttable_default = 0;
+    cnf->willingness_auto = DEF_WILL_AUTO;
+    cnf->ipc_connections = DEF_IPC_CONNECTIONS;
+    cnf->fib_metric = DEF_FIB_METRIC;
+
+    cnf->use_hysteresis = DEF_USE_HYST;
+    cnf->hysteresis_param.scaling = HYST_SCALING;
+    cnf->hysteresis_param.thr_high = HYST_THRESHOLD_HIGH;
+    cnf->hysteresis_param.thr_low = HYST_THRESHOLD_LOW;
+
+    cnf->pollrate = DEF_POLLRATE;
+    cnf->nic_chgs_pollrate = DEF_NICCHGPOLLRT;
+
+    cnf->tc_redundancy = TC_REDUNDANCY;
+    cnf->mpr_coverage = MPR_COVERAGE;
+    cnf->lq_level = DEF_LQ_LEVEL;
+    cnf->lq_fish = DEF_LQ_FISH;
+    cnf->lq_dlimit = DEF_LQ_DIJK_LIMIT;
+    cnf->lq_dinter = DEF_LQ_DIJK_INTER;
+    cnf->lq_aging = DEF_LQ_AGING;
+    cnf->lq_algorithm = NULL;
+    cnf->lq_nat_thresh = DEF_LQ_NAT_THRESH;
+    cnf->clear_screen = DEF_CLEAR_SCREEN;
+
+    cnf->del_gws = OLSR_FALSE;
+    cnf->will_int = 10 * HELLO_INTERVAL;
+    cnf->max_jitter = 0.0;
+    cnf->exit_value = EXIT_SUCCESS;
+    cnf->max_tc_vtime = 0.0;
+    cnf->ioctl_s = 0;
+#if LINUX_POLICY_ROUTING
+    cnf->rtnl_s = 0;
+#endif
+
+#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
+    cnf->rts = 0;
+#endif
+}
+
+
+
+
+struct if_config_options *
+get_default_if_config(void)
+{
+  struct in6_addr in6;
+  struct if_config_options *io = malloc(sizeof(*io));
+
+  if(io == NULL) {
+    fprintf(stderr, "Out of memory %s\n", __func__);
+    return NULL;
+  }
+
+  memset(io, 0, sizeof(*io));
+
+  io->ipv6_addrtype = 1; /* XXX - FixMe */
+
+  inet_pton(AF_INET6, OLSR_IPV6_MCAST_SITE_LOCAL, &in6);
+  io->ipv6_multi_site.v6 = in6;
+
+  inet_pton(AF_INET6, OLSR_IPV6_MCAST_GLOBAL, &in6);
+  io->ipv6_multi_glbl.v6 = in6;
+
+  io->lq_mult = NULL;
+
+  io->weight.fixed = OLSR_FALSE;
+  io->weight.value = 0;
+
+  io->ipv6_addrtype = 0; /* global */
+
+  io->hello_params.emission_interval = HELLO_INTERVAL;
+  io->hello_params.validity_time = NEIGHB_HOLD_TIME;
+  io->tc_params.emission_interval = TC_INTERVAL;
+  io->tc_params.validity_time = TOP_HOLD_TIME;
+  io->mid_params.emission_interval = MID_INTERVAL;
+  io->mid_params.validity_time = MID_HOLD_TIME;
+  io->hna_params.emission_interval = HNA_INTERVAL;
+  io->hna_params.validity_time = HNA_HOLD_TIME;
+  io->autodetect_chg = OLSR_TRUE;
+
+  return io;
+
+}
+
+
+
+void
+olsrd_print_cnf(struct olsrd_config *cnf)
+{
+  struct ip_prefix_list   *h  = cnf->hna_entries;
+  struct olsr_if           *in = cnf->interfaces;
+  struct plugin_entry      *pe = cnf->plugins;
+  struct ip_prefix_list    *ie = cnf->ipc_nets;
+  struct olsr_lq_mult      *mult;
+  char ipv6_buf[100];             /* buffer for IPv6 inet_htop */
+
+  printf(" *** olsrd configuration ***\n");
+
+  printf("Debug Level      : %d\n", cnf->debug_level);
+  if(cnf->ip_version == AF_INET6)
+    printf("IpVersion        : 6\n");
+  else
+    printf("IpVersion        : 4\n");
+  if(cnf->allow_no_interfaces)
+    printf("No interfaces    : ALLOWED\n");
+  else
+    printf("No interfaces    : NOT ALLOWED\n");
+  printf("TOS              : 0x%02x\n", cnf->tos);
+  printf("RtTable          : 0x%02x\n", cnf->rttable);
+  printf("RtTableDefault   : 0x%02x\n", cnf->rttable_default);
+  if(cnf->willingness_auto)
+    printf("Willingness      : AUTO\n");
+  else
+    printf("Willingness      : %d\n", cnf->willingness);
+
+  printf("IPC connections  : %d\n", cnf->ipc_connections);
+  while(ie)
+    {
+      struct ipaddr_str strbuf;
+      if (ie->net.prefix_len == olsr_cnf->maxplen) {
+          printf("\tHost %s\n", olsr_ip_to_string(&strbuf, &ie->net.prefix));
+      } else {
+          printf("\tNet %s/%d\n", olsr_ip_to_string(&strbuf, &ie->net.prefix), ie->net.prefix_len);
+      }
+      ie = ie->next;
+    }
+
+
+  printf("Pollrate         : %0.2f\n", cnf->pollrate);
+
+  printf("NIC ChangPollrate: %0.2f\n", cnf->nic_chgs_pollrate);
+
+  printf("TC redundancy    : %d\n", cnf->tc_redundancy);
+
+  printf("MPR coverage     : %d\n", cnf->mpr_coverage);
+   
+  printf("LQ level         : %d\n", cnf->lq_level);
+
+  printf("LQ fish eye      : %d\n", cnf->lq_fish);
+
+  printf("LQ Dijkstra limit: %d, %0.2f\n", cnf->lq_dlimit, cnf->lq_dinter);
+
+  printf("LQ aging factor  : %f\n", cnf->lq_aging);
+
+  printf("LQ algorithm name: %s\n", cnf->lq_algorithm ? cnf->lq_algorithm : "default");
+  
+  printf("NAT threshold    : %f\n", cnf->lq_nat_thresh);
+
+  printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
+
+  /* Interfaces */
+  if(in)
+    {
+      printf("Interfaces:\n");
+      while(in)
+	{
+	  printf(" dev: \"%s\"\n", in->name);
+	  
+	  if(in->cnf->ipv4_broadcast.v4.s_addr)
+	    {
+	      printf("\tIPv4 broadcast           : %s\n", inet_ntoa(in->cnf->ipv4_broadcast.v4));
+	    }
+	  else
+	    {
+	      printf("\tIPv4 broadcast           : AUTO\n");
+	    }
+	  
+	  printf("\tIPv6 addrtype            : %s\n", in->cnf->ipv6_addrtype ? "site-local" : "global");
+	  
+	  //union olsr_ip_addr       ipv6_multi_site;
+	  //union olsr_ip_addr       ipv6_multi_glbl;
+	  printf("\tIPv6 multicast site/glbl : %s", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_site.v6, ipv6_buf, sizeof(ipv6_buf)));
+	  printf("/%s\n", inet_ntop(AF_INET6, &in->cnf->ipv6_multi_glbl.v6, ipv6_buf, sizeof(ipv6_buf)));
+	  
+	  printf("\tHELLO emission/validity  : %0.2f/%0.2f\n", in->cnf->hello_params.emission_interval, in->cnf->hello_params.validity_time);
+	  printf("\tTC emission/validity     : %0.2f/%0.2f\n", in->cnf->tc_params.emission_interval, in->cnf->tc_params.validity_time);
+	  printf("\tMID emission/validity    : %0.2f/%0.2f\n", in->cnf->mid_params.emission_interval, in->cnf->mid_params.validity_time);
+	  printf("\tHNA emission/validity    : %0.2f/%0.2f\n", in->cnf->hna_params.emission_interval, in->cnf->hna_params.validity_time);
+	  
+          for (mult = in->cnf->lq_mult; mult != NULL; mult = mult->next)
+          {
+            printf("\tLinkQualityMult          : %s %0.2f\n", inet_ntop(cnf->ip_version, &mult->addr, ipv6_buf, sizeof (ipv6_buf)), (float)(mult->value)/65536.0);
+          }
+
+          printf("\tAutodetetc changes       : %s\n", in->cnf->autodetect_chg ? "yes" : "no");
+
+	  in = in->next;
+	}
+    }
+
+
+
+
+  /* Plugins */
+  if(pe)
+    {
+      printf("Plugins:\n");
+
+      while(pe)
+	{
+	  printf("\tName: \"%s\"\n", pe->name);
+	  pe = pe->next;
+	}
+    }
+
+  /* Hysteresis */
+  if(cnf->use_hysteresis) {
+    printf("Using hysteresis:\n");
+    printf("\tScaling      : %0.2f\n", cnf->hysteresis_param.scaling);
+    printf("\tThr high/low : %0.2f/%0.2f\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low);
+  } else {
+    printf("Not using hysteresis\n");
+  }
+
+  /* HNA IPv4 and IPv6 */
+  if(h) {
+    printf("HNA%d entries:\n", cnf->ip_version == AF_INET ? 4 : 6);
+    while(h) {
+      struct ipaddr_str buf;
+      printf("\t%s/", olsr_ip_to_string(&buf, &h->net.prefix));
+      if (cnf->ip_version == AF_INET) {
+        union olsr_ip_addr ip;
+        olsr_prefix_to_netmask(&ip, h->net.prefix_len);
+        printf("%s\n", olsr_ip_to_string(&buf, &ip));
+      } else {
+        printf("%d\n", h->net.prefix_len);
+      }
+      h = h->next;
+    }
+  }
+}
+
+#if defined WIN32
+struct ioinfo
+{
+	unsigned int handle;
+	unsigned char attr;
+	char buff;
+	int flag;
+	CRITICAL_SECTION lock;
+};
+
+void win32_stdio_hack(unsigned int handle)
+{
+  HMODULE lib;
+  struct ioinfo **info;
+
+  lib = LoadLibrary("msvcrt.dll");
+
+  info = (struct ioinfo **)GetProcAddress(lib, "__pioinfo");
+
+  // (*info)[1].handle = handle;
+  // (*info)[1].attr = 0x89; // FOPEN | FTEXT | FPIPE;
+
+  (*info)[2].handle = handle;
+  (*info)[2].attr = 0x89;
+
+  // stdout->_file = 1;
+  stderr->_file = 2;
+
+  // setbuf(stdout, NULL);
+  setbuf(stderr, NULL);
+}
+
+void*
+win32_olsrd_malloc(size_t size)
+{
+	return malloc(size);
+}
+
+void
+win32_olsrd_free(void* ptr)
+{
+	free(ptr);
+}
+#endif
+
+void ip_prefix_list_add(struct ip_prefix_list **list,
+                        const union olsr_ip_addr *net,
+                        olsr_u8_t prefix_len)
+{
+  struct ip_prefix_list *new_entry = malloc(sizeof(*new_entry));
+  
+  new_entry->net.prefix = *net;
+  new_entry->net.prefix_len = prefix_len;
+
+  /* Queue */
+  new_entry->next = *list;
+  *list = new_entry;
+}
+
+int ip_prefix_list_remove(struct ip_prefix_list **list,
+                          const union olsr_ip_addr *net,
+                          olsr_u8_t prefix_len)
+{
+  struct ip_prefix_list *h = *list, *prev = NULL;
+
+  while (h != NULL) {
+    if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) {
+      /* Dequeue */
+      if (prev == NULL) {
+        *list = h->next;
+      } else {
+        prev->next = h->next;
+      }
+      free(h);
+      return 1;
+    }
+    prev = h;
+    h = h->next;
+  }
+  return 0;
+}
+
+struct ip_prefix_list *ip_prefix_list_find(struct ip_prefix_list *list,
+                                           const union olsr_ip_addr *net,
+                                           olsr_u8_t prefix_len)
+{
+  struct ip_prefix_list *h;
+  for (h = list; h != NULL; h = h->next) {
+    if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) {
+      return h;
+    }
+  }
+  return NULL;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd.conf.example ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd.conf.example
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd.conf.example	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd.conf.example	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,287 @@
+#
+# UniK OLSR daemon config file
+#
+# Lines starting with a # are discarded
+#
+
+# Debug level(0-9)
+# If set to 0 the daemon runs in the background
+
+DebugLevel	1
+
+# IP version to use (4 or 6)
+
+IpVersion	4
+
+# HNA IPv4 routes
+# syntax: netaddr netmask
+# Example Internet gateway:
+# 0.0.0.0 0.0.0.0
+
+Hna4
+{
+    0.0.0.0   0.0.0.0
+    15.15.0.0 255.255.255.0
+    15.16.0.0 255.255.255.0
+}
+
+# HNA IPv6 routes
+# syntax: netaddr prefix
+# Example Internet gateway:
+Hna6
+{
+     ::              0
+    fecb:ab:ed:: 48
+    fecb:ff:dd::dd:d 48
+    fec0:2200:106:: 48
+    fec0:2200:106:0:0:0:0:0 48
+}
+
+
+# Should olsrd keep on running even if there are
+# no interfaces available? This is a good idea
+# for a PCMCIA/USB hotswap environment.
+# "yes" OR "no"
+
+AllowNoInt	yes
+
+# TOS(type of service) value for
+# the IP header of control traffic.
+# If not set it will default to 16
+
+#TosValue	16
+
+# The fixed willingness to use(0-7)
+# If not set willingness will be calculated
+# dynammically based on battery/power status
+
+#Willingness    	4
+
+# Allow processes like the GUI front-end
+# to connect to the daemon.
+
+IpcConnect
+{
+     # Determines how many simultaneously
+     # IPC connections that will be allowed
+     # Setting this to 0 disables IPC
+
+     MaxConnections  1
+
+     # By default only 127.0.0.1 is allowed
+     # to connect. Here allowed hosts can
+     # be added
+
+     Host            127.0.0.1
+     Host            10.0.0.5
+
+     # Specify entire net-ranges that are 
+     # allowed to connect
+
+     Net             192.168.1.0 255.255.255.0     
+}
+
+# Wether to use hysteresis or not
+# Hysteresis adds more robustness to the
+# link sensing but delays neighbor registration.
+# Used by default. 'yes' or 'no'
+
+UseHysteresis	yes
+
+# Hysteresis parameters
+# Do not alter these unless you know 
+# what you are doing!
+# Set to auto by default. Allowed
+# values are floating point values
+# in the interval 0,1
+# THR_LOW must always be lower than
+# THR_HIGH!!
+
+#HystScaling	0.50
+#HystThrHigh	0.80
+#HystThrLow	0.30
+
+
+# Polling rate in seconds(float). 
+# Default value 0.05 sec
+
+Pollrate	0.05
+
+
+# TC redundancy
+# Specifies how much neighbor info should
+# be sent in TC messages
+# Possible values are:
+# 0 - only send MPR selectors
+# 1 - send MPR selectors and MPRs
+# 2 - send all neighbors
+#
+# defaults to 0
+
+TcRedundancy	0
+
+#
+# NatThreshold 
+#
+# (currently this is only in the freifunk firmware)
+# If the NAT-Endpoint (the preferred 0/0 HNA 
+# emitting node) is to be changed, the ETX value of the current 0/0 is 
+# compared to the new one. If the ETX difference is too small, the default 
+# route isn't changed. 
+#NatThreshold  0.9
+
+#
+# MPR coverage
+# Specifies how many MPRs a node should
+# try select to reach every 2 hop neighbor
+#
+# Can be set to any integer >0
+#
+# defaults to 1
+
+MprCoverage	1
+
+
+# Olsrd plugins to load
+# This must be the absolute path to the file
+# or the loader will use the following scheme:
+# - Try the paths in the LD_LIBRARY_PATH 
+#   environment variable.
+# - The list of libraries cached in /etc/ld.so.cache
+# - /lib, followed by /usr/lib
+LoadPlugin "olsrd_secure.so.0.3"
+{
+    PlParam     "key1"   "value1"
+    # Might be possible to set options here in
+    # future versions
+}
+
+LoadPlugin "olsrd_dyn_gw.so.0.1"
+{
+    PlParam     "key4"   "value3"
+    # Might be possible to set options here in
+    # future versions
+}
+
+# olsrd_dyn_gw.so.0.1
+# olsrd_power.so.0.1
+
+
+
+
+# Interfaces and their rules
+# Omitted options will be set to the
+# default values.
+Interface "eth0"
+{
+
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    Ip4Broadcast	255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    # Ip6AddrType		site-local
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+
+    Ip6MulticastSite	ff05::11
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+
+    # Ip6MulticastGlobal	ff0e::1
+
+
+    # Emission intervals.
+    # If not defined, RFC proposed values will
+    # be used in most cases.
+
+    # Hello interval in seconds(float)
+    # HelloInterval    2.0
+
+    # HELLO validity time
+    # HelloValidityTime	6.0
+
+    # TC interval in seconds(float)
+    TcInterval        5.0
+
+    # TC validity time
+    # TcValidityTime	15.0
+
+    # MID interval in seconds(float)
+    # MidInterval	5.0
+
+    # MID validity time
+    # MidValidityTime	15.0
+
+    # HNA interval in seconds(float)
+    # HnaInterval	5.0
+
+    # HNA validity time
+    # HnaValidityTime 	15.0
+}
+
+Interface "eth1"
+{
+    # IPv4 broadcast address to use. The
+    # one usefull example would be 255.255.255.255
+    # If not defined the broadcastaddress
+    # every card is configured with is used
+
+    # Ip4Broadcast	255.255.255.255
+
+    # IPv6 address scope to use.
+    # Must be 'site-local' or 'global'
+
+    Ip6AddrType		site-local
+
+    # IPv6 multicast address to use when
+    # using site-local addresses.
+    # If not defined, ff05::15 is used
+
+    Ip6MulticastSite	ff05::15
+
+    # IPv6 multicast address to use when
+    # using global addresses
+    # If not defined, ff0e::1 is used
+
+    Ip6MulticastGlobal	ff0e::1
+
+
+    # Emission intervals.
+    # If not defined, RFC proposed values will
+    # be used in most cases.
+
+    # Hello interval in seconds(float)
+    HelloInterval    1.0
+
+    # HELLO validity time
+    HelloValidityTime	3.0
+
+    # TC interval in seconds(float)
+    TcInterval        4.0
+
+    # TC validity time
+    TcValidityTime	14.0
+
+    # MID interval in seconds(float)
+    MidInterval	5.0
+
+    # MID validity time
+    MidValidityTime	15.0
+
+    # HNA interval in seconds(float)
+    HnaInterval	5.0
+
+    # HNA validity time
+    HnaValidityTime 	15.0
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd_conf.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd_conf.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/olsrd_conf.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/olsrd_conf.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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_CONF_H
+#define _OLSRD_CONF_H
+
+#include "olsr_protocol.h"
+#include "olsr_cfg.h"
+
+#define PARSER_VERSION "0.1.2"
+
+
+extern int current_line;
+
+struct conf_token
+{
+  olsr_u32_t integer;
+  float      floating;
+  olsr_bool  boolean;
+  char       *string;
+};
+
+void
+set_default_cnf(struct olsrd_config *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/oparse.y ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/oparse.y
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/oparse.y	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/oparse.y	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1086 @@
+%{
+
+/*
+ * 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 "olsrd_conf.h"
+#include "../defs.h"
+#include "../ipcalc.h"
+#include "../net_olsr.h"
+#include "../link_set.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#define PARSER_DEBUG 0
+
+#if PARSER_DEBUG
+#define PARSER_DEBUG_PRINTF(x, ...)   printf(x, ##args)
+#else
+#define PARSER_DEBUG_PRINTF(x, ...)   do { } while (0)
+#endif
+
+#define YYSTYPE struct conf_token *
+
+void yyerror(const char *);
+int yylex(void);
+
+static int ifs_in_curr_cfg = 0;
+
+static int lq_mult_helper(YYSTYPE ip_addr_arg, YYSTYPE mult_arg);
+static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg);
+
+static int lq_mult_helper(YYSTYPE ip_addr_arg, YYSTYPE mult_arg)
+{
+  union olsr_ip_addr addr;
+  int i;
+  struct olsr_if *walker;
+
+#if PARSER_DEBUG > 0
+  printf("\tLinkQualityMult %s %0.2f\n",
+         (ip_addr_arg != NULL) ? ip_addr_arg->string : "any",
+         mult_arg->floating);
+#endif
+
+  memset(&addr, 0, sizeof(addr));
+
+  if (ip_addr_arg != NULL &&
+     inet_pton(olsr_cnf->ip_version, ip_addr_arg->string, &addr) <= 0) {
+    fprintf(stderr, "Cannot parse IP address %s.\n", ip_addr_arg->string);
+    return -1;
+  }
+
+  walker = olsr_cnf->interfaces;
+
+  for (i = 0; i < ifs_in_curr_cfg; i++) {
+    struct olsr_lq_mult *mult = malloc(sizeof(*mult));
+    if (mult == NULL) {
+      fprintf(stderr, "Out of memory (LQ multiplier).\n");
+      return -1;
+    }
+
+    mult->addr = addr;
+    mult->value = (olsr_u32_t)(mult_arg->floating * LINK_LOSS_MULTIPLIER);
+
+    mult->next = walker->cnf->lq_mult;
+    walker->cnf->lq_mult = mult;
+
+    walker = walker->next;
+  }
+
+  if (ip_addr_arg != NULL) {
+    free(ip_addr_arg->string);
+    free(ip_addr_arg);
+  }
+
+  free(mult_arg);
+
+  return 0;
+}
+
+static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
+{
+  union olsr_ip_addr ipaddr;
+  PARSER_DEBUG_PRINTF("HNA IPv6 entry: %s/%d\n", ipaddr_arg->string, prefixlen_arg->integer);
+
+  if (olsr_cnf->ip_version != AF_INET6) {
+    fprintf(stderr, "IPv6 addresses can only be used if \"IpVersion\" == 6\n");
+    return 1;
+  }
+
+  if(inet_pton(AF_INET6, ipaddr_arg->string, &ipaddr) <= 0) {
+    fprintf(stderr, "ihna6entry: Failed converting IP address %s\n", ipaddr_arg->string);
+    return 1;
+  }
+
+  if (prefixlen_arg->integer > 128) {
+    fprintf(stderr, "ihna6entry: Illegal IPv6 prefix length %d\n", prefixlen_arg->integer);
+    return 1;
+  }
+
+  /* Queue */
+  ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, prefixlen_arg->integer);
+
+  free(ipaddr_arg->string);
+  free(ipaddr_arg);
+  free(prefixlen_arg);
+
+  return 0;
+}
+
+%}
+
+%token TOK_SLASH
+%token TOK_OPEN
+%token TOK_CLOSE
+
+%token TOK_STRING
+%token TOK_INTEGER
+%token TOK_FLOAT
+%token TOK_BOOLEAN
+
+%token TOK_IP6TYPE
+
+%token TOK_DEBUGLEVEL
+%token TOK_IPVERSION
+%token TOK_HNA4
+%token TOK_HNA6
+%token TOK_PLUGIN
+%token TOK_INTERFACE
+%token TOK_NOINT
+%token TOK_TOS
+%token TOK_RTTABLE
+%token TOK_RTTABLE_DEFAULT
+%token TOK_WILLINGNESS
+%token TOK_IPCCON
+%token TOK_FIBMETRIC
+%token TOK_USEHYST
+%token TOK_HYSTSCALE
+%token TOK_HYSTUPPER
+%token TOK_HYSTLOWER
+%token TOK_POLLRATE
+%token TOK_NICCHGSPOLLRT
+%token TOK_TCREDUNDANCY
+%token TOK_MPRCOVERAGE
+%token TOK_LQ_LEVEL
+%token TOK_LQ_FISH
+%token TOK_LQ_DLIMIT
+%token TOK_LQ_WSIZE
+%token TOK_LQ_AGING
+%token TOK_LQ_PLUGIN
+%token TOK_LQ_NAT_THRESH
+%token TOK_LQ_MULT
+%token TOK_CLEAR_SCREEN
+%token TOK_PLPARAM
+
+%token TOK_HOSTLABEL
+%token TOK_NETLABEL
+%token TOK_MAXIPC
+
+%token TOK_IP4BROADCAST
+%token TOK_IP6ADDRTYPE
+%token TOK_IP6MULTISITE
+%token TOK_IP6MULTIGLOBAL
+%token TOK_IFWEIGHT
+%token TOK_HELLOINT
+%token TOK_HELLOVAL
+%token TOK_TCINT
+%token TOK_TCVAL
+%token TOK_MIDINT
+%token TOK_MIDVAL
+%token TOK_HNAINT
+%token TOK_HNAVAL
+%token TOK_AUTODETCHG
+
+%token TOK_IP4_ADDR
+%token TOK_IP6_ADDR
+%token TOK_DEFAULT
+
+%token TOK_COMMENT
+
+%%
+
+conf:
+          | conf block
+          | conf stmt
+;
+
+stmt:       idebug
+          | iipversion
+          | fibmetric
+          | bnoint
+          | atos
+          | arttable
+          | arttable_default
+          | awillingness
+          | busehyst
+          | fhystscale
+          | fhystupper
+          | fhystlower
+          | fpollrate
+          | fnicchgspollrt
+          | atcredundancy
+          | amprcoverage
+          | alq_level
+          | alq_plugin
+          | alq_fish
+          | alq_dlimit
+          | anat_thresh
+          | alq_wsize
+          | alq_aging
+          | bclear_screen
+          | vcomment
+;
+
+block:      TOK_HNA4 hna4body
+          | TOK_HNA6 hna6body
+          | TOK_IPCCON ipcbody
+          | ifblock ifbody
+          | plblock plbody
+;
+
+hna4body:       TOK_OPEN hna4stmts TOK_CLOSE
+;
+
+hna4stmts: | hna4stmts hna4stmt
+;
+
+hna4stmt:  vcomment
+         | ihna4entry
+;
+
+hna6body:       TOK_OPEN hna6stmts TOK_CLOSE
+;
+
+hna6stmts: | hna6stmts hna6stmt
+;
+
+hna6stmt:  vcomment
+         | ihna6entry
+;
+
+ipcbody:    TOK_OPEN ipcstmts TOK_CLOSE
+;
+
+ipcstmts: | ipcstmts ipcstmt
+;
+
+ipcstmt:  vcomment
+          | imaxipc
+          | ipchost
+          | ipcnet
+;
+
+ifblock:   ifstart ifnicks
+;
+
+ifnicks:   | ifnicks ifnick
+;
+
+ifbody:     TOK_OPEN ifstmts TOK_CLOSE
+;
+
+ifstmts:   | ifstmts ifstmt
+;
+
+ifstmt:      vcomment
+             | iifweight
+             | isetip4br
+             | isetip6addrt
+             | isetip6mults
+             | isetip6multg
+             | isethelloint
+             | isethelloval
+             | isettcint
+             | isettcval
+             | isetmidint
+             | isetmidval
+             | isethnaint
+             | isethnaval
+             | isetautodetchg
+             | isetlqmult
+;
+
+plbody:     TOK_OPEN plstmts TOK_CLOSE
+;
+
+plstmts:   | plstmts plstmt
+;
+
+plstmt:     plparam
+          | vcomment
+;
+
+imaxipc: TOK_MAXIPC TOK_INTEGER
+{
+  olsr_cnf->ipc_connections = $2->integer;
+  free($2);
+}
+;
+
+ipchost: TOK_HOSTLABEL TOK_IP4_ADDR
+{
+  union olsr_ip_addr ipaddr;
+  PARSER_DEBUG_PRINTF("\tIPC host: %s\n", $2->string);
+  
+  if (inet_aton($2->string, &ipaddr.v4) == 0) {
+    fprintf(stderr, "Failed converting IP address IPC %s\n", $2->string);
+    YYABORT;
+  }
+
+  ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_cnf->maxplen);
+
+  free($2->string);
+  free($2);
+}
+;
+
+ipcnet: TOK_NETLABEL TOK_IP4_ADDR TOK_IP4_ADDR
+{
+  union olsr_ip_addr ipaddr, netmask;
+
+  PARSER_DEBUG_PRINTF("\tIPC net: %s/%s\n", $2->string, $3->string);
+  
+  if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) {
+    fprintf(stderr, "Failed converting IP net IPC %s\n", $2->string);
+    YYABORT;
+  }
+
+  if (inet_pton(AF_INET, $3->string, &netmask.v4) == 0) {
+    fprintf(stderr, "Failed converting IP mask IPC %s\n", $3->string);
+    YYABORT;
+  }
+
+  ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_netmask_to_prefix(&netmask));
+
+  free($2->string);
+  free($2);
+  free($3->string);
+  free($3);
+}
+        |       TOK_NETLABEL TOK_IP4_ADDR TOK_SLASH TOK_INTEGER
+{
+  union olsr_ip_addr ipaddr;
+
+  PARSER_DEBUG_PRINTF("\tIPC net: %s/%s\n", $2->string, $3->string);
+  
+  if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) {
+    fprintf(stderr, "Failed converting IP net IPC %s\n", $2->string);
+    YYABORT;
+  }
+
+  if ($4->integer > olsr_cnf->maxplen) {
+    fprintf(stderr, "ipcnet: Prefix len %u > %d is not allowed!\n", $4->integer, olsr_cnf->maxplen);
+    YYABORT;
+  }
+
+  ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, $4->integer);
+
+  free($2->string);
+  free($2);
+  free($4);
+}
+;
+
+iifweight:       TOK_IFWEIGHT TOK_INTEGER
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("Fixed willingness: %d\n", $2->integer);
+
+  while (ifcnt) {
+    ifs->cnf->weight.value = $2->integer;
+    ifs->cnf->weight.fixed = OLSR_TRUE;
+
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+
+isetip4br: TOK_IP4BROADCAST TOK_IP4_ADDR
+{
+  struct in_addr in;
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tIPv4 broadcast: %s\n", $2->string);
+
+  if (inet_aton($2->string, &in) == 0) {
+    fprintf(stderr, "isetip4br: Failed converting IP address %s\n", $2->string);
+    YYABORT;
+  }
+
+  while (ifcnt) {
+    ifs->cnf->ipv4_broadcast.v4 = in;
+
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2->string);
+  free($2);
+}
+;
+
+isetip6addrt: TOK_IP6ADDRTYPE TOK_IP6TYPE
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  if ($2->boolean) {
+    while (ifcnt) {
+      ifs->cnf->ipv6_addrtype = IPV6_ADDR_SITELOCAL;
+	  
+      ifs = ifs->next;
+      ifcnt--;
+    }
+  } else {
+    while (ifcnt) {
+      ifs->cnf->ipv6_addrtype = 0;
+	  
+      ifs = ifs->next;
+      ifcnt--;
+    }
+  }
+
+  free($2);
+}
+;
+
+isetip6mults: TOK_IP6MULTISITE TOK_IP6_ADDR
+{
+  struct in6_addr in6;
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tIPv6 site-local multicast: %s\n", $2->string);
+
+  if (inet_pton(AF_INET6, $2->string, &in6) <= 0) {
+    fprintf(stderr, "isetip6mults: Failed converting IP address %s\n", $2->string);
+    YYABORT;
+  }
+
+  while (ifcnt) {
+    ifs->cnf->ipv6_multi_site.v6 = in6;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2->string);
+  free($2);
+}
+;
+
+
+isetip6multg: TOK_IP6MULTIGLOBAL TOK_IP6_ADDR
+{
+  struct in6_addr in6;
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tIPv6 global multicast: %s\n", $2->string);
+
+  if (inet_pton(AF_INET6, $2->string, &in6) <= 0) {
+    fprintf(stderr, "isetip6multg: Failed converting IP address %s\n", $2->string);
+    YYABORT;
+  }
+
+  while (ifcnt) {
+    //memcpy(&ifs->cnf->ipv6_multi_glbl.v6, &in6, sizeof(struct in6_addr));
+    ifs->cnf->ipv6_multi_glbl.v6 = in6;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2->string);
+  free($2);
+}
+;
+isethelloint: TOK_HELLOINT TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tHELLO interval: %0.2f\n", $2->floating);
+
+  while (ifcnt) {
+    ifs->cnf->hello_params.emission_interval = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isethelloval: TOK_HELLOVAL TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tHELLO validity: %0.2f\n", $2->floating);
+
+  while (ifcnt) {
+    ifs->cnf->hello_params.validity_time = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isettcint: TOK_TCINT TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tTC interval: %0.2f\n", $2->floating);
+
+  while (ifcnt) {
+    ifs->cnf->tc_params.emission_interval = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+  free($2);
+}
+;
+isettcval: TOK_TCVAL TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+  
+  PARSER_DEBUG_PRINTF("\tTC validity: %0.2f\n", $2->floating);
+  while (ifcnt) {
+    ifs->cnf->tc_params.validity_time = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isetmidint: TOK_MIDINT TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+
+  PARSER_DEBUG_PRINTF("\tMID interval: %0.2f\n", $2->floating);
+  while (ifcnt) {
+    ifs->cnf->mid_params.emission_interval = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isetmidval: TOK_MIDVAL TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tMID validity: %0.2f\n", $2->floating);
+  while (ifcnt) {
+    ifs->cnf->mid_params.validity_time = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isethnaint: TOK_HNAINT TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+  
+  PARSER_DEBUG_PRINTF("\tHNA interval: %0.2f\n", $2->floating);
+  while (ifcnt) {
+    ifs->cnf->hna_params.emission_interval = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isethnaval: TOK_HNAVAL TOK_FLOAT
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tHNA validity: %0.2f\n", $2->floating);
+  while (ifcnt) {
+    ifs->cnf->hna_params.validity_time = $2->floating;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+isetautodetchg: TOK_AUTODETCHG TOK_BOOLEAN
+{
+  int ifcnt = ifs_in_curr_cfg;
+  struct olsr_if *ifs = olsr_cnf->interfaces;
+
+  PARSER_DEBUG_PRINTF("\tAutodetect changes: %s\n", $2->boolean ? "YES" : "NO");
+  while (ifcnt) {
+    ifs->cnf->autodetect_chg = $2->boolean;
+      
+    ifs = ifs->next;
+    ifcnt--;
+  }
+
+  free($2);
+}
+;
+
+isetlqmult: TOK_LQ_MULT TOK_DEFAULT TOK_FLOAT
+{
+  if (lq_mult_helper($2, $3) < 0) {
+    YYABORT;
+  }
+}
+
+          | TOK_LQ_MULT TOK_IP4_ADDR TOK_FLOAT
+{
+  if (lq_mult_helper($2, $3) < 0) {
+    YYABORT;
+  }
+}
+
+          | TOK_LQ_MULT TOK_IP6_ADDR TOK_FLOAT
+{
+  if (lq_mult_helper($2, $3) < 0) {
+    YYABORT;
+  }
+}
+;
+
+idebug:       TOK_DEBUGLEVEL TOK_INTEGER
+{
+  olsr_cnf->debug_level = $2->integer;
+  PARSER_DEBUG_PRINTF("Debug level: %d\n", olsr_cnf->debug_level);
+  free($2);
+}
+;
+
+
+iipversion:    TOK_IPVERSION TOK_INTEGER
+{
+  if ($2->integer == 4) {
+    olsr_cnf->ip_version = AF_INET;
+    olsr_cnf->ipsize = sizeof(struct in_addr);
+    olsr_cnf->maxplen = 32;
+  } else if ($2->integer == 6) {
+    olsr_cnf->ip_version = AF_INET6;
+    olsr_cnf->ipsize = sizeof(struct in6_addr);
+    olsr_cnf->maxplen = 128;
+  } else {
+    fprintf(stderr, "IPversion must be 4 or 6!\n");
+    YYABORT;
+  }
+
+  PARSER_DEBUG_PRINTF("IpVersion: %d\n", $2->integer);
+  free($2);
+}
+;
+
+fibmetric:    TOK_FIBMETRIC TOK_STRING
+{
+  PARSER_DEBUG_PRINTF("FIBMetric: %d\n", $2->string);
+  if (strcmp($2->string, CFG_FIBM_FLAT) == 0) {
+      olsr_cnf->fib_metric = FIBM_FLAT;
+  } else if (strcmp($2->string, CFG_FIBM_CORRECT) == 0) {
+      olsr_cnf->fib_metric = FIBM_CORRECT;
+  } else if (strcmp($2->string, CFG_FIBM_APPROX) == 0) {
+      olsr_cnf->fib_metric = FIBM_APPROX;
+  } else {
+    fprintf(stderr, "FIBMetric must be \"%s\", \"%s\", or \"%s\"!\n", CFG_FIBM_FLAT, CFG_FIBM_CORRECT, CFG_FIBM_APPROX);
+    YYABORT;
+  }
+  free($1);
+  free($2->string);
+  free($2);
+}
+;
+
+ihna4entry:     TOK_IP4_ADDR TOK_IP4_ADDR
+{
+  union olsr_ip_addr ipaddr, netmask;
+
+  PARSER_DEBUG_PRINTF("HNA IPv4 entry: %s/%s\n", $1->string, $2->string);
+
+  if (olsr_cnf->ip_version != AF_INET) {
+    fprintf(stderr, "IPv4 addresses can only be used if \"IpVersion\" == 4\n");
+    YYABORT;
+  }
+
+  if (inet_pton(AF_INET, $1->string, &ipaddr.v4) <= 0) {
+    fprintf(stderr, "ihna4entry: Failed converting IP address %s\n", $1->string);
+    YYABORT;
+  }
+  if (inet_pton(AF_INET, $2->string, &netmask.v4) <= 0) {
+    fprintf(stderr, "ihna4entry: Failed converting IP address %s\n", $1->string);
+    YYABORT;
+  }
+
+  /* check that the given IP address is actually a network address */
+  if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
+    fprintf(stderr, "ihna4entry: The ipaddress \"%s\" is not a network address!\n", $1->string);
+    YYABORT;
+  }
+
+  /* Queue */
+  ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, olsr_netmask_to_prefix(&netmask));
+
+  free($1->string);
+  free($1);
+  free($2->string);
+  free($2);
+}
+        |       TOK_IP4_ADDR TOK_SLASH TOK_INTEGER
+{
+  union olsr_ip_addr ipaddr, netmask;
+
+  PARSER_DEBUG_PRINTF("HNA IPv4 entry: %s/%d\n", $1->string, $3->integer);
+
+  if (inet_pton(AF_INET, $1->string, &ipaddr.v4) <= 0) {
+    fprintf(stderr, "ihna4entry: Failed converting IP address %s\n", $1->string);
+    YYABORT;
+  }
+  if ($3->integer > olsr_cnf->maxplen) {
+    fprintf(stderr, "ihna4entry: Prefix len %u > %d is not allowed!\n", $3->integer, olsr_cnf->maxplen);
+    YYABORT;
+  }
+
+  /* check that the given IP address is actually a network address */
+  olsr_prefix_to_netmask(&netmask, $3->integer);
+  if ((ipaddr.v4.s_addr & ~netmask.v4.s_addr) != 0) {
+    fprintf(stderr, "ihna4entry: The ipaddress \"%s\" is not a network address!\n", $1->string);
+    YYABORT;
+  }
+
+  /* Queue */
+  ip_prefix_list_add(&olsr_cnf->hna_entries, &ipaddr, $3->integer);
+
+  free($1->string);
+  free($1);
+  free($3);
+}
+;
+
+ihna6entry:     TOK_IP6_ADDR TOK_INTEGER
+{
+  if (add_ipv6_addr($1, $2)) {
+    YYABORT;
+  }
+}
+        |       TOK_IP6_ADDR TOK_SLASH TOK_INTEGER
+{
+  if (add_ipv6_addr($1, $3)) {
+    YYABORT;
+  }
+}
+;
+
+ifstart: TOK_INTERFACE
+{
+  PARSER_DEBUG_PRINTF("setting ifs_in_curr_cfg = 0\n");
+  ifs_in_curr_cfg = 0;
+}
+;
+
+ifnick: TOK_STRING
+{
+  struct olsr_if *in = malloc(sizeof(*in));
+  
+  if (in == NULL) {
+    fprintf(stderr, "Out of memory(ADD IF)\n");
+    YYABORT;
+  }
+
+  in->cnf = get_default_if_config();
+
+  if (in->cnf == NULL) {
+    fprintf(stderr, "Out of memory(ADD IFRULE)\n");
+    YYABORT;
+  }
+
+  in->name = $1->string;
+
+  /* Queue */
+  in->next = olsr_cnf->interfaces;
+  olsr_cnf->interfaces = in;
+  ifs_in_curr_cfg++;
+  free($1);
+}
+;
+
+bnoint: TOK_NOINT TOK_BOOLEAN
+{
+  PARSER_DEBUG_PRINTF("Noint set to %d\n", $2->boolean);
+  olsr_cnf->allow_no_interfaces = $2->boolean;
+  free($2);
+}
+;
+
+atos: TOK_TOS TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("TOS: %d\n", $2->integer);
+  olsr_cnf->tos = $2->integer;
+  free($2);
+
+}
+;
+
+arttable: TOK_RTTABLE TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("RtTable: %d\n", $2->integer);
+  olsr_cnf->rttable = $2->integer;
+  free($2);
+}
+;
+
+arttable_default: TOK_RTTABLE_DEFAULT TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("RtTableDefault: %d\n", $2->integer);
+  olsr_cnf->rttable_default = $2->integer;
+  free($2);
+}
+;
+
+awillingness: TOK_WILLINGNESS TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("Willingness: %d\n", $2->integer);
+  olsr_cnf->willingness_auto = OLSR_FALSE;
+  olsr_cnf->willingness = $2->integer;
+  free($2);
+}
+;
+
+busehyst: TOK_USEHYST TOK_BOOLEAN
+{
+  olsr_cnf->use_hysteresis = $2->boolean;
+  PARSER_DEBUG_PRINTF("Hysteresis %s\n", olsr_cnf->use_hysteresis ? "enabled" : "disabled");
+  free($2);
+}
+;
+
+fhystscale: TOK_HYSTSCALE TOK_FLOAT
+{
+  olsr_cnf->hysteresis_param.scaling = $2->floating;
+  PARSER_DEBUG_PRINTF("Hysteresis Scaling: %0.2f\n", $2->floating);
+  free($2);
+}
+;
+
+fhystupper: TOK_HYSTUPPER TOK_FLOAT
+{
+  olsr_cnf->hysteresis_param.thr_high = $2->floating;
+  PARSER_DEBUG_PRINTF("Hysteresis UpperThr: %0.2f\n", $2->floating);
+  free($2);
+}
+;
+
+fhystlower: TOK_HYSTLOWER TOK_FLOAT
+{
+  olsr_cnf->hysteresis_param.thr_low = $2->floating;
+  PARSER_DEBUG_PRINTF("Hysteresis LowerThr: %0.2f\n", $2->floating);
+  free($2);
+}
+;
+
+fpollrate: TOK_POLLRATE TOK_FLOAT
+{
+  PARSER_DEBUG_PRINTF("Pollrate %0.2f\n", $2->floating);
+  olsr_cnf->pollrate = $2->floating;
+  free($2);
+}
+;
+
+fnicchgspollrt: TOK_NICCHGSPOLLRT TOK_FLOAT
+{
+  PARSER_DEBUG_PRINTF("NIC Changes Pollrate %0.2f\n", $2->floating);
+  olsr_cnf->nic_chgs_pollrate = $2->floating;
+  free($2);
+}
+;
+
+atcredundancy: TOK_TCREDUNDANCY TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("TC redundancy %d\n", $2->integer);
+  olsr_cnf->tc_redundancy = $2->integer;
+  free($2);
+}
+;
+
+amprcoverage: TOK_MPRCOVERAGE TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("MPR coverage %d\n", $2->integer);
+  olsr_cnf->mpr_coverage = $2->integer;
+  free($2);
+}
+;
+
+alq_level: TOK_LQ_LEVEL TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("Link quality level %d\n", $2->integer);
+  olsr_cnf->lq_level = $2->integer;
+  free($2);
+}
+;
+
+alq_fish: TOK_LQ_FISH TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("Link quality fish eye %d\n", $2->integer);
+  olsr_cnf->lq_fish = $2->integer;
+  free($2);
+}
+;
+
+alq_dlimit: TOK_LQ_DLIMIT TOK_INTEGER TOK_FLOAT
+{
+  PARSER_DEBUG_PRINTF("Link quality dijkstra limit %d, %0.2f\n", $2->integer, $3->floating);
+  olsr_cnf->lq_dlimit = $2->integer;
+  olsr_cnf->lq_dinter = $3->floating;
+  free($2);
+}
+;
+
+alq_wsize: TOK_LQ_WSIZE TOK_INTEGER
+{
+  free($2);
+}
+;
+
+alq_aging: TOK_LQ_AGING TOK_FLOAT
+{
+  PARSER_DEBUG_PRINTF("Link quality aging factor %f\n", $2->floating);
+  olsr_cnf->lq_aging = $2->floating;
+  free($2);
+}
+;
+
+alq_plugin: TOK_LQ_PLUGIN TOK_STRING
+{
+  olsr_cnf->lq_algorithm = $2->string;
+  PARSER_DEBUG_PRINTF("LQ Algorithm: %s\n", $2->string);
+  free($2);
+}
+;
+
+anat_thresh: TOK_LQ_NAT_THRESH TOK_FLOAT
+{
+  PARSER_DEBUG_PRINTF("NAT threshold %0.2f\n", $2->floating);
+  olsr_cnf->lq_nat_thresh = $2->floating;
+  free($2);
+}
+;
+
+bclear_screen: TOK_CLEAR_SCREEN TOK_BOOLEAN
+{
+  PARSER_DEBUG_PRINTF("Clear screen %s\n", olsr_cnf->clear_screen ? "enabled" : "disabled");
+  olsr_cnf->clear_screen = $2->boolean;
+  free($2);
+}
+;
+
+plblock: TOK_PLUGIN TOK_STRING
+{
+  struct plugin_entry *pe = malloc(sizeof(*pe));
+  
+  if (pe == NULL) {
+    fprintf(stderr, "Out of memory(ADD PL)\n");
+    YYABORT;
+  }
+
+  pe->name = $2->string;
+  pe->params = NULL;
+  
+  PARSER_DEBUG_PRINTF("Plugin: %s\n", $2->string);
+
+  /* Queue */
+  pe->next = olsr_cnf->plugins;
+  olsr_cnf->plugins = pe;
+
+  free($2);
+}
+;
+
+plparam: TOK_PLPARAM TOK_STRING TOK_STRING
+{
+  struct plugin_param *pp = malloc(sizeof(*pp));
+  
+  if (pp == NULL) {
+    fprintf(stderr, "Out of memory(ADD PP)\n");
+    YYABORT;
+  }
+  
+  PARSER_DEBUG_PRINTF("Plugin param key:\"%s\" val: \"%s\"\n", $2->string, $3->string);
+  
+  pp->key = $2->string;
+  pp->value = $3->string;
+
+  /* Queue */
+  pp->next = olsr_cnf->plugins->params;
+  olsr_cnf->plugins->params = pp;
+
+  free($2);
+  free($3);
+}
+;
+
+vcomment:       TOK_COMMENT
+{
+    //PARSER_DEBUG_PRINTF("Comment\n");
+}
+;
+
+
+
+%%
+
+void yyerror (const char *string)
+{
+  fprintf(stderr, "Config line %d: %s\n", current_line, string);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/oscan.lex ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/oscan.lex
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/oscan.lex	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/oscan.lex	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,494 @@
+%{
+
+/*
+ * 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.
+ *
+ */
+
+
+#define YYSTYPE struct conf_token *
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "olsrd_conf.h"
+
+#include "oparse.h"
+ 
+/* Prototypes */
+int yyget_lineno(void);
+FILE * yyget_in(void);
+FILE* yyget_out(void);
+int yyget_leng(void);
+char *yyget_text(void);
+void yyset_lineno(int);
+void yyset_in(FILE *);
+void yyset_out(FILE *);
+int yyget_debug(void);
+void yyset_debug(int);
+int yylex_destroy(void);
+int yylex(void);
+
+static struct conf_token *get_conf_token(void);
+static struct conf_token *get_string_token(const char * const s, const size_t n);
+static struct conf_token *get_integer_token(const char * const s);
+static struct conf_token *get_floating_token(const char * const s);
+static struct conf_token *get_boolean_token(const olsr_bool b);
+
+static struct conf_token *get_conf_token(void)
+{
+    struct conf_token *t = calloc(1, sizeof(struct conf_token));
+    if (t == NULL) {
+        fprintf(stderr, "Cannot allocate %d bytes for an configuration token.\n", (int)sizeof(struct conf_token));
+    }
+    return t;
+}
+
+static struct conf_token *get_string_token(const char * const s, const size_t n)
+{
+    struct conf_token *rv = get_conf_token();
+    if (rv != NULL) {
+        rv->string = malloc(n + 1);
+        if (rv->string == NULL) {
+          fprintf(stderr, "Cannot allocate %lu bytes for string token data.\n", (unsigned long)(n+1)); /* size_t on 64bit */
+            free(rv);
+            return NULL;
+        }
+        memcpy(rv->string, s, n);
+        rv->string[n] = '\0';
+    }
+    return rv;
+}
+
+static struct conf_token *get_integer_token(const char * const s)
+{
+    struct conf_token *rv = get_conf_token();
+    if (rv != NULL) {
+        rv->integer = strtol(s, NULL, 0);
+    }
+    return rv;
+}
+
+static struct conf_token *get_floating_token(const char * const s)
+{
+    struct conf_token *rv = get_conf_token();
+    if (rv != NULL) {
+	rv->floating = 0.0;
+	sscanf(s, "%f", &rv->floating);
+    }
+    return rv;
+}
+
+static struct conf_token *get_boolean_token(const olsr_bool b)
+{
+    struct conf_token *rv = get_conf_token();
+    if (rv != NULL) {
+        rv->boolean = b;
+    }
+    return rv;
+}
+
+%}
+
+%option never-interactive
+%option noalways-interactive
+%option nomain
+%option nostack
+%option noyywrap
+
+DECDIGIT [0-9]
+FLOAT {DECDIGIT}+\.{DECDIGIT}+
+HEX8 [a-fA-F0-9]
+QUAD {DECDIGIT}{1,3}
+
+IPV4ADDR {QUAD}\.{QUAD}\.{QUAD}\.{QUAD}
+
+HEX16 {HEX8}{1,4}
+
+IP6PAT2 ({HEX16}:){1}:({HEX16}:){0,5}{HEX16}
+IP6PAT3 ({HEX16}:){2}:({HEX16}:){0,4}{HEX16}
+IP6PAT4 ({HEX16}:){3}:({HEX16}:){0,3}{HEX16}
+IP6PAT5 ({HEX16}:){4}:({HEX16}:){0,2}{HEX16}
+IP6PAT6 ({HEX16}:){5}:({HEX16}:){0,1}{HEX16}
+IP6PAT7 ({HEX16}:){6}:({HEX16})
+IP6PAT1 ({HEX16}:){7}{HEX16}
+IP6PAT8 ({HEX16}:){1,7}:
+IP6PAT9 ::
+
+IPV6ADDR {IP6PAT1}|{IP6PAT2}|{IP6PAT3}|{IP6PAT4}|{IP6PAT5}|{IP6PAT6}|{IP6PAT7}|{IP6PAT8}|{IP6PAT9}
+
+%%
+
+\s*"#".*\n {
+    current_line++;
+    return TOK_COMMENT;
+}
+
+\/ {
+    yylval = NULL;
+    return TOK_SLASH;
+}
+
+\{ {
+    yylval = NULL;
+    return TOK_OPEN;
+}
+
+\} {
+    yylval = NULL;
+    return TOK_CLOSE;
+}
+
+\"[^\"]*\" {
+    yylval = get_string_token(yytext + 1, yyleng - 2);
+    if (yylval == NULL) {
+        yyterminate();
+    }
+    return TOK_STRING;
+}
+
+0x{HEX8}+ {
+    yylval = get_integer_token(yytext);
+    return TOK_INTEGER;
+}
+
+{FLOAT} {
+    yylval = get_floating_token(yytext);
+    return TOK_FLOAT;
+}
+
+{IPV4ADDR} {
+    yylval = get_string_token(yytext, yyleng + 1);
+    if (yylval == NULL) {
+        yyterminate();
+    }
+    return TOK_IP4_ADDR;
+}
+{IPV6ADDR} {
+    yylval = get_string_token(yytext, yyleng + 1);
+    if (yylval == NULL) {
+        yyterminate();
+    }
+    return TOK_IP6_ADDR;
+}
+
+"default" {
+    yylval = NULL;
+    return TOK_DEFAULT;
+}
+
+{DECDIGIT}+ {
+    yylval = get_integer_token(yytext);
+    return TOK_INTEGER;
+}
+
+
+"yes" {
+    yylval = get_boolean_token(OLSR_TRUE);
+    return TOK_BOOLEAN;
+}
+
+"no" {
+    yylval = get_boolean_token(OLSR_FALSE);
+    return TOK_BOOLEAN;
+}
+
+"site-local" {
+    yylval = get_boolean_token(OLSR_TRUE);
+    return TOK_IP6TYPE;
+}
+
+"global" {
+    yylval = get_boolean_token(OLSR_FALSE);
+    return TOK_IP6TYPE;
+}
+
+"Host" {
+    yylval = NULL;
+    return TOK_HOSTLABEL;
+}
+
+"Net" {
+    yylval = NULL;
+    return TOK_NETLABEL;
+}
+
+"MaxConnections" {
+    yylval = NULL;
+    return TOK_MAXIPC;
+}
+
+"DebugLevel" {
+    yylval = NULL;
+    return TOK_DEBUGLEVEL;
+}
+
+"IpVersion" {
+    yylval = NULL;
+    return TOK_IPVERSION;
+}
+
+"NicChgsPollInt" {
+    yylval = NULL;
+    return TOK_NICCHGSPOLLRT;
+}
+
+"Hna4" {
+    yylval = NULL;
+    return TOK_HNA4;
+}
+
+"Hna6" {
+    yylval = NULL;
+    return TOK_HNA6;
+}
+
+"LoadPlugin" {
+    yylval = NULL;
+    return TOK_PLUGIN;
+}
+
+"PlParam" {
+    yylval = NULL;
+    return TOK_PLPARAM;
+}
+
+"Interface" {
+    yylval = NULL;
+    return TOK_INTERFACE;
+}
+
+"AllowNoInt" {
+    yylval = NULL;
+    return TOK_NOINT;
+}
+
+"TosValue" {
+    yylval = NULL;
+    return TOK_TOS;
+}
+
+"RtTable" {
+  yylval = NULL;
+  return TOK_RTTABLE;
+}
+
+"RtTableDefault" {
+  yylval = NULL;
+  return TOK_RTTABLE_DEFAULT;
+}
+
+"Willingness" {
+    yylval = NULL;
+    return TOK_WILLINGNESS;
+}
+
+"IpcConnect" {
+    yylval = NULL;
+    return TOK_IPCCON;
+}
+
+"FIBMetric" {
+    yylval = NULL;
+    return TOK_FIBMETRIC;
+}
+
+"UseHysteresis" {
+    yylval = NULL;
+    return TOK_USEHYST;
+}
+
+"HystScaling" {
+    yylval = NULL;
+    return TOK_HYSTSCALE;
+}
+
+"HystThrHigh" {
+    yylval = NULL;
+    return TOK_HYSTUPPER;
+}
+
+"HystThrLow" {
+    yylval = NULL;
+    return TOK_HYSTLOWER;
+}
+
+"Pollrate" {
+    yylval = NULL;
+    return TOK_POLLRATE;
+}
+
+
+"TcRedundancy" {
+    yylval = NULL;
+    return TOK_TCREDUNDANCY;
+}
+
+"MprCoverage" {
+    yylval = NULL;
+    return TOK_MPRCOVERAGE;
+}
+
+"LinkQualityLevel" {
+    yylval = NULL;
+    return TOK_LQ_LEVEL;
+}
+
+"LinkQualityFishEye" {
+    yylval = NULL;
+    return TOK_LQ_FISH;
+}
+
+"LinkQualityDijkstraLimit" {
+    yylval = NULL;
+    return TOK_LQ_DLIMIT;
+}
+
+"LinkQualityAging" {
+    yylval = NULL;
+    return TOK_LQ_AGING;
+}
+
+"LinkQualityAlgorithm" {
+    yylval = NULL;
+    return TOK_LQ_PLUGIN;
+}
+
+"LinkQualityWinSize" {
+    yylval = NULL;
+    return TOK_LQ_WSIZE;
+}
+
+"NatThreshold" {
+    yylval = NULL;
+    return TOK_LQ_NAT_THRESH;
+}
+
+"LinkQualityMult" {
+    yylval = NULL;
+    return TOK_LQ_MULT;
+}
+
+"ClearScreen" {
+    yylval = NULL;
+    return TOK_CLEAR_SCREEN;
+}
+
+"Weight" {
+    yylval = NULL;
+    return TOK_IFWEIGHT;
+}
+
+"Ip4Broadcast" {
+    yylval = NULL;
+    return TOK_IP4BROADCAST;
+}
+"Ip6AddrType" {
+    yylval = NULL;
+    return TOK_IP6ADDRTYPE;
+}
+"Ip6MulticastSite" {
+    yylval = NULL;
+    return TOK_IP6MULTISITE;
+}
+"Ip6MulticastGlobal" {
+    yylval = NULL;
+    return TOK_IP6MULTIGLOBAL;
+}
+"HelloInterval" {
+    yylval = NULL;
+    return TOK_HELLOINT;
+}
+"HelloValidityTime" {
+    yylval = NULL;
+    return TOK_HELLOVAL;
+}
+"TcInterval" {
+    yylval = NULL;
+    return TOK_TCINT;
+}
+"TcValidityTime" {
+    yylval = NULL;
+    return TOK_TCVAL;
+}
+"MidInterval" {
+    yylval = NULL;
+    return TOK_MIDINT;
+}
+"MidValidityTime" {
+    yylval = NULL;
+    return TOK_MIDVAL;
+}
+"HnaInterval" {
+    yylval = NULL;
+    return TOK_HNAINT;
+}
+"HnaValidityTime" {
+    yylval = NULL;
+    return TOK_HNAVAL;
+}
+"AutoDetectChanges" {
+    yylval = NULL;
+    return TOK_AUTODETCHG;
+}
+
+
+\n|\r\n {
+    current_line++;
+}
+
+\ |\t
+
+. {
+  /* Do nothing */
+  //fprintf(stderr, "Failed to parse line %d of configuration file.\n",
+  //      current_line);
+  //yyterminate();
+  //yy_fatal_error("Parsing failed.\n");
+
+  /* To avoid compiler warning (stupid...) */
+  if(0)
+    yyunput(0, NULL);
+}
+
+%%
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/README ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/README
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/README	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/README	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,22 @@
+
+TODO..
+
+The configparser can be built in three ways.
+
+1. As part of olsrd. This is done when building olsrd.
+
+2. As a binary executable. Just do 'make' in the current
+   directory(src/cfgparser). The binary will be called
+   olsrd_cfgparser
+
+3. As a shared library. Do 'make MAKELIB=1' in the current
+   directory(src/cfgparser).
+
+
+the parser can both parse configfiles and write such files
+based on provided data.
+
+More to come.
+
+
+- Andreas
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/version-script.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/version-script.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/cfgparser/version-script.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/cfgparser/version-script.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,18 @@
+VERS_1.0
+{
+  global:
+    olsrd_parse_cnf;
+    olsrd_sanity_check_cnf;
+    olsrd_free_cnf;
+    olsrd_print_cnf;
+    olsrd_write_cnf;
+    olsrd_write_cnf_buf;
+    get_default_if_config;
+    olsrd_get_default_cnf;
+    olsrd_parse_cnf;
+    win32_stdio_hack;
+    win32_olsrd_malloc;
+    win32_olsrd_free;
+  local:
+    *;
+};
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/avl.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/avl.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/avl.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/avl.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,675 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * IPv4 performance optimization (c) 2006, sven-ola(gmx.de)
+ * 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 <stddef.h>
+#include <time.h>
+#include <string.h>
+
+#include "ipcalc.h"
+#include "common/avl.h"
+#include "net_olsr.h"
+
+/*
+ * default comparison pointers 
+ * set to the respective compare function.
+ * if avl_comp_default is set to zero, a fast
+ * inline ipv4 comparison will be executed.
+ */
+avl_tree_comp avl_comp_default = NULL;
+avl_tree_comp avl_comp_prefix_default;
+
+int
+avl_comp_ipv4(const void *ip1, const void *ip2)
+{
+  return ip4cmp(ip1, ip2);
+}
+
+int
+avl_comp_ipv6(const void *ip1, const void *ip2)
+{
+  return ip6cmp(ip1, ip2);
+}
+
+int
+avl_comp_mac(const void *ip1, const void *ip2)
+{
+  return memcmp(ip1, ip2, 6);
+}
+
+void
+avl_init(struct avl_tree *tree, avl_tree_comp comp)
+{
+  tree->root = NULL;
+  tree->first = NULL;
+  tree->last = NULL;
+  tree->count = 0;
+  
+  tree->comp = comp == avl_comp_ipv4 ? NULL : comp;
+}
+
+static struct avl_node *
+avl_find_rec_ipv4(struct avl_node *node, const void *key)
+{
+  if (*(const unsigned int *)key < *(const unsigned int *)node->key) {
+    if (node->left != NULL)
+      return avl_find_rec_ipv4(node->left, key);
+  }
+
+  else if (*(const unsigned int *)key > *(const unsigned int *)node->key) {
+    if (node->right != NULL)
+      return avl_find_rec_ipv4(node->right, key);
+  }
+
+  return node;
+}
+
+static struct avl_node *
+avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp)
+{
+  int diff;
+
+  if (NULL == comp)
+    return avl_find_rec_ipv4(node, key);
+
+  diff = (*comp) (key, node->key);
+
+  if (diff < 0) {
+    if (node->left != NULL)
+      return avl_find_rec(node->left, key, comp);
+
+    return node;
+  }
+
+  if (diff > 0) {
+    if (node->right != NULL)
+      return avl_find_rec(node->right, key, comp);
+
+    return node;
+  }
+
+  return node;
+}
+
+struct avl_node *
+avl_find(struct avl_tree *tree, const void *key)
+{
+  struct avl_node *node;
+
+  if (tree->root == NULL)
+    return NULL;
+
+  node = avl_find_rec(tree->root, key, tree->comp);
+
+  if (NULL == tree->comp) {
+    if (0 != ip4cmp(node->key, key))
+      return NULL;
+  }
+
+  else {
+    if ((*tree->comp) (node->key, key) != 0)
+      return NULL;
+  }
+
+  return node;
+}
+
+static void
+avl_rotate_right(struct avl_tree *tree, struct avl_node *node)
+{
+  struct avl_node *left, *parent;
+
+  left = node->left;
+  parent = node->parent;
+
+  left->parent = parent;
+  node->parent = left;
+
+  if (parent == NULL)
+    tree->root = left;
+
+  else {
+    if (parent->left == node)
+      parent->left = left;
+
+    else
+      parent->right = left;
+  }
+
+  node->left = left->right;
+  left->right = node;
+
+  if (node->left != NULL)
+    node->left->parent = node;
+
+  node->balance += 1 - MIN(left->balance, 0);
+  left->balance += 1 + MAX(node->balance, 0);
+}
+
+static void
+avl_rotate_left(struct avl_tree *tree, struct avl_node *node)
+{
+  struct avl_node *right, *parent;
+
+  right = node->right;
+  parent = node->parent;
+
+  right->parent = parent;
+  node->parent = right;
+
+  if (parent == NULL)
+    tree->root = right;
+
+  else {
+    if (parent->left == node)
+      parent->left = right;
+
+    else
+      parent->right = right;
+  }
+
+  node->right = right->left;
+  right->left = node;
+
+  if (node->right != NULL)
+    node->right->parent = node;
+
+  node->balance -= 1 + MAX(right->balance, 0);
+  right->balance -= 1 - MIN(node->balance, 0);
+}
+
+static void
+post_insert(struct avl_tree *tree, struct avl_node *node)
+{
+  struct avl_node *parent = node->parent;
+
+  if (parent == NULL)
+    return;
+
+  if (node == parent->left) {
+    parent->balance--;
+
+    if (parent->balance == 0)
+      return;
+
+    if (parent->balance == -1) {
+      post_insert(tree, parent);
+      return;
+    }
+
+    if (node->balance == -1) {
+      avl_rotate_right(tree, parent);
+      return;
+    }
+
+    avl_rotate_left(tree, node);
+    avl_rotate_right(tree, node->parent->parent);
+    return;
+  }
+
+  parent->balance++;
+
+  if (parent->balance == 0)
+    return;
+
+  if (parent->balance == 1) {
+    post_insert(tree, parent);
+    return;
+  }
+
+  if (node->balance == 1) {
+    avl_rotate_left(tree, parent);
+    return;
+  }
+
+  avl_rotate_right(tree, node);
+  avl_rotate_left(tree, node->parent->parent);
+}
+
+static void
+avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node,
+		  struct avl_node *node)
+{
+  if (pos_node->prev != NULL)
+    pos_node->prev->next = node;
+  else
+    tree->first = node;
+
+  node->prev = pos_node->prev;
+  node->next = pos_node;
+
+  pos_node->prev = node;
+
+  tree->count++;
+}
+
+static void
+avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node,
+		 struct avl_node *node)
+{
+  if (pos_node->next != NULL)
+    pos_node->next->prev = node;
+  else
+    tree->last = node;
+
+  node->prev = pos_node;
+  node->next = pos_node->next;
+
+  pos_node->next = node;
+
+  tree->count++;
+}
+
+static void
+avl_remove(struct avl_tree *tree, struct avl_node *node)
+{
+  if (node->prev != NULL)
+    node->prev->next = node->next;
+  else
+    tree->first = node->next;
+
+  if (node->next != NULL)
+    node->next->prev = node->prev;
+  else
+    tree->last = node->prev;
+
+  tree->count--;
+}
+
+int
+avl_insert(struct avl_tree *tree, struct avl_node *new, int allow_duplicates)
+{
+  struct avl_node *node;
+  struct avl_node *last;
+  int diff;
+
+  new->parent = NULL;
+
+  new->left = NULL;
+  new->right = NULL;
+
+  new->next = NULL;
+  new->prev = NULL;
+
+  new->balance = 0;
+  new->leader = 1;
+
+  if (tree->root == NULL) {
+    tree->root = new;
+    tree->first = new;
+    tree->last = new;
+    tree->count = 1;
+    return 0;
+  }
+
+  node = avl_find_rec(tree->root, new->key, tree->comp);
+
+  last = node;
+
+  while (last->next != NULL && last->next->leader == 0)
+    last = last->next;
+
+  if (NULL == tree->comp)
+    diff = ip4cmp(new->key, node->key);
+
+  else
+    diff = (*tree->comp) (new->key, node->key);
+
+  if (diff == 0) {
+    if (allow_duplicates == AVL_DUP_NO)
+      return -1;
+
+    new->leader = 0;
+
+    avl_insert_after(tree, last, new);
+    return 0;
+  }
+
+  if (node->balance == 1) {
+    avl_insert_before(tree, node, new);
+
+    node->balance = 0;
+    new->parent = node;
+    node->left = new;
+    return 0;
+  }
+
+  if (node->balance == -1) {
+    avl_insert_after(tree, last, new);
+
+    node->balance = 0;
+    new->parent = node;
+    node->right = new;
+    return 0;
+  }
+
+  if (diff < 0) {
+    avl_insert_before(tree, node, new);
+
+    node->balance = -1;
+    new->parent = node;
+    node->left = new;
+    post_insert(tree, node);
+    return 0;
+  }
+
+  avl_insert_after(tree, last, new);
+
+  node->balance = 1;
+  new->parent = node;
+  node->right = new;
+  post_insert(tree, node);
+  return 0;
+}
+
+static void
+avl_post_delete(struct avl_tree *tree, struct avl_node *node)
+{
+  struct avl_node *parent;
+
+  if ((parent = node->parent) == NULL)
+    return;
+
+  if (node == parent->left) {
+    parent->balance++;
+
+    if (parent->balance == 0) {
+      avl_post_delete(tree, parent);
+      return;
+    }
+
+    if (parent->balance == 1)
+      return;
+
+    if (parent->right->balance == 0) {
+      avl_rotate_left(tree, parent);
+      return;
+    }
+
+    if (parent->right->balance == 1) {
+      avl_rotate_left(tree, parent);
+      avl_post_delete(tree, parent->parent);
+      return;
+    }
+
+    avl_rotate_right(tree, parent->right);
+    avl_rotate_left(tree, parent);
+    avl_post_delete(tree, parent->parent);
+    return;
+  }
+
+  parent->balance--;
+
+  if (parent->balance == 0) {
+    avl_post_delete(tree, parent);
+    return;
+  }
+
+  if (parent->balance == -1)
+    return;
+
+  if (parent->left->balance == 0) {
+    avl_rotate_right(tree, parent);
+    return;
+  }
+
+  if (parent->left->balance == -1) {
+    avl_rotate_right(tree, parent);
+    avl_post_delete(tree, parent->parent);
+    return;
+  }
+
+  avl_rotate_left(tree, parent->left);
+  avl_rotate_right(tree, parent);
+  avl_post_delete(tree, parent->parent);
+}
+
+static struct avl_node *
+avl_local_min(struct avl_node *node)
+{
+  while (node->left != NULL)
+    node = node->left;
+
+  return node;
+}
+
+#if 0
+static struct avl_node *
+avl_local_max(struct avl_node *node)
+{
+  while (node->right != NULL)
+    node = node->right;
+
+  return node;
+}
+#endif
+
+static void
+avl_delete_worker(struct avl_tree *tree, struct avl_node *node)
+{
+  struct avl_node *parent, *min;
+
+  parent = node->parent;
+
+  if (node->left == NULL && node->right == NULL) {
+    if (parent == NULL) {
+      tree->root = NULL;
+      return;
+    }
+
+    if (parent->left == node) {
+      parent->left = NULL;
+      parent->balance++;
+
+      if (parent->balance == 1)
+	return;
+
+      if (parent->balance == 0) {
+	avl_post_delete(tree, parent);
+	return;
+      }
+
+      if (parent->right->balance == 0) {
+	avl_rotate_left(tree, parent);
+	return;
+      }
+
+      if (parent->right->balance == 1) {
+	avl_rotate_left(tree, parent);
+	avl_post_delete(tree, parent->parent);
+	return;
+      }
+
+      avl_rotate_right(tree, parent->right);
+      avl_rotate_left(tree, parent);
+      avl_post_delete(tree, parent->parent);
+      return;
+    }
+
+    if (parent->right == node) {
+      parent->right = NULL;
+      parent->balance--;
+
+      if (parent->balance == -1)
+	return;
+
+      if (parent->balance == 0) {
+	avl_post_delete(tree, parent);
+	return;
+      }
+
+      if (parent->left->balance == 0) {
+	avl_rotate_right(tree, parent);
+	return;
+      }
+
+      if (parent->left->balance == -1) {
+	avl_rotate_right(tree, parent);
+	avl_post_delete(tree, parent->parent);
+	return;
+      }
+
+      avl_rotate_left(tree, parent->left);
+      avl_rotate_right(tree, parent);
+      avl_post_delete(tree, parent->parent);
+      return;
+    }
+  }
+
+  if (node->left == NULL) {
+    if (parent == NULL) {
+      tree->root = node->right;
+      node->right->parent = NULL;
+      return;
+    }
+
+    node->right->parent = parent;
+
+    if (parent->left == node)
+      parent->left = node->right;
+
+    else
+      parent->right = node->right;
+
+    avl_post_delete(tree, node->right);
+    return;
+  }
+
+  if (node->right == NULL) {
+    if (parent == NULL) {
+      tree->root = node->left;
+      node->left->parent = NULL;
+      return;
+    }
+
+    node->left->parent = parent;
+
+    if (parent->left == node)
+      parent->left = node->left;
+
+    else
+      parent->right = node->left;
+
+    avl_post_delete(tree, node->left);
+    return;
+  }
+
+  min = avl_local_min(node->right);
+  avl_delete_worker(tree, min);
+  parent = node->parent;
+
+  min->balance = node->balance;
+  min->parent = parent;
+  min->left = node->left;
+  min->right = node->right;
+
+  if (min->left != NULL)
+    min->left->parent = min;
+
+  if (min->right != NULL)
+    min->right->parent = min;
+
+  if (parent == NULL) {
+    tree->root = min;
+    return;
+  }
+
+  if (parent->left == node) {
+    parent->left = min;
+    return;
+  }
+
+  parent->right = min;
+}
+
+void
+avl_delete(struct avl_tree *tree, struct avl_node *node)
+{
+  struct avl_node *next;
+  struct avl_node *parent;
+  struct avl_node *left;
+  struct avl_node *right;
+
+  if (node->leader != 0) {
+    next = node->next;
+
+    if (next != NULL && next->leader == 0) {
+      next->leader = 1;
+      next->balance = node->balance;
+
+      parent = node->parent;
+      left = node->left;
+      right = node->right;
+
+      next->parent = parent;
+      next->left = left;
+      next->right = right;
+
+      if (parent == NULL)
+	tree->root = next;
+
+      else {
+	if (node == parent->left)
+	  parent->left = next;
+
+	else
+	  parent->right = next;
+      }
+
+      if (left != NULL)
+	left->parent = next;
+
+      if (right != NULL)
+	right->parent = next;
+    }
+
+    else
+      avl_delete_worker(tree, node);
+  }
+
+  avl_remove(tree, node);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/avl.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/avl.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/avl.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/avl.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,149 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * IPv4 performance optimization (c) 2006, sven-ola(gmx.de)
+ * 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 _AVL_H
+#define _AVL_H
+
+#include <stddef.h>
+
+/* must be declared here because of circular dependency through "defs.h" */
+
+#define INLINE inline __attribute__((always_inline))
+
+struct avl_node {
+  struct avl_node *parent;
+  struct avl_node *left;
+  struct avl_node *right;
+  struct avl_node *next;
+  struct avl_node *prev;
+  void *key;
+  signed char balance;
+  unsigned char leader;
+};
+
+typedef int (*avl_tree_comp) (const void *, const void *);
+
+struct avl_tree {
+  struct avl_node *root;
+  struct avl_node *first;
+  struct avl_node *last;
+  unsigned int count;
+  avl_tree_comp comp;
+};
+
+#define AVL_DUP    1
+#define AVL_DUP_NO 0
+
+void avl_init(struct avl_tree *, avl_tree_comp);
+struct avl_node *avl_find(struct avl_tree *, const void *);
+int avl_insert(struct avl_tree *, struct avl_node *, int);
+void avl_delete(struct avl_tree *, struct avl_node *);
+
+static INLINE struct avl_node *
+avl_walk_first(struct avl_tree *tree)
+{
+  return tree->first;
+}
+static INLINE struct avl_node *
+avl_walk_last(struct avl_tree *tree)
+{
+  return tree->last;
+}
+static INLINE struct avl_node *
+avl_walk_next(struct avl_node *node)
+{
+  return node->next;
+}
+static INLINE struct avl_node *
+avl_walk_prev(struct avl_node *node)
+{
+  return node->prev;
+}
+
+/* and const versions*/
+static INLINE const struct avl_node *
+avl_walk_first_c(const struct avl_tree *tree)
+{
+  return tree->first;
+}
+static INLINE const struct avl_node *
+avl_walk_last_c(const struct avl_tree *tree)
+{
+  return tree->last;
+}
+static INLINE const struct avl_node *
+avl_walk_next_c(const struct avl_node *node)
+{
+  return node->next;
+}
+static INLINE const struct avl_node *
+avl_walk_prev_c(const struct avl_node *node)
+{
+  return node->prev;
+}
+
+extern avl_tree_comp avl_comp_default;
+extern avl_tree_comp avl_comp_prefix_default;
+extern int avl_comp_ipv4(const void *, const void *);
+extern int avl_comp_ipv6(const void *, const void *);
+extern int avl_comp_mac(const void *, const void *);
+
+/*
+ * Macro to define an inline function to map from a list_node offset back to the
+ * base of the datastructure. That way you save an extra data pointer.
+ */
+#define AVLNODE2STRUCT(funcname, structname, avlnodename) \
+static inline structname * funcname (struct avl_node *ptr)\
+{\
+  return( \
+    ptr ? \
+      (structname *) (((olsr_u8_t *) ptr) - offsetof(structname, avlnodename)) : \
+      NULL); \
+}
+
+#endif /* _AVL_H */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/list.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/list.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/list.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/list.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,106 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * IPv4 performance optimization (c) 2006, sven-ola(gmx.de)
+ * 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 <stdlib.h>
+#include "common/list.h"
+
+/* init a circular list  */
+void list_head_init(struct list_node *node)
+{
+  node->prev = node;
+  node->next = node;
+}
+
+void list_node_init(struct list_node *node)
+{
+  node->prev = NULL;
+  node->next = NULL;
+}
+
+int list_node_on_list(struct list_node *node)
+{
+  if (node->prev || node->next) {
+    return 1;
+  }
+
+  return 0;
+}
+
+int list_is_empty(struct list_node *node)
+{
+  if (node->prev == node && node->next == node) {
+    return 1;
+  }
+
+  return 0;
+}
+
+void list_add_after(struct list_node *pos_node, struct list_node *new_node)
+{
+  new_node->next = pos_node->next;
+  new_node->prev = pos_node;
+
+  pos_node->next->prev = new_node;
+  pos_node->next = new_node;
+}
+
+void list_add_before(struct list_node *pos_node, struct list_node *new_node)
+{
+  new_node->prev = pos_node->prev;
+  new_node->next = pos_node;
+
+  pos_node->prev->next = new_node;
+  pos_node->prev = new_node;
+}
+
+void list_remove(struct list_node *del_node)
+{
+  del_node->next->prev = del_node->prev;
+  del_node->prev->next = del_node->next;
+
+  list_node_init(del_node);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/list.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/list.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/common/list.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/common/list.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,76 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * IPv4 performance optimization (c) 2006, sven-ola(gmx.de)
+ * 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 _LIST_H
+#define _LIST_H
+
+#include "stddef.h"
+
+struct list_node
+{
+  struct list_node *next;
+  struct list_node *prev;
+};
+
+void list_head_init(struct list_node *);
+void list_node_init(struct list_node *);
+int list_node_on_list(struct list_node *);
+int list_is_empty(struct list_node *);
+
+void list_add_before(struct list_node *, struct list_node *);
+void list_add_after(struct list_node *, struct list_node *);
+
+void list_remove(struct list_node *);
+
+/*
+ * Macro to define an inline function to map from a list_node offset back to the
+ * base of the datastructure. That way you save an extra data pointer.
+ */
+#define LISTNODE2STRUCT(funcname, structname, listnodename) \
+static inline structname * funcname (struct list_node *ptr)\
+{\
+  return( \
+    ptr ? \
+      (structname *) (((olsr_u8_t *) ptr) - offsetof(structname, listnodename)) : \
+      NULL); \
+}
+
+#endif /* _LQ_LIST */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/defs.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/defs.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/defs.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/defs.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,209 @@
+/*
+ * 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 _OLSR_DEFS
+#define _OLSR_DEFS
+
+/* Common includes */
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+
+#include "olsr_protocol.h"
+#include "olsr_cfg.h"
+
+extern const char olsrd_version[];
+extern const char build_date[]; 
+extern const char build_host[];
+
+#ifndef OLSRD_GLOBAL_CONF_FILE
+#define OLSRD_CONF_FILE_NAME	"olsrd.conf"
+#define OLSRD_GLOBAL_CONF_FILE	"/etc/" OLSRD_CONF_FILE_NAME
+#endif
+
+#define	MAXMESSAGESIZE		1500	/* max broadcast size */
+#define UDP_IPV4_HDRSIZE        28
+#define UDP_IPV6_HDRSIZE        62
+
+#define MIN_PACKET_SIZE(ver)	((int)(sizeof(olsr_u8_t) * (((ver) == AF_INET) ? 4 : 7)))
+
+/* Debug helper macro */
+#ifdef DEBUG
+#define olsr_debug(lvl, format, args...) do {                           \
+    OLSR_PRINTF(lvl, "%s (%s:%d): ", __func__, __FILE__, __LINE__);     \
+    OLSR_PRINTF(lvl, (format), ##args);                                 \
+  } while (0)
+#endif
+
+extern FILE *debug_handle;
+
+#ifdef NODEBUG
+#define OLSR_PRINTF(lvl, format, args...) do { } while(0)
+#else
+#define OLSR_PRINTF(lvl, format, args...) do {                    \
+    if((olsr_cnf->debug_level >= (lvl)) && debug_handle)          \
+      fprintf(debug_handle, (format), ##args);                    \
+  } while (0)
+#endif
+
+/*
+ * Provides a timestamp s1 milliseconds in the future according
+ * to system ticks returned by times(2)
+*/
+#define GET_TIMESTAMP(s1)	(now_times + ((s1) / olsr_cnf->system_tick_divider))
+
+/* Compute the time in milliseconds when a timestamp will expire. */
+#define TIME_DUE(s1)   ((int)((s1) * olsr_cnf->system_tick_divider) - now_times)
+
+/* Returns TRUE if a timestamp is expired */
+#define TIMED_OUT(s1)	((int)((s1) - now_times) < 0)
+
+
+#define ARRAYSIZE(x)	(sizeof(x)/sizeof(*(x)))
+#ifndef MAX
+#define MAX(x,y)	((x) > (y) ? (x) : (y))
+#endif
+#ifndef MIN
+#define MIN(x,y)	((x) < (y) ? (x) : (y))
+#endif
+
+#define INLINE inline __attribute__((always_inline))
+
+/*
+ * A somewhat safe version of strncpy and strncat. Note, that
+ * BSD/Solaris strlcpy()/strlcat() differ in implementation, while
+ * the BSD compiler prints out a warning if you use plain strcpy().
+ */
+ 
+static INLINE char *strscpy(char *dest, const char *src, size_t size)
+{
+	register size_t l = 0;
+#if !defined(NODEBUG) && defined(DEBUG)
+	if (sizeof(dest) == size) fprintf(stderr, "Warning: probably sizeof(pointer) in strscpy(%p, %s, %d)!\n", dest, src, size);
+	if (NULL == dest) fprintf(stderr, "Warning: dest is NULL in strscpy!\n");
+	if (NULL == src) fprintf(stderr, "Warning: src is NULL in strscpy!\n");
+#endif
+	if (NULL != dest && NULL != src)
+	{
+		/* src does not need to be null terminated */
+		if (0 < size--) while(l < size && 0 != src[l]) l++;
+		dest[l] = 0;
+	}
+	return strncpy(dest, src, l);
+}
+
+static INLINE char *strscat(char *dest, const char *src, size_t size)
+{
+	register size_t l = strlen(dest);
+	return strscpy(dest + l, src, size > l ? size - l : 0);
+}
+
+/*
+ * Queueing macros
+ */
+
+/* First "argument" is NOT a pointer! */
+
+#define QUEUE_ELEM(pre, new) do { \
+    (pre).next->prev = (new);         \
+    (new)->next = (pre).next;         \
+    (new)->prev = &(pre);             \
+    (pre).next = (new);               \
+  } while (0)
+
+#define DEQUEUE_ELEM(elem) do { \
+    (elem)->prev->next = (elem)->next;     \
+    (elem)->next->prev = (elem)->prev;     \
+  } while (0)
+
+
+#define CLOSE(fd)  do { close(fd); (fd) = -1; } while (0)
+
+/*
+ * Global olsrd configuragtion
+ */
+extern struct olsrd_config *olsr_cnf;
+
+/* Timer data */
+extern clock_t now_times; /* current idea of times(2) reported uptime */
+
+#if defined WIN32
+extern olsr_bool olsr_win32_end_request;
+extern olsr_bool olsr_win32_end_flag;
+#endif
+
+/*
+ * a wrapper around times(2). times(2) has the problem, that it may return -1
+ * in case of an err (e.g. EFAULT on the parameter) or immediately before an
+ * overrun (though it is not en error) just because the jiffies (or whatever
+ * the underlying kernel calls the smallest accountable time unit) are
+ * inherently "unsigned" (and always incremented).
+ */
+unsigned long olsr_times(void);
+
+/*
+ *IPC functions
+ *These are moved to a plugin soon
+ * soon... duh!
+ */
+
+int
+ipc_init(void);
+
+#if 0
+int
+ipc_input(int);
+#endif
+
+int
+shutdown_ipc(void);
+
+int
+ipc_output(struct olsr *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/duplicate_set.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/duplicate_set.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/duplicate_set.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/duplicate_set.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,180 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 "duplicate_set.h"
+#include "ipcalc.h"
+#include "common/avl.h"
+#include "olsr.h"
+#include "mid_set.h"
+#include "scheduler.h"
+#include "mantissa.h"
+
+static void olsr_cleanup_duplicate_entry(void *unused);
+
+struct avl_tree duplicate_set;
+struct timer_entry *duplicate_cleanup_timer;
+
+
+void olsr_init_duplicate_set(void) {
+  avl_init(&duplicate_set, olsr_cnf->ip_version == AF_INET ? &avl_comp_ipv4 : &avl_comp_ipv6);
+
+  olsr_set_timer(&duplicate_cleanup_timer, DUPLICATE_CLEANUP_INTERVAL,
+     DUPLICATE_CLEANUP_JITTER, OLSR_TIMER_PERIODIC,
+     &olsr_cleanup_duplicate_entry, NULL, 0);
+}
+
+struct dup_entry *olsr_create_duplicate_entry(void *ip, olsr_u16_t seqnr) {
+  struct dup_entry *entry;
+  entry = olsr_malloc(sizeof(struct dup_entry), "New duplicate entry");
+  if (entry != NULL) {
+    memcpy (&entry->ip, ip, olsr_cnf->ip_version == AF_INET ? sizeof(entry->ip.v4) : sizeof(entry->ip.v6));
+    entry->seqnr = seqnr;
+    entry->too_low_counter = 0;
+    entry->avl.key = &entry->ip;
+  }
+  return entry;
+}
+
+static void olsr_cleanup_duplicate_entry(void __attribute__ ((unused)) *unused) {
+  struct dup_entry *entry;
+
+  OLSR_FOR_ALL_DUP_ENTRIES(entry) {
+    if (TIMED_OUT(entry->valid_until)) {
+      avl_delete(&duplicate_set, &entry->avl);
+      free (entry);
+    }
+  } OLSR_FOR_ALL_DUP_ENTRIES_END(entry);
+}
+
+int olsr_shall_process_message(void *ip, olsr_u16_t seqnr) {
+  struct dup_entry *entry;
+  int diff;
+  void *mainIp;
+  clock_t valid_until;
+
+  struct ipaddr_str buf;
+  // get main address
+  mainIp = mid_lookup_main_addr(ip);
+  if (mainIp == NULL) {
+    mainIp = ip;
+  }
+
+  valid_until = GET_TIMESTAMP(DUPLICATE_VTIME);
+
+  entry = (struct dup_entry *)avl_find(&duplicate_set, ip);
+  if (entry == NULL) {
+    entry = olsr_create_duplicate_entry(ip, seqnr);
+    if (entry != NULL) {
+      avl_insert(&duplicate_set, &entry->avl, 0);
+      entry->valid_until = valid_until;
+    }
+    return 1; // okay, we process this package
+  }
+
+  diff = (int)seqnr - (int)(entry->seqnr);
+
+  // update timestamp
+  if (valid_until > entry->valid_until) {
+    entry->valid_until = valid_until;
+  }
+
+  // overflow ?
+  if (diff > (1<<15)) {
+    diff -= (1<<16);
+  }
+
+  if (diff < -31) {
+    entry->too_low_counter ++;
+
+    // client did restart with a lower number ?
+    if (entry->too_low_counter > 16) {
+      entry->too_low_counter = 0;
+      entry->seqnr = seqnr;
+      entry->array = 1;
+      return 1;
+    }
+    OLSR_PRINTF(9, "blocked %x from %s\n", seqnr, olsr_ip_to_string(&buf, mainIp));
+    return 0;
+  }
+
+  entry->too_low_counter = 0;
+  if (diff <= 0) {
+    olsr_u32_t bitmask = 1 << ((olsr_u32_t) (-diff));
+
+    if ((entry->array & bitmask) != 0) {
+      OLSR_PRINTF(9, "blocked %x (diff=%d,mask=%08x) from %s\n", seqnr, diff, entry->array, olsr_ip_to_string(&buf, mainIp));
+      return 0;
+    }
+    entry->array |= bitmask;
+    OLSR_PRINTF(9, "processed %x from %s\n", seqnr, olsr_ip_to_string(&buf, mainIp));
+    return 1;
+  }
+  else if (diff < 32) {
+    entry->array <<= (olsr_u32_t)diff;
+  }
+  else {
+    entry->array = 0;
+  }
+  entry->array |= 1;
+  entry->seqnr = seqnr;
+  OLSR_PRINTF(9, "processed %x from %s\n", seqnr, olsr_ip_to_string(&buf, mainIp));
+  return 1;
+}
+
+void olsr_print_duplicate_table(void) {
+#ifndef NODEBUG
+  /* The whole function makes no sense without it. */
+  struct dup_entry *entry;
+  const int ipwidth = olsr_cnf->ip_version == AF_INET ? 15 : 30;
+  struct ipaddr_str addrbuf;
+
+  OLSR_PRINTF(1,
+        "\n--- %s ------------------------------------------------- DUPLICATE SET\n\n"
+        "%-*s %8s %s\n", olsr_wallclock_string(), ipwidth,
+        "Node IP", "DupArray", "VTime");
+
+  OLSR_FOR_ALL_DUP_ENTRIES(entry) {
+    OLSR_PRINTF(1, "%-*s %08x %s\n",
+        ipwidth, olsr_ip_to_string(&addrbuf, (union olsr_ip_addr *)(entry->avl.key)),
+        entry->array,
+        olsr_clock_string(entry->valid_until));
+  } OLSR_FOR_ALL_DUP_ENTRIES_END(entry);
+#endif
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/duplicate_set.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/duplicate_set.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/duplicate_set.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/duplicate_set.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,84 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 DUPLICATE_SET_2_H_
+#define DUPLICATE_SET_2_H_
+
+#include "defs.h"
+#include "olsr.h"
+#include "mantissa.h"
+#include "common/avl.h"
+
+#define DUPLICATE_CLEANUP_INTERVAL 15000
+#define DUPLICATE_CLEANUP_JITTER 25
+#define DUPLICATE_VTIME 120000
+
+struct dup_entry {
+  struct avl_node avl;
+  union olsr_ip_addr ip;
+  olsr_u16_t seqnr;
+  olsr_u16_t too_low_counter;
+  olsr_u32_t array;
+  clock_t    valid_until;
+};
+
+AVLNODE2STRUCT(duptree2dupentry, struct dup_entry , avl);
+
+void olsr_init_duplicate_set(void);
+struct dup_entry *olsr_create_duplicate_entry(void *ip, olsr_u16_t seqnr);
+int olsr_shall_process_message(void *ip, olsr_u16_t seqnr);
+void olsr_print_duplicate_table(void);
+
+#define OLSR_FOR_ALL_DUP_ENTRIES(dup) \
+{ \
+  struct avl_node *dup_tree_node, *next_dup_tree_node; \
+  for (dup_tree_node = avl_walk_first(&duplicate_set); \
+    dup_tree_node; dup_tree_node = next_dup_tree_node) { \
+    next_dup_tree_node = avl_walk_next(dup_tree_node); \
+    dup = duptree2dupentry(dup_tree_node);
+#define OLSR_FOR_ALL_DUP_ENTRIES_END(dup) }}
+
+#endif /*DUPLICATE_SET_2_H_*/
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/fpm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/fpm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/fpm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/fpm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,208 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008, Sven-Ola Tuecke (sven-ola@gmx.de)
+ * 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 <stdio.h>
+#include <assert.h>
+#include "fpm.h"
+
+#ifdef USE_FPM
+
+#ifndef NDEBUG
+
+fpm itofpm(int i)
+{
+  fpm r;
+  assert(FPM_MIN <= i && i <= FPM_MAX);
+  r = (fpm)itofpm_def(i);
+  return r;
+}
+
+fpm ftofpm(float f)
+{
+  fpm r;
+  assert(FPM_MIN <= (sfpm)f && (sfpm)f <= FPM_MAX);
+  r = (fpm)(sfpm)ftofpm_def(f);
+  return r;
+}
+
+int fpmtoi(fpm a)
+{
+  int r = fpmtoi_def((sfpm)a);
+  return r;
+}
+
+float fpmtof(fpm a)
+{
+  float r = fpmtof_def((sfpm)a);
+  return r;
+}
+
+fpm fpmadd(fpm a, fpm b)
+{
+  fpm r;
+  assert(0 > (sfpm)a || 0 > (sfpm)b || FPM_INT_MAX - (sfpm)a >= (sfpm)b);
+  assert(0 <= (sfpm)a || 0 <= (sfpm)b || (sfpm)a >= FPM_INT_MIN - (sfpm)b);
+  r = (fpm)fpmadd_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmsub(fpm a, fpm b)
+{
+  fpm r;
+  assert(0 > (sfpm)a || 0 <= (sfpm)b || (sfpm)a < FPM_INT_MAX + (sfpm)b);
+  assert(0 <= (sfpm)a || 0 > (sfpm)b || (sfpm)a >= FPM_INT_MIN + (sfpm)b);
+  r = (fpm)fpmsub_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmmul(fpm a, fpm b)
+{
+  fpm r;
+  assert((0 < (sfpm)a) != (0 < (sfpm)b) || ((double)(sfpm)a) * ((double)(sfpm)b) <= (double)FPM_INT_MAX);
+  assert((0 < (sfpm)a) == (0 < (sfpm)b) || ((double)(sfpm)a) * ((double)(sfpm)b) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmmul_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmdiv(fpm a, fpm b) {
+  fpm r;
+  assert(FPM_INT_MIN <= ((long long)(sfpm)a << FPM_BIT) && ((long long)(sfpm)a << FPM_BIT) <= FPM_INT_MAX);
+  r = (fpm)fpmdiv_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmimul(int a, fpm b)
+{
+  fpm r;
+  assert((0 < a) != (0 < (sfpm)b) || ((double)a * (double)(sfpm)b) <= (double)FPM_INT_MAX);
+  assert((0 < a) == (0 < (sfpm)b) || ((double)a * (double)(sfpm)b) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmimul_def(a, (sfpm)b);
+  return r;
+}
+
+fpm fpmmuli(fpm a, int b)
+{
+  fpm r;
+  assert((0 < (sfpm)a) != (0 < b) || ((double)(sfpm)a * (double)b) <= (double)FPM_INT_MAX);
+  assert((0 < (sfpm)a) == (0 < b) || ((double)(sfpm)a * (double)b) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmmuli_def((sfpm)a, b);
+  return r;
+}
+
+fpm fpmidiv(fpm a, int b)
+{
+  fpm r;
+  r = (fpm)fpmidiv_def((sfpm)a, b);
+  return r;
+}
+
+#if 0
+fpm fpmlmul(fpm a, fpm b)
+{
+  fpm r;
+  assert((0 < (sfpm)a) != (0 < (sfpm)b) || ((double)(sfpm)a * (double)(sfpm)b / FPM_NUM) <= (double)FPM_INT_MAX);
+  assert((0 < (sfpm)a) == (0 < (sfpm)b) || ((double)(sfpm)a * (double)(sfpm)b / FPM_NUM) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmlmul_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmldiv(fpm a, fpm b) {
+  fpm r;
+  r = (fpm)fpmldiv_def((sfpm)a, (sfpm)b);
+  return r;
+}
+#endif
+
+#endif /* !NDEBUG */
+
+fpm atofpm(const char *s)
+{
+  float r = 0.0;
+  sscanf(s, "%f", &r);
+  return ftofpm(r);
+}
+
+const char *fpmtoa(fpm a)
+{
+  static int idx = 0;
+  static char ret[4][20];
+
+  idx = (idx + 1) % (sizeof(ret) / sizeof(ret[0]));
+  snprintf(ret[idx], sizeof(ret[0]), "%ld.%03ld", (sfpm)a >> FPM_BIT,
+    (1000 * ((sfpm)(a) & FPM_MSK) + (FPM_NUM / 2)) >> FPM_BIT);
+  return ret[idx];
+}
+
+const char *etxtoa(fpm etx)
+{
+  return etx >= INFINITE_ETX ? "INF" : fpmtoa(etx);
+}
+
+#else /* USE_FPM */
+
+float atofpm(const char *s)
+{
+  float r = 0.0;
+  sscanf(s, "%f", &r);
+  return r;
+}
+
+const char *fpmtoa(float a)
+{
+  static int idx = 0;
+  static char ret[4][20];
+
+  idx = (idx + 1) % (sizeof(ret) / sizeof(ret[0]));
+  snprintf(ret[idx], sizeof(ret[0]), "%.3f", a);
+  return ret[idx];
+}
+
+const char *etxtoa(float etx)
+{
+  return etx >= INFINITE_ETX ? "INF" : fpmtoa(etx);
+}
+
+#endif /* USE_FPM */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/fpm.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/fpm.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/fpm.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/fpm.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,187 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008, Sven-Ola Tuecke (sven-ola@gmx.de)
+ * 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 _FPM_H
+#define _FPM_H
+
+#ifdef USE_FPM
+
+#if 0
+
+/* 
+ * Use this to find implicit number conversions when compiling
+ * Note: comparing pointers is unsigned, so do not use to run.
+ */
+typedef void* fpm;
+typedef signed long sfpm;
+typedef unsigned long ufpm;
+#define FPM_BIT 12
+
+#elif 0
+
+/*
+ * Use this for extra long 64 bit calculations
+ */
+typedef long long fpm;
+typedef signed long long sfpm;
+typedef unsigned long long ufpm;
+#define FPM_BIT 24
+
+#else
+
+/*
+ * The standard math should function with only 32 bits
+ */
+typedef long fpm;
+typedef signed long sfpm;
+typedef unsigned long ufpm;
+#define FPM_BIT 10
+ 
+#endif
+
+#define FPM_NUM (1 << FPM_BIT)
+#define FPM_MSK (FPM_NUM - 1)
+#define FPM_MAX ((sfpm)(~(ufpm)0 >> 1) >> FPM_BIT)
+#define FPM_MIN ((sfpm)-1 - FPM_MAX)
+#define FPM_INT_MAX ((sfpm)(~(ufpm)0 >> 1))
+#define FPM_INT_MIN ((sfpm)-1 - FPM_INT_MAX)
+
+#define itofpm_def(a) (fpm)((sfpm)((a) << FPM_BIT))
+#define ftofpm_def(a) (fpm)((sfpm)((a) * FPM_NUM))
+#define fpmtoi_def(a) (int)((sfpm)(a) >> FPM_BIT)
+#define fpmtof_def(a) ((float)(sfpm)(a) / FPM_NUM)
+
+#define fpmadd_def(a, b) (fpm)((sfpm)(a) + (sfpm)(b))
+#define fpmsub_def(a, b) (fpm)((sfpm)(a) - (sfpm)(b))
+#define fpmmul_def(a, b) (fpm)(((sfpm)(a) * (sfpm)(b)) >> FPM_BIT)
+#define fpmdiv_def(a, b) (fpm)(((sfpm)(a) << FPM_BIT) / (sfpm)(b))
+
+/*
+ * Special: first or second factor is an integer
+ */
+#define fpmimul_def(a, b) (fpm)((int)(a) * (sfpm)(b))
+#define fpmmuli_def(a, b) (fpm)((sfpm)(a) * (int)(b))
+
+/*
+ * Special: divisor is an integer
+ */
+#define fpmidiv_def(a, b) (fpm)((sfpm)(a) / (int)(b))
+
+#if 0
+/*
+ * Special: uses long long for larger numbers, currently unused
+ */
+#define fpmlmul_def(a, b) (sfpm)(((long long)(a) * (b)) >> FPM_BIT)
+#define fpmldiv_def(a, b) (sfpm)(((long long)(a) << FPM_BIT) / (b))
+#endif
+
+#ifdef NDEBUG
+
+#define itofpm itofpm_def
+#define ftofpm ftofpm_def
+#define fpmtoi fpmtoi_def
+#define fpmtof fpmtof_def
+
+#define fpmadd fpmadd_def
+#define fpmsub fpmsub_def
+#define fpmmul fpmmul_def
+#define fpmdiv fpmdiv_def
+#define fpmimul fpmimul_def
+#define fpmmuli fpmmuli_def
+#define fpmidiv fpmidiv_def
+
+#if 0
+#define fpmlmul fpmlmul_def
+#define fpmldiv fpmldiv_def
+#endif
+
+#else /* NDEBUG */
+
+fpm itofpm(int i);
+fpm ftofpm(float f);
+int fpmtoi(fpm a);
+float fpmtof(fpm a);
+
+fpm fpmadd(fpm a, fpm b);
+fpm fpmsub(fpm a, fpm b);
+fpm fpmmul(fpm a, fpm b);
+fpm fpmdiv(fpm a, fpm b);
+fpm fpmimul(int a, fpm b);
+fpm fpmmuli(fpm a, int b);
+fpm fpmidiv(fpm a, int b);
+
+#if 0
+fpm fpmlmul(fpm a, fpm b);
+fpm fpmldiv(fpm a, fpm b);
+#endif
+  
+#endif /* NDEBUG */
+
+#define INFINITE_ETX itofpm(FPM_MAX)
+#define MIN_LINK_QUALITY ftofpm(0.01)
+#define ZERO_ETX itofpm(0)
+#define CEIL_LQDIFF ftofpm(1.1)
+#define FLOOR_LQDIFF ftofpm(0.9)
+
+fpm atofpm(const char *);
+const char *fpmtoa(fpm);
+const char *etxtoa(fpm);
+
+#else /* USE_FPM */
+
+#define INFINITE_ETX ((float)(1 << 30))
+#define ZERO_ETX 0.0
+#define MIN_LINK_QUALITY 0.01
+#define CEIL_LQDIFF 1.1
+#define FLOOR_LQDIFF 0.9
+
+float atofpm(const char *);
+const char *fpmtoa(float);
+const char *etxtoa(float);
+
+#endif /* USE_FPM */
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/generate_msg.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/generate_msg.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/generate_msg.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/generate_msg.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,133 @@
+/*
+ * 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 "generate_msg.h"
+#include "defs.h"
+#include "olsr.h"
+#include "build_msg.h"
+#include "packet.h"
+
+/*
+ * Infomation repositiries
+ */
+#include "hna_set.h"
+#include "mid_set.h"
+#include "tc_set.h"
+#include "mpr_selector_set.h"
+#include "duplicate_set.h"
+#include "neighbor_table.h"
+#include "link_set.h"
+#include "two_hop_neighbor_table.h"
+#include "net_olsr.h"
+
+
+static char pulsedata[] = {'\\', '|', '/', '-'};
+#define PULSE_MAX 4
+static olsr_u8_t pulse_state = 0;
+
+
+void
+generate_hello(void *p)
+{
+  struct hello_message hellopacket;
+  struct interface *ifn = (struct interface *)p;
+
+  olsr_build_hello_packet(&hellopacket, ifn);
+      
+  if(queue_hello(&hellopacket, ifn))
+    net_output(ifn);
+
+  olsr_free_hello_packet(&hellopacket);
+
+}
+
+void
+generate_tc(void *p)
+{
+  struct tc_message tcpacket;
+  struct interface *ifn = (struct interface *)p;
+
+  olsr_build_tc_packet(&tcpacket);
+
+  if(queue_tc(&tcpacket, ifn) && TIMED_OUT(ifn->fwdtimer))
+    {
+      set_buffer_timer(ifn);
+    }
+
+  olsr_free_tc_packet(&tcpacket);
+}
+
+void
+generate_mid(void *p)
+{
+  struct interface *ifn = (struct interface *)p;
+  
+  if(queue_mid(ifn) && TIMED_OUT(ifn->fwdtimer))
+    {
+      set_buffer_timer(ifn);
+    }
+
+}
+
+
+
+void
+generate_hna(void *p)
+{
+  struct interface *ifn = (struct interface *)p;
+  
+  if(queue_hna(ifn) && TIMED_OUT(ifn->fwdtimer))
+    {
+      set_buffer_timer(ifn);
+    }
+}
+
+
+void
+generate_stdout_pulse(void *foo __attribute__((unused)))
+{
+  if(olsr_cnf->debug_level == 0)
+    return;
+
+  pulse_state = pulse_state == 3 ? 0 : pulse_state + 1;
+
+  printf("%c\r", pulsedata[pulse_state]);
+
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/generate_msg.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/generate_msg.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/generate_msg.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/generate_msg.h	2008-10-03 14:45:07.000000000 +0200
@@ -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.
+ *
+ */
+
+#ifndef _OLSR_GEN_MSG
+#define _OLSR_GEN_MSG
+
+#include "interfaces.h"
+
+#define STDOUT_PULSE_INT 600 /* msec */
+
+/* Functions */
+
+void
+generate_hello(void *);
+
+void
+generate_mid(void *);
+
+void
+generate_hna(void *);
+
+void
+generate_tc(void *);
+
+void
+generate_stdout_pulse(void *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hashing.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hashing.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hashing.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hashing.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,159 @@
+
+/*
+ * 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_protocol.h"
+#include "hashing.h"
+#include "defs.h"
+
+/*
+ * Taken from lookup2.c by Bob Jenkins.  (http://burtleburtle.net/bob/c/lookup2.c).
+ * --------------------------------------------------------------------
+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+ * You can use this free for any purpose.  It has no warranty.
+ * --------------------------------------------------------------------
+ */
+
+#define __jhash_mix(a, b, c) \
+{ \
+  a -= b; a -= c; a ^= (c>>13); \
+  b -= c; b -= a; b ^= (a<<8); \
+  c -= a; c -= b; c ^= (b>>13); \
+  a -= b; a -= c; a ^= (c>>12);  \
+  b -= c; b -= a; b ^= (a<<16); \
+  c -= a; c -= b; c ^= (b>>5); \
+  a -= b; a -= c; a ^= (c>>3);  \
+  b -= c; b -= a; b ^= (a<<10); \
+  c -= a; c -= b; c ^= (b>>15); \
+}
+
+static inline olsr_u32_t
+jenkins_hash(const olsr_u8_t * k, olsr_u32_t length)
+{
+  /* k: the key
+   * length: length of the key
+   * initval: the previous hash, or an arbitrary value
+   */
+  olsr_u32_t a, b, c, len;
+
+  /* Set up the internal state */
+  len = length;
+  a = b = 0x9e3779b9;		/* the golden ratio; an arbitrary value */
+  c = 0;			/* the previous hash value */
+
+  /* handle most of the key */
+  while (len >= 12) {
+    a += (k[0] + ((olsr_u32_t) k[1] << 8) + ((olsr_u32_t) k[2] << 16)
+	  + ((olsr_u32_t) k[3] << 24));
+    b += (k[4] + ((olsr_u32_t) k[5] << 8) + ((olsr_u32_t) k[6] << 16)
+	  + ((olsr_u32_t) k[7] << 24));
+    c += (k[8] + ((olsr_u32_t) k[9] << 8) + ((olsr_u32_t) k[10] << 16)
+	  + ((olsr_u32_t) k[11] << 24));
+
+    __jhash_mix(a, b, c);
+
+    k += 12;
+    len -= 12;
+  }
+
+  c += length;
+  switch (len) {
+  case 11:
+    c += ((olsr_u32_t) k[10] << 24);
+  case 10:
+    c += ((olsr_u32_t) k[9] << 16);
+  case 9:
+    c += ((olsr_u32_t) k[8] << 8);
+    /* the first byte of c is reserved for the length */
+  case 8:
+    b += ((olsr_u32_t) k[7] << 24);
+  case 7:
+    b += ((olsr_u32_t) k[6] << 16);
+  case 6:
+    b += ((olsr_u32_t) k[5] << 8);
+  case 5:
+    b += k[4];
+  case 4:
+    a += ((olsr_u32_t) k[3] << 24);
+  case 3:
+    a += ((olsr_u32_t) k[2] << 16);
+  case 2:
+    a += ((olsr_u32_t) k[1] << 8);
+  case 1:
+    a += k[0];
+  }
+  __jhash_mix(a, b, c);
+
+  return c;
+}
+
+
+/**
+ * Hashing function. Creates a key based on an IP address.
+ * @param address the address to hash
+ * @return the hash(a value in the (0 to HASHMASK-1) range)
+ */
+olsr_u32_t
+olsr_ip_hashing(const union olsr_ip_addr *address)
+{
+  olsr_u32_t hash;
+
+  switch (olsr_cnf->ip_version) {
+  case AF_INET:
+    hash = jenkins_hash((const olsr_u8_t *)&address->v4,
+                        sizeof(olsr_u32_t));
+    break;
+  case AF_INET6:
+    hash = jenkins_hash((const olsr_u8_t *)&address->v6,
+			sizeof(struct in6_addr));
+    break;
+  default:
+    hash = 0;
+    break;
+
+  }
+  return hash & HASHMASK;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hashing.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hashing.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hashing.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hashing.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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 _OLSR_HASHING
+#define _OLSR_HASHING
+
+#define	HASHSIZE	128
+#define	HASHMASK	(HASHSIZE - 1)
+
+#include "olsr_types.h"
+
+olsr_u32_t olsr_ip_hashing(const union olsr_ip_addr *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hna_set.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hna_set.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hna_set.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hna_set.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,359 @@
+/*
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+#include "tc_set.h"
+
+
+struct hna_entry hna_set[HASHSIZE];
+struct olsr_cookie_info *hna_net_timer_cookie = NULL;
+struct olsr_cookie_info *hna_entry_mem_cookie = NULL;
+struct olsr_cookie_info *hna_net_mem_cookie = NULL;
+
+/**
+ * Initialize the HNA set
+ */
+int
+olsr_init_hna_set(void)
+{
+  int idx;
+
+  for(idx=0;idx<HASHSIZE;idx++) {
+    hna_set[idx].next = &hna_set[idx];
+    hna_set[idx].prev = &hna_set[idx];
+  }
+
+  hna_net_timer_cookie =
+    olsr_alloc_cookie("HNA Network", OLSR_COOKIE_TYPE_TIMER);
+
+  hna_net_mem_cookie =
+    olsr_alloc_cookie("hna_net", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(hna_net_mem_cookie, sizeof(struct hna_net));
+
+  hna_entry_mem_cookie =
+    olsr_alloc_cookie("hna_entry", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(hna_entry_mem_cookie, sizeof(struct hna_entry));
+
+  return 1;
+}
+
+/**
+ * Lookup a network entry in a networkentry list.
+ *
+ * @param nets the network list to look in
+ * @param net the network to look for
+ * @param mask the netmask to look for
+ *
+ * @return the localized entry or NULL of not found
+ */
+struct hna_net *
+olsr_lookup_hna_net(const struct hna_net *nets, const union olsr_ip_addr *net,
+                    olsr_u8_t prefixlen)
+{
+  struct hna_net *tmp;
+
+  /* Loop trough entrys */
+  for (tmp = nets->next; tmp != nets; tmp = tmp->next) { 
+    if (tmp->prefixlen == prefixlen && ipequal(&tmp->A_network_addr, net)) {
+      return tmp;
+    }
+  }
+
+  /* Not found */
+  return NULL;
+}
+
+
+/**
+ * Lookup a gateway entry
+ *
+ * @param gw the address of the gateway
+ * @return the located entry or NULL if not found
+ */
+struct hna_entry *
+olsr_lookup_hna_gw(const union olsr_ip_addr *gw)
+{
+  struct hna_entry *tmp_hna;
+  olsr_u32_t hash = olsr_ip_hashing(gw);
+
+#if 0
+  OLSR_PRINTF(5, "HNA: lookup entry\n");
+#endif
+    /* Check for registered entry */
+
+  for(tmp_hna = hna_set[hash].next;
+      tmp_hna != &hna_set[hash];
+      tmp_hna = tmp_hna->next) {
+    if(ipequal(&tmp_hna->A_gateway_addr, gw)) {
+      return tmp_hna;
+    }
+  }
+  
+  /* Not found */
+  return NULL;
+}
+
+
+
+/**
+ *Add a gatewayentry to the HNA set
+ *
+ *@param addr the address of the gateway
+ *
+ *@return the created entry
+ */
+struct hna_entry *
+olsr_add_hna_entry(const union olsr_ip_addr *addr)
+{
+  struct hna_entry *new_entry;
+  olsr_u32_t hash;
+
+  new_entry = olsr_cookie_malloc(hna_entry_mem_cookie);
+
+  /* Fill struct */
+  new_entry->A_gateway_addr = *addr;
+
+  /* Link nets */
+  new_entry->networks.next = &new_entry->networks;
+  new_entry->networks.prev = &new_entry->networks;
+
+  /* queue */
+  hash = olsr_ip_hashing(addr);
+  
+  hna_set[hash].next->prev = new_entry;
+  new_entry->next = hna_set[hash].next;
+  hna_set[hash].next = new_entry;
+  new_entry->prev = &hna_set[hash];
+
+  return new_entry;
+}
+
+/**
+ * Adds a network entry to a HNA gateway.
+ *
+ * @param hna_gw the gateway entry to add the network to
+ * @param net the networkaddress to add
+ * @param mask the netmask
+ *
+ * @return the newly created entry
+ */
+struct hna_net *
+olsr_add_hna_net(struct hna_entry *hna_gw, const union olsr_ip_addr *net,
+                 olsr_u8_t prefixlen)
+{
+  /* Add the net */
+  struct hna_net *new_net = olsr_cookie_malloc(hna_net_mem_cookie);
+  
+  /* Fill struct */
+  memset(new_net, 0, sizeof(struct hna_net));
+  new_net->A_network_addr = *net;
+  new_net->prefixlen = prefixlen;
+
+  /* Set backpointer */
+  new_net->hna_gw = hna_gw;
+
+  /* Queue */
+  hna_gw->networks.next->prev = new_net;
+  new_net->next = hna_gw->networks.next;
+  hna_gw->networks.next = new_net;
+  new_net->prev = &hna_gw->networks;
+
+  return new_net;
+}
+
+/**
+ * Callback for the hna_net timer.
+ */
+static void
+olsr_expire_hna_net_entry(void *context)
+{
+#ifdef DEBUG
+  struct ipaddr_str buf1, buf2;
+#endif
+  struct hna_net *net_to_delete;
+  struct hna_entry *hna_gw;
+
+  net_to_delete = (struct hna_net *)context;
+  net_to_delete->hna_net_timer = NULL; /* be pedandic */
+  hna_gw = net_to_delete->hna_gw;
+
+#ifdef DEBUG
+  OLSR_PRINTF(5, "HNA: timeout %s/%u via hna-gw %s\n", 
+              olsr_ip_to_string(&buf1, &net_to_delete->A_network_addr),
+              net_to_delete->prefixlen,
+              olsr_ip_to_string(&buf2, &hna_gw->A_gateway_addr));
+#endif
+
+  /*
+   * Delete the rt_path for the entry.
+   */
+  olsr_delete_routing_table(&net_to_delete->A_network_addr,
+                            net_to_delete->prefixlen,
+                            &hna_gw->A_gateway_addr);
+
+
+  /* Delete hna_gw if empty */
+  if (hna_gw->networks.next == &hna_gw->networks) {
+    DEQUEUE_ELEM(hna_gw);
+    olsr_cookie_free(hna_entry_mem_cookie, hna_gw);
+  }
+
+  DEQUEUE_ELEM(net_to_delete);
+  olsr_cookie_free(hna_net_mem_cookie, net_to_delete);
+}
+
+/**
+ * Update a HNA entry. If it does not exist it
+ * is created.
+ * This is the only function that should be called 
+ * from outside concerning creation of HNA entries.
+ *
+ *@param gw address of the gateway
+ *@param net address of the network
+ *@param mask the netmask
+ *@param vtime the validitytime of the entry
+ *
+ *@return nada
+ */
+void
+olsr_update_hna_entry(const union olsr_ip_addr *gw, const union olsr_ip_addr *net,
+                      olsr_u8_t prefixlen, olsr_reltime vtime)
+{
+  struct hna_entry *gw_entry;
+  struct hna_net *net_entry;
+
+  gw_entry = olsr_lookup_hna_gw(gw);
+  if (!gw_entry) {
+
+    /* Need to add the entry */
+    gw_entry = olsr_add_hna_entry(gw);
+  }
+
+  net_entry = olsr_lookup_hna_net(&gw_entry->networks, net, prefixlen);
+  if (net_entry == NULL)  {
+
+    /* Need to add the net */
+    net_entry = olsr_add_hna_net(gw_entry, net, prefixlen);
+    changes_hna = OLSR_TRUE;
+  }
+
+  /*
+   * Add the rt_path for the entry.
+   */
+  olsr_insert_routing_table(&net_entry->A_network_addr,
+                            net_entry->prefixlen,
+                            &gw_entry->A_gateway_addr,
+                            OLSR_RT_ORIGIN_HNA);
+
+  /*
+   * Start, or refresh the timer, whatever is appropriate.
+   */
+  olsr_set_timer(&net_entry->hna_net_timer, vtime,
+                 OLSR_HNA_NET_JITTER, OLSR_TIMER_ONESHOT,
+                 &olsr_expire_hna_net_entry, net_entry,
+                 hna_net_timer_cookie->ci_id);
+}
+
+
+/**
+ * Print all HNA entries.
+ *
+ *@return nada
+ */
+void
+olsr_print_hna_set(void)
+{
+#ifdef NODEBUG
+  /* The whole function doesn't do anything else. */
+  int idx;
+
+  OLSR_PRINTF(1, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- HNA SET\n\n",
+              nowtm->tm_hour,
+              nowtm->tm_min,
+              nowtm->tm_sec,
+	      (int)now.tv_usec/10000);
+  
+  if(olsr_cnf->ip_version == AF_INET)
+    OLSR_PRINTF(1, "IP net          netmask         GW IP\n");
+  else
+    OLSR_PRINTF(1, "IP net/prefixlen               GW IP\n");
+
+  for(idx=0;idx<HASHSIZE;idx++)
+    {
+      struct hna_entry *tmp_hna = hna_set[idx].next;
+      /* Check all entrys */
+      while(tmp_hna != &hna_set[idx])
+	{
+	  /* Check all networks */
+	  struct hna_net *tmp_net = tmp_hna->networks.next;
+
+	  while(tmp_net != &tmp_hna->networks)
+	    {
+	      if(olsr_cnf->ip_version == AF_INET)
+		{
+                  struct ipaddr_str buf;
+		  OLSR_PRINTF(1, "%-15s ", olsr_ip_to_string(&buf, &tmp_net->A_network_addr));
+		  OLSR_PRINTF(1, "%-15d ", tmp_net->prefix_len);
+		  OLSR_PRINTF(1, "%-15s\n", olsr_ip_to_string(&buf, &tmp_hna->A_gateway_addr));
+		}
+	      else
+		{
+                  struct ipaddr_str buf;
+		  OLSR_PRINTF(1, "%-27s/%d", olsr_ip_to_string(&buf, &tmp_net->A_network_addr), tmp_net->A_netmask.v6);
+		  OLSR_PRINTF(1, "%s\n", olsr_ip_to_string(&buf, &tmp_hna->A_gateway_addr));
+		}
+
+	      tmp_net = tmp_net->next;
+	    }
+	  tmp_hna = tmp_hna->next;
+	}
+    }
+#endif
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hna_set.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hna_set.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hna_set.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hna_set.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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 _OLSR_HNA
+#define _OLSR_HNA
+
+#include "hashing.h"
+#include "olsr_types.h"
+#include "mantissa.h"
+
+#include <time.h>
+
+/* hna_netmask declared in packet.h */
+
+struct hna_net
+{
+  union olsr_ip_addr A_network_addr;
+  olsr_u8_t          prefixlen;
+  struct timer_entry *hna_net_timer;
+  struct hna_entry   *hna_gw; /* backpointer to the owning HNA entry */
+  struct hna_net     *next;
+  struct hna_net     *prev;
+};
+
+#define OLSR_HNA_NET_JITTER 5 /* percent */
+
+struct hna_entry
+{
+  union olsr_ip_addr A_gateway_addr;
+  struct hna_net     networks;
+  struct hna_entry   *next;
+  struct hna_entry   *prev;
+};
+
+#define OLSR_FOR_ALL_HNA_ENTRIES(hna) \
+{ \
+  int _idx; \
+  for (_idx = 0; _idx < HASHSIZE; _idx++) { \
+    for(hna = hna_set[_idx].next; \
+        hna != &hna_set[_idx]; \
+        hna = hna->next)
+#define OLSR_FOR_ALL_HNA_ENTRIES_END(hna) }}
+
+extern struct hna_entry hna_set[HASHSIZE];
+
+
+int
+olsr_init_hna_set(void);
+
+struct hna_net *
+olsr_lookup_hna_net(const struct hna_net *, const union olsr_ip_addr *, olsr_u8_t);
+
+struct hna_entry *
+olsr_lookup_hna_gw(const union olsr_ip_addr *);
+
+struct hna_entry *
+olsr_add_hna_entry(const union olsr_ip_addr *);
+
+struct hna_net *
+olsr_add_hna_net(struct hna_entry *, const union olsr_ip_addr *, olsr_u8_t);
+
+void
+olsr_update_hna_entry(const union olsr_ip_addr *, const union olsr_ip_addr *, olsr_u8_t, olsr_reltime);
+
+void
+olsr_print_hna_set(void);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hysteresis.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hysteresis.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hysteresis.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hysteresis.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,205 @@
+/*
+ * 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 <time.h>
+
+#include "olsr_protocol.h"
+#include "hysteresis.h"
+#include "defs.h"
+#include "olsr.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+#include "scheduler.h"
+
+#define hscaling olsr_cnf->hysteresis_param.scaling
+#define hhigh    olsr_cnf->hysteresis_param.thr_high
+#define hlow     olsr_cnf->hysteresis_param.thr_low
+
+float
+olsr_hyst_calc_stability(float old_quality)
+{
+  return (((1 - hscaling) * old_quality) + hscaling);
+}
+
+
+
+float
+olsr_hyst_calc_instability(float old_quality)
+{
+  return ((1 - hscaling) * old_quality);
+}
+
+
+
+int
+olsr_process_hysteresis(struct link_entry *entry)
+{
+  //printf("PROCESSING QUALITY: %f\n", entry->L_link_quality);
+  if(entry->L_link_quality > hhigh)
+    {
+      if(entry->L_link_pending == 1)
+	{
+          struct ipaddr_str buf;
+	  OLSR_PRINTF(1, "HYST[%s] link set to NOT pending!\n", 
+		      olsr_ip_to_string(&buf, &entry->neighbor_iface_addr));
+	  changes_neighborhood = OLSR_TRUE;
+	}
+
+      /* Pending = false */
+      entry->L_link_pending = 0;
+
+      if(!TIMED_OUT(entry->L_LOST_LINK_time))
+	changes_neighborhood = OLSR_TRUE;
+
+      /* time = now -1 */
+      entry->L_LOST_LINK_time = now_times - 1;
+
+      return 1;
+    }
+
+  if(entry->L_link_quality < hlow)
+    {
+      if(entry->L_link_pending == 0)
+	{
+          struct ipaddr_str buf;
+	  OLSR_PRINTF(1, "HYST[%s] link set to pending!\n", 
+		      olsr_ip_to_string(&buf, &entry->neighbor_iface_addr));
+	  changes_neighborhood = OLSR_TRUE;
+	}
+      
+      /* Pending = true */
+      entry->L_link_pending = 1;
+
+      if(TIMED_OUT(entry->L_LOST_LINK_time))
+	changes_neighborhood = OLSR_TRUE;
+
+      /* Timer = min (L_time, current time + NEIGHB_HOLD_TIME) */
+      entry->L_LOST_LINK_time = MIN(GET_TIMESTAMP(NEIGHB_HOLD_TIME * MSEC_PER_SEC),
+                                    entry->link_timer->timer_clock);
+
+      /* (the link is then considered as lost according to section
+	 8.5 and this may produce a neighbor loss).
+	 WTF?
+      */
+      return -1;
+    }
+
+  /*
+   *If we get here then:
+   *(HYST_THRESHOLD_LOW <= entry->L_link_quality <= HYST_THRESHOLD_HIGH)
+   */
+
+  /* L_link_pending and L_LOST_LINK_time remain unchanged. */
+  return 0;
+
+
+}
+
+/**
+ *Update the hello timeout of a hysteresis link
+ *entry
+ *
+ *@param entry the link entry to update
+ *@param htime the hello interval to use
+ *
+ *@return nada
+ */
+void
+olsr_update_hysteresis_hello(struct link_entry *entry, olsr_reltime htime)
+{
+  struct ipaddr_str buf;
+  OLSR_PRINTF(3, "HYST[%s]: HELLO update vtime %u ms\n",
+              olsr_ip_to_string(&buf, &entry->neighbor_iface_addr), htime+htime/2);
+
+  olsr_set_timer(&entry->link_hello_timer, htime + htime/2, OLSR_LINK_HELLO_JITTER,
+                 OLSR_TIMER_PERIODIC, &olsr_expire_link_hello_timer, entry, 0);
+
+  return;
+}
+
+
+
+void
+update_hysteresis_incoming(union olsr_ip_addr *remote, struct interface *local, olsr_u16_t seqno)
+{
+  struct link_entry *lnk = lookup_link_entry(remote, NULL, local);
+
+  /* Calculate new quality */
+  if(lnk != NULL)
+    {
+#ifdef DEBUG
+      struct ipaddr_str buf;
+#endif
+      lnk->L_link_quality = olsr_hyst_calc_stability(lnk->L_link_quality);
+#ifdef DEBUG
+      OLSR_PRINTF(3, "HYST[%s]: %f\n", olsr_ip_to_string(&buf, remote), lnk->L_link_quality);
+#endif
+
+      /* 
+       * see how many packets we have missed and update the link quality
+       * for each missed packet; HELLOs have already been accounted for by
+       * the timeout function and the number of missed HELLOs has already
+       * been added to olsr_seqno there
+       */
+
+      if (lnk->olsr_seqno_valid && 
+          (unsigned short)(seqno - lnk->olsr_seqno) < 100)
+	  while (lnk->olsr_seqno != seqno)
+	    {
+	      lnk->L_link_quality = olsr_hyst_calc_instability(lnk->L_link_quality);
+#ifdef DEBUG
+	      OLSR_PRINTF(5, "HYST[%s] PACKET LOSS! %f\n",
+			  olsr_ip_to_string(&buf, remote), lnk->L_link_quality);
+#endif
+	      if(lnk->L_link_quality < olsr_cnf->hysteresis_param.thr_low)
+		break;
+
+	      lnk->olsr_seqno++;
+	    }
+
+
+      lnk->olsr_seqno = seqno + 1;
+      lnk->olsr_seqno_valid = OLSR_TRUE;
+
+      //printf("Updating seqno to: %d\n", lnk->olsr_seqno);
+    }
+  return;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hysteresis.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hysteresis.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/hysteresis.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/hysteresis.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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 _OLSR_HYSTERESIS
+#define _OLSR_HYSTERESIS
+
+#include "link_set.h"
+#include "mantissa.h"
+
+float
+olsr_hyst_calc_stability
+(float);
+
+int
+olsr_process_hysteresis(struct link_entry *);
+
+float
+olsr_hyst_calc_instability(float);
+
+void
+olsr_update_hysteresis_hello(struct link_entry *, olsr_reltime);
+
+void
+update_hysteresis_incoming(union olsr_ip_addr *, struct interface *, olsr_u16_t);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ifnet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ifnet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ifnet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ifnet.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ */
+
+/* Network interface configuration interface.
+ * Platform independent - the implementations
+ * reside in OS/ifnet.c(e.g. linux/ifnet.c)
+ */
+
+#ifndef _OLSR_IFNET
+#define _OLSR_IFNET
+
+/* To get ifreq */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include "olsr_cfg.h"
+
+int
+set_flag(char *, short);
+
+void
+check_interface_updates(void *);
+
+int
+chk_if_changed(struct olsr_if *);
+
+int
+chk_if_up(struct olsr_if *, int);
+
+int
+add_hemu_if(struct olsr_if *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/.indent.pro ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/.indent.pro
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/.indent.pro	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/.indent.pro	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1 @@
+-i2 -npcs -br -brs -ce -ncs -bbb -cd40 -l80 -psl
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/interfaces.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/interfaces.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/interfaces.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/interfaces.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,367 @@
+/*
+ * 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 "defs.h"
+#include "interfaces.h"
+#include "ifnet.h"
+#include "scheduler.h"
+#include "olsr.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+
+/* The interface linked-list */
+struct interface *ifnet;
+
+
+/* Ifchange functions */
+struct ifchgf
+{
+  int (*function)(struct interface *, int);
+  struct ifchgf *next;
+};
+
+static struct ifchgf *ifchgf_list;
+
+
+/* Some cookies for stats keeping */
+struct olsr_cookie_info *interface_poll_timer_cookie = NULL;
+struct olsr_cookie_info *hello_gen_timer_cookie = NULL;
+struct olsr_cookie_info *tc_gen_timer_cookie = NULL;
+struct olsr_cookie_info *mid_gen_timer_cookie = NULL;
+struct olsr_cookie_info *hna_gen_timer_cookie = NULL;
+
+/**
+ *Do initialization of various data needed for
+ *network interface management.
+ *This function also tries to set up the given interfaces.
+ *
+ *@return the number of interfaces configured
+ */
+int
+ifinit(void)
+{
+  struct olsr_if *tmp_if;
+
+  /* Initial values */
+  ifnet = NULL;
+
+  /*
+   * Get some cookies for getting stats to ease troubleshooting.
+   */
+  interface_poll_timer_cookie =
+    olsr_alloc_cookie("Interface Polling", OLSR_COOKIE_TYPE_TIMER);
+
+  hello_gen_timer_cookie =
+    olsr_alloc_cookie("Hello Generation", OLSR_COOKIE_TYPE_TIMER);
+  tc_gen_timer_cookie =
+    olsr_alloc_cookie("TC Generation", OLSR_COOKIE_TYPE_TIMER);
+  mid_gen_timer_cookie =
+    olsr_alloc_cookie("MID Generation", OLSR_COOKIE_TYPE_TIMER);
+  hna_gen_timer_cookie =
+    olsr_alloc_cookie("HNA Generation", OLSR_COOKIE_TYPE_TIMER);
+
+  OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n");
+  /* Run trough all interfaces immedeatly */
+  for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
+    if (!tmp_if->host_emul) {
+      if (!olsr_cnf->host_emul) /* XXX: TEMPORARY! */
+        chk_if_up(tmp_if, 1);	
+    } else {
+      add_hemu_if(tmp_if);
+    }
+  }
+  
+  /* Kick a periodic timer for the network interface update function */
+  olsr_start_timer((unsigned int)olsr_cnf->nic_chgs_pollrate * MSEC_PER_SEC, 5,
+                   OLSR_TIMER_PERIODIC, &check_interface_updates, NULL,
+                   interface_poll_timer_cookie->ci_id);
+
+  return (ifnet == NULL) ? 0 : 1;
+}
+
+void
+run_ifchg_cbs(struct interface *ifp, int flag)
+{
+  struct ifchgf *tmp_ifchgf_list = ifchgf_list;
+
+  while(tmp_ifchgf_list != NULL)
+    {
+      tmp_ifchgf_list->function(ifp, flag);
+      tmp_ifchgf_list = tmp_ifchgf_list->next;
+    }
+}
+
+
+/**
+ *Find the local interface with a given address.
+ *
+ *@param addr the address to check.
+ *
+ *@return the interface struct representing the interface
+ *that matched the address.
+ */
+
+struct interface *
+if_ifwithaddr(const union olsr_ip_addr *addr)
+{
+  struct interface *ifp;
+
+  if(!addr)
+    return NULL;
+
+  for (ifp = ifnet; ifp; ifp = ifp->int_next)
+    {
+      if(olsr_cnf->ip_version == AF_INET)
+	{
+	  /* IPv4 */
+	  //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr));
+	  //printf("%s\n", olsr_ip_to_string(addr));
+
+	  if (((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr == addr->v4.s_addr)
+	      return ifp;
+	}
+      else
+	{
+	  /* IPv6 */
+	  //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr));
+	  //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr));
+          if (ip6equal(&ifp->int6_addr.sin6_addr, &addr->v6))
+	    return ifp;
+	}
+    }
+  return NULL;
+}
+
+
+
+/**
+ *Find the interface with a given number.
+ *
+ *@param nr the number of the interface to find.
+ *
+ *@return return the interface struct representing the interface
+ *that matched the number.
+ */
+struct interface *
+if_ifwithsock(int fd)
+{
+  struct interface *ifp;
+  ifp = ifnet;
+
+  while (ifp) 
+    {
+      if (ifp->olsr_socket == fd)
+	return ifp;
+      ifp = ifp->int_next;
+    }
+  
+  return NULL;
+}
+
+
+/**
+ *Find the interface with a given label.
+ *
+ *@param if_name the label of the interface to find.
+ *
+ *@return return the interface struct representing the interface
+ *that matched the label.
+ */
+struct interface *
+if_ifwithname(const char *if_name)
+{
+  struct interface *ifp = ifnet;
+  while (ifp) {
+    /* good ol' strcmp should be sufficcient here */
+    if (strcmp(ifp->int_name, if_name) == 0) {
+      return ifp;
+    }
+    ifp = ifp->int_next;
+  }
+  return NULL;
+}
+
+/**
+ *Find the interface with a given interface index.
+ *
+ *@param iif_index of the interface to find.
+ *
+ *@return return the interface struct representing the interface
+ *that matched the iif_index.
+ */
+struct interface *
+if_ifwithindex(const int if_index)
+{
+  struct interface *ifp = ifnet;
+  while (ifp != NULL) {
+      if (ifp->if_index == if_index) {
+          return ifp;
+      }
+      ifp = ifp->int_next;
+  }
+  return NULL;
+}
+
+/**
+ *Get an interface name for a given interface index
+ *
+ *@param iif_index of the interface to find.
+ *
+ *@return "" or interface name.
+ */
+const char *
+if_ifwithindex_name(const int if_index)
+{
+  const struct interface * const ifp = if_ifwithindex(if_index);
+  return ifp == NULL ? "void" : ifp->int_name;
+}
+
+
+/**
+ *Create a new interf_name struct using a given
+ *name and insert it into the interface list.
+ *
+ *@param name the name of the interface.
+ *
+ *@return nada
+ */
+struct olsr_if *
+queue_if(const char *name, int hemu)
+{
+  struct olsr_if *interf_n = olsr_cnf->interfaces;
+  size_t name_size;
+
+  //printf("Adding interface %s\n", name);
+
+  /* check if the inerfaces already exists */
+  while(interf_n != NULL)
+    {
+      if(memcmp(interf_n->name, name, strlen(name)) == 0)
+	{
+	  fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
+	  return NULL;
+	}
+      interf_n = interf_n->next;
+    }
+
+  interf_n = olsr_malloc(sizeof(struct olsr_if), "queue interface");
+
+  name_size = strlen(name) + 1;
+  interf_n->name = olsr_malloc(name_size, "queue interface name");
+  interf_n->cnf = NULL;
+  interf_n->interf = NULL;
+  interf_n->configured = 0;
+
+  interf_n->host_emul = hemu ? OLSR_TRUE : OLSR_FALSE;
+
+  strscpy(interf_n->name, name, name_size);
+  interf_n->next = olsr_cnf->interfaces;
+  olsr_cnf->interfaces = interf_n;
+
+  return interf_n;
+}
+
+
+
+/**
+ *Add an ifchange function. These functions are called on all (non-initial)
+ *changes in the interface set.
+ *
+ *@param
+ *
+ *@return
+ */
+int
+add_ifchgf(int (*f)(struct interface *, int))
+{
+
+  struct ifchgf *new_ifchgf;
+
+  new_ifchgf = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
+
+  new_ifchgf->next = ifchgf_list;
+  new_ifchgf->function = f;
+
+  ifchgf_list = new_ifchgf;
+
+  return 1;
+}
+
+
+
+/*
+ * Remove an ifchange function
+ */
+int
+del_ifchgf(int (*f)(struct interface *, int))
+{
+  struct ifchgf *tmp_ifchgf, *prev;
+
+  tmp_ifchgf = ifchgf_list;
+  prev = NULL;
+
+  while(tmp_ifchgf)
+    {
+      if(tmp_ifchgf->function == f)
+	{
+	  /* Remove entry */
+	  if(prev == NULL)
+	    {
+	      ifchgf_list = tmp_ifchgf->next;
+	      free(tmp_ifchgf);
+	    }
+	  else
+	    {
+	      prev->next = tmp_ifchgf->next;
+	      free(tmp_ifchgf);
+	    }
+	  return 1;
+	}
+      prev = tmp_ifchgf;
+      tmp_ifchgf = tmp_ifchgf->next;
+    }
+
+  return 0;
+}
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/interfaces.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/interfaces.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/interfaces.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/interfaces.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,234 @@
+/*
+ * 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 _OLSR_INTERFACE
+#define _OLSR_INTERFACE
+
+#include <sys/types.h>
+#ifdef _MSC_VER
+#include <WS2tcpip.h>
+#undef interface
+#else
+#include <sys/socket.h>
+#endif
+#include <time.h>
+
+#include "olsr_types.h"
+#include "mantissa.h"
+
+#define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
+
+
+#define IPV6_ADDR_ANY		0x0000U
+
+#define IPV6_ADDR_UNICAST      	0x0001U
+#define IPV6_ADDR_MULTICAST    	0x0002U
+#define IPV6_ADDR_ANYCAST	0x0004U
+
+#define IPV6_ADDR_LOOPBACK	0x0010U
+#define IPV6_ADDR_LINKLOCAL	0x0020U
+#define IPV6_ADDR_SITELOCAL	0x0040U
+
+#define IPV6_ADDR_COMPATv4	0x0080U
+
+#define IPV6_ADDR_SCOPE_MASK	0x00f0U
+
+#define IPV6_ADDR_MAPPED	0x1000U
+#define IPV6_ADDR_RESERVED	0x2000U
+
+
+#define MAX_IF_METRIC           100
+
+#define WEIGHT_LOWEST           0       /* No weight            */
+#define WEIGHT_LOW              1       /* Low                  */
+#define WEIGHT_ETHERNET_1GBP    2       /* Ethernet 1Gb+        */
+#define WEIGHT_ETHERNET_1GB     4       /* Ethernet 1Gb         */
+#define WEIGHT_ETHERNET_100MB   8       /* Ethernet 100Mb       */
+#define WEIGHT_ETHERNET_10MB    16      /* Ethernet 10Mb        */
+#define WEIGHT_ETHERNET_DEFAULT 32      /* Ethernet unknown rate*/
+#define WEIGHT_WLAN_HIGH        64      /* >54Mb WLAN           */
+#define WEIGHT_WLAN_54MB        128     /* 54Mb 802.11g         */
+#define WEIGHT_WLAN_11MB        256     /* 11Mb 802.11b         */
+#define WEIGHT_WLAN_LOW         512     /* <11Mb WLAN           */
+#define WEIGHT_WLAN_DEFAULT     1024    /* WLAN unknown rate    */
+#define WEIGHT_SERIAL           2048    /* Serial device        */
+#define WEIGHT_HIGH             4096    /* High                 */
+#define WEIGHT_HIGHEST          8192    /* Really high          */
+
+struct if_gen_property
+{
+  olsr_u32_t             owner_id;
+  void                   *data;
+  struct if_gen_property *next;
+};
+
+struct vtimes
+{
+  olsr_u8_t hello;
+  olsr_u8_t tc;
+  olsr_u8_t mid;
+  olsr_u8_t hna;
+};
+
+/* Output buffer structure. This should actually be in net_olsr.h but we have circular references then.
+ */
+struct olsr_netbuf
+{
+  olsr_u8_t *buff;     /* Pointer to the allocated buffer */
+  int bufsize;    /* Size of the buffer */
+  int maxsize;    /* Max bytes of payload that can be added to the buffer */
+  int pending;    /* How much data is currently pending in the buffer */
+  int reserved;   /* Plugins can reserve space in buffers */
+};
+
+/**
+ *A struct containing all necessary information about each
+ *interface participating in the OLSRD routing
+ */
+struct interface 
+{
+  /* IP version 4 */
+  struct	sockaddr_in int_addr;		/* address */
+  struct	sockaddr_in int_netmask;		/* netmask */
+  struct	sockaddr_in int_broadaddr;         /* broadcast address */
+  /* IP version 6 */
+  struct        sockaddr_in6 int6_addr;         /* Address */
+  struct        sockaddr_in6 int6_multaddr;     /* Multicast */
+  /* IP independent */
+  union         olsr_ip_addr ip_addr;
+  int           is_hcif;                        /* Is this a emulated host-client if? */
+  
+  int           olsr_socket;        /* The broadcast socket for this interface */
+  
+  int	          int_metric;			/* metric of interface */
+  int           int_mtu;        /* MTU of interface */
+  int	          int_flags;			/* see below */
+  int           if_index;       /* Kernels index of this interface */
+  int           is_wireless;    /* wireless interface or not*/
+  char	        *int_name;			/* from kernel if structure */
+  olsr_u16_t    olsr_seqnum;    /* Olsr message seqno */
+
+  /* Periodic message generation timers */
+  struct timer_entry *hello_gen_timer;
+  struct timer_entry *hna_gen_timer;
+  struct timer_entry *mid_gen_timer;
+  struct timer_entry *tc_gen_timer;
+
+#ifdef linux
+/* Struct used to store original redirect/ingress setting */
+  struct nic_state
+  {
+    char redirect; /* The original state of icmp redirect */
+    char spoof; /* The original state of the IP spoof filter */
+  } nic_state;
+#endif
+
+  olsr_reltime  hello_etime;
+  struct        vtimes valtimes;
+
+  clock_t       fwdtimer;                       /* Timeout for OLSR forwarding on this if */
+
+  struct olsr_netbuf netbuf;                    /* the buffer to construct the packet data */
+
+  struct        if_gen_property *gen_properties;/* Generic interface properties */
+  
+  int           ttl_index; /* index in TTL array for fish-eye */
+  
+  olsr_bool	immediate_send_tc; /* Hello's are sent immediately normally, this flag prefers to send TC's */
+
+  struct	interface *int_next;
+};
+
+
+#define OLSR_DEFAULT_MTU             1500
+
+/* Ifchange actions */
+
+#define IFCHG_IF_ADD           1
+#define IFCHG_IF_REMOVE        2
+#define IFCHG_IF_UPDATE        3
+
+/* The interface linked-list */
+extern struct interface *ifnet;
+
+int
+ifinit(void);
+
+void
+run_ifchg_cbs(struct interface *, int);
+
+struct interface *
+if_ifwithsock(int);
+
+struct interface *
+if_ifwithaddr(const union olsr_ip_addr *);
+
+struct interface *
+if_ifwithname(const char *);
+
+const char *
+if_ifwithindex_name(const int if_index);
+
+struct interface *
+if_ifwithindex(const int if_index);
+
+struct olsr_if *
+queue_if(const char *, int);
+
+int
+add_ifchgf(int (*f)(struct interface *, int));
+
+int
+del_ifchgf(int (*f)(struct interface *, int));
+
+extern struct olsr_cookie_info *interface_poll_timer_cookie;
+extern struct olsr_cookie_info *hello_gen_timer_cookie;
+extern struct olsr_cookie_info *tc_gen_timer_cookie;
+extern struct olsr_cookie_info *mid_gen_timer_cookie;
+extern struct olsr_cookie_info *hna_gen_timer_cookie;
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipcalc.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipcalc.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipcalc.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipcalc.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,166 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2007, Bernd Petrovitsch <berndÃ¦firmix.at>
+ * 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 "ipcalc.h"
+
+int
+prefix_to_netmask(olsr_u8_t *a, int len, olsr_u8_t prefixlen)
+{
+#if !defined(NODEBUG) && defined(DEBUG)
+  struct ipaddr_str buf;
+  const olsr_u8_t *a_start = a;
+#endif
+  int p;
+  const olsr_u8_t *a_end;
+
+  a_end = a+len;
+  for (p = prefixlen; a < a_end && p > 8; p -= 8) {
+    *a++ = 0xff;
+  }
+  if (a >= a_end) {
+    return 0;
+  }
+  *a++ = 0xff << (8 - p);
+  while (a < a_end) {
+    *a++ = 0;
+  }
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Prefix %d = Netmask: %s\n", prefixlen, inet_ntop(olsr_cnf->ip_version, a_start, buf.buf, sizeof(buf.buf)));
+#endif
+  return 1;
+}
+
+olsr_u8_t
+netmask_to_prefix(const olsr_u8_t *adr, int len)
+{
+  struct ipaddr_str buf;
+  const olsr_u8_t * const a_end = adr+len;
+  olsr_u16_t prefix = 0;
+  const olsr_u8_t *a;
+  for (a = adr; a < a_end && *a == 0xff; a++) {
+    prefix += 8;
+  }
+  if (a < a_end) {
+    /* handle the last byte */
+    switch (*a) {
+    case   0: prefix += 0; break;
+    case 128: prefix += 1; break;
+    case 192: prefix += 2; break;
+    case 224: prefix += 3; break;
+    case 240: prefix += 4; break;
+    case 248: prefix += 5; break;
+    case 252: prefix += 6; break;
+    case 254: prefix += 7; break;
+    case 255: prefix += 8; break; /* Shouldn't happen */
+    default:
+      OLSR_PRINTF(0, "%s: Got bogus netmask %s\n", __func__, olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr));
+      prefix = UCHAR_MAX;
+      *(int *)0 = 0;
+      break;
+    }
+  }
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr), prefix);
+#endif
+  return prefix;
+}
+
+const char *
+olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix)
+{
+  /* We need for IPv6 an IP address + '/' + prefix and for IPv4 an IP address + '/' + a netmask */
+  static char buf[MAX(INET6_ADDRSTRLEN + 1 + 3, INET_ADDRSTRLEN + 1 + INET_ADDRSTRLEN)];
+  const char *rv;
+
+  if(olsr_cnf->ip_version == AF_INET) {
+    /* IPv4 */
+    int len;
+    union olsr_ip_addr netmask;
+    rv = inet_ntop(AF_INET, &prefix->prefix.v4, buf, sizeof(buf));
+    len = strlen(buf);
+    buf[len++] = '/';
+    olsr_prefix_to_netmask(&netmask, prefix->prefix_len);
+    inet_ntop(AF_INET, &netmask.v4, buf+len, sizeof(buf)-len);
+  } else {
+    /* IPv6 */
+    int len;
+    rv = inet_ntop(AF_INET6, &prefix->prefix.v6, buf, sizeof(buf));
+    len = strlen(buf);
+    buf[len++] = '/';
+    snprintf(buf+len, sizeof(buf)-len, "/%d", prefix->prefix_len);
+  }
+  return rv;
+}
+
+
+/* see if the ipaddr is in the net. That is equivalent to the fact that the net part
+ * of both are equal. So we must compare the first <prefixlen> bits.
+ */
+int ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net)
+{
+  int rv;
+  if(olsr_cnf->ip_version == AF_INET) {
+    olsr_u32_t netmask = ~0 << (32 - net->prefix_len);
+    rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
+  } else {
+    /* IPv6 */
+    olsr_u32_t netmask;
+    const olsr_u32_t *i = (const olsr_u32_t *)&ipaddr->v6;
+    const olsr_u32_t *n = (const olsr_u32_t *)&net->prefix.v6;
+    unsigned int prefix_len;
+    for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
+      if (*i != *n) {
+        return OLSR_FALSE;
+      }
+      i++;
+      n++;
+    }
+    netmask = ~0 << (32 - prefix_len);
+    rv = (*i & netmask) == (*n & netmask);
+  }
+  return rv;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipcalc.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipcalc.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipcalc.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipcalc.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,98 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2007, Bernd Petrovitsch <berndÃ¦firmix.at>
+ * 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 _IPCALC
+#define _IPCALC
+
+#include "olsr_types.h"
+#include "defs.h"
+
+#include <limits.h>
+#include <arpa/inet.h>
+
+struct ipaddr_str {
+    char buf[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
+} __attribute__((unused));
+
+/*
+ * Macros for comparing and copying IP addresses
+ */
+static INLINE int ip4cmp(const struct in_addr *a, const struct in_addr *b) { return a->s_addr > b->s_addr ? +1 : a->s_addr < b->s_addr ? -1 : 0; }
+static INLINE int ip4equal(const struct in_addr *a, const struct in_addr *b) { return a->s_addr == b->s_addr; }
+
+static INLINE int ip6cmp(const struct in6_addr *a, const struct in6_addr *b) { return memcmp(a, b, sizeof(*a)); }
+static INLINE int ip6equal(const struct in6_addr *a, const struct in6_addr *b) { return ip6cmp(a, b) == 0; }
+
+#if 0
+static INLINE int ipcmp(const union olsr_ip_addr *a, const union olsr_ip_addr *b) { return olsr_cnf->ip_version == AF_INET ? ip4cmp(&a->v4, &b->v4) : ip6cmp(&a->v6, &b->v6); }
+#endif
+static INLINE int ipequal(const union olsr_ip_addr *a, const union olsr_ip_addr *b) { return olsr_cnf->ip_version == AF_INET ? ip4equal(&a->v4, &b->v4) : ip6equal(&a->v6, &b->v6); }
+
+/* Do not use this - this is as evil as the COPY_IP() macro was and only used in
+ * source which also needs cleanups.
+ */
+static INLINE void genipcopy(void *dst, const void *src) { memcpy(dst, src, olsr_cnf->ipsize); }
+
+int ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net);
+
+
+int prefix_to_netmask(olsr_u8_t *, int, olsr_u8_t);
+
+static INLINE int olsr_prefix_to_netmask(union olsr_ip_addr *adr, olsr_u8_t prefixlen) { return prefix_to_netmask(adr->v6.s6_addr, olsr_cnf->ipsize, prefixlen); }
+
+olsr_u8_t netmask_to_prefix(const olsr_u8_t *, int);
+
+static INLINE olsr_u8_t olsr_netmask_to_prefix(const union olsr_ip_addr *adr) { return netmask_to_prefix(adr->v6.s6_addr, olsr_cnf->ipsize); }
+
+static INLINE olsr_u8_t olsr_netmask4_to_prefix(const olsr_u32_t *a) { return netmask_to_prefix((const olsr_u8_t *)a, sizeof(*a)); }
+static INLINE olsr_u8_t olsr_netmask6_to_prefix(const struct in6_addr *a) { return netmask_to_prefix((const olsr_u8_t *)a, sizeof(*a)); }
+
+static INLINE const char *ip4_to_string(struct ipaddr_str * const buf, const struct in_addr addr4) { return inet_ntop(AF_INET, &addr4, buf->buf, sizeof(buf->buf)); }
+
+static INLINE const char *ip6_to_string(struct ipaddr_str * const buf, const struct in6_addr * const addr6) {  return inet_ntop(AF_INET6, addr6, buf->buf, sizeof(buf->buf)); }
+
+static INLINE const char *olsr_ip_to_string(struct ipaddr_str * const buf, const union olsr_ip_addr *addr) { return inet_ntop(olsr_cnf->ip_version, addr, buf->buf, sizeof(buf->buf)); }
+
+const char *olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix);
+
+static INLINE const char *sockaddr4_to_string(struct ipaddr_str * const buf, const struct sockaddr * const addr) { const struct sockaddr_in * const addr4 = (const struct sockaddr_in *)addr; return ip4_to_string(buf, addr4->sin_addr); }
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipc_frontend.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipc_frontend.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipc_frontend.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipc_frontend.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ *IPC - interprocess communication
+ *for the OLSRD - GUI front-end
+ *
+ */
+
+#include "ipc_frontend.h"
+#include "link_set.h"
+#include "olsr.h"
+#include "log.h"
+#include "parser.h"
+#include "socket_parser.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+#define perror(x) WinSockPError(x)
+void 
+WinSockPError(const char *);
+#endif
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+static int ipc_sock = -1;
+static int ipc_conn = -1;
+static int ipc_active = OLSR_FALSE;
+
+static int
+ipc_send_all_routes(int fd);
+
+static int
+ipc_send_net_info(int fd);
+
+
+/**
+ *Create the socket to use for IPC to the
+ *GUI front-end
+ *
+ *@return the socket FD
+ */
+int
+ipc_init(void)
+{
+  //int flags;
+  struct   sockaddr_in sin;
+  int yes = 1;
+
+  /* Add parser function */
+  olsr_parser_add_function(&frontend_msgparser, PROMISCUOUS, 0);
+
+  /* get an internet domain socket */
+  if ((ipc_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
+    {
+      perror("IPC socket");
+      olsr_exit("IPC socket", EXIT_FAILURE);
+    }
+
+  if(setsockopt(ipc_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
+    {
+      perror("SO_REUSEADDR failed");
+      return 0;
+    }
+
+  /* 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_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
+    {
+      perror("IPC bind");
+      OLSR_PRINTF(1, "Will retry in 10 seconds...\n");
+      sleep(10);
+      if(bind(ipc_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
+	{
+	  perror("IPC bind");
+	  olsr_exit("IPC bind", EXIT_FAILURE);
+	}
+      OLSR_PRINTF(1, "OK\n");
+    }
+
+  /* show that we are willing to listen */
+  if(listen(ipc_sock, olsr_cnf->ipc_connections) == -1) 
+    {
+      perror("IPC listen");
+      olsr_exit("IPC listen", EXIT_FAILURE);
+    }
+
+  /* Register the socket with the socket parser */
+  add_olsr_socket(ipc_sock, &ipc_accept);
+
+  return ipc_sock;
+}
+
+
+void
+ipc_accept(int fd)
+{
+  socklen_t addrlen;
+  struct sockaddr_in pin;
+  char *addr;  
+
+
+  addrlen = sizeof (struct sockaddr_in);
+  
+  if ((ipc_conn = accept(fd, (struct sockaddr *)  &pin, &addrlen)) == -1)
+    {
+      perror("IPC accept");
+      olsr_exit("IPC accept", EXIT_FAILURE);
+    }
+  else
+    {
+      OLSR_PRINTF(1, "Front end connected\n");
+      addr = inet_ntoa(pin.sin_addr);
+      if(ipc_check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr))
+	{
+	  ipc_active = OLSR_TRUE;
+	  ipc_send_net_info(ipc_conn);
+	  ipc_send_all_routes(ipc_conn);
+	  OLSR_PRINTF(1, "Connection from %s\n",addr);
+	}
+      else
+	{
+	  OLSR_PRINTF(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
+	  olsr_syslog(OLSR_LOG_ERR, "OLSR: Front end-connection from foregin host(%s) not allowed!\n", addr);
+	  CLOSE(ipc_conn);
+	}
+    }
+
+}
+
+olsr_bool
+ipc_check_allowed_ip(const union olsr_ip_addr *addr)
+{
+  struct ip_prefix_list *ipcn;
+
+  if(addr->v4.s_addr == ntohl(INADDR_LOOPBACK)) {
+    return OLSR_TRUE;
+  }
+
+  /* check nets */
+  for (ipcn = olsr_cnf->ipc_nets; ipcn != NULL; ipcn = ipcn->next) {
+    if (ip_in_net(addr, &ipcn->net)) { 
+      return OLSR_TRUE;
+    }
+  }
+
+  return OLSR_FALSE;
+}
+
+#if 0
+/**
+ *Read input from the IPC socket. Not in use.
+ *
+ *@todo for future use
+ *@param sock the IPC socket
+ *@return 1
+ */
+int
+ipc_input(int sock __attribute__((unused)))
+{
+  union 
+  {
+    char	buf[MAXPACKETSIZE+1];
+    struct olsr	olsr;
+  } inbuf;
+
+
+  if (recv(sock, dir, sizeof(dir), 0) == -1) 
+    {
+      perror("recv");
+      exit(1);
+    }
+  return 1;
+}
+#endif
+
+/**
+ *Sends a olsr packet on the IPC socket.
+ *
+ *@param olsr the olsr struct representing the packet
+ *
+ *@return negative on error
+ */
+void
+frontend_msgparser(union olsr_message *msg, struct interface *in_if __attribute__((unused)), union olsr_ip_addr *from_addr __attribute__((unused)))
+{
+  int size;
+
+  if(!ipc_active)
+    return;
+  
+  if(olsr_cnf->ip_version == AF_INET)
+    size = ntohs(msg->v4.olsr_msgsize);
+  else
+    size = ntohs(msg->v6.olsr_msgsize);
+  
+  if (send(ipc_conn, (void *)msg, size, MSG_NOSIGNAL) < 0) 
+    {
+      OLSR_PRINTF(1, "(OUTPUT)IPC connection lost!\n");
+      CLOSE(ipc_conn);
+      ipc_active = OLSR_FALSE;
+    }
+}
+
+
+/**
+ *Send a route table update to the front-end.
+ *
+ *@param kernel_route a rtentry describing the route update
+ *@param add 1 if the route is to be added 0 if it is to be deleted
+ *@param int_name the name of the interface the route is set to go by
+ *
+ *@return negative on error
+ */
+int
+ipc_route_send_rtentry(const union olsr_ip_addr *dst,
+                       const union olsr_ip_addr *gw,
+                       int met,
+                       int add,
+                       const char *int_name)
+{
+  struct ipcmsg packet;
+  char *tmp;
+
+  if (olsr_cnf->ipc_connections <= 0) {
+    return -1;
+  }
+
+  if (!ipc_active) {
+    return 0;
+  }
+  memset(&packet, 0, sizeof(struct ipcmsg));
+  packet.size = htons(IPC_PACK_SIZE);
+  packet.msgtype = ROUTE_IPC;
+
+  packet.target_addr = *dst;
+
+  packet.add = add;
+  if(add && gw)
+    {
+      packet.metric = met;
+      packet.gateway_addr = *gw;
+    }
+
+  if(int_name != NULL)
+    memcpy(&packet.device[0], int_name, 4);
+  else
+    memset(&packet.device[0], 0, 4);
+
+
+  tmp = (char *) &packet;
+  /*
+  x = 0;
+  for(i = 0; i < IPC_PACK_SIZE;i++)
+    {
+      if(x == 4)
+	{
+	  x = 0;
+	  printf("\n\t");
+	}
+      x++;
+      printf(" %03i", (u_char) tmp[i]);
+    }
+  
+  printf("\n");
+  */
+  
+  if (send(ipc_conn, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
+    {
+      OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n");
+      CLOSE(ipc_conn);
+
+      ipc_active = OLSR_FALSE;
+      return -1;
+    }
+
+  return 1;
+}
+
+
+
+static int
+ipc_send_all_routes(int fd)
+{
+  struct rt_entry  *rt;
+  struct ipcmsg packet;
+  char *tmp;
+  
+
+  if(!ipc_active)
+    return 0;
+  
+  OLSR_FOR_ALL_RT_ENTRIES(rt) {
+
+    memset(&packet, 0, sizeof(struct ipcmsg));
+    packet.size = htons(IPC_PACK_SIZE);
+    packet.msgtype = ROUTE_IPC;
+	  
+    packet.target_addr = rt->rt_dst.prefix;
+
+    packet.add = 1;
+    packet.metric = (olsr_u8_t)(rt->rt_best->rtp_metric.hops);
+
+    packet.gateway_addr = rt->rt_nexthop.gateway;
+
+    memcpy(&packet.device[0], if_ifwithindex_name(rt->rt_nexthop.iif_index), 4);
+
+    tmp = (char *) &packet;
+  
+    /* MSG_NOSIGNAL to avoid sigpipe */
+    if (send(fd, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) {
+      OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n");
+      CLOSE(ipc_conn);
+      ipc_active = OLSR_FALSE;
+      return -1;
+    }
+  } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
+  return 1;
+}
+
+
+
+/**
+ *Sends OLSR info to the front-end. This info consists of
+ *the different time intervals and holding times, number
+ *of interfaces, HNA routes and main address.
+ *
+ *@return negative on error
+ */
+static int
+ipc_send_net_info(int fd)
+{
+  struct ipc_net_msg *net_msg;
+  //int x, i;
+  char *msg;
+  
+
+  net_msg = olsr_malloc(sizeof(struct ipc_net_msg), "send net info");
+
+  msg = (char *)net_msg;
+
+  OLSR_PRINTF(1, "Sending net-info to front end...\n");
+  
+  memset(net_msg, 0, sizeof(struct ipc_net_msg));
+  
+  /* Message size */
+  net_msg->size = htons(sizeof(struct ipc_net_msg));
+  /* Message type */
+  net_msg->msgtype = NET_IPC;
+  
+  /* MIDs */
+  /* XXX fix IPC MIDcnt */
+  net_msg->mids = (ifnet != NULL && ifnet->int_next != NULL) ? 1 : 0;
+  
+  /* HNAs */
+  net_msg->hnas = olsr_cnf->hna_entries == NULL ? 0 : 1;
+
+  /* Different values */
+  /* Temporary fixes */
+  /* XXX fix IPC intervals */
+  net_msg->hello_int = 0;//htons((olsr_u16_t)hello_int);
+  net_msg->hello_lan_int = 0;//htons((olsr_u16_t)hello_int_nw);
+  net_msg->tc_int = 0;//htons((olsr_u16_t)tc_int);
+  net_msg->neigh_hold = 0;//htons((olsr_u16_t)neighbor_hold_time);
+  net_msg->topology_hold = 0;//htons((olsr_u16_t)topology_hold_time);
+
+  net_msg->ipv6 = olsr_cnf->ip_version == AF_INET ? 0 : 1;
+ 
+  /* Main addr */
+  net_msg->main_addr = olsr_cnf->main_addr;
+
+  /*
+  printf("\t");
+  x = 0;
+  for(i = 0; i < sizeof(struct ipc_net_msg);i++)
+    {
+      if(x == 4)
+	{
+	  x = 0;
+	  printf("\n\t");
+	}
+      x++;
+      printf(" %03i", (u_char) msg[i]);
+    }
+  
+  printf("\n");
+  */
+
+
+  if (send(fd, (char *)net_msg, sizeof(struct ipc_net_msg), MSG_NOSIGNAL) < 0) 
+    {
+      OLSR_PRINTF(1, "(NETINFO)IPC connection lost!\n");
+      CLOSE(ipc_conn);
+      return -1;
+    }
+
+  free(net_msg);
+  return 0;
+}
+
+
+
+int
+shutdown_ipc(void)
+{
+  OLSR_PRINTF(1, "Shutting down IPC...\n");
+  CLOSE(ipc_sock);
+  CLOSE(ipc_conn);
+  
+  return 1;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipc_frontend.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipc_frontend.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/ipc_frontend.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/ipc_frontend.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ *IPC - interprocess communication
+ *for the OLSRD - GUI front-end
+ *
+ */
+
+#ifndef _OLSR_IPC
+#define _OLSR_IPC
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <signal.h>
+
+#include "defs.h"
+
+#define IPC_PORT 1212
+#define IPC_PACK_SIZE 44 /* Size of the IPC_ROUTE packet */
+#define	ROUTE_IPC 11    /* IPC to front-end telling of route changes */
+#define NET_IPC 12      /* IPC to front end net-info */
+
+/*
+ *IPC message sent to the front-end
+ *at every route update. Both delete
+ *and add
+ */
+
+struct ipcmsg 
+{
+  olsr_u8_t          msgtype;
+  olsr_u16_t         size;
+  olsr_u8_t          metric;
+  olsr_u8_t          add;
+  union olsr_ip_addr target_addr;
+  union olsr_ip_addr gateway_addr;
+  char               device[4];
+};
+
+
+struct ipc_net_msg
+{
+  olsr_u8_t            msgtype;
+  olsr_u16_t           size;
+  olsr_u8_t            mids; /* No. of extra interfaces */
+  olsr_u8_t            hnas; /* No. of HNA nets */
+  olsr_u8_t            unused1;
+  olsr_u16_t           hello_int;
+  olsr_u16_t           hello_lan_int;
+  olsr_u16_t           tc_int;
+  olsr_u16_t           neigh_hold;
+  olsr_u16_t           topology_hold;
+  olsr_u8_t            ipv6;
+  union olsr_ip_addr   main_addr;
+};
+
+
+olsr_bool
+ipc_check_allowed_ip(const union olsr_ip_addr *);
+
+void
+ipc_accept(int);
+
+void
+frontend_msgparser(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+int
+ipc_route_send_rtentry(const union olsr_ip_addr *, const union olsr_ip_addr *, int, int, const char *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/kernel_routes.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/kernel_routes.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/kernel_routes.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/kernel_routes.h	2008-10-03 14:45:07.000000000 +0200
@@ -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 _OLSR_KERNEL_RT
+#define _OLSR_KERNEL_RT
+
+#include "defs.h"
+#include "routing_table.h"
+
+int
+olsr_ioctl_add_route(const struct rt_entry *);
+
+int
+olsr_ioctl_add_route6(const struct rt_entry *);
+
+int
+olsr_ioctl_del_route(const struct rt_entry *);
+
+int
+olsr_ioctl_del_route6(const struct rt_entry *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/link_set.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/link_set.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/link_set.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/link_set.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,841 @@
+
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Link sensing database for the OLSR routing daemon
+ */
+
+#include "defs.h"
+#include "link_set.h"
+#include "hysteresis.h"
+#include "mid_set.h"
+#include "mpr.h"
+#include "neighbor_table.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "olsr_spf.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+#include "lq_plugin.h"
+
+/* head node for all link sets */
+struct list_node link_entry_head;
+
+olsr_bool link_changes;		       /* is set if changes occur in MPRS set */
+
+void
+signal_link_changes(olsr_bool val)
+{				/* XXX ugly */
+  link_changes = val;
+}
+
+/* Prototypes. */
+static int check_link_status(const struct hello_message *message,
+                             const struct interface *in_if);
+static struct link_entry *add_link_entry(const union olsr_ip_addr *,
+					 const union olsr_ip_addr *,
+					 const union olsr_ip_addr *, olsr_reltime,
+					 olsr_reltime, const struct interface *);
+static int get_neighbor_status(const union olsr_ip_addr *);
+
+void
+olsr_init_link_set(void)
+{
+
+  /* Init list head */
+  list_head_init(&link_entry_head);
+}
+
+
+/**
+ * Get the status of a link. The status is based upon different
+ * timeouts in the link entry.
+ *
+ * @param remote address of the remote interface
+ * @return the link status of the link
+ */
+int
+lookup_link_status(const struct link_entry *entry)
+{
+
+  if (entry == NULL || list_is_empty(&link_entry_head)) {
+    return UNSPEC_LINK;
+  }
+
+  /*
+   * Hysteresis
+   */
+  if (olsr_cnf->use_hysteresis) {
+
+    /*
+     * if L_LOST_LINK_time is not expired, the link is advertised
+     * with a link type of LOST_LINK.
+     */
+
+    if (!TIMED_OUT(entry->L_LOST_LINK_time)) {
+      return LOST_LINK;
+    }
+
+    /*
+     * otherwise, if L_LOST_LINK_time is expired and L_link_pending
+     * is set to "true", the link SHOULD NOT be advertised at all;
+     */
+    if (entry->L_link_pending == 1) {
+#ifndef NODEBUG
+      struct ipaddr_str buf;
+      OLSR_PRINTF(3, "HYST[%s]: Setting to HIDE\n",
+		  olsr_ip_to_string(&buf, &entry->neighbor_iface_addr));
+#endif
+      return HIDE_LINK;
+    }
+
+    /*
+     * otherwise, if L_LOST_LINK_time is expired and L_link_pending
+     * is set to "false", the link is advertised as described
+     * previously in section 6.
+     */
+  }
+
+  if (entry->link_sym_timer) {
+    return SYM_LINK;
+  }
+
+  if (!TIMED_OUT(entry->ASYM_time)) {
+    return ASYM_LINK;
+  }
+
+  return LOST_LINK;
+}
+
+
+/**
+ * Find the "best" link status to a neighbor
+ *
+ * @param address the address to check for
+ * @return SYM_LINK if a symmetric link exists 0 if not
+ */
+static int
+get_neighbor_status(const union olsr_ip_addr *address)
+{
+  const union olsr_ip_addr *main_addr;
+  struct interface *ifs;
+
+  /* Find main address */
+  if (!(main_addr = mid_lookup_main_addr(address)))
+    main_addr = address;
+
+  /* Loop trough local interfaces to check all possebilities */
+  for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
+    struct mid_address *aliases;
+    struct link_entry *lnk = lookup_link_entry(main_addr, NULL, ifs);
+
+    if (lnk != NULL) {
+      if (lookup_link_status(lnk) == SYM_LINK)
+	return SYM_LINK;
+    }
+
+    /* Get aliases */
+    for (aliases = mid_lookup_aliases(main_addr);
+	 aliases != NULL; aliases = aliases->next_alias) {
+
+      lnk = lookup_link_entry(&aliases->alias, NULL, ifs);
+      if (lnk && (lookup_link_status(lnk) == SYM_LINK)) {
+	  return SYM_LINK;
+      }
+    }
+  }
+
+  return 0;
+}
+
+/**
+ * Find best link to a neighbor
+ */
+struct link_entry *
+get_best_link_to_neighbor(const union olsr_ip_addr *remote)
+{
+  const union olsr_ip_addr *main_addr;
+  struct link_entry *walker, *good_link, *backup_link;
+  struct interface *tmp_if;
+  int curr_metric = MAX_IF_METRIC;
+  olsr_linkcost curr_lcost = LINK_COST_BROKEN;
+  olsr_linkcost tmp_lc;
+
+  /* main address lookup */
+  main_addr = mid_lookup_main_addr(remote);
+
+  /* "remote" *already is* the main address */
+  if (!main_addr) {
+    main_addr = remote;
+  }
+
+  /* we haven't selected any links, yet */
+  good_link = NULL;
+  backup_link = NULL;
+
+  /* loop through all links that we have */
+  OLSR_FOR_ALL_LINK_ENTRIES(walker) {
+
+    /* if this is not a link to the neighour in question, skip */
+    if (!ipequal(&walker->neighbor->neighbor_main_addr, main_addr))
+      continue;
+
+    if (olsr_cnf->lq_level == 0) {
+
+      /*
+       * handle the non-LQ, RFC-compliant case
+       */
+
+      /*
+       * find the interface for the link.
+       * we select the link with the best local interface metric.
+       */
+      tmp_if = walker->if_name ? if_ifwithname(walker->if_name) :
+	if_ifwithaddr(&walker->local_iface_addr);
+
+      if (!tmp_if) {
+	continue;
+      }
+
+      /*
+       * is this interface better than anything we had before ?
+       * use the requested remote interface address as a tie-breaker
+       */
+      if ((tmp_if->int_metric < curr_metric) ||
+	  ((tmp_if->int_metric == curr_metric) &&
+	   ipequal(&walker->local_iface_addr, remote))) {
+
+	/* memorize the interface's metric */
+	curr_metric = tmp_if->int_metric;
+
+	/* prefer symmetric links over asymmetric links */
+	if (lookup_link_status(walker) == SYM_LINK) {
+	  good_link = walker;
+        } else {
+	  backup_link = walker;
+        }
+      }
+    } else {
+
+      /*
+       * handle the LQ, non-RFC compliant case.
+       */
+
+      /* get the link cost */
+      tmp_lc = walker->linkcost;
+
+      /*
+       * is this link better than anything we had before ?
+       * use the requested remote interface address as a tie-breaker.
+       */
+      if ((tmp_lc < curr_lcost) ||
+          ((tmp_lc == curr_lcost) &&
+           ipequal(&walker->local_iface_addr, remote))) {
+
+	/* memorize the link quality */
+	curr_lcost = tmp_lc;
+
+	/* prefer symmetric links over asymmetric links */
+	if (lookup_link_status(walker) == SYM_LINK) {
+	  good_link = walker;
+        } else {
+	  backup_link = walker;
+        }
+      }
+    }
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
+
+  /*
+   * if we haven't found any symmetric links, try to return an asymmetric link.
+   */
+  return good_link ? good_link : backup_link;
+}
+
+static void
+set_loss_link_multiplier(struct link_entry *entry)
+{
+  struct interface *inter;
+  struct olsr_if *cfg_inter;
+  struct olsr_lq_mult *mult;
+  olsr_u32_t val = 0;
+  union olsr_ip_addr null_addr;
+
+  /* find the interface for the link */
+  inter = if_ifwithaddr(&entry->local_iface_addr);
+
+  /* find the interface configuration for the interface */
+  for (cfg_inter = olsr_cnf->interfaces; cfg_inter;
+       cfg_inter = cfg_inter->next) {
+    if (cfg_inter->interf == inter) {
+      break;
+    }
+  }
+
+  /* create a null address for comparison */
+  memset(&null_addr, 0, sizeof(union olsr_ip_addr));
+
+  /* loop through the multiplier entries */
+  for (mult = cfg_inter->cnf->lq_mult; mult != NULL; mult = mult->next) {
+
+    /*
+     * use the default multiplier only if there isn't any entry that
+     * has a matching IP address.
+     */
+    if ((ipequal(&mult->addr, &null_addr) && val < 0.0) ||
+	ipequal(&mult->addr, &entry->neighbor_iface_addr)) {
+      val = mult->value;
+    }
+  }
+
+  /* if we have not found an entry, then use the default multiplier */
+  if (val == 0) {
+    val = LINK_LOSS_MULTIPLIER;
+  }
+
+  /* store the multiplier */
+  entry->loss_link_multiplier = val;
+}
+
+/*
+ * Delete, unlink and free a link entry.
+ */
+static void
+olsr_delete_link_entry(struct link_entry *link)
+{
+
+  /* Delete neighbor entry */
+  if (link->neighbor->linkcount == 1) {
+    olsr_delete_neighbor_table(&link->neighbor->neighbor_main_addr);
+  } else {
+    link->neighbor->linkcount--;
+  }
+
+  /* Kill running timers */
+  olsr_stop_timer(link->link_timer);
+  link->link_timer = NULL;
+  olsr_stop_timer(link->link_sym_timer);
+  link->link_sym_timer = NULL;
+  olsr_stop_timer(link->link_hello_timer);
+  link->link_hello_timer = NULL;
+  olsr_stop_timer(link->link_loss_timer);
+  link->link_loss_timer = NULL;
+
+  list_remove(&link->link_list);
+
+  free(link->if_name);
+  free(link);
+
+  changes_neighborhood = OLSR_TRUE;
+}
+
+void
+olsr_delete_link_entry_by_ip(const union olsr_ip_addr *int_addr)
+{
+  struct link_entry *link;
+
+  if (list_is_empty(&link_entry_head)) {
+    return;
+  }
+
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    if (ipequal(int_addr, &link->local_iface_addr)) {
+      olsr_delete_link_entry(link);
+      break;
+    }
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+}
+
+/**
+ * Callback for the link loss timer.
+ */
+static void
+olsr_expire_link_loss_timer(void *context)
+{
+  struct link_entry *link;
+
+  link = (struct link_entry *)context;
+
+  /* count the lost packet */
+  olsr_update_packet_loss_worker(link, OLSR_TRUE);
+
+  /* next timeout in 1.0 x htime */
+  olsr_change_timer(link->link_loss_timer, link->loss_helloint,
+		    OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC);
+}
+
+/**
+ * Callback for the link SYM timer.
+ */
+static void
+olsr_expire_link_sym_timer(void *context)
+{
+  struct link_entry *link;
+
+  link = (struct link_entry *)context;
+  link->link_sym_timer = NULL;	/* be pedandic */
+
+  if (link->prev_status != SYM_LINK) {
+    return;
+  }
+
+  link->prev_status = lookup_link_status(link);
+  update_neighbor_status(link->neighbor,
+			 get_neighbor_status(&link->neighbor_iface_addr));
+  changes_neighborhood = OLSR_TRUE;
+}
+
+/**
+ * Callback for the link_hello timer.
+ */
+void
+olsr_expire_link_hello_timer(void *context)
+{
+  struct ipaddr_str buf;
+  struct link_entry *link;
+
+  link = (struct link_entry *)context;
+
+  link->L_link_quality = olsr_hyst_calc_instability(link->L_link_quality);
+
+  OLSR_PRINTF(1, "HYST[%s] HELLO timeout %f\n",
+	      olsr_ip_to_string(&buf, &link->neighbor_iface_addr),
+	      link->L_link_quality);
+
+  /* Update hello_timeout - NO SLACK THIS TIME */
+  olsr_change_timer(link->link_hello_timer, link->last_htime,
+		    OLSR_LINK_JITTER, OLSR_TIMER_PERIODIC);
+
+  /* Update hysteresis values */
+  olsr_process_hysteresis(link);
+
+  /* update neighbor status */
+  update_neighbor_status(link->neighbor,
+			 get_neighbor_status(&link->neighbor_iface_addr));
+
+  /* Update seqno - not mentioned in the RFC... kind of a hack.. */
+  link->olsr_seqno++;
+}
+
+/**
+ * Callback for the link timer.
+ */
+static void
+olsr_expire_link_entry(void *context)
+{
+  struct link_entry *link;
+
+  link = (struct link_entry *)context;
+  link->link_timer = NULL;	/* be pedandic */
+
+  olsr_delete_link_entry(link);
+}
+
+/**
+ * Set the link expiration timer.
+ */
+void
+olsr_set_link_timer(struct link_entry *link, unsigned int rel_timer)
+{
+  olsr_set_timer(&link->link_timer, rel_timer, OLSR_LINK_JITTER,
+		 OLSR_TIMER_ONESHOT, &olsr_expire_link_entry, link, 0);
+}
+
+/**
+ * Nothing mysterious here.
+ * Adding a new link entry to the link set.
+ *
+ * @param local the local IP address
+ * @param remote the remote IP address
+ * @param remote_main the remote nodes main address
+ * @param vtime the validity time of the entry
+ * @param htime the HELLO interval of the remote node
+ * @param local_if the local interface
+ * @return the new link_entry
+ */
+static struct link_entry *
+add_link_entry(const union olsr_ip_addr *local,
+	       const union olsr_ip_addr *remote,
+	       const union olsr_ip_addr *remote_main,
+	       olsr_reltime vtime, olsr_reltime htime, const struct interface *local_if)
+{
+  struct link_entry *new_link;
+  struct neighbor_entry *neighbor;
+  struct link_entry *tmp_link_set;
+
+  tmp_link_set = lookup_link_entry(remote, remote_main, local_if);
+  if (tmp_link_set) {
+    return tmp_link_set;
+  }
+
+  /*
+   * if there exists no link tuple with
+   * L_neighbor_iface_addr == Source Address
+   */
+
+#ifdef DEBUG
+  {
+    struct ipaddr_str localbuf, rembuf;
+    OLSR_PRINTF(1, "Adding %s=>%s to link set\n",
+		olsr_ip_to_string(&localbuf, local), olsr_ip_to_string(&rembuf,
+								       remote));
+  }
+#endif
+
+  /* a new tuple is created with... */
+  new_link = olsr_malloc_link_entry("new link entry");
+
+  /* copy if_name, if it is defined */
+  if (local_if->int_name) {
+    size_t name_size = strlen(local_if->int_name) + 1;
+    new_link->if_name =
+      olsr_malloc(name_size, "target of if_name in new link entry");
+    strscpy(new_link->if_name, local_if->int_name, name_size);
+  } else
+    new_link->if_name = NULL;
+
+  /* shortcut to interface. XXX refcount */
+  new_link->inter = local_if;
+
+  /*
+   * L_local_iface_addr = Address of the interface
+   * which received the HELLO message
+   */
+  new_link->local_iface_addr = *local;
+
+  /* L_neighbor_iface_addr = Source Address */
+  new_link->neighbor_iface_addr = *remote;
+
+  /* L_time = current time + validity time */
+  olsr_set_link_timer(new_link, vtime);
+
+  new_link->prev_status = ASYM_LINK;
+
+  /* HYSTERESIS */
+  if (olsr_cnf->use_hysteresis) {
+    new_link->L_link_pending = 1;
+    new_link->L_LOST_LINK_time = GET_TIMESTAMP(vtime);
+    olsr_update_hysteresis_hello(new_link, htime);
+    new_link->last_htime = htime;
+    new_link->olsr_seqno = 0;
+    new_link->olsr_seqno_valid = OLSR_FALSE;
+  }
+
+  new_link->L_link_quality = 0.0;
+
+  if (olsr_cnf->lq_level > 0) {
+    new_link->loss_helloint = htime;
+
+    olsr_set_timer(&new_link->link_loss_timer, htime + htime/2,
+		   OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
+		   &olsr_expire_link_loss_timer, new_link, 0);
+
+    set_loss_link_multiplier(new_link);
+  }
+
+  new_link->linkcost = LINK_COST_BROKEN;
+
+  /* Add to queue */
+  list_add_before(&link_entry_head, &new_link->link_list);
+
+  /*
+   * Create the neighbor entry
+   */
+
+  /* Neighbor MUST exist! */
+  neighbor = olsr_lookup_neighbor_table(remote_main);
+  if (!neighbor) {
+#ifdef DEBUG
+    struct ipaddr_str buf;
+    OLSR_PRINTF(3, "ADDING NEW NEIGHBOR ENTRY %s FROM LINK SET\n",
+		olsr_ip_to_string(&buf, remote_main));
+#endif
+    neighbor = olsr_insert_neighbor_table(remote_main);
+  }
+
+  neighbor->linkcount++;
+  new_link->neighbor = neighbor;
+
+  return new_link;
+}
+
+
+/**
+ * Lookup the status of a link.
+ *
+ * @param int_addr address of the remote interface
+ * @return 1 of the link is symmertic 0 if not
+ */
+int
+check_neighbor_link(const union olsr_ip_addr *int_addr)
+{
+  struct link_entry *link;
+
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    if (ipequal(int_addr, &link->neighbor_iface_addr)) {
+      return lookup_link_status(link);
+    }
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+
+  return UNSPEC_LINK;
+}
+
+/**
+ * Lookup a link entry
+ *
+ * @param remote the remote interface address
+ * @param remote_main the remote nodes main address
+ * @param local the local interface address
+ * @return the link entry if found, NULL if not
+ */
+struct link_entry *
+lookup_link_entry(const union olsr_ip_addr *remote,
+		  const union olsr_ip_addr *remote_main,
+		  const struct interface *local)
+{
+  struct link_entry *link;
+
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    if (ipequal(remote, &link->neighbor_iface_addr) &&
+	(link->if_name ? !strcmp(link->if_name, local->int_name)
+	 : ipequal(&local->ip_addr, &link->local_iface_addr)))
+    {
+      /* check the remote-main address only if there is one given */
+      if (NULL != remote_main && !ipequal(remote_main, &link->neighbor->neighbor_main_addr))
+      {
+        /* Neighbor has changed it's main_addr, update */
+        struct ipaddr_str oldbuf, newbuf;
+        OLSR_PRINTF(1, "Neighbor changed main_ip, updating %s -> %s\n",
+          olsr_ip_to_string(&oldbuf, &link->neighbor->neighbor_main_addr), olsr_ip_to_string(&newbuf, remote_main));
+        link->neighbor->neighbor_main_addr = *remote_main;
+      }
+      return link;
+    }
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+
+  return NULL;
+}
+
+/**
+ * Update a link entry. This is the "main entrypoint" in
+ * the link-sensing. This function is called from the HELLO
+ * parser function. It makes sure a entry is updated or created.
+ *
+ * @param local the local IP address
+ * @param remote the remote IP address
+ * @param message the HELLO message
+ * @param in_if the interface on which this HELLO was received
+ * @return the link_entry struct describing this link entry
+ */
+struct link_entry *
+update_link_entry(const union olsr_ip_addr *local,
+		  const union olsr_ip_addr *remote,
+		  const struct hello_message *message,
+		  const struct interface *in_if)
+{
+  struct link_entry *entry;
+
+  /* Add if not registered */
+  entry =
+    add_link_entry(local, remote, &message->source_addr, message->vtime,
+		   message->htime, in_if);
+
+  /* Update ASYM_time */
+  entry->vtime = message->vtime;
+  entry->ASYM_time = GET_TIMESTAMP(message->vtime);
+
+  entry->prev_status = check_link_status(message, in_if);
+
+  switch (entry->prev_status) {
+  case (LOST_LINK):
+    olsr_stop_timer(entry->link_sym_timer);
+    entry->link_sym_timer = NULL;
+    break;
+  case (SYM_LINK):
+  case (ASYM_LINK):
+
+    /* L_SYM_time = current time + validity time */
+    olsr_set_timer(&entry->link_sym_timer, message->vtime,
+		   OLSR_LINK_SYM_JITTER, OLSR_TIMER_ONESHOT,
+		   &olsr_expire_link_sym_timer, entry, 0);
+
+    /* L_time = L_SYM_time + NEIGHB_HOLD_TIME */
+    olsr_set_link_timer(entry, message->vtime + NEIGHB_HOLD_TIME *
+			MSEC_PER_SEC);
+    break;
+  default:;
+  }
+
+  /* L_time = max(L_time, L_ASYM_time) */
+  if (entry->link_timer && (entry->link_timer->timer_clock < entry->ASYM_time)) {
+    olsr_set_link_timer(entry, TIME_DUE(entry->ASYM_time));
+  }
+
+  /* Update hysteresis values */
+  if (olsr_cnf->use_hysteresis)
+    olsr_process_hysteresis(entry);
+
+  /* Update neighbor */
+  update_neighbor_status(entry->neighbor, get_neighbor_status(remote));
+
+  return entry;
+}
+
+
+/**
+ * Function that updates all registered pointers to
+ * one neighbor entry with another pointer
+ * Used by MID updates.
+ *
+ * @old the pointer to replace
+ * @new the pointer to use instead of "old"
+ * @return the number of entries updated
+ */
+int
+replace_neighbor_link_set(const struct neighbor_entry *old,
+			  struct neighbor_entry *new)
+{
+  struct link_entry *link;
+  int retval = 0;
+
+  if (list_is_empty(&link_entry_head)) {
+    return retval;
+  }
+
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+
+    if (link->neighbor == old) {
+      link->neighbor = new;
+      retval++;
+    }
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+
+  return retval;
+}
+
+
+/**
+ *Checks the link status to a neighbor by
+ *looking in a received HELLO message.
+ *
+ *@param message the HELLO message to check
+ *
+ *@return the link status
+ */
+static int
+check_link_status(const struct hello_message *message,
+		  const struct interface *in_if)
+{
+  int ret = UNSPEC_LINK;
+  struct hello_neighbor *neighbors;
+
+  neighbors = message->neighbors;
+  while (neighbors) {
+
+    /*
+     * Note: If a neigh has 2 cards we can reach, the neigh
+     * will send a Hello with the same IP mentined twice
+     */
+    if (ipequal(&neighbors->address, &in_if->ip_addr)) {
+      ret = neighbors->link;
+      if (SYM_LINK == ret) {
+	break;
+      }
+    }
+    neighbors = neighbors->next;
+  }
+
+  return ret;
+}
+
+void
+olsr_print_link_set(void)
+{
+#ifndef NODEBUG
+  /* The whole function makes no sense without it. */
+  struct link_entry *walker;
+  const int addrsize = olsr_cnf->ip_version == AF_INET ? 15 : 39;
+
+  OLSR_PRINTF(0,
+	      "\n--- %s ---------------------------------------------------- LINKS\n\n",
+	      olsr_wallclock_string());
+  OLSR_PRINTF(1, "%-*s  %-6s %-14s %s\n", addrsize, "IP address", "hyst",
+	      "      LQ      ", "ETX");
+
+  OLSR_FOR_ALL_LINK_ENTRIES(walker) {
+
+    struct ipaddr_str buf;
+    struct lqtextbuffer lqbuffer1, lqbuffer2;
+    OLSR_PRINTF(1, "%-*s  %5.3f  %-14s %s\n",
+		addrsize, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
+		walker->L_link_quality,
+		get_link_entry_text(walker, '/', &lqbuffer1),
+		get_linkcost_text(walker->linkcost, OLSR_FALSE, &lqbuffer2));
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
+#endif
+}
+
+/*
+ * called for every LQ HELLO message.
+ * update the timeout with the htime value from the message
+ */
+void
+olsr_update_packet_loss_hello_int(struct link_entry *entry,
+				  olsr_reltime loss_hello_int)
+{
+  entry->loss_helloint = loss_hello_int;
+}
+
+void
+olsr_update_packet_loss(struct link_entry *entry)
+{
+  olsr_update_packet_loss_worker(entry, OLSR_FALSE);
+
+  /* timeout for the first lost packet is 1.5 x htime */
+  olsr_set_timer(&entry->link_loss_timer, entry->loss_helloint + entry->loss_helloint/2,
+		 OLSR_LINK_LOSS_JITTER, OLSR_TIMER_PERIODIC,
+		 &olsr_expire_link_loss_timer, entry, 0);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/link_set.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/link_set.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/link_set.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/link_set.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,155 @@
+
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Link sensing database for the OLSR routing daemon
+ */
+
+#ifndef _LINK_SET_H
+#define _LINK_SET_H
+
+#include "lq_plugin.h"
+#include "packet.h"
+#include "common/list.h"
+#include "mantissa.h"
+
+#define MID_ALIAS_HACK_VTIME  10.0
+
+#define LINK_LOSS_MULTIPLIER (1<<16)
+
+struct link_entry {
+  union olsr_ip_addr local_iface_addr;
+  union olsr_ip_addr neighbor_iface_addr;
+  const struct interface *inter;
+  char *if_name;
+  struct timer_entry *link_timer;
+  struct timer_entry *link_sym_timer;
+  clock_t ASYM_time;
+  olsr_reltime vtime;
+  struct neighbor_entry *neighbor;
+  olsr_u8_t prev_status;
+
+  /*
+   * Hysteresis
+   */
+  float L_link_quality;
+  int L_link_pending;
+  clock_t L_LOST_LINK_time;
+  struct timer_entry *link_hello_timer;	/* When we should receive a new HELLO */
+  olsr_reltime last_htime;
+  olsr_bool olsr_seqno_valid;
+  olsr_u16_t olsr_seqno;
+
+  /*
+   * packet loss
+   */
+  olsr_reltime loss_helloint;
+  struct timer_entry *link_loss_timer;
+
+  /* user defined multiplies for link quality, multiplied with 65536 */
+  olsr_u32_t loss_link_multiplier;
+
+  /* cost of this link */
+  olsr_linkcost linkcost;
+
+  struct list_node link_list;	       /* double linked list of all link entries */
+  olsr_u32_t linkquality[0];
+};
+
+/* inline to recast from link_list back to link_entry */
+LISTNODE2STRUCT(list2link, struct link_entry, link_list);
+
+#define OLSR_LINK_JITTER       5	/* percent */
+#define OLSR_LINK_HELLO_JITTER 0	/* percent jitter */
+#define OLSR_LINK_SYM_JITTER   0	/* percent jitter */
+#define OLSR_LINK_LOSS_JITTER  0	/* percent jitter */
+
+/* deletion safe macro for link entry traversal */
+#define OLSR_FOR_ALL_LINK_ENTRIES(link) \
+{ \
+  struct list_node *link_head_node, *link_node, *next_link_node; \
+  link_head_node = &link_entry_head; \
+  for (link_node = link_head_node->next; \
+    link_node != link_head_node; link_node = next_link_node) { \
+    next_link_node = link_node->next; \
+    link = list2link(link_node);
+#define OLSR_FOR_ALL_LINK_ENTRIES_END(link) }}
+
+/* Externals */
+extern struct list_node link_entry_head;
+extern olsr_bool link_changes;
+
+/* Function prototypes */
+
+void olsr_set_link_timer(struct link_entry *, unsigned int);
+void olsr_init_link_set(void);
+void olsr_delete_link_entry_by_ip(const union olsr_ip_addr *);
+void olsr_expire_link_hello_timer(void *);
+void olsr_update_packet_loss_worker(struct link_entry *, olsr_bool);
+void signal_link_changes(olsr_bool);   /* XXX ugly */
+
+
+struct link_entry *get_best_link_to_neighbor(const union olsr_ip_addr *);
+
+struct link_entry *lookup_link_entry(const union olsr_ip_addr *,
+				     const union olsr_ip_addr *remote_main,
+				     const struct interface *);
+
+struct link_entry *update_link_entry(const union olsr_ip_addr *,
+				     const union olsr_ip_addr *,
+				     const struct hello_message *,
+				     const struct interface *);
+
+int check_neighbor_link(const union olsr_ip_addr *);
+int replace_neighbor_link_set(const struct neighbor_entry *,
+			    struct neighbor_entry *);
+int lookup_link_status(const struct link_entry *);
+void olsr_update_packet_loss_hello_int(struct link_entry *, olsr_reltime);
+void olsr_update_packet_loss(struct link_entry *entry);
+void olsr_print_link_set(void);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/apm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/apm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/apm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/apm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Much of the ACPI code is taken from Florian Schaefers
+ * Acpi-Power Enlightenment epplet
+ */
+
+#include "apm.h"
+#include "defs.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* APM related stuff */
+
+#define APM_PROC "/proc/apm"
+
+struct linux_apm_info
+{
+  char driver_version[10];
+  int apm_version_major;
+  int apm_version_minor;
+  int apm_flags;
+  int ac_line_status;
+  int battery_status;
+  int battery_flags;
+  int battery_percentage;
+  int battery_time;
+  int using_minutes;
+};
+
+
+/* ACPI related stuff */
+static const char * const acpi_info[] = 
+  {
+    "/proc/acpi/battery/0/info",
+    "/proc/acpi/battery/1/info",
+    "/proc/acpi/battery/BATA/info",
+    "/proc/acpi/battery/BAT0/info",
+    "/proc/acpi/battery/BAT1/info" 
+  };
+
+static const char * const acpi_state[] =
+  {    
+    "/proc/acpi/battery/0/status",
+    "/proc/acpi/battery/1/status",
+    "/proc/acpi/battery/BATA/state",
+    "/proc/acpi/battery/BAT0/state",
+    "/proc/acpi/battery/BAT1/state" 
+  };
+
+
+#define ACPI_BT_CNT  ARRAYSIZE(acpi_state)
+
+
+static const char * const acpi_ac[] = 
+  {    
+    "/proc/acpi/ac_adapter/0/status",
+    "/proc/acpi/ac_adapter/AC/state",
+    "/proc/acpi/ac_adapter/ACAD/state" 
+  };
+
+#define ACPI_AC_CNT  ARRAYSIZE(acpi_ac)
+
+
+#define USE_APM    1
+#define USE_ACPI   2
+
+static int method;
+
+static int fd_index;
+
+static int ac_power_on;
+
+/* Prototypes */
+
+static int
+apm_read_apm(struct olsr_apm_info *);
+
+static int
+apm_read_acpi(struct olsr_apm_info *);
+
+static int
+acpi_probe(void);
+
+
+int 
+apm_init(void)
+{
+  struct olsr_apm_info ainfo;
+
+  method = -1;
+  OLSR_PRINTF(3, "Initializing APM\n");
+
+  if((((fd_index = acpi_probe()) >= 0) || ac_power_on) && apm_read_acpi(&ainfo))
+    method = USE_ACPI;
+  else if(apm_read_apm(&ainfo))
+    method = USE_APM;
+  
+  if(method != -1)
+    apm_printinfo(&ainfo);
+
+  return method;
+}
+
+
+void
+apm_printinfo(struct olsr_apm_info *ainfo)
+{
+  OLSR_PRINTF(5, "APM info:\n\tAC status %d\n\tBattery percentage %d%%\n\tBattery time left %d mins\n\n",
+	      ainfo->ac_line_status,
+	      ainfo->battery_percentage,
+	      ainfo->battery_time_left);
+
+  ainfo = NULL; /* squelch compiler warnings */
+}
+
+
+int
+apm_read(struct olsr_apm_info *ainfo)
+{
+  switch(method) {
+  case USE_APM:  return apm_read_apm(ainfo);
+  case USE_ACPI: return apm_read_acpi(ainfo);
+  default:       break;
+  }
+  return 0;
+}
+
+
+static int
+apm_read_apm(struct olsr_apm_info *ainfo)
+{
+  char buffer[100];
+  char units[10];
+  FILE *apm_procfile;
+  struct linux_apm_info lainfo;
+
+  /* Open procfile */
+  if((apm_procfile = fopen(APM_PROC, "r")) == NULL)
+    return 0;
+
+  if(fgets(buffer, sizeof(buffer), apm_procfile) == NULL)
+    {
+      fclose(apm_procfile);
+      /* Try re-opening the file */
+      if((apm_procfile = fopen(APM_PROC, "r")) != NULL)
+	return 0;
+
+      if(fgets(buffer, sizeof(buffer), apm_procfile) == NULL)
+	{
+	  /* Giving up */
+	  fprintf(stderr, "OLSRD: Could not read APM info - setting willingness to default");
+	  fclose(apm_procfile);
+	  return 0;
+	}
+    }
+  fclose(apm_procfile);
+
+
+  //printf("READ: %s\n", buffer);
+
+  /* Get the info */
+  sscanf(buffer, "%s %d.%d %x %x %x %x %d%% %d %s\n",
+	 lainfo.driver_version,
+	 &lainfo.apm_version_major,
+	 &lainfo.apm_version_minor,
+	 &lainfo.apm_flags,
+	 &lainfo.ac_line_status,
+	 &lainfo.battery_status,
+	 &lainfo.battery_flags,
+	 &lainfo.battery_percentage,
+	 &lainfo.battery_time,
+	 units);
+
+  lainfo.using_minutes = strncmp(units, "min", 3) ? 0 : 1;
+
+  /*
+   * Should take care of old APM type info here
+   */
+
+  /*
+   * Fix possible percentage error
+   */
+  if(lainfo.battery_percentage > 100)
+    lainfo.battery_percentage = -1;
+
+  /* Fill the provided struct */
+
+  if(lainfo.ac_line_status)
+    ainfo->ac_line_status = OLSR_AC_POWERED;
+  else
+    ainfo->ac_line_status = OLSR_BATTERY_POWERED;
+  
+  ainfo->battery_percentage = lainfo.battery_percentage;
+  ainfo->battery_time_left = lainfo.battery_time;
+  
+  return 1;
+}
+
+
+static int
+apm_read_acpi(struct olsr_apm_info *ainfo)
+{
+  FILE *fd;
+  int bat_max = 5000; /* Find some sane value */
+  int bat_val = 0;
+  int result;
+ 
+  /* reporbe in case ac status changed */
+  fd_index = acpi_probe();
+
+  /* No battery was found */
+  if(fd_index < 0)
+    {
+      /* but we have ac */
+      if(ac_power_on)
+        {
+           ainfo->ac_line_status = OLSR_AC_POWERED;
+
+           ainfo->battery_percentage = -1;
+
+           return 1;
+        }
+
+      /* not enough info */
+      return 0;
+    }
+
+  /* Get maxvalue */
+  if((fd = fopen(acpi_info[fd_index], "r")) == NULL) 
+    return 0;
+  
+  for(;;) 
+    {
+      char s1[32], s2[32], s3[32], s4[32], inbuff[127];
+      if (fgets(inbuff, sizeof(inbuff), fd) == NULL)
+        break;
+
+      sscanf(inbuff, "%s %s %s %s", s1, s2, s3, s4);	
+      if (!strcasecmp(s2, "full")) 
+	  bat_max = atoi(s4);
+    }
+  fclose(fd);
+
+
+  if((fd = fopen(acpi_state[fd_index], "r")) == NULL) 
+    return 0;
+
+  /* Extract battery status */
+  for(;;)
+    {
+      char s1[32], s2[32], s3[32], s4[32], inbuff[127];
+      if (fgets(inbuff, sizeof(inbuff), fd) == NULL)
+        break;
+      sscanf(inbuff, "%s %s %s %s", s1, s2, s3, s4);
+
+      /* find remaining juice */
+      if(!strcasecmp(s1, "Remaining")) 
+	  bat_val = atoi(s3);
+    }
+  fclose(fd);
+
+  ainfo->ac_line_status = ac_power_on ? OLSR_AC_POWERED : OLSR_BATTERY_POWERED;
+
+  result = bat_val * 100 / bat_max;
+
+  ainfo->battery_percentage = result > 100 ? 100 : result;
+
+  return 1;
+}
+
+
+static int
+acpi_probe(void)
+{
+  unsigned int i;
+  
+  /* First check for AC power */
+  ac_power_on = 0;
+
+  for(i = 0; i < ACPI_AC_CNT; i++)
+    {
+      char s1[32], s2[32];
+      int rc;
+      FILE *fd = fopen(acpi_ac[i], "r");
+  
+      /* Try opening the info file */
+      if(fd == NULL)
+	continue;
+      
+      /* Extract info */
+      rc = fscanf(fd, "%s %s", s1, s2);
+
+      /* Close info entry */
+      fclose(fd);
+
+      if(rc < 2)
+	  continue;
+      
+      /* Running on AC power */
+      if(!strcasecmp(s2, "on-line")) {
+
+        /* ac power enabled */
+        ac_power_on = 1;
+
+	break;
+      }
+    }
+
+  /* Only checking the first found battery entry... */
+  for(i = 0; i < ACPI_BT_CNT; i ++)
+    {
+      char s1[32], s2[32];
+      int rc;
+      FILE *fd = fopen(acpi_info[i], "r");
+  
+      /* Try opening the info file */
+      if(fd == NULL)
+	continue;
+
+      /* Extract info */
+      rc = fscanf(fd, "%s %s", s1, s2);
+
+      /* Close info entry */
+      fclose(fd);
+
+      if(rc < 2)
+	  continue;
+
+      /* Check if battery is present */
+      if((!strcasecmp(s1, "present:")) && (!strcasecmp(s2, "no"))) 
+	continue;
+
+      /* Open the corresponding state file */
+      if((fd = fopen(acpi_state[i], "r")) == NULL)
+	continue;
+
+      fclose(fd);
+      return i;
+    }
+
+  /* No battery found */
+  return -1;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/kernel_routes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/kernel_routes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/kernel_routes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/kernel_routes.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,491 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * Copyright (c) 2007, Sven-Ola for the policy routing stuff
+ * 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 "kernel_routes.h"
+#include "ipc_frontend.h"
+
+#if !LINUX_POLICY_ROUTING
+#include "log.h"
+
+static int delete_all_inet_gws(void);
+
+#else /* !LINUX_POLICY_ROUTING */
+
+#include <assert.h>
+#include <linux/types.h>
+#include <linux/rtnetlink.h>
+
+struct olsr_rtreq
+{
+  struct nlmsghdr n;
+  struct rtmsg    r;
+  char            buf[512];
+};
+
+static void olsr_netlink_addreq(struct olsr_rtreq *req, int type, const void *data, int len)
+{
+  struct rtattr *rta = (struct rtattr*)(((char*)req) + NLMSG_ALIGN(req->n.nlmsg_len));
+  req->n.nlmsg_len = NLMSG_ALIGN(req->n.nlmsg_len) + RTA_LENGTH(len);
+  assert(req->n.nlmsg_len < sizeof(struct olsr_rtreq));
+  rta->rta_type = type;
+  rta->rta_len = RTA_LENGTH(len);
+  memcpy(RTA_DATA(rta), data, len);
+}
+
+static int olsr_netlink_route(const struct rt_entry *rt, olsr_u8_t family, olsr_u8_t rttable, __u16 cmd)
+{
+  int ret = 0;
+  struct olsr_rtreq req;
+  struct iovec iov;
+  struct sockaddr_nl nladdr;
+  struct msghdr msg =
+  {
+    &nladdr,
+    sizeof(nladdr),
+    &iov,
+    1,
+    NULL,
+    0,
+    0
+  };
+  olsr_u32_t metric = FIBM_FLAT != olsr_cnf->fib_metric ? (RTM_NEWROUTE == cmd ?
+    rt->rt_best->rtp_metric.hops : rt->rt_metric.hops): RT_METRIC_DEFAULT;
+  const struct rt_nexthop* nexthop = (RTM_NEWROUTE == cmd) ?
+    &rt->rt_best->rtp_nexthop : &rt->rt_nexthop;
+
+  memset(&req, 0, sizeof(req));
+  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+  req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
+  req.n.nlmsg_type = cmd;
+  req.r.rtm_family = family;
+  req.r.rtm_table = rttable;
+  req.r.rtm_protocol = RTPROT_BOOT;
+  req.r.rtm_scope = RT_SCOPE_LINK;
+  req.r.rtm_type = RTN_UNICAST;
+  req.r.rtm_dst_len = rt->rt_dst.prefix_len;
+
+  if (AF_INET == family)
+  {
+    if (rt->rt_dst.prefix.v4.s_addr != nexthop->gateway.v4.s_addr)
+    {
+      olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v4, sizeof(nexthop->gateway.v4));
+      req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+    }
+    olsr_netlink_addreq(&req, RTA_DST, &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));
+  }
+  else
+  {
+    if (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6)))
+    {
+      olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
+      req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+    }
+    olsr_netlink_addreq(&req, RTA_DST, &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
+  }
+  if (FIBM_APPROX != olsr_cnf->fib_metric || RTM_NEWROUTE == cmd)
+  {
+    olsr_netlink_addreq(&req, RTA_PRIORITY, &metric, sizeof(metric));
+  }
+  olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
+  iov.iov_base = &req.n;
+  iov.iov_len = req.n.nlmsg_len;
+  memset(&nladdr, 0, sizeof(nladdr));
+  nladdr.nl_family = AF_NETLINK;
+  if (0 <= (ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0)))
+  {
+    iov.iov_base = req.buf;
+    iov.iov_len = sizeof(req.buf);
+    if (0 < (ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0)))
+    {
+      struct nlmsghdr* h = (struct nlmsghdr*)req.buf;
+      while (NLMSG_OK(h, (unsigned int)ret)) {
+        if (NLMSG_DONE == h->nlmsg_type) break;
+        if (NLMSG_ERROR == h->nlmsg_type)
+        {
+          if (NLMSG_LENGTH(sizeof(struct nlmsgerr) <= h->nlmsg_len))
+          {
+            struct nlmsgerr *l_err = (struct nlmsgerr*)NLMSG_DATA(h);
+            errno = -l_err->error;
+            if (0 != errno) ret = -1;
+          }
+          break;
+        }
+        h = NLMSG_NEXT(h, ret);
+      }
+    }
+    if (0 <= ret && olsr_cnf->ipc_connections > 0)
+    {
+      ipc_route_send_rtentry(
+        &rt->rt_dst.prefix,
+        &nexthop->gateway,
+        metric,
+        RTM_NEWROUTE == cmd,
+        if_ifwithindex_name(nexthop->iif_index));
+    }
+  }
+  return ret;
+}
+#endif /* LINUX_POLICY_ROUTING */
+
+/**
+ * Insert a route in the kernel routing table
+ *
+ * @param destination the route to add
+ *
+ * @return negative on error
+ */
+int
+olsr_ioctl_add_route(const struct rt_entry *rt)
+{
+#if !LINUX_POLICY_ROUTING
+  struct rtentry kernel_route;
+  union olsr_ip_addr mask;
+  int rslt;
+#endif /* LINUX_POLICY_ROUTING */
+
+  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
+
+#if !LINUX_POLICY_ROUTING
+  memset(&kernel_route, 0, sizeof(struct rtentry));
+
+  ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
+
+  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
+
+  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
+    return -1;
+  }
+  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
+
+  if (rt->rt_dst.prefix.v4.s_addr != rt->rt_best->rtp_nexthop.gateway.v4.s_addr) {
+    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr =
+      rt->rt_best->rtp_nexthop.gateway.v4;
+  }
+
+  kernel_route.rt_flags = olsr_rt_flags(rt);
+  kernel_route.rt_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
+
+  /*
+   * Set interface
+   */
+  kernel_route.rt_dev = if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index);
+
+  /* delete existing default route before ? */
+  if((olsr_cnf->del_gws) &&
+     (rt->rt_dst.prefix.v4.s_addr == INADDR_ANY) &&
+     (rt->rt_dst.prefix_len == INADDR_ANY)) {
+    delete_all_inet_gws();
+    olsr_cnf->del_gws = OLSR_FALSE;
+  }
+
+  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
+
+    /*
+     * Send IPC route update message
+     */
+    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway,
+                           rt->rt_best->rtp_metric.hops, 1,
+                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
+  }
+
+  return rslt;
+#else /* !LINUX_POLICY_ROUTING */
+  if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable)
+  {
+    /*
+     * Users start whining about not having internet with policy
+     * routing activated and no static default route in table 254.
+     * We maintain a fallback defroute in the default=253 table.
+     */
+    olsr_netlink_route(rt, AF_INET, 253, RTM_NEWROUTE);
+  }
+  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0)
+    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_NEWROUTE);
+  else
+    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_NEWROUTE);
+#endif /* LINUX_POLICY_ROUTING */
+}
+
+
+/**
+ *Insert a route in the kernel routing table
+ *
+ *@param destination the route to add
+ *
+ *@return negative on error
+ */
+int
+olsr_ioctl_add_route6(const struct rt_entry *rt)
+{
+#if !LINUX_POLICY_ROUTING
+  struct in6_rtmsg kernel_route;
+  int rslt;
+
+  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));
+
+  memset(&kernel_route, 0, sizeof(struct in6_rtmsg));
+
+  kernel_route.rtmsg_dst     = rt->rt_dst.prefix.v6;
+  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
+
+  kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
+
+  kernel_route.rtmsg_flags = olsr_rt_flags(rt);
+  kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
+  
+  /*
+   * set interface
+   */
+  kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;
+  
+  /* XXX delete 0/0 route before ? */
+
+  if((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {
+
+    /*
+     * Send IPC route update message
+     */
+    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, 
+                           rt->rt_best->rtp_metric.hops, 1,
+                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
+  }
+
+  return rslt;
+#else /* !LINUX_POLICY_ROUTING */
+  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0)
+    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_NEWROUTE);
+  else
+    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_NEWROUTE);
+#endif /* LINUX_POLICY_ROUTING */
+}
+
+
+/**
+ *Remove a route from the kernel
+ *
+ *@param destination the route to remove
+ *
+ *@return negative on error
+ */
+int
+olsr_ioctl_del_route(const struct rt_entry *rt)
+{
+#if !LINUX_POLICY_ROUTING
+  struct rtentry kernel_route;
+  union olsr_ip_addr mask;
+  int rslt;
+#endif /* LINUX_POLICY_ROUTING */
+
+  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
+
+#if !LINUX_POLICY_ROUTING
+  memset(&kernel_route,0,sizeof(struct rtentry));
+
+  ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
+  ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
+
+  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr = rt->rt_dst.prefix.v4;
+
+  if (rt->rt_dst.prefix.v4.s_addr != rt->rt_nexthop.gateway.v4.s_addr) {
+    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr = rt->rt_nexthop.gateway.v4;
+  }
+
+  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
+    return -1;
+  } else {
+    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr = mask.v4;
+  }
+
+  kernel_route.rt_flags = olsr_rt_flags(rt);
+  kernel_route.rt_metric = olsr_fib_metric(&rt->rt_metric.hops);
+
+  /*
+   * Set interface
+   */
+  kernel_route.rt_dev = NULL;
+
+  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) {
+
+    /*
+     * Send IPC route update message
+     */
+    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
+  }
+
+  return rslt;
+#else /* !LINUX_POLICY_ROUTING */
+  if (0 == olsr_cnf->rttable_default && 0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable)
+  {
+    /*
+     * Also remove the fallback default route
+     */
+    olsr_netlink_route(rt, AF_INET, 253, RTM_DELROUTE);
+  }
+  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0 )
+    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable_default, RTM_DELROUTE);
+  else
+    return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_DELROUTE);
+#endif /* LINUX_POLICY_ROUTING */
+}
+
+
+/**
+ *Remove a route from the kernel
+ *
+ *@param destination the route to remove
+ *
+ *@return negative on error
+ */
+int
+olsr_ioctl_del_route6(const struct rt_entry *rt)
+{
+#if !LINUX_POLICY_ROUTING
+  struct in6_rtmsg kernel_route;
+  int rslt;
+#endif /* LINUX_POLICY_ROUTING */
+
+  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
+
+#if !LINUX_POLICY_ROUTING
+  memset(&kernel_route,0,sizeof(struct in6_rtmsg));
+
+
+  kernel_route.rtmsg_dst     = rt->rt_dst.prefix.v6;
+  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;
+
+  kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6;
+
+  kernel_route.rtmsg_flags = olsr_rt_flags(rt);
+  kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric.hops);
+
+  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) {
+
+    /*
+     * Send IPC route update message
+     */
+    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);
+  }
+
+  return rslt;
+#else /* !LINUX_POLICY_ROUTING */
+  if (0 == rt->rt_dst.prefix_len && olsr_cnf->rttable_default != 0)
+    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable_default, RTM_DELROUTE);
+  else
+    return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_DELROUTE);
+#endif /* LINUX_POLICY_ROUTING */
+}
+
+#if !LINUX_POLICY_ROUTING
+static int delete_all_inet_gws(void)
+{  
+  int s;
+  char buf[BUFSIZ], *cp, *cplim;
+  struct ifconf ifc;
+  struct ifreq *ifr;
+  
+  OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n");
+  
+  /* Get a socket */
+  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
+    {
+      olsr_syslog(OLSR_LOG_ERR, "socket: %m");
+      return -1;
+    }
+  
+  ifc.ifc_len = sizeof (buf);
+  ifc.ifc_buf = buf;
+  if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 
+    {
+      olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");
+      close(s);
+      return -1;
+    }
+
+  ifr = ifc.ifc_req;
+  cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+  for (cp = buf; cp < cplim; cp += sizeof (ifr->ifr_name) + sizeof(ifr->ifr_addr)) 
+    {
+      struct rtentry kernel_route;
+      ifr = (struct ifreq *)cp;
+      
+      
+      if(strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0)
+	{
+          OLSR_PRINTF(1, "Skipping loopback...\n");
+	  continue;
+	}
+
+      OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);
+      
+      
+      memset(&kernel_route,0,sizeof(struct rtentry));
+      
+      ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;
+      ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;
+      ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;
+      ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;
+
+      ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;
+      ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;
+      
+
+      kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;
+	   
+      kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name;
+
+      if((ioctl(s, SIOCDELRT, &kernel_route)) < 0)
+         OLSR_PRINTF(1, "NO\n");
+      else
+         OLSR_PRINTF(1, "YES\n");
+    }  
+  close(s);
+  return 0;       
+}
+#endif /* LINUX_POLICY_ROUTING */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/link_layer.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/link_layer.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/link_layer.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/link_layer.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,418 @@
+/*
+ * 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.
+ *
+ */
+
+
+#if 0 /* DEPRECATED - KEPT FOR REFERENCE */
+
+/* Ugly fix to make this compile on wireless extentions < 16 */
+#define _LINUX_ETHTOOL_H
+
+#include "../link_layer.h"
+#include "../olsr_protocol.h"
+#include "../scheduler.h"
+#include "../interfaces.h"
+#include <linux/wireless.h>
+#include <linux/icmp.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <net/if_arp.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "olsr_protocol.h"
+
+void
+init_link_layer_notification(void);
+
+void
+poll_link_layer(void *);
+
+int
+add_spy_node(union olsr_ip_addr *, char *);
+
+#define	MAXIPLEN	60
+#define	MAXICMPLEN	76
+
+float poll_int = 200; /* msec */
+
+int
+iw_get_range_info(char *, struct iw_range *);
+
+int
+clear_spy_list(char *);
+
+int
+convert_ip_to_mac(union olsr_ip_addr *, struct sockaddr *, char *);
+
+void
+send_ping(union olsr_ip_addr *);
+
+
+void
+init_link_layer_notification()
+{
+  struct interface *ifd;
+
+  OLSR_PRINTF(1, "Initializing link-layer notification...\n");
+
+
+  for (ifd = ifnet; ifd ; ifd = ifd->int_next) 
+    {
+      if(ifd->is_wireless)
+	clear_spy_list(ifd->int_name);
+    }
+
+  olsr_start_timer(poll_int, 0, OLSR_TIMER_PERIODIC, &poll_link_layer, NULL, 0);
+
+  return;
+}
+
+int
+clear_spy_list(char *ifname)
+{
+  struct iwreq	wrq;
+
+  /* Time to do send addresses to the driver */
+  wrq.u.data.pointer = NULL;//(caddr_t) hw_address;
+  wrq.u.data.length = 0;
+  wrq.u.data.flags = 0;
+
+  /* Set device name */
+  strscpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name));
+
+  if(ioctl(olsr_cnf->ioctl_s, SIOCSIWSPY, &wrq) < 0)
+    {
+      OLSR_PRINTF(1, "Could not clear spylist %s\n", strerror(errno));
+      return -1;
+    }
+
+  return 1;
+}
+
+
+
+int
+add_spy_node(union olsr_ip_addr *addr, char *interface)
+{
+  struct sockaddr       new_node;
+  struct iwreq		wrq;
+  int			nbr;		/* Number of valid addresses */
+  struct sockaddr	hw_address[IW_MAX_SPY];
+  char	buffer[(sizeof(struct iw_quality) +
+		sizeof(struct sockaddr)) * IW_MAX_SPY];
+  
+  OLSR_PRINTF(1, "Adding spynode!\n\n");
+  
+  /* get all addresses already in the driver */
+
+  wrq.u.data.pointer = (caddr_t) buffer;
+  wrq.u.data.length = IW_MAX_SPY;
+  wrq.u.data.flags = 0;
+
+  strscpy(wrq.ifr_name, interface, sizeof(wrq.ifr_name));
+
+  if(ioctl(olsr_cnf->ioctl_s, SIOCGIWSPY, &wrq) < 0)
+    {
+      OLSR_PRINTF(1, "Could not get old spylist %s\n", strerror(errno));
+      return 0;
+    }
+
+  /* Copy old addresses */
+  nbr = wrq.u.data.length;
+  memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
+
+  OLSR_PRINTF(1, "Old addresses: %d\n\n", nbr);
+
+  /* Check upper limit */
+  if(nbr >= IW_MAX_SPY)
+    return 0;
+
+  /* Add new address if MAC exists in ARP cache */
+  if(convert_ip_to_mac(addr, &new_node, interface) > 0)
+    {
+      memcpy(&hw_address[nbr], &new_node, sizeof(struct sockaddr));
+      nbr++;
+    }
+  else
+    return 0;
+  
+  /* Add all addresses */
+  wrq.u.data.pointer = (caddr_t) hw_address;
+  wrq.u.data.length = nbr;
+  wrq.u.data.flags = 0;
+  
+  /* Set device name */
+  strscpy(wrq.ifr_name, interface, sizeof(wrq.ifr_name));
+  
+  if(ioctl(olsr_cnf->ioctl_s, SIOCSIWSPY, &wrq) < 0)
+    {
+      OLSR_PRINTF(1, "Could not clear spylist %s\n", strerror(errno));
+      return 0;
+    }
+
+
+  return 1;
+}
+
+
+int
+convert_ip_to_mac(union olsr_ip_addr *ip, struct sockaddr *mac, char *interface)
+{
+  struct arpreq	arp_query;
+  struct sockaddr_in tmp_sockaddr;
+
+
+  memset(&arp_query, 0, sizeof(struct arpreq));
+
+  OLSR_PRINTF(1, "\nARP conversion for %s interface %s\n", 
+	      olsr_ip_to_string(ip),
+	      interface);
+
+  tmp_sockaddr.sin_family = AF_INET;
+  tmp_sockaddr.sin_port = 0;
+
+  memcpy(&tmp_sockaddr.sin_addr, ip, olsr_cnf->ipsize);
+
+  /* Translate IP addresses to MAC addresses */
+  memcpy(&arp_query.arp_pa, &tmp_sockaddr, sizeof(struct sockaddr_in));
+  arp_query.arp_ha.sa_family = 0;
+  arp_query.arp_flags = 0;
+
+  strscpy(arp_query.arp_dev, interface, sizeof(arp_query.arp_dev));
+  
+  if((ioctl(olsr_cnf->ioctl_s, SIOCGARP, &arp_query) < 0) ||
+     !(arp_query.arp_flags & ATF_COM)) /* ATF_COM - hw addr valid */
+    {
+      OLSR_PRINTF(1, "Arp failed: (%s) - trying lookup\n", strerror(errno));
+
+      /* No address - create a thread that sends a PING */
+      send_ping(ip);
+  
+      return -1;
+    }
+
+  OLSR_PRINTF(1, "Arp success!\n");
+
+  memcpy(mac, &arp_query.arp_ha, sizeof(struct sockaddr));
+
+  return 1;
+}
+
+
+
+/**
+ *A thread that sends a ICMP echo "ping" packet
+ *to a given destination to force the ARP cache
+ *to be updated... kind of a kludge....
+ *
+ *@param _ip the IP address to ping
+ */
+/* ONLY IPv4 FOR NOW!!! */
+
+void
+send_ping(union olsr_ip_addr *ip)
+{
+  int ping_s;
+  struct sockaddr dst;
+  struct sockaddr_in *dst_in;
+  char *packet;
+  struct icmphdr *icp;
+
+  dst_in = (struct sockaddr_in *) &dst;
+
+  dst_in->sin_family = AF_INET;
+  memcpy(&dst_in->sin_addr, ip, olsr_cnf->ipsize);
+
+  OLSR_PRINTF(1, "pinging %s\n\n", olsr_ip_to_string(ip));
+
+  if ((ping_s = socket(AF_INET, SOCK_RAW, PF_INET)) < 0) 
+    {
+      OLSR_PRINTF(1, "Could not create RAW socket for ping!\n%s\n", strerror(errno));
+      return;
+    }
+
+  /* Create packet */
+  packet = malloc(MAXIPLEN + MAXICMPLEN);
+  
+  
+  icp = (struct icmphdr *)packet;
+  icp->type = ICMP_ECHO;
+  icp->code = 0;
+  icp->checksum = 0;
+  icp->un.echo.sequence = 1;
+  icp->un.echo.id = getpid() & 0xFFFF;
+
+  if((sendto(ping_s, packet, MAXIPLEN + MAXICMPLEN + 8, 0, &dst, sizeof(struct sockaddr))) !=
+     MAXIPLEN + MAXICMPLEN + 8)
+    {
+      OLSR_PRINTF(1, "Error PING: %s\n", strerror(errno));
+    }
+
+  /* Nevermind the pong ;-) */
+
+  OLSR_PRINTF(1, "Ping complete...\n");
+  close(ping_s);
+
+  free(packet);
+
+  return;
+}
+
+void
+poll_link_layer(void *foo)
+{
+  struct iwreq		wrq;
+  char		        buffer[(sizeof(struct iw_quality) +
+			       sizeof(struct sockaddr)) * IW_MAX_SPY];
+  struct sockaddr       *hwa;
+  struct iw_quality     *qual;
+  int		        n;
+  struct iw_range	range;
+  int		        i, j;
+  int                   has_range = 0;
+  struct interface      *iflist;
+
+  //OLSR_PRINTF(1, "Polling link-layer notification...\n");
+
+  for(iflist = ifnet; iflist != NULL; iflist = iflist->int_next)
+    {
+      if(!iflist->is_wireless)
+	continue;
+
+      /* Collect stats */
+      wrq.u.data.pointer = (caddr_t) buffer;
+      wrq.u.data.length = IW_MAX_SPY;
+      wrq.u.data.flags = 0;
+      
+      /* Set device name */
+      strscpy(wrq.ifr_name, iflist->int_name, sizeof(wrq.ifr_name));
+      
+      /* Do the request */
+      if(ioctl(olsr_cnf->ioctl_s, SIOCGIWSPY, &wrq) < 0)
+	{
+          OLSR_PRINTF(1, "%-8.16s  Interface doesn't support wireless statistic collection\n\n", iflist->int_name);
+	  return;
+	}
+      
+      /* Get range info if we can */
+      if(iw_get_range_info(iflist->int_name, &(range)) >= 0)
+	has_range = 1;
+      
+      /* Number of addresses */
+      n = wrq.u.data.length;
+      
+      /* The two lists */
+      hwa = (struct sockaddr *) buffer;
+      qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
+      
+      for(i = 0; i < n; i++)
+	{
+	  if(!(qual->updated & 0x7))
+	    continue;
+	  
+	  /* Print stats for each address */
+	  OLSR_PRINTF(1, "MAC");
+	  for(j = 0; j < 6; j++)
+	    {
+                    OLSR_PRINTF(1, ":%02x", (hwa[i].sa_data[j] % 0xffffff00));
+	    }
+	  if(!has_range)
+	    OLSR_PRINTF(1, " : Quality:%d  Signal level:%d dBm  Noise level:%d dBm",
+			qual[i].qual,
+			qual[i].level - 0x100, 
+			qual[i].noise - 0x100);
+	  else
+	    OLSR_PRINTF(1, " : Quality:%d/%d  Signal level:%d dBm  Noise level:%d dBm",
+			qual[i].qual,
+			range.max_qual.qual,
+			qual[i].level - 0x100, 
+			qual[i].noise - 0x100);
+	  
+	  OLSR_PRINTF(1, "\n");
+	  
+	}
+    }
+
+  //OLSR_PRINTF(1, "\n");
+  return;
+}
+
+
+
+
+
+/*
+ * Get the range information out of the driver
+ */
+int
+iw_get_range_info(char            *ifname,
+		  struct iw_range *range)
+{
+  struct iwreq		wrq;
+  char			buffer[sizeof(struct iw_range) * 2];	/* Large enough */
+  union iw_range_raw    *range_raw;
+
+  /* Cleanup */
+  bzero(buffer, sizeof(buffer));
+
+  wrq.u.data.pointer = (caddr_t) buffer;
+  wrq.u.data.length = sizeof(buffer);
+  wrq.u.data.flags = 0;
+
+  /* Set device name */
+  strscpy(wrq.ifr_name, ifname, sizeof(wrq.ifr_name));
+
+  if(ioctl(olsr_cnf->ioctl_s, SIOCGIWRANGE, &wrq) < 0)
+    {
+      OLSR_PRINTF(1, "NO RANGE\n");
+      return -1;
+    }
+
+  /* Point to the buffer */
+  range_raw = (union iw_range_raw *) buffer;
+
+  memcpy((char *) range, buffer, sizeof(struct iw_range));
+
+  return 1;
+}
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/net.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/net.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/linux/net.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/linux/net.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,908 @@
+/*
+ * 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.
+ *
+ */
+
+
+/*
+ * Linux spesific code
+ */
+
+#include "../net_os.h"
+#include "../ipcalc.h"
+
+#include <net/if.h>
+
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <syslog.h>
+
+
+/* Redirect proc entry */
+#define REDIRECT_PROC "/proc/sys/net/ipv4/conf/%s/send_redirects"
+
+/* IP spoof proc entry */
+#define SPOOF_PROC "/proc/sys/net/ipv4/conf/%s/rp_filter"
+
+/*
+ *Wireless definitions for ioctl calls
+ *(from linux/wireless.h)
+ */
+#define SIOCGIWNAME	0x8B01		/* get name == wireless protocol */
+#define SIOCGIWRATE	0x8B21		/* get default bit rate (bps) */
+
+/* The original state of the IP forwarding proc entry */
+static char orig_fwd_state;
+static char orig_global_redirect_state;
+
+/**
+ *Bind a socket to a device
+ *
+ *@param sock the socket to bind
+ *@param dev_name name of the device
+ *
+ *@return negative if error
+ */
+
+int
+bind_socket_to_device(int sock, char *dev_name)
+{
+  /*
+   *Bind to device using the SO_BINDTODEVICE flag
+   */
+  OLSR_PRINTF(3, "Binding socket %d to device %s\n", sock, dev_name);
+  return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, dev_name, strlen(dev_name)+1);
+}
+
+
+/**
+ *Enable IP forwarding.
+ *Just writing "1" to the /proc/sys/net/ipv4/ip_forward
+ *if using IPv4 or /proc/sys/net/ipv6/conf/all/forwarding
+ *if using IPv6.
+ *Could probably drop the check for
+ *"0" here and write "1" anyways.
+ *
+ *@param version IP version.
+ *
+ *@return 1 on sucess 0 on failiure
+ */ 
+int
+enable_ip_forwarding(int version)
+{
+  FILE *proc_fwd;
+  const char * const procfile = version == AF_INET
+      ? "/proc/sys/net/ipv4/ip_forward"
+      : "/proc/sys/net/ipv6/conf/all/forwarding";
+
+  if ((proc_fwd=fopen(procfile, "r"))==NULL)
+    {
+      /* IPv4 */
+      if(version == AF_INET)
+	fprintf(stderr, "WARNING! Could not open the %s file to check/enable IP forwarding!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n", procfile);
+      /* IPv6 */
+      else
+	fprintf(stderr, "WARNING! Could not open the %s file to check/enable IP forwarding!\nAre you using the procfile filesystem?\nDoes your system support IPv6?\nI will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n", procfile);
+      
+      sleep(3);
+      return 0;
+    }
+  
+  orig_fwd_state = fgetc(proc_fwd);
+  fclose(proc_fwd);
+  if(orig_fwd_state == '1')
+    {
+      OLSR_PRINTF(3, "\nIP forwarding is enabled on this system\n");
+    }
+  else
+    {
+      if ((proc_fwd=fopen(procfile, "w"))==NULL)
+        {
+          fprintf(stderr, "Could not open %s for writing!\n", procfile);
+          fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n");
+          sleep(3);
+          return 0;
+        }
+      else
+        {
+          syslog(LOG_INFO, "Writing \"1\" to %s\n", procfile);
+          fputs("1", proc_fwd);
+        }
+      fclose(proc_fwd);
+    }
+  return 1;      
+}
+
+int
+disable_redirects_global(int version)
+{
+  FILE *proc_redirect;
+  const char * const procfile = "/proc/sys/net/ipv4/conf/all/send_redirects";
+
+  if(version == AF_INET6)
+    return -1;
+
+  if((proc_redirect = fopen(procfile, "r")) == NULL)
+    {
+      fprintf(stderr, "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n", procfile);
+      
+      sleep(3);
+      return -1;
+    }
+  orig_global_redirect_state = fgetc(proc_redirect);
+  fclose(proc_redirect);
+
+  if(orig_global_redirect_state == '0')
+      return 0;
+
+  if ((proc_redirect = fopen(procfile, "w"))==NULL)
+    {
+      fprintf(stderr, "Could not open %s for writing!\n", procfile);
+      fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n");
+      sleep(3);
+      return 0;
+    }
+  syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
+  fputs("0", proc_redirect);
+  fclose(proc_redirect);  
+  return 1;
+}
+
+/**
+ *
+ *@return 1 on sucess 0 on failiure
+ */ 
+int
+disable_redirects(const char *if_name, struct interface *iface, int version)
+{
+  FILE *proc_redirect;
+  char procfile[FILENAME_MAX];
+
+  if(version == AF_INET6)
+    return -1;
+
+  /* Generate the procfile name */
+  snprintf(procfile, sizeof(procfile), REDIRECT_PROC, if_name);
+
+
+  if((proc_redirect = fopen(procfile, "r")) == NULL)
+    {
+      fprintf(stderr, "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n", procfile);      
+      sleep(3);
+      return 0;
+    }
+  iface->nic_state.redirect = fgetc(proc_redirect);
+  fclose(proc_redirect);      
+
+  if ((proc_redirect = fopen(procfile, "w"))==NULL)
+    {
+      fprintf(stderr, "Could not open %s for writing!\n", procfile);
+      fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n");
+      sleep(3);
+      return 0;
+    }
+  syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
+  fputs("0", proc_redirect);
+  fclose(proc_redirect);
+  return 1;
+}
+
+/**
+ *
+ *@return 1 on sucess 0 on failiure
+ */ 
+int
+deactivate_spoof(const char *if_name, struct interface *iface, int version)
+{
+  FILE *proc_spoof;
+  char procfile[FILENAME_MAX];
+
+  if(version == AF_INET6)
+    return -1;
+
+  /* Generate the procfile name */
+  sprintf(procfile, SPOOF_PROC, if_name);
+
+  if((proc_spoof = fopen(procfile, "r")) == NULL)
+    {
+      fprintf(stderr, "WARNING! Could not open the %s file to check/disable the IP spoof filter!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabled!\n\n", procfile);
+      
+      sleep(3);
+      return 0;
+    }
+  iface->nic_state.spoof = fgetc(proc_spoof);
+  fclose(proc_spoof);
+
+  if ((proc_spoof = fopen(procfile, "w")) == NULL)
+    {
+      fprintf(stderr, "Could not open %s for writing!\n", procfile);
+      fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabeled!\n\n");
+      sleep(3);
+      return 0;
+    }
+  syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
+  fputs("0", proc_spoof);
+  fclose(proc_spoof);
+  return 1;
+}
+
+/**
+ *Resets the spoof filter and ICMP redirect settings
+ */
+int
+restore_settings(int version)
+{
+  struct interface *ifs;
+
+  OLSR_PRINTF(1, "Restoring network state\n");
+
+  /* Restore IP forwarding to "off" */
+  if(orig_fwd_state == '0')
+    {
+      const char * const procfile = version == AF_INET
+        ? "/proc/sys/net/ipv4/ip_forward"
+        : "/proc/sys/net/ipv6/conf/all/forwarding";
+      FILE *proc_fd;
+
+      if ((proc_fd = fopen(procfile, "w")) == NULL)
+	{
+	  fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
+	}
+      else
+	{
+	  syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_fwd_state);
+	  fputc(orig_fwd_state, proc_fd);
+	  fclose(proc_fd);
+	}
+    }
+
+  /* Restore global ICMP redirect setting */
+  if(orig_global_redirect_state != '0')
+    {
+      if(version == AF_INET)
+	{
+	  const char * const procfile = "/proc/sys/net/ipv4/conf/all/send_redirects";
+          FILE *proc_fd;
+
+	  if ((proc_fd = fopen(procfile, "w")) == NULL)
+	    {
+	      fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
+	    }
+	  else
+	    {
+	      syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_global_redirect_state);
+	      fputc(orig_global_redirect_state, proc_fd);
+	      fclose(proc_fd);
+	    }
+	}
+    }
+
+  if(version == AF_INET6)
+    return 0;
+
+  for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
+    {
+      char procfile[FILENAME_MAX];
+      FILE *proc_fd;
+      /* Discard host-emulation interfaces */
+      if(ifs->is_hcif)
+	continue;
+      /* ICMP redirects */
+      
+      /* Generate the procfile name */
+      snprintf(procfile, sizeof(procfile), REDIRECT_PROC, ifs->int_name);
+      
+      if ((proc_fd = fopen(procfile, "w")) == NULL)
+	  fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
+      else
+	{
+	  syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.redirect);
+
+	  fputc(ifs->nic_state.redirect, proc_fd);
+	  fclose(proc_fd);
+	}
+      
+      /* Spoof filter */
+      
+      /* Generate the procfile name */
+      sprintf(procfile, SPOOF_PROC, ifs->int_name);
+      if ((proc_fd = fopen(procfile, "w")) == NULL)
+	  fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
+      else
+	{
+	  syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.spoof);
+
+	  fputc(ifs->nic_state.spoof, proc_fd);
+	  fclose(proc_fd);
+	}
+    }
+  return 1;
+}
+
+/**
+ *Creates a blocking tcp socket for communication with switch daemon.
+ *@param sa sockaddr struct. Used for bind(2).
+ *@return the FD of the socket or -1 on error.
+ */
+int
+gethemusocket(struct sockaddr_in *pin)
+{
+  int sock, on = 1;
+
+  OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
+  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
+    {
+      perror("hcsocket");
+      syslog(LOG_ERR, "hcsocket: %m");
+      return -1;
+    }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+    {
+      perror("SO_REUSEADDR failed");
+      close(sock);
+      return -1;
+    }
+  /* connect to PORT on HOST */
+  if (connect(sock,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
+    {
+      printf("FAILED\n");
+      fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+      printf("connection refused\n");
+      close(sock);
+      return -1;
+    }
+
+  printf("OK\n");
+
+  /* Keep TCP socket blocking */  
+  return sock;
+}
+
+
+/**
+ *Creates a nonblocking broadcast socket.
+ *@param sa sockaddr struct. Used for bind(2).
+ *@return the FD of the socket or -1 on error.
+ */
+int
+getsocket(int bufspace, char *int_name)
+{
+  struct sockaddr_in sin;
+  int on;
+  int sock = socket(AF_INET, SOCK_DGRAM, 0);
+  if (sock < 0) 
+    {
+      perror("socket");
+      syslog(LOG_ERR, "socket: %m");
+      return -1;
+    }
+
+  on = 1;
+#ifdef SO_BROADCAST
+  if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
+    {
+      perror("setsockopt");
+      syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+      close(sock);
+      return -1;
+    }
+#endif
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+    {
+      perror("SO_REUSEADDR failed");
+      close(sock);
+      return -1;
+    }
+
+#ifdef SO_RCVBUF
+  for (on = bufspace; ; on -= 1024) 
+    {
+      if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) == 0)
+	break;
+      if (on <= 8*1024) 
+	{
+	  perror("setsockopt");
+	  syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+	  break;
+	}
+    }
+#endif
+
+  /*
+   * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
+   */
+
+  /* Bind to device */
+  if(bind_socket_to_device(sock, int_name) < 0)
+    {
+      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;
+    }
+
+  memset(&sin, 0, sizeof (sin));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(OLSRPORT);
+  sin.sin_addr.s_addr = INADDR_ANY;
+  if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+      perror("bind");
+      syslog(LOG_ERR, "bind: %m");
+      close(sock);
+      return -1;
+  }
+
+  on = fcntl(sock, F_GETFL);
+  if (on == -1) {
+      syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
+  } else {
+      if (fcntl(sock, F_SETFL, on|O_NONBLOCK) == -1) {
+          syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
+      }
+  }
+  return sock;
+}
+
+
+/**
+ *Creates a nonblocking IPv6 socket
+ *@param sin sockaddr_in6 struct. Used for bind(2).
+ *@return the FD of the socket or -1 on error.
+ */
+int
+getsocket6(int bufspace, char *int_name)
+{
+  struct sockaddr_in6 sin;
+  int on;
+  int sock = socket(AF_INET6, SOCK_DGRAM, 0);
+  if (sock < 0) {
+    perror("socket");
+    syslog(LOG_ERR, "socket: %m");
+    return (-1);
+  }
+
+#ifdef IPV6_V6ONLY
+  on = 1;
+  if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+    perror("setsockopt(IPV6_V6ONLY)");
+    syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m");
+  }
+#endif
+
+
+  //#ifdef SO_BROADCAST
+  /*
+  if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof (on)) < 0)
+    {
+      perror("setsockopt");
+      syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+      close(sock);
+      return (-1);
+    }
+  */
+  //#endif
+
+#ifdef SO_RCVBUF
+  for (on = bufspace; ; on -= 1024) 
+    {
+      if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) == 0)
+	break;
+      if (on <= 8*1024) 
+	{
+	  perror("setsockopt");
+	  syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+	  break;
+	}
+    }
+#endif
+
+  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
+    {
+      perror("SO_REUSEADDR failed");
+      close(sock);
+      return (-1);
+    }
+
+  /*
+   * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
+   */
+
+  /* Bind to device */
+  if(bind_socket_to_device(sock, int_name) < 0)
+    {
+      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;
+    }
+
+  memset(&sin, 0, sizeof(sin));
+  sin.sin6_family = AF_INET6;
+  sin.sin6_port = htons(OLSRPORT);
+  //(addrsock6.sin6_addr).s_addr = IN6ADDR_ANY_INIT;
+  if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) 
+    {
+      perror("bind");
+      syslog(LOG_ERR, "bind: %m");
+      close(sock);
+      return (-1);
+    }
+
+  on = fcntl(sock, F_GETFL);
+  if (on == -1) {
+      syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
+  } else {
+      if (fcntl(sock, F_SETFL, on|O_NONBLOCK) == -1) {
+          syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
+      }
+  }
+  return sock;
+}
+
+int
+join_mcast(struct interface *ifs, int sock)
+{
+  /* See linux/in6.h */
+  struct ipaddr_str buf;
+  struct ipv6_mreq mcastreq;
+
+  mcastreq.ipv6mr_multiaddr = ifs->int6_multaddr.sin6_addr;
+  mcastreq.ipv6mr_interface = ifs->if_index;
+
+#if !defined __FreeBSD__ && !defined __MacOSX__ && !defined __NetBSD__
+  OLSR_PRINTF(3, "Interface %s joining multicast %s...", ifs->int_name, ip6_to_string(&buf, &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 */
+#ifdef IPV6_JOIN_GROUP
+  /* Join reciever group */
+  if(setsockopt(sock, 
+		IPPROTO_IPV6, 
+		IPV6_JOIN_GROUP, 
+		(char *)&mcastreq, 
+		sizeof(struct ipv6_mreq)) 
+     < 0)
+#else
+  /* Join reciever group */
+  if(setsockopt(sock, 
+		IPPROTO_IPV6, 
+		IPV6_ADD_MEMBERSHIP, 
+		(char *)&mcastreq, 
+		sizeof(struct ipv6_mreq)) 
+     < 0)
+#endif 
+    {
+      perror("Join multicast send");
+      return -1;
+    }  
+
+  if(setsockopt(sock, 
+		IPPROTO_IPV6, 
+		IPV6_MULTICAST_IF, 
+		(char *)&mcastreq.ipv6mr_interface, 
+		sizeof(mcastreq.ipv6mr_interface)) 
+     < 0)
+    {
+      perror("Set multicast if");
+      return -1;
+    }
+
+
+  OLSR_PRINTF(3, "OK\n");
+  return 0;
+}
+
+/*
+ *From net-tools lib/interface.c
+ *
+ */
+int
+get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
+{
+  char addr6[40], devname[IFNAMSIZ];
+  char addr6p[8][5];
+  int plen, scope, dad_status, if_idx;
+  FILE *f;
+  struct sockaddr_in6 tmp_sockaddr6;
+
+  if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) 
+    {
+      while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+		    addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+		    addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+		    &if_idx, &plen, &scope, &dad_status, devname) != EOF) 
+	{
+	  if (!strcmp(devname, ifname)) 
+	    {
+	      sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+		      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+		      addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+	      OLSR_PRINTF(5, "\tinet6 addr: %s\n", addr6);
+	      OLSR_PRINTF(5, "\tScope: %d\n", scope);
+	      if(scope == scope_in)
+		{
+		  OLSR_PRINTF(4, "Found addr: %s:%s:%s:%s:%s:%s:%s:%s\n",
+			      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+			      addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+		  inet_pton(AF_INET6,addr6,&tmp_sockaddr6);
+		  memcpy(&saddr6->sin6_addr, &tmp_sockaddr6, sizeof(struct in6_addr));	  
+		  fclose(f);
+		  return 1;
+		}
+	    }
+	}
+      fclose(f);
+    }  
+  return 0;
+}
+
+
+/**
+ * Wrapper for sendto(2)
+ */
+ssize_t
+olsr_sendto(int s, 
+	    const void *buf, 
+	    size_t len, 
+	    int flags, 
+	    const struct sockaddr *to, 
+	    socklen_t tolen)
+{
+  return sendto(s, buf, len, flags, to, tolen);
+}
+
+/**
+ * Wrapper for recvfrom(2)
+ */
+
+ssize_t  
+olsr_recvfrom(int  s, 
+	      void *buf, 
+	      size_t len, 
+	      int flags, 
+	      struct sockaddr *from,
+	      socklen_t *fromlen)
+{
+  return recvfrom(s, 
+		  buf, 
+		  len, 
+		  flags, 
+		  from, 
+		  fromlen);
+}
+
+/**
+ * Wrapper for select(2)
+ */
+
+int
+olsr_select(int nfds,
+            fd_set *readfds,
+            fd_set *writefds,
+            fd_set *exceptfds,
+            struct timeval *timeout)
+{
+  return select(nfds,
+                readfds,
+                writefds,
+                exceptfds,
+                timeout);
+}
+
+int
+check_wireless_interface(char * ifname)
+{
+  struct ifreq ifr;
+
+  memset(&ifr, 0, sizeof(ifr));
+  strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+  return (ioctl(olsr_cnf->ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;
+}
+
+#if 0
+
+#include <linux/sockios.h>
+#include <linux/types.h>
+
+/* This data structure is used for all the MII ioctl's */
+struct mii_data {
+    __u16	phy_id;
+    __u16	reg_num;
+    __u16	val_in;
+    __u16	val_out;
+};
+
+
+/* Basic Mode Control Register */
+#define MII_BMCR		0x00
+#define  MII_BMCR_RESET		0x8000
+#define  MII_BMCR_LOOPBACK	0x4000
+#define  MII_BMCR_100MBIT	0x2000
+#define  MII_BMCR_AN_ENA	0x1000
+#define  MII_BMCR_ISOLATE	0x0400
+#define  MII_BMCR_RESTART	0x0200
+#define  MII_BMCR_DUPLEX	0x0100
+#define  MII_BMCR_COLTEST	0x0080
+
+/* Basic Mode Status Register */
+#define MII_BMSR		0x01
+#define  MII_BMSR_CAP_MASK	0xf800
+#define  MII_BMSR_100BASET4	0x8000
+#define  MII_BMSR_100BASETX_FD	0x4000
+#define  MII_BMSR_100BASETX_HD	0x2000
+#define  MII_BMSR_10BASET_FD	0x1000
+#define  MII_BMSR_10BASET_HD	0x0800
+#define  MII_BMSR_NO_PREAMBLE	0x0040
+#define  MII_BMSR_AN_COMPLETE	0x0020
+#define  MII_BMSR_REMOTE_FAULT	0x0010
+#define  MII_BMSR_AN_ABLE	0x0008
+#define  MII_BMSR_LINK_VALID	0x0004
+#define  MII_BMSR_JABBER	0x0002
+#define  MII_BMSR_EXT_CAP	0x0001
+
+int
+calculate_if_metric(char *ifname)
+{
+  if(check_wireless_interface(ifname))
+    {
+      struct ifreq ifr;
+      strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+      
+      /* Get bit rate */
+      if(ioctl(olsr_cnf->ioctl_s, SIOCGIWRATE, &ifr) < 0)
+	{
+          OLSR_PRINTF(1, "Not able to find rate for WLAN interface %s\n", ifname);
+	  return WEIGHT_WLAN_11MB;
+	}
+      
+      OLSR_PRINTF(1, "Bitrate %d\n", ifr.ifr_ifru.ifru_ivalue);
+
+      //WEIGHT_WLAN_LOW,          /* <11Mb WLAN     */
+      //WEIGHT_WLAN_11MB,         /* 11Mb 802.11b   */
+      //WEIGHT_WLAN_54MB,         /* 54Mb 802.11g   */
+      return WEIGHT_WLAN_LOW;
+    }
+  else
+    {
+      /* Ethernet */
+      /* Mii wizardry */
+      struct ifreq ifr;
+      struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
+      int bmcr;
+      memset(&ifr, 0, sizeof(ifr));
+      strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+      if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
+	if (errno != ENODEV)
+	  OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
+		      ifr.ifr_name, strerror(errno));
+	return WEIGHT_ETHERNET_DEFAULT;
+      }
+
+      mii->reg_num = MII_BMCR;
+      if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) {
+	OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
+		    strerror(errno));
+	return WEIGHT_ETHERNET_DEFAULT;
+      }
+      bmcr = mii->val_out;
+
+
+      OLSR_PRINTF(1, "%s: ", ifr.ifr_name);
+      OLSR_PRINTF(1, "%s Mbit, %s duplex\n",
+		  (bmcr & MII_BMCR_100MBIT) ? "100" : "10",
+		  (bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
+    
+      is_if_link_up(ifname);
+
+      if(mii->val_out & MII_BMCR_100MBIT)
+	return WEIGHT_ETHERNET_100MB;
+      else
+	return WEIGHT_ETHERNET_10MB;
+      //WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb   */
+
+    }
+}
+
+
+olsr_bool
+is_if_link_up(char *ifname)
+{
+  if(check_wireless_interface(ifname))
+    {
+      /* No link checking on wireless devices */
+      return OLSR_TRUE;
+    }
+  else
+    {
+      /* Mii wizardry */
+      struct ifreq ifr;
+      struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
+      int bmsr;
+      memset(&ifr, 0, sizeof(ifr));
+      strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+      if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
+	if (errno != ENODEV)
+	  OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n",
+		      ifr.ifr_name, strerror(errno));
+	return WEIGHT_ETHERNET_DEFAULT;
+      }
+      mii->reg_num = MII_BMSR;
+      if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) {
+	OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
+		    strerror(errno));
+	return WEIGHT_ETHERNET_DEFAULT;
+      }
+      bmsr = mii->val_out;
+
+      OLSR_PRINTF(1, "%s: ", ifr.ifr_name);
+      OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link ");
+    
+      return (bmsr & MII_BMSR_LINK_VALID);
+
+    }
+}
+
+#else
+int
+calculate_if_metric(char *ifname)
+{
+  return check_wireless_interface(ifname);
+}
+#endif
+  
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/log.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/log.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/log.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/log.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ */
+
+/* 
+ * System logging interface
+ * Platform independent - the implementations
+ * reside in <OS>/log.c(e.g. linux/log.c)
+ */
+
+#ifndef _OLSR_SYSLOG_H
+#define _OLSR_SYSLOG_H
+
+#define OLSR_LOG_INFO            1
+#define OLSR_LOG_ERR             2
+
+void
+olsr_openlog(const char *ident);
+
+void
+olsr_syslog(int level, const char *format, ...) __attribute__((format(printf,2,3)));
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_mpr.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_mpr.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_mpr.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_mpr.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,188 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "defs.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "link_set.h"
+#include "lq_mpr.h"
+#include "scheduler.h"
+#include "lq_plugin.h"
+
+void olsr_calculate_lq_mpr(void)
+{
+  struct neighbor_2_entry *neigh2;
+  struct neighbor_list_entry *walker;
+  int i, k;
+  struct neighbor_entry *neigh;
+  olsr_linkcost best, best_1hop;
+  olsr_bool mpr_changes = OLSR_FALSE;
+
+  OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
+
+    /* Memorize previous MPR status. */
+
+    neigh->was_mpr = neigh->is_mpr;
+
+    /* Clear current MPR status. */
+
+    neigh->is_mpr = OLSR_FALSE;
+
+    /* In this pass we are only interested in WILL_ALWAYS neighbours */
+
+    if (neigh->status == NOT_SYM || neigh->willingness != WILL_ALWAYS) {
+      continue;
+    }
+
+    neigh->is_mpr = OLSR_TRUE;
+
+    if (neigh->is_mpr != neigh->was_mpr) {
+      mpr_changes = OLSR_TRUE;
+    }
+
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
+
+  for(i = 0; i < HASHSIZE; i++)
+    {
+      /* loop through all 2-hop neighbours */
+
+      for (neigh2 = two_hop_neighbortable[i].next;
+           neigh2 != &two_hop_neighbortable[i];
+           neigh2 = neigh2->next)
+        {
+          best_1hop = LINK_COST_BROKEN;
+
+          /* check whether this 2-hop neighbour is also a neighbour */
+
+          neigh = olsr_lookup_neighbor_table(&neigh2->neighbor_2_addr);
+
+          /* if it's a neighbour and also symmetric, then examine
+             the link quality */
+          
+          if (neigh != NULL && neigh->status == SYM)
+            {
+              /* if the direct link is better than the best route via
+               * an MPR, then prefer the direct link and do not select
+               * an MPR for this 2-hop neighbour */
+
+              /* determine the link quality of the direct link */
+
+              struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
+
+	      if (!lnk)
+		continue;
+
+              best_1hop = lnk->linkcost;
+
+              /* 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_linkcost < best_1hop)
+                  break;
+
+              /* we've reached the end of the list, so we haven't found
+               * a better route via an MPR - so, skip MPR selection for
+               * this 1-hop neighbor */
+
+              if (walker == &neigh2->neighbor_2_nblist)
+                continue;
+            }
+
+          /* find the connecting 1-hop neighbours with the
+           * best total link qualities */
+
+          /* mark all 1-hop neighbours as not selected */
+
+          for (walker = neigh2->neighbor_2_nblist.next;
+               walker != &neigh2->neighbor_2_nblist;
+               walker = walker->next)
+            walker->neighbor->skip = OLSR_FALSE;
+
+          for (k = 0; k < olsr_cnf->mpr_coverage; k++)
+            {
+              /* look for the best 1-hop neighbour that we haven't
+               * yet selected */
+
+              neigh = NULL;
+              best = LINK_COST_BROKEN;
+
+              for (walker = neigh2->neighbor_2_nblist.next;
+                   walker != &neigh2->neighbor_2_nblist;
+                   walker = walker->next)
+                if (walker->neighbor->status == SYM &&
+                    !walker->neighbor->skip &&
+                    walker->path_linkcost < best)
+                  {
+                    neigh = walker->neighbor;
+                    best = walker->path_linkcost;
+                  }
+
+              /* 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;
+          
+                  if (neigh->is_mpr != neigh->was_mpr)
+                    mpr_changes = OLSR_TRUE;
+                }
+
+              /* no neighbour found => the requested MPR coverage cannot
+               * be satisfied => stop */
+
+              else
+                break;
+            }
+        }
+    }
+
+  if (mpr_changes && olsr_cnf->tc_redundancy > 0)
+    signal_link_changes(OLSR_TRUE);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_mpr.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_mpr.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_mpr.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_mpr.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 _OLSR_LQ_MPR
+#define _OLSR_LQ_MPR
+
+void olsr_calculate_lq_mpr(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_packet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_packet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_packet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_packet.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,722 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2003, Andreas TÃ¸nnesen (andreto@olsr.org)
+ *               2004, Thomas Lopatic (thomas@lopatic.de)
+ *               2006, for some fixups, sven-ola(gmx.de)
+ * 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 "ipcalc.h"
+#include "olsr_protocol.h"
+#include "defs.h"
+#include "lq_packet.h"
+#include "interfaces.h"
+#include "link_set.h"
+#include "neighbor_table.h"
+#include "mpr_selector_set.h"
+#include "mid_set.h"
+#include "mantissa.h"
+#include "process_package.h" // XXX - remove
+#include "two_hop_neighbor_table.h"
+#include "hysteresis.h"
+#include "olsr.h"
+#include "build_msg.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+
+olsr_bool lq_tc_pending = OLSR_FALSE;
+
+static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
+
+static void
+create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
+{
+  struct link_entry *walker;
+
+  // initialize the static fields
+
+  lq_hello->comm.type = LQ_HELLO_MESSAGE;
+  lq_hello->comm.vtime = me_to_reltime(outif->valtimes.hello);
+  lq_hello->comm.size = 0;
+
+  lq_hello->comm.orig = olsr_cnf->main_addr;
+
+  lq_hello->comm.ttl = 1;
+  lq_hello->comm.hops = 0;
+
+  lq_hello->htime = outif->hello_etime;
+  lq_hello->will = olsr_cnf->willingness;
+
+  lq_hello->neigh = NULL;
+  
+  // loop through the link set
+
+  OLSR_FOR_ALL_LINK_ENTRIES(walker) {
+
+    // allocate a neighbour entry
+    struct lq_hello_neighbor *neigh = olsr_malloc_lq_hello_neighbor("Build LQ_HELLO");
+
+    // a) this neighbor interface IS NOT visible via the output interface
+    if(!ipequal(&walker->local_iface_addr, &outif->ip_addr))
+      neigh->link_type = UNSPEC_LINK;
+      
+    // b) this neighbor interface IS visible via the output interface
+
+    else
+      neigh->link_type = lookup_link_status(walker);
+
+    // set the entry's link quality
+    olsr_copy_hello_lq(neigh, walker);
+
+    // set the entry's neighbour type
+
+    if(walker->neighbor->is_mpr)
+      neigh->neigh_type = MPR_NEIGH;
+
+    else if (walker->neighbor->status == SYM)
+      neigh->neigh_type = SYM_NEIGH;
+
+    else if (walker->neighbor->status == NOT_SYM)
+      neigh->neigh_type = NOT_NEIGH;
+        
+    else {
+      OLSR_PRINTF(0, "Error: neigh_type undefined");
+      neigh->neigh_type = NOT_NEIGH;
+    }
+  
+    // set the entry's neighbour interface address
+
+    neigh->addr = walker->neighbor_iface_addr;
+      
+    // queue the neighbour entry
+    neigh->next = lq_hello->neigh;
+    lq_hello->neigh = neigh;
+
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
+}
+
+static void
+destroy_lq_hello(struct lq_hello_message *lq_hello)
+{
+  struct lq_hello_neighbor *walker, *aux;
+
+  // loop through the queued neighbour entries and free them
+
+  for (walker = lq_hello->neigh; walker != NULL; walker = aux)
+    {
+      aux = walker->next;
+      free(walker);
+    }
+
+  lq_hello->neigh = NULL;
+}
+
+static void
+create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
+{
+  struct link_entry *lnk;
+  struct neighbor_entry *walker;
+  struct tc_mpr_addr *neigh;
+  static int ttl_list[] = { 2, 8, 2, 16, 2, 8, 2, MAX_TTL};
+
+  // remember that we have generated an LQ TC message; this is
+  // checked in net_output()
+
+  lq_tc_pending = OLSR_TRUE;
+
+  // initialize the static fields
+
+  lq_tc->comm.type = LQ_TC_MESSAGE;
+  lq_tc->comm.vtime = me_to_reltime(outif->valtimes.tc);
+  lq_tc->comm.size = 0;
+
+  lq_tc->comm.orig = olsr_cnf->main_addr;
+
+  if (olsr_cnf->lq_fish > 0)
+  {
+    if (outif->ttl_index >= (int)(sizeof(ttl_list) / sizeof(ttl_list[0])))
+      outif->ttl_index = 0;
+    
+    lq_tc->comm.ttl = (0 <= outif->ttl_index ? ttl_list[outif->ttl_index] : MAX_TTL);
+    outif->ttl_index++;
+
+    OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
+  }
+
+  else
+    lq_tc->comm.ttl = MAX_TTL;
+
+  lq_tc->comm.hops = 0;
+
+  lq_tc->from = olsr_cnf->main_addr;
+
+  lq_tc->ansn = get_local_ansn();
+
+  lq_tc->neigh = NULL;
+ 
+  OLSR_FOR_ALL_NBR_ENTRIES(walker) {
+
+    /*
+     * TC redundancy 2
+     *
+     * Only consider symmetric neighbours.
+     */
+    if (walker->status != SYM) {
+      continue;
+    }
+
+    /*
+     * TC redundancy 1
+     *
+     * Only consider MPRs and MPR selectors
+     */
+    if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
+        !olsr_lookup_mprs_set(&walker->neighbor_main_addr)) {
+      continue;
+    }
+
+    /*
+     * TC redundancy 0
+     *
+     * Only consider MPR selectors
+     */
+    if (olsr_cnf->tc_redundancy == 0 &&
+        !olsr_lookup_mprs_set(&walker->neighbor_main_addr)) {
+      continue;
+    }
+
+    /* Set the entry's link quality */
+    lnk = get_best_link_to_neighbor(&walker->neighbor_main_addr);
+    if (!lnk) {
+      continue; // no link ?
+    }
+    
+    if (lnk->linkcost >= LINK_COST_BROKEN) {
+      continue; // don't advertise links with very low LQ
+    }
+    
+    /* Allocate a neighbour entry. */
+    neigh = olsr_malloc_tc_mpr_addr("Build LQ_TC");
+
+    /* Set the entry's main address. */
+    neigh->address = walker->neighbor_main_addr;
+
+    if (lnk) {
+      olsr_copylq_link_entry_2_tc_mpr_addr(neigh, lnk);
+    }
+
+    /* Queue the neighbour entry. */
+
+    // TODO: ugly hack until neighbor table is ported to avl tree
+    
+    if (lq_tc->neigh == NULL || avl_comp_default(&lq_tc->neigh->address, &neigh->address) > 0) {
+      neigh->next = lq_tc->neigh;
+      lq_tc->neigh = neigh;
+    }
+    else {
+      struct tc_mpr_addr *last = lq_tc->neigh, *n = last->next;
+      
+      while (n) {
+        if (avl_comp_default(&n->address, &neigh->address) > 0) {
+          break;
+        }
+        last = n;
+        n = n->next;
+      }
+      neigh->next = n;
+      last->next = neigh;
+    }
+
+    // neigh->next = lq_tc->neigh;
+    // lq_tc->neigh = neigh;
+
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(walker);
+}
+
+static void
+destroy_lq_tc(struct lq_tc_message *lq_tc)
+{
+  struct tc_mpr_addr *walker, *aux;
+
+  // loop through the queued neighbour entries and free them
+
+  for (walker = lq_tc->neigh; walker != NULL; walker = aux)
+    {
+      aux = walker->next;
+      free(walker);
+    }
+}
+
+static int common_size(void)
+{
+  // return the size of the header shared by all OLSR messages
+
+  return (olsr_cnf->ip_version == AF_INET) ?
+    sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
+}
+
+static void serialize_common(struct olsr_common *comm)
+{
+  if (olsr_cnf->ip_version == AF_INET)
+    {
+      // serialize an IPv4 OLSR message header
+      struct olsr_header_v4 *olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
+
+      olsr_head_v4->type = comm->type;
+      olsr_head_v4->vtime = reltime_to_me(comm->vtime);
+      olsr_head_v4->size = htons(comm->size);
+
+      olsr_head_v4->orig = comm->orig.v4.s_addr;
+
+      olsr_head_v4->ttl = comm->ttl;
+      olsr_head_v4->hops = comm->hops;
+      olsr_head_v4->seqno = htons(get_msg_seqno());
+    }
+  else
+    {
+      // serialize an IPv6 OLSR message header
+      struct olsr_header_v6 *olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
+
+      olsr_head_v6->type = comm->type;
+      olsr_head_v6->vtime = reltime_to_me(comm->vtime);
+      olsr_head_v6->size = htons(comm->size);
+
+      memcpy(&olsr_head_v6->orig, &comm->orig.v6.s6_addr, sizeof(olsr_head_v6->orig));
+
+      olsr_head_v6->ttl = comm->ttl;
+      olsr_head_v6->hops = comm->hops;
+      olsr_head_v6->seqno = htons(get_msg_seqno());
+    }
+}
+
+static void
+serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
+{
+  static const int LINK_ORDER[] = {SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK};
+  int rem, size, req, expected_size = 0;
+  struct lq_hello_info_header *info_head;
+  struct lq_hello_neighbor *neigh;
+  unsigned char *buff;
+  olsr_bool is_first;
+  int i;
+
+  // leave space for the OLSR header
+  int off = common_size();
+
+  // initialize the LQ_HELLO header
+
+  struct lq_hello_header *head = (struct lq_hello_header *)(msg_buffer + off);
+
+  head->reserved = 0;
+  head->htime = reltime_to_me(lq_hello->htime);
+  head->will = lq_hello->will; 
+
+  // 'off' is the offset of the byte following the LQ_HELLO header
+
+  off += sizeof (struct lq_hello_header);
+
+  // our work buffer starts at 'off'...
+
+  buff = msg_buffer + off;
+
+  // ... that's why we start with a 'size' of 0 and subtract 'off' from
+  // the remaining bytes in the output buffer
+
+  size = 0;
+  rem = net_outbuffer_bytes_left(outif) - off;
+
+  /*
+   * Initially, we want to put the complete lq_hello into the message.
+   * For this flush the output buffer (if there are some bytes in).
+   * This is a hack/fix, which prevents message fragementation resulting
+   * in instable links. The ugly lq/genmsg code should be reworked anyhow.
+   */
+  if (0 < net_output_pending(outif)) {
+    for (i = 0; i <= MAX_NEIGH; i++) {
+      unsigned int j;
+      for(j = 0; j < sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0]); j++) {
+        is_first = OLSR_TRUE;
+        for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next) {
+          if (0 == i && 0 == j) expected_size += olsr_cnf->ipsize + 4;
+          if (neigh->neigh_type == i && neigh->link_type == LINK_ORDER[j]) {
+            if (is_first) {
+              expected_size += sizeof(struct lq_hello_info_header);
+              is_first = OLSR_FALSE;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (rem < expected_size) {
+    net_output(outif);
+    rem = net_outbuffer_bytes_left(outif) - off;
+  }
+
+  info_head = NULL;
+
+  // iterate through all neighbor types ('i') and all link types ('j')
+
+  for (i = 0; i <= MAX_NEIGH; i++) 
+    {
+      unsigned int j;
+      for(j = 0; j < sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0]); j++)
+        {
+          is_first = OLSR_TRUE;
+
+          // loop through neighbors
+
+          for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
+            {  
+              if (neigh->neigh_type != i || neigh->link_type != LINK_ORDER[j])
+                continue;
+
+              // we need space for an IP address plus link quality
+              // information
+
+              req = olsr_cnf->ipsize + 4;
+
+              // no, we also need space for an info header, as this is the
+              // first neighbor with the current neighor type and link type
+
+              if (is_first)
+                req += sizeof (struct lq_hello_info_header);
+
+              // we do not have enough space left
+
+              // force signed comparison
+
+              if ((int)(size + req) > rem)
+                {
+                  // finalize the OLSR header
+
+                  lq_hello->comm.size = size + off;
+
+                  serialize_common(&lq_hello->comm);
+
+                  // finalize the info header
+
+                  info_head->size =
+                    ntohs(buff + size - (unsigned char *)info_head);
+			      
+                  // output packet
+
+                  net_outbuffer_push(outif, msg_buffer, size + off);
+
+                  net_output(outif);
+
+                  // move to the beginning of the buffer
+
+                  size = 0;
+                  rem = net_outbuffer_bytes_left(outif) - off;
+
+                  // we need a new info header
+
+                  is_first = OLSR_TRUE;
+                }
+
+              // create a new info header
+
+              if (is_first)
+                {
+                  info_head = (struct lq_hello_info_header *)(buff + size);
+                  size += sizeof (struct lq_hello_info_header);
+
+                  info_head->reserved = 0;
+                  info_head->link_code = CREATE_LINK_CODE(i, LINK_ORDER[j]);
+                }
+
+              // add the current neighbor's IP address
+
+              genipcopy(buff + size, &neigh->addr);
+              size += olsr_cnf->ipsize;
+
+              // add the corresponding link quality
+              size += olsr_serialize_hello_lq_pair(&buff[size], neigh);
+
+              is_first = OLSR_FALSE;
+            }
+
+          // finalize the info header, if there are any neighbors with the
+          // current neighbor type and link type
+
+          if (!is_first)
+            info_head->size = ntohs(buff + size - (unsigned char *)info_head);
+        }
+    }
+
+  // finalize the OLSR header
+
+  lq_hello->comm.size = size + off;
+
+  serialize_common((struct olsr_common *)lq_hello);
+
+  // move the message to the output buffer
+
+  net_outbuffer_push(outif, msg_buffer, size + off);
+}
+
+static olsr_u8_t
+calculate_border_flag(void *lower_border, void *higher_border) {
+	olsr_u8_t *lower = lower_border;
+	olsr_u8_t *higher = higher_border;
+	olsr_u8_t bitmask;
+	olsr_u8_t part, bitpos;
+	
+	for (part = 0; part < olsr_cnf->ipsize; part ++) {
+		if (lower[part] != higher[part]) {
+			break;
+		}
+	}
+	
+	if (part == olsr_cnf->ipsize) { // same IPs ?
+		return 0;
+	}
+	
+	// look for first bit of difference
+	bitmask = 0xfe;
+	for (bitpos = 0; bitpos < 8; bitpos++, bitmask <<= 1) {
+		if ((lower[part] & bitmask) == (higher[part] & bitmask)) {
+			break;
+		}
+	}
+	
+  bitpos += 8 * (olsr_cnf->ipsize - part - 1);
+	return bitpos + 1;
+}
+
+static void
+serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
+{
+  int off, rem, size, expected_size = 0;
+  struct lq_tc_header *head;
+  struct tc_mpr_addr *neigh;
+  unsigned char *buff;
+
+  union olsr_ip_addr *last_ip = NULL;
+  olsr_u8_t left_border_flag = 0xff;
+  
+  // leave space for the OLSR header
+
+  off = common_size();
+
+  // initialize the LQ_TC header
+
+  head = (struct lq_tc_header *)(msg_buffer + off);
+
+  head->ansn = htons(lq_tc->ansn);
+  head->lower_border = 0;
+  head->upper_border = 0;
+  
+  // 'off' is the offset of the byte following the LQ_TC header
+
+  off += sizeof (struct lq_tc_header);
+
+  // our work buffer starts at 'off'...
+
+  buff = msg_buffer + off;
+
+  // ... that's why we start with a 'size' of 0 and subtract 'off' from
+  // the remaining bytes in the output buffer
+
+  size = 0;
+  rem = net_outbuffer_bytes_left(outif) - off;
+
+  /*
+   * Initially, we want to put the complete lq_tc into the message.
+   * For this flush the output buffer (if there are some bytes in).
+   * This is a hack/fix, which prevents message fragementation resulting
+   * in instable links. The ugly lq/genmsg code should be reworked anyhow.
+   */
+  if (0 < net_output_pending(outif)) {
+    for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next) {
+      // TODO sizeof_tc_lq function required
+      expected_size += olsr_cnf->ipsize + 4;
+    }
+  }
+
+  if (rem < expected_size) {
+    net_output(outif);
+    rem = net_outbuffer_bytes_left(outif) - off;
+  }
+
+  // loop through neighbors
+
+  for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
+    {  
+      // we need space for an IP address plus link quality
+      // information
+
+      // force signed comparison
+
+    // TODO sizeof_tc_lq function required
+      if ((int)(size + olsr_cnf->ipsize + 4) > rem)
+        {
+      	  head->lower_border = left_border_flag;
+      	  head->upper_border = calculate_border_flag(last_ip, &neigh->address);
+      	  left_border_flag = head->upper_border;
+      	  
+          // finalize the OLSR header
+
+          lq_tc->comm.size = size + off;
+
+          serialize_common((struct olsr_common *)lq_tc);
+
+          // output packet
+
+          net_outbuffer_push(outif, msg_buffer, size + off);
+
+          net_output(outif);
+
+          // move to the beginning of the buffer
+
+          size = 0;
+          rem = net_outbuffer_bytes_left(outif) - off;
+        }
+
+      // add the current neighbor's IP address
+      genipcopy(buff + size, &neigh->address);
+      
+      // remember last ip
+      last_ip = (union olsr_ip_addr *)(buff+size);
+      
+      size += olsr_cnf->ipsize;
+
+      // add the corresponding link quality
+      size += olsr_serialize_tc_lq_pair(&buff[size], neigh);
+    }
+
+  // finalize the OLSR header
+
+  head->lower_border = left_border_flag;
+  head->upper_border = 0xff;
+  lq_tc->comm.size = size + off;
+
+  serialize_common((struct olsr_common *)lq_tc);
+
+  net_outbuffer_push(outif, msg_buffer, size + off);
+}
+
+void
+olsr_output_lq_hello(void *para)
+{
+  struct lq_hello_message lq_hello;
+  struct interface *outif = para;
+
+  if (outif == NULL) {
+    return;
+  }
+
+  // create LQ_HELLO in internal format
+  create_lq_hello(&lq_hello, outif);
+
+  // convert internal format into transmission format, send it
+  serialize_lq_hello(&lq_hello, outif);
+
+  // destroy internal format
+  destroy_lq_hello(&lq_hello);
+
+  if (net_output_pending(outif)) {
+    if (outif->immediate_send_tc) {
+      if (TIMED_OUT(outif->fwdtimer))
+        set_buffer_timer(outif);
+    }
+    else {
+      net_output(outif);
+    }
+  }
+}
+
+void
+olsr_output_lq_tc(void *para)
+{
+  static int prev_empty = 1;
+  struct lq_tc_message lq_tc;
+  struct interface *outif = para;
+
+  if (outif == NULL) {
+    return;
+  }
+  // create LQ_TC in internal format
+
+  create_lq_tc(&lq_tc, outif);
+
+  // a) the message is not empty
+
+  if (lq_tc.neigh != NULL) {
+      prev_empty = 0;
+      
+      // convert internal format into transmission format, send it
+      serialize_lq_tc(&lq_tc, outif);
+
+  // b) this is the first empty message
+  } else if (prev_empty == 0) {
+      // initialize timer
+
+      set_empty_tc_timer(GET_TIMESTAMP(olsr_cnf->max_tc_vtime * 3 * MSEC_PER_SEC));
+
+      prev_empty = 1;
+
+      // convert internal format into transmission format, send it
+
+      serialize_lq_tc(&lq_tc, outif);
+
+  // c) this is not the first empty message, send if timer hasn't fired
+  } else if (!TIMED_OUT(get_empty_tc_timer())) {
+      serialize_lq_tc(&lq_tc, outif);
+  }
+  // destroy internal format
+
+  destroy_lq_tc(&lq_tc);
+
+  if (net_output_pending(outif)) {
+    if (!outif->immediate_send_tc) {
+      if (TIMED_OUT(outif->fwdtimer))
+        set_buffer_timer(outif);
+    }
+    else {
+      net_output(outif);
+    }
+  }
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_packet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_packet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_packet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_packet.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,182 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 _OLSR_LQ_PACKET_H
+#define _OLSR_LQ_PACKET_H
+
+#include "olsr_types.h"
+#include "packet.h"
+#include "mantissa.h"
+#include "ipcalc.h"
+
+#define LQ_HELLO_MESSAGE      201
+#define LQ_TC_MESSAGE         202
+
+/* deserialized OLSR header */
+
+struct olsr_common
+{
+  olsr_u8_t          type;
+  olsr_reltime       vtime;
+  olsr_u16_t         size;
+  union olsr_ip_addr orig;
+  olsr_u8_t          ttl;
+  olsr_u8_t          hops;
+  olsr_u16_t         seqno;
+};
+
+/* serialized IPv4 OLSR header */
+
+struct olsr_header_v4
+{
+  olsr_u8_t  type;
+  olsr_u8_t  vtime;
+  olsr_u16_t size;
+  olsr_u32_t orig;
+  olsr_u8_t  ttl;
+  olsr_u8_t  hops;
+  olsr_u16_t seqno;
+};
+
+/* serialized IPv6 OLSR header */
+
+struct olsr_header_v6
+{
+  olsr_u8_t     type;
+  olsr_u8_t     vtime;
+  olsr_u16_t    size;
+  unsigned char orig[16];
+  olsr_u8_t     ttl;
+  olsr_u8_t     hops;
+  olsr_u16_t    seqno;
+};
+
+/* deserialized LQ_HELLO */
+
+struct lq_hello_neighbor
+{
+  olsr_u8_t                link_type;
+  olsr_u8_t                neigh_type;
+  union olsr_ip_addr       addr;
+  struct lq_hello_neighbor *next;
+  olsr_u32_t               linkquality[0];
+};
+
+struct lq_hello_message
+{
+  struct olsr_common       comm;
+  olsr_reltime             htime;
+  olsr_u8_t                will;
+  struct lq_hello_neighbor *neigh;
+};
+
+/* serialized LQ_HELLO */
+
+struct lq_hello_info_header
+{
+  olsr_u8_t  link_code;
+  olsr_u8_t  reserved;
+  olsr_u16_t size;
+};
+
+struct lq_hello_header
+{
+  olsr_u16_t reserved;
+  olsr_u8_t  htime;
+  olsr_u8_t  will;
+};
+
+/* deserialized LQ_TC */
+struct lq_tc_message
+{
+  struct olsr_common    comm;
+  union olsr_ip_addr    from;
+  olsr_u16_t            ansn;
+  struct tc_mpr_addr    *neigh;
+};
+
+/* serialized LQ_TC */
+
+struct lq_tc_header
+{
+  olsr_u16_t ansn;
+  olsr_u8_t lower_border;
+  olsr_u8_t upper_border;
+};
+
+static INLINE void        pkt_get_u8(const olsr_u8_t **p, olsr_u8_t  *var)         { *var =       *(const olsr_u8_t *)(*p);          *p += sizeof(olsr_u8_t); }
+static INLINE void       pkt_get_u16(const olsr_u8_t **p, olsr_u16_t *var)         { *var = ntohs(*(const olsr_u16_t *)(*p));        *p += sizeof(olsr_u16_t); }
+static INLINE void       pkt_get_u32(const olsr_u8_t **p, olsr_u32_t *var)         { *var = ntohl(*(const olsr_u32_t *)(p));         *p += sizeof(olsr_u32_t); }
+static INLINE void        pkt_get_s8(const olsr_u8_t **p, olsr_8_t  *var)          { *var =       *(const olsr_8_t *)(*p);           *p += sizeof(olsr_8_t); }
+static INLINE void       pkt_get_s16(const olsr_u8_t **p, olsr_16_t *var)          { *var = ntohs(*(const olsr_16_t *)(*p));         *p += sizeof(olsr_16_t); }
+static INLINE void       pkt_get_s32(const olsr_u8_t **p, olsr_32_t *var)          { *var = ntohl(*(const olsr_32_t *)(*p));         *p += sizeof(olsr_32_t); }
+static INLINE void   pkt_get_reltime(const olsr_u8_t **p, olsr_reltime *var)       { *var = me_to_reltime(**p);                       *p += sizeof(olsr_u8_t); }
+static INLINE void pkt_get_ipaddress(const olsr_u8_t **p, union olsr_ip_addr *var) { memcpy(var, *p, olsr_cnf->ipsize);              *p += olsr_cnf->ipsize; }
+static INLINE void pkt_get_prefixlen(const olsr_u8_t **p, olsr_u8_t *var)          { *var = netmask_to_prefix(*p, olsr_cnf->ipsize); *p += olsr_cnf->ipsize; }
+
+static INLINE void        pkt_ignore_u8(const olsr_u8_t **p) { *p += sizeof(olsr_u8_t); }
+static INLINE void       pkt_ignore_u16(const olsr_u8_t **p) { *p += sizeof(olsr_u16_t); }
+static INLINE void       pkt_ignore_u32(const olsr_u8_t **p) { *p += sizeof(olsr_u32_t); }
+static INLINE void        pkt_ignore_s8(const olsr_u8_t **p) { *p += sizeof(olsr_8_t); }
+static INLINE void       pkt_ignore_s16(const olsr_u8_t **p) { *p += sizeof(olsr_16_t); }
+static INLINE void       pkt_ignore_s32(const olsr_u8_t **p) { *p += sizeof(olsr_32_t); }
+static INLINE void pkt_ignore_ipaddress(const olsr_u8_t **p) { *p += olsr_cnf->ipsize; }
+static INLINE void pkt_ignore_prefixlen(const olsr_u8_t **p) { *p += olsr_cnf->ipsize; }
+
+static INLINE void        pkt_put_u8(olsr_u8_t **p, olsr_u8_t  var)                { *(olsr_u8_t *)(*p)  = var;          *p += sizeof(olsr_u8_t); }
+static INLINE void       pkt_put_u16(olsr_u8_t **p, olsr_u16_t var)                { *(olsr_u16_t *)(*p) = htons(var);   *p += sizeof(olsr_u16_t); }
+static INLINE void       pkt_put_u32(olsr_u8_t **p, olsr_u32_t var)                { *(olsr_u32_t *)(*p) = htonl(var);   *p += sizeof(olsr_u32_t); }
+static INLINE void        pkt_put_s8(olsr_u8_t **p, olsr_8_t  var)                 { *(olsr_8_t *)(*p)   = var;          *p += sizeof(olsr_8_t); }
+static INLINE void       pkt_put_s16(olsr_u8_t **p, olsr_16_t var)                 { *(olsr_16_t *)(*p)  = htons(var);   *p += sizeof(olsr_16_t); }
+static INLINE void       pkt_put_s32(olsr_u8_t **p, olsr_32_t var)                 { *(olsr_32_t *)(*p)  = htonl(var);   *p += sizeof(olsr_32_t); }
+static INLINE void   pkt_put_reltime(olsr_u8_t **p, olsr_reltime var)              { **p = reltime_to_me(var);           *p += sizeof(olsr_u8_t); }
+static INLINE void pkt_put_ipaddress(olsr_u8_t **p, const union olsr_ip_addr *var) { memcpy(*p, var, olsr_cnf->ipsize); *p += olsr_cnf->ipsize; }
+static INLINE void pkt_put_prefixlen(olsr_u8_t **p, olsr_u8_t var)                 { prefix_to_netmask(*p, olsr_cnf->ipsize, var); *p += olsr_cnf->ipsize; }
+
+void olsr_output_lq_hello(void *para);
+
+void olsr_output_lq_tc(void *para);
+
+void olsr_input_lq_hello(union olsr_message *ser, struct interface *inif,
+                         union olsr_ip_addr *from);
+
+extern olsr_bool lq_tc_pending;
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,496 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 "tc_set.h"
+#include "link_set.h"
+#include "olsr_spf.h"
+#include "lq_packet.h"
+#include "packet.h"
+#include "olsr.h"
+#include "two_hop_neighbor_table.h"
+#include "common/avl.h"
+
+#include "lq_plugin_default_float.h"
+#include "lq_plugin_default_fpm.h"
+#include "lq_plugin_default_ff.h"
+
+struct avl_tree lq_handler_tree;
+struct lq_handler *active_lq_handler = NULL;
+
+int
+avl_strcasecmp(const void *str1, const void *str2)
+{
+  return strcasecmp(str1, str2);
+}
+
+
+void
+init_lq_handler_tree(void)
+{
+  avl_init(&lq_handler_tree, &avl_strcasecmp);
+  register_lq_handler(&lq_etx_float_handler, LQ_ALGORITHM_ETX_FLOAT_NAME);
+  register_lq_handler(&lq_etx_fpm_handler, LQ_ALGORITHM_ETX_FPM_NAME);
+  register_lq_handler(&lq_etx_ff_handler, LQ_ALGORITHM_ETX_FF_NAME);
+  if (activate_lq_handler(olsr_cnf->lq_algorithm)) {
+    activate_lq_handler(LQ_ALGORITHM_ETX_FPM_NAME);
+  }
+}
+
+/*
+ * set_lq_handler
+ * 
+ * this function is used by routing metric plugins to activate their link
+ * quality handler
+ * 
+ * The name parameter is marked as "unused" to squelch a compiler warning if debug
+ * output is not active
+ * 
+ * @param pointer to lq_handler structure
+ * @param name of the link quality handler for debug output
+ */
+void
+register_lq_handler(struct lq_handler *handler, const char *name)
+{
+  struct lq_handler_node *node;
+  size_t name_size = sizeof(*node) + strlen(name) + 1;
+  
+  node = olsr_malloc(name_size, "olsr lq handler");
+   
+  strscpy(node->name, name, name_size);
+  node->node.key = node->name;
+  node->handler = handler;
+  
+  avl_insert(&lq_handler_tree, &node->node, OLSR_FALSE); 
+}
+
+int
+activate_lq_handler(const char *name)
+{
+  struct lq_handler_node *node;
+  if (name == NULL) {
+    return 1;
+  }
+  
+  node = (struct lq_handler_node *) avl_find(&lq_handler_tree, name);
+  if (node == NULL) {
+    OLSR_PRINTF(1, "Error, unknown lq_handler '%s'\n", name);
+    return 1;
+  }
+  
+  OLSR_PRINTF(1, "Using '%s' algorithm for lq calculation.\n", name);
+  active_lq_handler = node->handler;
+  active_lq_handler->initialize();
+  
+  return 0;
+}
+
+/*
+ * olsr_calc_tc_cost
+ * 
+ * this function calculates the linkcost of a tc_edge_entry
+ * 
+ * @param pointer to the tc_edge_entry
+ * @return linkcost
+ */
+olsr_linkcost
+olsr_calc_tc_cost(const struct tc_edge_entry *tc_edge)
+{
+  return active_lq_handler->calc_tc_cost(tc_edge->linkquality);
+}
+
+/*
+ * olsr_is_relevant_costchange
+ * 
+ * decides if the difference between two costs is relevant
+ * (for changing the route for example)
+ * 
+ * @param first linkcost value
+ * @param second linkcost value
+ * @return boolean
+ */
+olsr_bool
+olsr_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2)
+{
+  return active_lq_handler->is_relevant_costchange(c1, c2);
+}
+
+/*
+ * olsr_serialize_hello_lq_pair
+ * 
+ * this function converts the lq information of a lq_hello_neighbor into binary package
+ * format
+ * 
+ * @param pointer to binary buffer to write into
+ * @param pointer to lq_hello_neighbor
+ * @return number of bytes that have been written
+ */
+int
+olsr_serialize_hello_lq_pair(unsigned char *buff,
+			     struct lq_hello_neighbor *neigh)
+{
+  return active_lq_handler->serialize_hello_lq(buff, neigh->linkquality);
+}
+
+/*
+ * olsr_deserialize_hello_lq_pair
+ * 
+ * this function reads the lq information of a binary package into a hello_neighbor
+ * It also initialize the cost variable of the hello_neighbor
+ * 
+ * @param pointer to the current buffer pointer
+ * @param pointer to hello_neighbor
+ */
+void
+olsr_deserialize_hello_lq_pair(const olsr_u8_t ** curr,
+			       struct hello_neighbor *neigh)
+{
+  active_lq_handler->deserialize_hello_lq(curr, neigh->linkquality);
+  neigh->cost = active_lq_handler->calc_hello_cost(neigh->linkquality);
+}
+
+/*
+ * olsr_serialize_tc_lq_pair
+ * 
+ * this function converts the lq information of a olsr_serialize_tc_lq_pair
+ * into binary package format
+ * 
+ * @param pointer to binary buffer to write into
+ * @param pointer to olsr_serialize_tc_lq_pair
+ * @return number of bytes that have been written
+ */
+int
+olsr_serialize_tc_lq_pair(unsigned char *buff, struct tc_mpr_addr *neigh)
+{
+  return active_lq_handler->serialize_tc_lq(buff, neigh->linkquality);
+}
+
+/*
+ * olsr_deserialize_tc_lq_pair
+ * 
+ * this function reads the lq information of a binary package into a tc_edge_entry
+ * 
+ * @param pointer to the current buffer pointer
+ * @param pointer to tc_edge_entry
+ */
+void
+olsr_deserialize_tc_lq_pair(const olsr_u8_t ** curr, struct tc_edge_entry *edge)
+{
+  active_lq_handler->deserialize_tc_lq(curr, edge->linkquality);
+}
+
+/*
+ * olsr_update_packet_loss_worker
+ * 
+ * this function is called every times a hello package for a certain link_entry
+ * is lost (timeout) or received. This way the lq-plugin can update the links link
+ * quality value.
+ * 
+ * @param pointer to link_entry
+ * @param OLSR_TRUE if hello package was lost
+ */
+void
+olsr_update_packet_loss_worker(struct link_entry *entry, olsr_bool lost)
+{
+  olsr_linkcost lq;
+  lq = active_lq_handler->packet_loss_handler(entry, entry->linkquality, lost);
+
+  if (olsr_is_relevant_costchange(lq, entry->linkcost)) {
+    entry->linkcost = lq;
+
+    if (olsr_cnf->lq_dlimit > 0) {
+      changes_neighborhood = OLSR_TRUE;
+      changes_topology = OLSR_TRUE;
+    }
+
+    else
+      OLSR_PRINTF(3, "Skipping Dijkstra (1)\n");
+
+    /* XXX - we should check whether we actually announce this neighbour */
+    signal_link_changes(OLSR_TRUE);
+  }
+}
+
+/*
+ * olsr_memorize_foreign_hello_lq
+ * 
+ * this function is called to copy the link quality information from a received
+ * hello package into a link_entry.
+ * 
+ * @param pointer to link_entry
+ * @param pointer to hello_neighbor, if NULL the neighbor link quality information
+ * of the link entry has to be reset to "zero"
+ */
+void
+olsr_memorize_foreign_hello_lq(struct link_entry *local,
+			       struct hello_neighbor *foreign)
+{
+  if (foreign) {
+    active_lq_handler->memorize_foreign_hello(local->linkquality,
+					      foreign->linkquality);
+  } else {
+    active_lq_handler->memorize_foreign_hello(local->linkquality, NULL);
+  }
+}
+
+/*
+ * get_link_entry_text
+ * 
+ * this function returns the text representation of a link_entry cost value.
+ * It's not thread save and should not be called twice with the same println
+ * value in the same context (a single printf command for example).
+ * 
+ * @param pointer to link_entry
+ * @param char separator between LQ and NLQ 
+ * @param buffer for output
+ * @return pointer to a buffer with the text representation
+ */
+const char *
+get_link_entry_text(struct link_entry *entry, char separator, struct lqtextbuffer *buffer)
+{
+  return active_lq_handler->print_hello_lq(entry->linkquality, separator, buffer);
+}
+
+/*
+ * get_tc_edge_entry_text
+ * 
+ * this function returns the text representation of a tc_edge_entry cost value.
+ * It's not thread save and should not be called twice with the same println
+ * value in the same context (a single printf command for example).
+ * 
+ * @param pointer to tc_edge_entry
+ * @param char separator between LQ and NLQ 
+ * @param pointer to buffer
+ * @return pointer to the buffer with the text representation
+ */
+const char *
+get_tc_edge_entry_text(struct tc_edge_entry *entry, char separator, struct lqtextbuffer *buffer)
+{
+  return active_lq_handler->print_tc_lq(entry->linkquality, separator, buffer);
+}
+
+/*
+ * get_linkcost_text
+ * 
+ * This function transforms an olsr_linkcost value into it's text representation and copies
+ * the result into a buffer.
+ * 
+ * @param linkcost value
+ * @param true to transform the cost of a route, false for a link
+ * @param pointer to buffer
+ * @return pointer to buffer filled with text
+ */
+const char *
+get_linkcost_text(olsr_linkcost cost, olsr_bool route,
+		  struct lqtextbuffer *buffer)
+{
+  static const char *infinite = "INFINITE";
+
+  if (route) {
+    if (cost == ROUTE_COST_BROKEN) {
+      return infinite;
+    }
+  } else {
+    if (cost >= LINK_COST_BROKEN) {
+      return infinite;
+    }
+  }
+  return active_lq_handler->print_cost(cost, buffer);
+}
+
+/*
+ * olsr_copy_hello_lq
+ * 
+ * this function copies the link quality information from a link_entry to a
+ * lq_hello_neighbor.
+ * 
+ * @param pointer to target lq_hello_neighbor
+ * @param pointer to source link_entry
+ */
+void
+olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source)
+{
+  memcpy(target->linkquality, source->linkquality,
+	 active_lq_handler->hello_lq_size);
+}
+
+/*
+ * olsr_copylq_link_entry_2_tc_mpr_addr
+ * 
+ * this function copies the link quality information from a link_entry to a
+ * tc_mpr_addr.
+ * 
+ * @param pointer to tc_mpr_addr
+ * @param pointer to link_entry
+ */
+void
+olsr_copylq_link_entry_2_tc_mpr_addr(struct tc_mpr_addr *target,
+				     struct link_entry *source)
+{
+  active_lq_handler->copy_link_lq_into_tc(target->linkquality,
+					  source->linkquality);
+}
+
+/*
+ * olsr_copylq_link_entry_2_tc_edge_entry
+ * 
+ * this function copies the link quality information from a link_entry to a
+ * tc_edge_entry.
+ * 
+ * @param pointer to tc_edge_entry
+ * @param pointer to link_entry
+ */
+void
+olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target,
+				       struct link_entry *source)
+{
+  active_lq_handler->copy_link_lq_into_tc(target->linkquality,
+					  source->linkquality);
+}
+
+/*
+ * olsr_clear_tc_lq
+ * 
+ * this function resets the linkquality value of a tc_mpr_addr
+ * 
+ * @param pointer to tc_mpr_addr
+ */
+void
+olsr_clear_tc_lq(struct tc_mpr_addr *target)
+{
+  active_lq_handler->clear_tc(target->linkquality);
+}
+
+/*
+ * olsr_malloc_hello_neighbor
+ * 
+ * this function allocates memory for an hello_neighbor inclusive
+ * linkquality data.
+ * 
+ * @param id string for memory debugging
+ * 
+ * @return pointer to hello_neighbor
+ */
+struct hello_neighbor *
+olsr_malloc_hello_neighbor(const char *id)
+{
+  struct hello_neighbor *h;
+
+  h =
+    olsr_malloc(sizeof(struct hello_neighbor) +
+		active_lq_handler->hello_lq_size, id);
+
+  active_lq_handler->clear_hello(h->linkquality);
+  return h;
+}
+
+/*
+ * olsr_malloc_tc_mpr_addr
+ * 
+ * this function allocates memory for an tc_mpr_addr inclusive
+ * linkquality data.
+ * 
+ * @param id string for memory debugging
+ * 
+ * @return pointer to tc_mpr_addr
+ */
+struct tc_mpr_addr *
+olsr_malloc_tc_mpr_addr(const char *id)
+{
+  struct tc_mpr_addr *t;
+
+  t =
+    olsr_malloc(sizeof(struct tc_mpr_addr) + active_lq_handler->tc_lq_size, id);
+
+  active_lq_handler->clear_tc(t->linkquality);
+  return t;
+}
+
+/*
+ * olsr_malloc_lq_hello_neighbor
+ * 
+ * this function allocates memory for an lq_hello_neighbor inclusive
+ * linkquality data.
+ * 
+ * @param id string for memory debugging
+ * 
+ * @return pointer to lq_hello_neighbor
+ */
+struct lq_hello_neighbor *
+olsr_malloc_lq_hello_neighbor(const char *id)
+{
+  struct lq_hello_neighbor *h;
+
+  h =
+    olsr_malloc(sizeof(struct lq_hello_neighbor) +
+		active_lq_handler->hello_lq_size, id);
+
+  active_lq_handler->clear_hello(h->linkquality);
+  return h;
+}
+
+/*
+ * olsr_malloc_link_entry
+ * 
+ * this function allocates memory for an link_entry inclusive
+ * linkquality data.
+ * 
+ * @param id string for memory debugging
+ * 
+ * @return pointer to link_entry
+ */
+struct link_entry *
+olsr_malloc_link_entry(const char *id)
+{
+  struct link_entry *h;
+
+  h =
+    olsr_malloc(sizeof(struct link_entry) + active_lq_handler->hello_lq_size,
+		id);
+
+  active_lq_handler->clear_hello(h->linkquality);
+  return h;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_ff.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_ff.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_ff.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_ff.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,272 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 "tc_set.h"
+#include "link_set.h"
+#include "lq_plugin.h"
+#include "olsr_spf.h"
+#include "lq_packet.h"
+#include "packet.h"
+#include "olsr.h"
+#include "lq_plugin_default_ff.h"
+#include "parser.h"
+#include "fpm.h"
+#include "mid_set.h"
+#include "scheduler.h"
+
+/* etx lq plugin (freifunk fpm version) settings */
+struct lq_handler lq_etx_ff_handler = {
+    &default_lq_initialize_ff,
+    &default_lq_calc_cost_ff,
+    &default_lq_calc_cost_ff,
+
+    &default_lq_is_relevant_costchange_ff,
+    &default_lq_packet_loss_worker_ff,
+
+    &default_lq_memorize_foreign_hello_ff,
+    &default_lq_copy_link2tc_ff,
+    &default_lq_clear_ff_hello,
+    &default_lq_clear_ff,
+
+    &default_lq_serialize_hello_lq_pair_ff,
+    &default_lq_serialize_tc_lq_pair_ff,
+    &default_lq_deserialize_hello_lq_pair_ff,
+    &default_lq_deserialize_tc_lq_pair_ff,
+
+    &default_lq_print_ff,
+    &default_lq_print_ff,
+    &default_lq_print_cost_ff,
+
+    sizeof(struct default_lq_ff_hello),
+    sizeof(struct default_lq_ff)
+};
+
+static void default_lq_parser_ff(struct olsr *olsr, struct interface *in_if, union olsr_ip_addr *from_addr) {
+  const union olsr_ip_addr *main_addr;
+  struct link_entry *lnk;
+  struct default_lq_ff_hello *lq;
+  olsr_u32_t seq_diff;
+
+  /* Find main address */
+  main_addr = mid_lookup_main_addr(from_addr);
+
+  /* Loopup link entry */
+  lnk = lookup_link_entry(from_addr, main_addr, in_if);
+  if (lnk == NULL) {
+    return;
+  }
+
+  lq = (struct default_lq_ff_hello *)lnk->linkquality;
+
+  if (lq->last_seq_nr > olsr->olsr_seqno) {
+    seq_diff = (olsr_u32_t)olsr->olsr_seqno + 65536 - lq->last_seq_nr;
+  } else {
+    seq_diff = olsr->olsr_seqno - lq->last_seq_nr;
+  }
+
+  /* Jump in sequence numbers ? */
+  if (seq_diff > 256) {
+    seq_diff = 1;
+  }
+
+  lq->received[lq->activePtr]++;
+  lq->lost[lq->activePtr] += (seq_diff - 1);
+
+  lq->last_seq_nr = olsr->olsr_seqno;
+}
+
+static void default_lq_ff_timer(void __attribute__((unused)) *context) {
+  struct link_entry *link;
+  OLSR_FOR_ALL_LINK_ENTRIES(link) {
+    struct default_lq_ff_hello *tlq = (struct default_lq_ff_hello *)link->linkquality;
+    fpm ratio;
+    olsr_u16_t i, received, lost;
+
+    received = 0;
+    lost = 0;
+
+    /* enlarge window if still in quickstart phase */
+    if (tlq->windowSize < LQ_FF_WINDOW) {
+      tlq->windowSize++;
+    }
+    for (i=0; i < tlq->windowSize; i++) {
+      received += tlq->received[i];
+      lost += tlq->lost[i];
+    }
+
+    /* calculate link quality */
+    if (received + lost == 0) {
+      tlq->lq.valueLq = 0;
+    }
+    else {
+      // start with link-loss-factor
+      ratio = fpmidiv(itofpm(link->loss_link_multiplier), 65536);
+
+      // calculate received/(received + loss) factor
+      ratio = fpmmuli(ratio, (int)received);
+      ratio = fpmidiv(ratio, (int)(received + lost));
+      ratio = fpmmuli(ratio, 255);
+
+      tlq->lq.valueLq = (olsr_u8_t)(fpmtoi(ratio));
+    }
+    link->linkcost = default_lq_calc_cost_ff(tlq);
+
+    // shift buffer
+    tlq->activePtr = (tlq->activePtr + 1) % LQ_FF_WINDOW;
+    tlq->lost[tlq->activePtr] = 0;
+    tlq->received[tlq->activePtr] = 0;
+  }OLSR_FOR_ALL_LINK_ENTRIES_END(link);
+}
+
+void default_lq_initialize_ff(void) {
+  olsr_packetparser_add_function(&default_lq_parser_ff);
+  olsr_start_timer(1000, 0, OLSR_TIMER_PERIODIC, &default_lq_ff_timer, NULL, 0);
+}
+
+olsr_linkcost default_lq_calc_cost_ff(const void *ptr) {
+  const struct default_lq_ff *lq = ptr;
+  olsr_linkcost cost;
+
+  if (lq->valueLq < (unsigned int)(255 * MINIMAL_USEFUL_LQ) || lq->valueNlq < (unsigned int)(255 * MINIMAL_USEFUL_LQ)) {
+    return LINK_COST_BROKEN;
+  }
+
+  cost = fpmidiv(itofpm(255 * 255), (int)lq->valueLq * (int)lq->valueNlq);
+
+  if (cost > LINK_COST_BROKEN)
+    return LINK_COST_BROKEN;
+  if (cost == 0)
+    return 1;
+  return cost;
+}
+
+int default_lq_serialize_hello_lq_pair_ff(unsigned char *buff, void *ptr) {
+  struct default_lq_ff *lq = ptr;
+
+  buff[0] = (unsigned char)lq->valueLq;
+  buff[1] = (unsigned char)lq->valueNlq;
+  buff[2] = (unsigned char)(0);
+  buff[3] = (unsigned char)(0);
+
+  return 4;
+}
+
+void default_lq_deserialize_hello_lq_pair_ff(const olsr_u8_t **curr, void *ptr) {
+  struct default_lq_ff *lq = ptr;
+
+  pkt_get_u8(curr, &lq->valueLq);
+  pkt_get_u8(curr, &lq->valueNlq);
+  pkt_ignore_u16(curr);
+}
+
+olsr_bool default_lq_is_relevant_costchange_ff(olsr_linkcost c1, olsr_linkcost c2) {
+  if (c1 > c2) {
+    return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FF;
+  }
+  return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FF;
+}
+
+int default_lq_serialize_tc_lq_pair_ff(unsigned char *buff, void *ptr) {
+  struct default_lq_ff *lq = ptr;
+
+  buff[0] = (unsigned char)lq->valueLq;
+  buff[1] = (unsigned char)lq->valueNlq;
+  buff[2] = (unsigned char)(0);
+  buff[3] = (unsigned char)(0);
+
+  return 4;
+}
+
+void default_lq_deserialize_tc_lq_pair_ff(const olsr_u8_t **curr, void *ptr) {
+  struct default_lq_ff *lq = ptr;
+
+  pkt_get_u8(curr, &lq->valueLq);
+  pkt_get_u8(curr, &lq->valueNlq);
+  pkt_ignore_u16(curr);
+}
+
+olsr_linkcost default_lq_packet_loss_worker_ff(struct link_entry __attribute__((unused)) *link, void __attribute__((unused)) *ptr, olsr_bool __attribute__((unused)) lost) {
+  return link->linkcost;
+}
+
+void default_lq_memorize_foreign_hello_ff(void *ptrLocal, void *ptrForeign) {
+  struct default_lq_ff *local = ptrLocal;
+  struct default_lq_ff *foreign = ptrForeign;
+
+  if (foreign) {
+    local->valueNlq = foreign->valueLq;
+  } else {
+    local->valueNlq = 0;
+  }
+}
+
+void default_lq_copy_link2tc_ff(void *target, void *source) {
+  memcpy(target, source, sizeof(struct default_lq_ff));
+}
+
+void default_lq_clear_ff(void *target) {
+  memset(target, 0, sizeof(struct default_lq_ff));
+}
+
+void default_lq_clear_ff_hello(void *target) {
+  struct default_lq_ff_hello *local = target;
+  int i;
+
+  default_lq_clear_ff(&local->lq);
+  local->windowSize = LQ_FF_QUICKSTART_INIT;
+  for (i=0; i<LQ_FF_WINDOW; i++) {
+    local->lost[i] = 3;
+  }
+}
+
+const char *default_lq_print_ff(void *ptr, char separator, struct lqtextbuffer *buffer) {
+  struct default_lq_ff *lq = ptr;
+
+  snprintf(buffer->buf, sizeof(buffer->buf), "%s%c%s",
+      fpmtoa(fpmidiv(itofpm((int)lq->valueLq), 255)),
+      separator,
+      fpmtoa(fpmidiv(itofpm((int)lq->valueNlq), 255)));
+  return buffer->buf;
+}
+
+const char *default_lq_print_cost_ff(olsr_linkcost cost, struct lqtextbuffer *buffer) {
+  snprintf(buffer->buf, sizeof(buffer->buf), "%s", fpmtoa(cost));
+  return buffer->buf;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_ff.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_ff.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_ff.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_ff.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,90 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 LQ_ETX_FF_
+#define LQ_ETX_FF_
+
+#include "olsr_types.h"
+#include "lq_plugin.h"
+
+#define LQ_PLUGIN_LC_MULTIPLIER 1024
+#define LQ_PLUGIN_RELEVANT_COSTCHANGE_FF 16
+
+#define LQ_ALGORITHM_ETX_FF_NAME "etx_ff"
+
+#define LQ_FF_WINDOW 32
+#define LQ_FF_QUICKSTART_INIT 4
+
+struct default_lq_ff {
+  olsr_u8_t valueLq;
+  olsr_u8_t valueNlq;
+};
+
+struct default_lq_ff_hello {
+  struct default_lq_ff lq;
+	olsr_u8_t windowSize, activePtr;
+	olsr_u16_t last_seq_nr;
+	olsr_u16_t received[LQ_FF_WINDOW], lost[LQ_FF_WINDOW];
+};
+
+void default_lq_initialize_ff(void);
+
+olsr_linkcost default_lq_calc_cost_ff(const void *lq);
+
+olsr_bool default_lq_is_relevant_costchange_ff(olsr_linkcost c1, olsr_linkcost c2);
+
+olsr_linkcost default_lq_packet_loss_worker_ff(struct link_entry *link, void *lq, olsr_bool lost);
+void default_lq_memorize_foreign_hello_ff(void *local, void *foreign);
+
+int default_lq_serialize_hello_lq_pair_ff(unsigned char *buff, void *lq);
+void default_lq_deserialize_hello_lq_pair_ff(const olsr_u8_t **curr, void *lq);
+int default_lq_serialize_tc_lq_pair_ff(unsigned char *buff, void *lq);
+void default_lq_deserialize_tc_lq_pair_ff(const olsr_u8_t **curr, void *lq);
+
+void default_lq_copy_link2tc_ff(void *target, void *source);
+void default_lq_clear_ff(void *target);
+void default_lq_clear_ff_hello(void *target);
+
+const char *default_lq_print_ff(void *ptr, char separator, struct lqtextbuffer *buffer);
+const char *default_lq_print_cost_ff(olsr_linkcost cost, struct lqtextbuffer *buffer);
+
+extern struct lq_handler lq_etx_ff_handler;
+
+#endif /*LQ_ETX_FF_*/
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_float.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_float.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_float.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_float.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,203 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 "tc_set.h"
+#include "link_set.h"
+#include "olsr_spf.h"
+#include "lq_packet.h"
+#include "packet.h"
+#include "olsr.h"
+#include "lq_plugin_default_float.h"
+
+/* Default lq plugin settings */
+struct lq_handler lq_etx_float_handler = {
+  &default_lq_initialize_float,
+  
+  &default_lq_calc_cost_float,
+  &default_lq_calc_cost_float,
+
+  &default_lq_is_relevant_costchange_float,
+
+  &default_lq_packet_loss_worker_float,
+  &default_lq_memorize_foreign_hello_float,
+  &default_lq_copy_link2tc_float,
+  &default_lq_clear_float,
+  &default_lq_clear_float,
+
+  &default_lq_serialize_hello_lq_pair_float,
+  &default_lq_serialize_tc_lq_pair_float,
+  &default_lq_deserialize_hello_lq_pair_float,
+  &default_lq_deserialize_tc_lq_pair_float,
+
+  &default_lq_print_float,
+  &default_lq_print_float,
+  &default_lq_print_cost_float,
+
+  sizeof(struct default_lq_float),
+  sizeof(struct default_lq_float)
+};
+
+void default_lq_initialize_float(void) {
+  return;
+}
+
+olsr_linkcost default_lq_calc_cost_float(const void *ptr) {
+  const struct default_lq_float *lq = ptr;
+  olsr_linkcost cost;
+  
+  if (lq->lq < MINIMAL_USEFUL_LQ || lq->nlq < MINIMAL_USEFUL_LQ) {
+    return LINK_COST_BROKEN;
+  }
+  
+  cost = (olsr_linkcost)(1.0/(lq->lq * lq->nlq) * LQ_PLUGIN_LC_MULTIPLIER);
+  
+  if (cost > LINK_COST_BROKEN)
+    return LINK_COST_BROKEN;
+  if (cost == 0) {
+    return 1;
+  }
+  return cost;
+}
+
+int default_lq_serialize_hello_lq_pair_float(unsigned char *buff, void *ptr) {
+  struct default_lq_float *lq = ptr;
+  
+  buff[0] = (unsigned char)(lq->lq * 255);
+  buff[1] = (unsigned char)(lq->nlq * 255);
+  buff[2] = 0;
+  buff[3] = 0;
+  
+  return 4;
+}
+
+void default_lq_deserialize_hello_lq_pair_float(const olsr_u8_t **curr, void *ptr) {
+  struct default_lq_float *lq = ptr;
+  olsr_u8_t lq_value, nlq_value;
+  
+  pkt_get_u8(curr, &lq_value);
+  pkt_get_u8(curr, &nlq_value);
+  pkt_ignore_u16(curr);
+  
+  lq->lq = (float)lq_value / 255.0;
+  lq->nlq = (float)nlq_value / 255.0;
+}
+
+olsr_bool default_lq_is_relevant_costchange_float(olsr_linkcost c1, olsr_linkcost c2) {
+  if (c1 > c2) {
+    return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
+  }
+  return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE;
+}
+
+int default_lq_serialize_tc_lq_pair_float(unsigned char *buff, void *ptr) {
+  struct default_lq_float *lq = ptr;
+  
+  buff[0] = (unsigned char)(lq->lq * 255);
+  buff[1] = (unsigned char)(lq->nlq * 255);
+  buff[2] = 0;
+  buff[3] = 0;
+  
+  return 4;
+}
+
+void default_lq_deserialize_tc_lq_pair_float(const olsr_u8_t **curr, void *ptr) {
+  struct default_lq_float *lq = ptr;
+  olsr_u8_t lq_value, nlq_value;
+  
+  pkt_get_u8(curr, &lq_value);
+  pkt_get_u8(curr, &nlq_value);
+  pkt_ignore_u16(curr);
+  
+  lq->lq = (float)lq_value / 255.0;
+  lq->nlq = (float)nlq_value / 255.0;
+}
+
+olsr_linkcost default_lq_packet_loss_worker_float(struct link_entry *link, void *ptr, olsr_bool lost) {
+  struct default_lq_float *tlq = ptr;
+  float alpha = olsr_cnf->lq_aging;
+  
+  if (tlq->quickstart < LQ_QUICKSTART_STEPS) {
+    alpha = LQ_QUICKSTART_AGING; /* fast enough to get the LQ value within 6 Hellos up to 0.9 */
+    tlq->quickstart++;
+  }
+  // exponential moving average
+  tlq->lq *= (1 - alpha);
+  if (lost == 0) {
+    tlq->lq += (alpha * link->loss_link_multiplier / 65536);
+  }
+  return default_lq_calc_cost_float(ptr);
+}
+
+void default_lq_memorize_foreign_hello_float(void *ptrLocal, void *ptrForeign) {
+  struct default_lq_float *local = ptrLocal;
+  struct default_lq_float *foreign = ptrForeign;
+  
+  if (foreign) {
+    local->nlq = foreign->lq;
+  }
+  else {
+    local->nlq = 0;
+  }
+}
+
+void default_lq_copy_link2tc_float(void *target, void *source) {
+  memcpy(target, source, sizeof(struct default_lq_float));
+}
+
+void default_lq_clear_float(void *target) {
+  memset(target, 0, sizeof(struct default_lq_float));
+}
+
+const char *default_lq_print_float(void *ptr, char separator, struct lqtextbuffer *buffer) {
+  struct default_lq_float *lq = ptr;
+  
+  snprintf(buffer->buf, sizeof(struct lqtextbuffer), "%2.3f%c%2.3f",
+      lq->lq,
+      separator,
+      lq->nlq);
+  return buffer->buf;
+}
+
+const char *default_lq_print_cost_float(olsr_linkcost cost, struct lqtextbuffer *buffer) {
+  snprintf(buffer->buf, sizeof(struct lqtextbuffer), "%2.3f", ((float)cost)/LQ_PLUGIN_LC_MULTIPLIER );
+	
+
+  return buffer->buf;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_float.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_float.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_float.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_float.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,78 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 LQ_PLUGIN_DEFAULT_H_
+#define LQ_PLUGIN_DEFAULT_H_
+
+#include "olsr_types.h"
+#include "lq_plugin.h"
+
+#define LQ_ALGORITHM_ETX_FLOAT_NAME "etx_float"
+
+#define LQ_PLUGIN_LC_MULTIPLIER 1024
+
+struct default_lq_float {
+  float lq, nlq;
+  olsr_u16_t quickstart;
+};
+
+void default_lq_initialize_float(void);
+
+olsr_linkcost default_lq_calc_cost_float(const void *lq);
+
+olsr_bool default_lq_is_relevant_costchange_float(olsr_linkcost c1, olsr_linkcost c2);
+
+olsr_linkcost default_lq_packet_loss_worker_float(struct link_entry *link, void *lq, olsr_bool lost);
+void default_lq_memorize_foreign_hello_float(void *local, void *foreign);
+
+int default_lq_serialize_hello_lq_pair_float(unsigned char *buff, void *lq);
+void default_lq_deserialize_hello_lq_pair_float(const olsr_u8_t **curr, void *lq);
+int default_lq_serialize_tc_lq_pair_float(unsigned char *buff, void *lq);
+void default_lq_deserialize_tc_lq_pair_float(const olsr_u8_t **curr, void *lq);
+
+void default_lq_copy_link2tc_float(void *target, void *source);
+void default_lq_clear_float(void *target);
+
+const char *default_lq_print_float(void *ptr, char separator, struct lqtextbuffer *buffer);
+const char *default_lq_print_cost_float(olsr_linkcost cost, struct lqtextbuffer *buffer);
+
+extern struct lq_handler lq_etx_float_handler;
+
+#endif /*LQ_PLUGIN_DEFAULT_H_*/
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_fpm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_fpm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_fpm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_fpm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,214 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 "tc_set.h"
+#include "link_set.h"
+#include "lq_plugin.h"
+#include "olsr_spf.h"
+#include "lq_packet.h"
+#include "packet.h"
+#include "olsr.h"
+#include "lq_plugin_default_fpm.h"
+
+/* etx lq plugin (fpm version) settings */
+struct lq_handler lq_etx_fpm_handler = {
+    &default_lq_initialize_fpm,
+    
+    &default_lq_calc_cost_fpm,
+    &default_lq_calc_cost_fpm,
+    
+    &default_lq_is_relevant_costchange_fpm,
+    
+    &default_lq_packet_loss_worker_fpm,
+    &default_lq_memorize_foreign_hello_fpm,
+    &default_lq_copy_link2tc_fpm,
+    &default_lq_clear_fpm,
+    &default_lq_clear_fpm,
+    
+    &default_lq_serialize_hello_lq_pair_fpm,
+    &default_lq_serialize_tc_lq_pair_fpm,
+    &default_lq_deserialize_hello_lq_pair_fpm,
+    &default_lq_deserialize_tc_lq_pair_fpm,
+    
+    &default_lq_print_fpm,
+    &default_lq_print_fpm,
+    &default_lq_print_cost_fpm, 
+    
+    sizeof(struct default_lq_fpm),
+    sizeof(struct default_lq_fpm)
+};
+
+olsr_u32_t aging_factor_new, aging_factor_old;
+olsr_u32_t aging_quickstart_new, aging_quickstart_old;
+
+void default_lq_initialize_fpm(void) {
+  aging_factor_new = (olsr_u32_t)(olsr_cnf->lq_aging * LQ_FPM_INTERNAL_MULTIPLIER);
+  aging_factor_old = LQ_FPM_INTERNAL_MULTIPLIER - aging_factor_new;
+  
+  aging_quickstart_new = (olsr_u32_t)(LQ_QUICKSTART_AGING * LQ_FPM_INTERNAL_MULTIPLIER);
+  aging_quickstart_old = LQ_FPM_INTERNAL_MULTIPLIER - aging_quickstart_new;
+}
+
+olsr_linkcost default_lq_calc_cost_fpm(const void *ptr) {
+  const struct default_lq_fpm *lq = ptr;
+  olsr_linkcost cost;
+  
+  if (lq->valueLq < (unsigned int)(255 * MINIMAL_USEFUL_LQ) || lq->valueNlq < (unsigned int)(255 * MINIMAL_USEFUL_LQ)) {
+    return LINK_COST_BROKEN;
+  }
+  
+  cost = LQ_FPM_LINKCOST_MULTIPLIER * 255/(int)lq->valueLq * 255/(int)lq->valueNlq;
+
+  if (cost > LINK_COST_BROKEN)
+    return LINK_COST_BROKEN;
+  if (cost == 0)
+    return 1;
+  return cost;
+}
+
+int default_lq_serialize_hello_lq_pair_fpm(unsigned char *buff, void *ptr) {
+  struct default_lq_fpm *lq = ptr;
+  
+  buff[0] = (unsigned char)lq->valueLq;
+  buff[1] = (unsigned char)lq->valueNlq;
+  buff[2] = (unsigned char)(0);
+  buff[3] = (unsigned char)(0);
+  
+  return 4;
+}
+
+void default_lq_deserialize_hello_lq_pair_fpm(const olsr_u8_t **curr, void *ptr) {
+  struct default_lq_fpm *lq = ptr;
+  
+  pkt_get_u8(curr, &lq->valueLq);
+  pkt_get_u8(curr, &lq->valueNlq);
+  pkt_ignore_u16(curr);
+}
+
+olsr_bool default_lq_is_relevant_costchange_fpm(olsr_linkcost c1, olsr_linkcost c2) {
+  if (c1 > c2) {
+    return c2 - c1 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FPM;
+  }
+  return c1 - c2 > LQ_PLUGIN_RELEVANT_COSTCHANGE_FPM;
+}
+
+int default_lq_serialize_tc_lq_pair_fpm(unsigned char *buff, void *ptr) {
+  struct default_lq_fpm *lq = ptr;
+  
+  buff[0] = (unsigned char)lq->valueLq;
+  buff[1] = (unsigned char)lq->valueNlq;
+  buff[2] = (unsigned char)(0);
+  buff[3] = (unsigned char)(0);
+  
+  return 4;
+}
+
+void default_lq_deserialize_tc_lq_pair_fpm(const olsr_u8_t **curr, void *ptr) {
+  struct default_lq_fpm *lq = ptr;
+  
+  pkt_get_u8(curr, &lq->valueLq);
+  pkt_get_u8(curr, &lq->valueNlq);
+  pkt_ignore_u16(curr);
+}
+
+olsr_linkcost default_lq_packet_loss_worker_fpm(struct link_entry *link, void *ptr, olsr_bool lost) {
+  struct default_lq_fpm *tlq = ptr;
+  olsr_u32_t alpha_old = aging_factor_old;
+  olsr_u32_t alpha_new = aging_factor_new;
+  
+  olsr_u32_t value;
+  // fpm link_loss_factor = fpmidiv(itofpm(link->loss_link_multiplier), 65536);
+  
+  if (tlq->quickstart < LQ_QUICKSTART_STEPS) {
+    alpha_new = aging_quickstart_new;
+    alpha_old = aging_quickstart_old;
+    tlq->quickstart++;
+  }
+
+  // exponential moving average
+  value = (olsr_u32_t)(tlq->valueLq) * LQ_FPM_INTERNAL_MULTIPLIER / 255;
+
+  value = (value * alpha_old + LQ_FPM_INTERNAL_MULTIPLIER-1) / LQ_FPM_INTERNAL_MULTIPLIER;
+  
+  if (!lost) {
+    olsr_u32_t ratio;
+    
+    ratio = (alpha_new * link->loss_link_multiplier + LINK_LOSS_MULTIPLIER-1) / LINK_LOSS_MULTIPLIER;
+    value += ratio;
+  }
+  tlq->valueLq = (value * 255 + LQ_FPM_INTERNAL_MULTIPLIER-1) / LQ_FPM_INTERNAL_MULTIPLIER;
+  
+  return default_lq_calc_cost_fpm(ptr);
+}
+
+void default_lq_memorize_foreign_hello_fpm(void *ptrLocal, void *ptrForeign) {
+  struct default_lq_fpm *local = ptrLocal;
+  struct default_lq_fpm *foreign = ptrForeign;
+  
+  if (foreign) {
+    local->valueNlq = foreign->valueLq;
+  }
+  else {
+    local->valueNlq = 0;
+  }
+}
+
+void default_lq_copy_link2tc_fpm(void *target, void *source) {
+  memcpy(target, source, sizeof(struct default_lq_fpm));
+}
+
+void default_lq_clear_fpm(void *target) {
+  memset(target, 0, sizeof(struct default_lq_fpm));
+}
+
+const char *default_lq_print_fpm(void *ptr, char separator, struct lqtextbuffer *buffer) {
+  struct default_lq_fpm *lq = ptr;
+  
+  snprintf(buffer->buf, sizeof(buffer->buf), "%0.3f%c%0.3f",
+      (float)(lq->valueLq) / 255.0,
+      separator,
+      (float)(lq->valueNlq) / 255.0);
+  return buffer->buf;
+}
+
+const char *default_lq_print_cost_fpm(olsr_linkcost cost, struct lqtextbuffer *buffer) {
+  snprintf(buffer->buf, sizeof(buffer->buf), "%.3f", (float)(cost) / LQ_FPM_LINKCOST_MULTIPLIER);
+  return buffer->buf;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_fpm.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_fpm.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin_default_fpm.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin_default_fpm.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,84 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 LQ_ETX_FPM_
+#define LQ_ETX_FPM_
+
+#include "olsr_types.h"
+#include "lq_plugin.h"
+
+/* use only 1<<16 - 1 to allow the multiplication of two
+ * upscaled numbers between 0 and 1 */
+#define LQ_FPM_INTERNAL_MULTIPLIER 65535
+#define LQ_FPM_LINKCOST_MULTIPLIER 65535
+
+#define LQ_PLUGIN_RELEVANT_COSTCHANGE_FPM 64
+
+#define LQ_ALGORITHM_ETX_FPM_NAME "etx_fpm"
+
+struct default_lq_fpm {
+	olsr_u8_t valueLq;
+	olsr_u8_t valueNlq;
+	olsr_u16_t quickstart;
+};
+
+void default_lq_initialize_fpm(void);
+
+olsr_linkcost default_lq_calc_cost_fpm(const void *lq);
+
+olsr_bool default_lq_is_relevant_costchange_fpm(olsr_linkcost c1, olsr_linkcost c2);
+
+olsr_linkcost default_lq_packet_loss_worker_fpm(struct link_entry *link, void *lq, olsr_bool lost);
+void default_lq_memorize_foreign_hello_fpm(void *local, void *foreign);
+
+int default_lq_serialize_hello_lq_pair_fpm(unsigned char *buff, void *lq);
+void default_lq_deserialize_hello_lq_pair_fpm(const olsr_u8_t **curr, void *lq);
+int default_lq_serialize_tc_lq_pair_fpm(unsigned char *buff, void *lq);
+void default_lq_deserialize_tc_lq_pair_fpm(const olsr_u8_t **curr, void *lq);
+
+void default_lq_copy_link2tc_fpm(void *target, void *source);
+void default_lq_clear_fpm(void *target);
+
+const char *default_lq_print_fpm(void *ptr, char separator, struct lqtextbuffer *buffer);
+const char *default_lq_print_cost_fpm(olsr_linkcost cost, struct lqtextbuffer *buffer);
+
+extern struct lq_handler lq_etx_fpm_handler;
+
+#endif /*LQ_ETX_FPM_*/
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/lq_plugin.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/lq_plugin.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,164 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008 Henning Rogge <rogge@fgan.de>
+ * 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 LQPLUGIN_H_
+#define LQPLUGIN_H_
+
+#include "tc_set.h"
+#include "link_set.h"
+#include "olsr_spf.h"
+#include "lq_packet.h"
+#include "packet.h"
+#include "common/avl.h"
+
+#define LINK_COST_BROKEN (1<<22)
+#define ROUTE_COST_BROKEN (0xffffffff)
+#define ZERO_ROUTE_COST 0
+
+#define MINIMAL_USEFUL_LQ 0.1
+#define LQ_PLUGIN_RELEVANT_COSTCHANGE 16
+
+#define LQ_QUICKSTART_STEPS 12
+#define LQ_QUICKSTART_AGING 0.25
+
+struct lqtextbuffer {
+  char buf[16];
+};
+
+struct lq_handler {
+  void (*initialize)(void);
+  
+  olsr_linkcost(*calc_hello_cost) (const void *lq);
+  olsr_linkcost(*calc_tc_cost) (const void *lq);
+
+  olsr_bool(*is_relevant_costchange) (olsr_linkcost c1, olsr_linkcost c2);
+
+  olsr_linkcost(*packet_loss_handler) (struct link_entry * entry, void *lq,
+				       olsr_bool lost);
+
+  void (*memorize_foreign_hello) (void *local, void *foreign);
+  void (*copy_link_lq_into_tc) (void *target, void *source);
+  void (*clear_hello) (void *target);
+  void (*clear_tc) (void *target);
+
+  int (*serialize_hello_lq) (unsigned char *buff, void *lq);
+  int (*serialize_tc_lq) (unsigned char *buff, void *lq);
+  void (*deserialize_hello_lq) (const olsr_u8_t ** curr, void *lq);
+  void (*deserialize_tc_lq) (const olsr_u8_t ** curr, void *lq);
+
+  const char *(*print_hello_lq) (void *ptr, char separator, struct lqtextbuffer * buffer);
+  const char *(*print_tc_lq) (void *ptr, char separator, struct lqtextbuffer * buffer);
+  const char *(*print_cost) (olsr_linkcost cost, struct lqtextbuffer * buffer);
+
+  size_t hello_lq_size;
+  size_t tc_lq_size;
+};
+
+struct lq_handler_node {
+  struct avl_node node;
+  struct lq_handler *handler; 
+  char name[0];
+};
+
+AVLNODE2STRUCT(lq_handler_tree2lq_handler_node, struct lq_handler_node, node);
+
+#define OLSR_FOR_ALL_LQ_HANDLERS(lq) \
+{ \
+  struct avl_node *lq_tree_node, *next_lq_tree_node; \
+  for (lq_tree_node = avl_walk_first(&lq_handler_tree); \
+    lq_tree_node; lq_tree_node = next_lq_tree_node) { \
+    next_lq_tree_node = avl_walk_next(lq_tree_node); \
+    lq = lq_handler_tree2lq_handler_node(lq_tree_node);
+#define OLSR_FOR_ALL_LQ_HANDLERS_END(tc) }}
+
+int avl_strcasecmp(const void *str1, const void *str2);
+void init_lq_handler_tree(void);
+
+void register_lq_handler(struct lq_handler *handler, const char *name);
+int activate_lq_handler(const char *name);
+
+olsr_linkcost olsr_calc_tc_cost(const struct tc_edge_entry *);
+olsr_bool olsr_is_relevant_costchange(olsr_linkcost c1, olsr_linkcost c2);
+
+int olsr_serialize_hello_lq_pair(unsigned char *buff,
+				 struct lq_hello_neighbor *neigh);
+void olsr_deserialize_hello_lq_pair(const olsr_u8_t ** curr,
+				    struct hello_neighbor *neigh);
+int olsr_serialize_tc_lq_pair(unsigned char *buff, struct tc_mpr_addr *neigh);
+void olsr_deserialize_tc_lq_pair(const olsr_u8_t ** curr,
+				 struct tc_edge_entry *edge);
+
+void olsr_update_packet_loss_worker(struct link_entry *entry, olsr_bool lost);
+void olsr_memorize_foreign_hello_lq(struct link_entry *local,
+				    struct hello_neighbor *foreign);
+
+const char *get_link_entry_text(struct link_entry *entry,
+				char separator,
+				struct lqtextbuffer *buffer);
+const char *get_tc_edge_entry_text(struct tc_edge_entry *entry,
+				   char separator,
+				   struct lqtextbuffer *buffer);
+const char *get_linkcost_text(olsr_linkcost cost, olsr_bool route,
+			      struct lqtextbuffer *buffer);
+
+void olsr_copy_hello_lq(struct lq_hello_neighbor *target,
+			struct link_entry *source);
+void olsr_copylq_link_entry_2_tc_mpr_addr(struct tc_mpr_addr *target,
+					  struct link_entry *source);
+void olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target,
+					    struct link_entry *source);
+void olsr_clear_tc_lq(struct tc_mpr_addr *target);
+
+struct hello_neighbor *olsr_malloc_hello_neighbor(const char *id);
+struct tc_mpr_addr *olsr_malloc_tc_mpr_addr(const char *id);
+struct lq_hello_neighbor *olsr_malloc_lq_hello_neighbor(const char *id);
+struct link_entry *olsr_malloc_link_entry(const char *id);
+
+/* Externals. */
+extern struct lq_handler *active_lq_handler;
+
+#endif /*LQPLUGIN_H_ */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/main.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/main.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/main.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/main.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,909 @@
+/*
+ * 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 <unistd.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+#include "ipcalc.h"
+#include "defs.h"
+#include "olsr.h"
+#include "log.h"
+#include "scheduler.h"
+#include "parser.h"
+#include "generate_msg.h"
+#include "plugin_loader.h"
+#include "socket_parser.h"
+#include "apm.h"
+#include "net_os.h"
+#include "build_msg.h"
+#include "net_olsr.h"
+
+#if LINUX_POLICY_ROUTING
+#include <linux/types.h>
+#include <linux/rtnetlink.h>
+#include <fcntl.h>
+#endif
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+int __stdcall SignalHandler(unsigned long signal) __attribute__((noreturn));
+void ListInterfaces(void);
+void DisableIcmpRedirects(void);
+olsr_bool olsr_win32_end_request = OLSR_FALSE;
+olsr_bool olsr_win32_end_flag = OLSR_FALSE;
+#else
+static void
+olsr_shutdown(int) __attribute__((noreturn));
+#endif
+
+/*
+ * Local function prototypes
+ */
+void
+olsr_reconfigure(int) __attribute__((noreturn));
+
+static void
+print_usage(void);
+
+static int
+set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
+
+static int
+olsr_process_arguments(int, char *[], 
+		       struct olsrd_config *, 
+		       struct if_config_options *);
+
+#ifndef WIN32
+static char **olsr_argv;
+#endif
+
+static char copyright_string[] __attribute__((unused)) = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org) All rights reserved.";
+
+
+/**
+ * Main entrypoint
+ */
+
+int
+main(int argc, char *argv[])
+{
+  struct if_config_options *default_ifcnf;
+  char conf_file_name[FILENAME_MAX];
+  struct ipaddr_str buf;
+#ifdef WIN32
+  WSADATA WsaData;
+  size_t len;
+#endif
+
+  /* paranoia checks */
+  assert(sizeof(olsr_u8_t) == 1);
+  assert(sizeof(olsr_u16_t) == 2);
+  assert(sizeof(olsr_u32_t) == 4);
+  assert(sizeof(olsr_8_t) == 1);
+  assert(sizeof(olsr_16_t) == 2);
+  assert(sizeof(olsr_32_t) == 4);
+
+  debug_handle = stdout;
+#ifndef WIN32
+  olsr_argv = argv;
+#endif
+  setbuf(stdout, NULL);
+  setbuf(stderr, NULL);
+
+#ifndef WIN32
+  /* Check if user is root */
+  if(geteuid())
+    {
+      fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
+      exit(EXIT_FAILURE);
+    }
+#else
+  DisableIcmpRedirects();
+
+  if (WSAStartup(0x0202, &WsaData))
+    {
+      fprintf(stderr, "Could not initialize WinSock.\n");
+      olsr_exit(__func__, EXIT_FAILURE);
+    }
+#endif
+
+  /* Open syslog */
+  olsr_openlog("olsrd");
+
+  /* Grab initial timestamp */
+  now_times = olsr_times();
+    
+  printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", 
+	 olsrd_version, 
+	 build_date,
+         build_host);
+    
+  /* Using PID as random seed */
+  srandom(getpid());
+
+  /* Init widely used statics */
+  memset(&all_zero, 0, sizeof(union olsr_ip_addr));
+
+  /*
+   * Set configfile name and
+   * check if a configfile name was given as parameter
+   */
+#ifdef WIN32
+#ifndef WINCE
+  GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
+#else
+  conf_file_name[0] = 0;
+#endif
+  
+  len = strlen(conf_file_name);
+  
+  if (len == 0 || conf_file_name[len - 1] != '\\')
+    conf_file_name[len++] = '\\';
+  
+  strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
+#else
+  strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
+#endif
+
+  if ((argc > 1) && (strcmp(argv[1], "-f") == 0)) 
+    {
+      struct stat statbuf;
+
+      argv++; argc--;
+      if(argc == 1)
+	{
+	  fprintf(stderr, "You must provide a filename when using the -f switch!\n");
+	  exit(EXIT_FAILURE);
+	}
+
+      if (stat(argv[1], &statbuf) < 0)
+	{
+	  fprintf(stderr, "Could not find specified config file %s!\n%s\n\n", argv[1], strerror(errno));
+	  exit(EXIT_FAILURE);
+	}
+		 
+      strscpy(conf_file_name, argv[1], sizeof(conf_file_name));
+      argv++; argc--;
+
+    }
+
+  /*
+   * set up configuration prior to processing commandline options
+   */
+  if(NULL == (olsr_cnf = olsrd_parse_cnf(conf_file_name)))
+    {
+      printf("Using default config values(no configfile)\n");
+      olsr_cnf = olsrd_get_default_cnf();
+    }
+
+  default_ifcnf = get_default_if_config();
+  if (default_ifcnf == NULL) {
+    fprintf(stderr, "No default ifconfig found!\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* Initialize tick resolution */
+#ifndef WIN32
+  olsr_cnf->system_tick_divider = 1000/sysconf(_SC_CLK_TCK);
+#else
+  olsr_cnf->system_tick_divider = 1;
+#endif
+
+  /* Initialize timers */
+  olsr_init_timers();
+
+  /*
+   * Process olsrd options.
+   */
+  if(olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0)
+    {
+      print_usage();
+      olsr_exit(__func__, EXIT_FAILURE);
+    }
+
+  /*
+   * Set configuration for command-line specified interfaces
+   */
+  set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
+
+  /* free the default ifcnf */
+  free(default_ifcnf);
+
+  /* Sanity check configuration */
+  if(olsrd_sanity_check_cnf(olsr_cnf) < 0)
+    {
+      fprintf(stderr, "Bad configuration!\n");
+      olsr_exit(__func__, EXIT_FAILURE);      
+    }
+
+  /*
+   * Print configuration 
+   */
+  if(olsr_cnf->debug_level > 1) {
+    olsrd_print_cnf(olsr_cnf);
+  }
+#ifndef WIN32
+  /* Disable redirects globally */
+  disable_redirects_global(olsr_cnf->ip_version);
+#endif
+
+  /*
+   * socket for ioctl calls
+   */
+  olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
+  if (olsr_cnf->ioctl_s < 0) {
+    olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
+    olsr_exit(__func__, 0);
+  }
+
+#if LINUX_POLICY_ROUTING
+  olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+  if (olsr_cnf->rtnl_s < 0) {
+    olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
+    olsr_exit(__func__, 0);
+  }
+  fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
+#endif
+
+/*
+ * create routing socket
+ */
+#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
+  olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
+  if (olsr_cnf->rts < 0) {
+    olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
+    olsr_exit(__func__, 0);
+  }
+#endif
+
+  /* Init empty TC timer */
+  set_empty_tc_timer(GET_TIMESTAMP(0));
+
+  /*
+   *enable ip forwarding on host
+   */
+  enable_ip_forwarding(olsr_cnf->ip_version);
+
+  /* Initialize parser */
+  olsr_init_parser();
+
+  /* Initialize route-exporter */
+  olsr_init_export_route();
+
+  /* Initialize message sequencnumber */
+  init_msg_seqno();
+
+  /* Initialize dynamic willingness calculation */
+  olsr_init_willingness();
+
+  /*
+   *Set up willingness/APM
+   */
+  if(olsr_cnf->willingness_auto)
+    {
+      if(apm_init() < 0)
+	{
+	  OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
+
+	  olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
+
+	  olsr_cnf->willingness_auto = 0;
+	  olsr_cnf->willingness = WILL_DEFAULT;
+	}
+      else
+	{
+	  olsr_cnf->willingness = olsr_calculate_willingness();
+
+	  OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
+	}
+    }
+
+  /* Initialize net */
+  init_net();
+
+  /* Initializing networkinterfaces */
+  if(!ifinit())
+    {
+      if(olsr_cnf->allow_no_interfaces)
+	{
+	  fprintf(stderr, "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
+	  sleep(5);
+	}
+      else
+	{
+	  fprintf(stderr, "No interfaces detected!\nBailing out!\n");
+	  olsr_exit(__func__, EXIT_FAILURE);
+	}
+    }
+
+  /* Print heartbeat to stdout */
+
+#if !defined WINCE
+  if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
+    olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
+                     &generate_stdout_pulse, NULL, 0);
+  }
+#endif
+
+  /* Initialize the IPC socket */
+
+  if (olsr_cnf->ipc_connections > 0) {
+      ipc_init();
+  }
+  /* Initialisation of different tables to be used.*/
+  olsr_init_tables();
+
+  /* daemon mode */
+#ifndef WIN32
+  if(olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
+    printf("%s detaching from the current process...\n", olsrd_version);
+    if (daemon(0, 0) < 0) {
+      printf("daemon(3) failed: %s\n", strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+  }
+#endif
+
+  /* Load plugins */
+  olsr_load_plugins();
+
+  OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+
+  /* Start syslog entry */
+  olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
+
+  /*
+   *signal-handlers
+   */
+
+  /* ctrl-C and friends */
+#ifdef WIN32
+#ifndef WINCE
+  SetConsoleCtrlHandler(SignalHandler, OLSR_TRUE);
+#endif
+#else
+  signal(SIGHUP, olsr_reconfigure);  
+  signal(SIGINT,  olsr_shutdown);
+  signal(SIGQUIT, olsr_shutdown);
+  signal(SIGILL,  olsr_shutdown);
+  signal(SIGABRT, olsr_shutdown);
+//  signal(SIGSEGV, olsr_shutdown);
+  signal(SIGTERM, olsr_shutdown);
+  signal(SIGPIPE, SIG_IGN);
+#endif
+
+  link_changes = OLSR_FALSE;
+
+  /* Starting scheduler */
+  olsr_scheduler();
+
+  /* Like we're ever going to reach this ;-) */
+  return 1;
+} /* main */
+
+
+
+/**
+ * Reconfigure olsrd. Currently kind of a hack...
+ *
+ *@param signal the signal that triggered this callback
+ */
+#ifndef WIN32
+void
+olsr_reconfigure(int signal __attribute__((unused)))
+{
+  if(!fork())
+    {
+      /* New process */
+      sleep(3);
+      printf("Restarting %s\n", olsr_argv[0]);
+      execv(olsr_argv[0], olsr_argv);
+    }
+  olsr_shutdown(0);
+
+  printf("RECONFIGURING!\n");
+}
+#endif
+
+
+/**
+ *Function called at shutdown. Signal handler
+ *
+ * @param signal the signal that triggered this call
+ */
+#ifdef WIN32
+int __stdcall
+SignalHandler(unsigned long signal)
+#else
+static void
+olsr_shutdown(int signal __attribute__((unused)))
+#endif
+{
+  struct interface *ifn;
+
+  OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signal);
+
+#ifdef WIN32
+  OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
+
+  olsr_win32_end_request = TRUE;
+
+  while (!olsr_win32_end_flag)
+    Sleep(100);
+
+  OLSR_PRINTF(1, "Scheduler stopped.\n");
+#endif
+
+  olsr_delete_all_kernel_routes();
+
+  OLSR_PRINTF(1, "Closing sockets...\n");
+
+  /* front-end IPC socket */
+  if (olsr_cnf->ipc_connections > 0) {
+    shutdown_ipc();
+  }
+
+  /* OLSR sockets */
+  for (ifn = ifnet; ifn; ifn = ifn->int_next) 
+    close(ifn->olsr_socket);
+
+  /* Closing plug-ins */
+  olsr_close_plugins();
+
+  /* Reset network settings */
+  restore_settings(olsr_cnf->ip_version);
+
+  /* ioctl socket */
+  close(olsr_cnf->ioctl_s);
+
+#if LINUX_POLICY_ROUTING
+  close(olsr_cnf->rtnl_s);
+#endif
+
+#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
+  /* routing socket */
+  close(olsr_cnf->rts);
+#endif
+
+  /* Free cookies and memory pools attached. */
+  olsr_delete_all_cookies();
+
+  olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
+
+  OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
+
+  exit(olsr_cnf->exit_value);
+}
+
+/**
+ * Print the command line usage
+ */
+static void
+print_usage(void)
+{
+
+  fprintf(stderr,
+          "An error occured somwhere between your keyboard and your chair!\n"
+          "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
+          "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
+          "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
+          "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
+          "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
+          "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
+          "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
+          "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n");
+}
+
+
+/**
+ * Sets the provided configuration on all unconfigured
+ * interfaces
+ *
+ * @param ifs a linked list of interfaces to check and possible update
+ * @param cnf the default configuration to set on unconfigured interfaces
+ */
+int
+set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf)
+{
+  int changes = 0;
+
+  while(ifs)
+    {
+      if(ifs->cnf == NULL)
+	{
+	  ifs->cnf = olsr_malloc(sizeof(struct if_config_options), "Set default config");
+	  *ifs->cnf = *cnf;
+	  changes++;
+	}
+      ifs = ifs->next;
+    }
+  return changes;
+}
+
+
+#define NEXT_ARG do { argv++;argc--; } while (0)
+#define CHECK_ARGC do { if(!argc) { \
+      if((argc - 1) == 1){ \
+      fprintf(stderr, "Error parsing command line options!\n"); \
+      } else { \
+      argv--; \
+      fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
+     } \
+     olsr_exit(__func__, EXIT_FAILURE); \
+     } } while (0)
+
+/**
+ * Process command line arguments passed to olsrd
+ *
+ */
+static int
+olsr_process_arguments(int argc, char *argv[], 
+		       struct olsrd_config *cnf, 
+		       struct if_config_options *ifcnf)
+{
+  while (argc > 1)
+    {
+      NEXT_ARG;
+#ifdef WIN32
+      /*
+       *Interface list
+       */
+      if (strcmp(*argv, "-int") == 0)
+        {
+          ListInterfaces();
+          exit(0);
+        }
+#endif
+
+      /*
+       *Configfilename
+       */
+      if(strcmp(*argv, "-f") == 0) 
+	{
+	  fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
+	  olsr_exit(__func__, EXIT_FAILURE);
+	}
+
+      /*
+       *Use IP version 6
+       */
+      if(strcmp(*argv, "-ipv6") == 0) 
+	{
+	  cnf->ip_version = AF_INET6;
+	  continue;
+	}
+
+      /*
+       *Broadcast address
+       */
+      if(strcmp(*argv, "-bcast") == 0) 
+	{
+	  struct in_addr in;
+	  NEXT_ARG;
+          CHECK_ARGC;
+
+	  if (inet_aton(*argv, &in) == 0)
+	    {
+	      printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
+	      continue;
+	    }
+	  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, "-lqa") == 0) 
+	{
+	  float tmp_lq_aging;
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  
+	  sscanf(*argv, "%f", &tmp_lq_aging);
+
+	  if(tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING)
+	    {
+	      printf("LQ aging factor %f not allowed. Range [%f-%f]\n", 
+		     tmp_lq_aging, MIN_LQ_AGING, MAX_LQ_AGING);
+	      olsr_exit(__func__, EXIT_FAILURE);
+	    }
+	  olsr_cnf->lq_aging = tmp_lq_aging;
+	  continue;
+	}
+      
+      /*
+       * Set NAT threshold
+       */
+      if (strcmp(*argv, "-lqnt") == 0) 
+	{
+	  float tmp_lq_nat_thresh;
+	  NEXT_ARG;
+          CHECK_ARGC;
+
+	  sscanf(*argv,"%f", &tmp_lq_nat_thresh);
+
+	  if(tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0)
+	    {
+	      printf("NAT threshold %f not allowed. Range [%f-%f]\n", 
+		     tmp_lq_nat_thresh, 0.1, 1.0);
+	      olsr_exit(__func__, EXIT_FAILURE);
+	    }
+	  olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
+	  continue;
+	}
+
+      /*
+       * Enable additional debugging information to be logged.
+       */
+      if (strcmp(*argv, "-d") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+
+	  sscanf(*argv,"%d", &cnf->debug_level);
+	  continue;
+	}
+
+		
+      /*
+       * Interfaces to be used by olsrd.
+       */
+      if (strcmp(*argv, "-i") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+
+	  if(*argv[0] == '-')
+	    {
+	      fprintf(stderr, "You must provide an interface label!\n");
+	      olsr_exit(__func__, EXIT_FAILURE);
+	    }
+	  printf("Queuing if %s\n", *argv);
+	  queue_if(*argv, OLSR_FALSE);
+
+	  while((argc - 1) && (argv[1][0] != '-'))
+	    {
+	      NEXT_ARG;
+	      printf("Queuing if %s\n", *argv);
+	      queue_if(*argv, OLSR_FALSE);
+	    }
+
+	  continue;
+	}
+      /*
+       * Set the hello interval to be used by olsrd.
+       * 
+       */
+      if (strcmp(*argv, "-hint") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  sscanf(*argv,"%f", &ifcnf->hello_params.emission_interval);
+          ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval * 3;
+	  continue;
+	}
+
+      /*
+       * Set the HNA interval to be used by olsrd.
+       * 
+       */
+      if (strcmp(*argv, "-hnaint") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  sscanf(*argv,"%f", &ifcnf->hna_params.emission_interval);
+          ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
+	  continue;
+	}
+
+      /*
+       * Set the MID interval to be used by olsrd.
+       * 
+       */
+      if (strcmp(*argv, "-midint") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  sscanf(*argv,"%f", &ifcnf->mid_params.emission_interval);
+          ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
+	  continue;
+	}
+
+      /*
+       * Set the tc interval to be used by olsrd.
+       * 
+       */
+      if (strcmp(*argv, "-tcint") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  sscanf(*argv,"%f", &ifcnf->tc_params.emission_interval);
+          ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
+	  continue;
+	}
+
+      /*
+       * Set the polling interval to be used by olsrd.
+       */
+      if (strcmp(*argv, "-T") == 0) 
+	{
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  sscanf(*argv,"%f",&cnf->pollrate);
+	  continue;
+	}
+
+
+      /*
+       * Should we display the contents of packages beeing sent?
+       */
+      if (strcmp(*argv, "-dispin") == 0) 
+	{
+	  parser_set_disp_pack_in(OLSR_TRUE);
+	  continue;
+	}
+
+      /*
+       * Should we display the contents of incoming packages?
+       */
+      if (strcmp(*argv, "-dispout") == 0) 
+	{
+	  net_set_disp_pack_out(OLSR_TRUE);
+	  continue;
+	}
+
+
+      /*
+       * Should we set up and send on a IPC socket for the front-end?
+       */
+      if (strcmp(*argv, "-ipc") == 0) 
+	{
+	  cnf->ipc_connections = 1;
+	  continue;
+	}
+
+      /*
+       * IPv6 multicast addr
+       */
+      if (strcmp(*argv, "-multi") == 0) 
+	{
+	  struct in6_addr in6;
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  if(inet_pton(AF_INET6, *argv, &in6) <= 0)
+	    {
+	      fprintf(stderr, "Failed converting IP address %s\n", *argv);
+	      exit(EXIT_FAILURE);
+	    }
+
+	  memcpy(&ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));
+
+	  continue;
+	}
+
+      /*
+       * Host emulation
+       */
+      if (strcmp(*argv, "-hemu") == 0) 
+	{
+	  struct in_addr in;
+	  struct olsr_if *ifa;
+      
+	  NEXT_ARG;
+          CHECK_ARGC;
+	  if(inet_pton(AF_INET, *argv, &in) <= 0)
+	    {
+	      fprintf(stderr, "Failed converting IP address %s\n", *argv);
+	      exit(EXIT_FAILURE);
+	    }
+	  /* Add hemu interface */
+
+	  ifa = queue_if("hcif01", OLSR_TRUE);
+
+	  if(!ifa)
+	    continue;
+
+	  ifa->cnf = get_default_if_config();
+	  ifa->host_emul = OLSR_TRUE;
+	  memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
+	  cnf->host_emul = OLSR_TRUE;
+
+	  continue;
+	}
+
+
+      /*
+       * Delete possible default GWs
+       */
+      if (strcmp(*argv, "-delgw") == 0) 
+	{
+	  olsr_cnf->del_gws = OLSR_TRUE;
+	  continue;
+	}
+
+
+      if (strcmp(*argv, "-nofork") == 0) 
+	{
+	  cnf->no_fork = OLSR_TRUE;
+	  continue;
+	}
+
+      return -1;
+    }
+  return 0;
+}
+
+/*
+ * a wrapper around times(2). times(2) has the problem, that it may return -1
+ * in case of an err (e.g. EFAULT on the parameter) or immediately before an
+ * overrun (though it is not en error) just because the jiffies (or whatever
+ * the underlying kernel calls the smallest accountable time unit) are
+ * inherently "unsigned" (and always incremented).
+ */
+unsigned long olsr_times(void)
+{
+  struct tms tms_buf;
+  const long t = times(&tms_buf);
+  return t < 0 ? -errno : t;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mantissa.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mantissa.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mantissa.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mantissa.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,172 @@
+/*
+ * 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 "mantissa.h"
+
+/**
+ *Function that converts a double to a mantissa/exponent
+ *product as described in RFC3626:
+ *
+ * value = C*(1+a/16)*2^b [in seconds]
+ *
+ *  where a is the integer represented by the four highest bits of the
+ *  field and b the integer represented by the four lowest bits of the
+ *  field.
+ *
+ *@param interval the time interval to process
+ *
+ *@return a 8-bit mantissa/exponent product
+ */
+olsr_u8_t reltime_to_me(const olsr_reltime interval) {
+  olsr_u8_t a, b;
+  
+  /* It is sufficent to compare the integer part since we test on >=.
+   * So we have now only a floating point division and the rest of the loop
+   * are only integer operations.
+   * 
+   * const unsigned int unscaled_interval = interval / VTIME_SCALE_FACTOR;
+   * 
+   * VTIME_SCALE_FACTOR = 1/16
+   * 
+   * => unscaled_interval = interval(ms) / 1000 * 16
+   *                      = interval(ms) / 125 * 2
+   */
+  const unsigned int unscaled_interval = interval / 125 * 2;
+  b = 0;
+  while (unscaled_interval >= (1U << b)) {
+    b++;
+  }
+  
+  if (b == 0) {
+    a = 1;
+    b = 0;
+  } else {
+    b--;
+    if (b > 15) {
+      a = 15;
+      b = 15;
+    } else {
+      /* And again some maths simplification from the former version:
+       *    a = 16 * ((double)interval / (VTIME_SCALE_FACTOR * (double)(1 << b)) - 1)
+       * Since interval is already double:
+       *    a = 16 * (interval / (VTIME_SCALE_FACTOR * (double)(1 << b)) - 1)
+       * first, we can get rid of parentheses and change the * to a /
+       *    a = 16 * (interval / VTIME_SCALE_FACTOR / (double)(1 << b) - 1)
+       * then we make an integer addition from the floating point addition
+       *    a = (int)(16.0 * interval / VTIME_SCALE_FACTOR / (double)(1 << b)) - 16
+       * and we loose an unnecessary cast
+       *    a = (int)(16.0 * interval / VTIME_SCALE_FACTOR / (1 << b)) - 16
+       * 
+       * VTIME_SCALE_FACTOR = 1/16
+       * 
+       * => a = (16 * interval(ms) / 1000 * 16 / (1 << b)) - 16
+       *      = (interval(ms) * 256 / 1000 / (1 << b)) - 16
+       *      = (interval(ms) * 32 / 125 / (1<<b)) - 16
+       *      = (interval(ms) - 16/32*125*(1<<b)) * 32 / 125 / (1<<b)
+       *      = (interval(ms) - 125*(1<<(b-1))) * 32 / 125 / (1<<b)
+       * 
+       * 1. case: b >= 5
+       *      = (interval(ms) - (125 << (b-1))) / 125 / (1 << (b-5))
+       *      = (interval(ms) - (125 << (b-1))) / (125  << (b-5))
+       * 
+       * 2. case: b <= 5
+       *      = (interval(ms) - (125 << (b-1))) / 125 * (1 << (5-b))
+       *      = (interval(ms) - (125 << (b-1))) * (1 << (5-b)) / 125
+       */
+
+      if (b >= 5) {
+        a = (interval - (125 << (b-1))) / (125 << (b-5));
+      }
+      else {
+        a = (interval - (125 << (b-1))) * (1 << (5-b)) / 125;
+      }
+      
+      b += a >> 4;
+      a &= 0x0f;
+    }
+  }
+  
+  return (a << 4) | (b & 0x0F);
+}
+
+/**
+ * Function for converting a mantissa/exponent 8bit value back
+ * to double as described in RFC3626:
+ *
+ * value = C*(1+a/16)*2^b [in seconds]
+ *
+ *  where a is the integer represented by the four highest bits of the
+ *  field and b the integer represented by the four lowest bits of the
+ *  field.
+ *
+ * me is the 8 bit mantissa/exponent value
+ *
+ * To avoid expensive floating maths, we transform the equation:
+ *     value = C * (1 + a / 16) * 2^b
+ * first, we make an int addition from the floating point addition:
+ *     value = C * ((16 + a) / 16) * 2^b
+ * then we get rid of a pair of parentheses
+ *     value = C * (16 + a) / 16 * 2^b
+ * and now we make an int multiplication from the floating point one
+ *     value = C * (16 + a) * 2^b / 16
+ * so that we can make a shift from the multiplication
+ *     value = C * ((16 + a) << b) / 16
+ * and sionce C and 16 are constants
+ *     value = ((16 + a) << b) * C / 16
+ * 
+ * VTIME_SCALE_FACTOR = 1/16
+ * 
+ * =>  value(ms) = ((16 + a) << b) / 256 * 1000
+ * 
+ * 1. case: b >= 8
+ *           = ((16 + a) << (b-8)) * 1000
+ * 
+ * 2. case: b <= 8
+ *           = ((16 + a) * 1000) >> (8-b)
+ */
+olsr_reltime me_to_reltime(const olsr_u8_t me) {
+  const olsr_u8_t a = me >> 4;
+  const olsr_u8_t b = me & 0x0F;
+  
+  if (b >= 8) {
+    return ((16 + a) << (b-8)) * 1000;
+  }
+  return ((16 + a) * 1000) >> (8-b);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mantissa.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mantissa.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mantissa.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mantissa.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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 _OLSR_MANTISSA
+#define _OLSR_MANTISSA
+
+#include "olsr_types.h"
+
+/* olsr_reltime is a relative timestamp measured in microseconds */
+typedef olsr_u32_t olsr_reltime;
+
+/**
+ * Macro for converting a mantissa/exponent 8bit value back
+ * to an integer (measured in microseconds) as described in RFC3626:
+ *
+ * value = C*(1+a/16)*2^b [in seconds]
+ *
+ *  where a is the integer represented by the four highest bits of the
+ *  field and b the integer represented by the four lowest bits of the
+ *  field.
+ *
+ * me is the 8 bit mantissa/exponent value
+ *
+ */
+olsr_reltime me_to_reltime(const olsr_u8_t);
+
+olsr_u8_t reltime_to_me(const olsr_reltime);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mid_set.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mid_set.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mid_set.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mid_set.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,558 @@
+
+/*
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "two_hop_neighbor_table.h"
+#include "mid_set.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "neighbor_table.h"
+#include "link_set.h"
+#include "tc_set.h"
+#include "packet.h"		/* struct mid_alias */
+#include "net_olsr.h"
+
+
+struct mid_entry mid_set[HASHSIZE];
+struct mid_address reverse_mid_set[HASHSIZE];
+
+struct mid_entry *mid_lookup_entry_bymain(const union olsr_ip_addr *adr);
+
+/**
+ * Initialize the MID set
+ *
+ */
+int
+olsr_init_mid_set(void)
+{
+  int idx;
+
+  OLSR_PRINTF(5, "MID: init\n");
+
+  for (idx = 0; idx < HASHSIZE; idx++) {
+    mid_set[idx].next = &mid_set[idx];
+    mid_set[idx].prev = &mid_set[idx];
+
+    reverse_mid_set[idx].next = &reverse_mid_set[idx];
+    reverse_mid_set[idx].prev = &reverse_mid_set[idx];
+  }
+
+  return 1;
+}
+
+/**
+ * Wrapper for the timer callback.
+ */
+static void
+olsr_expire_mid_entry(void *context)
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  struct mid_entry *mid;
+
+  mid = (struct mid_entry *)context;
+  mid->mid_timer = NULL;
+
+#ifdef DEBUG
+  OLSR_PRINTF(1, "MID info for %s timed out.. deleting it\n",
+	      olsr_ip_to_string(&buf, &mid->main_addr));
+#endif
+
+  olsr_delete_mid_entry(mid);
+}
+
+
+/**
+ * Set the mid set expiration timer.
+ *
+ * all timer setting shall be done using this function.
+ * The timer param is a relative timer expressed in milliseconds.
+ */
+static void
+olsr_set_mid_timer(struct mid_entry *mid, olsr_reltime rel_timer)
+{
+
+  olsr_set_timer(&mid->mid_timer, rel_timer, OLSR_MID_JITTER,
+		 OLSR_TIMER_ONESHOT, &olsr_expire_mid_entry, mid, 0);
+}
+
+
+/**
+ * Insert a new interface alias to the interface association set.
+ * If the main interface of the association is not yet registered
+ * in the set a new entry is created.
+ *
+ * @param m_addr the main address of the node
+ * @param alias the alias address to insert
+ * @return nada
+ */
+
+void
+insert_mid_tuple(union olsr_ip_addr *m_addr, struct mid_address *alias,
+		 olsr_reltime vtime)
+{
+  struct mid_entry *tmp;
+  struct mid_address *tmp_adr;
+  olsr_u32_t hash, alias_hash;
+  union olsr_ip_addr *registered_m_addr;
+
+  hash = olsr_ip_hashing(m_addr);
+  alias_hash = olsr_ip_hashing(&alias->alias);
+
+  /* Check for registered entry */
+  for (tmp = mid_set[hash].next; tmp != &mid_set[hash]; tmp = tmp->next) {
+    if (ipequal(&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 && ipequal(registered_m_addr, m_addr)) {
+
+    /* Alias is already registered with main address. Nothing to do here. */
+    return;
+  }
+
+  /*
+   * Add a rt_path for the alias.
+   */
+  olsr_insert_routing_table(&alias->alias, olsr_cnf->maxplen, m_addr,
+			    OLSR_RT_ORIGIN_MID);
+
+  /*If the address was registered */
+  if (tmp != &mid_set[hash]) {
+    tmp_adr = tmp->aliases;
+    tmp->aliases = alias;
+    alias->main_entry = tmp;
+    QUEUE_ELEM(reverse_mid_set[alias_hash], alias);
+    alias->next_alias = tmp_adr;
+    olsr_set_mid_timer(tmp, vtime);
+  } else {
+
+    /*Create new node */
+    tmp = olsr_malloc(sizeof(struct mid_entry), "MID new alias");
+
+    tmp->aliases = alias;
+    alias->main_entry = tmp;
+    QUEUE_ELEM(reverse_mid_set[alias_hash], alias);
+    tmp->main_addr = *m_addr;
+    olsr_set_mid_timer(tmp, vtime);
+
+    /* Queue */
+    QUEUE_ELEM(mid_set[hash], tmp);
+  }
+
+
+
+  /*
+   * Delete possible duplicate entries in 2 hop set
+   * and delete duplicate neighbor entries. Redirect
+   * link entries to the correct neighbor entry.
+   *
+   *THIS OPTIMIZATION IS NOT SPECIFIED IN RFC3626
+   */
+
+  tmp_adr = alias;
+
+  while (tmp_adr) {
+    struct neighbor_2_entry *tmp_2_neighbor;
+    struct neighbor_entry *tmp_neigh, *real_neigh;
+
+    /* Delete possible 2 hop neighbor */
+    if ((tmp_2_neighbor =
+	 olsr_lookup_two_hop_neighbor_table_mid(&tmp_adr->alias)) != NULL) {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "Deleting 2 hop node from MID: %s to ",
+		  olsr_ip_to_string(&buf, &tmp_adr->alias));
+      OLSR_PRINTF(1, "%s\n", olsr_ip_to_string(&buf, m_addr));
+
+      olsr_delete_two_hop_neighbor_table(tmp_2_neighbor);
+
+      changes_neighborhood = OLSR_TRUE;
+    }
+
+    /* Delete a possible neighbor entry */
+    if (((tmp_neigh =
+	  olsr_lookup_neighbor_table_alias(&tmp_adr->alias)) != NULL)
+	&& ((real_neigh = olsr_lookup_neighbor_table_alias(m_addr)) != NULL))
+    {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "[MID]Deleting bogus neighbor entry %s real ",
+		  olsr_ip_to_string(&buf, &tmp_adr->alias));
+      OLSR_PRINTF(1, "%s\n", olsr_ip_to_string(&buf, m_addr));
+
+      replace_neighbor_link_set(tmp_neigh, real_neigh);
+
+      /* Dequeue */
+      DEQUEUE_ELEM(tmp_neigh);
+      /* Delete */
+      free(tmp_neigh);
+
+      changes_neighborhood = OLSR_TRUE;
+    }
+    tmp_adr = tmp_adr->next_alias;
+  }
+}
+
+
+/**
+ * Insert an alias address for a node.
+ * If the main address is not registered
+ * then a new entry is created.
+ *
+ * @param main_add the main address of the node
+ * @param alias the alias address to insert
+ * @param seq the sequence number to register a new node with
+ * @return nada
+ */
+void
+insert_mid_alias(union olsr_ip_addr *main_add, const union olsr_ip_addr *alias,
+		 olsr_reltime vtime)
+{
+  struct neighbor_entry *ne_old, *ne_new;
+  struct mid_entry *me_old;
+  int ne_ref_rp_count;
+  struct ipaddr_str buf1, buf2;
+  struct mid_address *adr;
+  if (!olsr_validate_address(alias))
+    return;
+
+  OLSR_PRINTF(1, "Inserting alias %s for ", olsr_ip_to_string(&buf1, alias));
+  OLSR_PRINTF(1, "%s\n", olsr_ip_to_string(&buf1, main_add));
+
+  adr = olsr_malloc(sizeof(struct mid_address), "Insert MID alias");
+
+  adr->alias = *alias;
+  adr->next_alias = NULL;
+
+  /*
+   * If we have an entry for this alias in neighbortable, we better adjust it's
+   * main address, because otherwise a fatal inconsistency between
+   * neighbortable and link_set will be created by way of this mid entry.
+   */
+  ne_old = olsr_lookup_neighbor_table_alias(alias);
+  if (ne_old != NULL) {
+    OLSR_PRINTF(2,
+		"Remote main address change detected. Mangling neighbortable to replace %s with %s.\n",
+		olsr_ip_to_string(&buf1, alias), olsr_ip_to_string(&buf2,
+								   main_add));
+    olsr_delete_neighbor_table(alias);
+    ne_new = olsr_insert_neighbor_table(main_add);
+    /* adjust pointers to neighbortable-entry in link_set */
+    ne_ref_rp_count = replace_neighbor_link_set(ne_old, ne_new);
+    if (ne_ref_rp_count > 0)
+      OLSR_PRINTF(2,
+		  "Performed %d neighbortable-pointer replacements (%p -> %p) in link_set.\n",
+		  ne_ref_rp_count, ne_old, ne_new);
+
+    me_old = mid_lookup_entry_bymain(alias);
+    if (me_old) {
+
+      /* 
+       * we knew aliases to the previous main address;
+       * better forget about them now.
+       */
+      OLSR_PRINTF(2, "I already have an mid entry mapping addresses to this "
+                  "alias address. Removing existing mid entry to preserve consistency of mid_set.\n");
+      olsr_delete_mid_entry(me_old);
+    }
+  }
+
+  insert_mid_tuple(main_add, adr, vtime);
+
+  /*
+   *Recalculate topology
+   */
+  changes_neighborhood = OLSR_TRUE;
+  changes_topology = OLSR_TRUE;
+}
+
+/**
+ * Lookup the main address for a alias address
+ *
+ * @param adr the alias address to check
+ * @return the main address registered on the alias
+ * or NULL if not found
+ */
+union olsr_ip_addr *
+mid_lookup_main_addr(const union olsr_ip_addr *adr)
+{
+  olsr_u32_t hash;
+  struct mid_address *tmp_list;
+
+  hash = olsr_ip_hashing(adr);
+
+  /*Traverse MID list */
+  for (tmp_list = reverse_mid_set[hash].next;
+       tmp_list != &reverse_mid_set[hash]; tmp_list = tmp_list->next) {
+    if (ipequal(&tmp_list->alias, adr))
+      return &tmp_list->main_entry->main_addr;
+  }
+  return NULL;
+
+}
+
+/*
+ * Find mid entry to an address.
+ *
+ * @param adr the main address to search for
+ * @return a linked list of address structs
+ */
+struct mid_entry *
+mid_lookup_entry_bymain(const union olsr_ip_addr *adr)
+{
+  struct mid_entry *tmp_list;
+  olsr_u32_t hash;
+
+  hash = olsr_ip_hashing(adr);
+
+  /* Check all registered nodes... */
+  for (tmp_list = mid_set[hash].next;
+       tmp_list != &mid_set[hash]; tmp_list = tmp_list->next) {
+    if (ipequal(&tmp_list->main_addr, adr))
+      return tmp_list;
+  }
+  return NULL;
+}
+
+/*
+ * Find all aliases for an address.
+ *
+ * @param adr the main address to search for
+ * @return a linked list of addresses structs
+ */
+struct mid_address *
+mid_lookup_aliases(const union olsr_ip_addr *adr)
+{
+  struct mid_entry *tmp = mid_lookup_entry_bymain(adr);
+  return tmp ? tmp->aliases : NULL;
+}
+
+
+/**
+ * Update the timer for an MID entry
+ *
+ * @param adr the main address of the entry
+ * @return 1 if the node was updated, 0 if not
+ */
+int
+olsr_update_mid_table(const union olsr_ip_addr *adr, olsr_reltime vtime)
+{
+  olsr_u32_t hash;
+  struct ipaddr_str buf;
+  struct mid_entry *tmp_list = mid_set;
+
+  OLSR_PRINTF(3, "MID: update %s\n", olsr_ip_to_string(&buf, adr));
+  hash = olsr_ip_hashing(adr);
+
+  /* Check all registered nodes... */
+  for (tmp_list = mid_set[hash].next;
+       tmp_list != &mid_set[hash]; tmp_list = tmp_list->next) {
+    /*find match */
+    if (ipequal(&tmp_list->main_addr, adr)) {
+      olsr_set_mid_timer(tmp_list, vtime);
+
+      return 1;
+    }
+  }
+  return 0;
+}
+
+
+/**
+ * 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(const 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_ip_hashing(m_addr);
+
+  /* Check for registered entry */
+  for (entry = mid_set[hash].next; entry != &mid_set[hash]; entry = entry->next) {
+    if (ipequal(&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 != NULL) {
+    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 &&
+	   !ipequal(&current_alias->alias, &declared_aliases->alias_addr)) {
+      declared_aliases = declared_aliases->next;
+    }
+
+    if (declared_aliases == NULL) {
+      struct ipaddr_str buf;
+      /* Current alias not found in list of declared aliases: free current alias */
+      OLSR_PRINTF(1, "MID remove: (%s, ",
+		  olsr_ip_to_string(&buf, &entry->main_addr));
+      OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&buf, &current_alias->alias));
+
+      /* Update linked list as seen by 'entry' */
+      if (previous_alias != NULL) {
+	previous_alias->next_alias = current_alias->next_alias;
+      } else {
+	entry->aliases = current_alias->next_alias;
+      }
+
+      /* Remove from hash table */
+      DEQUEUE_ELEM(current_alias);
+
+      /*
+       * Delete the rt_path for the alias.
+       */
+      olsr_delete_routing_table(&current_alias->alias, olsr_cnf->maxplen,
+				&entry->main_addr);
+
+      free(current_alias);
+
+      /*
+       *Recalculate topology
+       */
+      changes_neighborhood = OLSR_TRUE;
+      changes_topology = OLSR_TRUE;
+    } else {
+      previous_alias = current_alias;
+    }
+  }
+}
+
+
+/**
+ * Delete a MID entry
+ *
+ * @param entry the entry to delete
+ */
+void
+olsr_delete_mid_entry(struct mid_entry *mid)
+{
+  struct mid_address *aliases;
+
+  /* Free aliases */
+  aliases = mid->aliases;
+  while (aliases) {
+    struct mid_address *tmp_aliases = aliases;
+    aliases = aliases->next_alias;
+    DEQUEUE_ELEM(tmp_aliases);
+
+
+    /*
+     * Delete the rt_path for the alias.
+     */
+    olsr_delete_routing_table(&tmp_aliases->alias, olsr_cnf->maxplen,
+			      &mid->main_addr);
+
+    free(tmp_aliases);
+  }
+
+  /*
+   * Kill any pending timers.
+   */
+  if (mid->mid_timer) {
+    olsr_stop_timer(mid->mid_timer);
+    mid->mid_timer = NULL;
+  }
+
+  /* Dequeue */
+  DEQUEUE_ELEM(mid);
+  free(mid);
+}
+
+
+/**
+ * Print all MID entries
+ * For debuging purposes
+ */
+void
+olsr_print_mid_set(void)
+{
+  int idx;
+
+  OLSR_PRINTF(1,
+	      "\n--- %s ------------------------------------------------- MID\n\n",
+	      olsr_wallclock_string());
+
+  for (idx = 0; idx < HASHSIZE; idx++) {
+    struct mid_entry *tmp_list = mid_set[idx].next;
+    /*Traverse MID list */
+    for (tmp_list = mid_set[idx].next; tmp_list != &mid_set[idx];
+	 tmp_list = tmp_list->next) {
+      struct mid_address *tmp_addr;
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "%s: ", olsr_ip_to_string(&buf, &tmp_list->main_addr));
+      for (tmp_addr = tmp_list->aliases; tmp_addr;
+	   tmp_addr = tmp_addr->next_alias) {
+	OLSR_PRINTF(1, " %s ", olsr_ip_to_string(&buf, &tmp_addr->alias));
+      }
+      OLSR_PRINTF(1, "\n");
+    }
+  }
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mid_set.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mid_set.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mid_set.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mid_set.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,94 @@
+
+/*
+ * 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 _OLSR_MID
+#define _OLSR_MID
+
+#include "olsr_types.h"
+#include "hashing.h"
+#include "mantissa.h"
+
+struct mid_address {
+  union olsr_ip_addr alias;
+  struct mid_entry *main_entry;
+  struct mid_address *next_alias;
+
+  /* These are for the reverse list */
+  struct mid_address *prev;
+  struct mid_address *next;
+};
+
+/*
+ * Contains the main addr of a node and a list of aliases
+ */
+struct mid_entry {
+  union olsr_ip_addr main_addr;
+  struct mid_address *aliases;
+  struct mid_entry *prev;
+  struct mid_entry *next;
+  struct timer_entry *mid_timer;
+};
+
+#define OLSR_MID_JITTER 5	/* percent */
+
+extern struct mid_entry mid_set[HASHSIZE];
+extern struct mid_address reverse_mid_set[HASHSIZE];
+
+struct mid_alias;
+
+int olsr_init_mid_set(void);
+void insert_mid_tuple(union olsr_ip_addr *, struct mid_address *, olsr_reltime);
+void insert_mid_alias(union olsr_ip_addr *, const union olsr_ip_addr *, olsr_reltime);
+union olsr_ip_addr *mid_lookup_main_addr(const union olsr_ip_addr *);
+struct mid_address *mid_lookup_aliases(const union olsr_ip_addr *);
+struct mid_entry *mid_lookup_entry_bymain(const union olsr_ip_addr *);
+void olsr_print_mid_set(void);
+void olsr_prune_aliases(const union olsr_ip_addr *, struct mid_alias *);
+int olsr_update_mid_table(const union olsr_ip_addr *, olsr_reltime);
+void olsr_delete_mid_entry(struct mid_entry *);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/misc.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/misc.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/misc.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/misc.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 _OLSR_MISC_H
+#define _OLSR_MISC_H
+
+void clear_console(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,595 @@
+/*
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "mpr.h"
+#include "two_hop_neighbor_table.h"
+#include "olsr.h"
+#include "neighbor_table.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+
+/* Begin:
+ * Prototypes for internal functions 
+ */
+
+static olsr_u16_t
+add_will_always_nodes(void);
+
+static void
+olsr_optimize_mpr_set(void);
+
+static void
+olsr_clear_mprs(void);
+
+static void
+olsr_clear_two_hop_processed(void);
+
+static struct neighbor_entry *
+olsr_find_maximum_covered(int);
+
+static olsr_u16_t
+olsr_calculate_two_hop_neighbors(void);
+
+static int
+olsr_check_mpr_changes(void);
+
+static int
+olsr_chosen_mpr(struct neighbor_entry *, olsr_u16_t *);
+
+static struct neighbor_2_list_entry *
+olsr_find_2_hop_neighbors_with_1_link(int);
+
+
+/* End:
+ * Prototypes for internal functions 
+ */
+
+
+
+/**
+ *Find all 2 hop neighbors with 1 link
+ *connecting them to us trough neighbors
+ *with a given willingness.
+ *
+ *@param willingness the willigness of the neighbors
+ *
+ *@return a linked list of allocated neighbor_2_list_entry structures
+ */
+static struct neighbor_2_list_entry *
+olsr_find_2_hop_neighbors_with_1_link(int willingness)
+{
+  
+ 
+  olsr_u8_t                    index;
+  struct neighbor_2_list_entry *two_hop_list_tmp = NULL;
+  struct neighbor_2_list_entry *two_hop_list = NULL;
+  struct neighbor_entry        *dup_neighbor;
+  struct neighbor_2_entry      *two_hop_neighbor = NULL;
+
+
+  for(index=0;index<HASHSIZE;index++)
+    {
+
+      for(two_hop_neighbor = two_hop_neighbortable[index].next;
+	  two_hop_neighbor != &two_hop_neighbortable[index];
+	  two_hop_neighbor = two_hop_neighbor->next)
+	{
+	  
+	  //two_hop_neighbor->neighbor_2_state=0;
+	  //two_hop_neighbor->mpr_covered_count = 0;
+	  
+	  dup_neighbor = olsr_lookup_neighbor_table(&two_hop_neighbor->neighbor_2_addr);
+	  
+	  if((dup_neighbor != NULL) && (dup_neighbor->status != NOT_SYM))
+	    {
+	      
+	      //OLSR_PRINTF(1, "(1)Skipping 2h neighbor %s - already 1hop\n", olsr_ip_to_string(&buf, &two_hop_neighbor->neighbor_2_addr));
+
+	      continue;
+	    }
+	  
+	  if(two_hop_neighbor->neighbor_2_pointer == 1)
+	    {
+	      if((two_hop_neighbor->neighbor_2_nblist.next->neighbor->willingness == willingness) &&
+		 (two_hop_neighbor->neighbor_2_nblist.next->neighbor->status == SYM))
+		{
+		  two_hop_list_tmp = olsr_malloc(sizeof(struct neighbor_2_list_entry), "MPR two hop list");
+
+		  //OLSR_PRINTF(1, "ONE LINK ADDING %s\n", olsr_ip_to_string(&buf, &two_hop_neighbor->neighbor_2_addr));
+
+		  /* Only queue one way here */		  
+		  two_hop_list_tmp->neighbor_2 = two_hop_neighbor;
+		  
+		  two_hop_list_tmp->next = two_hop_list;
+		  
+		  two_hop_list= two_hop_list_tmp;
+		}
+	    }
+	  
+	}
+      
+    }
+  
+  return(two_hop_list_tmp);
+}
+  
+
+
+
+
+
+/**
+ *This function processes the chosen MPRs and updates the counters
+ *used in calculations
+ */
+static int
+olsr_chosen_mpr(struct neighbor_entry *one_hop_neighbor, olsr_u16_t *two_hop_covered_count)
+{
+  struct neighbor_list_entry   *the_one_hop_list;
+  struct neighbor_2_list_entry *second_hop_entries; 
+  struct neighbor_entry        *dup_neighbor;
+  olsr_u16_t                   count;
+  struct ipaddr_str            buf;
+  count = *two_hop_covered_count;
+
+  OLSR_PRINTF(1, "Setting %s as MPR\n", olsr_ip_to_string(&buf, &one_hop_neighbor->neighbor_main_addr));
+
+  //printf("PRE COUNT: %d\n\n", count);
+
+  one_hop_neighbor->is_mpr = OLSR_TRUE; //NBS_MPR;
+  
+  for(second_hop_entries = one_hop_neighbor->neighbor_2_list.next;
+      second_hop_entries != &one_hop_neighbor->neighbor_2_list;
+      second_hop_entries = second_hop_entries->next)
+    {
+      dup_neighbor = olsr_lookup_neighbor_table(&second_hop_entries->neighbor_2->neighbor_2_addr);
+
+      if((dup_neighbor != NULL) && (dup_neighbor->status == SYM))
+	{
+	  //OLSR_PRINTF(7, "(2)Skipping 2h neighbor %s - already 1hop\n", olsr_ip_to_string(&buf, &second_hop_entries->neighbor_2->neighbor_2_addr));
+	  continue;
+	}
+
+      //      if(!second_hop_entries->neighbor_2->neighbor_2_state)
+      //if(second_hop_entries->neighbor_2->mpr_covered_count < olsr_cnf->mpr_coverage)
+      //{
+	  /*
+	    Now the neighbor is covered by this mpr
+	  */
+	  second_hop_entries->neighbor_2->mpr_covered_count++;
+	  the_one_hop_list = second_hop_entries->neighbor_2->neighbor_2_nblist.next;
+
+	  //OLSR_PRINTF(1, "[%s](%x) has coverage %d\n", olsr_ip_to_string(&buf, &second_hop_entries->neighbor_2->neighbor_2_addr), second_hop_entries->neighbor_2, second_hop_entries->neighbor_2->mpr_covered_count);
+
+	  if(second_hop_entries->neighbor_2->mpr_covered_count >= olsr_cnf->mpr_coverage)
+	     count++;
+		      
+	  while(the_one_hop_list != &second_hop_entries->neighbor_2->neighbor_2_nblist)
+	    {
+	      
+	      if((the_one_hop_list->neighbor->status == SYM))
+		{
+		  if(second_hop_entries->neighbor_2->mpr_covered_count >= olsr_cnf->mpr_coverage)
+		    {
+		      the_one_hop_list->neighbor->neighbor_2_nocov--;
+		    }
+		}
+	      the_one_hop_list = the_one_hop_list->next;
+	    }
+	  
+	  //}
+    }
+
+  //printf("POST COUNT %d\n\n", count);
+  
+  *two_hop_covered_count = count;
+  return count;
+
+}
+
+
+/**
+ *Find the neighbor that covers the most 2 hop neighbors
+ *with a given willingness
+ *
+ *@param willingness the willingness of the neighbor
+ *
+ *@return a pointer to the neighbor_entry struct
+ */
+static struct neighbor_entry *
+olsr_find_maximum_covered(int willingness)
+{
+  olsr_u16_t                  maximum;
+  struct neighbor_entry       *a_neighbor;
+  struct neighbor_entry       *mpr_candidate = NULL;
+   
+  maximum = 0;
+
+  OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+
+#if 0
+      printf("[%s] nocov: %d mpr: %d will: %d max: %d\n\n", 
+             olsr_ip_to_string(&buf, &a_neighbor->neighbor_main_addr), 
+             a_neighbor->neighbor_2_nocov,
+             a_neighbor->is_mpr,
+             a_neighbor->willingness,
+             maximum);
+#endif
+
+      if ((!a_neighbor->is_mpr) &&
+          (a_neighbor->willingness == willingness) && 
+          (maximum < a_neighbor->neighbor_2_nocov)) {
+
+          maximum = a_neighbor->neighbor_2_nocov;
+          mpr_candidate = a_neighbor;
+      }
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+
+  return mpr_candidate;
+}
+
+
+/**
+ *Remove all MPR registrations
+ */
+static void
+olsr_clear_mprs(void)
+{
+  struct neighbor_entry *a_neighbor;
+  struct neighbor_2_list_entry *two_hop_list;
+
+  OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+
+    /* Clear MPR selection. */
+    if (a_neighbor->is_mpr) {
+      a_neighbor->was_mpr = OLSR_TRUE;
+      a_neighbor->is_mpr = OLSR_FALSE;
+    }
+
+    /* Clear two hop neighbors coverage count/ */
+    for (two_hop_list = a_neighbor->neighbor_2_list.next;
+         two_hop_list != &a_neighbor->neighbor_2_list;
+         two_hop_list = two_hop_list->next) {
+      two_hop_list->neighbor_2->mpr_covered_count = 0;
+    }
+
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+}
+
+
+/**
+ *Check for changes in the MPR set
+ *
+ *@return 1 if changes occured 0 if not
+ */
+static int
+olsr_check_mpr_changes(void)
+{
+  struct neighbor_entry *a_neighbor;
+  int retval;
+
+  retval = 0;
+  
+  OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+
+    if (a_neighbor->was_mpr) {
+      a_neighbor->was_mpr = OLSR_FALSE;
+
+      if (!a_neighbor->is_mpr) {
+        retval = 1;
+      }
+    }
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+
+  return retval;
+}
+
+
+/**
+ *Clears out proccess registration
+ *on two hop neighbors
+ */
+static void
+olsr_clear_two_hop_processed(void)
+{
+  int index;
+  
+  for(index=0;index<HASHSIZE;index++)
+    {
+      struct neighbor_2_entry  *neighbor_2;
+      for(neighbor_2 = two_hop_neighbortable[index].next;
+	  neighbor_2 != &two_hop_neighbortable[index];
+	  neighbor_2 = neighbor_2->next)
+	{
+	  /* Clear */
+	  neighbor_2->processed = 0;
+	}
+    }
+
+}
+
+
+/**
+ *This function calculates the number of two hop neighbors
+ */
+static olsr_u16_t
+olsr_calculate_two_hop_neighbors(void)
+{
+  struct neighbor_entry *a_neighbor, *dup_neighbor;
+  struct neighbor_2_list_entry *twohop_neighbors;
+  olsr_u16_t count = 0;
+  olsr_u16_t n_count = 0;
+  olsr_u16_t sum = 0;
+  
+  /* Clear 2 hop neighs */
+  olsr_clear_two_hop_processed();
+
+  OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+
+    if (a_neighbor->status == NOT_SYM) {	    
+      a_neighbor->neighbor_2_nocov = count;
+      continue;
+    }
+
+    for (twohop_neighbors = a_neighbor->neighbor_2_list.next;
+         twohop_neighbors != &a_neighbor->neighbor_2_list;
+         twohop_neighbors = twohop_neighbors->next) {
+
+      dup_neighbor = olsr_lookup_neighbor_table(&twohop_neighbors->neighbor_2->neighbor_2_addr);
+	      
+      if ((dup_neighbor == NULL) || (dup_neighbor->status != SYM)) {
+        n_count++;
+        if (!twohop_neighbors->neighbor_2->processed) {
+          count++;
+          twohop_neighbors->neighbor_2->processed = 1;
+        }
+      }
+    }
+    a_neighbor->neighbor_2_nocov = n_count;
+	  
+    /* Add the two hop count */
+    sum += count;
+
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+  
+  OLSR_PRINTF(3, "Two hop neighbors: %d\n", sum);
+  return sum;
+}
+
+
+
+
+/**
+ * Adds all nodes with willingness set to WILL_ALWAYS
+ */
+static olsr_u16_t
+add_will_always_nodes(void)
+{
+  struct neighbor_entry *a_neighbor;
+  olsr_u16_t count = 0;
+
+#if 0
+  printf("\nAdding WILL ALWAYS nodes....\n");
+#endif
+
+  OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+    struct ipaddr_str buf;
+    if ((a_neighbor->status == NOT_SYM) ||
+        (a_neighbor->willingness != WILL_ALWAYS)) {
+      continue;
+    }
+    olsr_chosen_mpr(a_neighbor, &count); 
+
+    OLSR_PRINTF(3, "Adding WILL_ALWAYS: %s\n",
+                olsr_ip_to_string(&buf, &a_neighbor->neighbor_main_addr));
+
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+
+#if 0  
+  OLSR_PRINTF(1, "Count: %d\n", count);
+#endif
+  return count;
+}
+
+/**
+ *This function calculates the mpr neighbors
+ *@return nada
+ */
+void
+olsr_calculate_mpr(void)     
+{  
+  olsr_u16_t two_hop_covered_count;
+  olsr_u16_t two_hop_count;
+  int i;
+
+  OLSR_PRINTF(3, "\n**RECALCULATING MPR**\n\n");
+
+  olsr_clear_mprs();
+  two_hop_count = olsr_calculate_two_hop_neighbors();
+  two_hop_covered_count = add_will_always_nodes();
+
+  /*
+   *Calculate MPRs based on WILLINGNESS
+   */
+
+  for(i = WILL_ALWAYS - 1; i > WILL_NEVER; i--)
+    {
+      struct neighbor_entry        *mprs; 
+      struct neighbor_2_list_entry *two_hop_list = olsr_find_2_hop_neighbors_with_1_link(i);
+
+      while(two_hop_list != NULL)
+	{
+          struct neighbor_2_list_entry *tmp;
+	  //printf("CHOSEN FROM 1 LINK\n");
+	  if(!two_hop_list->neighbor_2->neighbor_2_nblist.next->neighbor->is_mpr)
+	    olsr_chosen_mpr(two_hop_list->neighbor_2->neighbor_2_nblist.next->neighbor, &two_hop_covered_count); 
+	  tmp = two_hop_list;
+	  two_hop_list = two_hop_list->next;;
+	  free(tmp);
+	}
+      
+      if(two_hop_covered_count >= two_hop_count)
+	{
+	  i = WILL_NEVER;
+	  break;
+	}
+
+      //printf("two hop covered count: %d\n", two_hop_covered_count);
+   
+      while((mprs = olsr_find_maximum_covered(i)) != NULL)
+	{
+	  //printf("CHOSEN FROM MAXCOV\n");
+	  olsr_chosen_mpr(mprs,&two_hop_covered_count);
+
+	  if(two_hop_covered_count >= two_hop_count)
+	    {
+	      i = WILL_NEVER;
+	      break;
+	    }
+
+	}
+    }
+  
+  /*
+    increment the mpr sequence number
+  */
+  //neighbortable.neighbor_mpr_seq++;
+
+  /* Optimize selection */
+  olsr_optimize_mpr_set();
+
+  if(olsr_check_mpr_changes())
+    {
+      OLSR_PRINTF(3, "CHANGES IN MPR SET\n");
+      if(olsr_cnf->tc_redundancy > 0)
+	signal_link_changes(OLSR_TRUE);
+    }
+
+}
+
+/**
+ *Optimize MPR set by removing all entries
+ *where all 2 hop neighbors actually is
+ *covered by enough MPRs already
+ *Described in RFC3626 section 8.3.1
+ *point 5
+ *
+ *@return nada
+ */
+static void
+olsr_optimize_mpr_set(void)
+{
+  struct neighbor_entry *a_neighbor, *dup_neighbor;
+  struct neighbor_2_list_entry *two_hop_list;
+  int i, remove;
+
+#if 0
+  printf("\n**MPR OPTIMIZING**\n\n");
+#endif
+
+  for(i = WILL_NEVER + 1; i < WILL_ALWAYS; i++) {
+
+    OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+	      
+      if (a_neighbor->willingness != i) {
+        continue;
+      }
+	      
+      if (a_neighbor->is_mpr) {
+        remove = 1;
+
+        for (two_hop_list = a_neighbor->neighbor_2_list.next;
+             two_hop_list != &a_neighbor->neighbor_2_list;
+             two_hop_list = two_hop_list->next) {
+		      
+          dup_neighbor = olsr_lookup_neighbor_table(&two_hop_list->neighbor_2->neighbor_2_addr);
+		      
+          if ((dup_neighbor != NULL) && (dup_neighbor->status != NOT_SYM)) {
+            continue;
+          }
+		      
+          //printf("\t[%s] coverage %d\n", olsr_ip_to_string(&buf, &two_hop_list->neighbor_2->neighbor_2_addr), two_hop_list->neighbor_2->mpr_covered_count);
+          /* Do not remove if we find a entry which need this MPR */
+          if (two_hop_list->neighbor_2->mpr_covered_count <= olsr_cnf->mpr_coverage) {
+            remove = 0;
+          }      
+        }
+
+        if (remove) {
+          struct ipaddr_str buf;
+          OLSR_PRINTF(3, "MPR OPTIMIZE: removiong mpr %s\n\n", olsr_ip_to_string(&buf, &a_neighbor->neighbor_main_addr));
+          a_neighbor->is_mpr = OLSR_FALSE;
+        }
+      }
+    } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+  }
+}
+
+void
+olsr_print_mpr_set(void)
+{
+#ifndef NODEBUG
+  /* The whole function makes no sense without it. */
+  struct neighbor_entry *a_neighbor;
+
+  OLSR_PRINTF(1, "MPR SET: ");
+
+  OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) {
+
+    /* 
+     * Remove MPR settings
+     */
+    if (a_neighbor->is_mpr) {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "[%s] ", olsr_ip_to_string(&buf, &a_neighbor->neighbor_main_addr));
+    }
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor);
+
+  OLSR_PRINTF(1, "\n");
+#endif
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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 _OLSR_MPR
+#define _OLSR_MPR
+
+void
+olsr_calculate_mpr(void);
+
+void
+olsr_print_mpr_set(void);
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr_selector_set.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr_selector_set.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr_selector_set.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr_selector_set.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,247 @@
+/*
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "mpr_selector_set.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+
+static olsr_u16_t ansn;
+
+/* MPR selector list */
+static struct mpr_selector mprs_list;
+
+/**
+ *Initialize MPR selector set
+ */
+
+void
+olsr_init_mprs_set(void)
+{
+  OLSR_PRINTF(5, "MPRS: Init\n");
+
+  /* Initial values */
+  ansn = 0;
+
+  mprs_list.next = &mprs_list;
+  mprs_list.prev = &mprs_list;
+}
+
+
+olsr_u16_t 
+get_local_ansn(void)
+{
+  return ansn;
+}
+
+void
+increase_local_ansn(void)
+{
+  ansn++;
+}
+
+#if 0
+/**
+ * Check if we(this node) is selected as a MPR by any
+ * neighbors. If the list is empty we are not MPR.
+ */
+olsr_bool
+olsr_is_mpr(void)
+{
+    return ((mprs_list.next == &mprs_list) ? OLSR_FALSE : OLSR_TRUE);
+}
+#endif
+
+
+/**
+ * Wrapper for the timer callback.
+ */
+static void
+olsr_expire_mpr_sel_entry(void *context)
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  struct mpr_selector *mpr_sel;
+
+  mpr_sel = (struct mpr_selector *)context;
+  mpr_sel->MS_timer = NULL;
+
+#ifdef DEBUG
+  OLSR_PRINTF(1, "MPRS: Timing out %st\n",
+              olsr_ip_to_string(&buf, &mpr_sel->MS_main_addr));
+#endif
+
+  DEQUEUE_ELEM(mpr_sel);
+
+  /* Delete entry */
+  free(mpr_sel);
+  signal_link_changes(OLSR_TRUE);
+}
+
+
+/**
+ * Set the mpr selector expiration timer.
+ *
+ * all timer setting shall be done using this function.
+ * The timer param is a relative timer expressed in milliseconds.
+ */
+static void
+olsr_set_mpr_sel_timer(struct mpr_selector *mpr_sel, olsr_reltime rel_timer)
+{
+
+  olsr_set_timer(&mpr_sel->MS_timer, rel_timer, OLSR_MPR_SEL_JITTER,
+                 OLSR_TIMER_ONESHOT, &olsr_expire_mpr_sel_entry, mpr_sel, 0);
+}
+
+
+/**
+ *Add a MPR selector to the MPR selector set
+ *
+ *@param add address of the MPR selector
+ *@param vtime validity time for the new entry
+ *
+ *@return a pointer to the new entry
+ */
+struct mpr_selector *
+olsr_add_mpr_selector(const union olsr_ip_addr *addr, olsr_reltime vtime)
+{
+  struct ipaddr_str buf;
+  struct mpr_selector *new_entry;
+
+  OLSR_PRINTF(1, "MPRS: adding %s\n", olsr_ip_to_string(&buf, addr));
+
+  new_entry = olsr_malloc(sizeof(struct mpr_selector), "Add MPR selector");
+  /* Fill struct */
+  new_entry->MS_main_addr = *addr;
+  olsr_set_mpr_sel_timer(new_entry, vtime);
+  /* Queue */
+  QUEUE_ELEM(mprs_list, new_entry);
+  /*
+  new_entry->prev = &mprs_list;
+  new_entry->next = mprs_list.next;
+  mprs_list.next->prev = new_entry;
+  mprs_list.next = new_entry;
+  */
+  return new_entry;
+}
+
+
+
+/**
+ *Lookup an entry in the MPR selector table
+ *based on address
+ *
+ *@param addr the addres to check for
+ *
+ *@return a pointer to the entry or NULL
+ */
+struct mpr_selector *
+olsr_lookup_mprs_set(const union olsr_ip_addr *addr)
+{
+  struct mpr_selector *mprs;
+
+  if(addr == NULL)
+    return NULL;
+  //OLSR_PRINTF(1, "MPRS: Lookup....");
+
+  for (mprs = mprs_list.next; mprs != &mprs_list; mprs = mprs->next) {
+    if(ipequal(&mprs->MS_main_addr, addr)) {
+      //OLSR_PRINTF(1, "MATCH\n");
+      return mprs;
+    }
+  }
+  //OLSR_PRINTF(1, "NO MACH\n");
+  return NULL;
+}
+
+
+/**
+ *Update a MPR selector entry or create an new
+ *one if it does not exist
+ *
+ *@param addr the address of the MPR selector
+ *@param vtime tha validity time of the entry
+ *
+ *@return 1 if a new entry was added 0 if not
+ */
+int
+olsr_update_mprs_set(const union olsr_ip_addr *addr, olsr_reltime vtime)
+{
+  struct ipaddr_str buf;
+  struct mpr_selector *mprs = olsr_lookup_mprs_set(addr);
+
+  OLSR_PRINTF(5, "MPRS: Update %s\n", olsr_ip_to_string(&buf, addr));
+
+  if(mprs == NULL) {
+    olsr_add_mpr_selector(addr, vtime);
+    signal_link_changes(OLSR_TRUE);
+    return 1;
+  }
+  olsr_set_mpr_sel_timer(mprs, vtime);
+  return 0;
+}
+
+
+#if 0
+/**
+ *Print the current MPR selector set to STDOUT
+ */
+void
+olsr_print_mprs_set(void)
+{
+  struct mpr_selector *mprs;
+  OLSR_PRINTF(1, "MPR SELECTORS: ");
+  for(mprs = mprs_list.next; mprs != &mprs_list; mprs = mprs->next) {
+    struct ipaddr_str buf;
+    OLSR_PRINTF(1, "%s ", olsr_ip_to_string(&buf, &mprs->MS_main_addr));
+  }
+  OLSR_PRINTF(1, "\n");
+}
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr_selector_set.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr_selector_set.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/mpr_selector_set.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/mpr_selector_set.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,98 @@
+/*
+ * 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 _OLSR_MPRS_SET
+#define _OLSR_MPRS_SET
+
+#include "mantissa.h"
+
+struct mpr_selector
+{
+  union olsr_ip_addr  MS_main_addr;
+  struct timer_entry  *MS_timer;
+  struct mpr_selector *next;
+  struct mpr_selector *prev;
+};
+
+#define OLSR_MPR_SEL_JITTER 5 /* percent */
+
+#if 0
+olsr_bool
+olsr_is_mpr(void);
+#endif
+
+olsr_u16_t
+get_local_ansn(void);
+
+void
+increase_local_ansn(void);
+
+void
+olsr_init_mprs_set(void);
+
+
+struct mpr_selector *
+olsr_add_mpr_selector(const union olsr_ip_addr *, olsr_reltime);
+
+
+struct mpr_selector *
+olsr_lookup_mprs_set(const union olsr_ip_addr *);
+
+
+int
+olsr_update_mprs_set(const union olsr_ip_addr *, olsr_reltime);
+
+
+void
+olsr_time_out_mprs_set(void);
+
+#if 0
+void
+olsr_print_mprs_set(void);
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/neighbor_table.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/neighbor_table.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/neighbor_table.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/neighbor_table.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,441 @@
+/*
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "two_hop_neighbor_table.h"
+#include "mid_set.h"
+#include "mpr.h"
+#include "neighbor_table.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "link_set.h"
+#include "mpr_selector_set.h"
+#include "net_olsr.h"
+
+
+struct neighbor_entry neighbortable[HASHSIZE];
+
+
+void
+olsr_init_neighbor_table(void)
+{
+  int i;
+
+  for(i = 0; i < HASHSIZE; i++)
+    {
+      neighbortable[i].next = &neighbortable[i];
+      neighbortable[i].prev = &neighbortable[i];
+    }
+}
+
+/**
+ * Unlink, delete and free a nbr2_list entry.
+ */
+static void
+olsr_del_nbr2_list(struct neighbor_2_list_entry *nbr2_list)
+{
+  struct neighbor_entry *nbr;
+  struct neighbor_2_entry *nbr2;
+
+  nbr = nbr2_list->nbr2_nbr;
+  nbr2 = nbr2_list->neighbor_2;
+
+  if (nbr2->neighbor_2_pointer < 1) {
+      DEQUEUE_ELEM(nbr2);
+      free(nbr2);
+  }
+
+  /*
+   * Kill running timers.
+   */
+  olsr_stop_timer(nbr2_list->nbr2_list_timer);
+  nbr2_list->nbr2_list_timer = NULL;
+  
+  /* Dequeue */
+  DEQUEUE_ELEM(nbr2_list);
+  
+  free(nbr2_list);
+
+  /* Set flags to recalculate the MPR set and the routing table */
+  changes_neighborhood = OLSR_TRUE;
+  changes_topology = OLSR_TRUE;
+}
+
+/**
+ * Delete a two hop neighbor from a neighbors two hop neighbor list.
+ *
+ * @param neighbor the neighbor to delete the two hop neighbor from.
+ * @param address the IP address of the two hop neighbor to delete.
+ *
+ * @return positive if entry deleted
+ */
+int
+olsr_delete_neighbor_2_pointer(struct neighbor_entry *neighbor, union olsr_ip_addr *address)
+{
+  struct neighbor_2_list_entry *nbr2_list;
+  
+  nbr2_list = neighbor->neighbor_2_list.next;
+
+  while (nbr2_list != &neighbor->neighbor_2_list) {
+    if (ipequal(&nbr2_list->neighbor_2->neighbor_2_addr, address)) {
+      olsr_del_nbr2_list(nbr2_list);
+      return 1;	  
+    }
+    nbr2_list = nbr2_list->next;      
+  }
+  return 0;
+}
+
+
+/**
+ *Check if a two hop neighbor is reachable via a given
+ *neighbor.
+ *
+ *@param neighbor neighbor-entry to check via
+ *@param neighbor_main_address the addres of the two hop neighbor 
+ *to find.
+ *
+ *@return a pointer to the neighbor_2_list_entry struct
+ *representing the two hop neighbor if found. NULL if not found.
+ */
+struct neighbor_2_list_entry *
+olsr_lookup_my_neighbors(const struct neighbor_entry *neighbor, const union olsr_ip_addr *neighbor_main_address)
+{
+  struct neighbor_2_list_entry *entry;
+  
+  for(entry = neighbor->neighbor_2_list.next;
+      entry != &neighbor->neighbor_2_list;
+      entry = entry->next)
+    {
+      
+      if(ipequal(&entry->neighbor_2->neighbor_2_addr, neighbor_main_address))
+	return entry;
+      
+    }
+  return NULL;
+}
+
+
+
+/**
+ *Delete a neighbr table entry.
+ *
+ *Remember: Deleting a neighbor entry results 
+ *the deletion of its 2 hop neighbors list!!!
+ *@param neighbor the neighbor entry to delete
+ *
+ *@return nada
+ */
+
+int
+olsr_delete_neighbor_table(const union olsr_ip_addr *neighbor_addr)
+{  
+  struct  neighbor_2_list_entry *two_hop_list, *two_hop_to_delete;
+  olsr_u32_t                    hash;
+  struct neighbor_entry         *entry;
+
+  //printf("inserting neighbor\n");
+
+  hash = olsr_ip_hashing(neighbor_addr);
+
+  entry = neighbortable[hash].next;
+
+  /*
+   * Find neighbor entry
+   */
+  while(entry != &neighbortable[hash])
+    {
+      if(ipequal(&entry->neighbor_main_addr, neighbor_addr))
+	break;
+      
+      entry = entry->next;
+    }
+
+  if(entry == &neighbortable[hash])
+    return 0;
+
+
+  two_hop_list = entry->neighbor_2_list.next;
+
+  while (two_hop_list != &entry->neighbor_2_list) {
+      two_hop_to_delete = two_hop_list;
+      two_hop_list = two_hop_list->next;
+
+      two_hop_to_delete->neighbor_2->neighbor_2_pointer--;
+      olsr_delete_neighbor_pointer(two_hop_to_delete->neighbor_2,
+                                   &entry->neighbor_main_addr);
+
+      olsr_del_nbr2_list(two_hop_to_delete);
+    }
+
+
+  /* Dequeue */
+  DEQUEUE_ELEM(entry);
+
+  free(entry);
+
+  changes_neighborhood = OLSR_TRUE;
+  return 1;
+
+}
+
+
+
+/**
+ *Insert a neighbor entry in the neighbor table
+ *
+ *@param main_addr the main address of the new node
+ *
+ *@return 0 if neighbor already exists 1 if inserted
+ */
+struct neighbor_entry *
+olsr_insert_neighbor_table(const union olsr_ip_addr *main_addr)
+{
+  olsr_u32_t             hash;
+  struct neighbor_entry  *new_neigh;
+  
+  hash = olsr_ip_hashing(main_addr);
+
+  /* Check if entry exists */
+  
+  for(new_neigh = neighbortable[hash].next;
+      new_neigh != &neighbortable[hash];
+      new_neigh = new_neigh->next)
+    {
+      if(ipequal(&new_neigh->neighbor_main_addr, main_addr))
+	return new_neigh;
+    }
+  
+  //printf("inserting neighbor\n");
+  
+  new_neigh = olsr_malloc(sizeof(struct neighbor_entry), "New neighbor entry");
+  
+  /* Set address, willingness and status */
+  new_neigh->neighbor_main_addr = *main_addr;
+  new_neigh->willingness = WILL_NEVER;
+  new_neigh->status = NOT_SYM;
+
+  new_neigh->neighbor_2_list.next = &new_neigh->neighbor_2_list;
+  new_neigh->neighbor_2_list.prev = &new_neigh->neighbor_2_list;
+  
+  new_neigh->linkcount = 0;
+  new_neigh->is_mpr = OLSR_FALSE;
+  new_neigh->was_mpr = OLSR_FALSE;
+
+  /* Queue */
+  QUEUE_ELEM(neighbortable[hash], new_neigh);
+
+  return new_neigh;
+}
+
+
+
+/**
+ *Lookup a neighbor entry in the neighbortable based on an address.
+ *
+ *@param dst the IP address of the neighbor to look up
+ *
+ *@return a pointer to the neighbor struct registered on the given 
+ *address. NULL if not found.
+ */
+struct neighbor_entry *
+olsr_lookup_neighbor_table(const union olsr_ip_addr *dst)
+{
+  /*
+   *Find main address of node
+   */
+  union olsr_ip_addr *tmp_ip = mid_lookup_main_addr(dst);
+  if(tmp_ip != NULL)
+    dst = tmp_ip;
+  return olsr_lookup_neighbor_table_alias(dst);
+}
+
+
+/**
+ *Lookup a neighbor entry in the neighbortable based on an address.
+ *
+ *@param dst the IP address of the neighbor to look up
+ *
+ *@return a pointer to the neighbor struct registered on the given 
+ *address. NULL if not found.
+ */
+struct neighbor_entry *
+olsr_lookup_neighbor_table_alias(const union olsr_ip_addr *dst)
+{
+  struct neighbor_entry  *entry;
+  olsr_u32_t             hash = olsr_ip_hashing(dst);
+  
+  //printf("\nLookup %s\n", olsr_ip_to_string(&buf, dst));
+  for(entry = neighbortable[hash].next;
+      entry != &neighbortable[hash];
+      entry = entry->next)
+    {
+      //printf("Checking %s\n", olsr_ip_to_string(&buf, &entry->neighbor_main_addr));
+      if(ipequal(&entry->neighbor_main_addr, dst))
+	return entry;
+      
+    }
+  //printf("NOPE\n\n");
+
+  return NULL;
+
+}
+
+
+
+int
+update_neighbor_status(struct neighbor_entry *entry, int lnk)
+{
+  /*
+   * Update neighbor entry
+   */
+ 
+  if(lnk == SYM_LINK)
+    {
+      /* N_status is set to SYM */
+      if(entry->status == NOT_SYM)
+	{
+	  struct neighbor_2_entry *two_hop_neighbor;
+	  
+	  /* Delete posible 2 hop entry on this neighbor */
+	  if((two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&entry->neighbor_main_addr))!=NULL)
+	    {
+	      olsr_delete_two_hop_neighbor_table(two_hop_neighbor);
+	    }
+  
+	  changes_neighborhood = OLSR_TRUE;
+	  changes_topology = OLSR_TRUE;
+	  if(olsr_cnf->tc_redundancy > 1)
+	    signal_link_changes(OLSR_TRUE);
+	}
+      entry->status = SYM;
+    }
+  else
+    {
+      if(entry->status == SYM)
+	{
+	  changes_neighborhood = OLSR_TRUE;
+	  changes_topology = OLSR_TRUE;
+	  if(olsr_cnf->tc_redundancy > 1)
+	    signal_link_changes(OLSR_TRUE);
+	}
+      /* else N_status is set to NOT_SYM */
+      entry->status = NOT_SYM;
+      /* remove neighbor from routing list */
+    }
+
+  return entry->status;
+}
+
+
+/**
+ * Callback for the nbr2_list timer.
+ */
+void
+olsr_expire_nbr2_list(void *context)
+{
+  struct neighbor_2_list_entry *nbr2_list;
+  struct neighbor_entry *nbr;
+  struct neighbor_2_entry *nbr2; 
+
+  nbr2_list = (struct neighbor_2_list_entry *)context;
+  nbr2_list->nbr2_list_timer = NULL;
+
+  nbr = nbr2_list->nbr2_nbr;
+  nbr2 = nbr2_list->neighbor_2;
+
+  nbr2->neighbor_2_pointer--;
+  olsr_delete_neighbor_pointer(nbr2, &nbr->neighbor_main_addr); 
+
+  olsr_del_nbr2_list(nbr2_list);
+}
+
+
+/**
+ *Prints the registered neighbors and two hop neighbors
+ *to STDOUT.
+ *
+ *@return nada
+ */
+void
+olsr_print_neighbor_table(void)
+{
+#ifdef NODEBUG
+  /* The whole function doesn't do anything else. */
+#ifndef NODEBUG
+  const int iplen = olsr_cnf->ip_version == AF_INET ?  15 : 39;
+#endif
+  int idx;
+  OLSR_PRINTF(1, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------ NEIGHBORS\n\n"
+              "%*s  LQ     NLQ    SYM   MPR   MPRS  will\n",
+              nowtm->tm_hour,
+              nowtm->tm_min,
+              nowtm->tm_sec,
+              (int)now.tv_usec/10000,
+              iplen,
+              "IP address");
+
+  for (idx = 0; idx < HASHSIZE; idx++) {
+    struct neighbor_entry *neigh;
+    for(neigh = neighbortable[idx].next; neigh != &neighbortable[idx]; neigh = neigh->next) {
+      struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
+      if(lnk) {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(1, "%-*s  %5.3f  %5.3f  %s  %s  %s  %d\n",
+                    iplen,
+                    olsr_ip_to_string(&buf, &neigh->neighbor_main_addr),
+                    lnk->loss_link_quality,
+                    lnk->neigh_link_quality,
+                    neigh->status == SYM ? "YES " : "NO  ",
+                    neigh->is_mpr ? "YES " : "NO  ", 
+                    olsr_lookup_mprs_set(&neigh->neighbor_main_addr) == NULL ? "NO  " : "YES ",
+                    neigh->willingness);
+      }
+    }
+  }
+#endif
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/neighbor_table.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/neighbor_table.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/neighbor_table.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/neighbor_table.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,132 @@
+/*
+ * 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 _OLSR_NEIGH_TBL
+#define _OLSR_NEIGH_TBL
+
+#include "olsr_types.h"
+#include "hashing.h"
+
+
+struct neighbor_2_list_entry 
+{
+  struct neighbor_entry *nbr2_nbr; /* backpointer to owning nbr entry */
+  struct neighbor_2_entry      *neighbor_2;
+  struct timer_entry *nbr2_list_timer;
+  struct neighbor_2_list_entry *next;
+  struct neighbor_2_list_entry *prev;
+};
+
+#define OLSR_NBR2_LIST_JITTER 5 /* percent */
+
+struct neighbor_entry
+{
+  union olsr_ip_addr           neighbor_main_addr;
+  olsr_u8_t                    status;
+  olsr_u8_t                    willingness;
+  olsr_bool                    is_mpr;
+  olsr_bool                    was_mpr; /* Used to detect changes in MPR */
+  olsr_bool                    skip;
+  int                          neighbor_2_nocov;
+  int                          linkcount;
+  struct neighbor_2_list_entry neighbor_2_list; 
+  struct neighbor_entry        *next;
+  struct neighbor_entry        *prev;
+};
+
+#define OLSR_FOR_ALL_NBR_ENTRIES(nbr) \
+{ \
+  int _idx; \
+  for (_idx = 0; _idx < HASHSIZE; _idx++) { \
+    for(nbr = neighbortable[_idx].next; \
+        nbr != &neighbortable[_idx]; \
+        nbr = nbr->next)
+#define OLSR_FOR_ALL_NBR_ENTRIES_END(nbr) }}
+
+
+/*
+ * The neighbor table
+ */
+extern struct neighbor_entry neighbortable[HASHSIZE];
+
+
+void
+olsr_init_neighbor_table(void);
+
+int
+olsr_delete_neighbor_2_pointer(struct neighbor_entry *, union olsr_ip_addr *);
+
+struct neighbor_2_list_entry *
+olsr_lookup_my_neighbors(const struct neighbor_entry *, const union olsr_ip_addr *);
+
+int
+olsr_delete_neighbor_table(const union olsr_ip_addr *);
+
+struct neighbor_entry *
+olsr_insert_neighbor_table(const union olsr_ip_addr *);
+
+struct neighbor_entry *
+olsr_lookup_neighbor_table(const union olsr_ip_addr *);
+
+struct neighbor_entry *
+olsr_lookup_neighbor_table_alias(const union olsr_ip_addr *);
+
+void
+olsr_time_out_two_hop_neighbors(struct neighbor_entry  *);
+
+void
+olsr_time_out_neighborhood_tables(void);
+void olsr_expire_nbr2_list(void *);
+
+void
+olsr_print_neighbor_table(void);
+
+
+int
+update_neighbor_status(struct neighbor_entry *, int);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/net_olsr.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/net_olsr.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/net_olsr.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/net_olsr.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,494 @@
+/*
+ * 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 "net_olsr.h"
+#include "ipcalc.h"
+#include "log.h"
+#include "olsr.h"
+#include "net_os.h"
+#include "print_packet.h"
+#include "link_set.h"
+#include "lq_packet.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+
+static olsr_bool disp_pack_out = OLSR_FALSE;
+
+
+#ifdef WIN32
+#define perror(x) WinSockPError(x)
+void
+WinSockPError(const char *);
+#endif
+
+
+struct deny_address_entry
+{
+  union olsr_ip_addr        addr;
+  struct deny_address_entry *next;
+};
+
+
+/* Packet transform functions */
+
+struct ptf
+{
+  packet_transform_function function;
+  struct ptf *next;
+};
+
+static struct ptf *ptf_list;
+
+static struct deny_address_entry *deny_entries;
+
+static const char * const deny_ipv4_defaults[] =
+  {
+    "0.0.0.0",
+    "127.0.0.1",
+    NULL
+  };
+
+static const char * const deny_ipv6_defaults[] =
+  {
+    "0::0",
+    "0::1",
+    NULL
+  };
+
+void
+net_set_disp_pack_out(olsr_bool val)
+{
+  disp_pack_out = val;
+}
+
+/*
+ * Converts each invalid IP-address from string to network byte order
+ * and adds it to the invalid list.
+ *
+ * TODO: rename function
+ */
+void
+init_net(void)
+{
+  const char * const *defaults = (olsr_cnf->ip_version == AF_INET) ? deny_ipv4_defaults : deny_ipv6_defaults;
+  
+  for (; *defaults != NULL; defaults++) {
+    union olsr_ip_addr addr;
+    if(inet_pton(olsr_cnf->ip_version, *defaults, &addr) <= 0){
+      fprintf(stderr, "Error converting fixed IP %s for deny rule!!\n", *defaults);
+      continue;
+    }
+    olsr_add_invalid_address(&addr);
+  }
+}
+
+/**
+ * Create an outputbuffer for the given interface. This
+ * function will allocate the needed storage according 
+ * to the MTU of the interface.
+ *
+ * @param ifp the interface to create a buffer for
+ *
+ * @return 0 on success, negative if a buffer already existed
+ *  for the given interface
+ */ 
+int
+net_add_buffer(struct interface *ifp)
+{
+  /* Can the interfaces MTU actually change? If not, we can elimiate
+   * the "bufsize" field in "struct olsr_netbuf".
+   */
+  if (ifp->netbuf.bufsize != ifp->int_mtu && ifp->netbuf.buff != NULL) {
+    free(ifp->netbuf.buff);
+    ifp->netbuf.buff = NULL;
+  }
+  
+  if (ifp->netbuf.buff == NULL) {
+    ifp->netbuf.buff = olsr_malloc(ifp->int_mtu, "add_netbuff");
+  }
+
+  /* Fill struct */
+  ifp->netbuf.bufsize = ifp->int_mtu;
+  ifp->netbuf.maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
+
+  ifp->netbuf.pending = 0;
+  ifp->netbuf.reserved = 0;
+
+  return 0;
+}
+
+/**
+ * Remove a outputbuffer. Frees the allocated memory.
+ *
+ * @param ifp the interface corresponding to the buffer
+ * to remove
+ *
+ * @return 0 on success, negative if no buffer is found
+ */
+int
+net_remove_buffer(struct interface *ifp)
+{
+  /* Flush pending data */
+  if(ifp->netbuf.pending)
+    net_output(ifp);
+
+  free(ifp->netbuf.buff);
+  ifp->netbuf.buff = NULL;
+
+  return 0;
+}
+
+
+/**
+ * Reserve space in a outputbuffer. This should only be needed
+ * in very special cases. This will decrease the reported size
+ * of the buffer so that there is always <i>size</i> bytes
+ * of data available in the buffer. To add data in the reserved
+ * area one must use the net_outbuffer_push_reserved function.
+ *
+ * @param ifp the interface corresponding to the buffer
+ * to reserve space on
+ * @param size the number of bytes to reserve
+ *
+ * @return 0 on success, negative if there was not enough
+ *  bytes to reserve
+ */
+int
+net_reserve_bufspace(struct interface *ifp, int size)
+{
+  if(size > ifp->netbuf.maxsize)
+    return -1;
+  
+  ifp->netbuf.reserved = size;
+  ifp->netbuf.maxsize -= size;
+  
+  return 0;
+}
+
+/**
+ * Returns the number of bytes pending in the buffer. That
+ * is the number of bytes added but not sent.
+ *
+ * @param ifp the interface corresponding to the buffer
+ *
+ * @return the number of bytes currently pending
+ */
+olsr_u16_t
+net_output_pending(const struct interface *ifp)
+{
+  return ifp->netbuf.pending;
+}
+
+
+
+/**
+ * Add data to a buffer.
+ *
+ * @param ifp the interface corresponding to the buffer
+ * @param data a pointer to the data to add
+ * @param size the number of byte to copy from data
+ *
+ * @return -1 if no buffer was found, 0 if there was not 
+ *  enough room in buffer or the number of bytes added on 
+ *  success
+ */
+int
+net_outbuffer_push(struct interface *ifp, const void *data, const olsr_u16_t size)
+{
+  if((ifp->netbuf.pending + size) > ifp->netbuf.maxsize)
+    return 0;
+
+  memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
+  ifp->netbuf.pending += size;
+
+  return size;
+}
+
+
+/**
+ * Add data to the reserved part of a buffer
+ *
+ * @param ifp the interface corresponding to the buffer
+ * @param data a pointer to the data to add
+ * @param size the number of byte to copy from data
+ *
+ * @return -1 if no buffer was found, 0 if there was not 
+ *  enough room in buffer or the number of bytes added on 
+ *  success
+ */
+int
+net_outbuffer_push_reserved(struct interface *ifp, const void *data, const olsr_u16_t size)
+{
+  if((ifp->netbuf.pending + size) > (ifp->netbuf.maxsize + ifp->netbuf.reserved))
+    return 0;
+
+  memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
+  ifp->netbuf.pending += size;
+
+  return size;
+}
+
+/**
+ * Report the number of bytes currently available in the buffer
+ * (not including possible reserved bytes)
+ *
+ * @param ifp the interface corresponding to the buffer
+ *
+ * @return the number of bytes available in the buffer or
+ */
+int
+net_outbuffer_bytes_left(const struct interface *ifp)
+{
+  return ifp->netbuf.maxsize - ifp->netbuf.pending;
+}
+
+
+/**
+ * Add a packet transform function. Theese are functions
+ * called just prior to sending data in a buffer.
+ *
+ * @param f the function pointer
+ *
+ * @returns 1
+ */
+int
+add_ptf(packet_transform_function f)
+{
+
+  struct ptf *new_ptf;
+
+  new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
+
+  new_ptf->next = ptf_list;
+  new_ptf->function = f;
+
+  ptf_list = new_ptf;
+
+  return 1;
+}
+
+/**
+ * Remove a packet transform function
+ *
+ * @param f the function pointer
+ *
+ * @returns 1 if a functionpointer was removed
+ *  0 if not
+ */
+int
+del_ptf(packet_transform_function f)
+{
+  struct ptf *prev = NULL;
+  struct ptf *tmp_ptf = ptf_list;
+  while(tmp_ptf)
+    {
+      if(tmp_ptf->function == f)
+	{
+	  /* Remove entry */
+	  if(prev == NULL)
+	      ptf_list = tmp_ptf->next;
+	  else
+	      prev->next = tmp_ptf->next;
+          free(tmp_ptf);
+	  return 1;
+	}
+      prev = tmp_ptf;
+      tmp_ptf = tmp_ptf->next;
+    }
+
+  return 0;
+}
+
+/**
+ *Sends a packet on a given interface.
+ *
+ *@param ifp the interface to send on.
+ *
+ *@return negative on error
+ */
+int
+net_output(struct interface *ifp)
+{
+  struct sockaddr_in *sin = NULL;
+  struct sockaddr_in6 *sin6 = NULL;
+  struct ptf *tmp_ptf_list;
+  union olsr_packet *outmsg;
+  int retval;
+
+  if(!ifp->netbuf.pending)
+    return 0;
+
+  ifp->netbuf.pending += OLSR_HEADERSIZE;
+
+  retval = ifp->netbuf.pending;
+
+  outmsg = (union olsr_packet *)ifp->netbuf.buff;
+  /* Add the Packet seqno */
+  outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
+  /* Set the packetlength */
+  outmsg->v4.olsr_packlen = htons(ifp->netbuf.pending);
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      struct sockaddr_in dst;
+      /* IP version 4 */
+      sin = (struct sockaddr_in *)&ifp->int_broadaddr;
+
+      /* Copy sin */
+      dst = *sin;
+      sin = &dst;
+
+      if (sin->sin_port == 0)
+	sin->sin_port = htons(OLSRPORT);
+    }
+  else
+    {
+      struct sockaddr_in6 dst6;
+      /* IP version 6 */
+      sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
+      /* Copy sin */
+      dst6 = *sin6;
+      sin6 = &dst6;
+    }
+
+  /*
+   *Call possible packet transform functions registered by plugins  
+   */
+  for (tmp_ptf_list = ptf_list; tmp_ptf_list != NULL; tmp_ptf_list = tmp_ptf_list->next)
+    {
+      tmp_ptf_list->function(ifp->netbuf.buff, &ifp->netbuf.pending);
+    }
+
+  /*
+   *if the -dispout option was given
+   *we print the content of the packets
+   */
+  if(disp_pack_out)
+    print_olsr_serialized_packet(stdout, (union olsr_packet *)ifp->netbuf.buff, 
+				 ifp->netbuf.pending, &ifp->ip_addr); 
+  
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IP version 4 */
+      if(olsr_sendto(ifp->olsr_socket, 
+                     ifp->netbuf.buff, 
+		     ifp->netbuf.pending, 
+		     MSG_DONTROUTE, 
+		     (struct sockaddr *)sin, 
+		     sizeof (*sin))
+	 < 0)
+	{
+	  perror("sendto(v4)");
+	  olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
+	  retval = -1;
+	}
+    }
+  else
+    {
+      /* IP version 6 */
+      if(olsr_sendto(ifp->olsr_socket, 
+		     ifp->netbuf.buff,
+		     ifp->netbuf.pending, 
+		     MSG_DONTROUTE, 
+		     (struct sockaddr *)sin6, 
+		     sizeof (*sin6))
+	 < 0)
+	{
+          struct ipaddr_str buf;
+	  perror("sendto(v6)");
+	  olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
+	  fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_index);
+	  fprintf(stderr, "To: %s (size: %u)\n", ip6_to_string(&buf, &sin6->sin6_addr), (unsigned int)sizeof(*sin6));
+	  fprintf(stderr, "Outputsize: %d\n", ifp->netbuf.pending);
+	  retval = -1;
+	}
+    }
+  
+  ifp->netbuf.pending = 0;
+
+  /*
+   * if we've just transmitted a TC message, let Dijkstra use the current
+   * link qualities for the links to our neighbours
+   */
+
+  lq_tc_pending = OLSR_FALSE;
+
+  return retval;
+}
+
+/*
+ * Adds the given IP-address to the invalid list. 
+ */
+void
+olsr_add_invalid_address(const union olsr_ip_addr *adr)
+{
+  struct ipaddr_str buf;
+  struct deny_address_entry *new_entry = olsr_malloc(sizeof(struct deny_address_entry), "Add deny address");
+
+  new_entry->addr = *adr;
+  new_entry->next = deny_entries;
+  deny_entries = new_entry;
+  OLSR_PRINTF(1, "Added %s to IP deny set\n", olsr_ip_to_string(&buf, &new_entry->addr));
+}
+
+
+olsr_bool
+olsr_validate_address(const union olsr_ip_addr *adr)
+{
+  const struct deny_address_entry *deny_entry;
+
+  for (deny_entry = deny_entries; deny_entry != NULL; deny_entry = deny_entry->next) {
+    if(ipequal(adr, &deny_entry->addr))	{
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "Validation of address %s failed!\n", olsr_ip_to_string(&buf, adr));
+      return OLSR_FALSE;
+    }
+    if (deny_entry == (struct deny_address_entry *)&olsr_cnf->main_addr) break;
+  }
+  return OLSR_TRUE;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/net_olsr.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/net_olsr.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/net_olsr.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/net_olsr.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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 _NET_OLSR
+#define _NET_OLSR
+
+#include "olsr_types.h"
+#include "interfaces.h"
+#include "process_routes.h"
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+typedef int (*packet_transform_function)(olsr_u8_t *, int *);
+
+void
+net_set_disp_pack_out(olsr_bool);
+
+void
+init_net(void);
+
+int
+net_add_buffer(struct interface *);
+
+int
+net_remove_buffer(struct interface *);
+
+int
+net_outbuffer_bytes_left(const struct interface *);
+
+olsr_u16_t
+net_output_pending(const struct interface *);
+
+int
+net_reserve_bufspace(struct interface *, int);
+
+int
+net_outbuffer_push(struct interface *, const void *, const olsr_u16_t);
+
+int
+net_outbuffer_push_reserved(struct interface *, const void *, const olsr_u16_t);
+
+int
+net_output(struct interface *);
+
+int
+net_sendroute(struct rt_entry *, struct sockaddr *);
+
+int
+add_ptf(packet_transform_function);
+
+int
+del_ptf(packet_transform_function);
+
+olsr_bool
+olsr_validate_address(const union olsr_ip_addr *);
+
+void
+olsr_add_invalid_address(const union olsr_ip_addr *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/net_os.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/net_os.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/net_os.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/net_os.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ */
+
+
+/*
+ * This file defines the OS dependent network related functions
+ * that MUST be available to olsrd.
+ * The implementations of the functions should be found in
+ * <OS>/net.c (e.g. linux/net.c)
+ */
+
+
+#ifndef _OLSR_NET_OS_H
+#define _OLSR_NET_OS_H
+
+#include "olsr_types.h"
+#include "interfaces.h"
+
+/* OS dependent functions */
+ssize_t
+olsr_sendto(int, 
+	    const void *, 
+	    size_t, 
+	    int, 
+	    const struct sockaddr *, 
+	    socklen_t);
+
+ssize_t  
+olsr_recvfrom(int, 
+	      void *, 
+	      size_t, 
+	      int, 
+	      struct sockaddr *,
+	      socklen_t *);
+
+int
+olsr_select(int, 
+	    fd_set *, 
+	    fd_set *, 
+	    fd_set *, 
+	    struct timeval *);
+
+int
+bind_socket_to_device(int, char *);
+
+int
+convert_ip_to_mac(union olsr_ip_addr *, struct sockaddr *, char *);
+
+int
+disable_redirects(const char *, struct interface *, int);
+
+int
+disable_redirects_global(int);
+
+int
+deactivate_spoof(const char *, struct interface *, int);
+
+int
+restore_settings(int);
+
+int
+enable_ip_forwarding(int);
+
+int
+gethemusocket(struct sockaddr_in *);
+
+int  
+getsocket(int, char *);
+
+int  
+getsocket6(int, char *);
+
+int
+get_ipv6_address(char *, struct sockaddr_in6 *, int);
+
+int
+calculate_if_metric(char *);
+
+int
+check_wireless_interface(char *);
+
+olsr_bool
+is_if_link_up(char *);
+
+int
+join_mcast(struct interface *, int);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,628 @@
+/*
+ * 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.
+ *
+ */
+
+/**
+ * All these functions are global
+ */
+
+#include "defs.h"
+#include "olsr.h"
+#include "link_set.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "duplicate_set.h"
+#include "mpr_selector_set.h"
+#include "mid_set.h"
+#include "mpr.h"
+#include "lq_mpr.h"
+#include "olsr_spf.h"
+#include "scheduler.h"
+#include "apm.h"
+#include "misc.h"
+#include "neighbor_table.h"
+#include "log.h"
+#include "lq_packet.h"
+#include "common/avl.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+
+#include <stdarg.h>
+#include <signal.h>
+
+
+olsr_bool changes_topology;
+olsr_bool changes_neighborhood;
+olsr_bool changes_hna;
+olsr_bool changes_force;
+
+/**
+ * Process changes functions
+ */
+
+struct pcf
+{
+  int (*function)(int, int, int);
+  struct pcf *next;
+};
+
+static struct pcf *pcf_list;
+
+static olsr_u16_t message_seqno;
+union olsr_ip_addr all_zero;
+
+/**
+ *Initialize the message sequence number as a random value
+ */
+void
+init_msg_seqno(void)
+{
+  message_seqno = random() & 0xFFFF;
+}
+
+/**
+ * Get and increment the message sequence number
+ *
+ *@return the seqno
+ */
+olsr_u16_t
+get_msg_seqno(void)
+{
+  return message_seqno++;
+}
+
+
+void
+register_pcf(int (*f)(int, int, int))
+{
+  struct pcf *new_pcf;
+
+  OLSR_PRINTF(1, "Registering pcf function\n");
+
+  new_pcf = olsr_malloc(sizeof(struct pcf), "New PCF");
+
+  new_pcf->function = f;
+  new_pcf->next = pcf_list;
+  pcf_list = new_pcf;
+
+}
+
+
+/**
+ *Process changes in neighborhood or/and topology.
+ *Re-calculates the neighborhood/topology if there
+ *are any updates - then calls the right functions to
+ *update the routing table.
+ *@return 0
+ */
+void
+olsr_process_changes(void)
+{
+  struct pcf *tmp_pc_list;
+
+#ifdef DEBUG
+  if(changes_neighborhood)
+    OLSR_PRINTF(3, "CHANGES IN NEIGHBORHOOD\n");
+  if(changes_topology)
+    OLSR_PRINTF(3, "CHANGES IN TOPOLOGY\n");
+  if(changes_hna)
+    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)
+    return;
+
+  if (olsr_cnf->debug_level > 0 && olsr_cnf->clear_screen && isatty(1))
+  {
+      clear_console();
+      printf("       *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host);
+  }
+
+  if (changes_neighborhood) {
+    if (olsr_cnf->lq_level < 1) {
+      olsr_calculate_mpr();
+    } else {
+      olsr_calculate_lq_mpr();
+    }
+  }
+
+  /* calculate the routing table */
+  if (changes_neighborhood || changes_topology || changes_hna) {
+    olsr_calculate_routing_table();
+  }
+  
+  if (olsr_cnf->debug_level > 0)
+    {      
+      if (olsr_cnf->debug_level > 2) 
+        {
+          olsr_print_mid_set();
+	  
+          if (olsr_cnf->debug_level > 3)
+            {
+             if (olsr_cnf->debug_level > 8)
+               {
+                 olsr_print_duplicate_table();
+               }
+              olsr_print_hna_set();
+            }
+        }
+
+#if 1     
+      olsr_print_link_set();
+      olsr_print_neighbor_table();
+      olsr_print_two_hop_neighbor_table();
+      olsr_print_tc_table();
+#endif
+    }
+
+  for(tmp_pc_list = pcf_list; 
+      tmp_pc_list != NULL;
+      tmp_pc_list = tmp_pc_list->next)
+    {
+      tmp_pc_list->function(changes_neighborhood,
+			    changes_topology,
+			    changes_hna);
+    }
+
+  changes_neighborhood = OLSR_FALSE;
+  changes_topology = OLSR_FALSE;
+  changes_hna = OLSR_FALSE;
+  changes_force = OLSR_FALSE;
+}
+
+/*
+ * Callback for the periodic route calculation.
+ */
+void
+olsr_trigger_forced_update(void *unused __attribute__((unused))) {
+
+  changes_force = OLSR_TRUE;
+  changes_neighborhood = OLSR_TRUE;
+  changes_topology = OLSR_TRUE;
+  changes_hna = OLSR_TRUE;
+  
+  olsr_process_changes();
+}
+
+/**
+ *Initialize all the tables used(neighbor,
+ *topology, MID,  HNA, MPR, dup).
+ *Also initalizes other variables
+ */
+void
+olsr_init_tables(void)
+{  
+  changes_topology = OLSR_FALSE;
+  changes_neighborhood = OLSR_FALSE;
+  changes_hna = OLSR_FALSE;
+
+  /* Set avl tree comparator */
+  if (olsr_cnf->ipsize == 4) {
+    avl_comp_default = avl_comp_ipv4;
+    avl_comp_prefix_default = avl_comp_ipv4_prefix;
+  } else {
+    avl_comp_default = avl_comp_ipv6;
+    avl_comp_prefix_default = avl_comp_ipv6_prefix;
+  }
+
+  /* Initialize lq plugin set */
+  init_lq_handler_tree();
+  
+  /* Initialize link set */
+  olsr_init_link_set();
+
+  /* Initialize duplicate table */
+  olsr_init_duplicate_set();
+
+  /* Initialize neighbor table */
+  olsr_init_neighbor_table();
+
+  /* Initialize routing table */
+  olsr_init_routing_table();
+
+  /* Initialize two hop table */
+  olsr_init_two_hop_table();
+
+  /* Initialize topology */
+  olsr_init_tc();
+
+  /* Initialize mpr selector table */
+  olsr_init_mprs_set();
+
+  /* Initialize MID set */
+  olsr_init_mid_set();
+
+  /* Initialize HNA set */
+  olsr_init_hna_set();  
+
+#if 0
+  /* Initialize Layer 1/2 database */
+  olsr_initialize_layer12();
+#endif
+  
+  /* Start periodic SPF and RIB recalculation */
+  if (olsr_cnf->lq_dinter > 0.0) {
+    olsr_start_timer((unsigned int)(olsr_cnf->lq_dinter * MSEC_PER_SEC), 5,
+                     OLSR_TIMER_PERIODIC, &olsr_trigger_forced_update, NULL, 0);
+  }
+}
+
+/**
+ *Check if a message is to be forwarded and forward
+ *it if necessary.
+ *
+ *@param m the OLSR message recieved
+ *@param originator the originator of this message
+ *@param seqno the seqno of the message
+ *
+ *@returns positive if forwarded
+ */
+int
+olsr_forward_message(union olsr_message *m, 
+		     union olsr_ip_addr *from_addr)
+{
+  union olsr_ip_addr *src;
+  struct neighbor_entry *neighbor;
+  int msgsize;
+  struct interface *ifn;
+
+  /*
+   * Sven-Ola: We should not flood the mesh with overdue messages. Because
+   * of a bug in parser.c:parse_packet, we have a lot of messages because
+   * all older olsrd's have lq_fish enabled.
+   */
+  if (AF_INET == olsr_cnf->ip_version)
+  {
+    if (2 > m->v4.ttl || 255 < (int)m->v4.hopcnt + (int)m->v4.ttl) return 0;
+  }
+  else
+  {
+    if (2 > m->v6.ttl || 255 < (int)m->v6.hopcnt + (int)m->v6.ttl) return 0;
+  }
+
+  /* Lookup sender address */
+  src = mid_lookup_main_addr(from_addr);
+  if(!src)
+    src = from_addr;
+
+  neighbor=olsr_lookup_neighbor_table(src);
+  if(!neighbor)
+    return 0;
+
+  if(neighbor->status != SYM)
+    return 0;
+
+  /* Check MPR */
+  if(olsr_lookup_mprs_set(src) == NULL)
+    {
+#ifdef DEBUG
+      struct ipaddr_str buf;
+      OLSR_PRINTF(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(&buf, src));
+#endif
+      return 0;
+    }
+
+  /* Treat TTL hopcnt */
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IPv4 */
+      m->v4.hopcnt++;
+      m->v4.ttl--; 
+    }
+  else
+    {
+      /* IPv6 */
+      m->v6.hopcnt++;
+      m->v6.ttl--; 
+    }
+
+  /* Update packet data */
+  msgsize = ntohs(m->v4.olsr_msgsize);
+
+  /* looping trough interfaces */
+  for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
+    { 
+      if(net_output_pending(ifn))
+	{
+	  /*
+	   * Check if message is to big to be piggybacked
+	   */
+	  if(net_outbuffer_push(ifn, m, msgsize) != msgsize)
+	    {
+	      /* Send */
+	      net_output(ifn);
+	      /* Buffer message */
+	      set_buffer_timer(ifn);
+	      
+	      if(net_outbuffer_push(ifn, m, msgsize) != msgsize)
+		{
+		  OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
+		  olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
+		}
+	    }
+	}
+      else
+	{
+	  /* No forwarding pending */
+	  set_buffer_timer(ifn);
+	  
+	  if(net_outbuffer_push(ifn, m, msgsize) != msgsize)
+	    {
+	      OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
+	      olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize);
+	    }
+	}
+    }
+  return 1;
+}
+
+
+void
+set_buffer_timer(struct interface *ifn)
+{      
+  /* Set timer */
+  ifn->fwdtimer = GET_TIMESTAMP(random() * olsr_cnf->max_jitter * MSEC_PER_SEC / RAND_MAX);
+}
+
+void
+olsr_init_willingness(void)
+{
+  if (olsr_cnf->willingness_auto) {
+
+    /* Run it first and then periodic. */
+    olsr_update_willingness(NULL);
+
+    olsr_start_timer((unsigned int)olsr_cnf->will_int * MSEC_PER_SEC, 5,
+                     OLSR_TIMER_PERIODIC, &olsr_update_willingness, NULL, 0);
+  }
+}
+
+void
+olsr_update_willingness(void *foo __attribute__((unused)))
+{
+  int tmp_will = olsr_cnf->willingness;
+
+  /* Re-calculate willingness */
+  olsr_cnf->willingness = olsr_calculate_willingness();
+
+  if(tmp_will != olsr_cnf->willingness)
+    {
+      OLSR_PRINTF(1, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
+    }
+}
+
+
+/**
+ *Calculate this nodes willingness to act as a MPR
+ *based on either a fixed value or the power status
+ *of the node using APM
+ *
+ *@return a 8bit value from 0-7 representing the willingness
+ */
+
+olsr_u8_t
+olsr_calculate_willingness(void)
+{
+  struct olsr_apm_info ainfo;
+
+  /* If fixed willingness */
+  if(!olsr_cnf->willingness_auto)
+    return olsr_cnf->willingness;
+
+  if(apm_read(&ainfo) < 1)
+    return WILL_DEFAULT;
+
+  apm_printinfo(&ainfo);
+
+  /* If AC powered */
+  if(ainfo.ac_line_status == OLSR_AC_POWERED)
+    return 6;
+
+  /* If battery powered 
+   *
+   * juice > 78% will: 3
+   * 78% > juice > 26% will: 2
+   * 26% > juice will: 1
+   */
+  return (ainfo.battery_percentage / 26);
+}
+
+const char *
+olsr_msgtype_to_string(olsr_u8_t msgtype)
+{
+  static char type[20];
+
+  switch(msgtype)
+    {
+    case(HELLO_MESSAGE):
+      return "HELLO";
+    case(TC_MESSAGE):
+      return "TC";
+    case(MID_MESSAGE):
+      return "MID";
+    case(HNA_MESSAGE):
+      return "HNA";
+    case(LQ_HELLO_MESSAGE):
+      return("LQ-HELLO");
+    case(LQ_TC_MESSAGE):
+      return("LQ-TC");
+    default:
+      break;
+    }
+
+  snprintf(type, sizeof(type), "UNKNOWN(%d)", msgtype);
+  return type;
+}
+
+
+const char *
+olsr_link_to_string(olsr_u8_t linktype)
+{
+  static char type[20];
+
+  switch(linktype)
+    {
+    case(UNSPEC_LINK):
+      return "UNSPEC";
+    case(ASYM_LINK):
+      return "ASYM";
+    case(SYM_LINK):
+      return "SYM";
+    case(LOST_LINK):
+      return "LOST";
+    case(HIDE_LINK):
+      return "HIDE";
+    default:
+      break;
+    }
+
+  snprintf(type, sizeof(type), "UNKNOWN(%d)", linktype);
+  return type;
+}
+
+
+const char *
+olsr_status_to_string(olsr_u8_t status)
+{
+  static char type[20];
+
+  switch(status)
+    {
+    case(NOT_NEIGH):
+      return "NOT NEIGH";
+    case(SYM_NEIGH):
+      return "NEIGHBOR";
+    case(MPR_NEIGH):
+      return "MPR";
+    default:
+      break;
+    }
+
+  snprintf(type, sizeof(type), "UNKNOWN(%d)", status);
+  return type;
+}
+
+
+/**
+ *Termination function to be called whenever a error occures
+ *that requires the daemon to terminate
+ *
+ *@param msg the message to write to the syslog and possibly stdout
+ */
+
+void
+olsr_exit(const char *msg, int val)
+{
+  OLSR_PRINTF(1, "OLSR EXIT: %s\n", msg);
+  olsr_syslog(OLSR_LOG_ERR, "olsrd exit: %s\n", msg);
+  fflush(stdout);
+  olsr_cnf->exit_value = val;
+
+  raise(SIGTERM);
+}
+
+
+/**
+ * Wrapper for malloc(3) that does error-checking
+ *
+ * @param size the number of bytes to allocalte
+ * @param caller a string identifying the caller for
+ * use in error messaging
+ *
+ * @return a void pointer to the memory allocated
+ */
+void *
+olsr_malloc(size_t size, const char *id)
+{
+  void *ptr;
+
+  /*
+   * Not all the callers do a proper cleaning of memory.
+   * Clean it on behalf of those.
+   */
+  ptr = calloc(1, size);
+
+  if (!ptr) {
+      const char * const err_msg = strerror(errno);
+      OLSR_PRINTF(1, "OUT OF MEMORY: %s\n", err_msg);
+      olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %s\n", err_msg);
+      olsr_exit(id, EXIT_FAILURE);
+  }
+
+#if 0 
+  /* useful for debugging */
+  olsr_printf(1, "MEMORY: alloc %s %p, %u bytes\n",
+              id, ptr, size);
+#endif
+
+  return ptr;
+}
+
+
+/**
+ *Wrapper for printf that prints to a specific
+ *debuglevel upper limit
+ *
+ */
+
+int
+olsr_printf(int loglevel, const char *format, ...)
+{
+  if((loglevel <= olsr_cnf->debug_level) && debug_handle)
+    {
+      va_list arglist;
+      va_start(arglist, format);
+      vfprintf(debug_handle, format, arglist);
+      va_end(arglist);
+    }
+  return 0;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_cfg.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_cfg.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_cfg.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_cfg.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,314 @@
+/*
+ * 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_CFGPARSER_H
+#define _OLSRD_CFGPARSER_H
+
+#include "olsr_types.h"
+
+#ifndef LINUX_POLICY_ROUTING
+#if defined linux
+#  define LINUX_POLICY_ROUTING 1
+#else
+#  define LINUX_POLICY_ROUTING 0
+#endif
+#endif
+
+/* Default values not declared in olsr_protocol.h */
+#define DEF_POLLRATE        0.05
+#define DEF_NICCHGPOLLRT    2.5
+#define DEF_WILL_AUTO       OLSR_TRUE
+#define DEF_ALLOW_NO_INTS   OLSR_TRUE
+#define DEF_TOS             16
+#define DEF_DEBUGLVL        1
+#define DEF_IPC_CONNECTIONS 0
+#define DEF_USE_HYST        OLSR_FALSE
+#define DEF_FIB_METRIC      FIBM_FLAT
+#define DEF_LQ_LEVEL        2
+#define DEF_LQ_FISH         0
+#define DEF_LQ_DIJK_LIMIT   255
+#define DEF_LQ_DIJK_INTER   0.0
+#define DEF_LQ_NAT_THRESH   1.0
+#define DEF_LQ_AGING        0.1
+#define DEF_CLEAR_SCREEN    OLSR_FALSE
+
+/* Bounds */
+
+#define MIN_INTERVAL        0.01
+
+#define MAX_POLLRATE        10.0
+#define MIN_POLLRATE        0.01
+#define MAX_NICCHGPOLLRT    100.0
+#define MIN_NICCHGPOLLRT    1.0
+#define MAX_DEBUGLVL        9
+#define MIN_DEBUGLVL        0
+#define MAX_TOS             16
+#define MIN_TOS             0
+#define MAX_WILLINGNESS     7
+#define MIN_WILLINGNESS     0
+#define MAX_MPR_COVERAGE    20
+#define MIN_MPR_COVERAGE    1
+#define MAX_TC_REDUNDANCY   2
+#define MIN_TC_REDUNDANCY   0
+#define MAX_HYST_PARAM      1.0
+#define MIN_HYST_PARAM      0.0
+#define MAX_LQ_LEVEL        2
+#define MIN_LQ_LEVEL        0
+#define MAX_LQ_AGING        1.0
+#define MIN_LQ_AGING        0.01
+
+/* Option values */
+#define CFG_FIBM_FLAT          "flat"
+#define CFG_FIBM_CORRECT       "correct"
+#define CFG_FIBM_APPROX        "approx"
+
+#ifndef IPV6_ADDR_SITELOCAL
+#define IPV6_ADDR_SITELOCAL    0x0040U
+#endif
+
+#include "interfaces.h"
+
+struct olsr_msg_params
+{
+  float                    emission_interval;
+  float                    validity_time;
+};
+
+struct olsr_lq_mult
+{
+  union olsr_ip_addr addr;
+  olsr_u32_t value;
+  struct olsr_lq_mult *next;
+};
+
+struct olsr_if_weight
+{
+  int        value;
+  olsr_bool  fixed;
+};
+
+struct if_config_options
+{
+  union olsr_ip_addr       ipv4_broadcast;
+  int                      ipv6_addrtype;
+  union olsr_ip_addr       ipv6_multi_site;
+  union olsr_ip_addr       ipv6_multi_glbl;
+  struct olsr_if_weight    weight;
+  struct olsr_msg_params   hello_params;
+  struct olsr_msg_params   tc_params;
+  struct olsr_msg_params   mid_params;
+  struct olsr_msg_params   hna_params;
+  struct olsr_lq_mult      *lq_mult;
+  olsr_bool                autodetect_chg;
+};
+
+
+
+struct olsr_if
+{
+  char                     *name;
+  char                     *config;
+  olsr_bool                configured;
+  olsr_bool                host_emul;
+  union olsr_ip_addr       hemu_ip;
+  struct interface         *interf;
+  struct if_config_options *cnf;
+  struct olsr_if           *next;
+};
+
+struct ip_prefix_list
+{
+  struct olsr_ip_prefix    net;
+  struct ip_prefix_list    *next;
+};
+
+struct hyst_param
+{
+  float                    scaling;
+  float                    thr_high;
+  float                    thr_low;
+};
+
+struct plugin_param
+{
+  char                     *key;
+  char                     *value;
+  struct plugin_param      *next;
+};
+
+struct plugin_entry
+{
+  char                     *name;
+  struct plugin_param      *params;
+  struct plugin_entry      *next;
+};
+
+
+typedef enum {
+  FIBM_FLAT,
+  FIBM_CORRECT,
+  FIBM_APPROX
+} olsr_fib_metric_options;
+
+/*
+ * The config struct
+ */
+
+struct olsrd_config
+{
+  int                      debug_level;
+  olsr_bool                no_fork;
+  olsr_bool                host_emul;
+  int                      ip_version;
+  olsr_bool                allow_no_interfaces;
+  olsr_u16_t               tos;
+  olsr_u8_t                rttable;
+  olsr_u8_t                rttable_default;
+  olsr_u8_t                willingness;
+  olsr_bool                willingness_auto;
+  int                      ipc_connections;
+  olsr_bool                use_hysteresis;
+  olsr_fib_metric_options  fib_metric;
+  struct hyst_param        hysteresis_param;
+  struct plugin_entry      *plugins;
+  struct ip_prefix_list    *hna_entries;
+  struct ip_prefix_list    *ipc_nets;
+  struct olsr_if           *interfaces;
+  float                    pollrate;
+  float                    nic_chgs_pollrate;
+  olsr_bool                clear_screen;
+  olsr_u8_t                tc_redundancy;
+  olsr_u8_t                mpr_coverage;
+  olsr_u8_t                lq_level;
+  olsr_u8_t                lq_fish;
+  float                    lq_dinter;
+  float                    lq_aging;
+  char                     *lq_algorithm;
+  olsr_u8_t                lq_dlimit;
+
+  /* Stuff set by olsrd */
+  olsr_u16_t               system_tick_divider;  /* Tick resolution */
+  olsr_u8_t                maxplen;              /* maximum prefix len */
+  size_t                   ipsize;               /* Size of address */
+  olsr_bool                del_gws;              /* Delete InternetGWs at startup */
+  union olsr_ip_addr       main_addr;            /* Main address of this node */
+  float                    will_int;
+  float                    max_jitter;
+  int                      exit_value;           /* Global return value for process termination */
+  float                    max_tc_vtime;
+
+  int                      ioctl_s;              /* Socket used for ioctl calls */
+#if LINUX_POLICY_ROUTING
+  int                      rtnl_s;               /* Socket used for rtnetlink messages */
+#endif
+
+#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
+  int                      rts;                  /* Socket used for route changes on BSDs */
+#endif
+  float                    lq_nat_thresh;
+};
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * List functions
+ */
+
+void ip_prefix_list_add(struct ip_prefix_list **, const union olsr_ip_addr *, olsr_u8_t);
+
+int ip_prefix_list_remove(struct ip_prefix_list **, const union olsr_ip_addr *, olsr_u8_t);
+
+struct ip_prefix_list *ip_prefix_list_find(struct ip_prefix_list *, const union olsr_ip_addr *net, olsr_u8_t prefix_len);
+
+
+/*
+ * Interface to parser
+ */
+
+struct olsrd_config *
+olsrd_parse_cnf(const char *);
+
+int
+olsrd_sanity_check_cnf(struct olsrd_config *);
+
+void
+olsrd_free_cnf(struct olsrd_config *);
+
+void
+olsrd_print_cnf(struct olsrd_config *);
+
+int
+olsrd_write_cnf(struct olsrd_config *, const char *);
+
+int
+olsrd_write_cnf_buf(struct olsrd_config *, char *, olsr_u32_t);
+
+struct if_config_options *
+get_default_if_config(void);
+
+struct olsrd_config *
+olsrd_get_default_cnf(void);
+
+#if defined WIN32
+void 
+win32_stdio_hack(unsigned int);
+
+void*
+win32_olsrd_malloc(size_t size);
+
+void
+win32_olsrd_free(void* ptr);
+#endif
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_cookie.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_cookie.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_cookie.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_cookie.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,326 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008, Hannes Gredler (hannes@gredler.at)
+ * 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.h"
+#include "defs.h"
+#include "olsr_cookie.h"
+#include "log.h"
+
+#include <assert.h>
+
+/* Root directory of the cookies we have in the system */
+static struct olsr_cookie_info *cookies[COOKIE_ID_MAX] = { 0 };
+
+/*
+ * Allocate a cookie for the next available cookie id.
+ */
+struct olsr_cookie_info *
+olsr_alloc_cookie(const char *cookie_name, olsr_cookie_type cookie_type)
+{
+  struct olsr_cookie_info *ci;
+  int ci_index;
+
+  /*
+   * Look for an unused index.
+   * For ease of troubleshooting (non-zero patterns) we start at index 1.
+   */
+  for (ci_index = 1; ci_index < COOKIE_ID_MAX; ci_index++) {
+    if (!cookies[ci_index]) {
+      break;
+    }
+  }
+
+  assert(ci_index < COOKIE_ID_MAX);	/* increase COOKIE_ID_MAX */
+
+  ci = calloc(1, sizeof(struct olsr_cookie_info));
+  cookies[ci_index] = ci;
+
+  /* Now populate the cookie info */
+  ci->ci_id = ci_index;
+  ci->ci_type = cookie_type;
+  if (cookie_name) {
+    ci->ci_name = strdup(cookie_name);
+  }
+
+  /* Init the free list */
+  if (cookie_type == OLSR_COOKIE_TYPE_MEMORY) {
+    list_head_init(&ci->ci_free_list);
+  }
+
+  return ci;
+}
+
+/*
+ * Free a cookie that is no longer being used.
+ */
+void
+olsr_free_cookie(struct olsr_cookie_info *ci)
+{
+  struct list_node *memory_list;
+
+  /* Mark the cookie as unused */
+  cookies[ci->ci_id] = NULL;
+
+  /* Free name if set */
+  if (ci->ci_name) {
+    free(ci->ci_name);
+  }
+
+  /* Flush all the memory on the free list */
+  if (ci->ci_type == OLSR_COOKIE_TYPE_MEMORY) {
+    while (!list_is_empty(&ci->ci_free_list)) {
+      memory_list = ci->ci_free_list.next;
+      list_remove(memory_list);
+      free(memory_list);
+    }
+  }
+
+  free(ci);
+}
+
+/*
+ * Flush all cookies. This is really only called upon shutdown.
+ */
+void
+olsr_delete_all_cookies(void)
+{
+  int ci_index;
+
+  /*
+   * Walk the full index range and kill 'em all.
+   */
+  for (ci_index = 1; ci_index < COOKIE_ID_MAX; ci_index++) {
+    if (!cookies[ci_index]) {
+      continue;
+    }
+    olsr_free_cookie(cookies[ci_index]);
+  }
+}
+
+/*
+ * Set the size for fixed block allocations.
+ * This is only allowed for memory cookies.
+ */
+void
+olsr_cookie_set_memory_size(struct olsr_cookie_info *ci, size_t size)
+{
+  if (!ci) {
+    return;
+  }
+
+  assert(ci->ci_type == OLSR_COOKIE_TYPE_MEMORY);
+  ci->ci_size = size;
+}
+
+/*
+ * Basic sanity checking for a passed-in cookie-id.
+ */
+static olsr_bool
+olsr_cookie_valid(olsr_cookie_t cookie_id)
+{
+  if ((cookie_id < COOKIE_ID_MAX) && cookies[cookie_id]) {
+    return OLSR_TRUE;
+  }
+  return OLSR_FALSE;
+}
+
+/*
+ * Increment usage state for a given cookie.
+ */
+void
+olsr_cookie_usage_incr(olsr_cookie_t cookie_id)
+{
+  if (olsr_cookie_valid(cookie_id)) {
+    cookies[cookie_id]->ci_usage++;
+    cookies[cookie_id]->ci_changes++;
+  }
+}
+
+/*
+ * Decrement usage state for a given cookie.
+ */
+void
+olsr_cookie_usage_decr(olsr_cookie_t cookie_id)
+{
+  if (olsr_cookie_valid(cookie_id)) {
+    cookies[cookie_id]->ci_usage--;
+    cookies[cookie_id]->ci_changes++;
+  }
+}
+
+/*
+ * Return a cookie name.
+ * Mostly used for logging purposes.
+ */
+char *
+olsr_cookie_name(olsr_cookie_t cookie_id)
+{
+  static char unknown[] = "unknown";
+
+  if (olsr_cookie_valid(cookie_id)) {
+    return (cookies[cookie_id])->ci_name;
+  }
+
+  return unknown;
+}
+
+/*
+ * Allocate a fixed amount of memory based on a passed in cookie type.
+ */
+void *
+olsr_cookie_malloc(struct olsr_cookie_info *ci)
+{
+  void *ptr;
+  struct olsr_cookie_mem_brand *branding;
+  struct list_node *free_list_node;
+  olsr_bool reuse = OLSR_FALSE;
+
+  /*
+   * Check first if we have reusable memory.
+   */
+  if (!ci->ci_free_list_usage) {
+
+    /*
+     * No reusable memory block on the free_list.
+     */
+    ptr = calloc(1, ci->ci_size + sizeof(struct olsr_cookie_mem_brand));
+
+    if (!ptr) {
+      const char *const err_msg = strerror(errno);
+      OLSR_PRINTF(1, "OUT OF MEMORY: %s\n", err_msg);
+      olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %s\n", err_msg);
+      olsr_exit(ci->ci_name, EXIT_FAILURE);
+    }
+  } else {
+
+    /*
+     * There is a memory block on the free list.
+     * Carve it out of the list, and clean.
+     */
+    free_list_node = ci->ci_free_list.next;
+    list_remove(free_list_node);
+    ptr = (void *)free_list_node;
+    memset(ptr, 0, ci->ci_size);
+    ci->ci_free_list_usage--;
+    reuse = OLSR_TRUE;
+  }
+
+  /*
+   * Now brand mark the end of the memory block with a short signature
+   * indicating presence of a cookie. This will be checked against
+   * When the block is freed to detect corruption.
+   */
+  branding = (struct olsr_cookie_mem_brand *)
+    ((unsigned char *)ptr + ci->ci_size);
+  memcpy(&branding->cmb_sig, "cookie", 6);
+  branding->cmb_id = ci->ci_id;
+
+  /* Stats keeping */
+  olsr_cookie_usage_incr(ci->ci_id);
+
+#if 0
+  OLSR_PRINTF(1, "MEMORY: alloc %s, %p, %u bytes%s\n",
+	      ci->ci_name, ptr, ci->ci_size, reuse ? ", reuse" : "");
+#endif
+
+  return ptr;
+}
+
+/*
+ * Free a memory block owned by a given cookie.
+ * Run some corruption checks.
+ */
+void
+olsr_cookie_free(struct olsr_cookie_info *ci, void *ptr)
+{
+  struct olsr_cookie_mem_brand *branding;
+  struct list_node *free_list_node;
+  olsr_bool reuse = OLSR_FALSE;
+
+  branding = (struct olsr_cookie_mem_brand *)
+    ((unsigned char *)ptr + ci->ci_size);
+
+  /*
+   * Verify if there has been a memory overrun, or
+   * the wrong owner is trying to free this.
+   */
+  assert(!memcmp(&branding->cmb_sig, "cookie", 6) &&
+	 branding->cmb_id == ci->ci_id);
+
+  /* Kill the brand */
+  memset(branding, 0, sizeof(*branding));
+
+  /*
+   * Rather than freeing the memory right away, try to reuse at a later
+   * point. Keep at least ten percent of the active used blocks or at least
+   * ten blocks on the free list.
+   */
+  if ((ci->ci_free_list_usage < COOKIE_FREE_LIST_THRESHOLD) ||
+      (ci->ci_free_list_usage < ci->ci_usage / COOKIE_FREE_LIST_THRESHOLD)) {
+
+    free_list_node = (struct list_node *)ptr;
+    list_node_init(free_list_node);
+    list_add_before(&ci->ci_free_list, free_list_node);
+    ci->ci_free_list_usage++;
+    reuse = OLSR_TRUE;
+
+  } else {
+
+    /*
+     * No interest in reusing memory.
+     */
+    free(ptr);
+  }
+
+  /* Stats keeping */
+  olsr_cookie_usage_decr(ci->ci_id);
+
+#if 0
+  OLSR_PRINTF(1, "MEMORY: free %s, %p, %u bytes%s\n",
+	      ci->ci_name, ptr, ci->ci_size, reuse ? ", reuse" : "");
+#endif
+
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_cookie.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_cookie.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_cookie.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_cookie.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,103 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008, Hannes Gredler (hannes@gredler.at)
+ * 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 "common/list.h"
+
+#ifndef _OLSR_COOKIE_H
+#define _OLSR_COOKIE_H
+
+#define COOKIE_ID_MAX  25	/* maximum number of cookies in the system */
+
+typedef enum olsr_cookie_type_ {
+  OLSR_COOKIE_TYPE_MIN,
+  OLSR_COOKIE_TYPE_MEMORY,
+  OLSR_COOKIE_TYPE_TIMER,
+  OLSR_COOKIE_TYPE_MAX
+} olsr_cookie_type;
+
+/*
+ * This is a cookie. A cookie is a tool aimed for olsrd developers.
+ * It is used for tracking resource usage in the system and also
+ * for locating memory corruption.
+ */
+struct olsr_cookie_info {
+  olsr_cookie_t ci_id;		       /* ID */
+  char *ci_name;		       /* Name */
+  olsr_cookie_type ci_type;	       /* Type of cookie */
+  size_t ci_size;		       /* Fixed size for block allocations */
+  unsigned int ci_usage;	       /* Stats, resource usage */
+  unsigned int ci_changes;	       /* Stats, resource churn */
+  struct list_node ci_free_list;       /* List head for recyclable blocks */
+  unsigned int ci_free_list_usage;     /* Length of free list */
+};
+
+#define COOKIE_FREE_LIST_THRESHOLD 10  /* Blocks / Percent  */
+
+/*
+ * Small brand which gets appended on the end of every block allocation.
+ * Helps to detect memory corruption, like overruns, double frees.
+ */
+struct olsr_cookie_mem_brand {
+  char cmb_sig[6];
+  olsr_cookie_t cmb_id;
+};
+
+/* Externals. */
+extern struct olsr_cookie_info *olsr_alloc_cookie(const char *,
+						  olsr_cookie_type);
+extern void olsr_free_cookie(struct olsr_cookie_info *);
+extern void olsr_delete_all_cookies(void);
+extern char *olsr_cookie_name(olsr_cookie_t);
+extern void olsr_cookie_set_memory_size(struct olsr_cookie_info *, size_t);
+extern void olsr_cookie_usage_incr(olsr_cookie_t);
+extern void olsr_cookie_usage_decr(olsr_cookie_t);
+
+extern void *olsr_cookie_malloc(struct olsr_cookie_info *);
+extern void olsr_cookie_free(struct olsr_cookie_info *, void *);
+
+
+#endif /* _OLSR_COOKIE_H */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsrd_plugin.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsrd_plugin.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsrd_plugin.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsrd_plugin.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto-at-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 the UniK olsr daemon 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.
+ *
+ */
+
+
+/*
+ * Example plugin for olsrd.org OLSR daemon
+ * Only the bare minimum
+ */
+
+#ifndef _OLSRD_PLUGIN
+#define _OLSRD_PLUGIN
+
+
+/* Define the most recent version */
+#define MOST_RECENT_PLUGIN_INTERFACE_VERSION		5
+#define LAST_SUPPORTED_PLUGIN_INTERFACE_VERSION		4
+
+
+/****************************************************************************
+ *                Functions that the plugin MUST provide                    *
+ ****************************************************************************/
+#if 1
+/* We hide them from the compiler here to allow the plugins itself to declare them
+ * as they also implement them if we activate -Wredundant-decls.
+ * Normally we leave it seen so that we enforce a check by the compiler if they are
+ * identical.
+ */
+
+/**
+ * Plugin interface version
+ * Used by main olsrd to check plugin interface version
+ */
+int olsrd_plugin_interface_version(void);
+
+
+/**
+ * Initialize plugin
+ * Called after all parameters are passed
+ */
+int olsrd_plugin_init(void);
+
+
+/* Interface version 4 */
+/**
+ * Register parameters from config file
+ * Called for all plugin parameters
+ */
+int olsrd_plugin_register_param(char *key, char *value);
+
+/* Interface version 5 */
+
+typedef union {
+    unsigned int ui;
+    char *pc;
+} set_plugin_parameter_addon;
+
+typedef int set_plugin_parameter(const char *value, void *data, set_plugin_parameter_addon addon);
+
+struct olsrd_plugin_parameters {
+    const char *name;
+    set_plugin_parameter *set_plugin_parameter;
+    void *data;
+    set_plugin_parameter_addon addon;
+};
+
+/**
+ * Delivers the (address of the) table and the size of the parameter description
+ */
+void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size);
+
+#endif
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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 _OLSR_FUNCTIONS
+#define _OLSR_FUNCTIONS
+
+#include "olsr_protocol.h"
+#include "interfaces.h"
+
+extern olsr_bool changes_topology;
+extern olsr_bool changes_neighborhood;
+extern olsr_bool changes_hna;
+extern olsr_bool changes_force;
+
+extern union olsr_ip_addr all_zero;
+
+void
+register_pcf(int (*)(int, int, int));
+
+void
+olsr_process_changes(void);
+
+void
+init_msg_seqno(void);
+
+olsr_u16_t
+get_msg_seqno(void);
+
+int
+olsr_forward_message(union olsr_message *, 
+		     union olsr_ip_addr *);
+
+void
+set_buffer_timer(struct interface *);
+
+void
+olsr_init_tables(void);
+
+void
+olsr_init_willingness(void);
+
+void
+olsr_update_willingness(void *);
+
+olsr_u8_t
+olsr_calculate_willingness(void);
+
+const char *
+olsr_msgtype_to_string(olsr_u8_t);
+
+const char *
+olsr_link_to_string(olsr_u8_t);
+
+const char *
+olsr_status_to_string(olsr_u8_t);
+
+void
+olsr_exit(const char *, int);
+
+void *
+olsr_malloc(size_t, const char *);
+
+int
+olsr_printf(int, const char *, ...) __attribute__((format(printf,2,3)));
+
+void
+olsr_trigger_forced_update(void *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_protocol.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_protocol.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_protocol.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_protocol.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,443 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *Values and packet formats as proposed in RFC3626 and misc. values and
+ *data structures used by the olsr.org OLSR daemon.
+ */
+
+#ifndef _PROTOCOLS_OLSR_H
+#define	_PROTOCOLS_OLSR_H
+
+#include "olsr_types.h"
+#include "olsr_cfg.h"
+
+#include <string.h>
+
+/* Port for OLSR to use */
+
+#define OLSRPORT       698
+
+/* Default IPv6 multicast addresses */
+
+#define OLSR_IPV6_MCAST_SITE_LOCAL "ff05::15"
+#define OLSR_IPV6_MCAST_GLOBAL     "ff0e::1"
+
+#define OLSR_HEADERSIZE (sizeof(olsr_u16_t) + sizeof(olsr_u16_t))
+
+#define OLSR_MSGHDRSZ_IPV4 12
+#define OLSR_MSGHDRSZ_IPV6 24
+
+
+/*
+ *Emission Intervals
+ */
+
+#define HELLO_INTERVAL        2
+#define REFRESH_INTERVAL      2
+#define TC_INTERVAL           5
+#define MID_INTERVAL          TC_INTERVAL
+#define HNA_INTERVAL          TC_INTERVAL
+
+
+/* Emission Jitter */
+#define HELLO_JITTER         25 /* percent */
+#define HNA_JITTER           25 /* percent */
+#define MID_JITTER           25 /* percent */
+#define TC_JITTER            25 /* percent */
+
+/*
+ *Holding Time
+ */
+
+#define NEIGHB_HOLD_TIME      3 * REFRESH_INTERVAL
+#define TOP_HOLD_TIME         3 * TC_INTERVAL
+#define DUP_HOLD_TIME         30
+#define MID_HOLD_TIME         3 * MID_INTERVAL
+#define HNA_HOLD_TIME         3 * HNA_INTERVAL
+
+/*
+ *Message Types
+ */
+
+#define HELLO_MESSAGE         1
+#define TC_MESSAGE            2
+#define MID_MESSAGE           3
+#define HNA_MESSAGE           4
+#define MAX_MESSAGE           4
+
+/*
+ *Link Types
+ */
+
+#define UNSPEC_LINK           0
+#define ASYM_LINK             1
+#define SYM_LINK              2
+#define LOST_LINK             3
+#define HIDE_LINK             4
+#define MAX_LINK              4
+
+/*
+ *Neighbor Types
+ */
+
+#define NOT_NEIGH             0
+#define SYM_NEIGH             1
+#define MPR_NEIGH             2
+#define MAX_NEIGH             2
+
+/*
+ *Neighbor status
+ */
+
+#define NOT_SYM               0
+#define SYM                   1
+
+/*
+ *Link Hysteresis
+ */
+
+#define HYST_THRESHOLD_HIGH   0.8
+#define HYST_THRESHOLD_LOW    0.3
+#define HYST_SCALING          0.5
+
+/*
+ *Willingness
+ */
+
+#define WILL_NEVER            0
+#define WILL_LOW              1
+#define WILL_DEFAULT          3
+#define WILL_HIGH             6
+#define WILL_ALWAYS           7
+
+/*
+ *Redundancy defaults
+ */
+#define TC_REDUNDANCY         2
+#define MPR_COVERAGE          1
+
+/*
+ *Misc. Constants
+ */
+#define MAXJITTER             HELLO_INTERVAL / 4
+#define MAX_TTL               0xff
+
+/*
+ *Sequence numbering
+ */
+
+/* Seqnos are 16 bit values */
+
+#define MAXVALUE 0xFFFF
+
+/* Macro for checking seqnos "wraparound" */
+#define SEQNO_GREATER_THAN(s1, s2)                \
+        (((s1 > s2) && (s1 - s2 <= (MAXVALUE/2))) \
+     || ((s2 > s1) && (s2 - s1 > (MAXVALUE/2))))
+
+
+
+/*
+ * Macros for creating and extracting the neighbor 
+ * and link type information from 8bit link_code
+ * data as passed in HELLO messages
+ */
+
+#define CREATE_LINK_CODE(status, link) (link | (status<<2))
+
+#define EXTRACT_STATUS(link_code) ((link_code & 0xC)>>2)
+
+#define EXTRACT_LINK(link_code) (link_code & 0x3)
+
+
+/***********************************************
+ *           OLSR packet definitions           *
+ ***********************************************/
+
+
+/*
+ *The HELLO message
+ */
+
+/*
+ *Hello info
+ */
+struct hellinfo 
+{
+  olsr_u8_t   link_code;
+  olsr_u8_t   reserved;
+  olsr_u16_t  size;
+  olsr_u32_t  neigh_addr[1]; /* neighbor IP address(es) */
+} __attribute__ ((packed));
+
+struct hellomsg 
+{
+  olsr_u16_t      reserved;
+  olsr_u8_t       htime;
+  olsr_u8_t       willingness;
+  struct hellinfo hell_info[1];
+} __attribute__ ((packed));
+
+/*
+ *IPv6
+ */
+
+struct hellinfo6
+{
+  olsr_u8_t       link_code;
+  olsr_u8_t       reserved;
+  olsr_u16_t      size;
+  struct in6_addr neigh_addr[1]; /* neighbor IP address(es) */
+} __attribute__ ((packed));
+
+struct hellomsg6
+{
+  olsr_u16_t         reserved;
+  olsr_u8_t          htime;
+  olsr_u8_t          willingness;
+  struct hellinfo6   hell_info[1];
+} __attribute__ ((packed));
+
+/*
+ * Topology Control packet
+ */
+
+struct neigh_info
+{
+  olsr_u32_t       addr;
+} __attribute__ ((packed));
+
+
+struct olsr_tcmsg 
+{
+  olsr_u16_t        ansn;
+  olsr_u16_t        reserved;
+  struct neigh_info neigh[1];
+} __attribute__ ((packed));
+
+
+
+/*
+ *IPv6
+ */
+
+struct neigh_info6
+{
+  struct in6_addr      addr;
+} __attribute__ ((packed));
+
+
+struct olsr_tcmsg6
+{
+  olsr_u16_t           ansn;
+  olsr_u16_t           reserved;
+  struct neigh_info6   neigh[1];
+} __attribute__ ((packed));
+
+
+
+
+
+/*
+ *Multiple Interface Declaration message
+ */
+
+/* 
+ * Defined as s struct for further expansion 
+ * For example: do we want to tell what type of interface
+ * is associated whit each address?
+ */
+struct midaddr
+{
+  olsr_u32_t addr;
+} __attribute__ ((packed));
+
+
+struct midmsg 
+{
+  struct midaddr mid_addr[1];
+} __attribute__ ((packed));
+
+
+/*
+ *IPv6
+ */
+struct midaddr6
+{
+  struct in6_addr addr;
+} __attribute__ ((packed));
+
+
+struct midmsg6
+{
+  struct midaddr6 mid_addr[1];
+} __attribute__ ((packed));
+
+
+
+
+
+
+/*
+ * Host and Network Association message
+ */
+struct hnapair
+{
+  olsr_u32_t   addr;
+  olsr_u32_t   netmask;
+} __attribute__ ((packed));
+
+struct hnamsg
+{
+  struct hnapair hna_net[1];
+} __attribute__ ((packed));
+
+/*
+ *IPv6
+ */
+
+struct hnapair6
+{
+  struct in6_addr   addr;
+  struct in6_addr   netmask;
+} __attribute__ ((packed));
+
+struct hnamsg6
+{
+  struct hnapair6 hna_net[1];
+} __attribute__ ((packed));
+
+
+
+
+
+/*
+ * OLSR message (several can exist in one OLSR packet)
+ */
+
+struct olsrmsg
+{
+  olsr_u8_t     olsr_msgtype;
+  olsr_u8_t     olsr_vtime;
+  olsr_u16_t    olsr_msgsize;
+  olsr_u32_t    originator;
+  olsr_u8_t     ttl;
+  olsr_u8_t     hopcnt;
+  olsr_u16_t    seqno;
+
+  union 
+  {
+    struct hellomsg hello;
+    struct olsr_tcmsg    tc;
+    struct hnamsg   hna;
+    struct midmsg   mid;
+  } message;
+
+} __attribute__ ((packed));
+
+/*
+ *IPv6
+ */
+
+struct olsrmsg6
+{
+  olsr_u8_t        olsr_msgtype;
+  olsr_u8_t        olsr_vtime;
+  olsr_u16_t       olsr_msgsize;
+  struct in6_addr  originator;
+  olsr_u8_t        ttl;
+  olsr_u8_t        hopcnt;
+  olsr_u16_t       seqno;
+
+  union 
+  {
+    struct hellomsg6 hello;
+    struct olsr_tcmsg6    tc;
+    struct hnamsg6   hna;
+    struct midmsg6   mid;
+  } message;
+
+} __attribute__ ((packed));
+
+
+
+/*
+ * Generic OLSR packet
+ */
+
+struct olsr 
+{
+  olsr_u16_t	  olsr_packlen;		/* packet length */
+  olsr_u16_t	  olsr_seqno;
+  struct olsrmsg  olsr_msg[1];          /* variable messages */
+} __attribute__ ((packed));
+
+
+struct olsr6
+{
+  olsr_u16_t	    olsr_packlen;        /* packet length */
+  olsr_u16_t	    olsr_seqno;
+  struct olsrmsg6   olsr_msg[1];         /* variable messages */
+} __attribute__ ((packed));
+
+
+/* IPv4 <-> IPv6 compability */
+
+union olsr_message
+{
+  struct olsrmsg  v4;
+  struct olsrmsg6 v6;
+} __attribute__ ((packed));
+
+union olsr_packet
+{
+  struct olsr  v4;
+  struct olsr6 v6;
+} __attribute__ ((packed));
+
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_spf.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_spf.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_spf.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_spf.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,535 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * IPv4 performance optimization (c) 2006, sven-ola(gmx.de)
+ * SPF implementation (c) 2007, Hannes Gredler (hannes@gredler.at)
+ * 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.
+ *
+ * Implementation of Dijkstras algorithm. Initially all nodes
+ * are initialized to infinite cost. First we put ourselves
+ * on the heap of reachable nodes. Our heap implementation
+ * is based on an AVL tree which gives interesting performance
+ * characteristics for the frequent operations of minimum key
+ * extraction and re-keying. Next all neighbors of a node are
+ * explored and put on the heap if the cost of reaching them is
+ * better than reaching the current candidate node.
+ * The SPF calculation is terminated if there are no more nodes
+ * on the heap.
+ */
+
+#include "ipcalc.h"
+#include "defs.h"
+#include "olsr.h"
+#include "tc_set.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "link_set.h"
+#include "routing_table.h"
+#include "mid_set.h"
+#include "hna_set.h"
+#include "common/list.h"
+#include "common/avl.h"
+ #include "olsr_spf.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+
+struct timer_entry *spf_backoff_timer = NULL;
+
+/*
+ * avl_comp_etx
+ *
+ * compare two etx metrics.
+ * return 0 if there is an exact match and
+ * -1 / +1 depending on being smaller or bigger.
+ * note that this results in the most optimal code
+ * after compiler optimization.
+ */
+static int
+avl_comp_etx (const void *etx1, const void *etx2)
+{       
+  if (*(const olsr_linkcost *)etx1 < *(const olsr_linkcost *)etx2) {
+    return -1;
+  }
+
+  if (*(const olsr_linkcost *)etx1 > *(const olsr_linkcost *)etx2) {
+    return +1;
+  }
+
+  return 0;
+}
+
+/*
+ * olsr_spf_add_cand_tree
+ *
+ * Key an existing vertex to a candidate tree.
+ */
+static void
+olsr_spf_add_cand_tree (struct avl_tree *tree,
+                        struct tc_entry *tc)
+{
+#if !defined(NODEBUG) && defined(DEBUG)
+  struct ipaddr_str buf;
+  struct lqtextbuffer lqbuffer;
+#endif
+  tc->cand_tree_node.key = &tc->path_cost;
+
+#ifdef DEBUG
+  OLSR_PRINTF(2, "SPF: insert candidate %s, cost %s\n",
+              olsr_ip_to_string(&buf, &tc->addr),
+              get_linkcost_text(tc->path_cost, OLSR_FALSE, &lqbuffer));
+#endif
+
+  avl_insert(tree, &tc->cand_tree_node, AVL_DUP);
+}
+
+/*
+ * olsr_spf_del_cand_tree
+ *
+ * Unkey an existing vertex from a candidate tree.
+ */
+static void
+olsr_spf_del_cand_tree (struct avl_tree *tree,
+                        struct tc_entry *tc)
+{
+
+#ifdef DEBUG
+#ifndef NODEBUG
+  struct ipaddr_str buf;
+  struct lqtextbuffer lqbuffer;
+#endif
+  OLSR_PRINTF(2, "SPF: delete candidate %s, cost %s\n",
+              olsr_ip_to_string(&buf, &tc->addr),
+              get_linkcost_text(tc->path_cost, OLSR_FALSE, &lqbuffer));
+#endif
+
+  avl_delete(tree, &tc->cand_tree_node);
+}
+
+/*
+ * olsr_spf_add_path_list
+ *
+ * Insert an SPF result at the end of the path list.
+ */
+static void
+olsr_spf_add_path_list (struct list_node *head, int *path_count,
+                        struct tc_entry *tc)
+{
+#if !defined(NODEBUG) && defined(DEBUG)
+  struct ipaddr_str pathbuf, nbuf;
+  struct lqtextbuffer lqbuffer;
+#endif
+
+#ifdef DEBUG
+  OLSR_PRINTF(2, "SPF: append path %s, cost %s, via %s\n",
+              olsr_ip_to_string(&pathbuf, &tc->addr),
+              get_linkcost_text(tc->path_cost, OLSR_FALSE, &lqbuffer),
+              tc->next_hop ? olsr_ip_to_string(
+                &nbuf, &tc->next_hop->neighbor_iface_addr) : "-");
+#endif
+
+  list_add_before(head, &tc->path_list_node);
+  *path_count = *path_count + 1;
+}
+
+/*
+ * olsr_spf_extract_best
+ *
+ * return the node with the minimum pathcost.
+ */
+static struct tc_entry *
+olsr_spf_extract_best (struct avl_tree *tree)
+{
+  struct avl_node *node = avl_walk_first(tree);
+
+  return (node ? cand_tree2tc(node) :  NULL);
+}
+
+
+/*
+ * olsr_spf_relax
+ *
+ * Explore all edges of a node and add the node
+ * to the candidate tree if the if the aggregate
+ * path cost is better.
+ */
+static void
+olsr_spf_relax (struct avl_tree *cand_tree, struct tc_entry *tc)
+{
+  struct avl_node *edge_node;
+  olsr_linkcost new_cost;
+
+#ifdef DEBUG
+#ifndef NODEBUG
+  struct ipaddr_str buf, nbuf;
+  struct lqtextbuffer lqbuffer;
+#endif
+  OLSR_PRINTF(2, "SPF: exploring node %s, cost %s\n",
+              olsr_ip_to_string(&buf, &tc->addr),
+              get_linkcost_text(tc->path_cost, OLSR_FALSE, &lqbuffer));
+#endif
+
+  /*
+   * loop through all edges of this vertex.
+   */
+  for (edge_node = avl_walk_first(&tc->edge_tree);
+       edge_node;
+       edge_node = avl_walk_next(edge_node)) {
+
+    struct tc_entry *new_tc;
+    struct tc_edge_entry *tc_edge = edge_tree2tc_edge(edge_node);
+
+    /*
+     * We are not interested in dead-end edges.
+     */
+    if (!tc_edge->edge_inv) {
+#ifdef DEBUG
+      OLSR_PRINTF(2, "SPF:   ignoring edge %s\n",
+                  olsr_ip_to_string(&buf, &tc_edge->T_dest_addr));
+      if (!tc_edge->edge_inv) {
+        OLSR_PRINTF(2, "SPF:     no inverse edge\n");
+      }
+#endif
+      continue;
+    }
+
+    /*
+     * total quality of the path through this vertex
+     * to the destination of this edge
+     */
+    new_cost = tc->path_cost + tc_edge->cost;
+
+#ifdef DEBUG
+    OLSR_PRINTF(2, "SPF:   exploring edge %s, cost %s\n",
+                olsr_ip_to_string(&buf, &tc_edge->T_dest_addr),
+                get_linkcost_text(new_cost, OLSR_TRUE, &lqbuffer));
+#endif
+
+    /* 
+     * if it's better than the current path quality of this edge's
+     * destination node, then we've found a better path to this node.
+     */
+    new_tc = tc_edge->edge_inv->tc;
+
+    if (new_cost < new_tc->path_cost) {
+
+      /* if this node has been on the candidate tree delete it */
+      if (new_tc->path_cost < ROUTE_COST_BROKEN) {
+        olsr_spf_del_cand_tree(cand_tree, new_tc);
+      }
+
+      /* re-insert on candidate tree with the better metric */
+      new_tc->path_cost = new_cost;
+      olsr_spf_add_cand_tree(cand_tree, new_tc);
+
+      /* pull-up the next-hop and bump the hop count */
+      if (tc->next_hop) {
+        new_tc->next_hop = tc->next_hop;
+      }
+      new_tc->hops = tc->hops + 1;
+
+#ifdef DEBUG
+      OLSR_PRINTF(2, "SPF:   better path to %s, cost %s, via %s, hops %u\n",
+                  olsr_ip_to_string(&buf, &new_tc->addr),
+                  get_linkcost_text(new_cost, OLSR_TRUE, &lqbuffer),
+                  tc->next_hop ? olsr_ip_to_string(
+                    &nbuf, &tc->next_hop->neighbor_iface_addr) : "<none>",
+                  new_tc->hops);
+#endif
+
+    }
+  }
+}
+
+/*
+ * olsr_spf_run_full
+ *
+ * Run the Dijkstra algorithm.
+ * 
+ * A node gets added to the candidate tree when one of its edges has
+ * an overall better root path cost than the node itself.
+ * The node with the shortest metric gets moved from the candidate to
+ * the path list every pass.
+ * The SPF computation is completed when there are no more nodes
+ * on the candidate tree. 
+ */ 
+static void
+olsr_spf_run_full (struct avl_tree *cand_tree, struct list_node *path_list,
+                   int *path_count)
+{
+  struct tc_entry *tc;
+
+  *path_count = 0;
+
+  while ((tc = olsr_spf_extract_best(cand_tree))) {
+
+    olsr_spf_relax(cand_tree, tc);
+
+    /*
+     * move the best path from the candidate tree
+     * to the path list.
+     */
+    olsr_spf_del_cand_tree(cand_tree, tc);
+    olsr_spf_add_path_list(path_list, path_count, tc);
+  }
+}
+
+/**
+ * Callback for the SPF backoff timer.
+ */
+static void
+olsr_expire_spf_backoff(void *context __attribute__((unused)))
+{
+  spf_backoff_timer = NULL;
+}
+
+void
+olsr_calculate_routing_table (void)
+{
+#ifdef SPF_PROFILING
+  struct timeval t1, t2, t3, t4, t5, spf_init, spf_run, route, kernel, total;
+#endif
+  struct avl_tree cand_tree;
+  struct avl_node *rtp_tree_node;
+  struct list_node path_list; /* head of the path_list */
+  struct tc_entry *tc;
+  struct rt_path *rtp;
+  struct tc_edge_entry *tc_edge;
+  struct neighbor_entry *neigh;
+  struct link_entry *link;
+  int path_count = 0;
+
+  /* We are done if our backoff timer is running */
+  if (!spf_backoff_timer) {
+    spf_backoff_timer = 
+      olsr_start_timer(1000, 5, OLSR_TIMER_ONESHOT, &olsr_expire_spf_backoff,
+                       NULL, 0);
+  } else {
+    return;
+  }
+
+#ifdef SPF_PROFILING
+  gettimeofday(&t1, NULL);
+#endif
+
+  /*
+   * Prepare the candidate tree and result list.
+   */
+  avl_init(&cand_tree, avl_comp_etx);
+  list_head_init(&path_list);
+  olsr_bump_routingtree_version();
+
+  /*
+   * Initialize vertices in the lsdb.
+   */
+  OLSR_FOR_ALL_TC_ENTRIES(tc) {
+    tc->next_hop = NULL;
+    tc->path_cost = ROUTE_COST_BROKEN;
+    tc->hops = 0;
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+
+
+  /*
+   * Check if there was a change in the main IP address.
+   * Bail if there is no main IP address.
+   */
+  olsr_change_myself_tc();
+  if (!tc_myself) {
+
+    /*
+     * All gone now. Flush all routes.
+     */
+    olsr_update_rib_routes();
+    olsr_update_kernel_routes();
+    return;
+  }
+
+  /*
+   * zero ourselves and add us to the candidate tree.
+   */
+  tc_myself->path_cost = ZERO_ROUTE_COST;
+  olsr_spf_add_cand_tree(&cand_tree, tc_myself);
+
+  /*
+   * add edges to and from our neighbours.
+   */
+  OLSR_FOR_ALL_NBR_ENTRIES(neigh) {
+
+    if (neigh->status == SYM) {
+
+      tc_edge = olsr_lookup_tc_edge(tc_myself, &neigh->neighbor_main_addr);
+      link = get_best_link_to_neighbor(&neigh->neighbor_main_addr);
+      if (!link) {
+
+        /*
+         * If there is no best link to this neighbor
+         * and we had an edge before then flush the edge.
+         */
+        if (tc_edge) {
+          olsr_delete_tc_edge_entry(tc_edge);
+        }
+        continue;
+      }
+
+      /* find the interface for the link */
+      if (link->if_name) {
+        link->inter = if_ifwithname(link->if_name);
+      } else {
+        link->inter = if_ifwithaddr(&link->local_iface_addr);
+      }
+
+      /*
+       * Set the next-hops of our neighbors. 
+       */
+      if (!tc_edge) {
+        tc_edge = olsr_add_tc_edge_entry(tc_myself, &neigh->neighbor_main_addr,
+                                         0);
+      } else {
+
+        /*
+         * Update LQ and timers, such that the edge does not get deleted.
+         */
+        olsr_copylq_link_entry_2_tc_edge_entry(tc_edge, link);
+        olsr_calc_tc_edge_entry_etx(tc_edge);
+      }
+      if (tc_edge->edge_inv) {
+        tc_edge->edge_inv->tc->next_hop = link;
+      }
+    }
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(neigh);
+
+#ifdef SPF_PROFILING
+  gettimeofday(&t2, NULL);
+#endif
+
+  /*
+   * Run the SPF calculation.
+   */
+  olsr_spf_run_full(&cand_tree, &path_list, &path_count);
+
+  OLSR_PRINTF(2, "\n--- %s ------------------------------------------------- DIJKSTRA\n\n",
+              olsr_wallclock_string());
+
+#ifdef SPF_PROFILING
+  gettimeofday(&t3, NULL);
+#endif
+
+  /*
+   * In the path list we have all the reachable nodes in our topology.
+   */
+  for (; !list_is_empty(&path_list); list_remove(path_list.next)) {
+
+    tc = pathlist2tc(path_list.next);
+    link = tc->next_hop;
+
+    if (!link) {
+#ifdef DEBUG
+      /*
+       * Supress the error msg when our own tc_entry
+       * does not contain a next-hop.
+       */
+      if (tc != tc_myself) {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(2, "SPF: %s no next-hop\n", olsr_ip_to_string(&buf, &tc->addr));
+      }
+#endif
+      continue;
+    }
+
+    /*
+     * Now walk all prefixes advertised by that node.
+     * Since the node is reachable, insert the prefix into the global RIB.
+     * If the prefix is already in the RIB, refresh the entry such
+     * that olsr_delete_outdated_routes() does not purge it off.
+     */
+    for (rtp_tree_node = avl_walk_first(&tc->prefix_tree);
+         rtp_tree_node;
+         rtp_tree_node = avl_walk_next(rtp_tree_node)) {
+
+      rtp = rtp_prefix_tree2rtp(rtp_tree_node);
+
+      if (rtp->rtp_rt) {
+
+        /*
+         * If there is a route entry, the prefix is already in the global RIB.
+         */
+        olsr_update_rt_path(rtp, tc, link);
+
+      } else {
+
+        /*
+         * The prefix is reachable and not yet in the global RIB.
+         * Build a rt_entry for it.
+         */
+        olsr_insert_rt_path(rtp, tc, link);
+      }
+    }
+  }
+
+  /* Update the RIB based on the new SPF results */
+
+  olsr_update_rib_routes();
+
+#ifdef SPF_PROFILING
+  gettimeofday(&t4, NULL);
+#endif
+
+  /* move the route changes into the kernel */
+
+  olsr_update_kernel_routes();
+
+#ifdef SPF_PROFILING
+  gettimeofday(&t5, NULL);
+#endif
+
+#ifdef SPF_PROFILING
+  timersub(&t2, &t1, &spf_init);
+  timersub(&t3, &t2, &spf_run);
+  timersub(&t4, &t3, &route);
+  timersub(&t5, &t4, &kernel);
+  timersub(&t5, &t1, &total);
+  OLSR_PRINTF(1, "\n--- SPF-stats for %d nodes, %d routes (total/init/run/route/kern): "
+              "%d, %d, %d, %d, %d\n",
+              path_count, routingtree.count,
+              (int)total.tv_usec, (int)spf_init.tv_usec, (int)spf_run.tv_usec,
+              (int)route.tv_usec, (int)kernel.tv_usec);
+#endif
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_spf.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_spf.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_spf.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_spf.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 _OLSR_SPF_H
+#define _OLSR_SPF_H
+
+void olsr_calculate_routing_table(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/commands.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/commands.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/commands.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/commands.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,89 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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 _COMMAND
+#define _COMMAND
+
+#include "ohs_cmd.h"
+
+
+static const struct ohs_command ohs_commands[] =
+  {
+    { "help", "help",
+      "Help on shell commands",
+      "Help on shell commands",
+      ohs_cmd_help
+    },
+    { "exit", "exit",
+      "Exits olsr host switch",
+      "Exits olsr host switch",
+      ohs_cmd_exit
+    },
+    { "log", "log <set [type]>",
+      "Displays or sets log bits",
+      "This command sets or clears various logbits. Available logbits are:\n FORWARD - display info about all traffic forwarding\n CONNECT - display info about all connections happening\n LINK - display all link lookup information\n",
+      ohs_cmd_log
+    },
+    { "list", "list <clients|links>",
+      "List all connected clients or links",
+      "This command will list all the clients or all the links registered by olsr_switch. By default clients are listed.",
+      ohs_cmd_list
+    },
+    { "link", "link <bi> [srcIP|*] [dstIP|*] [0-100]",
+      "Manipulate links",
+      "This command is used for manipulating olsr links. The link quality is a number between 0-100 representing the chance in percentage for a packet to be forwarded on the link.\nTo make the link between 10.0.0.1 and 10.0.0.2 have 50% packet loss do:\nlink 10.0.0.1 10.0.0.2 50\nNote that this will only effect the unidirectional link 10.0.0.1 -> 10.0.0.2.\nTo make the changes affect traffic in both directions do:\nlink bi 10.0.0.1 10.0.0.2 50\nTo completely block a link do:\nlink 10.0.0.1 10.0.0.2 0\nTo make all traffic pass(delete the entry) do:\nlink 10.0.0.1 10.0.0.2 100\nNote that \"bi\" can be used in all these examples.\nWildcard source and/or destinations are also supported.\nTo block all traffic from a node do:\nlink 10.0.0.1 * 0\nTo set 50% packet loss on all links to 10.0.0.2 do:\nlink * 10.0.0.2 50\nTo delete all links do:\nlink * * 100\nWildcards can also be used in combination with 'bi'.\nTo list all manipulated links use 'list links'.\n",
+      ohs_cmd_link
+    },
+    { "olsrd", "olsrd [start|stop|show|setb|seta] [IP|path|args]",
+      "Start or stop local olsrd processes. Also used to set the olsrd binary path and arguments",
+      "This command is used for managing local olsrd instances from within olsr_switch.\nThe command can be configured in runtime using the setb and seta sub-commands.\nTo show the current olsrd command-configuration do:\nolsrd show\nTo set the olsrd binary path do:\nolsrd setb /full/path/to/olsrd\nTo start a olsrd instance with a IP address of 10.0.0.1, do:\nolsrd start 10.0.0.1\nTo stop that same instance do:\nolsrd stop 10.0.0.1\nseta would set arguments but is currently not implemented\n",
+      ohs_cmd_olsrd
+    },
+    { NULL, NULL,
+      NULL,
+      NULL,
+      NULL
+    }
+  };
+
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/link_rules.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/link_rules.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/link_rules.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/link_rules.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,158 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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 "link_rules.h"
+#include "olsr_host_switch.h"
+#include "ipcalc.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+ohs_check_link(struct ohs_connection *oc, union olsr_ip_addr *dst)
+{
+  struct ohs_ip_link *links;
+  for (links = oc->links; links != NULL; links = links->next) {
+    int r;
+    if (!ipequal(&links->dst, dst)) {
+        continue;
+    }
+    if (links->quality == 0) {
+      if (logbits & LOG_LINK) {
+        struct ipaddr_str addrstr, dststr;
+        printf("%s -> %s Q: %d\n", 
+               olsr_ip_to_string(&addrstr, &oc->ip_addr),
+               olsr_ip_to_string(&dststr, dst),
+               links->quality);
+      }
+      return 0;
+    }
+
+    r = 1 + (int)(100.0 / (RAND_MAX + 1.0) * rand());
+
+    if (logbits & LOG_LINK) {
+      struct ipaddr_str addrstr, dststr;
+      printf("%s -> %s Q: %d R: %d\n",  olsr_ip_to_string(&addrstr, &oc->ip_addr),
+             olsr_ip_to_string(&dststr, dst), links->quality, r);
+    }
+    /* Random - based on quality */
+    return links->quality > r ? 0 : 1;
+  }
+  return 1;
+}
+
+int
+ohs_delete_all_related_links(struct ohs_connection *oc)
+{
+  struct ohs_ip_link *links = oc->links;
+  int cnt = 0;
+
+  /* Delete links from this node*/
+  while(links)
+    {
+      struct ohs_ip_link *tmp_link = links;
+      links = links->next;
+      free(tmp_link);
+      cnt++;
+    }
+
+  /* Delete links to this node */
+
+  // XXX - ToDo
+
+  return cnt;
+}
+
+struct ohs_ip_link *
+add_link(struct ohs_connection *src, struct ohs_connection *dst)
+{
+  struct ohs_ip_link *link;
+  
+  /* Create new link */
+  link = malloc(sizeof(struct ohs_ip_link));
+  if(!link)
+    OHS_OUT_OF_MEMORY("New link");
+  /* Queue */
+  link->next = src->links;
+  src->links = link;
+  link->dst = dst->ip_addr;
+  src->linkcnt++;
+
+  return link;
+}
+
+int
+remove_link(struct ohs_connection *oc, struct ohs_ip_link *lnk)
+{
+  struct ohs_ip_link *links = oc->links;
+  struct ohs_ip_link *prev_link = NULL;
+
+  while(links)
+    {
+      if(links == lnk)
+        {
+          /* Remove */
+          if(prev_link)
+            prev_link->next = links->next;
+          else
+            oc->links = links->next;
+
+          free(lnk);
+          oc->linkcnt--;
+          return 1;
+        }
+      prev_link = links;
+      links = links->next;
+    }
+  return 0;
+}
+
+struct ohs_ip_link *
+get_link(struct ohs_connection *oc, union olsr_ip_addr *dst)
+{
+  struct ohs_ip_link *links;
+  for (links = oc->links; links != NULL; links = links->next) {
+    if (ipequal(&links->dst, dst)) {
+        return links;
+    }
+  }
+  return NULL;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/link_rules.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/link_rules.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/link_rules.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/link_rules.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,63 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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 _OLSR_SWITCH_LINK_RULES
+#define _OLSR_SWITCH_LINK_RULES
+
+#include "olsr_types.h"
+#include "olsr_host_switch.h"
+int
+ohs_check_link(struct ohs_connection *, union olsr_ip_addr *);
+
+struct ohs_ip_link *
+get_link(struct ohs_connection *, union olsr_ip_addr *);
+
+struct ohs_ip_link *
+add_link(struct ohs_connection *, struct ohs_connection *);
+
+int
+remove_link(struct ohs_connection *, struct ohs_ip_link *);
+
+int
+ohs_delete_all_related_links(struct ohs_connection *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/main.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/main.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/main.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/main.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,546 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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.
+ *
+ */
+
+/* olsrd host-switch daemon */
+
+#include "olsr_host_switch.h"
+#include "link_rules.h"
+#include "ohs_cmd.h"
+#include "ipcalc.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#ifdef WIN32
+#undef errno
+#define errno WSAGetLastError()
+#undef strerror
+#define strerror(x) StrError(x)
+#define close(x) closesocket(x)
+#else
+#include <sys/wait.h>
+#endif
+
+static int srv_socket;
+
+#define OHS_BUFSIZE 1500
+static olsr_u8_t data_buffer[OHS_BUFSIZE];
+
+struct ohs_connection *ohs_conns;
+
+//static int ip_version;
+//int ipsize;
+static struct olsrd_config olsr_cnf_data;
+struct olsrd_config *olsr_cnf = &olsr_cnf_data;
+
+olsr_u32_t logbits;
+
+/* local functions */
+static int
+ohs_init_new_connection(int);
+
+static int
+ohs_route_data(struct ohs_connection *);
+
+static int
+ohs_init_connect_sockets(void);
+
+static int
+ohs_configure(void);
+
+#if !defined WIN32
+static void
+ohs_listen_loop(void) __attribute__((noreturn));
+#else
+static void
+ohs_listen_loop(void);
+#endif
+
+#ifdef WIN32
+int __stdcall
+ohs_close(unsigned long signal __attribute__((unused)))
+#else
+void
+ohs_close(int signal __attribute__((unused)))
+#endif
+{
+  printf("OHS: exit\n");
+
+  close(srv_socket);
+
+  exit(0);
+}
+
+struct ohs_connection *
+get_client_by_addr(const union olsr_ip_addr *adr)
+{
+  struct ohs_connection *oc;
+  for (oc = ohs_conns; oc != NULL; oc = oc->next) {
+    if (ipequal(adr, &oc->ip_addr)) {
+        return oc;
+    }
+  }
+  return NULL;
+}
+
+
+static int
+ohs_init_new_connection(int s)
+{
+  struct ohs_connection *oc;
+  int i;
+
+  if(logbits & LOG_CONNECT) {
+    printf("ohs_init_new_connection\n");
+  }
+  /* Create new client node */
+  oc = calloc(1, sizeof(struct ohs_connection));
+  if (!oc) {
+    OHS_OUT_OF_MEMORY("New connection");
+  }
+
+  oc->socket = s;
+  oc->links = NULL;
+  oc->rx = 0;
+  oc->tx = 0;
+  oc->linkcnt = 0;
+
+  // hack alert: WSAEventSelect makes sockets non-blocking, so the
+  // recv() may return without having read anything on Windows; hence
+  // re-try for 2 seconds on Windows; shouldn't harm Linux et al.
+
+  /* Get "fake IP" */
+  for (i = 0; i < 20; i++) {
+    /* Win32 needs that cast. */
+      if (recv(oc->socket, (void *)&oc->ip_addr, olsr_cnf->ipsize, 0) == (int)olsr_cnf->ipsize) {
+      break;
+    }
+#if defined WIN32
+    Sleep(100);
+#endif
+  }
+
+  if (i == 20) {
+    printf("Failed to fetch IP address! (%s)\n", strerror(errno));
+    return -1;
+  }
+
+  if (logbits & LOG_CONNECT) {
+    struct ipaddr_str addrstr;
+    printf("IP: %s\n", olsr_ip_to_string(&addrstr, &oc->ip_addr));
+  }
+  if (get_client_by_addr(&oc->ip_addr)) {
+    if (logbits & LOG_CONNECT) {
+      struct ipaddr_str addrstr;
+      printf("IP: %s DUPLICATE! Disconecting client!\n", olsr_ip_to_string(&addrstr, &oc->ip_addr));
+    }
+    close(s);
+    free(oc);
+    return -1;
+  }
+
+  /* Queue */
+  oc->next = ohs_conns;
+  ohs_conns = oc;
+  return 1;
+}
+
+int
+ohs_delete_connection(struct ohs_connection *oc)
+{
+  if (!oc) {
+    return -1;
+  }
+  /* Close the socket */
+  close(oc->socket);
+
+  if(logbits & LOG_CONNECT) {
+    struct ipaddr_str addrstr;
+    printf("Removing entry %s\n", olsr_ip_to_string(&addrstr, &oc->ip_addr));
+  }
+  /* De-queue */
+  if(oc == ohs_conns) {
+    ohs_conns = ohs_conns->next;
+  } else {
+    struct ohs_connection *curr_entry = ohs_conns->next;
+    struct ohs_connection *prev_entry = ohs_conns;
+      
+    while (curr_entry != NULL) {
+      if(curr_entry == oc) {
+        prev_entry->next = curr_entry->next;
+        break;
+      }
+      prev_entry = curr_entry;
+      curr_entry = curr_entry->next;
+    }
+  }
+  ohs_delete_all_related_links(oc);
+
+  free(oc);
+  return 0;
+}
+
+static int
+ohs_route_data(struct ohs_connection *oc)
+{
+  struct ohs_connection *ohs_cs;
+  ssize_t len;
+  int cnt = 0;
+
+  oc->tx++;
+  /* Read data */
+  if((len = recv(oc->socket, data_buffer, OHS_BUFSIZE, 0)) <= 0)
+    return -1;
+
+  if(logbits & LOG_FORWARD) {
+    struct ipaddr_str addrstr;
+    printf("Received %ld bytes from %s\n", (long)len, olsr_ip_to_string(&addrstr, &oc->ip_addr));
+  }
+  /* Loop trough clients */
+  for(ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next) {
+    /* Check that the link is active open */
+    if(ohs_check_link(oc, &ohs_cs->ip_addr) &&
+       oc->socket != ohs_cs->socket) {
+      ssize_t sent;
+
+      /* Send link addr */
+      if (send(ohs_cs->socket, (const void *)&oc->ip_addr, olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize) {
+          printf("Error sending link address!\n");
+      }
+      /* Send data */
+      if (logbits & LOG_FORWARD) {
+          struct ipaddr_str addrstr, addrstr2;
+          printf("Sending %d bytes %s=>%s\n",
+                 (int)len,
+                 olsr_ip_to_string(&addrstr, &oc->ip_addr),
+                 olsr_ip_to_string(&addrstr2, &ohs_cs->ip_addr));
+      }
+
+      sent = send(ohs_cs->socket, data_buffer, len, 0);
+      if(sent != len) {
+        printf("Error sending(buf %d != sent %d)\n", (int)len, (int)sent);
+      }
+      ohs_cs->rx++;
+      cnt++;
+    }
+  }
+  return cnt;
+}
+
+static int
+ohs_init_connect_sockets(void)
+{
+  olsr_u32_t yes = 1;
+  struct sockaddr_in sin;
+
+  printf("Initiating socket TCP port %d\n", OHS_TCP_PORT);
+
+  if((srv_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    {
+      printf("Could not initialize socket(%d): %s\n", srv_socket, strerror(errno));
+      exit(0);
+    }
+
+  if(setsockopt(srv_socket, SOL_SOCKET, SO_REUSEADDR, 
+		(char *)&yes, sizeof(yes)) < 0) 
+    {
+      printf("SO_REUSEADDR failed for socket: %s\n", strerror(errno));
+      close(srv_socket);
+      exit(0);
+    }
+
+  /* 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(OHS_TCP_PORT);
+  
+  /* bind the socket to the port number */
+  if (bind(srv_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
+    {
+      printf("bind failed for socket: %s\n", strerror(errno));
+      close(srv_socket);
+      exit(0);
+    }
+  
+  /* show that we are willing to listen */
+  if (listen(srv_socket, 5) == -1) 
+    {
+      printf("listen failed for socket: %s\n", strerror(errno));
+      close(srv_socket);
+      exit(0);
+    }
+  return 1;
+}
+
+
+static int
+ohs_configure(void)
+{
+
+  return 1;
+}
+
+static void accept_handler(void)
+{
+  struct sockaddr_in pin;
+  socklen_t addrlen = sizeof(pin);
+  int s;
+	  
+  memset(&pin, 0 , sizeof(pin));
+
+  if((s = accept(srv_socket, (struct sockaddr *)&pin, &addrlen)) < 0)
+    {
+      printf("accept failed socket: %s\n", strerror(errno));
+    }
+  else
+    {
+      /* Create new node */
+      ohs_init_new_connection(s);
+    }
+}
+
+static void stdin_handler(void)
+{
+  ohs_parse_command();
+}
+
+static void read_handler(struct ohs_connection *con)
+{
+  if (ohs_route_data(con) < 0)
+    ohs_delete_connection(con);
+}
+
+static void
+ohs_listen_loop(void)
+{
+#if !defined WIN32
+  int n;
+  fd_set ibits;
+  int fn_stdin = fileno(stdin);
+
+  while(1)
+    {
+      int high;
+
+      struct ohs_connection *ohs_cs;
+
+      high = 0;
+      FD_ZERO(&ibits);
+
+      /* Add server socket */
+      high = srv_socket;
+      FD_SET(srv_socket, &ibits);
+
+      if(fn_stdin > high) 
+	high = fn_stdin;
+
+      FD_SET(fn_stdin, &ibits);
+
+      /* Add clients */
+      for(ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next)
+	{
+	  if(ohs_cs->socket > high)
+	    high = ohs_cs->socket;
+      
+	  FD_SET(ohs_cs->socket, &ibits);
+	}
+
+      /* block */
+      n = select(high + 1, &ibits, 0, 0, NULL);
+      
+      if(n == 0)
+        continue;
+
+      /* Did somethig go wrong? */
+      if (n < 0) 
+	{
+	  if(errno == EINTR)
+	    continue;
+	  
+	  printf("Error select: %s", strerror(errno));
+          continue;
+	}
+      
+      /* Check server socket */
+      if(FD_ISSET(srv_socket, &ibits))
+        accept_handler();
+
+      /* Loop trough clients */
+      ohs_cs = ohs_conns;
+      while(ohs_cs)
+	{
+	  struct ohs_connection *ohs_tmp = ohs_cs;
+	  ohs_cs = ohs_cs->next;
+
+	  if(FD_ISSET(ohs_tmp->socket, &ibits))
+            read_handler(ohs_tmp);
+	}
+
+      if(FD_ISSET(fn_stdin, &ibits))
+        stdin_handler();
+
+    }
+#else
+  HANDLE Objects[2];
+  WSANETWORKEVENTS NetEvents;
+  struct ohs_connection *Walker, *TmpWalker;
+  unsigned int Res;
+
+  Objects[0] = GetStdHandle(STD_INPUT_HANDLE);
+  Objects[1] = WSACreateEvent();
+
+  if (WSAEventSelect(srv_socket, Objects[1], FD_ACCEPT) == SOCKET_ERROR)
+  {
+    fprintf(stderr, "WSAEventSelect failed (1): %s\n", strerror(errno));
+    return;
+  }
+
+  while (1)
+  {
+    for (Walker = ohs_conns; Walker != NULL; Walker = Walker->next)
+    {
+      if (WSAEventSelect(Walker->socket, Objects[1], FD_READ | FD_CLOSE) == SOCKET_ERROR)
+      {
+        fprintf(stderr, "WSAEventSelect failed (2): %s\n", strerror(errno));
+        Sleep(1000);
+        continue;
+      }
+    }
+
+    Res = WaitForMultipleObjects(2, Objects, FALSE, INFINITE);
+
+    if (Res == WAIT_FAILED)
+    {
+      fprintf(stderr, "WaitForMultipleObjects failed: %s\n", strerror(GetLastError()));
+      Sleep(1000);
+      continue;
+    }
+
+    if (Res == WAIT_OBJECT_0)
+      stdin_handler();
+
+    else if (Res == WAIT_OBJECT_0 + 1)
+    {
+      if (WSAEnumNetworkEvents(srv_socket, Objects[1], &NetEvents) == SOCKET_ERROR)
+        fprintf(stderr, "WSAEnumNetworkEvents failed (1): %s\n", strerror(errno));
+
+      else
+      {
+        if ((NetEvents.lNetworkEvents & FD_ACCEPT) != 0)
+          accept_handler();
+      }
+
+      for (Walker = ohs_conns; Walker != NULL; Walker = TmpWalker)
+      {
+        TmpWalker = Walker->next;
+
+        if (WSAEnumNetworkEvents(Walker->socket, Objects[1], &NetEvents) == SOCKET_ERROR)
+          fprintf(stderr, "WSAEnumNetworkEvents failed (2): %s\n", strerror(errno));
+
+        else
+        {
+          if ((NetEvents.lNetworkEvents & (FD_READ | FD_CLOSE)) != 0)
+            read_handler(Walker);
+        }
+      }
+    }
+  }
+  
+#endif
+}
+
+int
+main(void)
+{
+
+#ifdef WIN32
+  WSADATA WsaData;
+
+  if (WSAStartup(0x0202, &WsaData))
+    {
+      fprintf(stderr, "Could not initialize WinSock.\n");
+      exit(EXIT_FAILURE);
+    }
+
+  SetConsoleCtrlHandler(ohs_close, OLSR_TRUE);
+
+#else
+  signal(SIGINT, ohs_close);  
+  signal(SIGTERM, ohs_close);  
+
+  /* Avoid zombie children */
+  signal(SIGCHLD, SIG_IGN);
+#endif
+
+  printf("olsrd host-switch daemon version %s starting\n", OHS_VERSION);
+
+  logbits = LOG_DEFAULT;
+  olsr_cnf->ip_version = AF_INET;
+  olsr_cnf->ipsize = sizeof(struct in_addr);
+
+  srand((unsigned int)time(NULL));
+
+  ohs_set_olsrd_path(OHS_DEFAULT_OLSRD_PATH);
+
+  ohs_init_connect_sockets();
+
+  ohs_configure();
+
+  printf("OHS command interpreter reading from STDIN\n");
+  printf("\n> ");
+  fflush(stdout);
+
+  ohs_listen_loop();
+
+  ohs_close(0);
+
+  return 1;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/Makefile ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/Makefile
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/Makefile	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,19 @@
+TOPDIR=../..
+include $(TOPDIR)/Makefile.inc
+
+ifeq ($(OS), win32)
+BINNAME = olsr_switch.exe
+OBJS += ../win32/compat.o
+else
+BINNAME = olsr_switch
+endif
+
+default_target:	$(OBJS)
+	$(CC) $(LDFLAGS) -o $(TOPDIR)/$(BINNAME) $(OBJS) $(LIBS)
+
+ohs_cmd.o: CFLAGS += -Wno-cast-qual
+
+clean:
+	rm -f *.[od]
+	rm -f *~
+	rm -f $(TOPDIR)/$(BINNAME)
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,617 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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_host_switch.h"
+#include "olsr_types.h"
+#include "commands.h"
+#include "link_rules.h"
+#include "ipcalc.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+#define TOK_BUF_SIZE 500
+static char tok_buf[TOK_BUF_SIZE];
+
+#define MAX_OLSRD_ARGS 10
+static char olsrd_path[FILENAME_MAX];
+
+static int
+get_next_token(const char *src, char *dst, size_t buflen)
+{
+  int i = 0, j = 0;
+
+  dst[0] = 0;
+  /* Skip leading spaces */
+  while(src[j] == ' ' && src[j] != 0)
+    {
+      j++;
+    }
+
+  src += j;
+  i = 0;
+  while((src[i] != ' ') && (src[i] != 0) && (i < ((int)buflen - 1)))
+    {
+      dst[i] = src[i];
+      i++;
+    }
+  dst[i] = 0;
+
+  //if(strlen(dst))
+  //printf("Extracted token: %s\n", dst);
+  return i + j;
+}
+
+int
+ohs_set_olsrd_path(const char *path)
+{
+  strscpy(olsrd_path, path, sizeof(olsrd_path));
+  return 0;
+}
+
+#ifdef WIN32
+int
+ohs_cmd_olsrd(char *args __attribute__((unused)))
+{
+  printf("olsrd command not available in windows version\nStart instances manually\n");
+  return 0;
+}
+#else
+int
+ohs_cmd_olsrd(const char *args)
+{
+  const char *olsrd_args[MAX_OLSRD_ARGS];
+  struct in_addr iaddr;
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+
+  if(!strlen(tok_buf))
+    goto print_usage;
+
+  /* Start olsrd instance */
+  if(!strncmp(tok_buf, "start", strlen("start")))
+    {
+      int argc = 0, i = 0;
+
+      args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+      
+      if(!strlen(tok_buf))
+	goto print_usage;
+
+      if(!inet_aton(tok_buf, &iaddr))
+	{
+	  printf("Invalid IP %s\n", tok_buf);
+	  goto print_usage;
+	}
+
+      olsrd_args[argc++] = olsrd_path;
+
+      if(1) /* config file is set */
+	{
+	  olsrd_args[argc++] = "-f";
+	  olsrd_args[argc++] = "/etc/olsrd-emu.conf";
+	}
+      olsrd_args[argc++] = "-hemu";
+      olsrd_args[argc++] = tok_buf;
+
+      olsrd_args[argc++] = "-d";
+      olsrd_args[argc++] = "0";
+      olsrd_args[argc++] = "-nofork";
+      olsrd_args[argc] = NULL;
+
+      printf("Executing: %s", olsrd_path);
+      for(i = 0; i < argc; i++)
+	printf(" %s", olsrd_args[i]);
+      printf("\n");
+
+      if(fork())
+	return 1;
+
+      if(execve(olsrd_path, (char * const *)olsrd_args, NULL) < 0)
+	{
+	  printf("Error executing olsrd: %s\n", strerror(errno));
+	  exit(1);
+	}
+    }
+  /* Stop olsrd instance */
+  else if(!strncmp(tok_buf, "stop", strlen("stop")))
+    {
+      struct ohs_connection *oc;
+
+      args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+      
+      if(!strlen(tok_buf))
+	goto print_usage;
+
+      if(!inet_aton(tok_buf, &iaddr))
+	{
+	  printf("Invalid IP %s\n", tok_buf);
+	  goto print_usage;
+	}
+
+      oc = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
+
+      if(!oc)
+	{
+	  printf("No such client: %s\n", tok_buf);
+	  return -1;
+	}
+      ohs_delete_connection(oc);
+      
+      return 1;
+    }
+  /* Set olsrd binary path */
+  else if(!strncmp(tok_buf, "setb", strlen("setb")))
+    {
+      struct stat sbuf;
+
+      args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+      
+      if(!strlen(tok_buf))
+	goto print_usage;
+
+      if(stat(tok_buf, &sbuf) < 0)
+	{
+	  printf("Error setting binary \"%s\": %s\n",
+		 tok_buf, strerror(errno));
+	  return -1;
+	}
+
+      if((sbuf.st_mode & S_IFDIR) || !(sbuf.st_mode & S_IXUSR))
+	{
+	  printf("Error setting binary \"%s\": Not a regular execuatble file!\n",
+		 tok_buf);
+	  return -1;
+	}
+
+      printf("New olsrd binary path:\"%s\"\n", tok_buf);
+      ohs_set_olsrd_path(tok_buf);
+
+      return 1;
+
+    }
+  /* Set arguments */
+  else if(!strncmp(tok_buf, "seta", strlen("seta")))
+    {
+	printf("Error - NOT IMPLEMENTED YET\n");
+	return 1;
+    }
+  /* Show settings */
+  else if(!strncmp(tok_buf, "show", strlen("show")))
+    {
+      printf("olsrd command settings:\n\tBinary path: %s\n\tArguments  : \n",
+	     olsrd_path);
+      return 1;
+    }
+
+ print_usage:
+  printf("Usage: olsrd [start|stop|show|setb|seta] [IP|path|args]\n");
+  return 0;
+}
+#endif
+
+int
+ohs_cmd_link(const char *args)
+{
+  olsr_u8_t bi = 0, wildc_src = 0, wildc_dst = 0;
+  struct ohs_connection *src, *dst;
+  struct in_addr iaddr;
+  int qual;
+  struct ohs_ip_link *link, *inv_link;
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+
+  if (!strlen(tok_buf)) {
+    goto print_usage;
+  }
+  if(!strncmp(tok_buf, "bi", strlen("bi"))) {
+    bi = 1;
+    args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+
+    if (!strlen(tok_buf)) {
+      goto print_usage;
+    }
+  }
+
+  if(tok_buf[0] == '*') {
+    wildc_src = 1;
+    src = ohs_conns;
+  } else {
+    if (!inet_aton(tok_buf, &iaddr)) {
+      printf("Invalid src IP %s\n", tok_buf);
+      return -1;
+    }
+
+    src = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
+
+    if (!src) {
+        printf("No such client: %s!\n", tok_buf);
+        return -1;
+    }
+  }
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+  
+  if (!strlen(tok_buf)) {
+    goto print_usage;
+  }
+
+  if(tok_buf[0] == '*') {
+    wildc_dst = 1;
+    dst = ohs_conns;
+  } else {
+    if(!inet_aton(tok_buf, &iaddr)) {
+      printf("Invalid src IP %s\n", tok_buf);
+      return -1;
+    }
+      
+    dst = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
+    if (!dst) {
+      printf("No such client: %s!\n", tok_buf);
+      return -1;
+    }
+  }
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+  
+  if (!strlen(tok_buf)) {
+    goto print_usage;
+  }
+
+  /* No use for bi if both src and dst are widcards */
+  if (wildc_src && wildc_dst) {
+    bi = 0;
+  }
+
+  qual = atoi(tok_buf);
+
+  if(qual < 0 || qual > 100) {
+    printf("Link quality out of range(0-100)\n");
+    return -1;
+  }
+
+  while (src) {
+    while (dst) {
+      struct ipaddr_str srcaddrstr, dstaddrstr;
+
+      if(src != dst) {
+        link = get_link(src, &dst->ip_addr);
+        inv_link = bi ? get_link(dst, &src->ip_addr) : NULL;
+        if(qual == 100)  {
+          /* Remove link entry */
+          if (link) {
+	    remove_link(src, link);
+          }
+          if (inv_link) {
+            remove_link(dst, inv_link);
+          }
+        } else  {
+          if (!link) {
+            /* Create new link */
+            link = add_link(src, dst);
+          }
+	      
+          link->quality = qual;
+	      
+          if (bi) {
+            if(!inv_link) {
+              /* Create new link */
+              inv_link = add_link(dst, src);
+            }
+            inv_link->quality = qual;
+          }
+        }
+        printf("%s %sdirectional link(s) %s %c=> %s quality %d\n", 
+               (qual == 100) ? "Removing" : "Setting",
+               bi ? "bi" : "uni",
+               olsr_ip_to_string(&srcaddrstr, &src->ip_addr),
+               bi ? '<' : '=', 
+               olsr_ip_to_string(&dstaddrstr, &dst->ip_addr),
+               qual);
+      }
+      if (wildc_dst) {
+	    dst = dst->next;
+      } else {
+	    break;
+      }
+    }
+    dst = wildc_dst ? ohs_conns : dst;
+    src = wildc_src ? src->next : NULL;
+  }
+
+  return 1;
+ print_usage:
+  printf("link <bi> srcIP dstIP [0-100]");
+  return -1;
+}
+
+int
+ohs_cmd_list(const char *args)
+{
+  struct ohs_connection *oc = ohs_conns;
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+  
+  if(!strlen(tok_buf) || 
+     !strncmp(tok_buf, "clients", strlen("clients"))) {
+    printf("All connected clients:\n");
+      
+    while(oc) {
+      struct ipaddr_str addrstr;
+      printf("\t%s - Rx: %d Tx: %d LinkCnt: %d\n",
+             olsr_ip_to_string(&addrstr, &oc->ip_addr), 
+             oc->rx,
+             oc->tx,
+             oc->linkcnt);
+      oc = oc->next;
+    }
+  }
+  else if(!strncmp(tok_buf, "links", strlen("links"))) {
+    printf("All configured links:\n");
+    while (oc) {
+      struct ohs_ip_link *links = oc->links;
+      while (links) {
+          struct ipaddr_str addrstr, dststr;
+        printf("\t%s => %s Quality: %d\n", 
+               olsr_ip_to_string(&addrstr, &oc->ip_addr),
+               olsr_ip_to_string(&dststr, &links->dst),
+               links->quality);
+
+        links = links->next;
+      }
+      oc = oc->next;
+    }
+  } else {
+    printf("list [clients|links]");
+    return -1;
+  }
+  return 1;
+}
+
+int
+ohs_cmd_help(const char *args)
+{
+  int i;
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+  
+  if(!strlen(tok_buf))
+    {
+      printf("Olsrd host switch version %s\n", OHS_VERSION);
+      printf("Available commands:\n");
+      
+      for(i = 0; ohs_commands[i].cmd; i++)
+	{
+	  if(ohs_commands[i].helptext_brief)
+	    printf("\t%s - %s\n", 
+		   ohs_commands[i].cmd,
+		   ohs_commands[i].helptext_brief);
+	}
+      printf("\nType 'help cmd' for help on a specific command\n");
+    }
+  else
+    {
+      for(i = 0; ohs_commands[i].cmd; i++)
+	{
+	  if(!strncmp(tok_buf, ohs_commands[i].cmd, strlen(ohs_commands[i].cmd)))
+	    {
+	      printf("Usage: %s\nDescription:\n%s\n", 
+		     ohs_commands[i].syntax,
+		     ohs_commands[i].helptext_long);
+	      return 1;
+	    }
+	}
+
+      printf("Usage: help <command>\n");
+    }
+
+  return i;
+}
+
+int
+ohs_cmd_log(const char *args)
+{
+  olsr_u8_t set = 0;
+
+  args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+  
+  if(strlen(tok_buf) &&
+     ((set = !strncmp(tok_buf, "set", strlen("set"))) || 
+      !strncmp(tok_buf, "unset", strlen("unset"))))
+    {
+        olsr_u32_t new_bit = 0;
+        
+        args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
+  
+        if(!strlen(tok_buf))
+            goto print_usage;
+        
+        
+        if(!strncmp(tok_buf, "CON", strlen("CON")))
+	    new_bit = LOG_CONNECT;
+        else if(!strncmp(tok_buf, "FOR", strlen("FOR")))
+	    new_bit = LOG_FORWARD;
+        else if(!strncmp(tok_buf, "LIN", strlen("LIN")))
+	    new_bit = LOG_LINK;
+	  
+        if(!new_bit)
+	    goto print_usage;
+
+        if(set)
+	    logbits |= new_bit;
+        else
+	    logbits &= ~new_bit;
+
+        printf("%s log bit: 0x%08x, new log: 0x%08x\n", set ? "Setting" : "Removing",
+               new_bit, logbits);
+
+    }
+  else
+    {
+      if(strlen(tok_buf))
+	goto print_usage;
+
+      printf("Log: (0x%08x) ", logbits);
+      if(logbits & LOG_CONNECT)
+	printf("CONNECT ");
+      if(logbits & LOG_FORWARD)
+	printf("FORWARD ");
+      if(logbits & LOG_LINK)
+	printf("LINK ");
+
+      printf("\n");
+    }
+  return 1;
+
+ print_usage:
+  printf("Usage: log <[set|unset] [CONNECT|FORWARD|LINK]>\n");
+  return 0;
+
+}
+
+int
+ohs_cmd_exit(const char *args __attribute__((unused)))
+{
+
+  printf("Exitting... bye-bye!\n");
+
+  ohs_close(0);
+}
+
+void
+ohs_parse_command(void)
+{
+  static char cmd_line[500];
+  static int cmd_len = 0;
+  char *args;
+  char cmd_token[20];
+  int i;
+#if defined WIN32
+  char c;
+  unsigned long Read;
+  INPUT_RECORD InRec;
+  KEY_EVENT_RECORD *KeyEventRec;
+#endif
+
+#if defined WIN32
+  if (!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &InRec, sizeof (InRec), &Read))
+  {
+    fprintf(stderr, "ReadConsoleInput failed: %s\n", strerror(GetLastError()));
+    return;
+  }
+
+  if (InRec.EventType != KEY_EVENT)
+    return;
+
+  KeyEventRec = &InRec.Event.KeyEvent;
+
+  if (!KeyEventRec->bKeyDown)
+    return;
+
+  c = KeyEventRec->uChar.AsciiChar;
+
+  if (c == 8)
+  {
+    if (cmd_len == 0)
+      return;
+
+    cmd_len--;
+
+    fputc(8, stdout);
+    fputc(32, stdout);
+    fputc(8, stdout);
+
+    fflush(stdout);
+
+    return;
+  }
+
+  fputc(c, stdout);
+  fflush(stdout);
+
+  if (c != '\n' && c != '\r' && cmd_len < (int)sizeof (cmd_line) - 1)
+    cmd_line[cmd_len++] = (char)c;
+
+  else
+#else
+  if(fgets(cmd_line, sizeof (cmd_line), stdin) == NULL) {
+    ohs_cmd_exit(NULL);
+  }
+
+  for (cmd_len = 0; cmd_line[cmd_len] != 0 && cmd_line[cmd_len] != '\n';
+       cmd_len++);
+#endif
+
+  {
+    cmd_line[cmd_len] = 0;
+    cmd_len = 0;
+
+    args = cmd_line + get_next_token(cmd_line, cmd_token, sizeof (cmd_token));
+
+    for (i = 0; ohs_commands[i].cmd != NULL; i++)
+    {
+      if (strcmp(cmd_token, ohs_commands[i].cmd) == 0)
+      {
+        if(ohs_commands[i].cmd_cb != NULL)
+          ohs_commands[i].cmd_cb(args);
+
+        else
+          printf("No action registered on cmd %s!\n", cmd_token);
+
+        break;
+      }
+    }
+  
+    if(ohs_commands[i].cmd == NULL)
+      printf("%s: no such cmd!\n", cmd_token);
+
+    printf("\n> ");
+    fflush(stdout);
+  }
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/ohs_cmd.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,81 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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 _OHS_CMD
+#define _OHS_CMD
+
+#include <stdio.h>
+
+struct ohs_command
+{
+  const char *cmd;
+  const char *syntax;
+  const char *helptext_brief;
+  const char *helptext_long;
+  int (*cmd_cb)(const char *);
+};
+
+int
+ohs_set_olsrd_path(const char *);
+
+void
+ohs_parse_command(void);
+
+int
+ohs_cmd_olsrd(const char *);
+
+int
+ohs_cmd_list(const char *);
+
+int
+ohs_cmd_help(const char *);
+
+int
+ohs_cmd_exit(const char *) __attribute__((noreturn));
+
+int
+ohs_cmd_log(const char *);
+
+int
+ohs_cmd_link(const char *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/olsr_host_switch.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/olsr_host_switch.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_switch/olsr_host_switch.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_switch/olsr_host_switch.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,102 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2005, 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 _OLSR_HOST_SWITCH
+#define _OLSR_HOST_SWITCH
+
+#include "olsr_types.h"
+
+#define OHS_TCP_PORT 10150
+
+#define OHS_VERSION "0.1"
+
+#define OHS_DEFAULT_OLSRD_PATH "./olsrd"
+
+#define OHS_OUT_OF_MEMORY(s) do { printf("ohsd: out of memory \"%s\"!\n", s); ohs_close(0); } while (0)
+
+#ifdef WIN32
+#define close(x) closesocket(x)
+int __stdcall ohs_close(unsigned long signal) __attribute__((noreturn));
+#else
+void ohs_close(int) __attribute__((noreturn));
+#endif
+
+struct ohs_ip_link
+{
+  union olsr_ip_addr   dst;
+  olsr_u8_t            quality; /* 0 - 100 */
+  struct ohs_ip_link   *next;
+};
+
+struct ohs_connection
+{
+  union olsr_ip_addr     ip_addr;
+  int                    socket;
+  olsr_u32_t             rx;
+  olsr_u32_t             tx;
+  olsr_u32_t             linkcnt;
+  struct ohs_ip_link     *links;
+  struct ohs_connection  *next;
+};
+
+extern olsr_u32_t logbits;
+
+extern struct ohs_connection *ohs_conns;
+
+#define LOG_DEFAULT 0x0
+#define LOG_FORWARD 0x1
+#define LOG_CONNECT 0x2
+#define LOG_LINK    0x4
+
+#ifdef WIN32
+int __stdcall
+SignalHandler(unsigned long);
+#else
+void
+ohs_close(int);
+#endif
+
+struct ohs_connection *
+get_client_by_addr(const union olsr_ip_addr *);
+
+int
+ohs_delete_connection(struct ohs_connection *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_types.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_types.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/olsr_types.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/olsr_types.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *Values and packet formats as proposed in RFC3626 and misc. values and
+ *data structures used by the olsr.org OLSR daemon.
+ */
+
+#ifndef _OLSR_TYPES_H
+#define	_OLSR_TYPES_H
+
+/* types */
+#ifdef _MSC_VER
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+typedef char            int8_t;
+typedef short           int16_t;
+typedef int             int32_t;
+#else
+#include <inttypes.h>
+#endif
+
+
+typedef enum {
+    OLSR_FALSE = 0,
+    OLSR_TRUE
+} olsr_bool;
+
+/* user defined cookies */
+typedef uint16_t        olsr_cookie_t;
+
+#if defined linux || defined __MacOSX__ || defined WIN32 || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
+
+typedef uint8_t         olsr_u8_t;
+typedef uint16_t        olsr_u16_t;
+typedef uint32_t        olsr_u32_t;
+typedef int8_t          olsr_8_t;
+typedef int16_t         olsr_16_t;
+typedef int32_t         olsr_32_t;
+
+#else
+#       error "Unsupported system"
+#endif
+
+/* OpenBSD wants this here */
+#include <sys/types.h>
+/* IPv6 address format in6_addr */
+#ifndef _MSC_VER
+#include <netinet/in.h>
+#endif
+
+
+union olsr_ip_addr {
+  struct in_addr v4;
+  struct in6_addr v6;
+};
+
+struct olsr_ip_prefix {
+  union olsr_ip_addr prefix;
+  olsr_u8_t prefix_len;
+};
+
+typedef olsr_u32_t olsr_linkcost;
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/packet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/packet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/packet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/packet.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,427 @@
+/*
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "link_set.h"
+#include "mpr_selector_set.h"
+#include "mpr.h"
+#include "olsr.h"
+#include "neighbor_table.h"
+#include "build_msg.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+
+static olsr_bool sending_tc = OLSR_FALSE;
+
+/**
+ *Free the memory allocated for a HELLO packet.
+ *
+ *@param message the pointer to the packet to erase
+ *
+ *@return nada
+ */
+void
+olsr_free_hello_packet(struct hello_message *message)
+{
+  struct hello_neighbor *nb;
+
+  if(!message)
+    return;
+  
+  nb = message->neighbors;
+  while (nb) {
+    struct hello_neighbor *prev_nb = nb;
+    nb = nb->next;
+    free(prev_nb);
+  }
+}
+
+/**
+ *Build an internal HELLO package for this
+ *node. This MUST be done for each interface.
+ *
+ *@param message the hello_message struct to fill with info
+ *@param outif the interface to send the message on - messages
+ *are created individually for each interface!
+ *@return 0
+ */
+int
+olsr_build_hello_packet(struct hello_message *message, struct interface *outif)
+{
+  struct hello_neighbor   *message_neighbor, *tmp_neigh;
+  struct link_entry       *links;
+  struct neighbor_entry   *neighbor;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "\tBuilding HELLO on interface \"%s\"\n", outif->int_name ? outif->int_name : "<null>");
+#endif
+
+  message->neighbors=NULL;
+  message->packet_seq_number=0;
+  
+  //message->mpr_seq_number=neighbortable.neighbor_mpr_seq;
+
+  /* Set willingness */
+
+  message->willingness = olsr_cnf->willingness;
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Willingness: %d\n", olsr_cnf->willingness);
+#endif
+
+  /* Set TTL */
+
+  message->ttl = 1;  
+  message->source_addr = olsr_cnf->main_addr;
+
+#ifdef DEBUG
+  OLSR_PRINTF(5, "On link:\n");
+#endif
+
+  /* Walk all links of this interface */
+  OLSR_FOR_ALL_LINK_ENTRIES(links) {
+#ifdef DEBUG
+    struct ipaddr_str buf;
+#endif
+    int lnk = lookup_link_status(links);
+    /* Update the status */
+      
+    /* Check if this link tuple is registered on the outgoing interface */
+    if (!ipequal(&links->local_iface_addr, &outif->ip_addr)) {
+      continue;
+    }
+
+    message_neighbor = olsr_malloc_hello_neighbor("Build HELLO");
+      
+    /* Find the link status */
+    message_neighbor->link = lnk;
+
+    /*
+     * Calculate neighbor status
+     */
+    /* 
+     * 2.1  If the main address, corresponding to
+     *      L_neighbor_iface_addr, is included in the MPR set:
+     *
+     *            Neighbor Type = MPR_NEIGH
+     */
+    if (links->neighbor->is_mpr) {
+      message_neighbor->status = MPR_NEIGH;
+    }
+    /*
+     *  2.2  Otherwise, if the main address, corresponding to
+     *       L_neighbor_iface_addr, is included in the neighbor set:
+     */
+      
+    /* NOTE:
+     * It is garanteed to be included when come this far
+     * due to the extentions made in the link sensing
+     * regarding main addresses.
+     */
+    else {
+
+      /*
+       *   2.2.1
+       *        if N_status == SYM
+       *
+       *             Neighbor Type = SYM_NEIGH
+       */
+      if (links->neighbor->status == SYM) {
+        message_neighbor->status = SYM_NEIGH;
+      }
+
+      /*
+       *   2.2.2
+       *        Otherwise, if N_status == NOT_SYM
+       *             Neighbor Type = NOT_NEIGH
+       */
+      else if (links->neighbor->status == NOT_SYM) {
+          message_neighbor->status = NOT_NEIGH;
+        }
+    }
+  
+    /* Set the remote interface address */
+    message_neighbor->address = links->neighbor_iface_addr;
+      
+    /* Set the main address */
+    message_neighbor->main_address = links->neighbor->neighbor_main_addr;
+#ifdef DEBUG
+    OLSR_PRINTF(5, "Added: %s -  status %d\n", olsr_ip_to_string(&buf, &message_neighbor->address), message_neighbor->status);
+#endif
+    message_neighbor->next=message->neighbors;
+    message->neighbors=message_neighbor;	    
+      
+  } OLSR_FOR_ALL_LINK_ENTRIES_END(links);
+  
+  /* Add the links */
+
+#ifdef DEBUG
+    OLSR_PRINTF(5, "Not on link:\n");
+#endif
+
+  /* Add the rest of the neighbors if running on multiple interfaces */
+  
+  if (ifnet != NULL && ifnet->int_next != NULL)
+    OLSR_FOR_ALL_NBR_ENTRIES(neighbor) {
+
+#ifdef DEBUG
+    struct ipaddr_str buf;
+#endif
+    /* Check that the neighbor is not added yet */
+    tmp_neigh = message->neighbors;
+    //printf("Checking that the neighbor is not yet added\n");
+    while (tmp_neigh) {
+      if (ipequal(&tmp_neigh->main_address, &neighbor->neighbor_main_addr)) {
+        //printf("Not adding duplicate neighbor %s\n", olsr_ip_to_string(&neighbor->neighbor_main_addr));
+        break;
+      }
+      tmp_neigh = tmp_neigh->next;
+    }
+
+    if (tmp_neigh) {
+      continue;
+    }
+	    
+	  message_neighbor = olsr_malloc_hello_neighbor("Build HELLO 2");
+	    
+    message_neighbor->link = UNSPEC_LINK;
+	    
+    /*
+     * Calculate neighbor status
+     */
+    /* 
+     * 2.1  If the main address, corresponding to
+     *      L_neighbor_iface_addr, is included in the MPR set:
+     *
+     *            Neighbor Type = MPR_NEIGH
+     */
+    if (neighbor->is_mpr) {
+      message_neighbor->status = MPR_NEIGH;
+    }
+    /*
+     *  2.2  Otherwise, if the main address, corresponding to
+     *       L_neighbor_iface_addr, is included in the neighbor set:
+     */
+	    
+    /* NOTE:
+     * It is garanteed to be included when come this far
+     * due to the extentions made in the link sensing
+     * regarding main addresses.
+     */
+    else {
+
+      /*
+       *   2.2.1
+       *        if N_status == SYM
+       *
+       *             Neighbor Type = SYM_NEIGH
+       */
+      if (neighbor->status == SYM) {
+        message_neighbor->status = SYM_NEIGH;
+      }
+
+      /*
+       *   2.2.2
+       *        Otherwise, if N_status == NOT_SYM
+       *             Neighbor Type = NOT_NEIGH
+       */
+      else if (neighbor->status == NOT_SYM) {
+        message_neighbor->status = NOT_NEIGH;		      
+      }
+    }
+	    
+
+    message_neighbor->address = neighbor->neighbor_main_addr;
+    message_neighbor->main_address = neighbor->neighbor_main_addr;
+#ifdef DEBUG
+    OLSR_PRINTF(5, "Added: %s -  status  %d\n", olsr_ip_to_string(&buf, &message_neighbor->address), message_neighbor->status);
+#endif
+    message_neighbor->next=message->neighbors;
+    message->neighbors=message_neighbor;	
+    
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor);
+
+  return 0;
+}
+
+
+/**
+ *Free the memory allocated for a TC packet.
+ *
+ *@param message the pointer to the packet to erase
+ *
+ *@return nada
+ */
+void 
+olsr_free_tc_packet(struct tc_message *message)
+{
+  struct tc_mpr_addr *mprs;
+
+  if(!message)
+    return;
+
+  mprs = message->multipoint_relay_selector_address;
+  while (mprs != NULL) {
+    struct tc_mpr_addr *prev_mprs = mprs;
+    mprs = mprs->next;
+    free(prev_mprs);
+  }
+}
+
+/**
+ *Build an internal TC package for this
+ *node.
+ *
+ *@param message the tc_message struct to fill with info
+ *@return 0
+ */
+int
+olsr_build_tc_packet(struct tc_message *message)
+{
+  struct tc_mpr_addr     *message_mpr;
+  struct neighbor_entry  *entry;
+  olsr_bool entry_added = OLSR_FALSE;
+
+  message->multipoint_relay_selector_address=NULL;
+  message->packet_seq_number=0;
+ 
+  message->hop_count = 0;
+  message->ttl = MAX_TTL;
+  message->ansn = get_local_ansn();
+
+  message->originator = olsr_cnf->main_addr;
+  message->source_addr = olsr_cnf->main_addr;
+  
+
+  /* Loop trough all neighbors */  
+  OLSR_FOR_ALL_NBR_ENTRIES(entry) {
+    if (entry->status != SYM) {
+      continue;
+    }
+
+    switch (olsr_cnf->tc_redundancy) {
+    case(2):
+    {
+	  	/* 2 = Add all neighbors */
+  		//printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
+		  message_mpr = olsr_malloc_tc_mpr_addr("Build TC");
+		
+      message_mpr->address = entry->neighbor_main_addr;
+      message_mpr->next = message->multipoint_relay_selector_address;
+      message->multipoint_relay_selector_address = message_mpr;
+      entry_added = OLSR_TRUE;		
+      break;
+    }
+    case(1):
+    {
+      /* 1 = Add all MPR selectors and selected MPRs */
+      if ((entry->is_mpr) ||
+          (olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL)) {
+        //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
+        message_mpr = olsr_malloc_tc_mpr_addr("Build TC 2");
+		    
+        message_mpr->address = entry->neighbor_main_addr;
+        message_mpr->next = message->multipoint_relay_selector_address;
+        message->multipoint_relay_selector_address = message_mpr;
+        entry_added = OLSR_TRUE;
+      }
+      break;
+    }
+    default:
+    {
+      /* 0 = Add only MPR selectors(default) */
+      if (olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL) {
+        //printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
+        message_mpr = olsr_malloc_tc_mpr_addr("Build TC 3");
+		    
+        message_mpr->address = entry->neighbor_main_addr;
+        message_mpr->next = message->multipoint_relay_selector_address;
+        message->multipoint_relay_selector_address = message_mpr;
+        entry_added = OLSR_TRUE;
+      }
+      break;
+    }		
+	  
+    } /* Switch */
+  } OLSR_FOR_ALL_NBR_ENTRIES_END(entry);
+
+  if (entry_added) {
+    sending_tc = OLSR_TRUE;
+  } else {
+    if (sending_tc) {
+      /* Send empty TC */
+      OLSR_PRINTF(3, "No more MPR selectors - will send empty TCs\n");
+      set_empty_tc_timer(GET_TIMESTAMP((olsr_cnf->max_tc_vtime * 3) * MSEC_PER_SEC));
+      sending_tc = OLSR_FALSE;
+    }
+  }
+
+  return 0;
+}
+
+/**
+ *Free the memory allocated for a MID packet.
+ *
+ *@param message the pointer to the packet to erase
+ *
+ *@return nada
+ */
+
+void
+olsr_free_mid_packet(struct mid_message *message)
+{
+  struct mid_alias *tmp_adr, *tmp_adr2;
+
+  tmp_adr = message->mid_addr;
+
+  while(tmp_adr)
+    {
+      tmp_adr2 = tmp_adr;
+      tmp_adr = tmp_adr->next;
+      free(tmp_adr2);
+    }
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/packet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/packet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/packet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/packet.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,141 @@
+/*
+ * 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 _OLSR_PACKET
+#define _OLSR_PACKET
+
+#include "olsr_protocol.h"
+#include "interfaces.h"
+#include "mantissa.h"
+
+struct hello_neighbor
+{
+  olsr_u8_t             status;
+  olsr_u8_t             link;
+  union olsr_ip_addr    main_address;
+  union olsr_ip_addr    address;
+  struct hello_neighbor *next;
+  olsr_linkcost         cost;
+  olsr_u32_t            linkquality[0];
+};
+
+struct hello_message
+{
+  olsr_reltime           vtime;
+  olsr_reltime           htime;
+  union olsr_ip_addr     source_addr;
+  olsr_u16_t             packet_seq_number;
+  olsr_u8_t              hop_count;
+  olsr_u8_t              ttl;
+  olsr_u8_t              willingness;
+  struct hello_neighbor  *neighbors;
+  
+};
+
+struct tc_mpr_addr
+{
+  union olsr_ip_addr address;
+  struct tc_mpr_addr *next;
+  olsr_u32_t         linkquality[0];
+};
+
+struct tc_message
+{
+  olsr_reltime        vtime;
+  union olsr_ip_addr  source_addr;
+  union olsr_ip_addr  originator;
+  olsr_u16_t          packet_seq_number;
+  olsr_u8_t           hop_count;
+  olsr_u8_t           ttl;
+  olsr_u16_t          ansn;
+  struct tc_mpr_addr  *multipoint_relay_selector_address;
+};
+
+/*
+ *MID messages - format:
+ *
+ *ADDR
+ *ADDR
+ *ADDR
+ *.....
+ */
+
+struct mid_alias
+{
+  union olsr_ip_addr alias_addr;
+  struct mid_alias   *next;
+};
+
+struct mid_message
+{
+  olsr_reltime       vtime;
+  union olsr_ip_addr mid_origaddr;  /* originator's address */
+  olsr_u8_t          mid_hopcnt;    /* number of hops to destination */
+  olsr_u8_t          mid_ttl;       /* ttl */
+  olsr_u16_t         mid_seqno;     /* sequence number */
+  union olsr_ip_addr addr;          /* main address */
+  struct mid_alias   *mid_addr;     /* variable length */
+};
+
+
+struct unknown_message
+{
+  olsr_u16_t         seqno;
+  union olsr_ip_addr originator;
+  olsr_u8_t          type;
+};
+
+
+void
+olsr_free_hello_packet(struct hello_message *);
+
+int
+olsr_build_hello_packet(struct hello_message *, struct interface *);
+
+void 
+olsr_free_tc_packet(struct tc_message *);
+
+int
+olsr_build_tc_packet(struct tc_message *);
+
+void
+olsr_free_mid_packet(struct mid_message *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/parser.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/parser.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/parser.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/parser.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,613 @@
+/*
+ * 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 "parser.h"
+#include "ipcalc.h"
+#include "defs.h"
+#include "process_package.h"
+#include "mantissa.h"
+#include "hysteresis.h"
+#include "duplicate_set.h"
+#include "mid_set.h"
+#include "olsr.h"
+#include "rebuild_packet.h"
+#include "net_os.h"
+#include "log.h"
+#include "print_packet.h"
+#include "net_olsr.h"
+
+#ifdef WIN32
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef errno
+#define errno WSAGetLastError()
+#undef strerror
+#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;
+struct preprocessor_function_entry *preprocessor_functions;
+struct packetparser_function_entry *packetparser_functions;
+
+static char inbuf[MAXMESSAGESIZE+1];
+
+static olsr_bool disp_pack_in = OLSR_FALSE;
+
+void parser_set_disp_pack_in(olsr_bool val) {
+  disp_pack_in = val;
+}
+
+/**
+ *Initialize the parser. 
+ *
+ *@return nada
+ */
+void olsr_init_parser(void) {
+  OLSR_PRINTF(3, "Initializing parser...\n");
+  
+  /* Initialize the packet functions */
+  olsr_init_package_process();
+  
+}
+
+void olsr_parser_add_function(parse_function *function, olsr_u32_t type, int forwarding) {
+  struct parse_function_entry *new_entry;
+  
+  OLSR_PRINTF(3, "Parser: registering event for type %d\n", type);
+  
+  new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
+  
+  new_entry->function = function;
+  new_entry->type = type;
+  new_entry->caller_forwarding = forwarding;
+  
+  /* Queue */
+  new_entry->next = parse_functions;
+  parse_functions = new_entry;
+  
+  OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type);
+  
+}
+
+int olsr_parser_remove_function(parse_function *function, olsr_u32_t type, int forwarding) {
+  struct parse_function_entry *entry, *prev;
+  
+  entry = parse_functions;
+  prev = NULL;
+  
+  while (entry) {
+    if ((entry->function == function) && (entry->type == type) && (entry->caller_forwarding == forwarding)) {
+      if (entry == parse_functions) {
+        parse_functions = entry->next;
+      } else {
+        prev->next = entry->next;
+      }
+      free(entry);
+      return 1;
+    }
+    
+    prev = entry;
+    entry = entry->next;
+  }
+  
+  return 0;
+}
+
+void olsr_preprocessor_add_function(preprocessor_function *function) {
+  struct preprocessor_function_entry *new_entry;
+  
+  OLSR_PRINTF(3, "Parser: registering preprocessor\n");
+  
+  new_entry = olsr_malloc(sizeof(struct preprocessor_function_entry), "Register preprocessor function");
+  
+  new_entry->function = function;
+  
+  /* Queue */
+  new_entry->next = preprocessor_functions;
+  preprocessor_functions = new_entry;
+  
+  OLSR_PRINTF(3, "Registered preprocessor function\n");
+  
+}
+
+int olsr_preprocessor_remove_function(preprocessor_function *function) {
+  struct preprocessor_function_entry *entry, *prev;
+  
+  entry = preprocessor_functions;
+  prev = NULL;
+  
+  while (entry) {
+    if (entry->function == function) {
+      if (entry == preprocessor_functions) {
+        preprocessor_functions = entry->next;
+      } else {
+        prev->next = entry->next;
+      }
+      free(entry);
+      return 1;
+    }
+    
+    prev = entry;
+    entry = entry->next;
+  }
+  
+  return 0;
+}
+
+void olsr_packetparser_add_function(packetparser_function *function) {
+  struct packetparser_function_entry *new_entry;
+  
+  OLSR_PRINTF(3, "Parser: registering packetparser\n");
+  
+  new_entry = olsr_malloc(sizeof(struct packetparser_function_entry), "Register packetparser function");
+  
+  new_entry->function = function;
+  
+  /* Queue */
+  new_entry->next = packetparser_functions;
+  packetparser_functions = new_entry;
+  
+  OLSR_PRINTF(3, "Registered packetparser  function\n");
+  
+}
+
+int olsr_packetparser_remove_function(packetparser_function *function) {
+  struct packetparser_function_entry *entry, *prev;
+  
+  entry = packetparser_functions;
+  prev = NULL;
+  
+  while (entry) {
+    if (entry->function == function) {
+      if (entry == packetparser_functions) {
+        packetparser_functions = entry->next;
+      } else {
+        prev->next = entry->next;
+      }
+      free(entry);
+      return 1;
+    }
+    
+    prev = entry;
+    entry = entry->next;
+  }
+  
+  return 0;
+}
+
+/**
+ *Process a newly received OLSR packet. Checks the type
+ *and to the neccessary convertions and call the
+ *corresponding functions to handle the information.
+ *@param from the sockaddr struct describing the sender
+ *@param olsr the olsr struct containing the message
+ *@param size the size of the message
+ *@return nada
+ */
+
+void parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr) {
+  union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
+  struct unknown_message unkpacket;
+  int count;
+  int msgsize;
+  int processed;
+  struct parse_function_entry *entry;
+  struct packetparser_function_entry *packetparser;
+  
+  count = size - ((char *)m - (char *)olsr);
+  
+  if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
+    return;
+  
+  if (ntohs(olsr->olsr_packlen) != size) {
+    struct ipaddr_str buf;
+    OLSR_PRINTF(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
+    
+    olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
+    olsr_ip_to_string(&buf, from_addr));
+    return;
+  }
+  
+  // translate sequence number to host order
+  olsr->olsr_seqno = ntohs(olsr->olsr_seqno);
+  
+  // call packetparser
+  packetparser = packetparser_functions;
+  while (packetparser) {
+    packetparser->function(olsr, in_if, from_addr);
+    packetparser = packetparser->next;
+  }
+  
+  //printf("Message from %s\n\n", olsr_ip_to_string(&buf, from_addr)); 
+
+  /* Display packet */
+  if (disp_pack_in)
+    print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
+  
+  if (olsr_cnf->ip_version == AF_INET)
+    msgsize = ntohs(m->v4.olsr_msgsize);
+  else
+    msgsize = ntohs(m->v6.olsr_msgsize);
+  
+  /*
+   * Hysteresis update - for every OLSR package
+   */
+  if (olsr_cnf->use_hysteresis) {
+    if (olsr_cnf->ip_version == AF_INET) {
+      /* IPv4 */
+      update_hysteresis_incoming(from_addr, in_if, ntohs(olsr->olsr_seqno));
+    } else {
+      /* IPv6 */
+      update_hysteresis_incoming(from_addr, in_if, ntohs(olsr->olsr_seqno));
+    }
+  }
+  
+  for (; count > 0; m = (union olsr_message *)((char *)m + (msgsize))) {
+    
+    processed = 0;
+    if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
+      break;
+    
+    if (olsr_cnf->ip_version == AF_INET)
+      msgsize = ntohs(m->v4.olsr_msgsize);
+    else
+      msgsize = ntohs(m->v6.olsr_msgsize);
+    
+    count -= msgsize;
+    
+    /* Check size of message */
+    if (count < 0) {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "packet length error in  packet received from %s!",
+          olsr_ip_to_string(&buf, from_addr));
+      
+      olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
+      olsr_ip_to_string(&buf, from_addr));
+      break;
+    }
+    
+#if 0
+    /*
+     * Sven-Ola: This code leads to flooding our meshes with invalid /
+     * overdue messages if lq_fish is enabled (which is true since 2005)
+     * because there was no "do not forward"-check in olsr.c. If a message
+     * (yes: ttl=0 is invalid) is received, we should say: Welcome message,
+     * let us evaluate! But: if TTL < 2 or TTL + hopcount is higher than
+     * plausible, we should not forward. See olsr.c:olsr_forward_message()
+     */
+
+    /* Treat TTL hopcnt */
+    if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IPv4 */
+      if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)
+      {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n",
+            m->v4.olsr_msgtype,
+            olsr_ip_to_string(&buf, from_addr));
+        continue;
+      }
+    }
+    else
+    {
+      /* IPv6 */
+      if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0)
+      {
+        struct ipaddr_str buf;
+        OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n",
+            m->v4.olsr_msgtype,
+            olsr_ip_to_string(&buf, from_addr));
+        continue;
+      }
+    }
+#endif
+    
+    /*RFC 3626 section 3.4:
+     *  2    If the time to live of the message is less than or equal to
+     *  '0' (zero), or if the message was sent by the receiving node
+     *  (i.e., the Originator Address of the message is the main
+     *  address of the receiving node): the message MUST silently be
+     *  dropped.
+     */
+
+    /* Should be the same for IPv4 and IPv6 */
+    if (ipequal((union olsr_ip_addr *)&m->v4.originator, &olsr_cnf->main_addr)
+        || !olsr_validate_address((union olsr_ip_addr *)&m->v4.originator)) {
+#ifdef DEBUG
+      struct ipaddr_str buf;
+#endif
+#ifdef DEBUG
+      OLSR_PRINTF(3, "Not processing message originating from %s!\n",
+          olsr_ip_to_string(&buf,(union olsr_ip_addr *)&m->v4.originator));
+#endif
+      continue;
+    }
+    
+    /* check for message duplicates */
+    if (olsr_cnf->ip_version == AF_INET) {
+      /* IPv4 */
+      if (olsr_shall_process_message(&m->v4.originator, ntohs(m->v4.seqno)) == 0) {
+        continue;
+      }
+    } else {
+      /* IPv6 */
+      if (olsr_shall_process_message(&m->v6.originator, ntohs(m->v6.seqno)) == 0) {
+        continue;
+      }
+    }
+    
+    //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
+
+    entry = parse_functions;
+    
+    while (entry) {
+      /* Should be the same for IPv4 and IPv6 */
+
+      /* Promiscuous or exact match */
+      if ((entry->type == PROMISCUOUS) || (entry->type == m->v4.olsr_msgtype)) {
+        entry->function(m, in_if, from_addr);
+        if (entry->caller_forwarding)
+          processed = 1;
+      }
+      entry = entry->next;
+    }
+    
+    /* UNKNOWN PACKETTYPE */
+    if (processed == 0) {
+      struct ipaddr_str buf;
+      unk_chgestruct(&unkpacket, m);
+      
+      OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",
+          m->v4.olsr_msgtype,
+          size,
+          olsr_ip_to_string(&buf, &unkpacket.originator));
+      
+      /* Forward message */
+      if (!ipequal(&unkpacket.originator, &olsr_cnf->main_addr)) {
+        /* Forward */
+        olsr_forward_message(m, from_addr);
+      }
+      
+      /* Cancel loop here, otherwise olsrd just hangs forever at this point */
+      break;
+    }
+    
+  } /* for olsr_msg */
+}
+
+/**
+ *Processing OLSR data from socket. Reading data, setting 
+ *wich interface recieved the message, Sends IPC(if used) 
+ *and passes the packet on to parse_packet().
+ *
+ *@param fd the filedescriptor that data should be read from.
+ *@return nada
+ */
+void olsr_input(int fd) {
+  struct interface *olsr_in_if;
+  union olsr_ip_addr from_addr;
+  struct preprocessor_function_entry *entry;
+  char *packet;
+  
+  cpu_overload_exit = 0;
+  
+  for (;;) {
+#ifdef DEBUG
+    struct ipaddr_str buf;
+#endif
+    /* sockaddr_in6 is bigger than sockaddr !!!! */
+    struct sockaddr_storage from;
+    socklen_t fromlen;
+    int cc;
+    
+    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, inbuf, sizeof (inbuf), 0, (struct sockaddr *)&from, &fromlen);
+    
+    if (cc <= 0) {
+      if (cc < 0 && errno != EWOULDBLOCK) {
+        OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno));
+        olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
+      }
+      break;
+    }
+    if (olsr_cnf->ip_version == AF_INET) {
+      /* IPv4 sender address */
+      from_addr.v4 = ((struct sockaddr_in *)&from)->sin_addr;
+    } else {
+      /* IPv6 sender address */
+      from_addr.v6 = ((struct sockaddr_in6 *)&from)->sin6_addr;
+    }
+    
+#ifdef DEBUG
+    OLSR_PRINTF(5, "Recieved a packet from %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
+#endif
+    
+    if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof(struct sockaddr_in)))
+      break;
+    else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof(struct sockaddr_in6)))
+      break;
+    
+    /* are we talking to ourselves? */
+    if (if_ifwithaddr(&from_addr) != NULL)
+      return;
+    
+    if ((olsr_in_if = if_ifwithsock(fd)) == NULL) {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
+          olsr_ip_to_string(&buf, &from_addr),
+          cc);
+      olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
+      olsr_ip_to_string(&buf, &from_addr),
+      cc);
+      return;
+    }
+    
+    // call preprocessors
+    entry = preprocessor_functions;
+    packet = &inbuf[0];
+    
+    while (entry) {
+      packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
+      // discard package ?
+      if (packet == NULL) {
+        return;
+      }
+      entry = entry->next;
+    }
+    
+    /*
+     * &from - sender
+     * &inbuf.olsr 
+     * cc - bytes read
+     */
+    parse_packet((struct olsr *)packet, cc, olsr_in_if, &from_addr);
+    
+  }
+}
+
+/**
+ *Processing OLSR data from socket. Reading data, setting 
+ *wich interface recieved the message, Sends IPC(if used) 
+ *and passes the packet on to parse_packet().
+ *
+ *@param fd the filedescriptor that data should be read from.
+ *@return nada
+ */
+void olsr_input_hostemu(int fd) {
+  /* sockaddr_in6 is bigger than sockaddr !!!! */
+  struct sockaddr_storage from;
+  socklen_t fromlen;
+  struct interface *olsr_in_if;
+  union olsr_ip_addr from_addr;
+  olsr_u16_t pcklen;
+  struct preprocessor_function_entry *entry;
+  char *packet;
+  
+  /* Host emulator receives IP address first to emulate
+   direct link */
+
+  int cc = recv(fd, from_addr.v6.s6_addr, olsr_cnf->ipsize, 0);
+  if (cc != (int)olsr_cnf->ipsize) {
+    fprintf(stderr, "Error receiving host-client IP hook(%d) %s!\n", cc, strerror(errno));
+    memcpy(&from_addr, &((struct olsr *)inbuf)->olsr_msg->originator, olsr_cnf->ipsize);
+  }
+  
+  /* are we talking to ourselves? */
+  if (if_ifwithaddr(&from_addr) != NULL)
+    return;
+  
+  /* Extract size */
+  if ((cc = recv(fd, (void *)&pcklen, 2, MSG_PEEK)) != 2) /* Win needs a cast */
+  {
+    if (cc <= 0) {
+      fprintf(stderr, "Lost olsr_switch connection - exit!\n");
+      olsr_exit(__func__, EXIT_FAILURE);
+    }
+    fprintf(stderr, "[hust-emu] error extracting size(%d) %s!\n", cc, strerror(errno));
+    return;
+  } else {
+    pcklen = ntohs(pcklen);
+  }
+  
+  fromlen = sizeof(struct sockaddr_storage);
+  
+  cc = olsr_recvfrom(fd, inbuf, pcklen, 0, (struct sockaddr *)&from, &fromlen);
+  
+  if (cc <= 0) {
+    if (cc < 0 && errno != EWOULDBLOCK) {
+      const char * const err_msg = strerror(errno);
+      OLSR_PRINTF(1, "error recvfrom: %s", err_msg);
+      olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %s", err_msg);
+    }
+    return;
+  }
+  
+  if (cc != pcklen) {
+    printf("Could not read whole packet(size %d, read %d)\n", pcklen, cc);
+    return;
+  }
+  
+  if ((olsr_in_if = if_ifwithsock(fd)) == NULL) {
+    struct ipaddr_str buf;
+    OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
+        olsr_ip_to_string(&buf, &from_addr),
+        cc);
+    olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
+    olsr_ip_to_string(&buf, &from_addr),
+    cc);
+    return;
+  }
+  
+  // call preprocessors
+  entry = preprocessor_functions;
+  packet = &inbuf[0];
+  
+  while (entry) {
+    packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
+    // discard package ?
+    if (packet == NULL) {
+      return;
+    }
+    entry = entry->next;
+  }
+  
+  /*
+   * &from - sender
+   * &inbuf.olsr 
+   * cc - bytes read
+   */
+  parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
+  
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/parser.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/parser.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/parser.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/parser.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,109 @@
+/*
+ * 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 _OLSR_MSG_PARSER
+#define _OLSR_MSG_PARSER
+
+#include "olsr_protocol.h"
+#include "packet.h"
+
+#define PROMISCUOUS 0xffffffff
+
+typedef void parse_function(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+struct parse_function_entry
+{
+  olsr_u32_t type;       /* If set to PROMISCUOUS all messages will be received */
+  int caller_forwarding; /* If set to 0 this entry is not registered as forwarding packets */
+  parse_function *function;
+  struct parse_function_entry *next;
+};
+
+typedef char *preprocessor_function(char *packet, struct interface *, union olsr_ip_addr *, int *length);
+
+struct preprocessor_function_entry
+{
+  preprocessor_function *function;
+  struct preprocessor_function_entry *next;
+};
+
+typedef void packetparser_function(struct olsr *olsr, struct interface *in_if, union olsr_ip_addr *from_addr);
+
+struct packetparser_function_entry
+{
+  packetparser_function *function;
+  struct packetparser_function_entry *next;
+};
+
+void
+parser_set_disp_pack_in(olsr_bool);
+
+void
+olsr_init_parser(void);
+
+void 
+olsr_input(int);
+
+void
+olsr_input_hostemu(int);
+
+void
+olsr_parser_add_function(parse_function, olsr_u32_t, int);
+
+int
+olsr_parser_remove_function(parse_function, olsr_u32_t, int);
+
+void
+olsr_preprocessor_add_function(preprocessor_function);
+
+int
+olsr_preprocessor_remove_function(preprocessor_function);
+
+void
+olsr_packetparser_add_function(packetparser_function *function);
+
+int
+olsr_packetparser_remove_function(packetparser_function *function);
+
+void
+parse_packet(struct olsr *, int, struct interface *, union olsr_ip_addr *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_loader.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_loader.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_loader.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_loader.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,316 @@
+/*
+ * 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 "plugin_loader.h"
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+#include "defs.h"
+#include "olsr.h"
+
+#include <dlfcn.h>
+
+/* Local functions */
+static int init_olsr_plugin(struct olsr_plugin *);
+static int olsr_load_dl(char *, struct plugin_param *);
+static int olsr_add_dl(struct olsr_plugin *);
+
+static struct olsr_plugin *olsr_plugins = NULL;
+
+
+/**
+ *Function that loads all registered plugins
+ *
+ *@return the number of plugins loaded
+ */
+void olsr_load_plugins(void)
+{
+    struct plugin_entry *entry = olsr_cnf->plugins;
+    int rv = 0;
+    for (entry = olsr_cnf->plugins; entry != NULL; entry = entry->next) {
+        if(olsr_load_dl(entry->name, entry->params) < 0) {
+            rv = 1;
+        }
+    }
+    if (rv != 0) {
+        OLSR_PRINTF(0, "-- PLUGIN LOADING FAILED! --\n");
+        exit(1);
+    }
+    OLSR_PRINTF(0, "-- ALL PLUGINS LOADED! --\n\n");
+}
+
+/**
+ *Try to load a shared library and extract
+ *the required information
+ *
+ *@param libname the name of the library(file)
+ *
+ *@return negative on error
+ */
+static int olsr_load_dl(char *libname, struct plugin_param *params)
+{
+    struct olsr_plugin *plugin = olsr_malloc(sizeof(struct olsr_plugin), "Plugin entry");
+    int rv;
+
+    OLSR_PRINTF(0, "---------- LOADING LIBRARY %s ----------\n", libname);
+
+    plugin->dlhandle = dlopen(libname, RTLD_NOW);
+    if(plugin->dlhandle == NULL) {
+        const int save_errno = errno;
+        OLSR_PRINTF(0, "DL loading failed: \"%s\"!\n", dlerror());
+        free(plugin);
+        errno = save_errno;
+        return -1;
+    }
+
+    rv = olsr_add_dl(plugin);
+    if (rv == -1) {
+        const int save_errno = errno;
+        dlclose(plugin->dlhandle);
+        free(plugin);
+        errno = save_errno;
+    } else {
+        plugin->params = params;
+
+        /* Initialize the plugin */
+        if (init_olsr_plugin(plugin) != 0) {
+            rv = -1;
+        }
+
+        /* queue */
+        plugin->next = olsr_plugins;
+        olsr_plugins = plugin;
+    }
+    OLSR_PRINTF(0, "---------- LIBRARY %s %s ----------\n\n", libname, rv == 0 ? "LOADED" : "FAILED");
+    return rv;
+}
+
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+static int try_old_versions(const struct olsr_plugin *plugin)
+{
+    get_interface_version_func get_interface_version;
+    int *interface_version;
+
+    OLSR_PRINTF(1, "trying v2 detection... ");
+    get_interface_version = dlsym(plugin->dlhandle, "get_plugin_interface_version");
+    if (get_interface_version != NULL) {
+        return get_interface_version();
+    }
+
+    OLSR_PRINTF(1, "trying v1 detection... ");
+    interface_version = dlsym(plugin->dlhandle, "plugin_interface_version");
+    if (interface_version != NULL) {
+        return *interface_version;
+    }
+    OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
+    return -1;
+}
+#else 
+#define try_old_versions(plugin) -1
+#endif
+
+static int olsr_add_dl(struct olsr_plugin *plugin)
+{
+    get_interface_version_func get_interface_version;
+    get_plugin_parameters_func get_plugin_parameters;
+    int plugin_interface_version;
+
+    /* Fetch the interface version function, 3 different ways */
+    OLSR_PRINTF(0, "Checking plugin interface version: ");
+    get_interface_version = dlsym(plugin->dlhandle, "olsrd_plugin_interface_version");
+    if (get_interface_version == NULL) {
+        plugin_interface_version = try_old_versions(plugin);
+    } else {
+        plugin_interface_version = get_interface_version();
+    }
+    if (plugin_interface_version == -1) {
+        OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
+        return -1;
+    }
+    OLSR_PRINTF(0, " %d - OK\n", plugin_interface_version);
+  
+    if (plugin_interface_version < 5){
+        /* old plugin interface */   
+        OLSR_PRINTF(0, "\nWARNING: YOU ARE USING AN OLD DEPRECATED PLUGIN INTERFACE!\n"
+                    "DETECTED VERSION %d AND THE CURRENT VERSION IS %d\n"
+                    "PLEASE UPGRADE YOUR PLUGIN!\n", plugin_interface_version, MOST_RECENT_PLUGIN_INTERFACE_VERSION);
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+        OLSR_PRINTF(0, "WILL CONTINUE IN 5 SECONDS...\n\n");      
+        sleep(5);
+#else
+        return -1;
+#endif
+    }
+
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+    /* new plugin interface */      
+    if (plugin_interface_version < LAST_SUPPORTED_PLUGIN_INTERFACE_VERSION) {
+        OLSR_PRINTF(0, "\n\nWARNING: VERSION MISMATCH!\n"
+                    "DETECTED %d AND LAST SUPPORTED VERSION IS %d\n"
+                    "THIS CAN CAUSE UNEXPECTED BEHAVIOUR AND CRASHES!\n"
+                    "WILL CONTINUE IN 5 SECONDS...\n\n", get_interface_version(), LAST_SUPPORTED_PLUGIN_INTERFACE_VERSION);
+        sleep(5);
+    }
+#endif
+   
+    /* Fetch the init function */
+    OLSR_PRINTF(1, "Trying to fetch plugin init function: ");
+    plugin->plugin_init = dlsym(plugin->dlhandle, "olsrd_plugin_init");
+    if (plugin->plugin_init == NULL) {
+        OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
+        return -1;
+    }
+    OLSR_PRINTF(1, "OK\n");
+
+    OLSR_PRINTF(1, "Trying to fetch parameter table and it's size... \n");
+
+    get_plugin_parameters = dlsym(plugin->dlhandle, "olsrd_get_plugin_parameters");
+    if (get_plugin_parameters != NULL) {
+        (*get_plugin_parameters)(&plugin->plugin_parameters, &plugin->plugin_parameters_size);
+    } else {
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+        /* Fetch the parameter function */
+        OLSR_PRINTF(1, "Trying to fetch param function: ");
+
+        plugin->register_param = dlsym(plugin->dlhandle, "olsrd_plugin_register_param");
+        if(plugin->register_param == NULL) {
+            OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
+            return -1;
+        } else {
+            OLSR_PRINTF(1, "OK\n");
+        }
+
+        plugin->plugin_parameters      = NULL;
+        plugin->plugin_parameters_size = 0;
+#else
+        OLSR_PRINTF(0, "Old plugin interfaces are not supported\n");
+        return -1;
+#endif
+    }
+    return 0;
+}
+
+
+/**
+ *Initialize a loaded plugin
+ *This includes sending information
+ *from olsrd to the plugin and
+ *register the functions from the plugin with olsrd
+ *
+ *@param entry the plugin to initialize
+ *
+ *@return -1 if there was an error
+ */
+static int init_olsr_plugin(struct olsr_plugin *entry)
+{
+    int rv = 0;
+    struct plugin_param *params;
+    OLSR_PRINTF(1, "Sending parameters...\n");
+    for(params = entry->params; params != NULL; params = params->next) {
+        OLSR_PRINTF(1, "\"%s\"/\"%s\"... ", params->key, params->value);
+        if (entry->plugin_parameters_size != 0) {
+            unsigned int i;
+            int rc = 0;
+            for (i = 0; i < entry->plugin_parameters_size; i++) {
+                if (0 == entry->plugin_parameters[i].name[0] ||
+                    0 == strcasecmp(entry->plugin_parameters[i].name, params->key))
+                {
+                    /* we have found it! */
+                    rc = entry->plugin_parameters[i].set_plugin_parameter(params->value, entry->plugin_parameters[i].data,
+                        0 == entry->plugin_parameters[i].name[0] ? (set_plugin_parameter_addon)params->key : entry->plugin_parameters[i].addon);
+                    if (rc != 0) {
+                        fprintf(stderr, "\nFatal error in plugin parameter \"%s\"/\"%s\"\n", params->key, params->value);
+                        rv = -1;
+                    }
+                    break;
+                }
+            }
+            if (i >= entry->plugin_parameters_size) {
+                OLSR_PRINTF(0, "Ignored parameter \"%s\"\n", params->key);
+            } else {
+                OLSR_PRINTF(1, "%s: %s\n", params->key, rc == 0 ? "OK" : "FAILED");
+                if (rc != 0) {
+                    rv = -1;
+                }
+            }
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+        } else if(entry->register_param != NULL) {
+            int rc;
+            OLSR_PRINTF(0, "Registering parameter \"%s\": ", params->key);
+            rc = entry->register_param(params->key, params->value);
+            if(rc < 0) {
+                fprintf(stderr, "\nFatal error in plugin parameter \"%s\"/\"%s\"\n", params->key, params->value);
+                exit(EXIT_FAILURE);
+            }
+            OLSR_PRINTF(0, "%s\n", rc == 0 ? "FAILED" : "OK");
+#endif
+        } else {
+            OLSR_PRINTF(0, "I don't know what to do with \"%s\"!\n", params->key);
+            rv = -1;
+        }
+    }
+
+    OLSR_PRINTF(1, "Running plugin_init function...\n");
+    entry->plugin_init();
+    return rv;
+}
+
+
+/**
+ *Close all loaded plugins
+ */
+void olsr_close_plugins(void)
+{
+    struct olsr_plugin *entry;
+
+    OLSR_PRINTF(0, "Closing plugins...\n");
+    for(entry = olsr_plugins; entry != NULL; entry = entry->next) {
+        dlclose(entry->dlhandle);
+        entry->dlhandle = NULL;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_loader.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_loader.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_loader.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_loader.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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 _OLSR_PLUGIN_LOADER
+#define _OLSR_PLUGIN_LOADER
+
+#include "olsrd_plugin.h"
+#include "olsr_types.h"
+#include "olsr_cfg.h"
+
+#ifndef OLSR_PLUGIN
+
+/* all */
+typedef int (*plugin_init_func)(void);
+typedef int (*get_interface_version_func)(void);
+
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+/* version 4 */
+typedef int (*register_param_func)(char *, char *);
+#endif
+
+/* version 5 */
+typedef void (*get_plugin_parameters_func)(const struct olsrd_plugin_parameters **params, unsigned int *size);
+
+
+struct olsr_plugin {
+    /* The handle */
+    void *dlhandle;
+  
+    struct plugin_param *params;
+    int plugin_interface_version;
+  
+#if SUPPORT_OLD_PLUGIN_VERSIONS
+    /* version 4 */
+    register_param_func register_param;
+#endif
+    plugin_init_func plugin_init;
+
+    /* version 5 */
+    const struct olsrd_plugin_parameters *plugin_parameters;
+    unsigned int plugin_parameters_size;
+  
+    struct olsr_plugin *next;
+};
+
+void olsr_load_plugins(void);
+
+void olsr_close_plugins(void);
+
+int olsr_plugin_io(int, void *, size_t);
+
+#endif
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_util.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_util.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_util.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_util.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,144 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2007, Bernd Petrovitsch <bernd@firmix.at>
+ * Copyright (c) 2007, Sven-Ola <sven-ola@gmx.de>
+ * 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 "plugin_util.h"
+#include "olsr.h"
+#include "defs.h"
+
+#include <arpa/inet.h>
+
+int set_plugin_port(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    char *endptr;
+    const unsigned int port = strtoul(value, &endptr, 0);
+    if (*endptr != '\0' || endptr == value) {
+        OLSR_PRINTF(0, "Illegal port number \"%s\"", value);
+        return 1;
+    }
+    if (port > 65535) {
+        OLSR_PRINTF(0, "Port number %u out of range", port);
+        return 1;
+    }
+    if (data != NULL) {
+        int *v = data;
+        *v = port;
+        OLSR_PRINTF(1, "%s port number %u\n", "Got", port);
+    } else {
+        OLSR_PRINTF(0, "%s port number %u\n", "Ignored", port);
+    }
+    return 0;
+}
+
+int set_plugin_ipaddress(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    char buf[INET6_ADDRSTRLEN];
+    union olsr_ip_addr ip_addr;
+    if (inet_pton(olsr_cnf->ip_version, value, &ip_addr) <= 0) {
+        OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
+        return 1;
+    }
+    inet_ntop(olsr_cnf->ip_version, &ip_addr, buf, sizeof(buf));
+    if (data != NULL) {
+        union olsr_ip_addr *v = data;
+        *v = ip_addr;
+        OLSR_PRINTF(1, "%s IP address %s\n", "Got", buf);
+    } else {
+        OLSR_PRINTF(0, "%s IP address %s\n", "Ignored", buf);
+    }
+    return 0;
+}
+
+
+int set_plugin_boolean(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    int *v = data;
+    if (strcasecmp (value, "yes") == 0 || strcasecmp (value, "true") == 0) {
+        *v = 1;
+    } else if (strcasecmp (value, "no") == 0 || strcasecmp (value, "false") == 0) {
+        *v = 0;
+    } else {
+        return 1;
+    }
+    return 0;
+}
+
+int set_plugin_int(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
+{
+    char *endptr;
+    const int theint = strtol(value, &endptr, 0);
+    if (*endptr != '\0' || endptr == value) {
+        OLSR_PRINTF(0, "Illegal int \"%s\"", value);
+        return 1;
+    }
+    if (data != NULL) {
+        int *v = data;
+        *v = theint;
+        OLSR_PRINTF(1, "%s int %d\n", "Got", theint);
+    } else {
+        OLSR_PRINTF(0, "%s int %d\n", "Ignored", theint);
+    }
+    return 0;
+}
+
+int set_plugin_string(const char *value, void *data, set_plugin_parameter_addon addon)
+{
+    if (data != NULL) {
+        char *v = data;
+        if ((unsigned)strlen(value) >= addon.ui) {
+            OLSR_PRINTF(0, "String too long \"%s\"", value);
+            return 1;
+        }
+        strscpy(v, value, addon.ui);
+        OLSR_PRINTF(1, "%s string %s\n", "Got", value);
+    } else {
+        OLSR_PRINTF(0, "%s string %s\n", "Ignored", value);
+    }
+    return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_util.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_util.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/plugin_util.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/plugin_util.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, Bernd Petrovitsch <bernd@firmix.at>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, 
+ *   this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, 
+ *   this list of conditions and the following disclaimer in the documentation 
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the UniK olsr daemon 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.
+ *
+ */
+
+
+/*
+ * Example plugin for olsrd.org OLSR daemon
+ * Only the bare minimum
+ */
+
+#ifndef _OLSRD_PLUGIN_UTIL
+#define _OLSRD_PLUGIN_UTIL
+
+#include "olsrd_plugin.h"
+
+/* Common/utility functions for plugins */
+set_plugin_parameter set_plugin_port;
+set_plugin_parameter set_plugin_ipaddress;
+set_plugin_parameter set_plugin_boolean;
+set_plugin_parameter set_plugin_int;
+set_plugin_parameter set_plugin_string;
+
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/print_packet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/print_packet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/print_packet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/print_packet.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,409 @@
+/*
+ * 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 "print_packet.h"
+#include "ipcalc.h"
+#include "mantissa.h"
+#include "defs.h"
+#include "olsr.h"
+#include "lq_packet.h"
+#include "net_olsr.h"
+
+
+static void
+print_messagedump(FILE *, olsr_u8_t *, olsr_16_t);
+
+static void
+print_midmsg(FILE *, olsr_u8_t *, olsr_16_t);
+
+static void
+print_hnamsg(FILE *, olsr_u8_t *, olsr_16_t);
+
+static void
+print_olsr_tcmsg(FILE *, olsr_u8_t *, olsr_16_t);
+
+static void
+print_olsr_tcmsg_lq(FILE *, olsr_u8_t *, olsr_16_t);
+
+static void
+print_hellomsg(FILE *, olsr_u8_t *, olsr_16_t);
+
+static void
+print_hellomsg_lq(FILE *, olsr_u8_t *, olsr_16_t);
+
+/* Entire packet */
+olsr_8_t
+print_olsr_serialized_packet(FILE *handle, union olsr_packet *pkt, 
+			     olsr_u16_t size, union olsr_ip_addr *from_addr)
+{
+  olsr_16_t remainsize = size - OLSR_HEADERSIZE;
+  union olsr_message *msg;
+  struct ipaddr_str buf;
+
+  /* Print packet header (no IP4/6 difference) */
+  fprintf(handle, "  ============== OLSR PACKET ==============\n   source: %s\n   length: %d bytes\n   seqno: %d\n\n",
+	  from_addr ? olsr_ip_to_string(&buf, from_addr) : "UNKNOWN",
+	  ntohs(pkt->v4.olsr_packlen), ntohs(pkt->v4.olsr_seqno));
+
+  /* Check size */
+  if(size != ntohs(pkt->v4.olsr_packlen))
+    fprintf(handle, "   SIZE MISSMATCH(%d != %d)!\n", size, ntohs(pkt->v4.olsr_packlen));
+
+  msg = (union olsr_message *)pkt->v4.olsr_msg;
+
+  /* Print all messages */
+  while((remainsize > 0) && ntohs(msg->v4.olsr_msgsize))
+    {
+      print_olsr_serialized_message(handle, msg);
+      remainsize -= ntohs(msg->v4.olsr_msgsize);
+      msg = (union olsr_message *)((char *)msg + ntohs(msg->v4.olsr_msgsize));
+    }
+
+  /* Done */
+  fprintf(handle, "  =========================================\n\n");
+  return 1;
+}
+
+/* Single message */
+olsr_8_t
+print_olsr_serialized_message(FILE *handle, union olsr_message *msg)
+{
+  struct ipaddr_str buf;
+
+  fprintf(handle, "   ------------ OLSR MESSAGE ------------\n");
+  fprintf(handle, "    Sender main addr: %s\n", 
+	  olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->v4.originator));
+  fprintf(handle, "    Type: %s, size: %d, vtime: %u ms\n", 
+	  olsr_msgtype_to_string(msg->v4.olsr_msgtype), 
+	  ntohs(msg->v4.olsr_msgsize),
+	  me_to_reltime(msg->v4.olsr_vtime));
+  fprintf(handle, "    TTL: %d, Hopcnt: %d, seqno: %d\n",
+	  (olsr_cnf->ip_version == AF_INET) ? msg->v4.ttl : msg->v6.ttl,
+	  (olsr_cnf->ip_version == AF_INET) ? msg->v4.hopcnt : msg->v6.hopcnt,
+	  ntohs((olsr_cnf->ip_version == AF_INET) ? msg->v4.seqno : msg->v6.seqno));
+
+  switch(msg->v4.olsr_msgtype)
+    {
+      /* Print functions for individual messagetypes */
+    case(MID_MESSAGE):
+      print_midmsg(handle,
+		   (olsr_cnf->ip_version == AF_INET) ? 
+		   (olsr_u8_t *)&msg->v4.message : (olsr_u8_t *)&msg->v6.message,
+		   ntohs(msg->v4.olsr_msgsize));
+      break;
+    case(HNA_MESSAGE):
+      print_hnamsg(handle,
+		   (olsr_cnf->ip_version == AF_INET) ? 
+		   (olsr_u8_t *)&msg->v4.message : (olsr_u8_t *)&msg->v6.message,
+		   ntohs(msg->v4.olsr_msgsize));
+      break;
+    case(TC_MESSAGE):
+      print_olsr_tcmsg(handle,
+		  (olsr_cnf->ip_version == AF_INET) ? 
+		  (olsr_u8_t *)&msg->v4.message : (olsr_u8_t *)&msg->v6.message,
+		  ntohs(msg->v4.olsr_msgsize));
+      break;
+    case(LQ_TC_MESSAGE):
+      print_olsr_tcmsg_lq(handle,
+		     (olsr_cnf->ip_version == AF_INET) ? 
+		     (olsr_u8_t *)&msg->v4.message : (olsr_u8_t *)&msg->v6.message,
+		     ntohs(msg->v4.olsr_msgsize));
+      break;
+    case(HELLO_MESSAGE):
+      print_hellomsg(handle,
+		     (olsr_cnf->ip_version == AF_INET) ? 
+		     (olsr_u8_t *)&msg->v4.message : (olsr_u8_t *)&msg->v6.message,
+		     ntohs(msg->v4.olsr_msgsize));
+      break;
+    case(LQ_HELLO_MESSAGE):
+      print_hellomsg_lq(handle,
+			(olsr_cnf->ip_version == AF_INET) ? 
+			(olsr_u8_t *)&msg->v4.message : (olsr_u8_t *)&msg->v6.message,
+		     ntohs(msg->v4.olsr_msgsize));
+      break;
+    default:
+      print_messagedump(handle, (olsr_u8_t *)msg, ntohs(msg->v4.olsr_msgsize));
+    }
+
+  fprintf(handle, "   --------------------------------------\n\n");
+  return 1;
+}
+
+
+static void
+print_messagedump(FILE *handle, olsr_u8_t *msg, olsr_16_t size)
+{
+  int i, x = 0;
+
+  fprintf(handle, "     Data dump:\n     ");
+  for(i = 0; i < size; i++)
+    {
+      if(x == 4)
+	{
+	  x = 0;
+	  fprintf(handle, "\n     ");
+	}
+      x++;
+      if(olsr_cnf->ip_version == AF_INET)
+	fprintf(handle, " %-3i ", (u_char) msg[i]);
+      else
+	fprintf(handle, " %-2x ", (u_char) msg[i]);
+    }
+  fprintf(handle, "\n");
+}
+
+
+static void
+print_hellomsg(FILE *handle, olsr_u8_t *data, olsr_16_t totsize)
+{
+  union olsr_ip_addr *haddr;
+  int hellosize = totsize - ((olsr_cnf->ip_version == AF_INET) ? OLSR_MSGHDRSZ_IPV4 : OLSR_MSGHDRSZ_IPV6);
+
+  fprintf(handle, "    +Htime: %u ms\n", me_to_reltime(data[2]));
+
+  fprintf(handle, "    +Willingness: %d\n", data[3]);
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IPv4 */
+      struct hellomsg *h;
+      struct hellinfo *hinf;
+
+      h = (struct hellomsg *)data;
+
+      for (hinf = h->hell_info; 
+	   (char *)hinf < ((char *)data + hellosize); 
+	   hinf = (struct hellinfo *)((char *)hinf + ntohs(hinf->size)))
+	{
+
+	  fprintf(handle, "    ++ Link: %s, Status: %s, Size: %d\n", 
+		  olsr_link_to_string(EXTRACT_LINK(hinf->link_code)), 
+		  olsr_status_to_string(EXTRACT_STATUS(hinf->link_code)),
+		  ntohs(hinf->size));
+
+	  for (haddr = (union olsr_ip_addr  *)&hinf->neigh_addr; 
+	       (char *)haddr < (char *)hinf + ntohs(hinf->size); 
+	       haddr = (union olsr_ip_addr *)&haddr->v6.s6_addr[4])
+	    {
+              struct ipaddr_str buf;
+	      fprintf(handle, "    ++ %s\n", olsr_ip_to_string(&buf, haddr));
+	    }
+	}
+
+      
+    }
+  else
+    {
+      /* IPv6 */
+      struct hellomsg6 *h6;
+      struct hellinfo6 *hinf6;
+
+      h6 = (struct hellomsg6 *)data;
+
+      for (hinf6 = h6->hell_info; (char *)hinf6 < ((char *)data + (hellosize)); 
+	   hinf6 = (struct hellinfo6 *)((char *)hinf6 + ntohs(hinf6->size)))
+	{
+	  fprintf(handle, "    ++ Link: %s, Status: %s, Size: %d\n", 
+		  olsr_link_to_string(EXTRACT_LINK(hinf6->link_code)), 
+		  olsr_status_to_string(EXTRACT_STATUS(hinf6->link_code)),
+		  ntohs(hinf6->size));
+
+	  for (haddr = (union olsr_ip_addr *)hinf6->neigh_addr; 
+	       (char *)haddr < (char *)hinf6 + ntohs(hinf6->size); 
+	       haddr++)
+	    {
+              struct ipaddr_str buf;
+	      fprintf(handle, "    ++ %s\n", olsr_ip_to_string(&buf, haddr));
+	    }
+	}
+
+    }
+
+}
+
+static void
+print_hellomsg_lq(FILE *handle, olsr_u8_t *data, olsr_16_t totsize)
+{
+  union olsr_ip_addr *haddr;
+  int hellosize = totsize - ((olsr_cnf->ip_version == AF_INET) ? OLSR_MSGHDRSZ_IPV4 : OLSR_MSGHDRSZ_IPV6);
+
+  fprintf(handle, "    +Htime: %u ms\n", me_to_reltime(data[2]));
+
+  fprintf(handle, "    +Willingness: %d\n", data[3]);
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IPv4 */
+      struct hellomsg *h;
+      struct hellinfo *hinf;
+
+      h = (struct hellomsg *)data;
+
+      for (hinf = h->hell_info; 
+	   (char *)hinf < ((char *)data + hellosize); 
+	   hinf = (struct hellinfo *)((char *)hinf + ntohs(hinf->size)))
+	{
+
+	  fprintf(handle, "    ++ Link: %s, Status: %s, Size: %d\n", 
+		  olsr_link_to_string(EXTRACT_LINK(hinf->link_code)), 
+		  olsr_status_to_string(EXTRACT_STATUS(hinf->link_code)),
+		  ntohs(hinf->size));
+
+	  for (haddr = (union olsr_ip_addr  *)&hinf->neigh_addr; 
+	       (char *)haddr < (char *)hinf + ntohs(hinf->size); 
+	       haddr = (union olsr_ip_addr *)&haddr->v6.s6_addr[8])
+	    {
+              struct ipaddr_str buf;
+	      olsr_u8_t *quality = (olsr_u8_t *)haddr + olsr_cnf->ipsize;
+	      fprintf(handle, "    ++ %s\n", olsr_ip_to_string(&buf, haddr));
+	      fprintf(handle, "    ++ LQ = %d, RLQ = %d\n", quality[0], quality[1]);
+	    }
+	}
+
+      
+    }
+  else
+    {
+      /* IPv6 */
+      struct hellomsg6 *h6;
+      struct hellinfo6 *hinf6;
+
+      h6 = (struct hellomsg6 *)data;
+
+      for (hinf6 = h6->hell_info; (char *)hinf6 < ((char *)data + (hellosize)); 
+	   hinf6 = (struct hellinfo6 *)((char *)hinf6 + ntohs(hinf6->size)))
+	{
+	  fprintf(handle, "    ++ Link: %s, Status: %s, Size: %d\n", 
+		  olsr_link_to_string(EXTRACT_LINK(hinf6->link_code)), 
+		  olsr_status_to_string(EXTRACT_STATUS(hinf6->link_code)),
+		  ntohs(hinf6->size));
+
+	  for (haddr = (union olsr_ip_addr *)hinf6->neigh_addr; 
+	       (char *)haddr < (char *)hinf6 + ntohs(hinf6->size) + 4; 
+	       haddr++)
+	    {
+              struct ipaddr_str buf;
+	      olsr_u8_t *quality = (olsr_u8_t *)haddr + olsr_cnf->ipsize;
+	      fprintf(handle, "    ++ %s\n", olsr_ip_to_string(&buf, haddr));
+	      fprintf(handle, "    ++ LQ = %d, RLQ = %d\n", quality[0], quality[1]);
+	    }
+	}
+
+    }
+}
+
+static void
+print_olsr_tcmsg_lq(FILE *handle, olsr_u8_t *data, olsr_16_t totsize)
+{
+  int remsize = totsize - ((olsr_cnf->ip_version == AF_INET) ? OLSR_MSGHDRSZ_IPV4 : OLSR_MSGHDRSZ_IPV6);
+  
+  fprintf(handle, "    +ANSN: %d\n", htons(((struct olsr_tcmsg *)data)->ansn));
+
+  data += 4;
+  remsize -= 4;
+
+  while(remsize)
+    {
+      struct ipaddr_str buf;
+      fprintf(handle, "    +Neighbor: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *) data));
+      data += olsr_cnf->ipsize;
+      fprintf(handle, "    +LQ: %d, ", *data);
+      data += 1;
+      fprintf(handle, "RLQ: %d\n", *data);
+      data += 3;
+      remsize -= (olsr_cnf->ipsize + 4);
+    }
+
+}
+
+
+static void
+print_olsr_tcmsg(FILE *handle, olsr_u8_t *data, olsr_16_t totsize)
+{
+  int remsize = totsize - ((olsr_cnf->ip_version == AF_INET) ? OLSR_MSGHDRSZ_IPV4 : OLSR_MSGHDRSZ_IPV6);
+  
+  fprintf(handle, "    +ANSN: %d\n", htons(((struct olsr_tcmsg *)data)->ansn));
+
+  data += 4;
+  remsize -= 4;
+
+  while(remsize)
+    {
+      struct ipaddr_str buf;
+      fprintf(handle, "    +Neighbor: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *) data));
+      data += olsr_cnf->ipsize;
+
+      remsize -= olsr_cnf->ipsize;
+    }
+
+}
+
+
+static void
+print_hnamsg(FILE *handle, olsr_u8_t *data, olsr_16_t totsize)
+{
+  int remsize = totsize - ((olsr_cnf->ip_version == AF_INET) ? OLSR_MSGHDRSZ_IPV4 : OLSR_MSGHDRSZ_IPV6);
+
+  while(remsize)
+    {
+      struct ipaddr_str buf;
+      fprintf(handle, "    +Network: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *) data));
+      data += olsr_cnf->ipsize;
+      fprintf(handle, "    +Netmask: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *) data));
+      data += olsr_cnf->ipsize;
+
+      remsize -= (olsr_cnf->ipsize*2);
+    }
+
+}
+
+static void
+print_midmsg(FILE *handle, olsr_u8_t *data, olsr_16_t totsize)
+{
+  int remsize = totsize - ((olsr_cnf->ip_version == AF_INET) ? OLSR_MSGHDRSZ_IPV4 : OLSR_MSGHDRSZ_IPV6);
+
+  while(remsize)
+    {
+      struct ipaddr_str buf;
+      fprintf(handle, "    +Alias: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *) data));
+      data += olsr_cnf->ipsize;
+      remsize -= olsr_cnf->ipsize;
+    }
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/print_packet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/print_packet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/print_packet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/print_packet.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,54 @@
+/*
+ * 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 _PRINT_PACKET
+#define _PRINT_PACKET
+
+#include "olsr_types.h"
+#include "olsr_protocol.h"
+#include <stdio.h>
+
+olsr_8_t
+print_olsr_serialized_packet(FILE *, union olsr_packet *, olsr_u16_t, union olsr_ip_addr *);
+
+olsr_8_t
+print_olsr_serialized_message(FILE *, union olsr_message *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_package.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_package.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_package.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_package.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,703 @@
+/*
+ * 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 "process_package.h"
+#include "ipcalc.h"
+#include "defs.h"
+#include "lq_packet.h"
+#include "hysteresis.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "mpr_selector_set.h"
+#include "mid_set.h"
+#include "olsr.h"
+#include "parser.h"
+#include "duplicate_set.h"
+#include "rebuild_packet.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+
+#include <stddef.h>
+
+static void process_message_neighbors(struct neighbor_entry *,
+                                      const struct hello_message *);
+
+static void linking_this_2_entries(struct neighbor_entry *,
+                                   struct neighbor_2_entry *, olsr_reltime);
+
+static olsr_bool lookup_mpr_status(const struct hello_message *,
+                                   const struct interface *);
+
+
+/**
+ *Processes an list of neighbors from an incoming HELLO message.
+ *@param neighbor the neighbor who sent the message.
+ *@param message the HELLO message
+ *@return nada
+ */
+static void
+process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message)
+{
+  struct hello_neighbor        *message_neighbors;
+
+  for(message_neighbors = message->neighbors;
+      message_neighbors != NULL;
+      message_neighbors = message_neighbors->next)
+    {
+#ifdef DEBUG
+      struct ipaddr_str buf;
+#endif
+      union olsr_ip_addr      *neigh_addr;
+      struct neighbor_2_entry *two_hop_neighbor;
+
+      /*
+       *check all interfaces
+       *so that we don't add ourselves to the
+       *2 hop list
+       *IMPORTANT!
+       */
+      if(if_ifwithaddr(&message_neighbors->address) != NULL)
+        continue;
+
+      /* Get the main address */
+      neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
+
+      if (neigh_addr != NULL) {
+        message_neighbors->address = *neigh_addr;
+      }
+
+      if(((message_neighbors->status == SYM_NEIGH) ||
+          (message_neighbors->status == MPR_NEIGH)))
+        {
+	  struct neighbor_2_list_entry *two_hop_neighbor_yet =
+            olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
+#ifdef DEBUG
+          OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&buf, &message_neighbors->address));
+#endif
+          if (two_hop_neighbor_yet != NULL)
+            {
+              /* Updating the holding time for this neighbor */
+              olsr_set_timer(&two_hop_neighbor_yet->nbr2_list_timer,
+                             message->vtime, OLSR_NBR2_LIST_JITTER,
+                             OLSR_TIMER_ONESHOT, &olsr_expire_nbr2_list,
+                             two_hop_neighbor_yet, 0);
+              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_linkcost = LINK_COST_BROKEN;
+                        }
+                    }
+                }
+            }
+          else
+            {
+              two_hop_neighbor =
+                olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
+              if (two_hop_neighbor == NULL)
+                {
+#ifdef DEBUG
+                  OLSR_PRINTF(5, 
+			      "Adding 2 hop neighbor %s\n\n", 
+			      olsr_ip_to_string(&buf, &message_neighbors->address));
+#endif
+                  changes_neighborhood = OLSR_TRUE;
+                  changes_topology = OLSR_TRUE;
+
+                  two_hop_neighbor =
+                    olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO");
+		  
+                  two_hop_neighbor->neighbor_2_nblist.next =
+                    &two_hop_neighbor->neighbor_2_nblist;
+
+                  two_hop_neighbor->neighbor_2_nblist.prev =
+                    &two_hop_neighbor->neighbor_2_nblist;
+
+                  two_hop_neighbor->neighbor_2_pointer = 0;
+		  
+                  two_hop_neighbor->neighbor_2_addr = message_neighbors->address;
+
+                  olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
+
+                  linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
+                }
+              else
+                {
+                  /*
+                    linking to this two_hop_neighbor entry
+                  */	
+                  changes_neighborhood = OLSR_TRUE;
+                  changes_topology = OLSR_TRUE;
+		  
+                  linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime); 
+                }
+            }
+        }
+    }
+
+  /* Separate, second pass for link quality OLSR */
+  /* Separate, second and third pass for link quality OLSR */
+
+  if (olsr_cnf->lq_level > 0)
+    {
+	  olsr_linkcost first_hop_pathcost;
+      struct link_entry *lnk =
+        get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
+
+      if(!lnk)
+	return;
+
+      /* calculate first hop path quality */
+      first_hop_pathcost = lnk->linkcost;
+      /*
+       *  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 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)
+                    {
+                      olsr_linkcost new_second_hop_linkcost, new_path_linkcost;
+
+                      // the link cost between the 1-hop neighbour and the
+                      // 2-hop neighbour
+
+                      new_second_hop_linkcost = message_neighbors->cost;
+
+                      // the total cost for the route
+                      // "us --- 1-hop --- 2-hop"
+
+                      new_path_linkcost =
+                        first_hop_pathcost + new_second_hop_linkcost;
+
+                      // Only copy the link quality if it is better than what we have
+                      // for this 2-hop neighbor
+                      if (new_path_linkcost < walker->path_linkcost)
+                        {
+                          walker->second_hop_linkcost = new_second_hop_linkcost;
+                          walker->path_linkcost = new_path_linkcost;
+                          
+                          if (olsr_is_relevant_costchange(new_path_linkcost, walker->saved_path_linkcost))
+                            {
+                              walker->saved_path_linkcost = new_path_linkcost;
+
+                              if (olsr_cnf->lq_dlimit > 0)
+                              {
+                                changes_neighborhood = OLSR_TRUE;
+                                changes_topology = OLSR_TRUE;
+                              }
+
+                              else
+                                OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+/**
+ *Links a one-hop neighbor with a 2-hop neighbor.
+ *
+ *@param neighbor the 1-hop neighbor
+ *@param two_hop_neighbor the 2-hop neighbor
+ *@return nada
+ */
+static void
+linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry *two_hop_neighbor, olsr_reltime vtime)
+{
+  struct neighbor_list_entry    *list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
+  struct neighbor_2_list_entry  *list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
+
+  list_of_1_neighbors->neighbor = neighbor;
+
+  list_of_1_neighbors->path_linkcost = LINK_COST_BROKEN;
+  list_of_1_neighbors->saved_path_linkcost = LINK_COST_BROKEN;
+  list_of_1_neighbors->second_hop_linkcost = LINK_COST_BROKEN;
+
+  /* Queue */
+  two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
+  list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
+
+  two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
+  list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
+  list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
+  list_of_2_neighbors->nbr2_nbr = neighbor; /* XXX refcount */
+  
+  olsr_change_timer(list_of_2_neighbors->nbr2_list_timer, vtime,
+                    OLSR_NBR2_LIST_JITTER, OLSR_TIMER_ONESHOT);
+
+  /* Queue */
+  neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
+  list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
+  neighbor->neighbor_2_list.next = list_of_2_neighbors;
+  list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
+  
+  /*increment the pointer counter*/
+  two_hop_neighbor->neighbor_2_pointer++;
+}
+
+/**
+ * Check if a hello message states this node as a MPR.
+ *
+ * @param message the message to check
+ * @param n_link the buffer to put the link status in
+ *
+ *@return 1 if we are selected as MPR 0 if not
+ */
+static olsr_bool
+lookup_mpr_status(const struct hello_message *message,
+                  const struct interface *in_if)
+{  
+  struct hello_neighbor  *neighbors; 
+
+  for (neighbors = message->neighbors; neighbors; neighbors = neighbors->next) {
+    if (olsr_cnf->ip_version == AF_INET
+        ? ip4equal(&neighbors->address.v4, &in_if->ip_addr.v4)
+        : ip6equal(&neighbors->address.v6, &in_if->int6_addr.sin6_addr)) {
+
+      if (neighbors->link == SYM_LINK && neighbors->status == MPR_NEIGH) {
+        return OLSR_TRUE;
+      }
+      break;
+    }
+  }
+  /* Not found */
+  return OLSR_FALSE;
+}
+
+static int deserialize_hello(struct hello_message *hello, const void *ser) {
+	const unsigned char *limit;
+	olsr_u8_t type;
+	olsr_u16_t size;
+	
+	const unsigned char *curr = ser;
+	pkt_get_u8(&curr, &type);
+	if (type != HELLO_MESSAGE && type != LQ_HELLO_MESSAGE) {
+		/* No need to do anything more */
+		return 1;
+	}
+	pkt_get_reltime(&curr, &hello->vtime);
+	pkt_get_u16(&curr, &size);
+	pkt_get_ipaddress(&curr, &hello->source_addr);
+	
+	pkt_get_u8(&curr, &hello->ttl);
+	pkt_get_u8(&curr, &hello->hop_count);
+	pkt_get_u16(&curr, &hello->packet_seq_number);
+	pkt_ignore_u16(&curr);
+	
+	pkt_get_reltime(&curr, &hello->htime);
+	pkt_get_u8(&curr, &hello->willingness);
+	
+	hello->neighbors = NULL;
+	limit = ((const unsigned char *)ser) + size;
+	while (curr < limit) {
+		const struct lq_hello_info_header *info_head = (const struct lq_hello_info_header *)curr;
+		const unsigned char *limit2 = curr + ntohs(info_head->size);
+		
+		curr = (const unsigned char *)(info_head + 1);
+		while (curr < limit2) {
+			struct hello_neighbor *neigh = olsr_malloc_hello_neighbor("HELLO deserialization");
+			pkt_get_ipaddress(&curr, &neigh->address);
+			
+			if (type == LQ_HELLO_MESSAGE) {
+				olsr_deserialize_hello_lq_pair(&curr, neigh);
+			}
+			neigh->link = EXTRACT_LINK(info_head->link_code);
+			neigh->status = EXTRACT_STATUS(info_head->link_code);
+			
+			neigh->next = hello->neighbors;
+			hello->neighbors = neigh;
+		}
+	}
+	return 0;
+}
+
+void olsr_input_hello(union olsr_message *ser, struct interface *inif, union olsr_ip_addr *from) {
+	struct hello_message hello;
+	
+	if (ser == NULL) {
+		return;
+	}
+	if (deserialize_hello(&hello, ser) != 0) {
+		return;
+	}
+	olsr_hello_tap(&hello, inif, from);
+}
+
+/**
+ *Initializing the parser functions we are using
+ */
+void
+olsr_init_package_process(void)
+{
+  if (olsr_cnf->lq_level == 0)
+    {
+      olsr_parser_add_function(&olsr_input_hello, HELLO_MESSAGE, 1);
+      olsr_parser_add_function(&olsr_input_tc, TC_MESSAGE, 1);
+    }
+  else
+    {
+      olsr_parser_add_function(&olsr_input_hello, LQ_HELLO_MESSAGE, 1);
+      olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
+    }
+
+  olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
+  olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
+}
+
+void
+olsr_hello_tap(struct hello_message *message,
+               struct interface *in_if,
+               const union olsr_ip_addr *from_addr)
+{
+  struct neighbor_entry     *neighbor;
+
+  /*
+   * Update link status
+   */
+  struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
+
+  if (olsr_cnf->lq_level > 0)
+    {
+      struct hello_neighbor *walker;
+      /* just in case our neighbor has changed its HELLO interval */
+      olsr_update_packet_loss_hello_int(lnk, message->htime);
+
+      /* find the input interface in the list of neighbor interfaces */
+      for (walker = message->neighbors; walker != NULL; walker = walker->next)
+        if (ipequal(&walker->address, &in_if->ip_addr))
+          break;
+
+      // memorize our neighbour's idea of the link quality, so that we
+      // know the link quality in both directions
+      olsr_memorize_foreign_hello_lq(lnk, walker);
+
+      /* update packet loss for link quality calculation */
+      olsr_update_packet_loss(lnk);
+    }
+  
+  neighbor = lnk->neighbor;
+
+  /*
+   * Hysteresis
+   */
+  if(olsr_cnf->use_hysteresis)
+    {
+      /* Update HELLO timeout */
+      /* printf("MESSAGE HTIME: %f\n", message->htime);*/
+      olsr_update_hysteresis_hello(lnk, message->htime);
+    }
+
+  /* Check if we are chosen as MPR */
+  if(lookup_mpr_status(message, in_if))
+    /* source_addr is always the main addr of a node! */
+    olsr_update_mprs_set(&message->source_addr, message->vtime);
+
+
+
+  /* Check willingness */
+  if(neighbor->willingness != message->willingness)
+    {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
+		  olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr),
+		  neighbor->willingness,
+		  message->willingness);
+      /*
+       *If willingness changed - recalculate
+       */
+      neighbor->willingness = message->willingness;
+      changes_neighborhood = OLSR_TRUE;
+      changes_topology = OLSR_TRUE;
+    }
+
+
+  /* Don't register neighbors of neighbors that announces WILL_NEVER */
+  if(neighbor->willingness != WILL_NEVER)
+    process_message_neighbors(neighbor, message);
+
+  /* Process changes immedeatly in case of MPR updates */
+  olsr_process_changes();
+
+  olsr_free_hello_packet(message);
+
+  return;
+}
+
+/**
+ *Process a received(and parsed) MID message
+ *For every address check if there is a topology node
+ *registered with it and update its addresses.
+ *
+ *@param m the OLSR message received.
+ *@return 1 on success
+ */
+
+void
+olsr_process_received_mid(union olsr_message *m,
+                          struct interface *in_if __attribute__((unused)),
+                          union olsr_ip_addr *from_addr)
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  struct mid_alias *tmp_adr;
+  struct mid_message message;
+
+  mid_chgestruct(&message, m);
+
+  if (!olsr_validate_address(&message.mid_origaddr)) {
+    olsr_free_mid_packet(&message);
+    return;
+  }
+
+#ifdef DEBUG
+    OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&buf, &message.mid_origaddr));
+#endif
+    tmp_adr = message.mid_addr;
+
+    /*
+     *      If the sender interface (NB: not originator) of this message
+     *      is not in the symmetric 1-hop neighborhood of this node, the
+     *      message MUST be discarded.
+     */
+
+    if(check_neighbor_link(from_addr) != SYM_LINK) {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
+      olsr_free_mid_packet(&message);
+      return;
+    }
+
+    /* Update the timeout of the MID */
+    olsr_update_mid_table(&message.mid_origaddr, message.vtime);
+
+    while (tmp_adr) {
+      if (!mid_lookup_main_addr(&tmp_adr->alias_addr)){
+        struct ipaddr_str buf;
+        OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&buf, &message.mid_origaddr));
+        OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&buf, &tmp_adr->alias_addr));
+        insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, message.vtime);
+      }
+      tmp_adr = tmp_adr->next;
+    } 
+  
+    olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
+
+  olsr_forward_message(m, from_addr);
+  olsr_free_mid_packet(&message);
+}
+
+
+/**
+ *Process incoming HNA message.
+ *Forwards the message if that is to be done.
+ *
+ *@param m the incoming OLSR message
+ *the OLSR message.
+ *@return 1 on success
+ */
+
+void
+olsr_process_received_hna(union olsr_message *m,
+                          struct interface *in_if __attribute__((unused)),
+                          union olsr_ip_addr *from_addr)
+{
+
+  olsr_u8_t          olsr_msgtype;
+  olsr_reltime       vtime;
+  olsr_u16_t         olsr_msgsize;
+  union olsr_ip_addr originator;
+  olsr_u8_t          hop_count;
+  olsr_u16_t         packet_seq_number;
+
+  int                hnasize;
+  const olsr_u8_t    *curr, *curr_end;
+
+#ifdef DEBUG
+  OLSR_PRINTF(5, "Processing HNA\n");
+#endif
+
+  /* Check if everyting is ok */
+  if (!m) {
+    return;
+  }
+  curr = (const olsr_u8_t *)m;
+
+  /* olsr_msgtype */
+  pkt_get_u8(&curr, &olsr_msgtype);
+  if (olsr_msgtype != HNA_MESSAGE) {
+    OLSR_PRINTF(0, "not a HNA message!\n");
+    return;
+  }
+  /* Get vtime */
+  pkt_get_reltime(&curr, &vtime);
+
+  /* olsr_msgsize */
+  pkt_get_u16(&curr, &olsr_msgsize);
+  hnasize = olsr_msgsize - (olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message));
+  if (hnasize < 0) {
+    OLSR_PRINTF(0, "message size %d too small (at least %lu)!\n", olsr_msgsize, (unsigned long)(olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message)));
+    return;
+  }
+  if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
+    OLSR_PRINTF(0, "Illegal message size %d!\n", olsr_msgsize);
+    return;
+  }
+  curr_end = (const olsr_u8_t *)m + olsr_msgsize;
+
+  /* validate originator */
+  pkt_get_ipaddress(&curr, &originator);
+  /*printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator));*/
+
+  /* ttl */
+  pkt_ignore_u8(&curr);
+
+  /* hopcnt */
+  pkt_get_u8(&curr, &hop_count);
+
+  /* seqno */
+  pkt_get_u16(&curr, &packet_seq_number);
+
+    /*
+     *      If the sender interface (NB: not originator) of this message
+     *      is not in the symmetric 1-hop neighborhood of this node, the
+     *      message MUST be discarded.
+     */
+    if (check_neighbor_link(from_addr) != SYM_LINK) {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
+      return;
+    }
+#if 1
+    while (curr < curr_end) {
+      union olsr_ip_addr net;
+      olsr_u8_t prefixlen;
+      struct ip_prefix_list *entry;
+
+      pkt_get_ipaddress(&curr, &net);
+      pkt_get_prefixlen(&curr, &prefixlen);
+      entry = ip_prefix_list_find(olsr_cnf->hna_entries, &net, prefixlen);
+      if (entry == NULL) {
+        /* only update if it's not from us */
+        olsr_update_hna_entry(&originator, &net, prefixlen, vtime);
+      }
+    }
+#else
+    while (hna_tmp) {
+      /* Don't add an HNA entry that we are advertising ourselves. */
+      if (!ip_prefix_list_find(olsr_cnf->hna_entries, &hna_tmp->net, hna_tmp->prefixlen)) {
+        olsr_update_hna_entry(&message.originator, &hna_tmp->net, hna_tmp->prefixlen, message.vtime);
+      }
+    }
+#endif
+  olsr_forward_message(m, from_addr);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_package.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_package.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_package.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_package.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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 _OLSR_PROCESS_PACKAGE
+#define _OLSR_PROCESS_PACKAGE
+
+#include "olsr_protocol.h"
+#include "packet.h"
+#include "neighbor_table.h"
+
+void
+olsr_input_hello(union olsr_message *ser, struct interface *inif, union olsr_ip_addr *from);
+
+void
+olsr_init_package_process(void);
+
+void
+olsr_hello_tap(struct hello_message *, struct interface *, const union olsr_ip_addr *);
+
+void
+olsr_process_received_hello(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+void
+olsr_process_received_mid(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+void
+olsr_process_received_hna(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_routes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_routes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_routes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_routes.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,403 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * RIB implementation (c) 2007, Hannes Gredler (hannes@gredler.at)
+ * All rights reserved.
+ *
+ * export_route_entry interface added by Immo 'FaUl Wehrenberg 
+ * <immo@chaostreff-dortmund.de> and reworked by sven-ola 2007
+ *
+ * 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 "ipcalc.h"
+#include "defs.h"
+#include "olsr.h"
+#include "log.h"
+#include "kernel_routes.h"
+#include "common/avl.h"
+#include "net_olsr.h"
+#include "tc_set.h"
+#include "olsr_cookie.h"
+
+#ifdef WIN32
+#undef strerror
+#define strerror(x) StrError(x)
+#endif
+
+static struct list_node add_kernel_list;
+static struct list_node chg_kernel_list;
+static struct list_node del_kernel_list;
+
+
+/**
+ *
+ * Calculate the kernel route flags.
+ * Called before enqueuing a change/delete operation
+ *
+ */
+olsr_u8_t
+olsr_rt_flags(const struct rt_entry *rt)
+{
+  const struct rt_nexthop *nh;
+  olsr_u8_t flags = RTF_UP;
+
+  /* destination is host */
+  if (rt->rt_dst.prefix_len == olsr_cnf->maxplen) {
+    flags |= RTF_HOST;
+  }
+
+  nh = olsr_get_nh(rt);
+
+  if(!ipequal(&rt->rt_dst.prefix, &nh->gateway)) {
+    flags |= RTF_GATEWAY;
+  }
+
+  return flags;
+}
+
+
+export_route_function olsr_addroute_function;
+export_route_function olsr_addroute6_function;
+export_route_function olsr_delroute_function;
+export_route_function olsr_delroute6_function;
+
+
+void 
+olsr_init_export_route(void)
+{
+  /* the add/chg/del kernel queues */
+  list_head_init(&add_kernel_list);
+  list_head_init(&chg_kernel_list);
+  list_head_init(&del_kernel_list);
+
+  olsr_addroute_function = olsr_ioctl_add_route;
+  olsr_addroute6_function = olsr_ioctl_add_route6;
+  olsr_delroute_function = olsr_ioctl_del_route;
+  olsr_delroute6_function = olsr_ioctl_del_route6;
+}
+
+/**
+ * Delete all OLSR routes.
+ *
+ * This is extremely simple - Just increment the version of the
+ * tree and then olsr_update_rib_routes() will see all routes in the tree
+ * as outdated and olsr_update_kernel_routes() will finally flush it.
+ *
+ */
+void
+olsr_delete_all_kernel_routes(void)
+{ 
+  OLSR_PRINTF(1, "Deleting all routes...\n");
+
+  olsr_bump_routingtree_version();
+  olsr_update_rib_routes();
+  olsr_update_kernel_routes();
+}
+
+/**
+ * Enqueue a route on a kernel add/chg/del queue.
+ */
+static void
+olsr_enqueue_rt(struct list_node *head_node, struct rt_entry *rt)
+{
+  const struct rt_nexthop *nh;
+
+  /* if this node is already on some changelist we are done */
+  if (list_node_on_list(&rt->rt_change_node)) {
+    return;
+  }
+
+  /*
+   * For easier route dependency tracking we enqueue nexthop routes
+   * at the head of the queue and non-nexthop routes at the tail of the queue.
+   */
+  nh = olsr_get_nh(rt);
+
+  if (ipequal(&rt->rt_dst.prefix, &nh->gateway)) {
+    list_add_after(head_node, &rt->rt_change_node);
+  } else {
+    list_add_before(head_node, &rt->rt_change_node);
+  }
+}
+
+/**
+ * Process a route from the kernel deletion list.
+ *
+ *@return nada
+ */
+static void
+olsr_delete_kernel_route(struct rt_entry *rt)
+{
+  if(!olsr_cnf->host_emul) {
+    olsr_16_t error = olsr_cnf->ip_version == AF_INET ?
+      olsr_delroute_function(rt) : olsr_delroute6_function(rt);
+
+    if(error < 0) {
+      const char * const err_msg = strerror(errno);
+      const char * const routestr = olsr_rt_to_string(rt);
+      OLSR_PRINTF(1, "KERN: ERROR deleting %s: %s\n", routestr, err_msg);
+
+      olsr_syslog(OLSR_LOG_ERR, "Delete route %s: %s", routestr, err_msg);
+    }
+  }
+}
+
+/**
+ * Process a route from the kernel addition list.
+ *
+ *@return nada
+ */
+static void
+olsr_add_kernel_route(struct rt_entry *rt)
+{
+
+  if(!olsr_cnf->host_emul) {
+    olsr_16_t error = (olsr_cnf->ip_version == AF_INET) ?
+      olsr_addroute_function(rt) : olsr_addroute6_function(rt);
+
+    if(error < 0) {
+      const char * const err_msg = strerror(errno);
+      const char * const routestr = olsr_rtp_to_string(rt->rt_best);
+      OLSR_PRINTF(1, "KERN: ERROR adding %s: %s\n", routestr, err_msg);
+
+      olsr_syslog(OLSR_LOG_ERR, "Add route %s: %s", routestr, err_msg);
+    } else {
+
+      /* route addition has suceeded */
+
+      /* save the nexthop and metric in the route entry */
+      rt->rt_nexthop = rt->rt_best->rtp_nexthop;
+      rt->rt_metric = rt->rt_best->rtp_metric;
+    }
+  }
+}
+
+/**
+ * process the kernel add list.
+ * the routes are already ordered such that nexthop routes
+ * are on the head of the queue.
+ * nexthop routes need to be added first and therefore
+ * the queue needs to be traversed from head to tail.
+ */
+static void
+olsr_add_kernel_routes(struct list_node *head_node)
+{
+  struct rt_entry *rt;
+
+  while (!list_is_empty(head_node)) {
+    rt = changelist2rt(head_node->next);
+    olsr_add_kernel_route(rt);
+
+    list_remove(&rt->rt_change_node);
+  }
+}
+
+/**
+ * process the kernel change list.
+ * the routes are already ordered such that nexthop routes
+ * are on the head of the queue.
+ * non-nexthop routes need to be changed first and therefore
+ * the queue needs to be traversed from tail to head.
+ */
+static void
+olsr_chg_kernel_routes(struct list_node *head_node)
+{
+  struct rt_entry *rt;
+  struct list_node *node;
+
+  if (list_is_empty(head_node)) {
+    return;
+  }
+
+  /*
+   * First pass.
+   * traverse from the end to the beginning of the list,
+   * such that nexthop routes are deleted last.
+   */
+  for (node = head_node->prev; head_node != node; node = node->prev) {
+    rt = changelist2rt(node);
+    olsr_delete_kernel_route(rt);
+  }
+
+  /*
+   * Second pass.
+   * Traverse from the beginning to the end of the list,
+   * such that nexthop routes are added first.
+   */
+  while (!list_is_empty(head_node)) {
+    rt = changelist2rt(head_node->next);
+    olsr_add_kernel_route(rt);
+
+    list_remove(&rt->rt_change_node);
+  }
+}
+
+/**
+ * process the kernel delete list.
+ * the routes are already ordered such that nexthop routes
+ * are on the head of the queue.
+ * non-nexthop routes need to be deleted first and therefore
+ * the queue needs to be traversed from tail to head.
+ */
+static void
+olsr_del_kernel_routes(struct list_node *head_node)
+{
+  struct rt_entry *rt;
+
+  while (!list_is_empty(head_node)) {
+    rt = changelist2rt(head_node->prev);
+    olsr_delete_kernel_route(rt);
+
+    list_remove(&rt->rt_change_node);
+    olsr_cookie_free(rt_mem_cookie, rt);
+  }
+}
+
+/**
+ * Check the version number of all route paths hanging off a route entry.
+ * If a route does not match the current routing tree number, remove it
+ * from the global originator tree for that rt_entry.
+ * Reset the best route pointer.
+ */
+static void
+olsr_delete_outdated_routes(struct rt_entry *rt)
+{
+  struct rt_path *rtp;
+  struct avl_node *rtp_tree_node, *next_rtp_tree_node;
+
+  for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree);
+       rtp_tree_node != NULL;
+       rtp_tree_node = next_rtp_tree_node) {
+
+    /*
+     * pre-fetch the next node before loosing context.
+     */
+    next_rtp_tree_node = avl_walk_next(rtp_tree_node);
+
+    rtp = rtp_tree2rtp(rtp_tree_node);
+
+    /*
+     * check the version number which gets incremented on every SPF run.
+     * comparing for unequalness avoids handling version number wraps.
+     */
+    if (routingtree_version != rtp->rtp_version) {
+
+      /* remove from the originator tree */
+      avl_delete(&rt->rt_path_tree, rtp_tree_node);
+      rtp->rtp_rt = NULL;
+    }
+  }
+
+  /* safety measure against dangling pointers */
+  rt->rt_best = NULL;
+}
+
+/**
+ * Walk all the routes, remove outdated routes and run
+ * best path selection on the remaining set.
+ * Finally compare the nexthop of the route head and the best
+ * path and enqueue an add/chg operation.
+ */
+void
+olsr_update_rib_routes(void)
+{
+  struct rt_entry *rt;
+
+  OLSR_PRINTF(3, "Updating kernel routes...\n");
+
+  /* walk all routes in the RIB. */
+
+  OLSR_FOR_ALL_RT_ENTRIES(rt) {
+
+    /* eliminate first unused routes */
+    olsr_delete_outdated_routes(rt);
+
+    if (!rt->rt_path_tree.count) {
+
+      /* oops, all routes are gone - flush the route head */
+      avl_delete(&routingtree, rt_tree_node);
+
+      olsr_enqueue_rt(&del_kernel_list, rt);
+      continue;
+    }
+
+    /* run best route election */
+    olsr_rt_best(rt);
+
+    /* nexthop or hopcount change ? */
+    if (olsr_nh_change(&rt->rt_best->rtp_nexthop, &rt->rt_nexthop) ||
+        (FIBM_CORRECT == olsr_cnf->fib_metric &&
+         olsr_hopcount_change(&rt->rt_best->rtp_metric, &rt->rt_metric))) {
+
+      if (0 > rt->rt_nexthop.iif_index) {
+
+        /* fresh routes do have an interface index of -1. */
+        olsr_enqueue_rt(&add_kernel_list, rt);
+      } else { 
+
+        /* this is a route change. */
+        olsr_enqueue_rt(&chg_kernel_list, rt);
+      }
+    }
+  } OLSR_FOR_ALL_RT_ENTRIES_END(rt);
+}
+
+/**
+ * Propagate the accumulated changes from the last rib update to the kernel.
+ */
+void
+olsr_update_kernel_routes(void)
+{
+
+  /* delete unreachable routes */
+  olsr_del_kernel_routes(&del_kernel_list);
+
+  /* route changes */
+  olsr_chg_kernel_routes(&chg_kernel_list);
+
+  /* route additions */
+  olsr_add_kernel_routes(&add_kernel_list);
+
+#if DEBUG
+  olsr_print_routing_table(&routingtree);
+#endif
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_routes.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_routes.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/process_routes.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/process_routes.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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 _OLSR_PROCESS_RT
+#define _OLSR_PROCESS_RT
+
+#include "routing_table.h"
+#include <sys/ioctl.h>
+
+typedef int (*export_route_function)(const struct rt_entry*);
+
+extern export_route_function olsr_addroute_function;
+extern export_route_function olsr_addroute6_function;
+extern export_route_function olsr_delroute_function;
+extern export_route_function olsr_delroute6_function;
+
+void olsr_init_export_route(void);
+void olsr_update_rib_routes(void);
+void olsr_update_kernel_routes(void);
+void olsr_delete_all_kernel_routes(void);
+olsr_u8_t olsr_rt_flags(const struct rt_entry *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/rebuild_packet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/rebuild_packet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/rebuild_packet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/rebuild_packet.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,216 @@
+/*
+ * 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 "rebuild_packet.h"
+#include "ipcalc.h"
+#include "defs.h"
+#include "olsr.h"
+#include "mid_set.h"
+#include "mantissa.h"
+#include "net_olsr.h"
+
+/**
+ *Process/rebuild MID message. Converts the OLSR
+ *packet to the internal mid_message format.
+ *@param mmsg the mid_message struct in wich infomation
+ *is to be put.
+ *@param m the entire OLSR message revieved.
+ *@return negative on error
+ */
+
+void
+mid_chgestruct(struct mid_message *mmsg, const union olsr_message *m)
+{
+  int i;
+  struct mid_alias *alias, *alias_tmp;
+  int no_aliases;
+
+  /* Checking if everything is ok */
+  if ((!m) || (m->v4.olsr_msgtype != MID_MESSAGE))
+    return;
+
+  alias = NULL;
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IPv4 */
+      const struct midaddr *maddr = m->v4.message.mid.mid_addr;
+      /*
+       * How many aliases?
+       * nextmsg contains size of
+       * the addresses + 12 bytes(nextmessage, from address and the header)
+       */
+      no_aliases =  ((ntohs(m->v4.olsr_msgsize) - 12) / 4);
+
+      /*printf("Aliases: %d\n", no_aliases); */
+      mmsg->mid_origaddr.v4.s_addr = m->v4.originator;
+      mmsg->addr.v4.s_addr = m->v4.originator;
+      /*seq number*/
+      mmsg->mid_seqno = ntohs(m->v4.seqno);
+      mmsg->mid_addr = NULL;
+
+      /* Get vtime */
+      mmsg->vtime = me_to_reltime(m->v4.olsr_vtime);
+
+      /*printf("Sequencenuber of MID from %s is %d\n", ip_to_string(&mmsg->addr), mmsg->mid_seqno); */
+
+
+      for(i = 0; i < no_aliases; i++)
+	{
+	  alias = olsr_malloc(sizeof(struct mid_alias), "MID chgestruct");
+	  
+          alias->alias_addr.v4.s_addr = maddr->addr;
+	  alias->next = mmsg->mid_addr;
+	  mmsg->mid_addr = alias;
+	  maddr++;
+	}
+      
+      
+      if(olsr_cnf->debug_level > 1)
+	{
+          struct ipaddr_str buf;
+	  OLSR_PRINTF(3, "Alias list for %s: ", olsr_ip_to_string(&buf, &mmsg->mid_origaddr));
+	  OLSR_PRINTF(3, "%s", olsr_ip_to_string(&buf, &mmsg->addr));
+	  alias_tmp = mmsg->mid_addr;
+	  while(alias_tmp)
+	    {
+	      OLSR_PRINTF(3, " - %s", olsr_ip_to_string(&buf, &alias_tmp->alias_addr));
+	      alias_tmp = alias_tmp->next;
+	    }
+	  OLSR_PRINTF(3, "\n");
+	}
+    }
+  else
+    {
+      /* IPv6 */
+      const struct midaddr6 *maddr6 = m->v6.message.mid.mid_addr;
+      /*
+       * How many aliases?
+       * nextmsg contains size of
+       * the addresses + 12 bytes(nextmessage, from address and the header)
+       */
+      no_aliases =  ((ntohs(m->v6.olsr_msgsize) - 12) / 16); /* NB 16 */
+
+      /*printf("Aliases: %d\n", no_aliases); */
+      mmsg->mid_origaddr.v6 = m->v6.originator;
+      mmsg->addr.v6 = m->v6.originator;
+      /*seq number*/
+      mmsg->mid_seqno = ntohs(m->v6.seqno);
+      mmsg->mid_addr = NULL;
+
+      /* Get vtime */
+      mmsg->vtime = me_to_reltime(m->v6.olsr_vtime);
+
+      /*printf("Sequencenuber of MID from %s is %d\n", ip_to_string(&mmsg->addr), mmsg->mid_seqno); */
+
+      for(i = 0; i < no_aliases; i++)
+	{
+	  alias = olsr_malloc(sizeof(struct mid_alias), "MID chgestruct 2");
+	  
+	  /*printf("Adding alias: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&maddr6->addr));*/
+	  alias->alias_addr.v6 = maddr6->addr;
+	  alias->next = mmsg->mid_addr;
+	  mmsg->mid_addr = alias;
+	   
+	  maddr6++;
+	}
+
+
+      if(olsr_cnf->debug_level > 1)
+	{
+          struct ipaddr_str buf;
+	  OLSR_PRINTF(3, "Alias list for %s", ip6_to_string(&buf, &mmsg->mid_origaddr.v6));
+	  OLSR_PRINTF(3, "%s", ip6_to_string(&buf, &mmsg->addr.v6));
+
+	  alias_tmp = mmsg->mid_addr;
+	  while(alias_tmp)
+	    {
+	      OLSR_PRINTF(3, " - %s", ip6_to_string(&buf, &alias_tmp->alias_addr.v6));
+	      alias_tmp = alias_tmp->next;
+	    }
+	  OLSR_PRINTF(3, "\n");
+	}
+    }
+
+}
+
+
+
+
+/**
+ *Process/rebuild a message of unknown type. Converts the OLSR
+ *packet to the internal unknown_message format.
+ *@param umsg the unknown_message struct in wich infomation
+ *is to be put.
+ *@param m the entire OLSR message revieved.
+ *@return negative on error
+ */
+
+void
+unk_chgestruct(struct unknown_message *umsg, const union olsr_message *m)
+{
+
+  /* Checking if everything is ok */
+  if (!m)
+    return;
+
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IPv4 */
+      /* address */
+      umsg->originator.v4.s_addr = m->v4.originator;
+      /*seq number*/
+      umsg->seqno = ntohs(m->v4.seqno);
+      /* type */
+      umsg->type = m->v4.olsr_msgtype;
+    }
+  else
+    {
+      /* IPv6 */
+      /* address */
+      umsg->originator.v6 = m->v6.originator;
+      /*seq number*/
+      umsg->seqno = ntohs(m->v6.seqno);
+      /* type */
+      umsg->type = m->v4.olsr_msgtype;
+    }
+  
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/rebuild_packet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/rebuild_packet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/rebuild_packet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/rebuild_packet.h	2008-10-03 14:45:07.000000000 +0200
@@ -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 _OLSR_REBUILD
+#define _OLSR_REBUILD
+
+#include "olsr_protocol.h"
+#include "packet.h"
+
+void
+mid_chgestruct(struct mid_message *, const union olsr_message *);
+
+void
+unk_chgestruct(struct unknown_message *, const union olsr_message *);
+
+void
+hello_chgestruct(struct hello_message *, const union olsr_message *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/routing_table.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/routing_table.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/routing_table.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/routing_table.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,726 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * RIB implementation (c) 2007, Hannes Gredler (hannes@gredler.at)
+ * 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 "routing_table.h"
+#include "ipcalc.h"
+#include "defs.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "mid_set.h"
+#include "neighbor_table.h"
+#include "olsr.h"
+#include "link_set.h"
+#include "common/avl.h"
+#include "olsr_spf.h"
+#include "net_olsr.h"
+
+#include <assert.h>
+
+/* Cookies */
+struct olsr_cookie_info *rt_mem_cookie = NULL;
+struct olsr_cookie_info *rtp_mem_cookie = NULL;
+
+/*
+ * Sven-Ola: if the current internet gateway is switched, the
+ * NAT connection info is lost for any active TCP/UDP session.
+ * For this reason, we do not want to switch if the advantage
+ * is only minimal (cost of loosing all NATs is too high).
+ * The following rt_path keeps track of the current inet gw.
+ */
+static struct rt_path *current_inetgw = NULL;
+
+/* Root of our RIB */
+struct avl_tree routingtree;
+
+/*
+ * Keep a version number for detecting outdated elements
+ * in the per rt_entry rt_path subtree.
+ */
+unsigned int routingtree_version;
+
+/**
+ * Bump the version number of the routing tree.
+ *
+ * After route-insertion compare the version number of the routes
+ * against the version number of the table.
+ * This is a lightweight detection if a node or prefix went away,
+ * rather than brute force old vs. new rt_entry comparision.
+ */
+unsigned int
+olsr_bump_routingtree_version(void)
+{
+  return routingtree_version++;
+}
+
+/**
+ * avl_comp_ipv4_prefix
+ *
+ * compare two ipv4 prefixes.
+ * first compare the prefixes, then
+ *  then compare the prefix lengths.
+ *
+ * return 0 if there is an exact match and
+ * -1 / +1 depending on being smaller or bigger.
+ */
+int
+avl_comp_ipv4_prefix (const void *prefix1, const void *prefix2)
+{       
+  const struct olsr_ip_prefix *pfx1 = prefix1;
+  const struct olsr_ip_prefix *pfx2 = prefix2;
+  const olsr_u32_t addr1 = ntohl(pfx1->prefix.v4.s_addr);
+  const olsr_u32_t addr2 = ntohl(pfx2->prefix.v4.s_addr);
+
+  /* prefix */
+  if (addr1 < addr2) {
+    return -1;
+  }
+  if (addr1 > addr2) {
+    return +1;
+  }
+
+  /* prefix length */
+  if (pfx1->prefix_len < pfx2->prefix_len) {
+    return -1;
+  }
+  if (pfx1->prefix_len > pfx2->prefix_len) {
+    return +1;
+  }
+
+  return 0;
+}
+
+/**
+ * avl_comp_ipv6_prefix
+ *
+ * compare two ipv6 prefixes.
+ * first compare the prefixes, then
+ *  then compare the prefix lengths.
+ *
+ * return 0 if there is an exact match and
+ * -1 / +1 depending on being smaller or bigger.
+ */
+int
+avl_comp_ipv6_prefix (const void *prefix1, const void *prefix2)
+{       
+  int res;
+  const struct olsr_ip_prefix *pfx1 = prefix1;
+  const struct olsr_ip_prefix *pfx2 = prefix2;
+
+  /* prefix */
+  res = memcmp(&pfx1->prefix.v6, &pfx2->prefix.v6, 16);
+  if (res != 0) {
+    return res;
+  } 
+  /* prefix length */
+  if (pfx1->prefix_len < pfx2->prefix_len) {
+    return -1;
+  }
+  if (pfx1->prefix_len > pfx2->prefix_len) {
+    return +1;
+  }
+
+  return 0;
+}
+
+/**
+ * Initialize the routingtree and kernel change queues.
+ */
+void
+olsr_init_routing_table(void)
+{
+  OLSR_PRINTF(5, "RIB: init routing tree\n");
+
+  /* the routing tree */
+  avl_init(&routingtree, avl_comp_prefix_default);
+  routingtree_version = 0;
+
+  /*
+   * Get some cookies for memory stats and memory recycling.
+   */
+  rt_mem_cookie = olsr_alloc_cookie("rt_entry", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(rt_mem_cookie, sizeof(struct rt_entry));
+
+  rtp_mem_cookie = olsr_alloc_cookie("rt_path", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(rtp_mem_cookie, sizeof(struct rt_path));
+}
+
+/**
+ * Look up a maxplen entry (= /32 or /128) in the routing table.
+ *
+ * @param dst the address of the entry
+ *
+ * @return a pointer to a rt_entry struct 
+ * representing the route entry.
+ */
+struct rt_entry *
+olsr_lookup_routing_table(const union olsr_ip_addr *dst)
+{
+  struct avl_node *rt_tree_node;
+  struct olsr_ip_prefix prefix;
+
+  prefix.prefix = *dst;
+  prefix.prefix_len = olsr_cnf->maxplen;
+
+  rt_tree_node = avl_find(&routingtree, &prefix);
+
+  return rt_tree_node ? rt_tree2rt(rt_tree_node) : NULL;
+}
+
+/**
+ * Update gateway/interface/etx/hopcount and the version for a route path.
+ */
+void
+olsr_update_rt_path(struct rt_path *rtp, struct tc_entry *tc,
+                    struct link_entry *link)
+{
+
+  rtp->rtp_version = routingtree_version;
+
+  /* gateway */
+  rtp->rtp_nexthop.gateway = link->neighbor_iface_addr;
+
+  /* interface */
+  rtp->rtp_nexthop.iif_index = link->inter->if_index;
+
+  /* metric/etx */
+  rtp->rtp_metric.hops = tc->hops;
+  rtp->rtp_metric.cost = tc->path_cost;
+}
+
+/**
+ * Alloc and key a new rt_entry.
+ */
+static struct rt_entry *
+olsr_alloc_rt_entry(struct olsr_ip_prefix *prefix)
+{
+  struct rt_entry *rt = olsr_cookie_malloc(rt_mem_cookie);
+  if (!rt) {
+    return NULL;
+  }
+
+  memset(rt, 0, sizeof(*rt));
+  
+  /* Mark this entry as fresh (see process_routes.c:512) */
+  rt->rt_nexthop.iif_index = -1;
+
+  /* set key and backpointer prior to tree insertion */
+  rt->rt_dst = *prefix;
+
+  rt->rt_tree_node.key = &rt->rt_dst;
+  avl_insert(&routingtree, &rt->rt_tree_node, AVL_DUP_NO);
+
+  /* init the originator subtree */
+  avl_init(&rt->rt_path_tree, avl_comp_default);
+
+  return rt;
+}
+
+/**
+ * Alloc and key a new rt_path.
+ */
+static struct rt_path *
+olsr_alloc_rt_path(struct tc_entry *tc,
+                   struct olsr_ip_prefix *prefix, olsr_u8_t origin)
+{
+  struct rt_path *rtp = olsr_cookie_malloc(rtp_mem_cookie);
+
+  if (!rtp) {
+    return NULL;
+  }
+
+  memset(rtp, 0, sizeof(*rtp));
+
+  rtp->rtp_dst = *prefix;
+
+  /* set key and backpointer prior to tree insertion */
+  rtp->rtp_prefix_tree_node.key = &rtp->rtp_dst;
+
+  /* insert to the tc prefix tree */
+  avl_insert(&tc->prefix_tree, &rtp->rtp_prefix_tree_node, AVL_DUP_NO);
+  olsr_lock_tc_entry(tc);
+
+  /* backlink to the owning tc entry */
+  rtp->rtp_tc = tc;
+
+  /* store the origin of the route */
+  rtp->rtp_origin = origin;
+
+  return rtp;
+}
+
+/**
+ * Create a route entry for a given rt_path and
+ * insert it into the global RIB tree.
+ */
+void
+olsr_insert_rt_path(struct rt_path *rtp, struct tc_entry *tc,
+                    struct link_entry *link)
+{
+  struct rt_entry *rt;
+  struct avl_node *node;
+
+  /*
+   * no unreachable routes please.
+   */
+  if (tc->path_cost == ROUTE_COST_BROKEN) {
+    return;
+  }
+
+  /*
+   * No bogus prefix lengths.
+   */
+  if (rtp->rtp_dst.prefix_len > olsr_cnf->maxplen) {
+    return;
+  }
+
+  /*
+   * first check if there is a route_entry for the prefix.
+   */
+  node = avl_find(&routingtree, &rtp->rtp_dst);
+
+  if (!node) {
+
+    /* no route entry yet */
+    rt = olsr_alloc_rt_entry(&rtp->rtp_dst);
+
+    if (!rt) {
+      return;
+    }
+
+  } else {
+    rt = rt_tree2rt(node);
+  }
+
+
+  /* Now insert the rt_path to the owning rt_entry tree */
+  rtp->rtp_originator = tc->addr;
+
+  /* set key and backpointer prior to tree insertion */
+  rtp->rtp_tree_node.key = &rtp->rtp_originator;
+
+  /* insert to the route entry originator tree */
+  avl_insert(&rt->rt_path_tree, &rtp->rtp_tree_node, AVL_DUP_NO);
+
+  /* backlink to the owning route entry */
+  rtp->rtp_rt = rt;
+
+  /* update the version field and relevant parameters */
+  olsr_update_rt_path(rtp, tc, link);
+}
+
+/**
+ * Unlink and free a rt_path.
+ */
+void
+olsr_delete_rt_path(struct rt_path *rtp)
+{
+
+  /* remove from the originator tree */
+  if (rtp->rtp_rt) {
+    avl_delete(&rtp->rtp_rt->rt_path_tree, &rtp->rtp_tree_node);
+    rtp->rtp_rt = NULL;
+  }
+
+  /* remove from the tc prefix tree */
+  if (rtp->rtp_tc) {
+    avl_delete(&rtp->rtp_tc->prefix_tree, &rtp->rtp_prefix_tree_node);
+    olsr_unlock_tc_entry(rtp->rtp_tc);
+    rtp->rtp_tc = NULL;
+  }
+
+  /* no current inet gw if the rt_path is removed */
+  if (current_inetgw == rtp) {
+    current_inetgw = NULL;
+  }
+
+  olsr_cookie_free(rtp_mem_cookie, rtp);
+}
+
+
+/**
+ * Check if there is an interface or gateway change.
+ */
+olsr_bool
+olsr_nh_change(const struct rt_nexthop *nh1, const struct rt_nexthop *nh2)
+{
+  if (!ipequal(&nh1->gateway, &nh2->gateway) ||
+      (nh1->iif_index != nh2->iif_index)) {
+    return OLSR_TRUE;
+  }
+  return OLSR_FALSE;
+}
+
+/**
+ * Check if there is a hopcount change.
+ */
+olsr_bool
+olsr_hopcount_change(const struct rt_metric *met1, const struct rt_metric *met2)
+{
+  return (met1->hops != met2->hops);
+}
+
+/**
+ * Depending if flat_metric is configured and the kernel fib operation
+ * return the hopcount metric of a route.
+ * For adds this is the metric of best rour after olsr_rt_best() election,
+ * for deletes this is the metric of the route that got stored in the rt_entry,
+ * during route installation.
+ */
+olsr_u8_t
+olsr_fib_metric(const struct rt_metric *met)
+{
+  if (FIBM_CORRECT == olsr_cnf->fib_metric) {
+    return met->hops;
+  }
+  return RT_METRIC_DEFAULT;
+}
+
+/**
+ * depending on the operation (add/chg/del) the nexthop
+ * field from the route entry or best route path shall be used.
+ */
+const struct rt_nexthop *
+olsr_get_nh(const struct rt_entry *rt)
+{
+
+  if(rt->rt_best) {
+
+    /* this is a route add/chg - grab nexthop from the best route. */
+    return &rt->rt_best->rtp_nexthop;
+  } 
+  
+  /* this is a route deletion - all routes are gone. */
+  return &rt->rt_nexthop;
+}
+
+/**
+ * compare two route paths.
+ *
+ * returns TRUE if the first path is better
+ * than the second one, FALSE otherwise.
+ */
+static olsr_bool
+olsr_cmp_rtp(const struct rt_path *rtp1, const struct rt_path *rtp2, const struct rt_path *inetgw)
+{
+    olsr_linkcost etx1 = rtp1->rtp_metric.cost;
+    olsr_linkcost etx2 = rtp2->rtp_metric.cost;
+    if (inetgw == rtp1) etx1 *= olsr_cnf->lq_nat_thresh;
+    if (inetgw == rtp2) etx2 *= olsr_cnf->lq_nat_thresh;
+
+    /* etx comes first */
+    if (etx1 < etx2) {
+      return OLSR_TRUE;
+    }
+
+    /* hopcount is next tie breaker */
+    if ((etx1 == etx2) &&
+        (rtp1->rtp_metric.hops < rtp2->rtp_metric.hops)) {
+      return OLSR_TRUE;
+    }
+
+    /* originator (which is guaranteed to be unique) is final tie breaker */
+    if ((rtp1->rtp_metric.hops == rtp2->rtp_metric.hops) &&
+        (memcmp(&rtp1->rtp_originator, &rtp2->rtp_originator,
+                olsr_cnf->ipsize) == -1)) {
+      return OLSR_TRUE;
+    }
+
+    return OLSR_FALSE;
+}
+
+/**
+ * compare the best path of two route entries.
+ *
+ * returns TRUE if the first entry is better
+ * than the second one, FALSE otherwise.
+ */
+olsr_bool
+olsr_cmp_rt(const struct rt_entry *rt1, const struct rt_entry *rt2)
+{
+  return olsr_cmp_rtp(rt1->rt_best, rt2->rt_best, NULL);
+}
+
+/**
+ * run best route selection among a
+ * set of identical prefixes.
+ */
+void
+olsr_rt_best(struct rt_entry *rt)
+{
+  /* grab the first entry */
+  struct avl_node *node = avl_walk_first(&rt->rt_path_tree);
+
+  assert(node != 0); /* should not happen */
+
+  rt->rt_best = rtp_tree2rtp(node);
+
+  /* walk all remaining originator entries */
+  while ((node = avl_walk_next(node))) {
+    struct rt_path *rtp = rtp_tree2rtp(node);
+
+    if (olsr_cmp_rtp(rtp, rt->rt_best, current_inetgw)) {
+      rt->rt_best = rtp;
+    }
+  }
+
+  if (0 == rt->rt_dst.prefix_len) {
+    current_inetgw = rt->rt_best;
+  }
+}
+
+/**
+ * Insert a prefix into the prefix tree hanging off a lsdb (tc) entry.
+ *
+ * Check if the candidate route (we call this a rt_path) is known,
+ * if not create it.
+ * Upon post-SPF processing (if the node is reachable) the prefix
+ * will be finally inserted into the global RIB.
+ *
+ *@param dst the destination
+ *@param plen the prefix length
+ *@param originator the originating router
+ *
+ *@return the new rt_path struct
+ */
+struct rt_path *
+olsr_insert_routing_table(union olsr_ip_addr *dst, int plen,
+                          union olsr_ip_addr *originator, int origin)
+{
+#ifdef DEBUG
+  struct ipaddr_str dstbuf, origbuf;
+#endif
+  struct tc_entry *tc;
+  struct rt_path *rtp;
+  struct avl_node *node;
+  struct olsr_ip_prefix prefix;
+
+  /*
+   * No bogus prefix lengths.
+   */
+  if (plen > olsr_cnf->maxplen) {
+    return NULL;
+  }
+
+  /*
+   * For all routes we use the tc_entry as an hookup point.
+   * If the tc_entry is disconnected, i.e. has no edges it will not
+   * be explored during SPF run.
+   */
+  tc = olsr_locate_tc_entry(originator);
+  
+  /*
+   * first check if there is a rt_path for the prefix.
+   */
+  prefix.prefix = *dst;
+  prefix.prefix_len = plen;
+
+  node = avl_find(&tc->prefix_tree, &prefix);
+
+  if (!node) {
+
+    /* no rt_path for this prefix yet */
+    rtp = olsr_alloc_rt_path(tc, &prefix, origin);
+
+    if (!rtp) {
+      return NULL;
+    }
+
+#ifdef DEBUG
+    OLSR_PRINTF(1, "RIB: add prefix %s/%u from %s\n",
+                olsr_ip_to_string(&dstbuf, dst), plen,
+                olsr_ip_to_string(&origbuf, originator));
+#endif
+
+    /* overload the hna change bit for flagging a prefix change */
+    changes_hna = OLSR_TRUE;
+
+  } else {
+    rtp = rtp_prefix_tree2rtp(node);
+  }
+
+  return rtp;
+}
+
+/**
+ * Delete a prefix from the prefix tree hanging off a lsdb (tc) entry.
+ */
+void
+olsr_delete_routing_table(union olsr_ip_addr *dst, int plen,
+                          union olsr_ip_addr *originator)
+{
+#ifdef DEBUG
+  struct ipaddr_str dstbuf, origbuf;
+#endif
+
+  struct tc_entry *tc;
+  struct rt_path *rtp;
+  struct avl_node *node;
+  struct olsr_ip_prefix prefix;
+
+  /*
+   * No bogus prefix lengths.
+   */
+  if (plen > olsr_cnf->maxplen) {
+    return;
+  }
+
+  tc = olsr_lookup_tc_entry(originator);
+  if (!tc) {
+    return;
+  }
+
+  /*
+   * Grab the rt_path for the prefix.
+   */
+  prefix.prefix = *dst;
+  prefix.prefix_len = plen;
+
+  node = avl_find(&tc->prefix_tree, &prefix);
+
+  if (node) {
+    rtp = rtp_prefix_tree2rtp(node);
+    olsr_delete_rt_path(rtp);
+
+#ifdef DEBUG
+    OLSR_PRINTF(1, "RIB: del prefix %s/%u from %s\n",
+                olsr_ip_to_string(&dstbuf, dst), plen,
+                olsr_ip_to_string(&origbuf, originator));
+#endif
+
+    /* overload the hna change bit for flagging a prefix change */
+    changes_hna = OLSR_TRUE;
+  }
+}
+
+/**
+ * format a route entry into a buffer
+ */
+char *
+olsr_rt_to_string(const struct rt_entry *rt)
+{
+  static char buff[128];
+  struct ipaddr_str prefixstr, gwstr;
+
+  snprintf(buff, sizeof(buff),
+           "%s/%u via %s",
+           olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix),
+           rt->rt_dst.prefix_len,
+           olsr_ip_to_string(&gwstr, &rt->rt_nexthop.gateway));
+
+  return buff;
+}
+
+/**
+ * format a route path into a buffer
+ */
+char *
+olsr_rtp_to_string(const struct rt_path *rtp)
+{
+  static char buff[128];
+  struct ipaddr_str prefixstr, origstr, gwstr;
+  struct rt_entry *rt = rtp->rtp_rt;
+  struct lqtextbuffer lqbuffer;
+  
+  snprintf(buff, sizeof(buff),
+           "%s/%u from %s via %s, "
+           "cost %s, metric %u, v %u",
+           olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix),
+           rt->rt_dst.prefix_len,
+           olsr_ip_to_string(&origstr, &rtp->rtp_originator),
+           olsr_ip_to_string(&gwstr, &rtp->rtp_nexthop.gateway),
+           get_linkcost_text(rtp->rtp_metric.cost, OLSR_TRUE, &lqbuffer),
+           rtp->rtp_metric.hops,
+           rtp->rtp_version);
+
+  return buff;
+}
+
+/**
+ * Print the routingtree to STDOUT
+ *
+ */
+void
+olsr_print_routing_table(struct avl_tree *tree)
+{
+#ifndef NODEBUG
+  /* The whole function makes no sense without it. */
+  struct avl_node *rt_tree_node;
+  struct lqtextbuffer lqbuffer;
+  
+  OLSR_PRINTF(6, "ROUTING TABLE\n");
+
+  for (rt_tree_node = avl_walk_first(tree);
+       rt_tree_node != NULL;
+       rt_tree_node = avl_walk_next(rt_tree_node)) {
+    struct avl_node *rtp_tree_node;
+    struct ipaddr_str prefixstr, origstr, gwstr;
+    struct rt_entry *rt = rt_tree2rt(rt_tree_node);
+
+    /* first the route entry */
+    OLSR_PRINTF(6, "%s/%u, via %s, best-originator %s\n",
+           olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix),
+           rt->rt_dst.prefix_len,
+           olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway),
+           olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator));
+
+    /* walk the per-originator path tree of routes */
+    for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree);
+         rtp_tree_node != NULL;
+         rtp_tree_node = avl_walk_next(rtp_tree_node)) {
+      struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node);
+      OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n",
+             olsr_ip_to_string(&origstr, &rtp->rtp_originator),
+             get_linkcost_text(rtp->rtp_metric.cost, OLSR_TRUE, &lqbuffer),
+             rtp->rtp_metric.hops,
+             olsr_ip_to_string(&gwstr, &rtp->rtp_nexthop.gateway),
+             if_ifwithindex_name(rt->rt_nexthop.iif_index),
+             rtp->rtp_version);    
+    }
+  }
+#endif
+  tree = NULL; /* squelch compiler warnings */
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/routing_table.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/routing_table.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/routing_table.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/routing_table.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,245 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * RIB implementation (c) 2007, Hannes Gredler (hannes@gredler.at)
+ * 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 _OLSR_ROUTING_TABLE
+#define _OLSR_ROUTING_TABLE
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/route.h>
+#include "hna_set.h"
+#include "link_set.h"
+#include "olsr_cookie.h"
+#include "common/avl.h"
+#include "common/list.h"
+
+#define NETMASK_HOST 0xffffffff
+#define NETMASK_DEFAULT 0x0
+
+/*
+ * the kernel FIB does not need to know the metric of a route.
+ * this saves us from enqueuing/dequeueing hopcount only changes.
+ */
+#define RT_METRIC_DEFAULT 2
+
+/* a composite metric is used for path selection */
+struct rt_metric
+{
+  olsr_linkcost       cost;
+  olsr_u32_t 	        hops;
+};
+
+/* a nexthop is a pointer to a gateway router plus an interface */
+struct rt_nexthop
+{
+  union olsr_ip_addr    gateway; /* gateway router */
+  int                   iif_index; /* outgoing interface index */
+};
+
+/*
+ * Every prefix in our RIB needs a route entry that contains
+ * the nexthop of the best path as installed in the kernel FIB.
+ * The route entry is the root of a rt_path tree of equal prefixes
+ * originated by different routers. It also contains a shortcut
+ * for accessing the best route among all contributing routes.
+ */
+struct rt_entry
+{
+  struct olsr_ip_prefix rt_dst;
+  struct avl_node       rt_tree_node; 
+  struct rt_path        *rt_best; /* shortcut to the best path */
+  struct rt_nexthop     rt_nexthop; /* nexthop of FIB route */
+  struct rt_metric      rt_metric; /* metric of FIB route */
+  struct avl_tree       rt_path_tree;
+  struct list_node      rt_change_node; /* queue for kernel FIB add/chg/del */
+};
+
+AVLNODE2STRUCT(rt_tree2rt, struct rt_entry, rt_tree_node);
+LISTNODE2STRUCT(changelist2rt, struct rt_entry, rt_change_node);
+
+/*
+ * For every received route a rt_path is added to the RIB.
+ * Depending on the results of the SPF calculation we perform a
+ * best_path calculation and pick the one with the lowest etx/metric.
+ * The rt_path gets first inserted into the per tc_entry prefix tree.
+ * If during the SPF calculation the tc_entry becomes reachable via
+ * a local nexthop it is inserted into the global RIB tree.
+ */
+struct rt_path
+{
+  struct rt_entry       *rtp_rt; /* backpointer to owning route head */
+  struct tc_entry       *rtp_tc; /* backpointer to owning tc entry */
+  struct rt_nexthop     rtp_nexthop;
+  struct rt_metric      rtp_metric;
+  struct avl_node       rtp_tree_node; /* global rtp node */
+  union olsr_ip_addr    rtp_originator; /* originator of the route */
+  struct avl_node       rtp_prefix_tree_node; /* tc entry rtp node */
+  struct olsr_ip_prefix rtp_dst; /* the prefix */
+  olsr_u32_t            rtp_version; /* for detection of outdated rt_paths */
+  olsr_u8_t             rtp_origin; /* internal, MID or HNA */
+};
+
+AVLNODE2STRUCT(rtp_tree2rtp, struct rt_path, rtp_tree_node);
+AVLNODE2STRUCT(rtp_prefix_tree2rtp, struct rt_path, rtp_prefix_tree_node);
+
+/*
+ * In olsrd we have three different route types.
+ * Internal routes are generated by simple reachability
+ * of a node (by means of a tc message reception).
+ * MID routes result from MID messages and HNA routes
+ * from a gw routers HNA anncouncements.
+ */
+enum olsr_rt_origin {
+  OLSR_RT_ORIGIN_MIN,
+  OLSR_RT_ORIGIN_INT,
+  OLSR_RT_ORIGIN_MID,
+  OLSR_RT_ORIGIN_HNA,
+  OLSR_RT_ORIGIN_MAX
+};
+
+/*
+ * OLSR_FOR_ALL_RT_ENTRIES
+ *
+ * macro for traversing the entire routing table.
+ * it is recommended to use this because it hides all the internal
+ * datastructure from the callers.
+ *
+ * the loop prefetches the next node in order to not loose context if
+ * for example the caller wants to delete the current rt_entry.
+ */
+#define OLSR_FOR_ALL_RT_ENTRIES(rt) \
+{ \
+  struct avl_node *rt_tree_node, *next_rt_tree_node; \
+  for (rt_tree_node = avl_walk_first(&routingtree); \
+    rt_tree_node; rt_tree_node = next_rt_tree_node) { \
+    next_rt_tree_node = avl_walk_next(rt_tree_node); \
+    rt = rt_tree2rt(rt_tree_node);
+#define OLSR_FOR_ALL_RT_ENTRIES_END(rt) }}
+
+/*
+ * OLSR_FOR_ALL_HNA_RT_ENTRIES
+ *
+ * macro for traversing the entire routing table and pick only
+ * HNA routes. This is not optimal - however, If the RIBs become
+ * too big one day then we keep an additional per origin tree
+ * in order to speed up traversal.
+ * In the meantime it is recommended to use this macro because
+ * it hides all the internal datastructure from the callers
+ * and the core maintainers do not have to update all the plugins
+ * once we decide to change the datastructures.
+ */
+#define OLSR_FOR_ALL_HNA_RT_ENTRIES(rt) \
+{ \
+  struct avl_node *rt_tree_node, *next_rt_tree_node; \
+  for (rt_tree_node = avl_walk_first(&routingtree); \
+    rt_tree_node; rt_tree_node = next_rt_tree_node) { \
+    next_rt_tree_node = avl_walk_next(rt_tree_node); \
+    rt = rt_tree2rt(rt_tree_node); \
+    if (rt->rt_best->rtp_origin != OLSR_RT_ORIGIN_HNA) \
+      continue; 
+#define OLSR_FOR_ALL_HNA_RT_ENTRIES_END(rt) }}
+
+
+/**
+ * IPv4 <-> IPv6 wrapper
+ */
+union olsr_kernel_route
+{
+  struct
+  {
+    struct sockaddr rt_dst;
+    struct sockaddr rt_gateway;
+    olsr_u32_t metric;
+  } v4;
+
+  struct
+  {
+    struct in6_addr rtmsg_dst;
+    struct in6_addr rtmsg_gateway;
+    olsr_u32_t rtmsg_metric;
+  } v6;
+};
+
+
+extern struct avl_tree routingtree;
+extern unsigned int routingtree_version;
+extern struct olsr_cookie_info *rt_mem_cookie;
+
+void
+olsr_init_routing_table(void);
+
+unsigned int olsr_bump_routingtree_version(void);
+
+int avl_comp_ipv4_prefix (const void *, const void *);
+int avl_comp_ipv6_prefix (const void *, const void *);
+
+void olsr_rt_best(struct rt_entry *);
+olsr_bool olsr_nh_change(const struct rt_nexthop *, const struct rt_nexthop *);
+olsr_bool olsr_hopcount_change(const struct rt_metric *, const struct rt_metric *);
+olsr_bool olsr_cmp_rt(const struct rt_entry *, const struct rt_entry *);
+olsr_u8_t olsr_fib_metric(const struct rt_metric *);
+
+char *olsr_rt_to_string(const struct rt_entry *);
+char *olsr_rtp_to_string(const struct rt_path *);
+void olsr_print_routing_table(struct avl_tree *);
+
+const struct rt_nexthop * olsr_get_nh(const struct rt_entry *);
+
+/* rt_path manipulation */
+struct rt_path *olsr_insert_routing_table(union olsr_ip_addr *, int, union olsr_ip_addr *, int);
+void olsr_delete_routing_table(union olsr_ip_addr *, int, union olsr_ip_addr *);
+void olsr_insert_rt_path(struct rt_path *, struct tc_entry *, struct link_entry *);
+void olsr_update_rt_path(struct rt_path *, struct tc_entry *, struct link_entry *);
+void olsr_delete_rt_path(struct rt_path *);
+
+struct rt_entry *
+olsr_lookup_routing_table(const union olsr_ip_addr *);
+
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/scheduler.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/scheduler.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/scheduler.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/scheduler.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,722 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * Timer rewrite (c) 2008, Hannes Gredler (hannes@gredler.at)
+ * 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 "defs.h"
+#include "scheduler.h"
+#include "log.h"
+#include "tc_set.h"
+#include "link_set.h"
+#include "duplicate_set.h"
+#include "mpr_selector_set.h"
+#include "mid_set.h"
+#include "mpr.h"
+#include "olsr.h"
+#include "build_msg.h"
+#include "net_olsr.h"
+#include "socket_parser.h"
+#include "olsr_spf.h"
+#include "link_set.h"
+#include "olsr_cookie.h"
+
+/* Timer data, global. Externed in defs.h */
+clock_t now_times;		       /* current idea of times(2) reported uptime */
+
+/* Hashed root of all timers */
+struct list_node timer_wheel[TIMER_WHEEL_SLOTS];
+clock_t timer_last_run;		       /* remember the last timeslot walk */
+
+/* Pool of timers to avoid malloc() churn */
+struct list_node free_timer_list;
+
+/* Statistics */
+unsigned int timers_running;
+
+
+/**
+ * Sleep until the next scheduling interval.
+ *
+ * @param scheduler loop runtime in clock ticks.
+ * @return nada
+ */
+static void
+olsr_scheduler_sleep(unsigned long scheduler_runtime)
+{
+  struct timespec remainder_spec, sleeptime_spec;
+  struct timeval sleeptime_val, time_used, next_interval;
+  olsr_u32_t next_interval_usec;
+  unsigned long milliseconds_used;
+
+  /* Calculate next planned scheduler invocation */
+  next_interval_usec = olsr_cnf->pollrate * USEC_PER_SEC;
+  next_interval.tv_sec = next_interval_usec / USEC_PER_SEC;
+  next_interval.tv_usec = next_interval_usec % USEC_PER_SEC;
+
+  /* Determine used runtime */
+  milliseconds_used = scheduler_runtime * olsr_cnf->system_tick_divider;
+  time_used.tv_sec = milliseconds_used / MSEC_PER_SEC;
+  time_used.tv_usec = (milliseconds_used % MSEC_PER_SEC) * USEC_PER_MSEC;
+
+  if (timercmp(&time_used, &next_interval, <)) {
+    timersub(&next_interval, &time_used, &sleeptime_val);
+
+    sleeptime_spec.tv_sec = sleeptime_val.tv_sec;
+    sleeptime_spec.tv_nsec = sleeptime_val.tv_usec * NSEC_PER_USEC;
+
+    while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)
+      sleeptime_spec = remainder_spec;
+  }
+}
+
+/**
+ * Main scheduler event loop. Polls at every
+ * sched_poll_interval and calls all functions
+ * that are timed out or that are triggered.
+ * Also calls the olsr_process_changes()
+ * function at every poll.
+ *
+ * @return nada
+ */
+void
+olsr_scheduler(void)
+{
+  struct interface *ifn;
+
+  OLSR_PRINTF(1, "Scheduler started - polling every %0.2f seconds\n",
+	      olsr_cnf->pollrate);
+  OLSR_PRINTF(3, "Max jitter is %f\n\n", olsr_cnf->max_jitter);
+
+  /* Main scheduler loop */
+  for (;;) {
+
+    /*
+     * Update the global timestamp. We are using a non-wallclock timer here
+     * to avoid any undesired side effects if the system clock changes.
+     */
+    now_times = olsr_times();
+
+    /* Read incoming data */
+    olsr_poll_sockets();
+
+    /* Process timers (before packet generation) */
+    olsr_walk_timers(&timer_last_run);
+
+    /* Update */
+    olsr_process_changes();
+
+    /* Check for changes in topology */
+    if (link_changes) {
+      OLSR_PRINTF(3, "ANSN UPDATED %d\n\n", get_local_ansn());
+      increase_local_ansn();
+      link_changes = OLSR_FALSE;
+    }
+
+    /* looping trough interfaces and emmitting pending data */
+    for (ifn = ifnet; ifn; ifn = ifn->int_next) {
+      if (net_output_pending(ifn) && TIMED_OUT(ifn->fwdtimer)) {
+	net_output(ifn);
+      }
+    }
+
+    /* We are done, sleep until the next scheduling interval. */
+    olsr_scheduler_sleep(olsr_times() - now_times);
+
+#if defined WIN32
+    /* The Ctrl-C signal handler thread asks us to exit */
+    if (olsr_win32_end_request) {
+      break;
+    }
+#endif
+  }
+
+#if defined WIN32
+  /* Tell the Ctrl-C signal handler thread that we have exited */
+  olsr_win32_end_flag = TRUE;
+
+  /*
+   * The Ctrl-C signal handler thread will exit the process
+   * and hence also kill us.
+   */
+  while (1) {
+    Sleep(1000);		/* milliseconds */
+  }
+#endif
+}
+
+
+/**
+ * Decrement a relative timer by a random number range.
+ *
+ * @param the relative timer expressed in units of milliseconds.
+ * @param the jitter in percent
+ * @param cached result of random() at system init.
+ * @return the absolute timer in system clock tick units
+ */
+static clock_t
+olsr_jitter(unsigned int rel_time, olsr_u8_t jitter_pct, unsigned int random)
+{
+  unsigned int jitter_time;
+
+  /*
+   * No jitter or, jitter larger than 99% does not make sense.
+   * Also protect against overflows resulting from > 25 bit timers.
+   */
+  if (jitter_pct == 0 || jitter_pct > 99 || rel_time > (1 << 24)) {
+    return GET_TIMESTAMP(rel_time);
+  }
+
+  /*
+   * Play some tricks to avoid overflows with integer arithmetic.
+   */
+  jitter_time = (jitter_pct * rel_time) / 100;
+  jitter_time = random / (1 + RAND_MAX / jitter_time);
+
+#if 0
+  OLSR_PRINTF(3, "TIMER: jitter %u%% rel_time %ums to %ums\n",
+	      jitter_pct, rel_time, rel_time - jitter_time);
+#endif
+
+  return GET_TIMESTAMP(rel_time - jitter_time);
+}
+
+
+/**
+ * Allocate a timer_entry.
+ * Do this first by checking if something is available in the free_timer_pool
+ * If not then allocate a big chunk of memory and thread its elements up
+ * to the free_timer_list.
+ */
+static struct timer_entry *
+olsr_get_timer(void)
+{
+  void *timer_block;
+  struct timer_entry *timer;
+  struct list_node *timer_list_node;
+  unsigned int timer_index;
+
+  /*
+   * If there is at least one timer in the pool then remove the first
+   * element from the pool and recycle it.
+   */
+  if (!list_is_empty(&free_timer_list)) {
+    timer_list_node = free_timer_list.next;
+
+    /* carve it out of the pool, do not memset overwrite timer->timer_random */
+    list_remove(timer_list_node);
+    timer = list2timer(timer_list_node);
+
+    return timer;
+  }
+
+  /*
+   * Nothing in the pool, allocate a new chunk.
+   */
+  timer_block =
+    olsr_malloc(sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK,
+		"timer chunk");
+
+#if 0
+  OLSR_PRINTF(3, "TIMER: alloc %u bytes chunk at %p\n",
+	      sizeof(struct timer_entry) * OLSR_TIMER_MEMORY_CHUNK,
+	      timer_block);
+#endif
+
+  /*
+   * Slice the chunk up and put the future timer_entries in the free timer pool.
+   */
+  timer = timer_block;
+  for (timer_index = 0; timer_index < OLSR_TIMER_MEMORY_CHUNK; timer_index++) {
+
+    /* Insert new timers at the tail of the free_timer list */
+    list_add_before(&free_timer_list, &timer->timer_list);
+
+    /* 
+     * For performance reasons (read: frequent timer changes),
+     * precompute a random number once per timer and reuse later.
+     * The random number only gets recomputed if a periodical timer fires,
+     * such that a different jitter is applied for future firing.
+     */
+    timer->timer_random = random();
+
+    timer++;
+  }
+
+  /*
+   * There are now timers in the pool, recurse once.
+   */
+  return olsr_get_timer();
+}
+
+
+/**
+ * Init datastructures for maintaining timers.
+ */
+void
+olsr_init_timers(void)
+{
+  struct list_node *timer_head_node;
+  int index;
+
+  OLSR_PRINTF(5, "TIMER: init timers\n");
+
+  memset(timer_wheel, 0, sizeof(timer_wheel));
+
+  timer_head_node = timer_wheel;
+  for (index = 0; index < TIMER_WHEEL_SLOTS; index++) {
+    list_head_init(timer_head_node);
+    timer_head_node++;
+  }
+
+  /*
+   * Reset the last timer run.
+   */
+  timer_last_run = now_times;
+
+  /* Timer memory pooling */
+  list_head_init(&free_timer_list);
+  timers_running = 0;
+}
+
+/*
+ * olsr_get_next_list_entry
+ *
+ * Get the next list node in a hash bucket.
+ * The listnode of the timer in may be subject to getting removed from
+ * this timer bucket in olsr_change_timer() and olsr_stop_timer(), which
+ * means that we can miss our walking context.
+ * By caching the previous node we can figure out if the current node
+ * has been removed from the hash bucket and compute the next node.
+ */
+static struct list_node *
+olsr_get_next_list_entry (struct list_node **prev_node,
+                          struct list_node *current_node)
+{
+  if ((*prev_node)->next == current_node) {
+
+    /*
+     * No change in the list, normal traversal, update the previous node.
+     */
+    *prev_node = current_node;
+    return (current_node->next);
+  } else {
+
+    /*
+     * List change. Recompute the walking context.
+     */
+    return ((*prev_node)->next);
+  }
+}
+
+/**
+ * Walk through the timer list and check if any timer is ready to fire.
+ * Callback the provided function with the context pointer.
+ */
+void
+olsr_walk_timers(clock_t * last_run)
+{
+  static struct timer_entry *timer;
+  struct list_node *timer_head_node, *timer_walk_node, *timer_walk_prev_node;
+  unsigned int timers_walked, timers_fired;
+  unsigned int total_timers_walked, total_timers_fired;
+  unsigned int wheel_slot_walks = 0;
+
+  /*
+   * Check the required wheel slots since the last time a timer walk was invoked,
+   * or check *all* the wheel slots, whatever is less work.
+   * The latter is meant as a safety belt if the scheduler falls behind.
+   */
+  total_timers_walked = total_timers_fired = timers_walked = timers_fired = 0;
+  while ((*last_run <= now_times) && (wheel_slot_walks < TIMER_WHEEL_SLOTS)) {
+
+    /* keep some statistics */
+    total_timers_walked += timers_walked;
+    total_timers_fired += timers_fired;
+    timers_walked = 0;
+    timers_fired = 0;
+
+    /* Get the hash slot for this clocktick */
+    timer_head_node = &timer_wheel[*last_run & TIMER_WHEEL_MASK];
+    timer_walk_prev_node = timer_head_node;
+
+    /* Walk all entries hanging off this hash bucket */
+    for (timer_walk_node = timer_head_node->next;
+         timer_walk_node != timer_head_node; /* circular list */
+	 timer_walk_node = olsr_get_next_list_entry(&timer_walk_prev_node,
+                                                    timer_walk_node)) {
+
+      timer = list2timer(timer_walk_node);
+
+      timers_walked++;
+
+      /* Ready to fire ? */
+      if (TIMED_OUT(timer->timer_clock)) {
+
+	OLSR_PRINTF(3, "TIMER: fire %s timer %p, ctx %p, "
+		    "at clocktick %u (%s)\n",
+		    olsr_cookie_name(timer->timer_cookie),
+		    timer, timer->timer_cb_context,
+                    (unsigned int)*last_run,
+                    olsr_wallclock_string());
+
+	/* This timer is expired, call into the provided callback function */
+	timer->timer_cb(timer->timer_cb_context);
+
+	if (timer->timer_period) {
+
+	  /*
+	   * Don't restart the periodic timer if the callback function has
+	   * stopped the timer.
+	   */
+	  if (timer->timer_flags & OLSR_TIMER_RUNNING) {
+
+	    /* For periodical timers, rehash the random number and restart */
+	    timer->timer_random = random();
+	    olsr_change_timer(timer, timer->timer_period,
+			      timer->timer_jitter_pct, OLSR_TIMER_PERIODIC);
+	  }
+
+	} else {
+
+	  /*
+	   * Don't stop the singleshot timer if the callback function has
+	   * stopped the timer.
+	   */
+	  if (timer->timer_flags & OLSR_TIMER_RUNNING) {
+
+	    /* Singleshot timers are stopped and returned to the pool */
+	    olsr_stop_timer(timer);
+	  }
+	}
+
+	timers_fired++;
+      }
+    }
+
+    /* Increment the time slot and wheel slot walk iteration */
+    (*last_run)++;
+    wheel_slot_walks++;
+  }
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "TIMER: processed %4u/%u clockwheel slots, "
+	      "timers walked %4u/%u, timers fired %u\n",
+	      wheel_slot_walks, TIMER_WHEEL_SLOTS,
+	      total_timers_walked, timers_running, total_timers_fired);
+#endif
+
+  /*
+   * If the scheduler has slipped and we have walked all wheel slots,
+   * reset the last timer run.
+   */
+  *last_run = now_times;
+}
+
+/**
+ * Returns the difference between gmt and local time in seconds.
+ * Use gmtime() and localtime() to keep things simple.
+ * 
+ * taken and slightly modified from www.tcpdump.org.
+ */
+static int
+olsr_get_timezone(void)
+{
+#define OLSR_TIMEZONE_UNINITIALIZED -1
+
+  static int time_diff = OLSR_TIMEZONE_UNINITIALIZED;
+  int dir;
+  struct tm *gmt, *loc;
+  struct tm sgmt;
+  time_t t;
+
+  if (time_diff != OLSR_TIMEZONE_UNINITIALIZED) {
+    return time_diff;
+  }
+
+  t = time(NULL);
+  gmt = &sgmt;
+  *gmt = *gmtime(&t);
+  loc = localtime(&t);
+
+  time_diff = (loc->tm_hour - gmt->tm_hour) * 60 * 60
+    + (loc->tm_min - gmt->tm_min) * 60;
+
+  /*
+   * If the year or julian day is different, we span 00:00 GMT
+   * and must add or subtract a day. Check the year first to
+   * avoid problems when the julian day wraps.
+   */
+  dir = loc->tm_year - gmt->tm_year;
+  if (!dir) {
+    dir = loc->tm_yday - gmt->tm_yday;
+  }
+
+  time_diff += dir * 24 * 60 * 60;
+
+  return (time_diff);
+}
+
+/**
+ * Format an absolute wallclock system time string.
+ * May be called upto 4 times in a single printf() statement.
+ * Displays microsecond resolution.
+ *
+ * @return buffer to a formatted system time string.
+ */
+const char *
+olsr_wallclock_string(void)
+{
+  static char buf[4][sizeof("00:00:00.000000")];
+  static int idx = 0;
+  char *ret;
+  struct timeval now;
+  int sec, usec;
+
+  ret = buf[idx];
+  idx = (idx + 1) & 3;
+
+  gettimeofday(&now, NULL);
+
+  sec = (int)now.tv_sec + olsr_get_timezone();
+  usec = (int)now.tv_usec;
+
+  snprintf(ret, sizeof(buf)/4, "%02u:%02u:%02u.%06u",
+	   (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60, usec);
+
+  return ret;
+}
+
+
+/**
+ * Format an relative non-wallclock system time string.
+ * May be called upto 4 times in a single printf() statement.
+ * Displays millisecond resolution.
+ *
+ * @param absolute time expressed in clockticks
+ * @return buffer to a formatted system time string.
+ */
+const char *
+olsr_clock_string(clock_t clock)
+{
+  static char buf[4][sizeof("00:00:00.000")];
+  static int idx = 0;
+  char *ret;
+  unsigned int sec, msec;
+
+  ret = buf[idx];
+  idx = (idx + 1) & 3;
+
+  /* On most systems a clocktick is a 10ms quantity. */
+  msec = olsr_cnf->system_tick_divider * (unsigned int)(clock - now_times);
+  sec = msec / MSEC_PER_SEC;
+
+  snprintf(ret, sizeof(buf) / 4, "%02u:%02u:%02u.%03u",
+	   sec / 3600, (sec % 3600) / 60, (sec % 60), (msec % MSEC_PER_SEC));
+
+  return ret;
+}
+
+
+/**
+ * Start a new timer.
+ *
+ * @param relative time expressed in milliseconds
+ * @param jitter expressed in percent
+ * @param timer callback function
+ * @param context for the callback function
+ * @return a pointer to the created entry
+ */
+struct timer_entry *
+olsr_start_timer(unsigned int rel_time, olsr_u8_t jitter_pct,
+		 olsr_bool periodical, void (*timer_cb_function) (void *),
+		 void *context, olsr_cookie_t cookie)
+{
+  struct timer_entry *timer;
+
+  timer = olsr_get_timer();
+
+  /* Fill entry */
+  timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
+  timer->timer_cb = timer_cb_function;
+  timer->timer_cb_context = context;
+  timer->timer_jitter_pct = jitter_pct;
+  timer->timer_flags = OLSR_TIMER_RUNNING;
+
+  /* The cookie is used for debugging to traceback the originator */
+  timer->timer_cookie = cookie;
+  olsr_cookie_usage_incr(cookie);
+
+  /* Singleshot or periodical timer ? */
+  if (periodical) {
+    timer->timer_period = rel_time;
+  } else {
+    timer->timer_period = 0;
+  }
+
+  /*
+   * Now insert in the respective timer_wheel slot.
+   */
+  list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK],
+		  &timer->timer_list);
+  timers_running++;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "TIMER: start %s timer %p firing in %s, ctx %p\n",
+	      olsr_cookie_name(timer->timer_cookie),
+	      timer, olsr_clock_string(timer->timer_clock), context);
+#endif
+
+  return timer;
+}
+
+/**
+ * Delete a timer.
+ *
+ * @param the timer_entry that shall be removed
+ * @return nada
+ */
+void
+olsr_stop_timer(struct timer_entry *timer)
+{
+
+  /* sanity check */
+  if (!timer) {
+    return;
+  }
+#ifdef DEBUG
+  OLSR_PRINTF(3, "TIMER: stop %s timer %p, ctx %p\n",
+	      olsr_cookie_name(timer->timer_cookie),
+	      timer, timer->timer_cb_context);
+#endif
+
+  /*
+   * Carve out of the existing wheel_slot and return to the pool
+   * rather than freeing for later reycling.
+   */
+  list_remove(&timer->timer_list);
+  list_add_before(&free_timer_list, &timer->timer_list);
+  timer->timer_flags &= ~OLSR_TIMER_RUNNING;
+  olsr_cookie_usage_decr(timer->timer_cookie);
+  timers_running--;
+}
+
+
+/**
+ * Change a timer_entry.
+ *
+ * @param timer_entry to be changed.
+ * @param new relative time expressed in units of milliseconds.
+ * @param new jitter expressed in percent.
+ * @return nada
+ */
+void
+olsr_change_timer(struct timer_entry *timer, unsigned int rel_time,
+		  olsr_u8_t jitter_pct, olsr_bool periodical)
+{
+
+  /* Sanity check. */
+  if (!timer) {
+    return;
+  }
+
+  /* Singleshot or periodical timer ? */
+  if (periodical) {
+    timer->timer_period = rel_time;
+  } else {
+    timer->timer_period = 0;
+  }
+
+  timer->timer_clock = olsr_jitter(rel_time, jitter_pct, timer->timer_random);
+  timer->timer_jitter_pct = jitter_pct;
+
+  /*
+   * Changes are easy: Remove timer from the exisiting timer_wheel slot
+   * and reinsert into the new slot.
+   */
+  list_remove(&timer->timer_list);
+  list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK],
+		  &timer->timer_list);
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "TIMER: change %s timer %p, firing to %s, ctx %p\n",
+	      olsr_cookie_name(timer->timer_cookie), timer,
+	      olsr_clock_string(timer->timer_clock), timer->timer_cb_context);
+#endif
+}
+
+
+/*
+ * This is the one stop shop for all sort of timer manipulation.
+ * Depending on the paseed in parameters a new timer is started,
+ * or an existing timer is started or an existing timer is
+ * terminated.
+ */
+void
+olsr_set_timer(struct timer_entry **timer_ptr, unsigned int rel_time,
+	       olsr_u8_t jitter_pct, olsr_bool periodical,
+	       void (*timer_cb_function) (void *), void *context,
+	       olsr_cookie_t cookie)
+{
+
+  if (!*timer_ptr) {
+
+    /* No timer running, kick it. */
+    *timer_ptr = olsr_start_timer(rel_time, jitter_pct, periodical,
+				  timer_cb_function, context, cookie);
+  } else {
+
+    if (!rel_time) {
+
+      /* No good future time provided, kill it. */
+      olsr_stop_timer(*timer_ptr);
+      *timer_ptr = NULL;
+    } else {
+
+      /* Time is ok and timer is running, change it ! */
+      olsr_change_timer(*timer_ptr, rel_time, jitter_pct, periodical);
+    }
+  }
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/scheduler.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/scheduler.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/scheduler.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/scheduler.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,116 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * Timer rewrite (c) 2008, Hannes Gredler (hannes@gredler.at)
+ * 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 _OLSR_SCHEDULER
+#define _OLSR_SCHEDULER
+
+#include "common/list.h"
+
+#define TIMER_WHEEL_SLOTS 256
+#define TIMER_WHEEL_MASK (TIMER_WHEEL_SLOTS - 1)
+
+/* Some defs for juggling with timers */
+#define MSEC_PER_SEC 1000
+#define USEC_PER_SEC 1000000
+#define NSEC_PER_USEC 1000
+#define USEC_PER_MSEC 1000
+
+/*
+ * Our timer implementation is a based on individual timers arranged in
+ * a double linked list hanging of hash containers called a timer wheel slot.
+ * For every timer a timer_entry is created and attached to the timer wheel slot.
+ * When the timer fires, the timer_cb function is called with the
+ * context pointer.
+ * The implementation supports periodic and oneshot timers.
+ * For a periodic timer the timer_period field is set to non zero,
+ * which causes the timer to run forever until manually stopped.
+ */
+struct timer_entry {
+  struct list_node timer_list;	       /* memory pooling, or wheel membership */
+  clock_t timer_clock;		       /* when timer shall fire (absolute time) */
+  unsigned int timer_period;	       /* set for periodical timers (relative time) */
+  olsr_cookie_t timer_cookie;	       /* used for diag stuff */
+  olsr_u8_t timer_jitter_pct;	       /* the jitter expressed in percent */
+  olsr_u8_t timer_flags;	       /* misc flags */
+  unsigned int timer_random;	       /* cache random() result for performance reasons */
+  void (*timer_cb) (void *);	       /* callback function */
+  void *timer_cb_context;	       /* context pointer */
+};
+
+/* inline to recast from timer_list back to timer_entry */
+LISTNODE2STRUCT(list2timer, struct timer_entry, timer_list);
+
+#define OLSR_TIMER_ONESHOT    0	/* One shot timer */
+#define OLSR_TIMER_PERIODIC   1	/* Periodic timer */
+
+/* Timer flags */
+#define OLSR_TIMER_RUNNING  ( 1 << 0)	/* this timer is running */
+
+/* Memory pooling */
+#define OLSR_TIMER_MEMORY_CHUNK 100	/* timers per chunk */
+
+/* Timers */
+void olsr_init_timers(void);
+void olsr_walk_timers(clock_t *);
+void olsr_set_timer(struct timer_entry **, unsigned int, olsr_u8_t, olsr_bool,
+		    void (*)(void *), void *, olsr_cookie_t);
+struct timer_entry *olsr_start_timer(unsigned int, olsr_u8_t, olsr_bool,
+				     void (*)(void *), void *, olsr_cookie_t);
+void olsr_change_timer(struct timer_entry *, unsigned int, olsr_u8_t,
+		       olsr_bool);
+void olsr_stop_timer(struct timer_entry *);
+
+/* Printing timestamps */
+const char *olsr_clock_string(clock_t);
+const char *olsr_wallclock_string(void);
+
+/* Main scheduler loop */
+void olsr_scheduler(void) __attribute__ ((noreturn));
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/socket_parser.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/socket_parser.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/socket_parser.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/socket_parser.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,204 @@
+/*
+ * 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 <unistd.h>
+#include "socket_parser.h"
+#include "olsr.h"
+#include "defs.h"
+#include "log.h"
+#include "net_os.h"
+
+#ifdef WIN32
+#undef EINTR
+#define EINTR WSAEINTR
+#undef errno
+#define errno WSAGetLastError()
+#undef strerror
+#define strerror(x) StrError(x)
+#endif
+
+
+struct olsr_socket_entry *olsr_socket_entries;
+
+static int hfd = 0;
+
+/**
+ * Add a socket and handler to the socketset
+ * beeing used in the main select(2) loop
+ * in listen_loop
+ *
+ *@param fd the socket
+ *@param pf the processing function
+ */
+void
+add_olsr_socket(int fd, void(*pf)(int fd))
+{
+  struct olsr_socket_entry *new_entry;
+
+  if((fd == 0) || (pf == NULL))
+    {
+      fprintf(stderr, "Bogus socket entry - not registering...\n");
+      return;
+    }
+  OLSR_PRINTF(2, "Adding OLSR socket entry %d\n", fd);
+
+  new_entry = olsr_malloc(sizeof(struct olsr_socket_entry), "Socket entry");
+
+  new_entry->fd = fd;
+  new_entry->process_function = pf;
+
+  /* Queue */
+  new_entry->next = olsr_socket_entries;
+  olsr_socket_entries = new_entry;
+
+  if(fd + 1 > hfd)
+    hfd = fd + 1;
+}
+
+/**
+ * Remove a socket and handler to the socketset
+ * beeing used in the main select(2) loop
+ * in listen_loop
+ *
+ *@param fd the socket
+ *@param pf the processing function
+ */
+int
+remove_olsr_socket(int fd, void(*pf)(int))
+{
+  struct olsr_socket_entry *entry, *prev_entry;
+
+  if((fd == 0) || (pf == NULL))
+    {
+      olsr_syslog(OLSR_LOG_ERR, "Bogus socket entry - not processing...\n");
+      return 0;
+    }
+  OLSR_PRINTF(1, "Removing OLSR socket entry %d\n", fd);
+
+  entry = olsr_socket_entries;
+  prev_entry = NULL;
+
+  while(entry)
+    {
+      if((entry->fd == fd) && (entry->process_function == pf))
+	{
+	  if(prev_entry == NULL)
+	    {
+	      olsr_socket_entries = entry->next;
+	      free(entry);
+	    }
+	  else
+	    {
+	      prev_entry->next = entry->next;
+	      free(entry);
+	    }
+
+	  if(hfd == fd + 1)
+	    {
+	      /* Re-calculate highest FD */
+	      entry = olsr_socket_entries;
+	      hfd = 0;
+	      while(entry)
+		{
+		  if(entry->fd + 1 > hfd)
+		    hfd = entry->fd + 1;
+		  entry = entry->next;
+		}
+	    }
+	  return 1;
+	}
+      prev_entry = entry;
+      entry = entry->next;
+    }
+
+  return 0;
+}
+
+
+void
+olsr_poll_sockets(void)
+{
+  int n;
+  struct olsr_socket_entry *olsr_sockets;
+  fd_set ibits;
+  struct timeval tvp = {0, 0};
+
+
+  /* If there are no registered sockets we
+   * do not call select(2)
+   */
+  if(hfd == 0)
+    return;
+  
+  FD_ZERO(&ibits);
+  
+  /* Adding file-descriptors to FD set */
+  
+  for(olsr_sockets = olsr_socket_entries; olsr_sockets; olsr_sockets = olsr_sockets->next)
+    {
+      FD_SET((unsigned int)olsr_sockets->fd, &ibits); /* And we cast here since we get a warning on Win32 */    
+    }
+      
+  /* Runnig select on the FD set */
+  n = olsr_select(hfd, &ibits, NULL, NULL, &tvp);
+  
+  if(n == 0)
+    return;
+  /* Did somethig go wrong? */
+  if (n < 0) 
+    {
+      if(errno != EINTR) {
+        const char * const err_msg = strerror(errno);
+        olsr_syslog(OLSR_LOG_ERR, "select: %s", err_msg);
+        OLSR_PRINTF(1, "Error select: %s", err_msg);
+      }
+      return;
+    }
+
+  /* Update time since this is much used by the parsing functions */
+  now_times = olsr_times();
+
+  for(olsr_sockets = olsr_socket_entries;olsr_sockets;olsr_sockets = olsr_sockets->next)
+    {
+      if(FD_ISSET(olsr_sockets->fd, &ibits))
+	  olsr_sockets->process_function(olsr_sockets->fd);
+    }  	
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/socket_parser.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/socket_parser.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/socket_parser.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/socket_parser.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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 _OLSR_SOCKET_PARSER
+#define _OLSR_SOCKET_PARSER
+
+
+struct olsr_socket_entry
+{
+  int fd;
+  int arp_type;
+  void(*process_function)(int fd);
+  struct olsr_socket_entry *next;
+};
+
+extern struct olsr_socket_entry *olsr_socket_entries;
+void olsr_poll_sockets(void);
+
+void add_olsr_socket(int, void(*)(int));
+int remove_olsr_socket(int, void(*)(int));
+void listen_loop(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/tc_set.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/tc_set.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/tc_set.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/tc_set.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,971 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * LSDB rewrite (c) 2007, Hannes Gredler (hannes@gredler.at)
+ * 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 "tc_set.h"
+#include "ipcalc.h"
+#include "mid_set.h"
+#include "link_set.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "olsr_spf.h"
+#include "common/avl.h"
+#include "lq_packet.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
+#include "olsr_cookie.h"
+
+#include <assert.h>
+
+/* Root of the link state database */
+struct avl_tree tc_tree;
+struct tc_entry *tc_myself;	       /* Shortcut to ourselves */
+
+/* Some cookies for stats keeping */
+struct olsr_cookie_info *tc_edge_gc_timer_cookie = NULL;
+struct olsr_cookie_info *tc_validity_timer_cookie = NULL;
+struct olsr_cookie_info *tc_edge_mem_cookie = NULL;
+struct olsr_cookie_info *tc_mem_cookie = NULL;
+
+/*
+ * Sven-Ola 2007-Dec: These four constants include an assumption
+ * on how long a typical olsrd mesh memorizes (TC) messages in the
+ * RAM of all nodes and how many neighbour changes between TC msgs.
+ * In Berlin, we encounter hop values up to 70 which means that
+ * messages may live up to ~15 minutes cycling between nodes and
+ * obviously breaking out of the timeout_dup() jail. It may be more
+ * correct to dynamically adapt those constants, e.g. by using the
+ * max hop number (denotes size-of-mesh) in some form or maybe
+ * a factor indicating how many (old) versions of olsrd are on.
+ */
+
+/* Value window for ansn, identifies old messages to be ignored */
+#define TC_ANSN_WINDOW 256
+
+/* Value window for seqno, identifies old messages to be ignored */
+#define TC_SEQNO_WINDOW 1024
+
+/* Enlarges the value window for upcoming ansn/seqno to be accepted */
+#define TC_ANSN_WINDOW_MULT 4
+
+/* Enlarges the value window for upcoming ansn/seqno to be accepted */
+#define TC_SEQNO_WINDOW_MULT 8
+
+static olsr_bool
+olsr_seq_inrange_low(int beg, int end, olsr_u16_t seq)
+{
+  if (beg < 0) {
+    if (seq >= (olsr_u16_t) beg || seq < end) {
+      return OLSR_TRUE;
+    }
+  } else if (end >= 0x10000) {
+    if (seq >= beg || seq < (olsr_u16_t) end) {
+      return OLSR_TRUE;
+    }
+  } else if (seq >= beg && seq < end) {
+    return OLSR_TRUE;
+  }
+  return OLSR_FALSE;
+}
+
+static olsr_bool
+olsr_seq_inrange_high(int beg, int end, olsr_u16_t seq)
+{
+  if (beg < 0) {
+    if (seq > (olsr_u16_t) beg || seq <= end) {
+      return OLSR_TRUE;
+    }
+  } else if (end >= 0x10000) {
+    if (seq > beg || seq <= (olsr_u16_t) end) {
+      return OLSR_TRUE;
+    }
+  } else if (seq > beg && seq <= end) {
+    return OLSR_TRUE;
+  }
+  return OLSR_FALSE;
+}
+
+/**
+ * Add a new tc_entry to the tc tree
+ *
+ * @param (last)adr address of the entry
+ * @return a pointer to the created entry
+ */
+static struct tc_entry *
+olsr_add_tc_entry(union olsr_ip_addr *adr)
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  struct tc_entry *tc;
+
+  /*
+   * Safety net against loss of the last main IP address.
+   */
+  if (ipequal(&olsr_cnf->main_addr, &all_zero)) {
+    return NULL;
+  }
+
+#ifdef DEBUG
+  OLSR_PRINTF(1, "TC: add entry %s\n", olsr_ip_to_string(&buf, adr));
+#endif
+
+  tc = olsr_cookie_malloc(tc_mem_cookie);
+  if (!tc) {
+    return NULL;
+  }
+
+  /* Fill entry */
+  tc->addr = *adr;
+  tc->vertex_node.key = &tc->addr;
+
+  /*
+   * Insert into the global tc tree.
+   */
+  avl_insert(&tc_tree, &tc->vertex_node, AVL_DUP_NO);
+  olsr_lock_tc_entry(tc);
+
+  /*
+   * Initialize subtrees for edges and prefixes.
+   */
+  avl_init(&tc->edge_tree, avl_comp_default);
+  avl_init(&tc->prefix_tree, avl_comp_prefix_default);
+
+  /*
+   * Add a rt_path for ourselves.
+   */
+  olsr_insert_routing_table(adr, olsr_cnf->maxplen, adr, OLSR_RT_ORIGIN_INT);
+
+  return tc;
+}
+
+/**
+ * Initialize the topology set
+ *
+ */
+void
+olsr_init_tc(void)
+{
+  OLSR_PRINTF(5, "TC: init topo\n");
+
+  avl_init(&tc_tree, avl_comp_default);
+
+  /*
+   * Get some cookies for getting stats to ease troubleshooting.
+   */
+  tc_edge_gc_timer_cookie =
+    olsr_alloc_cookie("TC edge GC", OLSR_COOKIE_TYPE_TIMER);
+  tc_validity_timer_cookie =
+    olsr_alloc_cookie("TC validity", OLSR_COOKIE_TYPE_TIMER);
+
+  tc_edge_mem_cookie =
+    olsr_alloc_cookie("tc_edge_entry", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(tc_edge_mem_cookie,
+			      sizeof(struct tc_edge_entry) +
+			      active_lq_handler->tc_lq_size);
+
+  tc_mem_cookie = olsr_alloc_cookie("tc_entry", OLSR_COOKIE_TYPE_MEMORY);
+  olsr_cookie_set_memory_size(tc_mem_cookie, sizeof(struct tc_entry));
+
+  /*
+   * Add a TC entry for ourselves.
+   */
+  tc_myself = olsr_add_tc_entry(&olsr_cnf->main_addr);
+}
+
+/**
+ * The main ip address has changed.
+ * Do the needful.
+ */
+void
+olsr_change_myself_tc(void)
+{
+  if (tc_myself) {
+
+    /*
+     * Check if there was a change.
+     */
+    if (ipequal(&tc_myself->addr, &olsr_cnf->main_addr)) {
+      return;
+    }
+
+    /*
+     * Flush our own tc_entry.
+     */
+    olsr_delete_tc_entry(tc_myself);
+  }
+
+  /*
+   * The old entry for ourselves is gone, generate a new one and trigger SPF.
+   */
+  tc_myself = olsr_add_tc_entry(&olsr_cnf->main_addr);
+  changes_topology = OLSR_TRUE;
+}
+
+/*
+ * Increment the reference counter.
+ */
+void
+olsr_lock_tc_entry(struct tc_entry *tc)
+{
+  tc->refcount++;
+}
+
+/*
+ * Unlock and free a tc_entry once all references are gone.
+ */
+void
+olsr_unlock_tc_entry(struct tc_entry *tc)
+{
+  if (--tc->refcount) {
+    return;
+  }
+
+  /*
+   * All references are gone.
+   */
+  olsr_cookie_free(tc_mem_cookie, tc);
+}
+
+/**
+ * Delete a TC entry.
+ *
+ * @param entry the TC entry to delete
+ *
+ */
+void
+olsr_delete_tc_entry(struct tc_entry *tc)
+{
+  struct tc_edge_entry *tc_edge;
+  struct rt_path *rtp;
+#if 0
+  struct ipaddr_str buf;
+  OLSR_PRINTF(1, "TC: del entry %s\n", olsr_ip_to_string(&buf, &tc->addr));
+#endif
+
+  /*
+   * Delete the rt_path for ourselves.
+   */
+  olsr_delete_routing_table(&tc->addr, olsr_cnf->maxplen, &tc->addr);
+
+  /* The edgetree and prefix tree must be empty before */
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+    olsr_delete_tc_edge_entry(tc_edge);
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+
+  OLSR_FOR_ALL_PREFIX_ENTRIES(tc, rtp) {
+    olsr_delete_rt_path(rtp);
+  } OLSR_FOR_ALL_PREFIX_ENTRIES_END(tc, rtp);
+
+  /* Stop running timers */
+  olsr_stop_timer(tc->edge_gc_timer);
+  tc->edge_gc_timer = NULL;
+  olsr_stop_timer(tc->validity_timer);
+  tc->validity_timer = NULL;
+
+  avl_delete(&tc_tree, &tc->vertex_node);
+  olsr_unlock_tc_entry(tc);
+}
+
+/**
+ * Look up a entry from the TC tree based on address
+ *
+ * @param adr the address to look for
+ * @return the entry found or NULL
+ */
+struct tc_entry *
+olsr_lookup_tc_entry(union olsr_ip_addr *adr)
+{
+  struct avl_node *node;
+
+#if 0
+  OLSR_PRINTF(1, "TC: lookup entry\n");
+#endif
+
+  node = avl_find(&tc_tree, adr);
+
+  return (node ? vertex_tree2tc(node) : NULL);
+}
+
+/*
+ * Lookup a tc entry. Creates one if it does not exist yet.
+ */
+struct tc_entry *
+olsr_locate_tc_entry(union olsr_ip_addr *adr)
+{
+  struct tc_entry *tc;
+
+  if (!(tc = olsr_lookup_tc_entry(adr))) {
+    return olsr_add_tc_entry(adr);
+  }
+  return tc;
+}
+
+/**
+ * Format tc_edge contents into a buffer.
+ */
+char *
+olsr_tc_edge_to_string(struct tc_edge_entry *tc_edge)
+{
+  static char buf[128];
+  struct ipaddr_str addrbuf, dstbuf;
+  struct tc_entry *tc = tc_edge->tc;
+  struct lqtextbuffer lqbuffer1, lqbuffer2;
+
+  snprintf(buf, sizeof(buf),
+	   "%s > %s, cost (%6s) %s",
+	   olsr_ip_to_string(&addrbuf, &tc->addr),
+	   olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
+	   get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1),
+	   get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2));
+
+  return buf;
+}
+
+/**
+ * Wrapper for the timer callback.
+ * A TC entry has not been refreshed in time.
+ * Remove it from the link-state database.
+ */
+static void
+olsr_expire_tc_entry(void *context)
+{
+  struct tc_entry *tc;
+
+  tc = (struct tc_entry *)context;
+  tc->validity_timer = NULL;
+
+  olsr_delete_tc_entry(tc);
+  changes_topology = OLSR_TRUE;
+}
+
+/**
+ * Wrapper for the timer callback.
+ * Does the garbage collection of older ansn entries after no edge addition to
+ * the TC entry has happened for OLSR_TC_EDGE_GC_TIME.
+ */
+static void
+olsr_expire_tc_edge_gc(void *context)
+{
+  struct tc_entry *tc;
+
+  tc = (struct tc_entry *)context;
+  tc->edge_gc_timer = NULL;
+
+  if (olsr_delete_outdated_tc_edges(tc)) {
+    changes_topology = OLSR_TRUE;
+  }
+}
+
+/*
+ * If the edge does not have a minimum acceptable link quality
+ * set the etx cost to infinity such that it gets ignored during
+ * SPF calculation.
+ * 
+ * @return 1 if the change of the etx value was relevant
+ */
+olsr_bool
+olsr_calc_tc_edge_entry_etx(struct tc_edge_entry *tc_edge)
+{
+  olsr_linkcost old;
+
+  /*
+   * Some sanity check before recalculating the etx.
+   */
+  if (olsr_cnf->lq_level < 1) {
+    return 0;
+  }
+
+  old = tc_edge->cost;
+  tc_edge->cost = olsr_calc_tc_cost(tc_edge);
+
+  return olsr_is_relevant_costchange(old, tc_edge->cost);
+}
+
+/**
+ * Add a new tc_edge_entry to the tc_edge_tree
+ *
+ * @param (last)adr address of the entry
+ * @return a pointer to the created entry
+ */
+struct tc_edge_entry *
+olsr_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr,
+		       olsr_u16_t ansn)
+{
+#ifdef DEBUG
+  struct ipaddr_str buf;
+#endif
+  struct tc_entry *tc_neighbor;
+  struct tc_edge_entry *tc_edge, *tc_edge_inv;
+
+  tc_edge = olsr_cookie_malloc(tc_edge_mem_cookie);
+  if (!tc_edge) {
+    return NULL;
+  }
+
+  /* Fill entry */
+  tc_edge->T_dest_addr = *addr;
+  tc_edge->ansn = ansn;
+  tc_edge->edge_node.key = &tc_edge->T_dest_addr;
+
+  /*
+   * Insert into the edge tree.
+   */
+  avl_insert(&tc->edge_tree, &tc_edge->edge_node, AVL_DUP_NO);
+  olsr_lock_tc_entry(tc);
+
+  /*
+   * Connect backpointer.
+   */
+  tc_edge->tc = tc;
+
+  /*
+   * Check if the neighboring router and the inverse edge is in the lsdb.
+   * Create short cuts to the inverse edge for faster SPF execution.
+   */
+  tc_neighbor = olsr_lookup_tc_entry(&tc_edge->T_dest_addr);
+  if (tc_neighbor) {
+#ifdef DEBUG
+    OLSR_PRINTF(1, "TC:   found neighbor tc_entry %s\n",
+		olsr_ip_to_string(&buf, &tc_neighbor->addr));
+#endif
+
+    tc_edge_inv = olsr_lookup_tc_edge(tc_neighbor, &tc->addr);
+    if (tc_edge_inv) {
+#ifdef DEBUG
+      OLSR_PRINTF(1, "TC:   found inverse edge for %s\n",
+		  olsr_ip_to_string(&buf, &tc_edge_inv->T_dest_addr));
+#endif
+
+      /*
+       * Connect the edges mutually.
+       */
+      tc_edge_inv->edge_inv = tc_edge;
+      tc_edge->edge_inv = tc_edge_inv;
+
+    }
+  }
+
+  /*
+   * Update the etx.
+   */
+  olsr_calc_tc_edge_entry_etx(tc_edge);
+
+#ifdef DEBUG
+  OLSR_PRINTF(1, "TC: add edge entry %s\n", olsr_tc_edge_to_string(tc_edge));
+#endif
+
+  return tc_edge;
+}
+
+/**
+ * Delete a TC edge entry.
+ *
+ * @param tc the TC entry
+ * @param tc_edge the TC edge entry
+ */
+void
+olsr_delete_tc_edge_entry(struct tc_edge_entry *tc_edge)
+{
+  struct tc_entry *tc;
+  struct tc_edge_entry *tc_edge_inv;
+
+#ifdef DEBUG
+  OLSR_PRINTF(1, "TC: del edge entry %s\n", olsr_tc_edge_to_string(tc_edge));
+#endif
+
+  tc = tc_edge->tc;
+  avl_delete(&tc->edge_tree, &tc_edge->edge_node);
+  olsr_unlock_tc_entry(tc);
+
+  /*
+   * Clear the backpointer of our inverse edge.
+   */
+  tc_edge_inv = tc_edge->edge_inv;
+  if (tc_edge_inv) {
+    tc_edge_inv->edge_inv = NULL;
+  }
+
+  olsr_cookie_free(tc_edge_mem_cookie, tc_edge);
+}
+
+/**
+ * Delete all destinations that have a lower ANSN.
+ *
+ * @param tc the entry to delete edges from
+ * @return TRUE if any destinations were deleted, FALSE if not
+ */
+olsr_bool
+olsr_delete_outdated_tc_edges(struct tc_entry *tc)
+{
+  struct tc_edge_entry *tc_edge;
+  olsr_bool retval = OLSR_FALSE;
+
+#if 0
+  OLSR_PRINTF(5, "TC: deleting outdated TC-edge entries\n");
+#endif
+
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+    if (SEQNO_GREATER_THAN(tc->ansn, tc_edge->ansn)) {
+      olsr_delete_tc_edge_entry(tc_edge);
+      retval = OLSR_TRUE;
+    }
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+
+  return retval;
+}
+
+/**
+ * Delete all destinations that are inside the borders but
+ * not updated in the last tc.
+ *
+ * @param tc the entry to delete edges from
+ * @param ansn the advertised neighbor set sequence number
+ * @return 1 if any destinations were deleted 0 if not
+ */
+static int
+olsr_delete_revoked_tc_edges(struct tc_entry *tc, olsr_u16_t ansn,
+			     union olsr_ip_addr *lower_border,
+			     union olsr_ip_addr *upper_border)
+{
+  struct tc_edge_entry *tc_edge;
+  int retval = 0;
+
+#if 0
+  OLSR_PRINTF(5, "TC: deleting MPRS\n");
+#endif
+
+  olsr_bool passedLowerBorder = OLSR_FALSE;
+
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+    if (!passedLowerBorder) {
+      if (avl_comp_default(lower_border, &tc_edge->T_dest_addr) <= 0) {
+	passedLowerBorder = OLSR_TRUE;
+      } else {
+	continue;
+      }
+    }
+
+    if (passedLowerBorder) {
+      if (avl_comp_default(upper_border, &tc_edge->T_dest_addr) <= 0) {
+	break;
+      }
+    }
+
+    if (SEQNO_GREATER_THAN(ansn, tc_edge->ansn)) {
+      olsr_delete_tc_edge_entry(tc_edge);
+      retval = 1;
+    }
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+
+  return retval;
+}
+
+
+/**
+ * Update an edge registered on an entry.
+ * Creates new edge-entries if not registered.
+ * Bases update on a received TC message
+ *
+ * @param entry the TC entry to check
+ * @pkt the TC edge entry in the packet
+ * @return 1 if entries are added 0 if not
+ */
+static int
+olsr_tc_update_edge(struct tc_entry *tc, olsr_u16_t ansn,
+		    const unsigned char **curr, union olsr_ip_addr *neighbor)
+{
+  struct tc_edge_entry *tc_edge;
+  int edge_change;
+
+  edge_change = 0;
+
+  /*
+   * Fetch the per-edge data
+   */
+  pkt_get_ipaddress(curr, neighbor);
+
+  /* First check if we know this edge */
+  tc_edge = olsr_lookup_tc_edge(tc, neighbor);
+
+  if (!tc_edge) {
+
+    /*
+     * Yet unknown - create it.
+     * Check if the address is allowed.
+     */
+    if (!olsr_validate_address(neighbor)) {
+      return 0;
+    }
+
+    tc_edge = olsr_add_tc_edge_entry(tc, neighbor, ansn);
+
+    olsr_deserialize_tc_lq_pair(curr, tc_edge);
+    edge_change = 1;
+
+  } else {
+
+    /*
+     * We know this edge - Update entry.
+     */
+    tc_edge->ansn = ansn;
+
+    /*
+     * Update link quality if configured.
+     */
+    if (olsr_cnf->lq_level > 0) {
+      olsr_deserialize_tc_lq_pair(curr, tc_edge);
+    }
+
+    /*
+     * Update the etx.
+     */
+    if (olsr_calc_tc_edge_entry_etx(tc_edge)) {
+      if (tc->msg_hops <= olsr_cnf->lq_dlimit) {
+	edge_change = 1;
+      }
+    }
+#if DEBUG
+    if (edge_change) {
+      OLSR_PRINTF(1, "TC:   chg edge entry %s\n",
+		  olsr_tc_edge_to_string(tc_edge));
+    }
+#endif
+
+  }
+
+  return edge_change;
+}
+
+/**
+ * Lookup an edge hanging off a TC entry.
+ *
+ * @param entry the entry to check
+ * @param dst_addr the destination address to check for
+ * @return a pointer to the tc_edge found - or NULL
+ */
+struct tc_edge_entry *
+olsr_lookup_tc_edge(struct tc_entry *tc, union olsr_ip_addr *edge_addr)
+{
+  struct avl_node *edge_node;
+
+#if 0
+  OLSR_PRINTF(1, "TC: lookup dst\n");
+#endif
+
+  edge_node = avl_find(&tc->edge_tree, edge_addr);
+
+  return (edge_node ? edge_tree2tc_edge(edge_node) : NULL);
+}
+
+/**
+ * Print the topology table to stdout
+ */
+void
+olsr_print_tc_table(void)
+{
+#ifndef NODEBUG
+  /* The whole function makes no sense without it. */
+  struct tc_entry *tc;
+  const int ipwidth = olsr_cnf->ip_version == AF_INET ? 15 : 30;
+
+  OLSR_PRINTF(1,
+	      "\n--- %s ------------------------------------------------- TOPOLOGY\n\n"
+	      "%-*s %-*s %-14s  %s\n", olsr_wallclock_string(), ipwidth,
+	      "Source IP addr", ipwidth, "Dest IP addr", "      LQ      ",
+	      "ETX");
+
+  OLSR_FOR_ALL_TC_ENTRIES(tc) {
+    struct tc_edge_entry *tc_edge;
+    OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
+      struct ipaddr_str addrbuf, dstaddrbuf;
+      struct lqtextbuffer lqbuffer1, lqbuffer2;
+
+      OLSR_PRINTF(1, "%-*s %-*s %-14s %s\n",
+		  ipwidth, olsr_ip_to_string(&addrbuf, &tc->addr),
+		  ipwidth, olsr_ip_to_string(&dstaddrbuf,
+					     &tc_edge->T_dest_addr),
+		  get_tc_edge_entry_text(tc_edge, '/', &lqbuffer1),
+		  get_linkcost_text(tc_edge->cost, OLSR_FALSE, &lqbuffer2));
+
+    } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
+  } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
+#endif
+}
+
+/*
+ * calculate the border IPs of a tc edge set according to the border flags
+ *
+ * @param lower border flag
+ * @param pointer to lower border ip
+ * @param upper border flag
+ * @param pointer to upper border ip
+ * @result 1 if lower/upper border ip have been set 
+ */
+static int
+olsr_calculate_tc_border(olsr_u8_t lower_border,
+			 union olsr_ip_addr *lower_border_ip,
+			 olsr_u8_t upper_border,
+			 union olsr_ip_addr *upper_border_ip)
+{
+  if (lower_border == 0 && upper_border == 0) {
+    return 0;
+  }
+  if (lower_border == 0xff) {
+    memset(&lower_border_ip, 0, sizeof(lower_border_ip));
+  } else {
+    int i;
+
+    lower_border--;
+    for (i = 0; i < lower_border / 8; i++) {
+		lower_border_ip->v6.s6_addr[olsr_cnf->ipsize - i - 1] = 0;
+    }
+    lower_border_ip->v6.s6_addr[olsr_cnf->ipsize - lower_border / 8 -
+				       1] &= (0xff << (lower_border & 7));
+    lower_border_ip->v6.s6_addr[olsr_cnf->ipsize - lower_border / 8 -
+				       1] |= (1 << (lower_border & 7));
+  }
+
+  if (upper_border == 0xff) {
+    memset(&upper_border_ip, 0xff, sizeof(upper_border_ip));
+  } else {
+    int i;
+
+    upper_border--;
+
+    for (i = 0; i < upper_border / 8; i++) {
+		upper_border_ip->v6.s6_addr[olsr_cnf->ipsize - i - 1] = 0;
+    }
+    upper_border_ip->v6.s6_addr[olsr_cnf->ipsize - upper_border / 8 -
+				       1] &= (0xff << (upper_border & 7));
+    upper_border_ip->v6.s6_addr[olsr_cnf->ipsize - upper_border / 8 -
+				       1] |= (1 << (upper_border & 7));
+  }
+  return 1;
+}
+
+/*
+ * Process an incoming TC or TC_LQ message.
+ *
+ * If the message is interesting enough, update our edges for it,
+ * trigger SPF and finally flood it to all our 2way neighbors.
+ *
+ * The order for extracting data off the message does matter, 
+ * as every call to pkt_get increases the packet offset and
+ * hence the spot we are looking at.
+ */
+void
+olsr_input_tc(union olsr_message *msg,
+	      struct interface *input_if __attribute__ ((unused)),
+	      union olsr_ip_addr *from_addr)
+{
+  struct ipaddr_str buf;
+  olsr_u16_t size, msg_seq, ansn;
+  olsr_u8_t type, ttl, msg_hops, lower_border, upper_border;
+  olsr_reltime vtime;
+  union olsr_ip_addr originator;
+  const unsigned char *limit, *curr;
+  struct tc_entry *tc;
+
+  union olsr_ip_addr lower_border_ip, upper_border_ip;
+  int borderSet = 0;
+
+  curr = (void *)msg;
+  if (!msg) {
+    return;
+  }
+
+  /* We are only interested in TC message types. */
+  pkt_get_u8(&curr, &type);
+  if ((type != LQ_TC_MESSAGE) && (type != TC_MESSAGE)) {
+    return;
+  }
+
+  pkt_get_reltime(&curr, &vtime);
+  pkt_get_u16(&curr, &size);
+
+  pkt_get_ipaddress(&curr, &originator);
+
+  /* Copy header values */
+  pkt_get_u8(&curr, &ttl);
+  pkt_get_u8(&curr, &msg_hops);
+  pkt_get_u16(&curr, &msg_seq);
+  pkt_get_u16(&curr, &ansn);
+
+  /* Get borders */
+  pkt_get_u8(&curr, &lower_border);
+  pkt_get_u8(&curr, &upper_border);
+
+  tc = olsr_lookup_tc_entry(&originator);
+
+  if (tc && 0 != tc->edge_tree.count) {
+    if (olsr_seq_inrange_high((int)tc->msg_seq - TC_SEQNO_WINDOW,
+			      tc->msg_seq,
+			      msg_seq) &&
+	olsr_seq_inrange_high((int)tc->ansn - TC_ANSN_WINDOW, tc->ansn, ansn)) {
+
+      /*
+       * Ignore already seen seq/ansn values (small window for mesh memory)
+       */
+      if ((tc->msg_seq == msg_seq) || (tc->ignored++ < 32)) {
+	return;
+      }
+
+      OLSR_PRINTF(1, "Ignored to much LQTC's for %s, restarting\n",
+		  olsr_ip_to_string(&buf, &originator));
+
+    } else
+      if (!olsr_seq_inrange_high
+	  (tc->msg_seq,
+	   (int)tc->msg_seq + TC_SEQNO_WINDOW * TC_SEQNO_WINDOW_MULT, msg_seq)
+	  || !olsr_seq_inrange_low(tc->ansn,
+				   (int)tc->ansn +
+				   TC_ANSN_WINDOW * TC_ANSN_WINDOW_MULT,
+				   ansn)) {
+
+      /*
+       * Only accept future seq/ansn values (large window for node reconnects).
+       * Restart in all other cases. Ignore a single stray message.
+       */
+      if (!tc->err_seq_valid) {
+	tc->err_seq = msg_seq;
+	tc->err_seq_valid = OLSR_TRUE;
+      }
+      if (tc->err_seq == msg_seq) {
+	return;
+      }
+
+      OLSR_PRINTF(2, "Detected node restart for %s\n",
+		  olsr_ip_to_string(&buf, &originator));
+    }
+  }
+
+  /*
+   * Generate a new tc_entry in the lsdb and store the sequence number.
+   */
+  if (!tc) {
+    tc = olsr_add_tc_entry(&originator);
+  }
+
+  /*
+   * Update the tc entry.
+   */
+  tc->msg_hops = msg_hops;
+  tc->msg_seq = msg_seq;
+  tc->ansn = ansn;
+  tc->ignored = 0;
+  tc->err_seq_valid = OLSR_FALSE;
+
+  /*
+   * If the sender interface (NB: not originator) of this message
+   * is not in the symmetric 1-hop neighborhood of this node, the
+   * message MUST be discarded.
+   */
+  if (check_neighbor_link(from_addr) != SYM_LINK) {
+    OLSR_PRINTF(2, "Received TC from NON SYM neighbor %s\n",
+		olsr_ip_to_string(&buf, from_addr));
+    return;
+  }
+
+  OLSR_PRINTF(1, "Processing TC from %s, seq 0x%04x\n",
+	      olsr_ip_to_string(&buf, &originator), tc->msg_seq);
+
+  /*
+   * Now walk the edge advertisements contained in the packet.
+   */
+
+  limit = (unsigned char *)msg + size;
+  borderSet = 0;
+  while (curr < limit) {
+    if (olsr_tc_update_edge(tc, ansn, &curr, &upper_border_ip)) {
+      changes_topology = OLSR_TRUE;
+    }
+
+    if (!borderSet) {
+      borderSet = 1;
+      memcpy(&lower_border_ip, &upper_border_ip, sizeof(lower_border_ip));
+    }
+  }
+
+  /*
+   * Calculate real border IPs.
+   */
+  if (borderSet) {
+    borderSet = olsr_calculate_tc_border(lower_border, &lower_border_ip,
+					 upper_border, &upper_border_ip);
+  }
+
+  /*
+   * Set or change the expiration timer accordingly.
+   */
+  olsr_set_timer(&tc->validity_timer, vtime,
+		 OLSR_TC_VTIME_JITTER, OLSR_TIMER_ONESHOT,
+		 &olsr_expire_tc_entry, tc, tc_validity_timer_cookie->ci_id);
+
+  if (borderSet) {
+
+    /*
+     * Delete all old tc edges within borders.
+     */
+    olsr_delete_revoked_tc_edges(tc, ansn, &lower_border_ip, &upper_border_ip);
+  } else {
+
+    /*
+     * Kick the the edge garbage collection timer. In the meantime hopefully
+     * all edges belonging to a multipart neighbor set will arrive.
+     */
+    olsr_set_timer(&tc->edge_gc_timer, OLSR_TC_EDGE_GC_TIME,
+		   OLSR_TC_EDGE_GC_JITTER, OLSR_TIMER_ONESHOT,
+		   &olsr_expire_tc_edge_gc, tc, tc_edge_gc_timer_cookie->ci_id);
+  }
+
+  /*
+   * Last, flood the message to our other neighbors.
+   */
+  olsr_forward_message(msg, from_addr);
+  return;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/tc_set.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/tc_set.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/tc_set.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/tc_set.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,179 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas TÃ¸nnesen(andreto@olsr.org)
+ * LSDB rewrite (c) 2007, Hannes Gredler (hannes@gredler.at)
+ * 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 _OLSR_TOP_SET
+#define _OLSR_TOP_SET
+
+#include "defs.h"
+#include "packet.h"
+#include "common/avl.h"
+#include "common/list.h"
+#include "scheduler.h"
+
+/*
+ * This file holds the definitions for the link state database.
+ * The lsdb consists of nodes and edges.
+ * During input parsing all nodes and edges are extracted and synthesized.
+ * The SPF calculation operates on these datasets.
+ */
+
+struct tc_edge_entry {
+  struct avl_node edge_node;	       /* edge_tree node in tc_entry */
+  union olsr_ip_addr T_dest_addr;      /* edge_node key */
+  struct tc_edge_entry *edge_inv;      /* shortcut, used during SPF calculation */
+  struct tc_entry *tc;		       /* backpointer to owning tc entry */
+  olsr_linkcost cost;		       /* metric used for SPF calculation */
+  olsr_u16_t ansn;		       /* ansn of this edge, used for multipart msgs */
+  olsr_u32_t linkquality[0];
+};
+
+AVLNODE2STRUCT(edge_tree2tc_edge, struct tc_edge_entry, edge_node);
+
+struct tc_entry {
+  struct avl_node vertex_node;	       /* node keyed by ip address */
+  union olsr_ip_addr addr;	       /* vertex_node key */
+  struct avl_node cand_tree_node;      /* SPF candidate heap, node keyed by path_etx */
+  olsr_linkcost path_cost;	       /* SPF calculated distance, cand_tree_node key */
+  struct list_node path_list_node;     /* SPF result list */
+  struct avl_tree edge_tree;	       /* subtree for edges */
+  struct avl_tree prefix_tree;	       /* subtree for prefixes */
+  struct link_entry *next_hop;	       /* SPF calculated link to the 1st hop neighbor */
+  struct timer_entry *edge_gc_timer;   /* used for edge garbage collection */
+  struct timer_entry *validity_timer;  /* tc validity time */
+  olsr_u32_t refcount;		       /* reference counter */
+  olsr_u16_t msg_seq;		       /* sequence number of the tc message */
+  olsr_u8_t msg_hops;		       /* hopcount as per the tc message */
+  olsr_u8_t hops;		       /* SPF calculated hopcount */
+  olsr_u16_t ansn;		       /* ANSN number of the tc message */
+  olsr_u16_t ignored;		       /* how many TC messages ignored in a sequence
+                                          (kindof emergency brake) */
+  olsr_u16_t err_seq;		       /* sequence number of an unplausible TC */
+  olsr_bool err_seq_valid;	       /* do we have an error (unplauible seq/ansn) */
+};
+
+/*
+ * Garbage collection time for edges.
+ * This is used for multipart messages.
+ */
+#define OLSR_TC_EDGE_GC_TIME (2*1000)	/* milliseconds */
+#define OLSR_TC_EDGE_GC_JITTER 5	/* percent */
+
+#define OLSR_TC_VTIME_JITTER 25	/* percent */
+
+
+AVLNODE2STRUCT(vertex_tree2tc, struct tc_entry, vertex_node);
+AVLNODE2STRUCT(cand_tree2tc, struct tc_entry, cand_tree_node);
+LISTNODE2STRUCT(pathlist2tc, struct tc_entry, path_list_node);
+
+/*
+ * macros for traversing vertices, edges and prefixes in the link state database.
+ * it is recommended to use this because it hides all the internal
+ * datastructure from the callers.
+ *
+ * the loop prefetches the next node in order to not loose context if
+ * for example the caller wants to delete the current entry.
+ */
+#define OLSR_FOR_ALL_TC_ENTRIES(tc) \
+{ \
+  struct avl_node *tc_tree_node, *next_tc_tree_node; \
+  for (tc_tree_node = avl_walk_first(&tc_tree); \
+    tc_tree_node; tc_tree_node = next_tc_tree_node) { \
+    next_tc_tree_node = avl_walk_next(tc_tree_node); \
+    tc = vertex_tree2tc(tc_tree_node);
+#define OLSR_FOR_ALL_TC_ENTRIES_END(tc) }}
+
+#define OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) \
+{ \
+  struct avl_node *tc_edge_node, *next_tc_edge_node; \
+  for (tc_edge_node = avl_walk_first(&tc->edge_tree); \
+    tc_edge_node; tc_edge_node = next_tc_edge_node) { \
+    next_tc_edge_node = avl_walk_next(tc_edge_node); \
+    tc_edge = edge_tree2tc_edge(tc_edge_node);
+#define OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge) }}
+
+#define OLSR_FOR_ALL_PREFIX_ENTRIES(tc, rtp) \
+{ \
+  struct avl_node *rtp_node, *next_rtp_node; \
+  for (rtp_node = avl_walk_first(&tc->prefix_tree); \
+    rtp_node; rtp_node = next_rtp_node) { \
+    next_rtp_node = avl_walk_next(rtp_node); \
+    rtp = rtp_prefix_tree2rtp(rtp_node);
+#define OLSR_FOR_ALL_PREFIX_ENTRIES_END(tc, rtp) }}
+
+extern struct avl_tree tc_tree;
+extern struct tc_entry *tc_myself;
+
+void olsr_init_tc(void);
+void olsr_change_myself_tc(void);
+void olsr_print_tc_table(void);
+void olsr_time_out_tc_set(void);
+
+/* tc msg input parser */
+void olsr_input_tc(union olsr_message *, struct interface *,
+		   union olsr_ip_addr *from);
+
+/* tc_entry manipulation */
+struct tc_entry *olsr_lookup_tc_entry(union olsr_ip_addr *);
+struct tc_entry *olsr_locate_tc_entry(union olsr_ip_addr *);
+void olsr_lock_tc_entry(struct tc_entry *);
+void olsr_unlock_tc_entry(struct tc_entry *);
+
+/* tc_edge_entry manipulation */
+olsr_bool olsr_delete_outdated_tc_edges(struct tc_entry *);
+char *olsr_tc_edge_to_string(struct tc_edge_entry *);
+struct tc_edge_entry *olsr_lookup_tc_edge(struct tc_entry *,
+					  union olsr_ip_addr *);
+struct tc_edge_entry *olsr_add_tc_edge_entry(struct tc_entry *,
+					     union olsr_ip_addr *, olsr_u16_t);
+void olsr_delete_tc_entry(struct tc_entry *);
+void olsr_delete_tc_edge_entry(struct tc_edge_entry *);
+olsr_bool olsr_calc_tc_edge_entry_etx(struct tc_edge_entry *);
+void olsr_set_tc_edge_timer(struct tc_edge_entry *, unsigned int);
+// static olsr_bool olsr_etx_significant_change(float, float);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/two_hop_neighbor_table.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/two_hop_neighbor_table.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/two_hop_neighbor_table.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/two_hop_neighbor_table.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,273 @@
+/*
+ * 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 "two_hop_neighbor_table.h"
+#include "ipcalc.h"
+#include "defs.h"
+#include "mid_set.h"
+#include "neighbor_table.h"
+#include "net_olsr.h"
+#include "scheduler.h"
+
+
+struct neighbor_2_entry two_hop_neighbortable[HASHSIZE];
+
+
+/**
+ *Initialize 2 hop neighbor table
+ */
+void
+olsr_init_two_hop_table(void)
+{
+  int idx;
+  for(idx=0;idx<HASHSIZE;idx++)
+    {
+      two_hop_neighbortable[idx].next = &two_hop_neighbortable[idx];
+      two_hop_neighbortable[idx].prev = &two_hop_neighbortable[idx];
+    }
+}
+
+
+/**
+ *Remove a one hop neighbor from a two hop neighbors
+ *one hop list.
+ *
+ *@param two_hop_entry the two hop neighbor to remove the 
+ *one hop neighbor from
+ *@param address the address of the one hop neighbor to remove
+ *
+ *@return nada
+ */
+
+void
+olsr_delete_neighbor_pointer(struct neighbor_2_entry *two_hop_entry, const union olsr_ip_addr *address)
+{
+  struct neighbor_list_entry *entry = two_hop_entry->neighbor_2_nblist.next;
+  while(entry != &two_hop_entry->neighbor_2_nblist)
+    {
+      if(ipequal(&entry->neighbor->neighbor_main_addr, address))
+	{
+	  struct neighbor_list_entry *entry_to_delete = entry;
+	  entry = entry->next;
+	  
+	  /* dequeue */
+	  DEQUEUE_ELEM(entry_to_delete);
+	  
+	  free(entry_to_delete);
+	}
+      else
+	{
+	  entry = entry->next;
+	}
+    }
+}
+
+
+
+/**
+ *Delete an entry from the two hop neighbor table.
+ *
+ *@param two_hop_neighbor the two hop neighbor to delete.
+ *
+ *@return nada
+ */
+void
+olsr_delete_two_hop_neighbor_table(struct neighbor_2_entry *two_hop_neighbor)
+{
+  struct neighbor_list_entry *one_hop_list;
+  
+  one_hop_list = two_hop_neighbor->neighbor_2_nblist.next;
+  
+  /* Delete one hop links */
+  while(one_hop_list != &two_hop_neighbor->neighbor_2_nblist)
+    {
+      struct neighbor_entry *one_hop_entry = one_hop_list->neighbor;
+      struct neighbor_list_entry *entry_to_delete = one_hop_list;
+
+      olsr_delete_neighbor_2_pointer(one_hop_entry, &two_hop_neighbor->neighbor_2_addr);
+      one_hop_list = one_hop_list->next;
+      /* no need to dequeue */
+      free(entry_to_delete);
+    }
+  
+  /* dequeue */
+  DEQUEUE_ELEM(two_hop_neighbor);
+  free(two_hop_neighbor);
+}
+
+
+
+/**
+ *Insert a new entry to the two hop neighbor table.
+ *
+ *@param two_hop_neighbor the entry to insert
+ *
+ *@return nada
+ */
+void
+olsr_insert_two_hop_neighbor_table(struct neighbor_2_entry *two_hop_neighbor)
+{
+  olsr_u32_t hash = olsr_ip_hashing(&two_hop_neighbor->neighbor_2_addr);
+
+#if 0
+    printf("Adding 2 hop neighbor %s\n", olsr_ip_to_string(&buf, &two_hop_neighbor->neighbor_2_addr));
+#endif
+
+  /* Queue */  
+  QUEUE_ELEM(two_hop_neighbortable[hash], two_hop_neighbor);
+}
+
+
+/**
+ *Look up an entry in the two hop neighbor table.
+ *
+ *@param dest the IP address of the entry to find
+ *
+ *@return a pointer to a neighbor_2_entry struct
+ *representing the two hop neighbor
+ */
+struct neighbor_2_entry *
+olsr_lookup_two_hop_neighbor_table(const union olsr_ip_addr *dest)
+{
+
+  struct neighbor_2_entry  *neighbor_2;
+  olsr_u32_t               hash = olsr_ip_hashing(dest);
+
+  /* printf("LOOKING FOR %s\n", olsr_ip_to_string(&buf, dest)); */
+  for(neighbor_2 = two_hop_neighbortable[hash].next;
+      neighbor_2 != &two_hop_neighbortable[hash];
+      neighbor_2 = neighbor_2->next)
+    {
+      struct mid_address *adr;
+
+      /* printf("Checking %s\n", olsr_ip_to_string(&buf, dest)); */
+      if (ipequal(&neighbor_2->neighbor_2_addr, dest))
+	return neighbor_2;
+
+      adr = mid_lookup_aliases(&neighbor_2->neighbor_2_addr);
+
+      while(adr)
+	{
+	  if(ipequal(&adr->alias, dest))
+	    return neighbor_2;
+	  adr = adr->next_alias;
+	} 
+    }
+
+  return NULL;
+}
+
+
+
+/**
+ *Look up an entry in the two hop neighbor table.
+ *NO CHECK FOR MAIN ADDRESS OR ALIASES!
+ *
+ *@param dest the IP address of the entry to find
+ *
+ *@return a pointer to a neighbor_2_entry struct
+ *representing the two hop neighbor
+ */
+struct neighbor_2_entry *
+olsr_lookup_two_hop_neighbor_table_mid(const union olsr_ip_addr *dest)
+{
+  struct neighbor_2_entry  *neighbor_2;
+  olsr_u32_t               hash;
+
+  /* printf("LOOKING FOR %s\n", olsr_ip_to_string(&buf, dest)); */
+  hash = olsr_ip_hashing(dest);
+  
+  for(neighbor_2 = two_hop_neighbortable[hash].next;
+      neighbor_2 != &two_hop_neighbortable[hash];
+      neighbor_2 = neighbor_2->next)
+    {
+      if (ipequal(&neighbor_2->neighbor_2_addr, dest))
+	return neighbor_2;
+    }
+
+  return NULL;
+}
+
+
+
+/**
+ *Print the two hop neighbor table to STDOUT.
+ *
+ *@return nada
+ */
+void
+olsr_print_two_hop_neighbor_table(void)
+{
+#ifndef NODEBUG
+  /* The whole function makes no sense without it. */
+  int i;
+
+  OLSR_PRINTF(1, "\n--- %s ----------------------- TWO-HOP NEIGHBORS\n\n"
+              "IP addr (2-hop)  IP addr (1-hop)  Total cost\n",
+              olsr_wallclock_string());
+
+  for (i = 0; i < HASHSIZE; i++) {
+    struct neighbor_2_entry *neigh2;
+    for (neigh2 = two_hop_neighbortable[i].next;
+         neigh2 != &two_hop_neighbortable[i];
+         neigh2 = neigh2->next)	{
+      struct neighbor_list_entry *entry;
+      olsr_bool first = OLSR_TRUE;
+
+      for (entry = neigh2->neighbor_2_nblist.next;
+           entry != &neigh2->neighbor_2_nblist;
+           entry = entry->next) {
+        struct ipaddr_str buf;
+        struct lqtextbuffer lqbuffer;
+        if (first) {
+          OLSR_PRINTF(1, "%-15s  ",
+                      olsr_ip_to_string(&buf, &neigh2->neighbor_2_addr));
+          first = OLSR_FALSE;
+        } else {
+          OLSR_PRINTF(1, "                 ");
+        }
+        OLSR_PRINTF(1, "%-15s  %s\n",
+                    olsr_ip_to_string(&buf, &entry->neighbor->neighbor_main_addr),
+                    get_linkcost_text(entry->path_linkcost, OLSR_FALSE, &lqbuffer));
+      }
+    }
+  }
+#endif
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/two_hop_neighbor_table.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/two_hop_neighbor_table.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/two_hop_neighbor_table.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/two_hop_neighbor_table.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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 _OLSR_TWO_HOP_TABLE
+#define _OLSR_TWO_HOP_TABLE
+
+#include "defs.h"
+#include "hashing.h"
+#include "lq_plugin.h"
+
+#define	NB2S_COVERED 	0x1		/* node has been covered by a MPR */
+
+
+struct neighbor_list_entry 
+{
+  struct	neighbor_entry *neighbor;
+  olsr_linkcost second_hop_linkcost;
+  olsr_linkcost path_linkcost;
+  olsr_linkcost saved_path_linkcost;
+  struct	neighbor_list_entry *next;
+  struct	neighbor_list_entry *prev;
+};
+
+
+struct neighbor_2_entry
+{
+  union olsr_ip_addr         neighbor_2_addr;
+  olsr_u8_t      	     mpr_covered_count;    /*used in mpr calculation*/
+  olsr_u8_t      	     processed;            /*used in mpr calculation*/
+  olsr_16_t                  neighbor_2_pointer;   /* Neighbor count */
+  struct neighbor_list_entry neighbor_2_nblist; 
+  struct neighbor_2_entry    *prev;
+  struct neighbor_2_entry    *next;
+};
+
+
+extern struct neighbor_2_entry two_hop_neighbortable[HASHSIZE];
+
+
+void
+olsr_init_two_hop_table(void);
+
+void
+olsr_delete_neighbor_pointer(struct neighbor_2_entry *, const union olsr_ip_addr *);
+
+void
+olsr_delete_two_hop_neighbor_table(struct neighbor_2_entry *);
+
+void
+olsr_insert_two_hop_neighbor_table(struct neighbor_2_entry *);
+
+struct neighbor_2_entry *
+olsr_lookup_two_hop_neighbor_table(const union olsr_ip_addr *);
+
+struct neighbor_2_entry *
+olsr_lookup_two_hop_neighbor_table_mid(const union olsr_ip_addr *);
+
+void
+olsr_print_two_hop_neighbor_table(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/unix/ifnet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/unix/ifnet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/unix/ifnet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/unix/ifnet.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1017 @@
+/*
+ * 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.
+ *
+ */
+
+
+#if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
+#define ifr_netmask ifr_addr
+#endif
+
+#include "ifnet.h"
+#include "ipcalc.h"
+#include "interfaces.h"
+#include "defs.h"
+#include "olsr.h"
+#include "net_os.h"
+#include "net_olsr.h"
+#include "socket_parser.h"
+#include "parser.h"
+#include "scheduler.h"
+#include "generate_msg.h"
+#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>
+#include <net/if_arp.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#define BUFSPACE  (127*1024)	/* max. input buffer size to request */
+
+int
+set_flag(char *ifname, short flag __attribute__((unused)))
+{
+  struct ifreq ifr;
+
+  strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+  /* Get flags */
+  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) 
+    {
+      fprintf(stderr,"ioctl (get interface flags)");
+      return -1;
+    }
+
+  strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+  
+  //printf("Setting flags for if \"%s\"\n", ifr.ifr_name);
+
+  if(!(ifr.ifr_flags & (IFF_UP | IFF_RUNNING)))
+    {
+      /* Add UP */
+      ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
+      /* Set flags + UP */
+      if(ioctl(olsr_cnf->ioctl_s, SIOCSIFFLAGS, &ifr) < 0)
+	{
+	  fprintf(stderr, "ERROR(%s): %s\n", ifr.ifr_name, strerror(errno));
+	  return -1;
+	}
+    }
+  return 1;
+
+}
+
+
+
+
+void
+check_interface_updates(void *foo __attribute__((unused)))
+{
+  struct olsr_if *tmp_if;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Checking for updates in the interface set\n");
+#endif
+
+  for(tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next)
+    {
+      if(tmp_if->host_emul)
+	continue;
+      
+      if(olsr_cnf->host_emul) /* XXX: TEMPORARY! */
+	continue;
+
+      if(!tmp_if->cnf->autodetect_chg) 
+        {
+#ifdef DEBUG
+          /* Don't check this interface */
+          OLSR_PRINTF(3, "Not checking interface %s\n", tmp_if->name);
+#endif
+          continue;
+        }
+
+      if(tmp_if->configured)
+        {
+          chk_if_changed(tmp_if);
+        }
+      else
+        {
+          chk_if_up(tmp_if, 3);
+        }
+    }
+
+  return;
+}
+
+/**
+ * Checks if an initialized interface is changed
+ * that is if it has been set down or the address
+ * has been changed.
+ *
+ *@param iface the olsr_if struct describing the interface
+ */
+int
+chk_if_changed(struct olsr_if *iface)
+{
+  struct interface *ifp, *tmp_ifp;
+  struct ifreq ifr;
+  struct sockaddr_in6 tmp_saddr6;
+  int if_changes;
+  if_changes = 0;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Checking if %s is set down or changed\n", iface->name);
+#endif
+
+  if(iface->host_emul)
+    return -1;
+
+  ifp = iface->interf;
+
+  if(ifp == NULL)
+    {
+      /* Should not happen */
+      iface->configured = 0;
+      return 0;
+    }
+
+  memset(&ifr, 0, sizeof(struct ifreq));
+  strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
+
+
+  /* Get flags (and check if interface exists) */
+  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) 
+    {
+      OLSR_PRINTF(3, "No such interface: %s\n", iface->name);
+      goto remove_interface;
+    }
+
+  ifp->int_flags = ifr.ifr_flags;
+
+  /*
+   * First check if the interface is set DOWN
+   */
+
+  if ((ifp->int_flags & IFF_UP) == 0)
+    {
+      OLSR_PRINTF(1, "\tInterface %s not up - removing it...\n", iface->name);
+      goto remove_interface;
+    }
+
+  /*
+   * We do all the interface type checks over.
+   * This is because the interface might be a PCMCIA card. Therefore
+   * It might not be the same physical interface as we configured earlier.
+   */
+
+  /* Check broadcast */
+  if ((olsr_cnf->ip_version == AF_INET) && 
+      !iface->cnf->ipv4_broadcast.v4.s_addr && /* Skip if fixed bcast */ 
+      (!(ifp->int_flags & IFF_BROADCAST))) 
+    {
+      OLSR_PRINTF(3, "\tNo broadcast - removing\n");
+      goto remove_interface;
+    }
+
+  if (ifp->int_flags & IFF_LOOPBACK)
+    {
+      OLSR_PRINTF(3, "\tThis is a loopback interface - removing it...\n");
+      goto remove_interface;
+    }
+
+  ifp->is_hcif = OLSR_FALSE;
+
+  /* trying to detect if interface is wireless. */
+  ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
+
+  /* Set interface metric */
+  if(iface->cnf->weight.fixed)
+    ifp->int_metric = iface->cnf->weight.value;
+  else
+    ifp->int_metric = calculate_if_metric(ifr.ifr_name);
+
+  /* Get MTU */
+  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0)
+    ifp->int_mtu = 0;
+  else
+    {
+      ifr.ifr_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
+
+      if(ifp->int_mtu != ifr.ifr_mtu)
+	{
+	  ifp->int_mtu = ifr.ifr_mtu;
+	  /* Create new outputbuffer */
+	  net_remove_buffer(ifp); /* Remove old */
+	  net_add_buffer(ifp);
+	}
+    }
+
+
+  /* Get interface index */
+  ifp->if_index = if_nametoindex(ifr.ifr_name);
+
+  /*
+   * Now check if the IP has changed
+   */
+  
+  /* IP version 6 */
+  if(olsr_cnf->ip_version == AF_INET6)
+    {
+#ifdef DEBUG
+      struct ipaddr_str buf;
+#endif
+      /* Get interface address */
+      
+      if(get_ipv6_address(ifr.ifr_name, &tmp_saddr6, iface->cnf->ipv6_addrtype) <= 0)
+	{
+	  if(iface->cnf->ipv6_addrtype == IPV6_ADDR_SITELOCAL)
+	    OLSR_PRINTF(3, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
+	  else
+	    OLSR_PRINTF(3, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
+	  
+	  
+	  goto remove_interface;
+	}
+      
+#ifdef DEBUG
+      OLSR_PRINTF(3, "\tAddress: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
+#endif
+
+      if(memcmp(&tmp_saddr6.sin6_addr, &ifp->int6_addr.sin6_addr, olsr_cnf->ipsize) != 0)
+	{
+          struct ipaddr_str buf;
+	  OLSR_PRINTF(1, "New IP address for %s:\n", ifr.ifr_name);
+	  OLSR_PRINTF(1, "\tOld: %s\n", ip6_to_string(&buf, &ifp->int6_addr.sin6_addr));
+	  OLSR_PRINTF(1, "\tNew: %s\n", ip6_to_string(&buf, &tmp_saddr6.sin6_addr));
+
+	  /* Check main addr */
+	  if(memcmp(&olsr_cnf->main_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize) == 0)
+	    {
+	      /* Update main addr */
+	      memcpy(&olsr_cnf->main_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
+	    }
+
+	  /* Update address */
+	  memcpy(&ifp->int6_addr.sin6_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
+	  memcpy(&ifp->ip_addr, &tmp_saddr6.sin6_addr, olsr_cnf->ipsize);
+
+	  run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
+
+	  return 1;	  	  
+	}
+      return 0;
+
+    }
+  else
+  /* IP version 4 */
+    {
+      struct ipaddr_str buf;
+      /* Check interface address (IPv4)*/
+      if(ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) 
+	{
+	  OLSR_PRINTF(1, "\tCould not get address of interface - removing it\n");
+	  goto remove_interface;
+	}
+
+#ifdef DEBUG
+      OLSR_PRINTF(3, "\tAddress:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
+#endif
+
+      if(memcmp(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr,
+		&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, 
+		olsr_cnf->ipsize) != 0)
+	{
+	  /* New address */
+	  OLSR_PRINTF(1, "IPv4 address changed for %s\n", ifr.ifr_name);
+	  OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_addr.sin_addr));
+	  OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
+
+	  ifp->int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
+
+	  if(memcmp(&olsr_cnf->main_addr, 
+		    &ifp->ip_addr,
+		    olsr_cnf->ipsize) == 0)
+	    {
+	      OLSR_PRINTF(1, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
+	      olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr));
+	      memcpy(&olsr_cnf->main_addr, 
+		     &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, 
+		     olsr_cnf->ipsize);
+	    }
+
+	  memcpy(&ifp->ip_addr, 
+		 &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, 
+		 olsr_cnf->ipsize);
+
+	  if_changes = 1;
+	}
+
+      /* Check netmask */
+      if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) 
+	{
+	  olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
+	  goto remove_interface;
+	}
+
+#ifdef DEBUG
+      OLSR_PRINTF(3, "\tNetmask:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_netmask));
+#endif
+
+      if(memcmp(&((struct sockaddr_in *)&ifp->int_netmask)->sin_addr.s_addr,
+		&((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr, 
+		olsr_cnf->ipsize) != 0)
+	{
+          struct ipaddr_str buf;
+	  /* New address */
+	  OLSR_PRINTF(1, "IPv4 netmask changed for %s\n", ifr.ifr_name);
+	  OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_netmask.sin_addr));
+	  OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_netmask));
+
+	  ifp->int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
+
+	  if_changes = 1;
+	}
+      
+      if(!iface->cnf->ipv4_broadcast.v4.s_addr)
+	{
+	  /* Check broadcast address */      
+	  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) 
+	    {
+	      olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
+	      goto remove_interface;
+	    }
+	  
+#ifdef DEBUG
+	  OLSR_PRINTF(3, "\tBroadcast address:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_broadaddr));
+#endif
+	  
+	  if(ifp->int_broadaddr.sin_addr.s_addr != ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr)
+	    {
+              struct ipaddr_str buf;
+	      /* New address */
+	      OLSR_PRINTF(1, "IPv4 broadcast changed for %s\n", ifr.ifr_name);
+	      OLSR_PRINTF(1, "\tOld:%s\n", ip4_to_string(&buf, ifp->int_broadaddr.sin_addr));
+	      OLSR_PRINTF(1, "\tNew:%s\n", sockaddr4_to_string(&buf, &ifr.ifr_broadaddr));
+	      
+	      ifp->int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
+	      if_changes = 1;
+	    }            
+	}
+    }
+
+  if(if_changes)
+    run_ifchg_cbs(ifp, IFCHG_IF_UPDATE);
+
+  return if_changes;
+
+
+ remove_interface:
+  OLSR_PRINTF(1, "Removing interface %s\n", iface->name);
+  olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name);
+
+  olsr_delete_link_entry_by_ip(&ifp->ip_addr);
+
+  /*
+   *Call possible ifchange functions registered by plugins  
+   */
+  run_ifchg_cbs(ifp, IFCHG_IF_REMOVE);
+  
+  /* Dequeue */
+  if(ifp == ifnet)
+    {
+      ifnet = ifp->int_next;
+    }
+  else
+    {
+      tmp_ifp = ifnet;
+      while(tmp_ifp->int_next != ifp)
+	{
+	  tmp_ifp = tmp_ifp->int_next;
+	}
+      tmp_ifp->int_next = ifp->int_next;
+    }
+
+
+  /* Remove output buffer */
+  net_remove_buffer(ifp);
+
+  /* Check main addr */
+  if(ipequal(&olsr_cnf->main_addr, &ifp->ip_addr))
+    {
+      if(ifnet == NULL)
+	{
+	  /* No more interfaces */
+	  memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize);
+	  OLSR_PRINTF(1, "No more interfaces...\n");
+	}
+      else
+	{
+          struct ipaddr_str buf;
+	  olsr_cnf->main_addr = ifnet->ip_addr;
+	  OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+	  olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+	}
+    }
+
+  /*
+   * Deregister functions for periodic message generation 
+   */
+  olsr_stop_timer(ifp->hello_gen_timer);
+  olsr_stop_timer(ifp->tc_gen_timer);
+  olsr_stop_timer(ifp->mid_gen_timer);
+  olsr_stop_timer(ifp->hna_gen_timer);
+
+  iface->configured = 0;
+  iface->interf = NULL;
+  /* Close olsr socket */
+  close(ifp->olsr_socket);
+  remove_olsr_socket(ifp->olsr_socket, &olsr_input);
+
+  /* Free memory */
+  free(ifp->int_name);
+  free(ifp);
+
+  if((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces))
+    {
+      OLSR_PRINTF(1, "No more active interfaces - exiting.\n");
+      olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n");
+      olsr_cnf->exit_value = EXIT_FAILURE;
+      kill(getpid(), SIGINT);
+    }
+
+  return 0;
+
+}
+
+/**
+ * Initializes the special interface used in
+ * host-client emulation
+ */
+int
+add_hemu_if(struct olsr_if *iface)
+{
+  struct interface *ifp;
+  union olsr_ip_addr null_addr;
+  olsr_u32_t addr[4];
+  struct ipaddr_str buf;
+  size_t name_size;
+
+  if(!iface->host_emul)
+    return -1;
+
+  ifp = olsr_malloc(sizeof (struct interface), "Interface update 2");
+
+  memset(ifp, 0, sizeof (struct interface));
+
+  iface->configured = OLSR_TRUE;
+  iface->interf = ifp;
+
+  name_size = strlen("hcif01") + 1;
+  ifp->is_hcif = OLSR_TRUE;
+  ifp->int_name = olsr_malloc(name_size, "Interface update 3");
+  ifp->int_metric = 0;
+
+  strscpy(ifp->int_name, "hcif01", name_size);
+
+  OLSR_PRINTF(1, "Adding %s(host emulation):\n", ifp->int_name);
+
+  OLSR_PRINTF(1, "       Address:%s\n", olsr_ip_to_string(&buf, &iface->hemu_ip));
+
+  OLSR_PRINTF(1, "       NB! This is a emulated interface\n       that does not exist in the kernel!\n");
+
+  ifp->int_next = ifnet;
+  ifnet = ifp;
+
+  memset(&null_addr, 0, olsr_cnf->ipsize);
+  if(ipequal(&null_addr, &olsr_cnf->main_addr))
+    {
+      olsr_cnf->main_addr = iface->hemu_ip;
+      OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+	olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+    }
+
+  ifp->int_mtu = OLSR_DEFAULT_MTU;
+
+  ifp->int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
+
+  /* Set up buffer */
+  net_add_buffer(ifp);
+
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      struct sockaddr_in sin;
+
+      memset(&sin, 0, sizeof(sin));
+
+      sin.sin_family = AF_INET;
+      sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+      sin.sin_port = htons(10150);
+ 
+     /* IP version 4 */
+      ifp->ip_addr.v4 = iface->hemu_ip.v4;
+
+      memcpy(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, &iface->hemu_ip, olsr_cnf->ipsize);
+      
+      /*
+       *We create one socket for each interface and bind
+       *the socket to it. This to ensure that we can control
+       *on what interface the message is transmitted
+       */
+      
+      ifp->olsr_socket = gethemusocket(&sin);
+      
+      if (ifp->olsr_socket < 0)
+	{
+	  fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+	  olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
+	  olsr_cnf->exit_value = EXIT_FAILURE;
+	  kill(getpid(), SIGINT);
+	}
+
+    }
+  else
+    {
+      /* IP version 6 */
+      memcpy(&ifp->ip_addr, &iface->hemu_ip, olsr_cnf->ipsize);
+
+#if 0      
+      /*
+       *We create one socket for each interface and bind
+       *the socket to it. This to ensure that we can control
+       *on what interface the message is transmitted
+       */
+      
+      ifp->olsr_socket = gethcsocket6(&addrsock6, BUFSPACE, ifp->int_name);
+      
+      join_mcast(ifp, ifp->olsr_socket);
+      
+      if (ifp->olsr_socket < 0)
+	{
+	  fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+	  olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
+	  olsr_cnf->exit_value = EXIT_FAILURE;
+	  kill(getpid(), SIGINT);
+	}
+      
+#endif
+    }
+
+  /* Send IP as first 4/16 bytes on socket */
+  memcpy(addr, iface->hemu_ip.v6.s6_addr, olsr_cnf->ipsize);
+  addr[0] = htonl(addr[0]);
+  addr[1] = htonl(addr[1]);
+  addr[2] = htonl(addr[2]);
+  addr[3] = htonl(addr[3]);
+
+  if(send(ifp->olsr_socket, addr , olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize)
+    {
+      fprintf(stderr, "Error sending IP!");
+    }  
+  
+  /* Register socket */
+  add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu);
+
+
+  /*
+   * Register functions for periodic message generation 
+   */
+  
+  ifp->hello_gen_timer =
+    olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
+                     HELLO_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
+                     ifp, hello_gen_timer_cookie->ci_id);
+  ifp->tc_gen_timer =
+    olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
+                     TC_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
+                     ifp, tc_gen_timer_cookie->ci_id);
+  ifp->mid_gen_timer =
+    olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
+                     MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
+                     mid_gen_timer_cookie->ci_id);
+  ifp->hna_gen_timer =
+    olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
+                     HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
+                     hna_gen_timer_cookie->ci_id);
+
+  /* Recalculate max topology hold time */
+  if(olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
+    olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
+
+  ifp->hello_etime = (olsr_reltime)(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
+  ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
+
+  return 1;
+}
+
+static char basenamestr[32];
+static const char* if_basename(const char* name);
+static const char* if_basename(const char* name)
+{
+	char *p = strchr(name, ':');
+	if (NULL == p || p - name >= (int)(sizeof(basenamestr) / sizeof(basenamestr[0]) - 1)) {
+        	return name;
+        }
+	memcpy(basenamestr, name, p - name);
+	basenamestr[p - name] = 0;
+	return basenamestr;
+}
+
+/**
+ * Initializes a interface described by iface,
+ * if it is set up and is of the correct type.
+ *
+ *@param iface the olsr_if struct describing the interface
+ *@param so the socket to use for ioctls
+ *
+ */
+int
+chk_if_up(struct olsr_if *iface, int debuglvl __attribute__((unused)))
+{
+  struct interface ifs, *ifp;
+  struct ifreq ifr;
+  union olsr_ip_addr null_addr;
+  size_t name_size;
+#ifdef linux
+  int precedence = IPTOS_PREC(olsr_cnf->tos);
+  int tos_bits = IPTOS_TOS(olsr_cnf->tos);
+#endif
+
+  if(iface->host_emul)
+    return -1;
+
+  memset(&ifr, 0, sizeof(struct ifreq));
+  memset(&ifs, 0, sizeof(struct interface));
+  strscpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
+
+  OLSR_PRINTF(debuglvl, "Checking %s:\n", ifr.ifr_name);
+
+  /* Get flags (and check if interface exists) */
+  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) 
+    {
+      OLSR_PRINTF(debuglvl, "\tNo such interface!\n");
+      return 0;
+    }
+
+  ifs.int_flags = ifr.ifr_flags;      
+
+
+  if ((ifs.int_flags & IFF_UP) == 0)
+    {
+      OLSR_PRINTF(debuglvl, "\tInterface not up - skipping it...\n");
+      return 0;
+    }
+
+  /* Check broadcast */
+  if ((olsr_cnf->ip_version == AF_INET) &&
+      !iface->cnf->ipv4_broadcast.v4.s_addr && /* Skip if fixed bcast */ 
+      (!(ifs.int_flags & IFF_BROADCAST))) 
+    {
+      OLSR_PRINTF(debuglvl, "\tNo broadcast - skipping\n");
+      return 0;
+    }
+
+
+  if (ifs.int_flags & IFF_LOOPBACK)
+    {
+      OLSR_PRINTF(debuglvl, "\tThis is a loopback interface - skipping it...\n");
+      return 0;
+    }
+
+  ifs.is_hcif = OLSR_FALSE;
+
+  /* trying to detect if interface is wireless. */
+  ifs.is_wireless = check_wireless_interface(ifr.ifr_name);
+
+  if(ifs.is_wireless)
+    OLSR_PRINTF(debuglvl, "\tWireless interface detected\n");
+  else
+    OLSR_PRINTF(debuglvl, "\tNot a wireless interface\n");
+
+  
+  /* IP version 6 */
+  if(olsr_cnf->ip_version == AF_INET6)
+    {
+      /* Get interface address */
+      struct ipaddr_str buf;
+      if(get_ipv6_address(ifr.ifr_name, &ifs.int6_addr, iface->cnf->ipv6_addrtype) <= 0)
+	{
+	  if(iface->cnf->ipv6_addrtype == IPV6_ADDR_SITELOCAL)
+	    OLSR_PRINTF(debuglvl, "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name);
+	  else
+	    OLSR_PRINTF(debuglvl, "\tCould not find global IPv6 address for %s\n", ifr.ifr_name);
+	  
+	  return 0;
+	}
+      
+      OLSR_PRINTF(debuglvl, "\tAddress: %s\n", ip6_to_string(&buf, &ifs.int6_addr.sin6_addr));
+      
+      /* Multicast */
+      memset (&ifs.int6_multaddr, 0, sizeof (ifs.int6_multaddr));
+      ifs.int6_multaddr.sin6_family   = AF_INET6;
+      ifs.int6_multaddr.sin6_flowinfo = htonl(0);
+      ifs.int6_multaddr.sin6_scope_id = if_nametoindex(ifr.ifr_name);
+      ifs.int6_multaddr.sin6_port     = htons(OLSRPORT);
+      ifs.int6_multaddr.sin6_addr = (iface->cnf->ipv6_addrtype == IPV6_ADDR_SITELOCAL) ? 
+	iface->cnf->ipv6_multi_site.v6 :
+	iface->cnf->ipv6_multi_glbl.v6;
+      
+#ifdef __MacOSX__
+      ifs.int6_multaddr.sin6_scope_id = 0;
+#endif
+
+      OLSR_PRINTF(debuglvl, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
+      
+    }
+  /* IP version 4 */
+  else
+    {
+      /* Get interface address (IPv4)*/
+      if(ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) 
+	{
+	  OLSR_PRINTF(debuglvl, "\tCould not get address of interface - skipping it\n");
+	  return 0;
+	}
+      
+      ifs.int_addr = *(struct sockaddr_in *)&ifr.ifr_addr;
+      
+      /* Find netmask */
+      
+      if (ioctl(olsr_cnf->ioctl_s, SIOCGIFNETMASK, &ifr) < 0) 
+	{
+	  olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get netmask)", ifr.ifr_name);
+	  return 0;
+	}
+      
+      ifs.int_netmask = *(struct sockaddr_in *)&ifr.ifr_netmask;
+      
+      /* Find broadcast address */
+      if(iface->cnf->ipv4_broadcast.v4.s_addr)
+	{
+	  /* Specified broadcast */
+	  memcpy(&((struct sockaddr_in *)&ifs.int_broadaddr)->sin_addr.s_addr, 
+		 &iface->cnf->ipv4_broadcast.v4, 
+		 sizeof(olsr_u32_t));
+	}
+      else
+	{
+	  /* Autodetect */
+	  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFBRDADDR, &ifr) < 0) 
+	    {
+	      olsr_syslog(OLSR_LOG_ERR, "%s: ioctl (get broadaddr)", ifr.ifr_name);
+	      return 0;
+	    }
+	  
+	  ifs.int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr;
+	}
+      
+      /* Deactivate IP spoof filter */
+      deactivate_spoof(if_basename(ifr.ifr_name), &ifs, olsr_cnf->ip_version);
+      
+      /* Disable ICMP redirects */
+      disable_redirects(if_basename(ifr.ifr_name), &ifs, olsr_cnf->ip_version);
+      
+    }
+  
+  
+  /* Get interface index */
+  
+  ifs.if_index = if_nametoindex(ifr.ifr_name);
+  
+  /* Set interface metric */
+  if(iface->cnf->weight.fixed)
+    ifs.int_metric = iface->cnf->weight.value;
+  else
+    ifs.int_metric = calculate_if_metric(ifr.ifr_name);
+  OLSR_PRINTF(1, "\tMetric: %d\n", ifs.int_metric);
+
+  /* Get MTU */
+  if (ioctl(olsr_cnf->ioctl_s, SIOCGIFMTU, &ifr) < 0)
+    ifs.int_mtu = OLSR_DEFAULT_MTU;
+  else
+    ifs.int_mtu = ifr.ifr_mtu;
+
+  ifs.int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
+
+  ifs.ttl_index = -32; /* For the first 32 TC's, fish-eye is disabled */
+
+  /* Set up buffer */
+  net_add_buffer(&ifs);
+	       
+  OLSR_PRINTF(1, "\tMTU - IPhdr: %d\n", ifs.int_mtu);
+
+  olsr_syslog(OLSR_LOG_INFO, "Adding interface %s\n", iface->name);
+  OLSR_PRINTF(1, "\tIndex %d\n", ifs.if_index);
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "\tAddress:%s\n", ip4_to_string(&buf, ifs.int_addr.sin_addr));
+      OLSR_PRINTF(1, "\tNetmask:%s\n", ip4_to_string(&buf, ifs.int_netmask.sin_addr));
+      OLSR_PRINTF(1, "\tBroadcast address:%s\n", ip4_to_string(&buf, ifs.int_broadaddr.sin_addr));
+    }
+  else
+    {
+      struct ipaddr_str buf;
+      OLSR_PRINTF(1, "\tAddress: %s\n", ip6_to_string(&buf, &ifs.int6_addr.sin6_addr));
+      OLSR_PRINTF(1, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
+    }
+  
+  ifp = olsr_malloc(sizeof (struct interface), "Interface update 2");
+  
+  iface->configured = 1;
+  iface->interf = ifp;
+
+  /* XXX bad code */
+  memcpy(ifp, &ifs, sizeof(struct interface));
+  
+  ifp->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
+  if (olsr_cnf->max_jitter == 0)
+  {
+    /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
+    olsr_cnf->max_jitter = ifp->immediate_send_tc ? iface->cnf->tc_params.emission_interval : iface->cnf->hello_params.emission_interval;
+  }
+
+  name_size = strlen(if_basename(ifr.ifr_name)) + 1;
+  ifp->gen_properties = NULL;
+  ifp->int_name = olsr_malloc(name_size, "Interface update 3");
+  strscpy(ifp->int_name, if_basename(ifr.ifr_name), name_size);
+  ifp->int_next = ifnet;
+  ifnet = ifp;
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      /* IP version 4 */
+      ifp->ip_addr.v4 = ifp->int_addr.sin_addr;
+      /*
+       *We create one socket for each interface and bind
+       *the socket to it. This to ensure that we can control
+       *on what interface the message is transmitted
+       */
+      
+      ifp->olsr_socket = getsocket(BUFSPACE, ifp->int_name);
+      
+      if (ifp->olsr_socket < 0)
+	{
+	  fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+	  olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
+	  olsr_cnf->exit_value = EXIT_FAILURE;
+	  kill(getpid(), SIGINT);
+	}
+
+    }
+  else
+    {
+      /* IP version 6 */
+      ifp->ip_addr.v6 =  ifp->int6_addr.sin6_addr;
+      
+      /*
+       *We create one socket for each interface and bind
+       *the socket to it. This to ensure that we can control
+       *on what interface the message is transmitted
+       */
+      
+      ifp->olsr_socket = getsocket6(BUFSPACE, ifp->int_name);
+      
+      join_mcast(ifp, ifp->olsr_socket);
+      
+      if (ifp->olsr_socket < 0)
+	{
+	  fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+	  olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
+	  olsr_cnf->exit_value = EXIT_FAILURE;
+	  kill(getpid(), SIGINT);
+	}
+      
+    }
+
+  set_buffer_timer(ifp);
+
+  /* Register socket */
+  add_olsr_socket(ifp->olsr_socket, &olsr_input);
+  
+#ifdef linux 
+  /* Set TOS */
+  
+  if (setsockopt(ifp->olsr_socket, SOL_SOCKET, SO_PRIORITY, (char*)&precedence, sizeof(precedence)) < 0)
+    {
+      perror("setsockopt(SO_PRIORITY)");
+      olsr_syslog(OLSR_LOG_ERR, "OLSRD: setsockopt(SO_PRIORITY) error %m");
+    }
+  if (setsockopt(ifp->olsr_socket, SOL_IP, IP_TOS, (char*)&tos_bits, sizeof(tos_bits)) < 0)    
+    {
+      perror("setsockopt(IP_TOS)");
+      olsr_syslog(OLSR_LOG_ERR, "setsockopt(IP_TOS) error %m");
+    }
+#endif
+  
+  /*
+   *Initialize sequencenumber as a random 16bit value
+   */
+  ifp->olsr_seqnum = random() & 0xFFFF;
+
+  /*
+   * Set main address if this is the only interface
+   */
+  memset(&null_addr, 0, olsr_cnf->ipsize);
+  if(ipequal(&null_addr, &olsr_cnf->main_addr))
+    {
+      struct ipaddr_str buf;
+      olsr_cnf->main_addr = ifp->ip_addr;
+      OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+      olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+    }
+  
+  /*
+   * Register functions for periodic message generation 
+   */
+  ifp->hello_gen_timer =
+    olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
+                     HELLO_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
+                     ifp, hello_gen_timer_cookie->ci_id);
+  ifp->tc_gen_timer =
+    olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
+                     TC_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
+                     ifp, tc_gen_timer_cookie->ci_id);
+  ifp->mid_gen_timer =
+    olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
+                     MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
+                     mid_gen_timer_cookie->ci_id);
+  ifp->hna_gen_timer =
+    olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
+                     HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
+                     hna_gen_timer_cookie->ci_id);
+
+  /* Recalculate max topology hold time */
+  if(olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval) {
+    olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
+  }
+  ifp->hello_etime = (olsr_reltime)(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
+  ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
+
+
+  /*
+   *Call possible ifchange functions registered by plugins  
+   */
+  run_ifchg_cbs(ifp, IFCHG_IF_ADD);
+
+  return 1;
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/unix/log.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/unix/log.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/unix/log.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/unix/log.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ */
+
+/* 
+ * System logging interface for GNU/Linux systems
+ */
+
+#include "../log.h"
+#include <syslog.h>
+#include <stdarg.h>
+
+void
+olsr_openlog(const char *ident)
+{
+  openlog(ident, LOG_PID | LOG_ODELAY, LOG_DAEMON);
+  setlogmask(LOG_UPTO(LOG_INFO));
+
+  return;
+}
+
+
+void
+olsr_syslog(int level, const char *format, ...)
+{
+
+  int linux_level;
+  va_list arglist;
+
+  switch(level)
+    {
+    case(OLSR_LOG_INFO):
+      linux_level = LOG_INFO;
+      break;
+    case(OLSR_LOG_ERR):
+      linux_level = LOG_ERR;
+      break;
+    default:
+      return;
+    }
+
+  va_start(arglist, format);
+  vsyslog(linux_level, format, arglist);
+  va_end(arglist);
+
+  return;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/unix/misc.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/unix/misc.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/unix/misc.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/unix/misc.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,72 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 <stdio.h>
+#include <unistd.h>
+#include "misc.h"
+#include "olsr_types.h"
+
+void clear_console(void)
+{
+  static int len = -1;
+  static char clear_buff[100];
+  int i;
+
+  if (len < 0)
+    {
+      FILE *pip = popen("clear", "r");
+      for (len = 0; len < (int)sizeof(clear_buff); len++)
+        {
+          int c = fgetc(pip);
+          if (c == EOF)
+            break;
+
+          clear_buff[len] = c;
+        }
+
+      pclose(pip);
+    }
+
+  for (i = 0; i < len; i++)
+    fputc(clear_buff[i], stdout);
+
+  fflush(stdout);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/apm.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/apm.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/apm.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/apm.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,91 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "apm.h"
+#include "defs.h"
+#include <stdio.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef interface
+
+int apm_init(void)
+{
+  struct olsr_apm_info ApmInfo;
+
+  OLSR_PRINTF(3, "Initializing APM\n");
+
+  if(apm_read(&ApmInfo) < 0)
+    return -1;
+
+  apm_printinfo(&ApmInfo);
+
+  return 0;
+}
+
+void apm_printinfo(struct olsr_apm_info *ApmInfo)
+{
+  OLSR_PRINTF(5, "APM info:\n\tAC status %d\n\tBattery percentage %d%%\n\n",
+	      ApmInfo->ac_line_status,
+	      ApmInfo->battery_percentage);
+}
+
+int apm_read(struct olsr_apm_info *ApmInfo)
+{
+#if !defined WINCE
+  SYSTEM_POWER_STATUS PowerStat;
+
+  memset(ApmInfo, 0, sizeof (struct olsr_apm_info));
+
+  if (!GetSystemPowerStatus(&PowerStat))
+    return 0;
+
+  ApmInfo->ac_line_status = (PowerStat.ACLineStatus == 1) ?
+    OLSR_AC_POWERED : OLSR_BATTERY_POWERED;
+    
+  ApmInfo->battery_percentage = (PowerStat.BatteryLifePercent <= 100) ?
+    PowerStat.BatteryLifePercent : 0;
+
+  return 1;
+#else
+  return 0;
+#endif
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/arpa/inet.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/arpa/inet.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/arpa/inet.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/arpa/inet.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,54 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_ARPA_INET_H_INCLUDED
+
+#define TL_ARPA_INET_H_INCLUDED
+
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#undef interface
+
+int inet_aton(const char *cp, struct in_addr *addr);
+int inet_pton(int af, const char *src, void *dst);
+char *inet_ntop(int af, const void *src, char *dst, int size);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/ce/ws2tcpip.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/ce/ws2tcpip.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/ce/ws2tcpip.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/ce/ws2tcpip.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,39 @@
+#if !defined TL_WS2TCPIP_INCLUDED
+
+#define TL_WS2TCPIP_INCLUDED
+
+#define AF_INET6 23
+
+struct in6_addr
+{
+  unsigned char s6_addr[16];
+};
+
+struct sockaddr_in6
+{
+  short sin6_family;
+  unsigned short sin6_port;
+  unsigned long sin6_flowinfo;
+  struct in6_addr sin6_addr;
+  unsigned long sin6_scope_id;
+};
+
+typedef int socklen_t;
+
+struct sockaddr_storage
+{
+  unsigned char dummy[128];
+};
+
+#define IPPROTO_IPV6 41
+
+#define IPV6_MULTICAST_IF 9
+#define IPV6_ADD_MEMBERSHIP 12
+
+struct ipv6_mreq
+{
+  struct in6_addr ipv6mr_multiaddr;
+  unsigned int ipv6mr_interface;
+};
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/compat.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/compat.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/compat.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/compat.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,543 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <ctype.h>
+#include <dlfcn.h>
+#include <io.h>
+#include <arpa/inet.h>
+
+#include "defs.h"
+
+void PError(char *Str);
+void WinSockPError(char *Str);
+
+void sleep(unsigned int Sec)
+{
+  Sleep(Sec * 1000);
+}
+
+static unsigned int RandState;
+
+void srandom(unsigned int Seed)
+{
+  RandState = Seed;
+}
+
+unsigned int random(void)
+{
+  RandState = RandState * 1103515245 + 12345;
+
+  return (RandState ^ (RandState >> 16)) & RAND_MAX;
+}
+
+int getpid(void)
+{
+  HANDLE h = GetCurrentThread();
+  return (int)h;
+}
+
+int nanosleep(struct timespec *Req, struct timespec *Rem)
+{
+  Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000);
+
+  Rem->tv_sec = 0;
+  Rem->tv_nsec = 0;
+
+  return 0;
+}
+
+void gettimeofday(struct timeval *TVal, void *TZone __attribute__((unused)))
+{
+  SYSTEMTIME SysTime;
+  FILETIME FileTime;
+  unsigned __int64 Ticks;
+
+  GetSystemTime(&SysTime);
+  SystemTimeToFileTime(&SysTime, &FileTime);
+
+  Ticks = ((__int64)FileTime.dwHighDateTime << 32) |
+    (__int64)FileTime.dwLowDateTime;
+
+  Ticks -= 116444736000000000LL;
+
+  TVal->tv_sec = (unsigned int)(Ticks / 10000000);
+  TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
+}
+
+long times(struct tms *Dummy __attribute__((unused)))
+{
+  return (long)GetTickCount();
+}
+
+int inet_aton(const char *AddrStr, struct in_addr *Addr)
+{
+  Addr->s_addr = inet_addr(AddrStr);
+
+  return 1;
+}
+
+char *StrError(unsigned int ErrNo)
+{
+  static char Msg[1000];
+
+#if !defined WINCE
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg,
+                sizeof (Msg), NULL);
+#else
+  short WideMsg[1000];
+
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg,
+                sizeof (WideMsg) / 2, NULL);
+
+  if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof (Msg),
+                          NULL, NULL) == 0)
+  strscpy(Msg, "[cannot convert string]", sizeof(Msg));
+#endif
+
+  return Msg;
+}
+
+void PError(char *Str)
+{
+  fprintf(stderr, "ERROR - %s: %s", Str, StrError(GetLastError()));
+}
+
+void WinSockPError(char *Str)
+{
+  fprintf(stderr, "ERROR - %s: %s", Str, StrError(WSAGetLastError()));
+}
+
+// XXX - not thread-safe, which is okay for our purposes
+ 
+void *dlopen(char *Name, int Flags __attribute__((unused)))
+{
+#if !defined WINCE
+  return (void *)LoadLibrary(Name);
+#else
+  short WideName[1000];
+
+  MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName));
+  return (void *)LoadLibrary(WideName);
+#endif
+}
+
+int dlclose(void *Handle)
+{
+  FreeLibrary((HMODULE)Handle);
+  return 0;
+}
+
+void *dlsym(void *Handle, const char *Name)
+{
+#if !defined WINCE
+  return GetProcAddress((HMODULE)Handle, Name);
+#else
+  short WideName[1000];
+
+  MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName));
+  return GetProcAddress((HMODULE)Handle, WideName);
+#endif
+}
+
+char *dlerror(void)
+{
+  return StrError(GetLastError());
+}
+
+#define NS_INADDRSZ 4
+#define NS_IN6ADDRSZ 16
+#define NS_INT16SZ 2
+
+static int inet_pton4(const char *src, unsigned char *dst)
+{
+  int saw_digit, octets, ch;
+  u_char tmp[NS_INADDRSZ], *tp;
+
+  saw_digit = 0;
+  octets = 0;
+  *(tp = tmp) = 0;
+
+  while ((ch = *src++) != '\0')
+  {
+    if (ch >= '0' && ch <= '9') {
+      unsigned int new = *tp * 10 + (ch - '0');
+
+      if (new > 255)
+        return (0);
+
+      *tp = new;
+
+      if (!saw_digit)
+      {
+        if (++octets > 4)
+          return (0);
+
+        saw_digit = 1;
+      }
+    }
+
+    else if (ch == '.' && saw_digit)
+    {
+      if (octets == 4)
+        return (0);
+
+      *++tp = 0;
+
+      saw_digit = 0;
+    }
+
+    else
+      return (0);
+  }
+
+  if (octets < 4)
+    return (0);
+
+  memcpy(dst, tmp, NS_INADDRSZ);
+  return (1);
+}
+
+static int inet_pton6(const char *src, unsigned char *dst)
+{
+  static const char xdigits[] = "0123456789abcdef";
+  u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+  const char *curtok;
+  int ch, saw_xdigit;
+  u_int val;
+
+  tp = memset(tmp, '\0', NS_IN6ADDRSZ);
+  endp = tp + NS_IN6ADDRSZ;
+  colonp = NULL;
+
+  if (*src == ':')
+    if (*++src != ':')
+      return (0);
+
+  curtok = src;
+  saw_xdigit = 0;
+  val = 0;
+
+  while ((ch = tolower (*src++)) != '\0')
+  {
+    const char *pch;
+
+    pch = strchr(xdigits, ch);
+
+    if (pch != NULL)
+    {
+      val <<= 4;
+      val |= (pch - xdigits);
+
+      if (val > 0xffff)
+        return (0);
+
+      saw_xdigit = 1;
+      continue;
+    }
+
+    if (ch == ':')
+    {
+      curtok = src;
+
+      if (!saw_xdigit)
+      {
+        if (colonp)
+          return (0);
+
+        colonp = tp;
+        continue;
+      }
+
+      else if (*src == '\0')
+      {
+        return (0);
+      }
+
+      if (tp + NS_INT16SZ > endp)
+        return (0);
+
+      *tp++ = (u_char) (val >> 8) & 0xff;
+      *tp++ = (u_char) val & 0xff;
+      saw_xdigit = 0;
+      val = 0;
+      continue;
+    }
+
+    if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+        inet_pton4(curtok, tp) > 0)
+    {
+      tp += NS_INADDRSZ;
+      saw_xdigit = 0;
+      break;
+    }
+
+    return (0);
+  }
+
+  if (saw_xdigit)
+  {
+    if (tp + NS_INT16SZ > endp)
+      return (0);
+
+    *tp++ = (u_char) (val >> 8) & 0xff;
+    *tp++ = (u_char) val & 0xff;
+  }
+
+  if (colonp != NULL)
+  {
+    const int n = tp - colonp;
+    int i;
+
+    if (tp == endp)
+      return (0);
+
+    for (i = 1; i <= n; i++)
+    {
+      endp[- i] = colonp[n - i];
+      colonp[n - i] = 0;
+    }
+
+    tp = endp;
+  }
+
+  if (tp != endp)
+    return (0);
+
+  memcpy(dst, tmp, NS_IN6ADDRSZ);
+  return (1);
+}
+
+int inet_pton(int af, const char *src, void *dst)
+{
+  switch (af)
+  {
+  case AF_INET:
+    return (inet_pton4(src, dst));
+
+  case AF_INET6:
+    return (inet_pton6(src, dst));
+
+  default:
+    return -1;
+  }
+}
+
+static char *inet_ntop4(const unsigned char *src, char *dst, int size)
+{
+  static const char fmt[] = "%u.%u.%u.%u";
+  char tmp[sizeof "255.255.255.255"];
+
+  if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
+    return (NULL);
+
+  return strscpy(dst, tmp, size);
+}
+
+static char *inet_ntop6(const unsigned char *src, char *dst, int size)
+{
+  char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+  struct { int base, len; } best, cur;
+  u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+  int i;
+
+  memset(words, '\0', sizeof words);
+
+  for (i = 0; i < NS_IN6ADDRSZ; i += 2)
+    words[i / 2] = (src[i] << 8) | src[i + 1];
+
+  best.base = -1;
+  cur.base = -1;
+
+  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+  {
+    if (words[i] == 0)
+    {
+      if (cur.base == -1)
+        cur.base = i, cur.len = 1;
+
+      else
+        cur.len++;
+    }
+
+    else
+    {
+      if (cur.base != -1)
+      {
+        if (best.base == -1 || cur.len > best.len)
+          best = cur;
+
+        cur.base = -1;
+      }
+    }
+  }
+
+  if (cur.base != -1)
+  {
+    if (best.base == -1 || cur.len > best.len)
+      best = cur;
+  }
+
+  if (best.base != -1 && best.len < 2)
+    best.base = -1;
+
+  tp = tmp;
+
+  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+  {
+    if (best.base != -1 && i >= best.base && i < (best.base + best.len))
+    {
+      if (i == best.base)
+        *tp++ = ':';
+
+      continue;
+    }
+
+    if (i != 0)
+      *tp++ = ':';
+
+    
+    if (i == 6 && best.base == 0 &&
+        (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
+    {
+      if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+        return (NULL);
+
+      tp += strlen(tp);
+
+      break;
+    }
+
+    tp += sprintf(tp, "%x", words[i]);
+  }
+
+  if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
+    *tp++ = ':';
+
+  *tp++ = '\0';
+
+  if ((tp - tmp) > size)
+    return (NULL);
+
+  return strscpy(dst, tmp, size);
+}
+
+char *inet_ntop(int af, const void *src, char *dst, int size)
+{
+  switch (af)
+  {
+  case AF_INET:
+    return (inet_ntop4(src, dst, size));
+
+  case AF_INET6:
+    return (inet_ntop6(src, dst, size));
+
+  default:
+    return (NULL);
+  }
+}
+
+int isatty(int fd)
+{
+#if !defined WINCE
+  HANDLE Hand;
+  CONSOLE_SCREEN_BUFFER_INFO Info;
+  unsigned long Events;
+
+  if (fd == 0)
+  {
+    Hand = GetStdHandle(STD_INPUT_HANDLE);
+    return GetNumberOfConsoleInputEvents(Hand, &Events);
+  }
+
+  else if (fd == 1)
+  {
+    Hand = GetStdHandle(STD_OUTPUT_HANDLE);
+    return GetConsoleScreenBufferInfo(Hand, &Info);
+  }
+
+  else if (fd == 2)
+  {
+    Hand = GetStdHandle(STD_ERROR_HANDLE);
+    return GetConsoleScreenBufferInfo(Hand, &Info);
+  }
+
+  return -1;
+#else
+  return 0;
+#endif
+}
+
+#define CHUNK_SIZE 512
+
+/* and we emulate a real write(2) syscall using send() */
+int write(int fd, const void *buf, unsigned int count)
+{
+  size_t written = 0;
+  while (written < count) {
+    ssize_t rc = send(fd, (const unsigned char*)buf+written, min(count-written, CHUNK_SIZE), 0);
+    if (rc <= 0) {
+      break;
+    }
+    written += rc;
+  }
+  return written;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/dlfcn.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/dlfcn.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/dlfcn.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/dlfcn.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_DLFCN_H_INCLUDED
+
+#define TL_DLFCN_H_INCLUDED
+
+#define RTLD_NOW 0
+
+void *dlopen(char *Name, int Flags);
+int dlclose(void *Handle);
+void *dlsym(void *Handle, const char *Name);
+char *dlerror(void);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/ifnet.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/ifnet.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/ifnet.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/ifnet.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,1072 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 <winsock2.h>
+#include "interfaces.h"
+#include "olsr.h"
+#include "parser.h"
+#include "socket_parser.h"
+#include "defs.h"
+#include "net_os.h"
+#include "ifnet.h"
+#include "generate_msg.h"
+#include "scheduler.h"
+#include "mantissa.h"
+#include "lq_packet.h"
+#include "net_olsr.h"
+
+#include <iphlpapi.h>
+#include <iprtrmib.h>
+
+#include <arpa/inet.h>
+
+#define BUFSPACE  (127*1024)	/* max. input buffer size to request */
+
+
+struct MibIpInterfaceRow
+{
+  USHORT Family;
+  ULONG64 InterfaceLuid;
+  ULONG InterfaceIndex;
+  ULONG MaxReassemblySize;
+  ULONG64 InterfaceIdentifier;
+  ULONG MinRouterAdvertisementInterval;
+  ULONG MaxRouterAdvertisementInterval;
+  BOOLEAN AdvertisingEnabled;
+  BOOLEAN ForwardingEnabled;
+  BOOLEAN WeakHostSend;
+  BOOLEAN WeakHostReceive;
+  BOOLEAN UseAutomaticMetric;
+  BOOLEAN UseNeighborUnreachabilityDetection;   
+  BOOLEAN ManagedAddressConfigurationSupported;
+  BOOLEAN OtherStatefulConfigurationSupported;
+  BOOLEAN AdvertiseDefaultRoute;
+  INT RouterDiscoveryBehavior;
+  ULONG DadTransmits;
+  ULONG BaseReachableTime;
+  ULONG RetransmitTime;
+  ULONG PathMtuDiscoveryTimeout;
+  INT LinkLocalAddressBehavior;
+  ULONG LinkLocalAddressTimeout;
+  ULONG ZoneIndices[16];
+  ULONG SitePrefixLength;
+  ULONG Metric;
+  ULONG NlMtu;    
+  BOOLEAN Connected;
+  BOOLEAN SupportsWakeUpPatterns;   
+  BOOLEAN SupportsNeighborDiscovery;
+  BOOLEAN SupportsRouterDiscovery;
+  ULONG ReachableTime;
+  BYTE TransmitOffload;
+  BYTE ReceiveOffload; 
+  BOOLEAN DisableDefaultRoutes;
+};
+
+typedef DWORD (__stdcall *GETIPINTERFACEENTRY)
+  (struct MibIpInterfaceRow *Row);
+
+typedef DWORD (__stdcall *GETADAPTERSADDRESSES)
+  (ULONG Family, DWORD Flags, PVOID Reserved,
+   PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen);
+
+struct InterfaceInfo
+{
+  unsigned int Index;
+  int Mtu;
+  int Metric;
+  unsigned int Addr;
+  unsigned int Mask;
+  unsigned int Broad;
+  char Guid[39];
+};
+
+void WinSockPError(char *);
+char *StrError(unsigned int ErrNo);
+
+void ListInterfaces(void);
+int GetIntInfo(struct InterfaceInfo *Info, char *Name);
+void RemoveInterface(struct olsr_if *IntConf);
+
+#define MAX_INTERFACES 100
+
+int __stdcall SignalHandler(unsigned long Signal);
+
+static unsigned long __stdcall SignalHandlerWrapper(void *Dummy __attribute__((unused)))
+{
+  SignalHandler(0);
+  return 0;
+}
+
+static void CallSignalHandler(void)
+{
+  unsigned long ThreadId;
+
+  CreateThread(NULL, 0, SignalHandlerWrapper, NULL, 0, &ThreadId);
+}
+
+static void MiniIndexToIntName(char *String, int MiniIndex)
+{
+  const char *HexDigits = "0123456789abcdef";
+
+  String[0] = 'i';
+  String[1] = 'f';
+
+  String[2] = HexDigits[(MiniIndex >> 4) & 15];
+  String[3] = HexDigits[MiniIndex & 15];
+
+  String[4] = 0;
+}
+
+static int IntNameToMiniIndex(int *MiniIndex, char *String)
+{
+  const char *HexDigits = "0123456789abcdef";
+  int i, k;
+  char ch;
+
+  if ((String[0] != 'i' && String[0] != 'I') ||
+      (String[1] != 'f' && String[1] != 'F'))
+    return -1;
+
+  *MiniIndex = 0;
+
+  for (i = 2; i < 4; i++)
+  {
+    ch = String[i];
+
+    if (ch >= 'A' && ch <= 'F')
+      ch += 32;
+
+    for (k = 0; k < 16 && ch != HexDigits[k]; k++);
+
+    if (k == 16)
+      return -1;
+
+    *MiniIndex = (*MiniIndex << 4) | k;
+  }
+
+  return 0;
+}
+
+static int FriendlyNameToMiniIndex(int *MiniIndex, char *String)
+{
+  unsigned long BuffLen;
+  unsigned long Res;
+  IP_ADAPTER_ADDRESSES AdAddr[MAX_INTERFACES], *WalkerAddr;
+  char FriendlyName[MAX_INTERFACE_NAME_LEN];
+  HMODULE h;
+  GETADAPTERSADDRESSES pfGetAdaptersAddresses;
+  
+  h = LoadLibrary("iphlpapi.dll");
+
+  if (h == NULL)
+  {
+    fprintf(stderr, "LoadLibrary() = %08lx", GetLastError());
+    return -1;
+  }
+
+  pfGetAdaptersAddresses = (GETADAPTERSADDRESSES) GetProcAddress(h, "GetAdaptersAddresses");
+
+  if (pfGetAdaptersAddresses == NULL)
+  {
+    fprintf(stderr, "Unable to use adapter friendly name (GetProcAddress() = %08lx)\n", GetLastError());
+    return -1;
+  }
+  
+  BuffLen = sizeof (AdAddr);
+
+  Res = pfGetAdaptersAddresses(AF_INET, 0, NULL, AdAddr, &BuffLen);
+
+  if (Res != NO_ERROR)
+  {  
+    fprintf(stderr, "GetAdaptersAddresses() = %08lx", GetLastError());
+    return -1;
+  }
+
+  for (WalkerAddr = AdAddr; WalkerAddr != NULL; WalkerAddr = WalkerAddr->Next)
+  {
+    OLSR_PRINTF(5, "Index = %08x - ", (int)WalkerAddr->IfIndex);
+
+    wcstombs(FriendlyName, WalkerAddr->FriendlyName, MAX_INTERFACE_NAME_LEN); 
+
+    OLSR_PRINTF(5, "Friendly name = %s\n", FriendlyName);
+
+    if (strncmp(FriendlyName, String, MAX_INTERFACE_NAME_LEN) == 0)
+      break;
+  }
+
+  if (WalkerAddr == NULL)
+  {
+    fprintf(stderr, "No such interface: %s!\n", String);
+    return -1;
+  }
+
+  *MiniIndex = WalkerAddr->IfIndex & 255;
+
+  return 0;
+}
+
+int GetIntInfo(struct InterfaceInfo *Info, char *Name)
+{
+  int MiniIndex;
+  unsigned char Buff[MAX_INTERFACES * sizeof (MIB_IFROW) + 4];
+  MIB_IFTABLE *IfTable;
+  unsigned long BuffLen;
+  unsigned long Res;
+  int TabIdx;
+  IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
+  HMODULE Lib;
+  struct MibIpInterfaceRow Row;
+  GETIPINTERFACEENTRY InterfaceEntry;
+
+  if (olsr_cnf->ip_version == AF_INET6)
+  {
+    fprintf(stderr, "IPv6 not supported by GetIntInfo()!\n");
+    return -1;
+  }
+
+  if ((Name[0] != 'i' && Name[0] != 'I') ||
+      (Name[1] != 'f' && Name[1] != 'F'))
+  {
+    if (FriendlyNameToMiniIndex(&MiniIndex, Name) < 0)
+    {
+      fprintf(stderr, "No such interface: %s!\n", Name);
+      return -1;
+    }
+  }
+
+  else
+  {
+    if (IntNameToMiniIndex(&MiniIndex, Name) < 0)
+    {
+      fprintf(stderr, "No such interface: %s!\n", Name);
+      return -1;
+    }
+  }
+
+  IfTable = (MIB_IFTABLE *)Buff;
+
+  BuffLen = sizeof (Buff);
+
+  Res = GetIfTable(IfTable, &BuffLen, FALSE);
+
+  if (Res != NO_ERROR)
+  {
+    fprintf(stderr, "GetIfTable() = %08lx, %s", Res, StrError(Res));
+    return -1;
+  }
+
+  for (TabIdx = 0; TabIdx < (int)IfTable->dwNumEntries; TabIdx++)
+  {
+    OLSR_PRINTF(5, "Index = %08x\n", (int)IfTable->table[TabIdx].dwIndex);
+
+    if ((int)(IfTable->table[TabIdx].dwIndex & 255) == MiniIndex)
+      break;
+  }
+
+  if (TabIdx == (int)IfTable->dwNumEntries)
+  {
+    fprintf(stderr, "No such interface: %s!\n", Name);
+    return -1;
+  }
+    
+  Info->Index = IfTable->table[TabIdx].dwIndex;
+  Info->Mtu = (int)IfTable->table[TabIdx].dwMtu;
+
+  Info->Mtu -= (olsr_cnf->ip_version == AF_INET6) ?
+    UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
+
+  Lib = LoadLibrary("iphlpapi.dll");
+
+  if (Lib == NULL)
+  {
+    fprintf(stderr, "Cannot load iphlpapi.dll: %08lx\n", GetLastError());
+    return -1;
+  }
+
+  InterfaceEntry = (GETIPINTERFACEENTRY)GetProcAddress(Lib, "GetIpInterfaceEntry");
+
+  if (InterfaceEntry == NULL)
+  {
+    OLSR_PRINTF(5, "Not running on Vista - setting interface metric to 0.\n");
+
+    Info->Metric = 0;
+  }
+
+  else
+  {
+    memset(&Row, 0, sizeof (struct MibIpInterfaceRow));
+
+    Row.Family = AF_INET;
+    Row.InterfaceIndex = Info->Index;
+
+    Res = InterfaceEntry(&Row);
+
+    if (Res != NO_ERROR)
+    {
+      fprintf(stderr, "GetIpInterfaceEntry() = %08lx", Res);
+      FreeLibrary(Lib);
+      return -1;
+    }
+
+    Info->Metric = Row.Metric;
+
+    OLSR_PRINTF(5, "Running on Vista - interface metric is %d.\n", Info->Metric);
+  }
+
+  FreeLibrary(Lib);
+
+  BuffLen = sizeof (AdInfo);
+
+  Res = GetAdaptersInfo(AdInfo, &BuffLen);
+
+  if (Res != NO_ERROR)
+  {
+    fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", GetLastError(),
+            StrError(Res));
+    return -1;
+  }
+
+  for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next)
+  {
+    OLSR_PRINTF(5, "Index = %08x\n", (int)Walker->Index);
+
+    if ((int)(Walker->Index & 255) == MiniIndex)
+      break;
+  }
+
+  if (Walker == NULL)
+  {
+    fprintf(stderr, "No such interface: %s!\n", Name);
+    return -1;
+  }
+
+  inet_pton(AF_INET, Walker->IpAddressList.IpAddress.String, &Info->Addr);
+  inet_pton(AF_INET, Walker->IpAddressList.IpMask.String, &Info->Mask);
+
+  Info->Broad = Info->Addr | ~Info->Mask;
+
+  strscpy(Info->Guid, Walker->AdapterName, sizeof(Info->Guid));
+
+  if ((IfTable->table[TabIdx].dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED &&
+      IfTable->table[TabIdx].dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL) ||
+      Info->Addr == 0)
+  {
+    OLSR_PRINTF(3, "Interface %s not up!\n", Name);
+    return -1;
+  }
+
+  return 0;
+}
+
+#if !defined OID_802_11_CONFIGURATION
+#define OID_802_11_CONFIGURATION 0x0d010211
+#endif
+
+#if !defined IOCTL_NDIS_QUERY_GLOBAL_STATS
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002
+#endif
+
+static int IsWireless(char *IntName)
+{
+#if !defined WINCE
+  struct InterfaceInfo Info;
+  char DevName[43];
+  HANDLE DevHand;
+  unsigned int ErrNo;
+  unsigned int Oid;
+  unsigned char OutBuff[100];
+  unsigned long OutBytes;
+
+  if (GetIntInfo(&Info, IntName) < 0)
+    return -1;
+
+  DevName[0] = '\\';
+  DevName[1] = '\\';
+  DevName[2] = '.';
+  DevName[3] = '\\';
+
+  strscpy(DevName + 4, Info.Guid, sizeof(DevName) - 4);
+
+  OLSR_PRINTF(5, "Checking whether interface %s is wireless.\n", DevName);
+
+  DevHand = CreateFile(DevName, GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+
+  if (DevHand == INVALID_HANDLE_VALUE)
+  {
+    ErrNo = GetLastError();
+
+    OLSR_PRINTF(5, "CreateFile() = %08x, %s\n", ErrNo, StrError(ErrNo));
+    return -1;
+  }
+
+  Oid = OID_802_11_CONFIGURATION;
+
+  if (!DeviceIoControl(DevHand, IOCTL_NDIS_QUERY_GLOBAL_STATS,
+                       &Oid, sizeof (Oid),
+                       OutBuff, sizeof (OutBuff),
+                       &OutBytes, NULL))
+  {
+    ErrNo = GetLastError();
+
+    CloseHandle(DevHand);
+
+    if (ErrNo == ERROR_GEN_FAILURE || ErrNo == ERROR_INVALID_PARAMETER)
+    {
+      OLSR_PRINTF(5, "OID not supported. Device probably not wireless.\n");
+      return 0;
+    }
+
+    OLSR_PRINTF(5, "DeviceIoControl() = %08x, %s\n", ErrNo, StrError(ErrNo));
+    return -1;
+  }
+
+  CloseHandle(DevHand);
+#endif
+  return 1;
+}
+
+void ListInterfaces(void)
+{
+  IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
+  unsigned long AdInfoLen;
+  char IntName[5];
+  IP_ADDR_STRING *Walker2;
+  unsigned long Res;
+  int IsWlan;
+  
+  if (olsr_cnf->ip_version == AF_INET6)
+  {
+    fprintf(stderr, "IPv6 not supported by ListInterfaces()!\n");
+    return;
+  }
+
+  AdInfoLen = sizeof (AdInfo);
+
+  Res = GetAdaptersInfo(AdInfo, &AdInfoLen);
+
+  if (Res == ERROR_NO_DATA)
+  {
+    printf("No interfaces detected.\n");
+    return;
+  }
+  
+  if (Res != NO_ERROR)
+  {
+    fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", Res, StrError(Res));
+    return;
+  }
+
+  for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next)
+  {
+    OLSR_PRINTF(5, "Index = %08x\n", (int)Walker->Index);
+
+    MiniIndexToIntName(IntName, Walker->Index);
+
+    printf("%s: ", IntName);
+
+    IsWlan = IsWireless(IntName);
+
+    if (IsWlan < 0)
+      printf("?");
+
+    else if (IsWlan == 0)
+      printf("-");
+
+    else
+      printf("+");
+
+    for (Walker2 = &Walker->IpAddressList; Walker2 != NULL;
+         Walker2 = Walker2->Next)
+      printf(" %s", Walker2->IpAddress.String);
+
+    printf("\n");
+  }
+}
+
+void RemoveInterface(struct olsr_if *IntConf)
+{
+  struct interface *Int, *Prev;
+
+  OLSR_PRINTF(1, "Removing interface %s.\n", IntConf->name);
+  
+  Int = IntConf->interf;
+
+  run_ifchg_cbs(Int, IFCHG_IF_ADD);
+
+  if (Int == ifnet)
+    ifnet = Int->int_next;
+
+  else
+  {
+    for (Prev = ifnet; Prev->int_next != Int; Prev = Prev->int_next);
+
+    Prev->int_next = Int->int_next;
+  }
+
+  if(ipequal(&olsr_cnf->main_addr, &Int->ip_addr))
+  {
+    if(ifnet == NULL)
+    {
+      memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize);
+      OLSR_PRINTF(1, "Removed last interface. Cleared main address.\n");
+    }
+
+    else
+    {
+      struct ipaddr_str buf;
+      olsr_cnf->main_addr = ifnet->ip_addr;
+      OLSR_PRINTF(1, "New main address: %s.\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+    }
+  }
+
+  /*
+   * Deregister functions for periodic message generation 
+   */
+  olsr_stop_timer(Int->hello_gen_timer);
+  olsr_stop_timer(Int->tc_gen_timer);
+  olsr_stop_timer(Int->mid_gen_timer);
+  olsr_stop_timer(Int->hna_gen_timer);
+
+  net_remove_buffer(Int);
+
+  IntConf->configured = 0;
+  IntConf->interf = NULL;
+
+  closesocket(Int->olsr_socket);
+  remove_olsr_socket(Int->olsr_socket, &olsr_input);
+
+  free(Int->int_name);
+  free(Int);
+
+  if (ifnet == NULL && !olsr_cnf->allow_no_interfaces)
+  {
+    OLSR_PRINTF(1, "No more active interfaces - exiting.\n");
+    olsr_cnf->exit_value = EXIT_FAILURE;
+    CallSignalHandler();
+  }
+}
+
+int add_hemu_if(struct olsr_if *iface)
+{
+  struct interface *ifp;
+  union olsr_ip_addr null_addr;
+  olsr_u32_t addr[4];
+  struct ipaddr_str buf;
+  size_t name_size;
+
+  if(!iface->host_emul)
+    return -1;
+
+  ifp = olsr_malloc(sizeof (struct interface), "Interface update 2");
+
+  memset(ifp, 0, sizeof (struct interface));
+
+  iface->configured = OLSR_TRUE;
+  iface->interf = ifp;
+
+  name_size = strlen("hcif01") + 1;
+  ifp->is_hcif = OLSR_TRUE;
+  ifp->int_name = olsr_malloc(name_size, "Interface update 3");
+  ifp->int_metric = 0;
+
+  strscpy(ifp->int_name, "hcif01", name_size);
+
+  OLSR_PRINTF(1, "Adding %s(host emulation):\n", ifp->int_name);
+
+  OLSR_PRINTF(1, "       Address:%s\n", olsr_ip_to_string(&buf, &iface->hemu_ip));
+
+  OLSR_PRINTF(1, "       NB! This is a emulated interface\n       that does not exist in the kernel!\n");
+
+  ifp->int_next = ifnet;
+  ifnet = ifp;
+
+  memset(&null_addr, 0, olsr_cnf->ipsize);
+  if(ipequal(&null_addr, &olsr_cnf->main_addr))
+    {
+      olsr_cnf->main_addr = iface->hemu_ip;
+      OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+    }
+
+  ifp->int_mtu = OLSR_DEFAULT_MTU;
+
+  ifp->int_mtu -= (olsr_cnf->ip_version == AF_INET6) ?
+    UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
+
+  /* Set up buffer */
+  net_add_buffer(ifp);
+
+
+  if(olsr_cnf->ip_version == AF_INET)
+    {
+      struct sockaddr_in sin;
+
+      memset(&sin, 0, sizeof(sin));
+
+      sin.sin_family = AF_INET;
+      sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+      sin.sin_port = htons(10150);
+ 
+     /* IP version 4 */
+      ifp->ip_addr.v4 = iface->hemu_ip.v4;
+
+      memcpy(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, &iface->hemu_ip, olsr_cnf->ipsize);
+      
+      /*
+       *We create one socket for each interface and bind
+       *the socket to it. This to ensure that we can control
+       *on what interface the message is transmitted
+       */
+      
+      ifp->olsr_socket = gethemusocket(&sin);
+      
+      if (ifp->olsr_socket < 0)
+	{
+	  fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+	  exit(1);
+	}
+
+    }
+  else
+    {
+      /* IP version 6 */
+      memcpy(&ifp->ip_addr, &iface->hemu_ip, olsr_cnf->ipsize);
+
+#if 0      
+      /*
+       *We create one socket for each interface and bind
+       *the socket to it. This to ensure that we can control
+       *on what interface the message is transmitted
+       */
+      
+      ifp->olsr_socket = gethcsocket6(&addrsock6, bufspace, ifp->int_name);
+      
+      join_mcast(ifp, ifp->olsr_socket);
+      
+      if (ifp->olsr_socket < 0)
+	{
+	  fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+	  exit(1);
+	}
+      
+#endif
+    }
+
+  /* Send IP as first 4/16 bytes on socket */
+  memcpy(addr, iface->hemu_ip.v6.s6_addr, olsr_cnf->ipsize);
+  addr[0] = htonl(addr[0]);
+  addr[1] = htonl(addr[1]);
+  addr[2] = htonl(addr[2]);
+  addr[3] = htonl(addr[3]);
+
+  if(send(ifp->olsr_socket, (char *)addr, olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize)
+    {
+      fprintf(stderr, "Error sending IP!");
+    }  
+  
+  /* Register socket */
+  add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu);
+
+  /*
+   * Register functions for periodic message generation 
+   */
+  ifp->hello_gen_timer =
+    olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC,
+                     HELLO_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
+                     ifp, hello_gen_timer_cookie->ci_id);
+  ifp->tc_gen_timer =
+    olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC,
+                     TC_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
+                     ifp, tc_gen_timer_cookie->ci_id);
+  ifp->mid_gen_timer =
+    olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC,
+                     MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
+                     mid_gen_timer_cookie->ci_id);
+  ifp->hna_gen_timer =
+    olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC,
+                     HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
+                     hna_gen_timer_cookie->ci_id);
+
+  /* Recalculate max topology hold time */
+  if(olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
+    olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
+
+  ifp->hello_etime = (olsr_reltime)(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
+  ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
+  ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
+
+  return 1;
+}
+
+int chk_if_changed(struct olsr_if *IntConf)
+{
+  struct ipaddr_str buf;
+  struct interface *Int;
+  struct InterfaceInfo Info;
+  int Res;
+  int IsWlan;
+  union olsr_ip_addr OldVal, NewVal;
+  struct sockaddr_in *AddrIn;
+
+  if (olsr_cnf->ip_version == AF_INET6)
+  {
+    fprintf(stderr, "IPv6 not supported by chk_if_changed()!\n");
+    return 0;
+  }
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Checking if %s is set down or changed\n", IntConf->name);
+#endif
+
+  Int = IntConf->interf;
+
+  if (GetIntInfo(&Info, IntConf->name) < 0)
+  {
+    RemoveInterface(IntConf);
+    return 1;
+  }
+
+  Res = 0;
+
+  IsWlan = IsWireless(IntConf->name);
+
+  if (IsWlan < 0)
+    IsWlan = 1;
+
+  if (Int->is_wireless != IsWlan)
+  {
+    OLSR_PRINTF(1, "\tLAN/WLAN change: %d -> %d.\n", Int->is_wireless, IsWlan);
+
+    Int->is_wireless = IsWlan;
+
+    if (IntConf->cnf->weight.fixed)
+      Int->int_metric = IntConf->cnf->weight.value;
+
+    else
+      Int->int_metric = Info.Metric;
+
+    Res = 1;
+  }
+
+  if (Int->int_mtu != Info.Mtu)
+  {
+    OLSR_PRINTF(1, "\tMTU change: %d -> %d.\n", (int)Int->int_mtu,
+                Info.Mtu);
+
+    Int->int_mtu = Info.Mtu;
+
+    net_remove_buffer(Int);
+    net_add_buffer(Int);
+
+    Res = 1;
+  }
+
+  OldVal.v4 = ((struct sockaddr_in *)&Int->int_addr)->sin_addr;
+  NewVal.v4.s_addr = Info.Addr;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "\tAddress: %s\n", olsr_ip_to_string(&buf, &NewVal));
+#endif
+
+  if (NewVal.v4.s_addr != OldVal.v4.s_addr)
+  {
+    OLSR_PRINTF(1, "\tAddress change.\n");
+    OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
+    OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
+
+    Int->ip_addr.v4 = NewVal.v4;
+
+    AddrIn = (struct sockaddr_in *)&Int->int_addr;
+
+    AddrIn->sin_family = AF_INET;
+    AddrIn->sin_port = 0;
+    AddrIn->sin_addr = NewVal.v4;
+
+    if (olsr_cnf->main_addr.v4.s_addr == OldVal.v4.s_addr)
+    {
+      OLSR_PRINTF(1, "\tMain address change.\n");
+
+      olsr_cnf->main_addr.v4 = NewVal.v4;
+    }
+
+    Res = 1;
+  }
+
+  else
+    OLSR_PRINTF(3, "\tNo address change.\n");
+
+  OldVal.v4 = ((struct sockaddr_in *)&Int->int_netmask)->sin_addr;
+  NewVal.v4.s_addr = Info.Mask;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "\tNetmask: %s\n", olsr_ip_to_string(&buf, &NewVal));
+#endif
+
+  if (NewVal.v4.s_addr != OldVal.v4.s_addr)
+  {
+    OLSR_PRINTF(1, "\tNetmask change.\n");
+    OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
+    OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
+
+    AddrIn = (struct sockaddr_in *)&Int->int_netmask;
+
+    AddrIn->sin_family = AF_INET;
+    AddrIn->sin_port = 0;
+    AddrIn->sin_addr = NewVal.v4;
+
+    Res = 1;
+  }
+
+  else
+    OLSR_PRINTF(3, "\tNo netmask change.\n");
+
+  OldVal.v4 = ((struct sockaddr_in *)&Int->int_broadaddr)->sin_addr;
+  NewVal.v4.s_addr = Info.Broad;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "\tBroadcast address: %s\n", olsr_ip_to_string(&buf, &NewVal));
+#endif
+
+  if (NewVal.v4.s_addr != OldVal.v4.s_addr)
+  {
+    OLSR_PRINTF(1, "\tBroadcast address change.\n");
+    OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
+    OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
+
+    AddrIn = (struct sockaddr_in *)&Int->int_broadaddr;
+
+    AddrIn->sin_family = AF_INET;
+    AddrIn->sin_port = 0;
+    AddrIn->sin_addr = NewVal.v4;
+
+    Res = 1;
+  }
+
+  else
+    OLSR_PRINTF(3, "\tNo broadcast address change.\n");
+
+  if (Res != 0)
+    run_ifchg_cbs(Int, IFCHG_IF_UPDATE);
+
+  return Res;
+}
+
+int chk_if_up(struct olsr_if *IntConf, int DebugLevel __attribute__((unused)))
+{
+  struct ipaddr_str buf;
+  struct InterfaceInfo Info;
+  struct interface *New;
+  union olsr_ip_addr NullAddr;
+  int IsWlan;
+  struct sockaddr_in *AddrIn;
+  size_t name_size;
+  
+  if (olsr_cnf->ip_version == AF_INET6)
+  {
+    fprintf(stderr, "IPv6 not supported by chk_if_up()!\n");
+    return 0;
+  }
+
+  if (GetIntInfo(&Info, IntConf->name) < 0)
+    return 0;
+
+  New = olsr_malloc(sizeof (struct interface), "Interface 1");
+
+  New->immediate_send_tc = (IntConf->cnf->tc_params.emission_interval < IntConf->cnf->hello_params.emission_interval);
+  if (olsr_cnf->max_jitter == 0)
+  {
+    /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
+    olsr_cnf->max_jitter = New->immediate_send_tc ? IntConf->cnf->tc_params.emission_interval : IntConf->cnf->hello_params.emission_interval;
+  }
+
+  New->gen_properties = NULL;
+
+  AddrIn = (struct sockaddr_in *)&New->int_addr;
+
+  AddrIn->sin_family = AF_INET;
+  AddrIn->sin_port = 0;
+  AddrIn->sin_addr.s_addr = Info.Addr;
+
+  AddrIn = (struct sockaddr_in *)&New->int_netmask;
+
+  AddrIn->sin_family = AF_INET;
+  AddrIn->sin_port = 0;
+  AddrIn->sin_addr.s_addr = Info.Mask;
+
+  AddrIn = (struct sockaddr_in *)&New->int_broadaddr;
+
+  AddrIn->sin_family = AF_INET;
+  AddrIn->sin_port = 0;
+  AddrIn->sin_addr.s_addr = Info.Broad;
+
+  if (IntConf->cnf->ipv4_broadcast.v4.s_addr != 0)
+    AddrIn->sin_addr = IntConf->cnf->ipv4_broadcast.v4;
+
+  New->int_flags = 0;
+
+  New->is_hcif = OLSR_FALSE;
+
+  New->int_mtu = Info.Mtu;
+
+  name_size = strlen(IntConf->name) + 1;
+  New->int_name = olsr_malloc(name_size, "Interface 2");
+  strscpy(New->int_name, IntConf->name, name_size);
+
+  IsWlan = IsWireless(IntConf->name);
+
+  if (IsWlan < 0)
+    IsWlan = 1;
+
+  New->is_wireless = IsWlan;
+
+  if (IntConf->cnf->weight.fixed)
+    New->int_metric = IntConf->cnf->weight.value;
+
+  else
+    New->int_metric = Info.Metric;
+
+  New->olsr_seqnum = random() & 0xffff;
+
+  New->ttl_index = -32; /* For the first 32 TC's, fish-eye is disabled */
+    
+  OLSR_PRINTF(1, "\tInterface %s set up for use with index %d\n\n",
+              IntConf->name, New->if_index);
+      
+  OLSR_PRINTF(1, "\tMTU: %d\n", New->int_mtu);
+  OLSR_PRINTF(1, "\tAddress: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr*)&New->int_addr));
+  OLSR_PRINTF(1, "\tNetmask: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr*)&New->int_netmask));
+  OLSR_PRINTF(1, "\tBroadcast address: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr*)&New->int_broadaddr));
+
+  New->ip_addr.v4 = New->int_addr.sin_addr;
+      
+  New->if_index = Info.Index;
+
+  OLSR_PRINTF(3, "\tKernel index: %08x\n", New->if_index);
+
+  New->olsr_socket = getsocket(BUFSPACE, New->int_name);
+      
+  if (New->olsr_socket < 0)
+  {
+    fprintf(stderr, "Could not initialize socket... exiting!\n\n");
+    exit(1);
+  }
+
+  add_olsr_socket(New->olsr_socket, &olsr_input);
+
+  New->int_next = ifnet;
+  ifnet = New;
+
+  IntConf->interf = New;
+  IntConf->configured = 1;
+
+  memset(&NullAddr, 0, olsr_cnf->ipsize);
+  
+  if(ipequal(&NullAddr, &olsr_cnf->main_addr))
+  {
+    olsr_cnf->main_addr = New->ip_addr;
+    OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+  }
+
+  net_add_buffer(New);
+
+  /*
+   * Register functions for periodic message generation 
+   */
+  New->hello_gen_timer =
+    olsr_start_timer(IntConf->cnf->hello_params.emission_interval * MSEC_PER_SEC,
+                     HELLO_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello,
+                     New, hello_gen_timer_cookie->ci_id);
+  New->tc_gen_timer =
+    olsr_start_timer(IntConf->cnf->tc_params.emission_interval * MSEC_PER_SEC,
+                     TC_JITTER, OLSR_TIMER_PERIODIC,
+                     olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc,
+                     New, tc_gen_timer_cookie->ci_id);
+  New->mid_gen_timer =
+    olsr_start_timer(IntConf->cnf->mid_params.emission_interval * MSEC_PER_SEC,
+                     MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, New,
+                     mid_gen_timer_cookie->ci_id);
+  New->hna_gen_timer =
+    olsr_start_timer(IntConf->cnf->hna_params.emission_interval * MSEC_PER_SEC,
+                     HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, New,
+                     hna_gen_timer_cookie->ci_id);
+
+  if(olsr_cnf->max_tc_vtime < IntConf->cnf->tc_params.emission_interval)
+    olsr_cnf->max_tc_vtime = IntConf->cnf->tc_params.emission_interval;
+
+  New->hello_etime = (olsr_reltime)(IntConf->cnf->hello_params.emission_interval * MSEC_PER_SEC);
+  New->valtimes.hello = reltime_to_me(IntConf->cnf->hello_params.validity_time * MSEC_PER_SEC);
+  New->valtimes.tc = reltime_to_me(IntConf->cnf->tc_params.validity_time * MSEC_PER_SEC);
+  New->valtimes.mid = reltime_to_me(IntConf->cnf->mid_params.validity_time * MSEC_PER_SEC);
+  New->valtimes.hna = reltime_to_me(IntConf->cnf->hna_params.validity_time * MSEC_PER_SEC);
+
+  run_ifchg_cbs(New, IFCHG_IF_ADD);
+
+  return 1;
+}
+
+void check_interface_updates(void *dummy __attribute__((unused)))
+{
+  struct olsr_if *IntConf;
+
+#ifdef DEBUG
+  OLSR_PRINTF(3, "Checking for updates in the interface set\n");
+#endif
+
+  for(IntConf = olsr_cnf->interfaces; IntConf != NULL; IntConf = IntConf->next)
+  {
+    if(IntConf->host_emul)
+      continue;
+      
+    if(olsr_cnf->host_emul) /* XXX: TEMPORARY! */
+      continue;
+ 
+    if(IntConf->configured)    
+      chk_if_changed(IntConf);
+
+    else
+      chk_if_up(IntConf, 3);
+  }
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/kernel_routes.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/kernel_routes.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/kernel_routes.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/kernel_routes.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,201 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 <stdio.h>
+#include "net/route.h"
+
+#include "kernel_routes.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+#include "ipc_frontend.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <iprtrmib.h>
+#include <iphlpapi.h>
+
+char *StrError(unsigned int ErrNo);
+
+/**
+ *Insert a route in the kernel routing table
+ *
+ *@param destination the route to add
+ *
+ *@return negative on error
+ */
+int olsr_ioctl_add_route(const struct rt_entry *rt)
+{
+  MIB_IPFORWARDROW Row;
+  union olsr_ip_addr mask;
+  unsigned long Res;
+  struct interface *iface = if_ifwithindex(rt->rt_best->rtp_nexthop.iif_index);
+
+  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rt_to_string(rt));
+
+  memset(&Row, 0, sizeof (MIB_IPFORWARDROW));
+
+  Row.dwForwardDest = rt->rt_dst.prefix.v4.s_addr;
+
+  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
+    return -1;
+  } else {
+      Row.dwForwardMask = mask.v4.s_addr;
+  }
+
+  Row.dwForwardPolicy = 0;
+  Row.dwForwardNextHop = rt->rt_best->rtp_nexthop.gateway.v4.s_addr;
+  Row.dwForwardIfIndex = rt->rt_best->rtp_nexthop.iif_index;
+  // MIB_IPROUTE_TYPE_DIRECT and MIB_IPROUTE_TYPE_INDIRECT
+  Row.dwForwardType = (rt->rt_dst.prefix.v4.s_addr == rt->rt_best->rtp_nexthop.gateway.v4.s_addr) ? 3 : 4;
+  Row.dwForwardProto = 3; // MIB_IPPROTO_NETMGMT
+  Row.dwForwardAge = INFINITE;
+  Row.dwForwardNextHopAS = 0;
+  Row.dwForwardMetric1 = iface ? iface->int_metric : 0 + olsr_fib_metric(&rt->rt_best->rtp_metric);
+  Row.dwForwardMetric2 = -1;
+  Row.dwForwardMetric3 = -1;
+  Row.dwForwardMetric4 = -1;
+  Row.dwForwardMetric5 = -1;
+
+  Res = SetIpForwardEntry(&Row);
+
+  if (Res != NO_ERROR)
+  {
+    if (Res != ERROR_NOT_FOUND)
+      fprintf(stderr, "SetIpForwardEntry() = %08lx, %s", Res, StrError(Res));
+
+    Res = CreateIpForwardEntry(&Row);
+  }
+
+  if (Res != NO_ERROR)
+  {
+    fprintf(stderr, "CreateIpForwardEntry() = %08lx, %s", Res, StrError(Res));
+
+    // XXX - report error in a different way
+
+    errno = Res;
+
+    return -1;
+  }
+
+  /*
+   * Send IPC route update message
+   */
+  if (olsr_cnf->ipc_connections > 0) {
+    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway,
+        rt->rt_best->rtp_metric.hops, 1,
+        if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
+  }
+
+  return 0;
+}
+
+// XXX - to be implemented
+
+int olsr_ioctl_add_route6(const struct rt_entry *rt __attribute__((unused)))
+{
+  return 0;
+}
+
+/**
+ *Remove a route from the kernel
+ *
+ *@param destination the route to remove
+ *
+ *@return negative on error
+ */
+int olsr_ioctl_del_route(const struct rt_entry *rt)
+{
+  MIB_IPFORWARDROW Row;
+  union olsr_ip_addr mask;
+  unsigned long Res;
+  struct interface *iface = if_ifwithindex(rt->rt_nexthop.iif_index);
+
+  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));
+
+  memset(&Row, 0, sizeof (Row));
+
+  Row.dwForwardDest = rt->rt_dst.prefix.v4.s_addr;
+
+  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
+    return -1;
+  }
+  Row.dwForwardMask = mask.v4.s_addr;
+  Row.dwForwardPolicy = 0;
+  Row.dwForwardNextHop = rt->rt_nexthop.gateway.v4.s_addr;
+  Row.dwForwardIfIndex = rt->rt_nexthop.iif_index;
+  // MIB_IPROUTE_TYPE_DIRECT and MIB_IPROUTE_TYPE_INDIRECT
+  Row.dwForwardType = (rt->rt_dst.prefix.v4.s_addr == rt->rt_nexthop.gateway.v4.s_addr) ? 3 : 4;
+  Row.dwForwardProto = 3; // MIB_IPPROTO_NETMGMT
+  Row.dwForwardAge = INFINITE;
+  Row.dwForwardNextHopAS = 0;
+  Row.dwForwardMetric1 = iface ? iface->int_metric : 0 + olsr_fib_metric(&rt->rt_metric);
+  Row.dwForwardMetric2 = -1;
+  Row.dwForwardMetric3 = -1;
+  Row.dwForwardMetric4 = -1;
+  Row.dwForwardMetric5 = -1;
+
+  Res = DeleteIpForwardEntry(&Row);
+
+  if (Res != NO_ERROR)
+  {
+    fprintf(stderr, "DeleteIpForwardEntry() = %08lx, %s", Res, StrError(Res));
+
+    // XXX - report error in a different way
+
+    errno = Res;
+
+    return -1;
+  }
+
+  /*
+   * Send IPC route update message
+   */
+  if (olsr_cnf->ipc_connections > 0) {
+    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0 , 0, NULL);
+  }
+
+  return 0;
+}
+
+// XXX - to be implemented
+
+int olsr_ioctl_del_route6(const struct rt_entry *rt __attribute__((unused)))
+{
+  return 0;
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/log.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/log.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/log.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/log.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,49 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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 "../log.h"
+
+void olsr_openlog(const char *Id __attribute__((unused)))
+{
+}
+
+void olsr_syslog(int Level __attribute__((unused)), const char *Format __attribute__((unused)), ...)
+{
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/misc.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/misc.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/misc.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/misc.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,75 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef interface
+
+#include <misc.h>
+
+void clear_console(void)
+{
+#if !defined WINCE
+  HANDLE Hand;
+  CONSOLE_SCREEN_BUFFER_INFO Info;
+  unsigned long Written;
+  static COORD Home = { 0, 0 };
+
+  Hand = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  if (Hand == INVALID_HANDLE_VALUE)
+    return;
+
+  if(!GetConsoleScreenBufferInfo(Hand, &Info))
+    return;
+
+  if(!FillConsoleOutputCharacter(Hand, ' ',
+                                 Info.dwSize.X * Info.dwSize.Y, Home,
+                                 &Written))
+    return;
+
+  if(!FillConsoleOutputAttribute(Hand, Info.wAttributes,
+                                 Info.dwSize.X * Info.dwSize.Y, Home,
+                                 &Written))
+    return;
+
+  SetConsoleCursorPosition(Hand, Home);
+#endif
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/net/if.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/net/if.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/net/if.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/net/if.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/net/route.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/net/route.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/net/route.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/net/route.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,49 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_NET_ROUTE_H_INCLUDED
+
+#define TL_NET_ROUTE_H_INCLUDED
+
+#define RTF_UP 1
+#define RTF_HOST 2
+#define RTF_GATEWAY 4
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/net.c ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/net.c
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/net.c	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/net.c	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,473 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if defined WINCE
+#include <sys/types.h> // for time_t
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <iphlpapi.h>
+#undef interface
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "defs.h"
+#include "net_os.h"
+#include "net_olsr.h"
+#include "ipcalc.h"
+
+#if defined WINCE
+#define WIDE_STRING(s) L##s
+#else
+#define WIDE_STRING(s) s
+#endif
+
+void WinSockPError(const char *Str);
+void PError(const char *);
+
+void DisableIcmpRedirects(void);
+int disable_ip_forwarding(int Ver);
+
+
+int
+gethemusocket(struct sockaddr_in *pin)
+{
+  int sock;
+
+  OLSR_PRINTF(1, "       Connecting to switch daemon port 10150...");
+
+  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
+    {
+      perror("hcsocket");
+      return (-1);
+    }
+
+  /* connect to PORT on HOST */
+  if (connect(sock,(struct sockaddr *) pin, sizeof(*pin)) < 0) 
+    {
+      printf("FAILED\n");
+      fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
+      printf("connection refused\n");
+      closesocket(sock);
+      return (-1);
+    }
+
+  printf("OK\n");
+
+  /* Keep TCP socket blocking */  
+  return (sock);
+}
+
+int getsocket(int BuffSize, char *Int __attribute__((unused)))
+{
+  struct sockaddr_in Addr;
+  int On = 1;
+  unsigned long Len;
+  int Sock = socket(AF_INET, SOCK_DGRAM, 0);
+  if (Sock < 0)
+  {
+    WinSockPError("getsocket/socket()");
+    return -1;
+  }
+
+  if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
+                 (char *)&On, sizeof (On)) < 0)
+  {
+    WinSockPError("getsocket/setsockopt(SO_BROADCAST)");
+    closesocket(Sock);
+    return -1;
+  }
+
+  if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR,
+                 (char *)&On, sizeof (On)) < 0)
+  {
+    WinSockPError("getsocket/setsockopt(SO_REUSEADDR)");
+    closesocket(Sock);
+    return -1;
+  }
+
+  while (BuffSize > 8192)
+  {
+    if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
+                   sizeof (BuffSize)) == 0)
+      break;
+
+    BuffSize -= 1024;
+  }
+
+  if (BuffSize <= 8192) 
+    fprintf(stderr, "Cannot set IPv4 socket receive buffer.\n");
+
+  memset(&Addr, 0, sizeof (Addr));
+  Addr.sin_family = AF_INET;
+  Addr.sin_port = htons(OLSRPORT);
+  Addr.sin_addr.s_addr = INADDR_ANY;
+  if (bind(Sock, (struct sockaddr *)&Addr, sizeof (Addr)) < 0)
+  {
+    WinSockPError("getsocket/bind()");
+    closesocket(Sock);
+    return -1;
+  }
+
+  if (WSAIoctl(Sock, FIONBIO, &On, sizeof (On), NULL, 0, &Len, NULL, NULL) < 0)
+  {
+    WinSockPError("WSAIoctl");
+    closesocket(Sock);
+    return -1;
+  }
+
+  return Sock;
+}
+
+int getsocket6(int BuffSize, char *Int __attribute__((unused)))
+{
+  struct sockaddr_in6 Addr6;
+  int On = 1;
+  int Sock = socket(AF_INET6, SOCK_DGRAM, 0);
+  if (Sock < 0)
+  {
+    WinSockPError("getsocket6/socket()");
+    return -1;
+  }
+
+  if (setsockopt(Sock, SOL_SOCKET, SO_BROADCAST,
+                 (char *)&On, sizeof (On)) < 0)
+  {
+    WinSockPError("getsocket6/setsockopt(SO_BROADCAST)");
+    closesocket(Sock);
+    return -1;
+  }
+
+  if (setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR,
+                 (char *)&On, sizeof (On)) < 0)
+  {
+    WinSockPError("getsocket6/setsockopt(SO_REUSEADDR)");
+    closesocket(Sock);
+    return -1;
+  }
+
+  while (BuffSize > 8192)
+  {
+    if (setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char *)&BuffSize,
+                   sizeof (BuffSize)) == 0)
+      break;
+
+    BuffSize -= 1024;
+  }
+
+  if (BuffSize <= 8192) 
+    fprintf(stderr, "Cannot set IPv6 socket receive buffer.\n");
+
+  memset(&Addr6, 0, sizeof (Addr6));
+  Addr6.sin6_family = AF_INET6;
+  Addr6.sin6_port = htons(OLSRPORT);
+  //Addr6.sin6_addr.s_addr = IN6ADDR_ANY_INIT;
+  if (bind(Sock, (struct sockaddr *)&Addr6, sizeof (Addr6)) < 0)
+  {
+    WinSockPError("getsocket6/bind()");
+    closesocket(Sock);
+    return -1;
+  }
+
+  return Sock;
+}
+
+static OVERLAPPED RouterOver;
+
+int enable_ip_forwarding(int Ver)
+{
+  HMODULE Lib;
+  unsigned int __stdcall (*EnableRouter)(HANDLE *Hand, OVERLAPPED *Over);
+  HANDLE Hand;
+
+  Ver = Ver;
+
+  Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
+
+  if (Lib == NULL)
+    return 0;
+
+  EnableRouter = (unsigned int __stdcall (*)(HANDLE *, OVERLAPPED *))
+    GetProcAddress(Lib, WIDE_STRING("EnableRouter"));
+
+  if (EnableRouter == NULL)
+    return 0;
+
+  memset(&RouterOver, 0, sizeof (OVERLAPPED));
+
+  RouterOver.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+  if (RouterOver.hEvent == NULL)
+  {
+    PError("CreateEvent()");
+    return -1;
+  }
+  
+  if (EnableRouter(&Hand, &RouterOver) != ERROR_IO_PENDING)
+  {
+    PError("EnableRouter()");
+    return -1;
+  }
+
+  OLSR_PRINTF(3, "Routing enabled.\n");
+
+  return 0;
+}
+
+int disable_ip_forwarding(int Ver)
+{
+  HMODULE Lib;
+  unsigned int  __stdcall (*UnenableRouter)(OVERLAPPED *Over,
+                                            unsigned int *Count);
+  unsigned int Count;
+
+  Ver = Ver;
+  
+  Lib = LoadLibrary(WIDE_STRING("iphlpapi.dll"));
+
+  if (Lib == NULL)
+    return 0;
+
+  UnenableRouter = (unsigned int __stdcall (*)(OVERLAPPED *, unsigned int *))
+    GetProcAddress(Lib, WIDE_STRING("UnenableRouter"));
+
+  if (UnenableRouter == NULL)
+    return 0;
+
+  if (UnenableRouter(&RouterOver, &Count) != NO_ERROR)
+  {
+    PError("UnenableRouter()");
+    return -1;
+  }
+
+  OLSR_PRINTF(3, "Routing disabled, count = %u.\n", Count);
+
+  return 0;
+}
+
+int restore_settings(int Ver)
+{
+  disable_ip_forwarding(Ver);
+
+  return 0;
+}
+
+static int SetEnableRedirKey(unsigned long New)
+{
+#if !defined WINCE
+  HKEY Key;
+  unsigned long Type;
+  unsigned long Len;
+  unsigned long Old;
+
+  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                   "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+                   0, KEY_READ | KEY_WRITE, &Key) != ERROR_SUCCESS)
+    return -1;
+
+  Len = sizeof (Old);
+
+  if (RegQueryValueEx(Key, "EnableICMPRedirect", NULL, &Type,
+                      (unsigned char *)&Old, &Len) != ERROR_SUCCESS ||
+      Type != REG_DWORD)
+    Old = 1;
+
+  if (RegSetValueEx(Key, "EnableICMPRedirect", 0, REG_DWORD,
+                    (unsigned char *)&New, sizeof (New)))
+  {
+    RegCloseKey(Key);
+    return -1;
+  }
+
+  RegCloseKey(Key);
+  return Old;
+#else
+  return 0;
+#endif
+}
+
+void DisableIcmpRedirects(void)
+{
+  int Res;
+
+  Res = SetEnableRedirKey(0);
+
+  if (Res != 1)
+    return;
+
+  fprintf(stderr, "\n*** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT *** IMPORTANT ***\n\n");
+
+#if 0
+  if (Res < 0)
+  {
+    fprintf(stderr, "Cannot disable ICMP redirect processing in the registry.\n");
+    fprintf(stderr, "Please disable it manually. Continuing in 3 seconds...\n");
+    Sleep(3000);
+
+    return;
+  }
+#endif
+
+  fprintf(stderr, "I have disabled ICMP redirect processing in the registry for you.\n");
+  fprintf(stderr, "REBOOT NOW, so that these changes take effect. Exiting...\n\n");
+
+  exit(0);
+}
+
+
+int join_mcast(struct interface *Nic, int Sock)
+{
+  /* See linux/in6.h */
+  struct ipaddr_str buf;
+  struct ipv6_mreq McastReq;
+
+  McastReq.ipv6mr_multiaddr = Nic->int6_multaddr.sin6_addr;
+  McastReq.ipv6mr_interface = Nic->if_index;
+
+  OLSR_PRINTF(3, "Interface %s joining multicast %s...", Nic->int_name, olsr_ip_to_string(&buf, (union olsr_ip_addr *)&Nic->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;
+    }
+
+  /* Old libc fix */
+#ifdef IPV6_JOIN_GROUP
+  /* Join reciever group */
+  if(setsockopt(Sock, 
+		IPPROTO_IPV6, 
+		IPV6_JOIN_GROUP, 
+		(char *)&McastReq, 
+		sizeof(struct ipv6_mreq)) 
+     < 0)
+#else
+  /* Join reciever group */
+  if(setsockopt(Sock, 
+		IPPROTO_IPV6, 
+		IPV6_ADD_MEMBERSHIP, 
+		(char *)&McastReq, 
+		sizeof(struct ipv6_mreq)) 
+     < 0)
+#endif 
+    {
+      perror("Join multicast send");
+      return -1;
+    }
+
+  
+  if(setsockopt(Sock, 
+		IPPROTO_IPV6, 
+		IPV6_MULTICAST_IF, 
+		(char *)&McastReq.ipv6mr_interface, 
+		sizeof(McastReq.ipv6mr_interface)) 
+     < 0)
+    {
+      perror("Set multicast if");
+      return -1;
+    }
+
+
+  OLSR_PRINTF(3, "OK\n");
+  return 0;
+}
+
+
+/**
+ * Wrapper for sendto(2)
+ */
+
+ssize_t
+olsr_sendto(int s, 
+	    const void *buf, 
+	    size_t len, 
+	    int flags, 
+	    const struct sockaddr *to, 
+	    socklen_t tolen)
+{
+  return sendto(s, buf, len, flags, to, tolen);
+}
+
+
+/**
+ * Wrapper for recvfrom(2)
+ */
+
+ssize_t  
+olsr_recvfrom(int  s, 
+	      void *buf, 
+	      size_t len, 
+	      int flags __attribute__((unused)), 
+	      struct sockaddr *from,
+	      socklen_t *fromlen)
+{
+  return recvfrom(s, 
+		  buf, 
+		  len, 
+		  0, 
+		  from, 
+		  fromlen);
+}
+
+/**
+ * Wrapper for select(2)
+ */
+
+int
+olsr_select(int nfds,
+            fd_set *readfds,
+            fd_set *writefds,
+            fd_set *exceptfds,
+            struct timeval *timeout)
+{
+  return select(nfds,
+                readfds,
+                writefds,
+                exceptfds,
+                timeout);
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/netinet/in.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/netinet/in.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/netinet/in.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/netinet/in.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,50 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_NETINET_IN_H_INCLUDED
+
+#define TL_NETINET_IN_H_INCLUDED
+
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#undef interface
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/ioctl.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/ioctl.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/ioctl.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/ioctl.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/socket.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/socket.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/socket.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/socket.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_SYS_SOCKET_H_INCLUDED
+
+#define TL_SYS_SOCKET_H_INCLUDED
+
+#define MSG_NOSIGNAL 0
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/time.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/time.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/time.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/time.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,94 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_SYS_TIME_H_INCLUDED
+
+#define TL_SYS_TIME_H_INCLUDED
+
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#undef interface
+
+#define timeradd(x, y, z)                       \
+  do                                            \
+  {                                             \
+    (z)->tv_sec = (x)->tv_sec + (y)->tv_sec;    \
+                                                \
+    (z)->tv_usec = (x)->tv_usec + (y)->tv_usec; \
+                                                \
+    if ((z)->tv_usec >= 1000000)                \
+    {                                           \
+      (z)->tv_sec++;                            \
+      (z)->tv_usec -= 1000000;                  \
+    }                                           \
+  }                                             \
+  while (0)
+
+#define timersub(x, y, z)                       \
+  do                                            \
+  {                                             \
+    (z)->tv_sec = (x)->tv_sec - (y)->tv_sec;    \
+                                                \
+    (z)->tv_usec = (x)->tv_usec - (y)->tv_usec; \
+                                                \
+    if ((z)->tv_usec < 0)                       \
+    {                                           \
+      (z)->tv_sec--;                            \
+      (z)->tv_usec += 1000000;                  \
+    }                                           \
+  }                                             \
+  while (0)
+
+#if !defined WINCE
+struct timespec
+{
+  unsigned int tv_sec;
+  unsigned int tv_nsec;
+};
+#else
+#include <time.h>
+#endif
+
+int nanosleep(struct timespec *Req, struct timespec *Rem);
+
+void gettimeofday(struct timeval *TVal, void *TZone);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/times.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/times.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/times.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/times.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_SYS_TIMES_H_INCLUDED
+
+#define TL_SYS_TIMES_H_INCLUDED
+
+struct tms
+{
+  int dummy;
+};
+
+long times(struct tms *);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/utsname.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/utsname.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/sys/utsname.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/sys/utsname.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/unistd.h ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/unistd.h
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/src/win32/unistd.h	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/src/win32/unistd.h	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,61 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon (olsrd)
+ * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
+ * 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.
+ *
+ */
+
+#if !defined TL_UNISTD_H_INCLUDED
+
+#include <stddef.h>
+
+#define TL_UNISTD_H_INCLUDED
+
+void sleep(unsigned int Sec);
+
+void srandom(unsigned int Seed);
+unsigned int random(void);
+
+char *StrError(unsigned int ErrNo);
+
+int getpid(void);
+
+#define IPTOS_TOS(x) ((x) & 0x1e)
+#define IPTOS_PREC(x) ((x) & 0xe0)
+
+int isatty(int fd);
+
+#endif
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/valgrind-howto.txt ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/valgrind-howto.txt
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd/valgrind-howto.txt	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd/valgrind-howto.txt	2008-10-03 14:45:07.000000000 +0200
@@ -0,0 +1,28 @@
+Valgrind is a powerful tool for performance and correctness analysis of code.
+This mini-howto discusses how to set your development environment up,
+such that you can profile a running olsr daemon and later analyze its
+recordings using a graphical frontend called Kcachegrind.
+
+First patch your makefile such that the debug symbols are not removed after
+compilation
+
+    diff -r 26494c58ff86 Makefile.inc
+    --- a/Makefile.inc Wed Jan 09 22:01:18 2008 +0100
+    +++ b/Makefile.inc Thu Jan 10 14:46:27 2008 +0100
+    @@ -5,10 +5,10 @@
+    #
+    # activate debugging with 1 or deactivate with 0
+    -DEBUG ?= 0
+    +DEBUG ?= 1
+    # compile OLSR_PRINTF out
+    -NO_DEBUG_MESSAGES ?= 0
+    +NO_DEBUG_MESSAGES ?= 1
+
+Next run valgrind with the following command line options.
+
+valgrind --tool=callgrind -v --dump-instr=yes --trace-jump=yes ./olsrd -d 0 -nofork
+
+Finally load kcachgrind to display the profiling data. (watch out the callgrind
+data are written with a umask of 600 as user root - so you may want to chown or
+chmod the file, otherwise kcachegrind cannot open your data and will display an
+empty screen)
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd-additional/olsrd.conf ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd-additional/olsrd.conf
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd-additional/olsrd.conf	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd-additional/olsrd.conf	2008-11-05 23:20:51.000000000 +0100
@@ -0,0 +1,39 @@
+DebugLevel 0
+IpVersion 4
+AllowNoInt yes
+Pollrate 0.025
+TcRedundancy 2
+MprCoverage 7
+LinkQualityFishEye 1
+LinkQualityWinSize 100
+LinkQualityDijkstraLimit 0 10.0
+LinkQualityLevel 2
+UseHysteresis no
+FIBMetric "flat"
+ClearScreen yes
+Willingness 3
+LinkQualityAging 0.1
+LinkQualityAlgorithm "etx_fpm"
+
+Interface "eth0"
+{
+        HelloInterval 5.0
+        HelloValidityTime 125.0
+        TcInterval 2.0
+        TcValidityTime 500.0
+        MidInterval 25.0
+        MidValidityTime 500.0
+        HnaInterval 25.0
+        HnaValidityTime 500.0
+}
+Interface "ath0"
+{
+        HelloInterval 5.0
+        HelloValidityTime 125.0
+        TcInterval 2.0
+        TcValidityTime 500.0
+        MidInterval 25.0
+        MidValidityTime 500.0
+        HnaInterval 25.0
+        HnaValidityTime 500.0
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd-additional/olsrd-init ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd-additional/olsrd-init
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd-additional/olsrd-init	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd-additional/olsrd-init	2008-11-05 23:20:51.000000000 +0100
@@ -0,0 +1,13 @@
+plugin_start() {
+  rm /etc/olsrd.conf
+  if [ -f /etc/persistent/olsrd.conf ]; then
+    ln -s /etc/persistent/olsrd.conf /etc/olsrd.conf
+  else
+    ln -s /usr/etc/olsrd.conf /etc/olsrd.conf
+  fi
+}
+plugin_stop() {
+  kill `pidof olsrd`
+  true
+}
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd.mk ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd.mk
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/gpl/olsrd.mk	1970-01-01 01:00:00.000000000 +0100
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/gpl/olsrd.mk	2008-11-04 15:19:33.000000000 +0100
@@ -0,0 +1,34 @@
+.PHONY: olsrd olsrd-install olsrd-clean
+
+olsrd: 
+	LDFLAGS="${build_ldflags}" \
+	CFLAGS="${build_cflags} -Os -I${BUILDDIR}/apps/gpl" \
+	CC="${build_toolchain_prefix}gcc" \
+	LD="${build_toolchain_prefix}gcc" \
+	AR="${build_toolchain_prefix}ar" \
+	RANLIB="${build_toolchain_prefix}ranlib" \
+	OS="linux" \
+	NODEBUG=1 \
+	SUBDIRS="bmf dot_draw dyn_gw httpinfo nameservice txtinfo" \
+	$(MAKE) -C olsrd all libs
+
+olsrd-clean:
+	SUBDIRS="bmf dot_draw dyn_gw httpinfo nameservice txtinfo" \
+	$(MAKE) -C olsrd clean clean_libs || echo "Ignoring olsrd-clean errors"
+
+olsrd-install: olsrd
+	mkdir -p $(build_install_directory)/sbin/
+	cp -f olsrd/olsrd $(build_install_directory)/sbin/
+	$(STRIP) $(build_install_directory)/sbin/olsrd
+	mkdir -p $(build_install_directory)/usr/etc/init.d/
+	cp -f olsrd-additional/olsrd.conf $(build_install_directory)/usr/etc/
+	cp -f olsrd-additional/olsrd-init $(build_install_directory)/usr/etc/init.d/olsrd
+	mkdir -p $(build_install_directory)/lib/
+	cp -f olsrd/lib/dot_draw/olsrd_dot_draw.so.* $(build_install_directory)/lib/
+	cp -f olsrd/lib/bmf/olsrd_bmf.so.* $(build_install_directory)/lib/
+	cp -f olsrd/lib/dyn_gw/olsrd_dyn_gw.so.* $(build_install_directory)/lib/
+	cp -f olsrd/lib/httpinfo/olsrd_httpinfo.so.* $(build_install_directory)/lib/
+	cp -f olsrd/lib/nameservice/olsrd_nameservice.so.* $(build_install_directory)/lib/
+	cp -f olsrd/lib/txtinfo/olsrd_txtinfo.so.* $(build_install_directory)/lib/
+	cp -af $(build_toolchain_dir)/lib/libpthread* $(build_install_directory)/lib/
+
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/link.inc ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/link.inc
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/link.inc	2008-09-02 14:02:39.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/link.inc	2008-11-05 23:19:37.000000000 +0100
@@ -915,10 +915,16 @@
 );
 
 Function cfg_get_ipv4gw $cfg, $iface, $gw (
-        if (!strlen($gw)) {
-                $gw = "0.0.0.0";
-        }
-        return cfg_get_def($cfg, "route.1.gateway", $gw);
+  $status = "disabled";
+  $status = cfg_get_def($cfg, "route.1.status", $status);
+  if($status == "enabled")
+  {
+    if (!strlen($gw)) {
+      $gw = "0.0.0.0";
+    }
+    return cfg_get_def($cfg, "route.1.gateway", $gw);
+  }
+  return "";
 );
 
 Function cfg_get_dns $cfg, $dns (
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/netrouterap.tmpl ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/netrouterap.tmpl
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/netrouterap.tmpl	2008-09-04 14:37:10.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/netrouterap.tmpl	2008-11-04 15:22:28.000000000 +0100
@@ -126,7 +126,7 @@
 	  	onClick="return openPage('ipalias.cgi?iface=<? echo $wan_iface;>',720,330);" /></td>
       </tr>
        <tr><td class="f"><strong><? echo dict_translate("Gateway IP:"); ></strong></td>
-	<td colspan="3"><input class="f" type="text" name="wangw" id="wangw" value="<?echo $wangw>" required="1" callback="validateWanIP" realname="<? echo dict_translate("LAN Gateway IP"); >"/></td>
+	<td colspan="3"><input class="f" type="text" name="wangw" id="wangw" value="<?echo $wangw>" required="1" callback="validateWlanOptIP" realname="<? echo dict_translate("LAN Gateway IP"); >"/></td>
       </tr>
        <tr><td class="f"><strong><? echo dict_translate("Primary DNS IP:"); ></strong></td>
 	<td colspan="3"><input class="f" type="text" name="dns1" id="dns1" value="<?echo $dns1>" required="1" callback="validateWanIP" realname="<? echo dict_translate("Primary DNS IP"); >"/></td>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/netroutersta.tmpl ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/netroutersta.tmpl
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/netroutersta.tmpl	2008-09-04 14:37:10.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/netroutersta.tmpl	2008-11-04 15:22:28.000000000 +0100
@@ -83,7 +83,7 @@
 	  	onClick="return openPage('ipalias.cgi?iface=<? echo $wan_iface;>',720,330);" /></td>
       </tr>
        <tr><td class="f"><strong><? echo dict_translate("Gateway IP:"); ></strong></td>
-	<td colspan="3"><input class="f" type="text" name="wangw" id="wangw" value="<?echo $wangw>" required="1" callback="validateWanIP" realname="<? echo dict_translate("WLAN Gateway IP"); >"/></td>
+	<td colspan="3"><input class="f" type="text" name="wangw" id="wangw" value="<?echo $wangw>" required="1" callback="validateWlanOptIP" realname="<? echo dict_translate("WLAN Gateway IP"); >"/></td>
       </tr>
        <tr><td class="f"><strong><? echo dict_translate("Primary DNS IP:"); ></strong></td>
 	<td colspan="3"><input class="f" type="text" name="dns1" id="dns1" value="<?echo $dns1>" required="1" callback="validateWanIP" realname="<? echo dict_translate("Primary DNS IP"); >"/></td>
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/services.tmpl ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/services.tmpl
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/lib/services.tmpl	2008-09-03 15:01:28.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/lib/services.tmpl	2008-11-04 15:22:28.000000000 +0100
@@ -19,6 +19,7 @@
                 telnetStatusClicked();
                 sshStatusClicked();
                 syslogStatusClicked();
+                olsrStatusClicked();
         }
         window.onload=init;
 </script>
@@ -242,6 +243,23 @@
 	</tr>
 	</table>
 	</form>
+
+	<form enctype="multipart/form-data" action="services.cgi" method="POST" onSubmit="return validateStandard(this, 'error');">
+	<table class="linktable" cellspacing="0"> 
+	<tr><th colspan="3"><? echo dict_translate("OLSRd"); ></th></tr>
+	<tr>
+	<td class="f"><strong><? echo dict_translate("Enable OLSRd:"); ></strong></td>
+	<td><input type="checkbox" name="olsr_status" value="enabled" id="olsr_status" <? if ($olsr_status=="enabled") { echo "checked"; }> onClick="olsrStatusClicked();"></td>
+	<td class="f">&nbsp;</td>
+	</tr>
+	<tr>
+	  <td class="f">&nbsp;<input type="hidden" name="action" value="cholsr"></td>
+	  <td><input type="submit" value="<? echo dict_translate("Change"); >">&nbsp;</td>
+	  <td class="f">&nbsp; </td>
+	</tr>
+	</table>
+	</form>
+
 <!-- we use default certificates
 	<form enctype="multipart/form-data" action="services.cgi" method="POST" onSubmit="return validateStandard(this, 'error');">
 	<table class="linktable" cellspacing="0"> 
@@ -274,6 +292,31 @@
 	</form>
 -->
 
+	<form enctype="multipart/form-data" action="services.cgi" method="POST" onSubmit="return validateStandard(this, 'error');">
+	<table class="linktable" cellspacing="0"> 
+	<tr><th colspan="3"><? echo dict_translate("OLSRd Configuration"); ></th></tr>
+	<tr>
+	<td class="f"><strong><? echo dict_translate("Configuration File:"); ></strong></td>
+	<td><input type="file" name="olsr_conf_file" id="olsr_conf_file" realname="<? echo dict_translate("Configuration File"); >"></td>
+	</td>
+	<td class="f">&nbsp;</td>
+	</tr>
+	<tr>
+	  <td class="f">&nbsp;<input type="hidden" name="action" value="olsrconfupload"></td>
+	  <td><input type="submit" value="<? echo dict_translate("Upload"); >">&nbsp;</td>
+	  <td class="f">&nbsp; </td>
+	</tr>
+	<tr>
+	 <td class="f"><strong><? echo dict_translate("Remove Configuration File:"); ></strong></td>
+	 <td><input type="submit" id="olsrconfdelete" name="olsrconfdelete" value="<? echo dict_translate("Remove"); >"
+         onClick="return confirm('<? echo dict_translate("qst_remove_olsr_conf|Do you really want to remove uploaded OLSRd Configuration file?"); >');">
+	 </td>
+	  <td class="f"> &nbsp; </td>
+	</tr>
+	</table>
+	</form>
+
+
     </td>
   </tr>
   <tr> 
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/services.cgi ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/services.cgi
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/services.cgi	2008-07-22 11:23:08.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/services.cgi	2008-11-04 15:22:28.000000000 +0100
@@ -136,6 +136,13 @@
                 }
 		cfg_save($cfg, $cfg_file);
 		cfg_set_modified($cfg_file);
+	} elseif ($action == "cholsr") {
+		if ($olsr_status != "enabled") {
+			$olsr_status = "disabled";
+		}
+		cfg_set($cfg, "olsrd.status", $olsr_status);
+		cfg_save($cfg, $cfg_file);
+		cfg_set_modified($cfg_file);
 	} elseif ($action == "httpscertupload" && strlen($httpscertdelete) > 0) {
 		@unlink("/etc/persistent/https/server.crt");
 		@unlink("/etc/persistent/https/server.key");
@@ -178,6 +185,32 @@
 		}
 		cfg_save($cfg, $cfg_file);
 		cfg_set_modified($cfg_file);
+	} elseif ($action == "olsrconfupload" && strlen($olsrconfdelete) > 0) {
+		@unlink("/etc/persistent/olsrd.conf");
+		cfg_save($cfg, $cfg_file);
+		cfg_set_modified($cfg_file);
+	} elseif ($action == "olsrconfupload") {
+		if (strlen($olsr_conf_file) == 0)
+		{
+			$error_msg = dict_translate("msg_no_olsr_conf_file_specified|No OLSRd configuration file specified.");
+			include("lib/services.tmpl");
+			exit;			
+		}
+		$conf_error = check_uploaded_file($olsr_conf_file,
+				$olsr_conf_file_size, dict_translate("OLSRd configuration"), 5120);
+		if (strlen($conf_error) > 0)
+		{
+  		$error_msg = $conf_error;
+			@unlink($olsr_conf_file);
+			include("lib/services.tmpl");
+			exit;
+		}		
+		if (strlen($olsr_conf_file))
+		{
+			exec("mv "+$olsr_conf_file+" /etc/persistent/olsrd.conf");
+		}
+		cfg_save($cfg, $cfg_file);
+		cfg_set_modified($cfg_file);
 	}
 }
 
@@ -186,6 +219,7 @@
 $ssh_status = cfg_get_def($cfg, "sshd.status", $ssh_status);
 $syslog_status = cfg_get_def($cfg, "syslog.status", $syslog_status);
 $rsyslog_status = cfg_get_def($cfg, "syslog.remote.status", $rsyslog_status);
+$olsr_status = cfg_get_def($cfg, "olsrd.status", $olsr_status);
 $httpport = cfg_get_def($cfg, "httpd.port", "80");
 if (strlen($httpport) == 0) {
 	$httpport = "80";
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/system.js ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/system.js
--- ubnt-lsX-SDK-v3.2.3743.orig/apps/web/common/system.js	2008-07-29 12:31:25.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/apps/web/common/system.js	2008-11-04 15:22:28.000000000 +0100
@@ -99,3 +99,7 @@
 var c=document.getElementById('roStatus');
 statusClicked(c,new Array('rousername', 'roPassword'));
 }
+function olsrStatusClicked() {
+var c=document.getElementById('olsr_status');
+statusClicked(c,new Array());
+}
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/conf/xs2/busybox.config ubnt-lsX-SDK-v3.2.3743.diff/conf/xs2/busybox.config
--- ubnt-lsX-SDK-v3.2.3743.orig/conf/xs2/busybox.config	2008-09-02 06:39:27.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/conf/xs2/busybox.config	2008-11-04 15:26:23.000000000 +0100
@@ -360,8 +360,9 @@
 CONFIG_PIDOF=y
 CONFIG_PS=y
 # CONFIG_RENICE is not set
-# CONFIG_TOP is not set
-# CONFIG_UPTIME is not set
+CONFIG_TOP=y
+FEATURE_CPU_USAGE_PERCENTAGE=y
+CONFIG_UPTIME=y
 # CONFIG_SYSCTL is not set
 
 #
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/conf/xs2/product.mk ubnt-lsX-SDK-v3.2.3743.diff/conf/xs2/product.mk
--- ubnt-lsX-SDK-v3.2.3743.orig/conf/xs2/product.mk	2008-09-04 17:17:22.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/conf/xs2/product.mk	2008-11-04 15:26:23.000000000 +0100
@@ -38,6 +38,7 @@
 	    iproute2  trigger_url ntpclient igmpproxy dropbear
 #	    bird batmand wifidog
 #APPS_GPL += libpcap tcpdump iperf
+APPS_GPL += libpcap tcpdump olsrd
 
 export DRIVERS APPS_OPEN APPS_GPL
 
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/conf/xs5/busybox.config ubnt-lsX-SDK-v3.2.3743.diff/conf/xs5/busybox.config
--- ubnt-lsX-SDK-v3.2.3743.orig/conf/xs5/busybox.config	2008-09-02 06:39:27.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/conf/xs5/busybox.config	2008-11-04 15:26:23.000000000 +0100
@@ -360,8 +360,9 @@
 CONFIG_PIDOF=y
 CONFIG_PS=y
 # CONFIG_RENICE is not set
-# CONFIG_TOP is not set
-# CONFIG_UPTIME is not set
+CONFIG_TOP=y
+FEATURE_CPU_USAGE_PERCENTAGE=y
+CONFIG_UPTIME=y
 # CONFIG_SYSCTL is not set
 
 #
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/conf/xs5/product.mk ubnt-lsX-SDK-v3.2.3743.diff/conf/xs5/product.mk
--- ubnt-lsX-SDK-v3.2.3743.orig/conf/xs5/product.mk	2008-09-04 17:17:22.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/conf/xs5/product.mk	2008-11-04 15:26:23.000000000 +0100
@@ -38,6 +38,7 @@
 	    iproute2  trigger_url ntpclient igmpproxy dropbear 
 #	    bird batmand wifidog
 #APPS_GPL += libpcap tcpdump iperf
+APPS_GPL += libpcap tcpdump olsrd
 
 export DRIVERS APPS_OPEN APPS_GPL
 
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/rootfs/ls2/linuxrc ubnt-lsX-SDK-v3.2.3743.diff/rootfs/ls2/linuxrc
--- ubnt-lsX-SDK-v3.2.3743.orig/rootfs/ls2/linuxrc	2008-08-29 04:19:27.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/rootfs/ls2/linuxrc	2008-11-04 15:24:39.000000000 +0100
@@ -128,6 +128,15 @@
 	/sbin/ubntconf
 fi
 
+# add olsrd to init
+grep -q "olsrd.status=enabled" /tmp/system.cfg
+if [ $? -eq 0 ] && [ -x /bin/olsrd ]; then
+    cp -f /usr/etc/init.d/olsrd /etc/sysinit/olsrd.conf
+    echo "null::respawn:/bin/olsrd -nofork" >> /etc/inittab
+    echo "olsrd" >> /etc/startup.list
+fi
+
+
 echo "Executing init..."
 exec /sbin/init -f
 
diff -Nur ubnt-lsX-SDK-v3.2.3743.orig/rootfs/ls2/usr/etc/rc.d/rc.softrestart ubnt-lsX-SDK-v3.2.3743.diff/rootfs/ls2/usr/etc/rc.d/rc.softrestart
--- ubnt-lsX-SDK-v3.2.3743.orig/rootfs/ls2/usr/etc/rc.d/rc.softrestart	2008-07-29 13:03:56.000000000 +0200
+++ ubnt-lsX-SDK-v3.2.3743.diff/rootfs/ls2/usr/etc/rc.d/rc.softrestart	2008-11-04 15:25:00.000000000 +0100
@@ -20,6 +20,14 @@
 	/sbin/ubntconf
 fi
 
+# add olsrd to init
+grep -q "olsrd.status=enabled" /tmp/system.cfg
+if [ $? -eq 0 ] && [ -x /bin/olsrd ]; then
+    cp -f /usr/etc/init.d/olsrd /etc/sysinit/olsrd.conf
+    echo "null::respawn:/bin/olsrd -nofork" >> /etc/inittab
+    echo "olsrd" >> /etc/startup.list
+fi
+
 RC_CMD=start
 . /etc/rc.d/rc
 
