Beautified the files due to incorrect tab settings
authorCaspar van Zon <CHW.van.Zon@mindef.nl>
Thu, 18 Mar 2010 13:24:27 +0000 (14:24 +0100)
committerCaspar van Zon <CHW.van.Zon@mindef.nl>
Thu, 18 Mar 2010 13:24:27 +0000 (14:24 +0100)
lib/dyn_gw/src/olsrd_dyn_gw.c

index ed03157..e5cc19d 100644 (file)
-
-/*
- * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tonnesen(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 "log.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
-
-static int hna_check_interval  = DEFAULT_HNA_CHECK_INTERVAL;
-/* set default interval, in case none is given in the config file */
-static int ping_check_interval = DEFAULT_PING_CHECK_INTERVAL;
-
-/* 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_addr;
-  uint8_t hna_prefixlen;
-  bool hna_added;
-  bool checked;
-  bool active;
-  struct hna_list *next;
-};
-
-static struct hna_list *add_to_hna_list(struct hna_list *, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen);
-
-struct hna_group {
-  struct hna_list *            hna_list;
-  struct ping_list *   ping_hosts;
-  bool                                                         probe_ok;
-  struct hna_group *   next;
-};
-
-bool hna_ping_check    = false;
-static struct hna_group * hna_groups = NULL;
-
-static struct hna_group *add_to_hna_group(struct hna_group *);
-
-static void looped_checks(void *) __attribute__ ((noreturn));
-
-static bool check_gw(union olsr_ip_addr *, uint8_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 *);
-
-struct hna_list* find_hna(uint32_t src_addr, uint32_t src_mask);
-
-char *get_ip_str(uint32_t address, char *s, size_t maxlen);
-int update_routing(void);
-
-/**
- * read config file parameters
- */
-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 (hna_groups == NULL) { 
-    hna_groups = add_to_hna_group(hna_groups);
-    if (hna_groups == NULL)
-      return 1;
-  } else {
-    if (hna_groups->hna_list != NULL) {
-      hna_groups = add_to_hna_group(hna_groups);
-               }
-       }
-
-  hna_groups->ping_hosts = add_to_ping_list(value, hna_groups->ping_hosts);
-  hna_ping_check = true;
-  
-  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_addr;
-  union olsr_ip_addr temp_mask;
-  char s_addr[128];
-  char s_mask[128];
-  
-  //Example: 192.168.1.0  255.255.255.0
-  int i = sscanf(value, "%127s %127s", s_addr, s_mask);
-  if (i != 2) {
-    OLSR_PRINTF(0, "Cannot get IP address and netmask from \"%s\"", value);
-    return 1;
-  }
-
-  if (inet_pton(olsr_cnf->ip_version, s_addr, &temp_addr) <= 0) {
-    OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_addr);
-    return 1;
-  }
-
-  if (inet_pton(olsr_cnf->ip_version, s_mask, &temp_mask) <= 0) {
-    OLSR_PRINTF(0, "Illegal netmask \"%s\"", s_mask);
-    return 1;
-  }
-
-       if (hna_groups == NULL)
-       {
-    hna_groups = add_to_hna_group(hna_groups);
-    if (hna_groups == NULL) {
-      return 1;
-               }
-       }
-       
-  hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));
-  if (hna_groups->hna_list == NULL) {
-    return 1;
-  }
-  return 0;
-}
-
-static const struct olsrd_plugin_parameters plugin_parameters[] = {
-  {.name = "interval",                 .set_plugin_parameter = &set_plugin_int,        .data = &ping_check_interval    },
-  {.name = "pinginterval",     .set_plugin_parameter = &set_plugin_int,        .data = &ping_check_interval    },
-  {.name = "checkinterval",    .set_plugin_parameter = &set_plugin_int,        .data = &hna_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;
-
-  if (hna_groups == NULL) {
-    hna_groups = add_to_hna_group(hna_groups);
-    if (hna_groups == NULL)
-      return 1;
-       }
-       
-       // Add a default gateway if the top entry was just a ping address
-       if (hna_groups->hna_list == NULL) {
-    union olsr_ip_addr temp_addr;
-    union olsr_ip_addr temp_mask;
-    
-    temp_addr.v4.s_addr = INET_ADDR;
-    temp_mask.v4.s_addr = INET_MASK;
-    hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));
-    if (hna_groups->hna_list == NULL) {
-      return 1;
-    }
-       }
-       
-  // Prepare all routing information
-  update_routing();
-  
-  if (hna_ping_check) {
-    pthread_create(&ping_thread, NULL, (void *(*)(void *))looped_checks, NULL);
-  } else {
-    struct hna_group *grp;
-    for (grp = hna_groups; grp; grp = grp->next) {
-      grp->probe_ok = true;
-               }
-       }
-
-       // Print the current configuration
-       {
-         struct hna_group *grp;
-         int i = 0;
-         for (grp = hna_groups; grp; grp = grp->next, ++i) {
-           struct hna_list *lst;
-           struct ping_list *png;
-           
-           olsr_printf(1, "Group %d:\n", i);
-           for (lst = grp->hna_list; lst; lst = lst->next) {
-             char addr[INET_ADDRSTRLEN];
-             olsr_printf(1, "  HNA %s\n", get_ip_str(lst->hna_addr.v4.s_addr, addr, INET_ADDRSTRLEN));
-                       }
-                       for (png = grp->ping_hosts; png; png = png->next) {
-                         olsr_printf(1, "  PING %s\n", png->ping_address);
-                       }
-               }
-       }
-
-  /* Register the GW check */
-  olsr_start_timer(hna_check_interval, 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_group* grp;
-  struct hna_list *li;
-
-  update_routing();
-  
-  for (grp = hna_groups; grp; grp = grp->next) {
-    for (li = grp->hna_list; li; li = li->next) {
-      if (!li->hna_added) {
-        if (grp->probe_ok && li->active) {
-          olsr_printf(1, "Adding OLSR local HNA entry\n");
-          ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen);
-          li->hna_added = true;
-                               }
-                       } else {
-                         if (!grp->probe_ok || !li->active) {
-          while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen)) {
-            olsr_printf(1, "Removing OLSR local HNA entry\n");
-          }
-          li->hna_added = false;
-                               }
-                       }
-    }
-  }
-}
-
-/**
- * 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_group *grp;
-    struct hna_list *li;
-    struct timespec remainder_spec;
-    /* the time to wait in "Interval" sec (see connfig), default=5sec */
-    struct timespec sleeptime_spec = { ping_check_interval, 0L };
-
-    for (grp = hna_groups; grp; grp = grp->next) {
-      for (li = grp->hna_list; li; li = li->next) {
-      
-               // If this HNA is not active skip to the next one
-        if (!li->active)
-          continue;
-          
-        /* check for gw in table entry and if Ping IPs are given also do pings */
-        grp->probe_ok = check_gw(&li->hna_addr, li->hna_prefixlen, grp->ping_hosts);
-        if (grp->probe_ok)
-                break; // Valid host found so we can bail out of the inner loop here
-      }
-    }
-
-    while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)
-      sleeptime_spec = remainder_spec;
-  }
-  // return NULL;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : find_hna
- * Description: Lookup an HNA that matches the specified parameters
- * Input      : src_addr - IP address of the HNA to find
- *              src_mask - Address mask of the HNA to find
- * Output     : none
- * Return     : The HNA specified or NULL when HNA not found
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-struct hna_list*
-find_hna(uint32_t src_addr, uint32_t src_mask)
-{
-  struct hna_group * grp;
-  struct hna_list *li;
-  union olsr_ip_addr mask;
-
-  for (grp = hna_groups; grp; grp = grp->next) {
-    for (li = grp->hna_list; li; li = li->next) {
-      olsr_prefix_to_netmask(&mask, li->hna_prefixlen);
-               if (li->hna_addr.v4.s_addr == src_addr && mask.v4.s_addr == src_mask) {
-                   return li;
-                       }
-               }
-       }
-  return NULL;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : get_ip_str
- * Description: Convert the specified address to an IPv4 compatible string
- * Input      : address - IPv4 address to convert to string 
- *              s       - string buffer to contain the resulting string
- *              maxlen  - maximum length of the string buffer 
- * Output     : none
- * Return     : Pointer to the string buffer containing the result
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-char *
-get_ip_str(uint32_t address, char *s, size_t maxlen)
-{
-  struct sockaddr_in v4;
-  
-  v4.sin_addr.s_addr = address;
-  inet_ntop(AF_INET, &v4.sin_addr, s, maxlen);
-
-  return s;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : update_routing
- * Description: Mark the HNAs in the HNA list(s) corresponding to the results
- *              found in the routing table. HNAs that are found in the routing
- *              table will be marked as 'active', otherwise they'll remain
- *              inactive.    
- * Input      : nothing
- * Output     : none
- * Return     : -1 if an error occurred, 0 otherwise
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-int 
-update_routing(void)
-{
-  char buf[1024], iface[16];
-  uint32_t gate_addr, dest_addr, netmask;
-  unsigned int iflags;
-  int metric, refcnt, use;
-  struct hna_group *grp;
-  struct hna_list *li;
-  
-  FILE *fp = fopen(PROCENTRY_ROUTE, "r");
-  if (!fp) {
-    perror(PROCENTRY_ROUTE);
-    olsr_printf(1, "INET (IPv4) not configured in this system.\n");
-    return -1;
-  }
-
-  // Phase 1: reset the 'checked' flag, during the check of the routing table we 
-       // will (re)discover whether the HNA is valid or not.
-  for (grp = hna_groups; grp; grp = grp->next) {
-    for (li = grp->hna_list; li; li = li->next) {
-      li->checked = false;
-               }
-       }
-
-  /*
-     olsr_printf(1, "Genmask         Destination     Gateway         "
-     "Flags Metric Ref    Use Iface\n");
-   */
-  while (fgets(buf, sizeof(buf), fp)) {
-    struct hna_list *hna;
-    char s_addr[INET_ADDRSTRLEN], s_mask[INET_ADDRSTRLEN];
-    
-    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;
-
-    get_ip_str(dest_addr, s_addr, INET_ADDRSTRLEN);
-    get_ip_str(netmask, s_mask, INET_ADDRSTRLEN);
-    
-    hna = find_hna(dest_addr, netmask);
-    if (hna == NULL) { // Entry not found, try the next one
-      continue;
-    }
-    
-    if ((iflags & RTF_UP) && (metric == 0)) {
-          hna->checked = true;
-    }
-  }
-  fclose(fp);
-  
-  // Phase 2: now copy the 'checked' flag to the 'active' flag.
-  // The total check is a 2-phase process so the ping check loop won't be 
-       // disturbed too badly.
-  for (grp = hna_groups; grp; grp = grp->next) {
-    for (li = grp->hna_list; li; li = li->next) {
-      li->active = li->checked;
-               }
-       }
-       
-       return 0;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : check_gw
- * Description: Check the specified gateway(s) by sending a ping
- * Input      : addr      - the address of the HNA to which the ping is related
- *              prefixlen - the length of the prefix for this HNA 
- *              the_ping_list - list with related ping hosts
- * Output     : none
- * Return     : true if the ping host could be reached, false otherwise
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-static bool
-check_gw(union olsr_ip_addr *addr, uint8_t prefixlen, struct ping_list *the_ping_list)
-{
-  bool retval = false;
-  union olsr_ip_addr mask;
-
-  olsr_prefix_to_netmask(&mask, prefixlen);
-  
-  /* 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) detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);
-      retval = true;
-    }
-  } else {
-    olsr_printf(1, "HNA[%08x/%08x] detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);
-    retval = true;
-  }
-
-  if (retval == false) {
-    /* And we cast here since we get warnings on Win32 */
-    olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)addr->v4.s_addr, (unsigned int)mask.v4.s_addr);
-  }
-  return retval;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : ping_is_possible
- * Description: Ping the specified host(s)
- * Input      : the_ping_list - the list of hosts to ping
- * Output     : none
- * Return     : 1 if any host responded, 0 otherwise
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-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;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : add_to_ping_list
- * Description: Add a new ping host to the list of ping hosts
- * Input      : ping_address - the address of the ping host
- *              the_ping_list - the list of ping hosts 
- * Output     : none
- * Return     : a pointer to the newly added ping host, i.e. start of the list
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-/* 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 = calloc(1, sizeof(struct ping_list));
-  if (!new) {
-    fprintf(stderr, "DYN GW: Out of memory!\n");
-    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");
-    exit(0);
-  }
-  new->ping_address = strdup(ping_address);
-  new->next = the_ping_list;
-  return new;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : add_to_hna_list
- * Description: Add a new HNA entry to the list of HNA entries
- * Input      : list_root - the start of the list with HNA entries
- *              hna_addr  - the address of the new HNA entry
- *              prefixlen - the prefix-length of the new HNA entry 
- * Output     : none
- * Return     : a pointer to the newly added HNA entry, i.e. start of the list
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-static struct hna_list *
-add_to_hna_list(struct hna_list *list_root, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen)
-{
-  struct hna_list *new = calloc(1, sizeof(struct hna_list));
-  if (new == NULL) {
-    fprintf(stderr, "DYN GW: Out of memory!\n");
-    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");
-    exit(0);
-  }
-
-  new->hna_addr.v4 = hna_addr->v4;
-  new->hna_prefixlen = hna_prefixlen;
-  new->hna_added = false;
-  new->next = list_root;
-  return new;
-}
-
-/* -------------------------------------------------------------------------
- * Function   : add_to_hna_group
- * Description: Add a new HNA group to the list of HNA groups
- * Input      : list_root - the start of the list with HNA groups
- * Output     : none
- * Return     : a pointer to the newly added HNA group, i.e. start of the list
- * Data Used  : none
- * ------------------------------------------------------------------------- */
-static struct hna_group *
-add_to_hna_group(struct hna_group *list_root)
-{
-  struct hna_group *new = calloc(1, sizeof(struct hna_group));
-  if (new == NULL) {
-    fprintf(stderr, "DYN GW: Out of memory!\n");
-    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");
-    exit(0);
-       }
-       
-       new->next =  list_root;
-       return new;
-}
-
-
-#ifdef WIN32
-
-/*
- * Windows pthread 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
-
-/*
- * Local Variables:
- * c-basic-offset: 2
- * indent-tabs-mode: nil
- * End:
- */
+\r
+/*\r
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)\r
+ * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ * * Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in\r
+ *   the documentation and/or other materials provided with the\r
+ *   distribution.\r
+ * * Neither the name of olsr.org, olsrd nor the names of its\r
+ *   contributors may be used to endorse or promote products derived\r
+ *   from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * Visit http://www.olsr.org for more information.\r
+ *\r
+ * If you find this software useful feel free to make a donation\r
+ * to the project. For more information see the website or contact\r
+ * the copyright holders.\r
+ *\r
+ */\r
+\r
+/*\r
+ * -Threaded ping code added by Jens Nachtigall\r
+ * -HNA4 checking by bjoern riemer\r
+ */\r
+\r
+#include <arpa/inet.h>\r
+\r
+#include "olsr_types.h"\r
+#include "olsrd_dyn_gw.h"\r
+#include "olsr.h"\r
+#include "defs.h"\r
+#include "ipcalc.h"\r
+#include "scheduler.h"\r
+#include "log.h"\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <sys/time.h>\r
+#include <net/route.h>\r
+#ifdef linux\r
+#include <linux/in_route.h>\r
+#endif\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <time.h>\r
+#ifndef WIN32\r
+#include <pthread.h>\r
+#else\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+#undef interface\r
+\r
+#define close(x) closesocket(x)\r
+\r
+typedef HANDLE pthread_mutex_t;\r
+typedef HANDLE pthread_t;\r
+\r
+int pthread_create(HANDLE * Hand, void *Attr, void *(*Func) (void *), void *Arg);\r
+int pthread_kill(HANDLE Hand, int Sig);\r
+int pthread_mutex_init(HANDLE * Hand, void *Attr);\r
+int pthread_mutex_lock(HANDLE * Hand);\r
+int pthread_mutex_unlock(HANDLE * Hand);\r
+\r
+struct ThreadPara {\r
+  void *(*Func) (void *);\r
+  void *Arg;\r
+};\r
+#endif\r
+\r
+static int hna_check_interval  = DEFAULT_HNA_CHECK_INTERVAL;\r
+/* set default interval, in case none is given in the config file */\r
+static int ping_check_interval = DEFAULT_PING_CHECK_INTERVAL;\r
+\r
+/* list to store the Ping IP addresses given in the config file */\r
+struct ping_list {\r
+  char *ping_address;\r
+  struct ping_list *next;\r
+};\r
+\r
+static struct ping_list *add_to_ping_list(const char *, struct ping_list *);\r
+\r
+struct hna_list {\r
+  union olsr_ip_addr   hna_addr;\r
+  uint8_t              hna_prefixlen;\r
+  bool                 hna_added;\r
+  bool                 checked;\r
+  bool                 active;\r
+  struct hna_list *    next;\r
+};\r
+\r
+static struct hna_list *add_to_hna_list(struct hna_list *, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen);\r
+\r
+struct hna_group {\r
+  struct hna_list *    hna_list;\r
+  struct ping_list *   ping_hosts;\r
+  bool                 probe_ok;\r
+  struct hna_group *   next;\r
+};\r
+\r
+bool hna_ping_check    = false;\r
+static struct hna_group * hna_groups = NULL;\r
+\r
+static struct hna_group *add_to_hna_group(struct hna_group *);\r
+\r
+static void looped_checks(void *) __attribute__ ((noreturn));\r
+\r
+static bool check_gw(union olsr_ip_addr *, uint8_t, struct ping_list *);\r
+\r
+static int ping_is_possible(struct ping_list *);\r
+\r
+/* Event function to register with the scheduler */\r
+static void olsr_event_doing_hna(void *);\r
+\r
+struct hna_list* find_hna(uint32_t src_addr, uint32_t src_mask);\r
+\r
+char *get_ip_str(uint32_t address, char *s, size_t maxlen);\r
+int update_routing(void);\r
+\r
+/**\r
+ * read config file parameters\r
+ */\r
+static int\r
+set_plugin_ping(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))\r
+{\r
+  union olsr_ip_addr foo_addr;\r
+\r
+  if (inet_pton(olsr_cnf->ip_version, value, &foo_addr) <= 0) {\r
+    OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);\r
+    return 1;\r
+  }\r
+\r
+  if (hna_groups == NULL) { \r
+    hna_groups = add_to_hna_group(hna_groups);\r
+    if (hna_groups == NULL)\r
+      return 1;\r
+  } else {\r
+    if (hna_groups->hna_list != NULL) {\r
+      hna_groups = add_to_hna_group(hna_groups);\r
+    }\r
+  }\r
+\r
+  hna_groups->ping_hosts = add_to_ping_list(value, hna_groups->ping_hosts);\r
+  hna_ping_check = true;\r
+  \r
+  return 0;\r
+}\r
+\r
+static int\r
+set_plugin_hna(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))\r
+{\r
+  union olsr_ip_addr temp_addr;\r
+  union olsr_ip_addr temp_mask;\r
+  char s_addr[128];\r
+  char s_mask[128];\r
+  \r
+  //Example: 192.168.1.0  255.255.255.0\r
+  int i = sscanf(value, "%127s %127s", s_addr, s_mask);\r
+  if (i != 2) {\r
+    OLSR_PRINTF(0, "Cannot get IP address and netmask from \"%s\"", value);\r
+    return 1;\r
+  }\r
+\r
+  if (inet_pton(olsr_cnf->ip_version, s_addr, &temp_addr) <= 0) {\r
+    OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_addr);\r
+    return 1;\r
+  }\r
+\r
+  if (inet_pton(olsr_cnf->ip_version, s_mask, &temp_mask) <= 0) {\r
+    OLSR_PRINTF(0, "Illegal netmask \"%s\"", s_mask);\r
+    return 1;\r
+  }\r
+\r
+  if (hna_groups == NULL)\r
+  {\r
+    hna_groups = add_to_hna_group(hna_groups);\r
+    if (hna_groups == NULL) {\r
+      return 1;\r
+    }\r
+  }\r
+       \r
+  hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));\r
+  if (hna_groups->hna_list == NULL) {\r
+    return 1;\r
+  }\r
+  return 0;\r
+}\r
+\r
+static const struct olsrd_plugin_parameters plugin_parameters[] = {\r
+  {.name = "interval",      .set_plugin_parameter = &set_plugin_int,  .data = &ping_check_interval  },\r
+  {.name = "pinginterval",  .set_plugin_parameter = &set_plugin_int,  .data = &ping_check_interval  },\r
+  {.name = "checkinterval", .set_plugin_parameter = &set_plugin_int,  .data = &hna_check_interval   },\r
+  {.name = "ping",          .set_plugin_parameter = &set_plugin_ping, .data = NULL                  },\r
+  {.name = "hna",           .set_plugin_parameter = &set_plugin_hna,  .data = NULL                  },\r
+};\r
+\r
+void\r
+olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)\r
+{\r
+  *params = plugin_parameters;\r
+  *size = sizeof(plugin_parameters) / sizeof(*plugin_parameters);\r
+}\r
+\r
+/**\r
+ *Do initialization here\r
+ *\r
+ *\r
+ *This function is called by the my_init\r
+ *function in uolsrd_plugin.c\r
+ *It is ran _after_ register_olsr_param\r
+ */\r
+int\r
+olsrd_plugin_init(void)\r
+{\r
+  pthread_t ping_thread;\r
+\r
+  if (hna_groups == NULL) {\r
+    hna_groups = add_to_hna_group(hna_groups);\r
+    if (hna_groups == NULL)\r
+      return 1;\r
+  }\r
+       \r
+  // Add a default gateway if the top entry was just a ping address\r
+  if (hna_groups->hna_list == NULL) {\r
+    union olsr_ip_addr temp_addr;\r
+    union olsr_ip_addr temp_mask;\r
+    \r
+    temp_addr.v4.s_addr = INET_ADDR;\r
+    temp_mask.v4.s_addr = INET_MASK;\r
+    hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));\r
+    if (hna_groups->hna_list == NULL) {\r
+      return 1;\r
+    }\r
+  }\r
+       \r
+  // Prepare all routing information\r
+  update_routing();\r
+  \r
+  if (hna_ping_check) {\r
+    pthread_create(&ping_thread, NULL, (void *(*)(void *))looped_checks, NULL);\r
+  } else {\r
+    struct hna_group *grp;\r
+    for (grp = hna_groups; grp; grp = grp->next) {\r
+      grp->probe_ok = true;\r
+    }\r
+  }\r
+\r
+  // Print the current configuration\r
+  {\r
+    struct hna_group *grp;\r
+    int i = 0;\r
+    for (grp = hna_groups; grp; grp = grp->next, ++i) {\r
+      struct hna_list *lst;\r
+      struct ping_list *png;\r
+           \r
+      olsr_printf(1, "Group %d:\n", i);\r
+      for (lst = grp->hna_list; lst; lst = lst->next) {\r
+        char addr[INET_ADDRSTRLEN];\r
+        olsr_printf(1, "  HNA %s\n", get_ip_str(lst->hna_addr.v4.s_addr, addr, INET_ADDRSTRLEN));\r
+      }\r
+      for (png = grp->ping_hosts; png; png = png->next) {\r
+        olsr_printf(1, "  PING %s\n", png->ping_address);\r
+      }\r
+    }\r
+  }\r
+\r
+  /* Register the GW check */\r
+  olsr_start_timer(hna_check_interval, 0, OLSR_TIMER_PERIODIC, &olsr_event_doing_hna, NULL, 0);\r
+  return 1;\r
+}\r
+\r
+/**\r
+ * Scheduled event to update the hna table,\r
+ * called from olsrd main thread to keep the hna table thread-safe\r
+ */\r
+static void\r
+olsr_event_doing_hna(void *foo __attribute__ ((unused)))\r
+{\r
+  struct hna_group* grp;\r
+  struct hna_list *li;\r
+\r
+  update_routing();\r
+  \r
+  for (grp = hna_groups; grp; grp = grp->next) {\r
+    for (li = grp->hna_list; li; li = li->next) {\r
+      if (!li->hna_added) {\r
+        if (grp->probe_ok && li->active) {\r
+          olsr_printf(1, "Adding OLSR local HNA entry\n");\r
+          ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen);\r
+          li->hna_added = true;\r
+        }\r
+      } else {\r
+        if (!grp->probe_ok || !li->active) {\r
+          while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen)) {\r
+            olsr_printf(1, "Removing OLSR local HNA entry\n");\r
+          }\r
+          li->hna_added = false;\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+ * the threaded function which happens within an endless loop,\r
+ * reiterated every "Interval" sec (as given in the config or\r
+ * the default value)\r
+ */\r
+static void\r
+looped_checks(void *foo __attribute__ ((unused)))\r
+{\r
+  for (;;) {\r
+    struct hna_group *grp;\r
+    struct hna_list *li;\r
+    struct timespec remainder_spec;\r
+    /* the time to wait in "Interval" sec (see connfig), default=5sec */\r
+    struct timespec sleeptime_spec = { ping_check_interval, 0L };\r
+\r
+    for (grp = hna_groups; grp; grp = grp->next) {\r
+      for (li = grp->hna_list; li; li = li->next) {\r
+      \r
+               // If this HNA is not active skip to the next one\r
+        if (!li->active)\r
+          continue;\r
+          \r
+        /* check for gw in table entry and if Ping IPs are given also do pings */\r
+        grp->probe_ok = check_gw(&li->hna_addr, li->hna_prefixlen, grp->ping_hosts);\r
+        if (grp->probe_ok)\r
+          break;       // Valid host found so we can bail out of the inner loop here\r
+      }\r
+    }\r
+\r
+    while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)\r
+      sleeptime_spec = remainder_spec;\r
+  }\r
+  // return NULL;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : find_hna\r
+ * Description: Lookup an HNA that matches the specified parameters\r
+ * Input      : src_addr - IP address of the HNA to find\r
+ *              src_mask - Address mask of the HNA to find\r
+ * Output     : none\r
+ * Return     : The HNA specified or NULL when HNA not found\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+struct hna_list*\r
+find_hna(uint32_t src_addr, uint32_t src_mask)\r
+{\r
+  struct hna_group * grp;\r
+  struct hna_list *li;\r
+  union olsr_ip_addr mask;\r
+\r
+  for (grp = hna_groups; grp; grp = grp->next) {\r
+    for (li = grp->hna_list; li; li = li->next) {\r
+      olsr_prefix_to_netmask(&mask, li->hna_prefixlen);\r
+      if (li->hna_addr.v4.s_addr == src_addr && mask.v4.s_addr == src_mask) {\r
+        return li;\r
+      }\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : get_ip_str\r
+ * Description: Convert the specified address to an IPv4 compatible string\r
+ * Input      : address - IPv4 address to convert to string \r
+ *              s       - string buffer to contain the resulting string\r
+ *              maxlen  - maximum length of the string buffer \r
+ * Output     : none\r
+ * Return     : Pointer to the string buffer containing the result\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+char *\r
+get_ip_str(uint32_t address, char *s, size_t maxlen)\r
+{\r
+  struct sockaddr_in v4;\r
+  \r
+  v4.sin_addr.s_addr = address;\r
+  inet_ntop(AF_INET, &v4.sin_addr, s, maxlen);\r
+\r
+  return s;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : update_routing\r
+ * Description: Mark the HNAs in the HNA list(s) corresponding to the results\r
+ *              found in the routing table. HNAs that are found in the routing\r
+ *              table will be marked as 'active', otherwise they'll remain\r
+ *              inactive.    \r
+ * Input      : nothing\r
+ * Output     : none\r
+ * Return     : -1 if an error occurred, 0 otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+int \r
+update_routing(void)\r
+{\r
+  char buf[1024], iface[16];\r
+  uint32_t gate_addr, dest_addr, netmask;\r
+  unsigned int iflags;\r
+  int metric, refcnt, use;\r
+  struct hna_group *grp;\r
+  struct hna_list *li;\r
+  \r
+  FILE *fp = fopen(PROCENTRY_ROUTE, "r");\r
+  if (!fp) {\r
+    perror(PROCENTRY_ROUTE);\r
+    olsr_printf(1, "INET (IPv4) not configured in this system.\n");\r
+    return -1;\r
+  }\r
+\r
+  // Phase 1: reset the 'checked' flag, during the check of the routing table we \r
+  // will (re)discover whether the HNA is valid or not.\r
+  for (grp = hna_groups; grp; grp = grp->next) {\r
+    for (li = grp->hna_list; li; li = li->next) {\r
+      li->checked = false;\r
+    }\r
+  }\r
+\r
+  /*\r
+     olsr_printf(1, "Genmask         Destination     Gateway         "\r
+     "Flags Metric Ref    Use Iface\n");\r
+   */\r
+  while (fgets(buf, sizeof(buf), fp)) {\r
+    struct hna_list *hna;\r
+    char s_addr[INET_ADDRSTRLEN], s_mask[INET_ADDRSTRLEN];\r
+    \r
+    int num = sscanf(buf, \r
+                     "%15s %128X %128X %X %d %d %d %128X \n",\r
+                     iface, \r
+                     &dest_addr,\r
+                     &gate_addr,\r
+                     &iflags, \r
+                     &refcnt,\r
+                     &use,\r
+                     &metric,\r
+                     &netmask);\r
+    if (num < 8)\r
+      continue;\r
+\r
+    get_ip_str(dest_addr, s_addr, INET_ADDRSTRLEN);\r
+    get_ip_str(netmask, s_mask, INET_ADDRSTRLEN);\r
+    \r
+    hna = find_hna(dest_addr, netmask);\r
+    if (hna == NULL) { // Entry not found, try the next one\r
+      continue;\r
+    }\r
+    \r
+    if ((iflags & RTF_UP) && (metric == 0)) {\r
+      hna->checked = true;\r
+    }\r
+  }\r
+  fclose(fp);\r
+  \r
+  // Phase 2: now copy the 'checked' flag to the 'active' flag.\r
+  // The total check is a 2-phase process so the ping check loop won't be \r
+  // disturbed too badly.\r
+  for (grp = hna_groups; grp; grp = grp->next) {\r
+    for (li = grp->hna_list; li; li = li->next) {\r
+      li->active = li->checked;\r
+    }\r
+  }\r
+       \r
+  return 0;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : check_gw\r
+ * Description: Check the specified gateway(s) by sending a ping\r
+ * Input      : addr      - the address of the HNA to which the ping is related\r
+ *              prefixlen - the length of the prefix for this HNA \r
+ *              the_ping_list - list with related ping hosts\r
+ * Output     : none\r
+ * Return     : true if the ping host could be reached, false otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+static bool\r
+check_gw(union olsr_ip_addr *addr, uint8_t prefixlen, struct ping_list *the_ping_list)\r
+{\r
+  bool retval = false;\r
+  union olsr_ip_addr mask;\r
+\r
+  olsr_prefix_to_netmask(&mask, prefixlen);\r
+  \r
+  /* don't ping, if there was no "Ping" IP addr in the config file */\r
+  if (the_ping_list != NULL) {\r
+    /*validate the found inet gw by pinging */\r
+    if (ping_is_possible(the_ping_list)) {\r
+      olsr_printf(1, "HNA[%08x/%08x](ping is possible) detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);\r
+      retval = true;\r
+    }\r
+  } else {\r
+    olsr_printf(1, "HNA[%08x/%08x] detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);\r
+    retval = true;\r
+  }\r
+\r
+  if (retval == false) {\r
+    /* And we cast here since we get warnings on Win32 */\r
+    olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)addr->v4.s_addr, (unsigned int)mask.v4.s_addr);\r
+  }\r
+  return retval;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : ping_is_possible\r
+ * Description: Ping the specified host(s)\r
+ * Input      : the_ping_list - the list of hosts to ping\r
+ * Output     : none\r
+ * Return     : 1 if any host responded, 0 otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+static int\r
+ping_is_possible(struct ping_list *the_ping_list)\r
+{\r
+  struct ping_list *list;\r
+  for (list = the_ping_list; list; list = list->next) {\r
+    char ping_command[50];\r
+    snprintf(ping_command, sizeof(ping_command), "ping -c 1 -q %s", list->ping_address);\r
+    olsr_printf(1, "\nDo ping on %s ...\n", list->ping_address);\r
+    if (system(ping_command) == 0) {\r
+      olsr_printf(1, "...OK\n\n");\r
+      return 1;\r
+    }\r
+    olsr_printf(1, "...FAILED\n\n");\r
+  }\r
+  return 0;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : add_to_ping_list\r
+ * Description: Add a new ping host to the list of ping hosts\r
+ * Input      : ping_address - the address of the ping host\r
+ *              the_ping_list - the list of ping hosts \r
+ * Output     : none\r
+ * Return     : a pointer to the newly added ping host, i.e. start of the list\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+/* add the valid IPs to the head of the list */\r
+static struct ping_list *\r
+add_to_ping_list(const char *ping_address, struct ping_list *the_ping_list)\r
+{\r
+  struct ping_list *new = calloc(1, sizeof(struct ping_list));\r
+  if (!new) {\r
+    fprintf(stderr, "DYN GW: Out of memory!\n");\r
+    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");\r
+    exit(0);\r
+  }\r
+  new->ping_address = strdup(ping_address);\r
+  new->next = the_ping_list;\r
+  return new;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : add_to_hna_list\r
+ * Description: Add a new HNA entry to the list of HNA entries\r
+ * Input      : list_root - the start of the list with HNA entries\r
+ *              hna_addr  - the address of the new HNA entry\r
+ *              prefixlen - the prefix-length of the new HNA entry \r
+ * Output     : none\r
+ * Return     : a pointer to the newly added HNA entry, i.e. start of the list\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+static struct hna_list *\r
+add_to_hna_list(struct hna_list *list_root, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen)\r
+{\r
+  struct hna_list *new = calloc(1, sizeof(struct hna_list));\r
+  if (new == NULL) {\r
+    fprintf(stderr, "DYN GW: Out of memory!\n");\r
+    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");\r
+    exit(0);\r
+  }\r
+\r
+  new->hna_addr.v4 = hna_addr->v4;\r
+  new->hna_prefixlen = hna_prefixlen;\r
+  new->hna_added = false;\r
+  new->next = list_root;\r
+  return new;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : add_to_hna_group\r
+ * Description: Add a new HNA group to the list of HNA groups\r
+ * Input      : list_root - the start of the list with HNA groups\r
+ * Output     : none\r
+ * Return     : a pointer to the newly added HNA group, i.e. start of the list\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+static struct hna_group *\r
+add_to_hna_group(struct hna_group *list_root)\r
+{\r
+  struct hna_group *new = calloc(1, sizeof(struct hna_group));\r
+  if (new == NULL) {\r
+    fprintf(stderr, "DYN GW: Out of memory!\n");\r
+    olsr_syslog(OLSR_LOG_ERR, "DYN GW: Out of memory!\n");\r
+    exit(0);\r
+  }\r
+       \r
+  new->next =  list_root;\r
+  return new;\r
+}\r
+\r
+\r
+#ifdef WIN32\r
+\r
+/*\r
+ * Windows pthread compat stuff\r
+ */\r
+static unsigned long __stdcall\r
+ThreadWrapper(void *Para)\r
+{\r
+  struct ThreadPara *Cast;\r
+  void *(*Func) (void *);\r
+  void *Arg;\r
+\r
+  Cast = (struct ThreadPara *)Para;\r
+\r
+  Func = Cast->Func;\r
+  Arg = Cast->Arg;\r
+\r
+  HeapFree(GetProcessHeap(), 0, Para);\r
+\r
+  Func(Arg);\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+pthread_create(HANDLE * Hand, void *Attr __attribute__ ((unused)), void *(*Func) (void *), void *Arg)\r
+{\r
+  struct ThreadPara *Para;\r
+  unsigned long ThreadId;\r
+\r
+  Para = HeapAlloc(GetProcessHeap(), 0, sizeof(struct ThreadPara));\r
+\r
+  if (Para == NULL)\r
+    return -1;\r
+\r
+  Para->Func = Func;\r
+  Para->Arg = Arg;\r
+\r
+  *Hand = CreateThread(NULL, 0, ThreadWrapper, Para, 0, &ThreadId);\r
+\r
+  if (*Hand == NULL)\r
+    return -1;\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+pthread_kill(HANDLE Hand, int Sig __attribute__ ((unused)))\r
+{\r
+  if (!TerminateThread(Hand, 0))\r
+    return -1;\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+pthread_mutex_init(HANDLE * Hand, void *Attr __attribute__ ((unused)))\r
+{\r
+  *Hand = CreateMutex(NULL, FALSE, NULL);\r
+\r
+  if (*Hand == NULL)\r
+    return -1;\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+pthread_mutex_lock(HANDLE * Hand)\r
+{\r
+  if (WaitForSingleObject(*Hand, INFINITE) == WAIT_FAILED)\r
+    return -1;\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+pthread_mutex_unlock(HANDLE * Hand)\r
+{\r
+  if (!ReleaseMutex(*Hand))\r
+    return -1;\r
+\r
+  return 0;\r
+}\r
+\r
+#endif\r
+\r
+/*\r
+ * Local Variables:\r
+ * c-basic-offset: 2\r
+ * indent-tabs-mode: nil\r
+ * End:\r
+ */\r