* killed lots of #ifdef ... #endif which make the source quite unreadable
[olsrd.git] / src / process_package.c
index 0e47526..2367ea0 100644 (file)
@@ -1,28 +1,47 @@
 /*
- * OLSR ad-hoc routing table management protocol
- * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
+ * All rights reserved.
  *
- * This file is part of the olsr.org OLSR daemon.
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
  *
- * olsr.org 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.
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   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.
  *
- * olsr.org 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.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
  *
- * 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
+ * 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 "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 "parser.h"
 #include "duplicate_set.h"
 #include "rebuild_packet.h"
+#include "scheduler.h"
+#include "net_olsr.h"
+#include "lq_plugin.h"
 
+#include <stddef.h>
 
-#ifdef linux 
-#include "linux/tunnel.h"
-#elif defined WIN32
-#include "win32/tunnel.h"
-#endif
+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 *);
 
 
 /**
- *Initializing the parser functions we are using
+ *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
  */
-void
-olsr_init_package_process()
+static void
+process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message)
 {
+  struct hello_neighbor        *message_neighbors;
 
-  olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
-  olsr_parser_add_function(&olsr_process_received_tc, 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);
-}
+  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;
 
-/**
- *Processes a received HELLO message. 
- *
- *@param m the incoming OLSR message
- *@return 0 on sucess
- */
+      /*
+       *check all interfaces
+       *so that we don't add ourselves to the
+       *2 hop list
+       *IMPORTANT!
+       */
+      if(if_ifwithaddr(&message_neighbors->address) != NULL)
+        continue;
 
-void
-olsr_process_received_hello(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
-{
-  struct link_entry         *link;
-  struct neighbor_entry     *neighbor;
-  struct hello_message      message;
+      /* Get the main address */
+      neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
 
-  hello_chgestruct(&message, m);
+      if (neigh_addr != NULL) {
+        message_neighbors->address = *neigh_addr;
+      }
 
-  /*
-  if(COMP_IP(&message.source_addr, &main_addr))
-    {
-      olsr_destroy_hello_message(&message);
-      return;
-    }
-  */
+      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;
 
-  /*
-   * Update link status
-   */
-  link = update_link_entry(&in_if->ip_addr, from_addr, &message, in_if);
+                  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;
 
-  neighbor = link->neighbor;
+                  two_hop_neighbor->neighbor_2_nblist.prev =
+                    &two_hop_neighbor->neighbor_2_nblist;
 
-  /*
-   * Hysteresis
-   */
-  if(use_hysteresis)
-    {
-      /* Update HELLO timeout */
-      //printf("MESSAGE HTIME: %f\n", message.htime);
-      olsr_update_hysteresis_hello(link, message.htime);
+                  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); 
+                }
+            }
+        }
     }
 
-  /* Check if we are chosen as MPR */
-  if(olsr_lookup_mpr_status(&message, in_if))
-    /* source_addr is always the main addr of a node! */
-    olsr_update_mprs_set(&message.source_addr, (float)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;
 
-  /* Check willingness */
-  if(neighbor->willingness != message.willingness)
-    {
-      olsr_printf(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
-                 olsr_ip_to_string(&neighbor->neighbor_main_addr),
-                 neighbor->willingness,
-                 message.willingness);
+      /* calculate first hop path quality */
+      first_hop_pathcost = lnk->linkcost;
       /*
-       *If willingness changed - recalculate
+       *  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.
        */
-      neighbor->willingness = message.willingness;
-      changes_neighborhood = UP;
-      changes_topology = UP;
+
+      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");
 
-  /* Don't register neighbors of neighbors that announces WILL_NEVER */
-  if(neighbor->willingness != WILL_NEVER)
-    olsr_process_message_neighbors(neighbor, &message);
+  list_of_1_neighbors->neighbor = neighbor;
 
-  /* Process changes immedeatly in case of MPR updates */
-  olsr_process_changes();
+  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;
 
-  olsr_destroy_hello_message(&message);
+  /* 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;
 
-  return;
-}
+  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);
+}
 
 /**
- *Process a received TopologyControl message
- *
- *
- *@param m the incoming OLSR message
- *@return 0 on success
+ *Initializing the parser functions we are using
  */
 void
-olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
-{ 
-  struct tc_mpr_addr              *mpr;
-  struct tc_entry                 *tc_last;
-  struct tc_message               message;
-
-  tc_chgestruct(&message, m, from_addr);
-
-  /*    
-  if(COMP_IP(&message.originator, &main_addr))
-    { 
-      goto forward;
+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);
     }
-  */
-
-  if(!olsr_check_dup_table_proc(&message.originator, 
-                               message.packet_seq_number))
+  else
     {
-      goto forward;
+      olsr_parser_add_function(&olsr_input_hello, LQ_HELLO_MESSAGE, 1);
+      olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
     }
 
-  olsr_printf(3, "Processing TC from %s\n", olsr_ip_to_string(&message.originator));
-
-
-
+  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;
 
   /*
-   *      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.
+   * Update link status
    */
+  struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
 
-  if(check_neighbor_link(from_addr) != SYM_LINK)
-    {
-      olsr_printf(2, "Received TC from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
-      olsr_destroy_tc_message(&message);
-      return;
-    }
-
-
-  if(debug_level > 2)
+  if (olsr_cnf->lq_level > 0)
     {
-      mpr = message.multipoint_relay_selector_address;
-      olsr_printf(3, "mpr_selector_list:[");      
-      while(mpr!=NULL)
-       {
-         olsr_printf(3, "%s:", olsr_ip_to_string(&mpr->address));
-         mpr=mpr->next;
-       }
-      olsr_printf(3, "]\n");
-    }
+      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);
 
-  tc_last = olsr_lookup_tc_entry(&message.originator);
+      /* update packet loss for link quality calculation */
+      olsr_update_packet_loss(lnk);
+    }
   
-  if(tc_last != NULL)
+  neighbor = lnk->neighbor;
+
+  /*
+   * Hysteresis
+   */
+  if(olsr_cnf->use_hysteresis)
     {
-      /* Update entry */
+      /* Update HELLO timeout */
+      /* printf("MESSAGE HTIME: %f\n", message->htime);*/
+      olsr_update_hysteresis_hello(lnk, message->htime);
+    }
 
-      /* Delete destinations with lower ANSN */
-      if(olsr_tc_delete_mprs(tc_last, &message))
-       changes_topology=UP; 
+  /* 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);
 
-      /* Update destinations */
-      if(olsr_tc_update_mprs(tc_last, &message))
-       changes_topology = UP;
 
-      /* Delete possible empty TC entry */
-      if(changes_topology == UP)
-       olsr_tc_delete_entry_if_empty(tc_last);
 
-    }
-  else
+  /* Check willingness */
+  if(neighbor->willingness != message->willingness)
     {
-      /*if message is empty then skip it */
-      if(message.multipoint_relay_selector_address != NULL)
-       {
-         /* New entry */
-         tc_last = olsr_add_tc_entry(&message.originator);      
-         
-         /* Update destinations */
-         olsr_tc_update_mprs(tc_last, &message);
-         
-         changes_topology = UP;
-       }
-      else
-       {
-         olsr_printf(3, "Dropping empty TC from %s\n", olsr_ip_to_string(&message.originator)); 
-       }
+      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;
     }
 
-  /* Process changes */
-  //olsr_process_changes();
 
- forward:
+  /* 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_forward_message(m, 
-                      &message.originator, 
-                      message.packet_seq_number, 
-                      in_if,
-                      from_addr);
-  olsr_destroy_tc_message(&message);
+  olsr_free_hello_packet(message);
 
   return;
 }
 
-
-
-
-
-
 /**
  *Process a received(and parsed) MID message
  *For every address check if there is a topology node
@@ -266,82 +536,61 @@ olsr_process_received_tc(union olsr_message *m, struct interface *in_if, union o
  */
 
 void
-olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
+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(COMP_IP(&message.mid_origaddr, &main_addr))
-    {
-      goto forward;  
-    }
-  */
-
-  if(!olsr_check_dup_table_proc(&message.mid_origaddr, 
-                               message.mid_seqno))
-    {
-      goto forward;
-    }
-  
-  olsr_printf(5, "Processing MID from %s...\n", olsr_ip_to_string(&message.mid_origaddr));
-
-  tmp_adr = message.mid_addr;
+  if (!olsr_validate_address(&message.mid_origaddr)) {
+    olsr_free_mid_packet(&message);
+    return;
+  }
 
-
-  /*
-   *      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 MID from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
-      olsr_destroy_mid_message(&message);
+#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);
 
-
-  /* Update the timeout of the MID */
-  olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
-
-  while(tmp_adr)
-    {
-      if(!mid_lookup_main_addr(&tmp_adr->alias_addr))
-       {
-         olsr_printf(1, "MID new: (%s, ", olsr_ip_to_string(&message.mid_origaddr));
-         olsr_printf(1, "%s)\n", olsr_ip_to_string(&tmp_adr->alias_addr));
-         insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)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;
     } 
   
-  /*Update topology if neccesary*/
-  //olsr_process_changes();
-
- forward:
-  
-  olsr_forward_message(m, 
-                      &message.mid_origaddr, 
-                      message.mid_seqno, 
-                      in_if,
-                      from_addr);
-  olsr_destroy_mid_message(&message);
+    olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
 
-  return;
+  olsr_forward_message(m, from_addr);
+  olsr_free_mid_packet(&message);
 }
 
 
-
-
-
 /**
  *Process incoming HNA message.
  *Forwards the message if that is to be done.
@@ -352,286 +601,103 @@ olsr_process_received_mid(union olsr_message *m, struct interface *in_if, union
  */
 
 void
-olsr_process_received_hna(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr)
+olsr_process_received_hna(union olsr_message *m,
+                          struct interface *in_if __attribute__((unused)),
+                          union olsr_ip_addr *from_addr)
 {
-  struct hna_net_addr  *hna_tmp;
-  struct  hna_message message;
-
-  //printf("Processing HNA\n");
-
-  hna_chgestruct(&message, m);
-  
-
-  /* Process message */          
-  /*
-  if(COMP_IP(&message.originator, &main_addr)) 
-    {
-      goto forward;
-    }
-  */
-
-  if(!olsr_check_dup_table_proc(&message.originator, 
-                               message.packet_seq_number))
-    {
-      goto forward;
-    }
-
 
+  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;
 
-  hna_tmp = message.hna_net;
-
-
-
-  /*
-   *      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.
-   */
-
+#ifdef DEBUG
+  OLSR_PRINTF(5, "Processing HNA\n");
+#endif
 
-  if(check_neighbor_link(from_addr) != SYM_LINK)
-    {
-      olsr_printf(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(from_addr));
-      olsr_destroy_hna_message(&message);
+  /* 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;
     }
-
-  while(hna_tmp)
-    {
-      
-      /*
-       * Set up tunnel to Internet gateway
-       */
-      if((use_tunnel) && (ipversion == AF_INET) && (hna_tmp->net.v4 == 0))
-       {
-         if(inet_tnl_added || gw_tunnel)
-           {
-             hna_tmp = hna_tmp->next;
-             continue;
-           }
-         
-         olsr_printf(1, "Internet gateway discovered! Setting up tunnel:\n");
-
-         /* Set up tunnel endpoint */
-         set_up_source_tnl(&main_addr, &message.originator, in_if->if_index); 
-       }
-      else
-       {
-         olsr_update_hna_entry(&message.originator, &hna_tmp->net, &hna_tmp->netmask, (float)message.vtime); 
-       }
-      
-      hna_tmp = hna_tmp->next;
-    }
-  
-  /*Update topology if neccesary*/
-  //olsr_process_changes();
-
- forward:
-  olsr_forward_message(m, 
-                      &message.originator, 
-                      message.packet_seq_number, 
-                      in_if,
-                      from_addr);
-  olsr_destroy_hna_message(&message);
-
-  return;
-}
-
-
-
-
-
-
-
-/**
- *Processes an list of neighbors from an incoming HELLO message.
- *@param neighbor the neighbor who sendt the message.
- *@param message the HELLO message
- *@return nada
- */
-void
-olsr_process_message_neighbors(struct neighbor_entry *neighbor,struct hello_message *message)
-{
-  struct hello_neighbor        *message_neighbors;
-  struct neighbor_2_list_entry *two_hop_neighbor_yet;
-  struct neighbor_2_entry      *two_hop_neighbor;
-  union olsr_ip_addr           *neigh_addr;
-  
-
-  for(message_neighbors=message->neighbors;
-      message_neighbors!=NULL;
-      message_neighbors=message_neighbors->next)
-    {
-      
-      /*
-       *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 */
-      if((neigh_addr = mid_lookup_main_addr(&message_neighbors->address)) != NULL)
-       COPY_IP(&message_neighbors->address, neigh_addr);
-      
-
-      if(((message_neighbors->status==SYM_NEIGH) || (message_neighbors->status==MPR_NEIGH)))
-       {
-         //printf("\tProcessing %s\n", olsr_ip_to_string(&message_neighbors->address));
-         
-         //printf("\tMain addr: %s\n", olsr_ip_to_string(neigh_addr));
-         
-         if((two_hop_neighbor_yet = olsr_lookup_my_neighbors(neighbor, &message_neighbors->address))!=NULL)
-           {
-             
-             /* Updating the holding time for this neighbor */
-             olsr_get_timestamp((olsr_u32_t) message->vtime*1000, &two_hop_neighbor_yet->neighbor_2_timer);
-
-           }
-         else
-           {
-             
-             if((two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&message_neighbors->address)) == NULL)
-               {
-                
-                 //printf("Adding 2 hop neighbor %s\n\n", olsr_ip_to_string(&message_neighbors->address)); 
-                 changes_neighborhood=UP;
-                 changes_topology=UP;
-                 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;
-                 
-                 COPY_IP(&two_hop_neighbor->neighbor_2_addr,&message_neighbors->address);
-                 olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
-                 olsr_linking_this_2_entries(neighbor, two_hop_neighbor, (float)message->vtime);
-               }
-             else
-               {
-                 
-                 /*
-                   linking to this two_hop_neighbor entry
-                 */    
-                 changes_neighborhood=UP;
-                 changes_topology=UP;
-                 
-                 olsr_linking_this_2_entries(neighbor, two_hop_neighbor, (float)message->vtime); 
-               }
-           }
-       }
-      
-    }
-
-}
-
-
-
-
-
-
-
-
-/**
- *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
- */
-void
-olsr_linking_this_2_entries(struct neighbor_entry *neighbor,struct neighbor_2_entry *two_hop_neighbor, float vtime)
-{
-  struct neighbor_list_entry    *list_of_1_neighbors;
-  struct neighbor_2_list_entry  *list_of_2_neighbors;
-
-  list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
-
-  list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
-
-  list_of_1_neighbors->neighbor = neighbor;
-
-  /* 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;
-  
-  olsr_get_timestamp((olsr_u32_t) vtime*1000, &list_of_2_neighbors->neighbor_2_timer);
-
-  /* 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
- *@param n_status the buffer to put the status in
- *
- *@return 1 if we are selected as MPR 0 if not
- */
-int
-olsr_lookup_mpr_status(struct hello_message *message, struct interface *in_if)
-{
-  
-  struct hello_neighbor  *neighbors;
-
-  neighbors=message->neighbors;
-  
-  while(neighbors!=NULL)
-    {  
-      //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&neighbors->address));
-      //printf("against %s\n",olsr_ip_to_string(&main_addr));
-
-
-    if(ipversion == AF_INET)
-      {        
-       /* IPv4 */  
-       if(COMP_IP(&neighbors->address, &in_if->ip_addr))
-         {
-           //printf("ok");
-           if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
-             return 1;
-           
-           return 0;
-         }
+#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
-      {        
-       /* IPv6 */  
-       if(COMP_IP(&neighbors->address, &in_if->int6_addr.sin6_addr))
-         {
-           //printf("ok");
-           if((neighbors->link == SYM_LINK) && (neighbors->status == MPR_NEIGH))
-             return 1;
-           
-           return 0;
-         }
+    }
+#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);
       }
-      neighbors = neighbors->next; 
     }
-
-  /* Not found */
-  return 0;
+#endif
+  olsr_forward_message(m, from_addr);
 }
 
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */