* killed lots of #ifdef ... #endif which make the source quite unreadable
[olsrd.git] / src / process_package.c
index ab884c1..2367ea0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004, Andreas Tønnesen(andreto@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 
@@ -36,7 +36,6 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: process_package.c,v 1.48 2007/11/29 18:10:17 bernd67 Exp $
  */
 
 #include "process_package.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 process_message_neighbors(struct neighbor_entry *,
+                                      const struct hello_message *);
 
-static void linking_this_2_entries(struct neighbor_entry *, struct neighbor_2_entry *, float);
+static void linking_this_2_entries(struct neighbor_entry *,
+                                   struct neighbor_2_entry *, olsr_reltime);
 
-static int lookup_mpr_status(const struct hello_message *, const struct interface *);
+static olsr_bool lookup_mpr_status(const struct hello_message *,
+                                   const struct interface *);
 
 
 /**
@@ -78,7 +82,7 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
       message_neighbors != NULL;
       message_neighbors = message_neighbors->next)
     {
-#if !defined(NODEBUG) && defined(DEBUG)
+#ifdef DEBUG
       struct ipaddr_str buf;
 #endif
       union olsr_ip_addr      *neigh_addr;
@@ -111,17 +115,24 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
           if (two_hop_neighbor_yet != NULL)
             {
               /* Updating the holding time for this neighbor */
-              two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
+              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.
+              /*
+               * 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'
+                  /*
+                   * loop through the one-hop neighbors that see this
+                   * 'two_hop_neighbor'
+                   */
 
                   struct neighbor_list_entry *walker;
 
@@ -129,12 +140,14 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
                        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?
+                      /*
+                       * have we found the one-hop neighbor that sent the
+                       * HELLO message that we're current processing?
+                       */
 
                       if (walker->neighbor == neighbor)
                         {
-                          walker->path_link_quality = 0.0;
+                          walker->path_linkcost = LINK_COST_BROKEN;
                         }
                     }
                 }
@@ -184,22 +197,28 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
         }
     }
 
-  // Separate, second and third pass for link quality OLSR
+  /* 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;
 
-      // 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.
+      /* 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;
@@ -221,121 +240,55 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
 
               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
 
-              // loop through the one-hop neighbors that see this
-              // 'two_hop_neighbor'
+              /*
+               *  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?
+                  /*
+                   * have we found the one-hop neighbor that sent the
+                   * HELLO message that we're current processing?
+                   */
 
                   if (walker->neighbor == neighbor)
                     {
-                      double new_second_hop_link_quality, new_path_link_quality;
-
-                      // path link quality = link quality between us
-                      // and our one-hop neighbor x link quality between
-                      // our one-hop neighbor and the two-hop neighbor
-
-                      // let's compare this to ETX:
-
-                      // 1 / LQ1 + 1 / LQ2 < 1 / LQ3 + 1 / LQ4 <=>
-                      // LQ1 * LQ2 > LQ3 * LQ4
+                      olsr_linkcost new_second_hop_linkcost, new_path_linkcost;
 
-                      // so comparing path link quality values with ">" is
-                      // equivalent to comparing ETX values with "<"
-
-                      // the link quality between the 1-hop neighbour and the
+                      // the link cost between the 1-hop neighbour and the
                       // 2-hop neighbour
 
-                      new_second_hop_link_quality = 
-                        message_neighbors->link_quality *
-                        message_neighbors->neigh_link_quality;
+                      new_second_hop_linkcost = message_neighbors->cost;
 
-                      // the total quality for the route
+                      // the total cost for the route
                       // "us --- 1-hop --- 2-hop"
 
-                      new_path_link_quality =
-                        new_second_hop_link_quality *
-                        lnk->loss_link_quality * lnk->neigh_link_quality;
+                      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_link_quality > walker->path_link_quality)
-                        {
-                          walker->second_hop_link_quality = new_second_hop_link_quality;
-                          walker->path_link_quality = new_path_link_quality;
-                        }
-                    }
-                }
-            }
-        }
-
-      // Third pass for link quality OLSR: check if the 2-hop path qualities have
-      // actually changed. If so, signal this through the 'changes_neighborhood'
-      // and 'changes_topology' booleans. Keep a 'saved_path_link_quality' for
-      // later reference.
-      for(message_neighbors = message->neighbors;
-          message_neighbors != NULL;
-          message_neighbors = message_neighbors->next)
-        {
-          if(if_ifwithaddr(&message_neighbors->address) != NULL)
-            continue;
-
-          if(((message_neighbors->status == SYM_NEIGH) ||
-              (message_neighbors->status == MPR_NEIGH)))
-            {
-              struct neighbor_list_entry *walker;
-              struct neighbor_2_entry *two_hop_neighbor;
-              struct neighbor_2_list_entry *two_hop_neighbor_yet =
-                olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
-
-              if(!two_hop_neighbor_yet)
-                continue;
-
-              two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
-
-              // loop through the one-hop neighbors that see this
-              // 'two_hop_neighbor'
-
-              for (walker = two_hop_neighbor->neighbor_2_nblist.next;
-                   walker != &two_hop_neighbor->neighbor_2_nblist;
-                   walker = walker->next)
-                {
-                  // have we found the one-hop neighbor that sent the
-                  // HELLO message that we're current processing?
-
-                  if (walker->neighbor == neighbor)
-                    {
-                      double saved_lq, rel_lq;
-
-                      // saved previous total link quality
-
-                      saved_lq = walker->saved_path_link_quality;
-
-                      if (saved_lq == 0.0)
-                        saved_lq = -1.0;
-
-                      // if the link cost has changed by more than 10
-                      // percent, signal
-
-                      rel_lq = walker->path_link_quality / saved_lq;
-
-                      if (rel_lq > 1.1 || rel_lq < 0.9)
+                      if (new_path_linkcost < walker->path_linkcost)
                         {
-                          walker->saved_path_link_quality =
-                            walker->path_link_quality;
-
-                          if (olsr_cnf->lq_dlimit > 0)
-                          {
-                            changes_neighborhood = OLSR_TRUE;
-                            changes_topology = OLSR_TRUE;
-                          }
-
-                          else
-                            OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
+                          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");
+                            }
                         }
                     }
                 }
@@ -352,16 +305,16 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
  *@return nada
  */
 static void
-linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry *two_hop_neighbor, float vtime)
+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_link_quality = 0.0;
-  list_of_1_neighbors->saved_path_link_quality = 0.0;
-  list_of_1_neighbors->second_hop_link_quality = 0.0;
+  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;
@@ -370,8 +323,10 @@ linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry
   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 */
   
-  list_of_2_neighbors->neighbor_2_timer = GET_TIMESTAMP(vtime*1000);
+  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;
@@ -384,36 +339,92 @@ linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry
 }
 
 /**
- *Check if a hello message states this node as a MPR.
+ * 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
+ * @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 int
-lookup_mpr_status(const struct hello_message *message, const struct interface *in_if)
+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 != NULL; neighbors = neighbors->next) {
-    //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&buf, &neighbors->address));
-    //printf("against %s\n",olsr_ip_to_string(&buf, &main_addr));
 
+  for (neighbors = message->neighbors; neighbors; neighbors = neighbors->next) {
     if (olsr_cnf->ip_version == AF_INET
-              ? /* IPv4 */ ip4equal(&neighbors->address.v4, &in_if->ip_addr.v4)
-              : /* IPv6 */ ip6equal(&neighbors->address.v6, &in_if->int6_addr.sin6_addr)) {
-      //printf("ok");
+        ? 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 1;
+        return OLSR_TRUE;
       }
       break;
     }
   }
   /* Not found */
-  return 0;
+  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
@@ -423,12 +434,12 @@ olsr_init_package_process(void)
 {
   if (olsr_cnf->lq_level == 0)
     {
-      olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
+      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_lq_hello, LQ_HELLO_MESSAGE, 1);
+      olsr_parser_add_function(&olsr_input_hello, LQ_HELLO_MESSAGE, 1);
       olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
     }
 
@@ -450,59 +461,21 @@ olsr_hello_tap(struct hello_message *message,
 
   if (olsr_cnf->lq_level > 0)
     {
-      double saved_lq;
-      double rel_lq;
       struct hello_neighbor *walker;
-      // just in case our neighbor has changed its HELLO interval
+      /* 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
-
+      /* 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;
 
-      // the current reference link quality
-
-      saved_lq = lnk->saved_neigh_link_quality;
-
-      if (saved_lq == 0.0)
-        saved_lq = -1.0;
-
       // 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);
 
-      if (walker != NULL)
-        lnk->neigh_link_quality = walker->link_quality;
-
-      else
-        lnk->neigh_link_quality = 0.0;
-
-      // if the link quality has changed by more than 10 percent,
-      // print the new link quality table
-
-      rel_lq = lnk->neigh_link_quality / saved_lq;
-
-      if (rel_lq > 1.1 || rel_lq < 0.9)
-        {
-          lnk->saved_neigh_link_quality = lnk->neigh_link_quality;
-
-          if (olsr_cnf->lq_dlimit > 0)
-          {
-            changes_neighborhood = OLSR_TRUE;
-            changes_topology = OLSR_TRUE;
-          }
-
-          else
-            OLSR_PRINTF(3, "Skipping Dijkstra (2)\n");
-
-          // create a new ANSN
-
-          // XXX - we should check whether we actually
-          // announce this neighbour
-
-         signal_link_changes(OLSR_TRUE);
-        }
+      /* update packet loss for link quality calculation */
+      olsr_update_packet_loss(lnk);
     }
   
   neighbor = lnk->neighbor;
@@ -513,7 +486,7 @@ olsr_hello_tap(struct hello_message *message,
   if(olsr_cnf->use_hysteresis)
     {
       /* Update HELLO timeout */
-      //printf("MESSAGE HTIME: %f\n", message->htime);
+      /* printf("MESSAGE HTIME: %f\n", message->htime);*/
       olsr_update_hysteresis_hello(lnk, message->htime);
     }
 
@@ -527,9 +500,7 @@ olsr_hello_tap(struct hello_message *message,
   /* Check willingness */
   if(neighbor->willingness != message->willingness)
     {
-#ifndef NODEBUG
       struct ipaddr_str buf;
-#endif
       OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
                  olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr),
                  neighbor->willingness,
@@ -555,31 +526,6 @@ olsr_hello_tap(struct hello_message *message,
   return;
 }
 
-/**
- *Processes a received HELLO message. 
- *
- *@param m the incoming OLSR message
- *@return 0 on sucess
- */
-
-void
-olsr_process_received_hello(union olsr_message *m,
-                            struct interface *in_if,
-                            union olsr_ip_addr *from_addr)
-{
-  struct hello_message      message;
-
-  hello_chgestruct(&message, m);
-
-  if(!olsr_validate_address(&message.source_addr))
-    {
-      olsr_free_hello_packet(&message);
-      return;
-    }
-
-  olsr_hello_tap(&message, in_if, from_addr);
-}
-
 /**
  *Process a received(and parsed) MID message
  *For every address check if there is a topology node
@@ -591,10 +537,10 @@ olsr_process_received_hello(union olsr_message *m,
 
 void
 olsr_process_received_mid(union olsr_message *m,
-                          struct interface *in_if,
+                          struct interface *in_if __attribute__((unused)),
                           union olsr_ip_addr *from_addr)
 {
-#if !defined(NODEBUG) && defined(DEBUG)
+#ifdef DEBUG
   struct ipaddr_str buf;
 #endif
   struct mid_alias *tmp_adr;
@@ -607,9 +553,6 @@ olsr_process_received_mid(union olsr_message *m,
     return;
   }
 
-  if (olsr_check_dup_table_proc(&message.mid_origaddr, 
-                                message.mid_seqno)) {
-
 #ifdef DEBUG
     OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&buf, &message.mid_origaddr));
 #endif
@@ -622,37 +565,28 @@ olsr_process_received_mid(union olsr_message *m,
      */
 
     if(check_neighbor_link(from_addr) != SYM_LINK) {
-#ifndef NODEBUG
       struct ipaddr_str buf;
-#endif
       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, (float)message.vtime);
+    olsr_update_mid_table(&message.mid_origaddr, message.vtime);
 
     while (tmp_adr) {
       if (!mid_lookup_main_addr(&tmp_adr->alias_addr)){
-#ifndef NODEBUG
         struct ipaddr_str buf;
-#endif
         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, (float)message.vtime);
+        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, 
-                      &message.mid_origaddr, 
-                      message.mid_seqno, 
-                      in_if,
-                      from_addr);
+  olsr_forward_message(m, from_addr);
   olsr_free_mid_packet(&message);
 }
 
@@ -668,56 +602,102 @@ olsr_process_received_mid(union olsr_message *m,
 
 void
 olsr_process_received_hna(union olsr_message *m,
-                          struct interface *in_if,
+                          struct interface *in_if __attribute__((unused)),
                           union olsr_ip_addr *from_addr)
 {
-  struct hna_net_addr  *hna_tmp;
-  struct  hna_message message;
+
+  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
 
-  hna_chgestruct(&message, m);
+  /* Check if everyting is ok */
+  if (!m) {
+    return;
+  }
+  curr = (const olsr_u8_t *)m;
 
-  if(!olsr_validate_address(&message.originator)) {
-    olsr_free_hna_packet(&message);
+  /* 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;
 
-  if (olsr_check_dup_table_proc(&message.originator, 
-                                message.packet_seq_number)) {
+  /* validate originator */
+  pkt_get_ipaddress(&curr, &originator);
+  /*printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator));*/
 
-    hna_tmp = message.hna_net;
+  /* 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) {
-#ifndef NODEBUG
+    if (check_neighbor_link(from_addr) != SYM_LINK) {
       struct ipaddr_str buf;
-#endif
       OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
-      olsr_free_hna_packet(&message);
       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);
       }
-
-      hna_tmp = hna_tmp->next;
     }
-  }
-
-  olsr_forward_message(m, 
-                      &message.originator, 
-                      message.packet_seq_number, 
-                      in_if,
-                      from_addr);
-  olsr_free_hna_packet(&message);
+#endif
+  olsr_forward_message(m, from_addr);
 }
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */