Improved duplicate/sequencenumber handling. Small change in message handler callback...
authorHenning Rogge <hrogge@googlemail.com>
Sun, 19 Jul 2009 17:08:11 +0000 (19:08 +0200)
committerHenning Rogge <hrogge@googlemail.com>
Sun, 19 Jul 2009 17:08:11 +0000 (19:08 +0200)
21 files changed:
lib/debuginfo/src/olsrd_debuginfo.c
lib/mdns/src/mdns.c
lib/mdns/src/mdns.h
lib/nameservice/src/nameservice.c
lib/nameservice/src/nameservice.h
src/duplicate_set.c
src/duplicate_set.h
src/hna_set.c
src/hna_set.h
src/interfaces.c
src/main.c
src/mid_set.c
src/mid_set.h
src/olsr.c
src/olsr_time.c
src/parser.c
src/parser.h
src/process_package.c
src/tc_set.c
src/tc_set.h
src/unix/ifnet.c

index 3ad27fb..be7c4d6 100644 (file)
@@ -80,7 +80,7 @@ static enum olsr_txtcommand_result debuginfo_pktstat(struct comport_connection *
 static enum olsr_txtcommand_result debuginfo_cookies(struct comport_connection *con,  char *cmd, char *param);
 
 static void update_statistics_ptr(void *);
-static bool olsr_msg_statistics(union olsr_message *msg, struct interface *input_if, union olsr_ip_addr *from_addr);
+static void olsr_msg_statistics(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 static char *olsr_packet_statistics(char *packet, struct interface *interface, union olsr_ip_addr *, int *length);
 static void update_statistics_ptr(void *data __attribute__ ((unused)));
 
@@ -307,9 +307,9 @@ update_statistics_ptr(void *data __attribute__ ((unused)))
 }
 
 /* update message statistics */
-static bool
-olsr_msg_statistics(union olsr_message *msg,
-                    struct interface *input_if __attribute__ ((unused)), union olsr_ip_addr *from_addr __attribute__ ((unused)))
+static void
+olsr_msg_statistics(union olsr_message *msg, struct interface *input_if __attribute__ ((unused)),
+    union olsr_ip_addr *from_addr __attribute__ ((unused)), enum duplicate_status status  __attribute__ ((unused)))
 {
   int msgtype, msgsize;
   union olsr_ip_addr origaddr;
@@ -368,7 +368,6 @@ olsr_msg_statistics(union olsr_message *msg,
   tr->current.data[type]++;
   tr->current.data[DTR_MESSAGES]++;
   tr->current.data[DTR_MSG_TRAFFIC] += msgsize;
-  return true;
 }
 
 /* update traffic statistics */
index d6e7894..9f25b4d 100644 (file)
@@ -133,8 +133,9 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
 
 
 
-bool
-olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr)
+void
+olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)),
+    union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
 {
   union olsr_ip_addr originator;
   int size;
@@ -154,14 +155,14 @@ olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unuse
   /* Check if message originated from this node.
    *         If so - back off */
   if (olsr_ipcmp(&originator, &olsr_cnf->router_id) == 0)
-    return false;
+    return;
 
   /* Check that the neighbor this message was received from is symmetric.
    *         If not - back off*/
   if (check_neighbor_link(ipaddr) != SYM_LINK) {
     //struct ipaddr_str strbuf;
     //OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
-    return false;
+    return;
   }
 
   if (olsr_cnf->ip_version == AF_INET) {
@@ -169,8 +170,6 @@ olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unuse
   } else {
     PacketReceivedFromOLSR((unsigned char *)&m->v6.message, size - 12 - 96);
   }
-  /* Forward the message */
-  return true;
 }
 
 //Sends a packet in the OLSR network
index 4f6fd6a..d7ce36b 100644 (file)
@@ -27,7 +27,7 @@ Written by Saverio Proto <zioproto@gmail.com> and Claudio Pisa <clauz@ninux.org>
 
 
 #include "plugin.h"             /* union set_plugin_parameter_addon */
-
+#include "duplicate_set.h"
 #include "parser.h"
 
 #define MESSAGE_TYPE 132
@@ -67,7 +67,7 @@ void CloseMDNS(void);
 void olsr_mdns_gen(unsigned char *packet, int len);
 
 /* Parser function to register with the scheduler */
-bool olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *);
+void olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 
 #endif /* _MDNS_MDNS_H */
 
index dca47ab..d006242 100644 (file)
@@ -669,8 +669,9 @@ olsr_namesvc_gen(void *foo __attribute__ ((unused)))
 /**
  * Parse name olsr message of NAME type
  */
-bool
-olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr)
+void
+olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)),
+    union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
 {
   struct namemsg *namemessage;
   union olsr_ip_addr originator;
@@ -698,7 +699,7 @@ olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unuse
   /* Check if message originated from this node.
      If so - back off */
   if (olsr_ipcmp(&originator, &olsr_cnf->router_id) == 0)
-    return false;
+    return;
 
   /* Check that the neighbor this message was received from is symmetric.
      If not - back off */
@@ -707,13 +708,10 @@ olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unuse
     struct ipaddr_str strbuf;
 #endif
     OLSR_DEBUG(LOG_PLUGINS, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
-    return false;
+    return;
   }
 
   update_name_entry(&originator, namemessage, size, vtime);
-
-  /* Forward the message */
-  return true;
 }
 
 /**
index ee955f4..2445a9e 100644 (file)
@@ -54,7 +54,7 @@
 #include "interfaces.h"
 #include "olsr_protocol.h"
 #include "common/list.h"
-
+#include "duplicate_set.h"
 #include "plugin.h"
 #include "nameservice_msg.h"
 #include "hashing.h"
@@ -129,7 +129,7 @@ void olsr_expire_write_file_timer(void *);
 void olsr_namesvc_delete_db_entry(struct db_entry *);
 
 /* Parser function to register with the sceduler */
-bool olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *);
+void olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 
 /* callback for periodic timer */
 void olsr_namesvc_gen(void *);
index 1079db0..6c5360a 100644 (file)
@@ -60,6 +60,21 @@ static struct timer_entry *duplicate_cleanup_timer;
 static struct olsr_cookie_info *duplicate_timer_cookie = NULL;
 static struct olsr_cookie_info *duplicate_mem_cookie = NULL;
 
+int olsr_seqno_diff(uint16_t reference, uint16_t other) {
+  int diff;
+
+  diff = (int)reference - (int)other;
+
+  // overflow ?
+  if (diff >= (1 << 15)) {
+    diff -= (1 << 16);
+  }
+  else if (diff < -(1 << 15)) {
+    diff += (1 << 16);
+  }
+  return diff;
+}
+
 void
 olsr_init_duplicate_set(void)
 {
@@ -140,8 +155,8 @@ olsr_flush_duplicate_entries(void)
   } OLSR_FOR_ALL_DUP_ENTRIES_END(entry);
 }
 
-int
-olsr_message_is_duplicate(union olsr_message *m, bool forwarding)
+bool
+olsr_is_duplicate_message(union olsr_message *m, bool forwarding, enum duplicate_status *status)
 {
   struct avl_tree *tree;
   struct dup_entry *entry;
@@ -150,11 +165,16 @@ olsr_message_is_duplicate(union olsr_message *m, bool forwarding)
   uint32_t valid_until;
   uint16_t seqnr;
   union olsr_ip_addr *ip;
+  enum duplicate_status dummy = 0;
 
 #if !defined(REMOVE_LOG_DEBUG)
   struct ipaddr_str buf;
 #endif
 
+  if (status == NULL) {
+    status = &dummy;
+  }
+
   tree = forwarding ? &forward_set : &processing_set;
   if (olsr_cnf->ip_version == AF_INET) {
     seqnr = ntohs(m->v4.seqno);
@@ -179,19 +199,17 @@ olsr_message_is_duplicate(union olsr_message *m, bool forwarding)
       avl_insert(tree, &entry->avl, 0);
       entry->valid_until = valid_until;
     }
+
+    *status = NEW_OLSR_MESSAGE;
     return false;               // okay, we process this package
   }
 
-  diff = (int)seqnr - (int)(entry->seqnr);
+  diff = olsr_seqno_diff(seqnr, entry->seqnr);
 
   // update timestamp
   if (valid_until > entry->valid_until) {
     entry->valid_until = valid_until;
   }
-  // overflow ?
-  if (diff > (1 << 15)) {
-    diff -= (1 << 16);
-  }
 
   if (diff < -31) {
     entry->too_low_counter++;
@@ -201,10 +219,16 @@ olsr_message_is_duplicate(union olsr_message *m, bool forwarding)
       entry->too_low_counter = 0;
       entry->seqnr = seqnr;
       entry->array = 1;
-      return false;             /* start with a new sequence number, so NO duplicate */
+
+      /* start with a new sequence number, so NO duplicate */
+      *status = RESET_SEQNO_OLSR_MESSAGE;
+      return false;
     }
     OLSR_DEBUG(LOG_DUPLICATE_SET, "blocked %x from %s\n", seqnr, olsr_ip_to_string(&buf, mainIp));
-    return true;                /* duplicate ! */
+
+    /* much too old */
+    *status = TOO_OLD_OLSR_MESSAGE;
+    return true;
   }
 
   entry->too_low_counter = 0;
@@ -214,11 +238,17 @@ olsr_message_is_duplicate(union olsr_message *m, bool forwarding)
     if ((entry->array & bitmask) != 0) {
       OLSR_DEBUG(LOG_DUPLICATE_SET, "blocked %x (diff=%d,mask=%08x) from %s\n", seqnr, diff,
                  entry->array, olsr_ip_to_string(&buf, mainIp));
-      return true;              /* duplicate ! */
+
+      /* duplicate ! */
+      *status = DUPLICATE_OLSR_MESSAGE;
+      return true;
     }
     entry->array |= bitmask;
     OLSR_DEBUG(LOG_DUPLICATE_SET, "processed %x from %s\n", seqnr, olsr_ip_to_string(&buf, mainIp));
-    return false;               /* no duplicate */
+
+    /* no duplicate */
+    *status = OLD_OLSR_MESSAGE;
+    return false;
   } else if (diff < 32) {
     entry->array <<= (uint32_t) diff;
   } else {
@@ -227,7 +257,10 @@ olsr_message_is_duplicate(union olsr_message *m, bool forwarding)
   entry->array |= 1;
   entry->seqnr = seqnr;
   OLSR_DEBUG(LOG_DUPLICATE_SET, "processed %x from %s\n", seqnr, olsr_ip_to_string(&buf, mainIp));
-  return false;                 /* no duplicate */
+
+  /* no duplicate */
+  *status = NEW_OLSR_MESSAGE;
+  return false;
 }
 
 void
index bcddf56..0ec7af7 100644 (file)
@@ -60,10 +60,19 @@ struct dup_entry {
   uint32_t valid_until;
 };
 
+enum duplicate_status {
+  RESET_SEQNO_OLSR_MESSAGE,
+  NEW_OLSR_MESSAGE,
+  OLD_OLSR_MESSAGE,
+  DUPLICATE_OLSR_MESSAGE,
+  TOO_OLD_OLSR_MESSAGE
+};
+
 AVLNODE2STRUCT(duptree2dupentry, struct dup_entry, avl);
 
+int EXPORT(olsr_seqno_diff)(uint16_t reference, uint16_t other);
 void olsr_init_duplicate_set(void);
-int olsr_message_is_duplicate(union olsr_message *m, bool forward_set);
+bool olsr_is_duplicate_message(union olsr_message *m, bool forward_set, enum duplicate_status *status);
 void olsr_print_duplicate_table(void);
 void olsr_flush_duplicate_entries(void);
 
index 0fb1a60..b417af3 100644 (file)
@@ -189,7 +189,8 @@ olsr_expire_hna_net_entry(void *context)
  *@return nada
  */
 static void
-olsr_update_hna_entry(const union olsr_ip_addr *gw, const struct olsr_ip_prefix *prefix, uint32_t vtime)
+olsr_update_hna_entry(const union olsr_ip_addr *gw, const struct olsr_ip_prefix *prefix, uint32_t vtime,
+    uint16_t msg_seq)
 {
   struct tc_entry *tc = olsr_locate_tc_entry(gw);
   struct hna_net *net_entry = olsr_lookup_hna_net(tc, prefix);
@@ -200,6 +201,8 @@ olsr_update_hna_entry(const union olsr_ip_addr *gw, const struct olsr_ip_prefix
     changes_hna = true;
   }
 
+  net_entry->tc_entry_seqno = msg_seq;
+
   /*
    * Add the rt_path for the entry.
    */
@@ -239,27 +242,57 @@ olsr_print_hna_set(void)
 #endif
 }
 
+static void
+olsr_prune_hna_entries(struct tc_entry *tc)
+{
+  struct hna_net *hna_net;
+
+  OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, hna_net) {
+    if (hna_net->tc_entry_seqno != tc->hna_seq) {
+      olsr_delete_hna_net(hna_net);
+    }
+  } OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, hna_net);
+}
+
 /**
  * Process incoming HNA message.
  * Forwards the message if that is to be done.
  */
-bool
-olsr_input_hna(union olsr_message *msg, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *from_addr)
+void
+olsr_input_hna(union olsr_message *msg, struct interface *in_if __attribute__ ((unused)),
+    union olsr_ip_addr *from_addr, enum duplicate_status status)
 {
-  struct olsrmsg_hdr msg_hdr;
+  uint16_t msg_size, msg_seq;
+  uint8_t type, ttl, msg_hops;
+  uint32_t vtime;
+  union olsr_ip_addr originator;
+  struct tc_entry *tc;
   struct olsr_ip_prefix prefix;
   const uint8_t *curr, *curr_end;
 #if !defined REMOVE_LOG_DEBUG
   struct ipaddr_str buf;
 #endif
 
-  if (!(curr = olsr_parse_msg_hdr(msg, &msg_hdr))) {
-    return false;
+  curr = (void *)msg;
+
+  /* We are only interested in MID message types. */
+  pkt_get_u8(&curr, &type);
+  if (type != HNA_MESSAGE) {
+    return;
   }
 
-  /* We are only interested in HNA message types. */
-  if (msg_hdr.type != HNA_MESSAGE) {
-    return false;
+  pkt_get_reltime(&curr, &vtime);
+  pkt_get_u16(&curr, &msg_size);
+
+  pkt_get_ipaddress(&curr, &originator);
+
+  /* Copy header values */
+  pkt_get_u8(&curr, &ttl);
+  pkt_get_u8(&curr, &msg_hops);
+  pkt_get_u16(&curr, &msg_seq);
+
+  if (!olsr_validate_address(&originator)) {
+    return;
   }
 
   /*
@@ -269,16 +302,24 @@ olsr_input_hna(union olsr_message *msg, struct interface *in_if __attribute__ ((
    */
   if (check_neighbor_link(from_addr) != SYM_LINK) {
     OLSR_DEBUG(LOG_HNA, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
-    return false;
+    return;
+  }
+
+  tc = olsr_locate_tc_entry(&originator);
+  if (status != RESET_SEQNO_OLSR_MESSAGE && olsr_seqno_diff(msg_seq, tc->mid_seq) <= 0) {
+    /* this HNA is too old, discard it */
+    return;
   }
+  tc->hna_seq = msg_seq;
 
-  OLSR_DEBUG(LOG_HNA, "Processing HNA from %s, seq 0x%04x\n", olsr_ip_to_string(&buf, &msg_hdr.originator), msg_hdr.seqno);
+  OLSR_DEBUG(LOG_HNA, "Processing HNA from %s, seq 0x%04x\n", olsr_ip_to_string(&buf, &originator), msg_seq);
 
   /*
    * Now walk the list of HNA advertisements.
    */
-  curr_end = (const uint8_t *)msg + msg_hdr.size;
-  while (curr < curr_end) {
+  curr_end = (uint8_t *)msg + msg_size;
+
+  while (curr + olsr_cnf->ipsize < curr_end) {
 
     pkt_get_ipaddress(&curr, &prefix.prefix);
     pkt_get_prefixlen(&curr, &prefix.prefix_len);
@@ -287,11 +328,15 @@ olsr_input_hna(union olsr_message *msg, struct interface *in_if __attribute__ ((
       /*
        * Only update if it's not from us.
        */
-      olsr_update_hna_entry(&msg_hdr.originator, &prefix, msg_hdr.vtime);
+      olsr_update_hna_entry(&originator, &prefix, vtime, msg_seq);
     }
   }
-  /* Forward the message */
-  return true;
+
+  /*
+   * Prune the HNAs that did not get refreshed by this advertisment.
+   */
+  olsr_prune_hna_entries(tc);
+
 }
 
 /*
index a336a2e..2840643 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "olsr_types.h"
 #include "olsr_protocol.h"
+#include "duplicate_set.h"
 #include "common/avl.h"
 
 struct hna_net {
@@ -52,6 +53,7 @@ struct hna_net {
   struct olsr_ip_prefix hna_prefix;    /* the prefix, key */
   struct timer_entry *hna_net_timer;   /* expiration timer */
   struct tc_entry *hna_tc;             /* backpointer to the owning tc entry */
+  uint16_t tc_entry_seqno;             /* sequence number for cleanup */
 };
 
 AVLNODE2STRUCT(hna_tc_tree2hna, struct hna_net, hna_tc_node);
@@ -68,7 +70,7 @@ AVLNODE2STRUCT(hna_tc_tree2hna, struct hna_net, hna_tc_node);
 #define OLSR_FOR_ALL_TC_HNA_ENTRIES_END(tc, hna_net) }}
 
 /* HNA msg input parser */
-bool olsr_input_hna(union olsr_message *, struct interface *, union olsr_ip_addr *);
+void olsr_input_hna(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 
 void olsr_init_hna_set(void);
 void olsr_flush_hna_nets(struct tc_entry *tc);
index 1cf1e7c..1a5cefd 100644 (file)
@@ -290,11 +290,9 @@ remove_interface(struct interface **pinterf)
   CLOSESOCKET(ifp->olsr_socket);
   ifp->olsr_socket = -1;
 
+//  free(ifp->int_name);
   unlock_interface(ifp);
 
-  free(ifp->int_name);
-  olsr_cookie_free(interface_mem_cookie, ifp);
-
   if (list_is_empty(&interface_head) && !olsr_cnf->allow_no_interfaces) {
     OLSR_ERROR(LOG_INTERFACE, "No more active interfaces - exiting.\n");
     olsr_exit(EXIT_FAILURE);
index 7567b72..1ebd0c4 100644 (file)
@@ -478,12 +478,11 @@ static void
 olsr_shutdown(void)
 {
   struct mid_entry *mid;
-  struct olsr_if_config *iface;
+  struct interface *iface;
 
   olsr_delete_all_kernel_routes();
 
   olsr_delete_all_tc_entries();
-  olsr_unlock_tc_entry(tc_myself);
 
   /* Flush MID database */
   OLSR_FOR_ALL_MID_ENTRIES(mid) {
@@ -505,9 +504,10 @@ olsr_shutdown(void)
   olsr_destroy_pluginsystem();
 
   /* Remove active interfaces */
-  for (iface = olsr_cnf->if_configs; iface != NULL; iface = iface->next) {
-    remove_interface(&iface->interf);
-  }
+  OLSR_FOR_ALL_INTERFACES(iface) {
+    struct interface **ptr = &iface;
+    remove_interface(ptr);
+  } OLSR_FOR_ALL_INTERFACES_END(iface)
 
   /* delete lo:olsr if neccesarry */
   if (olsr_cnf->source_ip_mode) {
@@ -539,9 +539,6 @@ olsr_shutdown(void)
   /* Stop and delete all timers. */
   olsr_flush_timers();
 
-  /* Free cookies and memory pools attached. */
-  olsr_delete_all_cookies();
-
   /* Remove parser hooks */
   olsr_deinit_parser();
 
@@ -552,6 +549,9 @@ olsr_shutdown(void)
 
   olsr_log_cleanup();
 
+  /* Free cookies and memory pools attached. */
+  olsr_delete_all_cookies();
+
   /* Flush config */
   olsr_free_cfg(olsr_cnf);
 }
index f8835d1..4407b92 100644 (file)
@@ -55,7 +55,6 @@
 #include <stdlib.h>
 
 static struct mid_entry *olsr_lookup_mid_entry(const union olsr_ip_addr *);
-static void olsr_prune_mid_entries(const union olsr_ip_addr *main_addr, uint16_t mid_seqno);
 
 /* Root of the MID tree */
 struct avl_tree mid_tree;
@@ -214,7 +213,7 @@ olsr_fixup_mid_main_addr(const union olsr_ip_addr *main_addr, const union olsr_i
  */
 static struct mid_entry *
 olsr_insert_mid_entry(const union olsr_ip_addr *main_addr,
-                      const union olsr_ip_addr *alias_addr, uint32_t vtime, uint16_t mid_seqno)
+                      const union olsr_ip_addr *alias_addr, uint32_t vtime)
 {
   struct tc_entry *tc;
   struct mid_entry *alias;
@@ -259,9 +258,6 @@ olsr_insert_mid_entry(const union olsr_ip_addr *main_addr,
   olsr_set_mid_timer(alias->mid_tc, vtime);
   olsr_lock_tc_entry(tc);
 
-  /* Set sequence number for alias purging */
-  alias->mid_seqno = mid_seqno;
-
   return alias;
 }
 
@@ -277,7 +273,7 @@ olsr_insert_mid_entry(const union olsr_ip_addr *main_addr,
  */
 static void
 olsr_update_mid_entry(const union olsr_ip_addr *main_addr,
-                      const union olsr_ip_addr *alias_addr, uint32_t vtime, uint16_t mid_seqno)
+                      const union olsr_ip_addr *alias_addr, uint32_t vtime, uint16_t msg_seq)
 {
   struct mid_entry *alias;
 
@@ -290,10 +286,7 @@ olsr_update_mid_entry(const union olsr_ip_addr *main_addr,
    */
   alias = olsr_lookup_mid_entry(alias_addr);
   if (alias) {
-    /* Update sequence number for alias purging */
-    alias->mid_seqno = mid_seqno;
-
-    /* XXX handle main IP address changes */
+    alias->mid_entry_seqno = msg_seq;
 
     /* Refresh the timer. */
     olsr_set_mid_timer(alias->mid_tc, vtime);
@@ -303,7 +296,9 @@ olsr_update_mid_entry(const union olsr_ip_addr *main_addr,
   /*
    * This is a fresh alias.
    */
-  alias = olsr_insert_mid_entry(main_addr, alias_addr, vtime, mid_seqno);
+  alias = olsr_insert_mid_entry(main_addr, alias_addr, vtime);
+
+  alias->mid_entry_seqno = msg_seq;
 
   /*
    * Do the needful if one of our neighbors has changed its main address.
@@ -419,15 +414,13 @@ olsr_flush_mid_entries(struct tc_entry *tc)
  * collection of the old entries.
  *
  * @param main_addr the root of MID entries.
- * @param mid_seqno the most recent message sequence number
  */
 static void
-olsr_prune_mid_entries(const union olsr_ip_addr *main_addr, uint16_t mid_seqno)
+olsr_prune_mid_entries(struct tc_entry *tc)
 {
-  struct tc_entry *tc = olsr_locate_tc_entry(main_addr);
   struct mid_entry *alias;
   OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias) {
-    if (alias->mid_seqno != mid_seqno) {
+    if (alias->mid_entry_seqno != tc->mid_seq) {
       olsr_delete_mid_entry(alias);
     }
   }
@@ -462,28 +455,26 @@ olsr_print_mid_set(void)
 /**
  * Process an incoming MID message.
  */
-bool
-olsr_input_mid(union olsr_message *msg, struct interface *input_if __attribute__ ((unused)), union olsr_ip_addr *from_addr)
+void
+olsr_input_mid(union olsr_message *msg, struct interface *input_if __attribute__ ((unused)),
+    union olsr_ip_addr *from_addr, enum duplicate_status status)
 {
   uint16_t msg_size, msg_seq;
   uint8_t type, ttl, msg_hops;
-  const unsigned char *curr;
+  const unsigned char *curr, *end;
   uint32_t vtime;
   union olsr_ip_addr originator, alias;
-  int alias_count;
+  struct tc_entry *tc;
 #if !defined REMOVE_LOG_DEBUG
   struct ipaddr_str buf;
 #endif
 
   curr = (void *)msg;
-  if (!msg) {
-    return false;
-  }
 
   /* We are only interested in MID message types. */
   pkt_get_u8(&curr, &type);
   if (type != MID_MESSAGE) {
-    return false;
+    return;
   }
 
   pkt_get_reltime(&curr, &vtime);
@@ -497,7 +488,7 @@ olsr_input_mid(union olsr_message *msg, struct interface *input_if __attribute__
   pkt_get_u16(&curr, &msg_seq);
 
   if (!olsr_validate_address(&originator)) {
-    return false;
+    return;
   }
 
   /*
@@ -507,33 +498,36 @@ olsr_input_mid(union olsr_message *msg, struct interface *input_if __attribute__
    */
   if (check_neighbor_link(from_addr) != SYM_LINK) {
     OLSR_DEBUG(LOG_MID, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
-    return false;
+    return;
   }
 
+  tc = olsr_locate_tc_entry(&originator);
 
-  /*
-   * How many aliases ?
-   */
-  alias_count = (msg_size - 12) / olsr_cnf->ipsize;
+  if (status != RESET_SEQNO_OLSR_MESSAGE && olsr_seqno_diff(msg_seq, tc->mid_seq) <= 0) {
+    /* this MID is too old, discard it */
+    return;
+  }
+  tc->mid_seq = msg_seq;
 
   OLSR_DEBUG(LOG_MID, "Processing MID from %s with %d aliases, seq 0x%04x\n",
-             olsr_ip_to_string(&buf, &originator), alias_count, msg_seq);
+             olsr_ip_to_string(&buf, &originator), (int)((msg_size-12)/olsr_cnf->ipsize), msg_seq);
+
+
+  /* calculate end of message */
+  end = (uint8_t *)msg + msg_size;
+
   /*
    * Now walk the list of alias advertisements one by one.
    */
-  while (alias_count) {
+  while (curr + olsr_cnf->ipsize < end) {
     pkt_get_ipaddress(&curr, &alias);
     olsr_update_mid_entry(&originator, &alias, vtime, msg_seq);
-    alias_count--;
   }
 
   /*
    * Prune the aliases that did not get refreshed by this advertisment.
    */
-  olsr_prune_mid_entries(&originator, msg_seq);
-
-  /* Forward the message */
-  return true;
+  olsr_prune_mid_entries(tc);
 }
 
 /*
index e8d52bb..c3ea15f 100644 (file)
 #include "olsr_types.h"
 #include "olsr_protocol.h"
 #include "common/avl.h"
+#include "duplicate_set.h"
 
 struct mid_entry {
   struct avl_node mid_tc_node;         /* node in the per-tc mid tree */
   struct avl_node mid_node;            /* node in the global mid tree */
   union olsr_ip_addr mid_alias_addr;   /* key for both trees */
   struct tc_entry *mid_tc;             /* backpointer to owning tc entry */
-  uint16_t mid_seqno;                  /* msg seq number for change tracking */
+  uint16_t mid_entry_seqno;            /* msg seq number for change tracking */
 };
 
 AVLNODE2STRUCT(global_tree2mid, struct mid_entry, mid_node);
@@ -81,7 +82,7 @@ AVLNODE2STRUCT(alias_tree2mid, struct mid_entry, mid_tc_node);
 extern struct avl_tree mid_tree;
 
 /* MID msg input parser */
-bool olsr_input_mid(union olsr_message *, struct interface *, union olsr_ip_addr *);
+void olsr_input_mid(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 
 void olsr_init_mid_set(void);
 void olsr_delete_mid_entry(struct mid_entry *);
index f788587..848db55 100644 (file)
@@ -298,7 +298,7 @@ olsr_forward_message(union olsr_message *m, struct interface *in_if, union olsr_
   }
 
   /* check if we already forwarded this message */
-  if (olsr_message_is_duplicate(m, true)) {
+  if (olsr_is_duplicate_message(m, true, NULL)) {
     OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because we already forwarded it.\n",
         m->v4.olsr_msgtype, olsr_ip_to_string(&buf, src));
     return 0;                   /* it's a duplicate, forget about it */
index 46b0714..dfb8ae7 100644 (file)
@@ -161,9 +161,12 @@ uint32_t
 olsr_txt_to_milli(char *txt) {
   uint32_t t1 = 0,t2 = 0;
   char *fraction;
+  char *savePtr = NULL, save = 0;
 
   fraction = strchr(txt, '.');
   if (fraction != NULL) {
+    savePtr = fraction;
+    save = *savePtr;
     *fraction++ = 0;
 
     t2 = strtoul(fraction, NULL, 10);
@@ -178,6 +181,10 @@ olsr_txt_to_milli(char *txt) {
   if (t1 > UINT32_MAX / MSEC_PER_SEC) {
     t1 = UINT32_MAX / MSEC_PER_SEC;
   }
+
+  if (savePtr) {
+    *savePtr = save;
+  }
   return t1*MSEC_PER_SEC + t2;
 }
 
index 7d512b2..49e0498 100644 (file)
@@ -232,12 +232,14 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
   int msgsize;
   struct parse_function_entry *entry;
   struct packetparser_function_entry *packetparser;
+  enum duplicate_status dup_status = 0;
   int count = size - ((char *)m - (char *)olsr);
 #if !defined(REMOVE_LOG_INFO) || !defined(REMOVE_LOG_WARN)
   struct ipaddr_str buf;
 #endif
 
-  if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version)) {
+  /* packet smaller than minimal olsr packet ? */
+  if (count < 4) {
     return;
   }
   if (ntohs(olsr->olsr_packlen) != (size_t) size) {
@@ -256,9 +258,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
   msgsize = ntohs(olsr_cnf->ip_version == AF_INET ? m->v4.olsr_msgsize : m->v6.olsr_msgsize);
 
   for (; count > 0; m = (union olsr_message *)((char *)m + msgsize)) {
-    bool forward = true;
-
-    if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version)) {
+    if (count < MIN_MESSAGE_SIZE()) {
       break;
     }
     msgsize = ntohs(olsr_cnf->ip_version == AF_INET ? m->v4.olsr_msgsize : m->v6.olsr_msgsize);
@@ -287,7 +287,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
       continue;
     }
 
-    if (olsr_message_is_duplicate(m, false)) {
+    if (olsr_is_duplicate_message(m, false, &dup_status)) {
       OLSR_INFO(LOG_PACKET_PARSING, "Not processing message duplicate from %s!\n",
           olsr_ip_to_string(&buf, (union olsr_ip_addr *)&m->v4.originator));
     }
@@ -296,14 +296,11 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
         /* Should be the same for IPv4 and IPv6 */
         /* Promiscuous or exact match */
         if ((entry->type == PROMISCUOUS) || (entry->type == m->v4.olsr_msgtype)) {
-          if (!entry->function(m, in_if, from_addr))
-            forward = false;
+          entry->function(m, in_if, from_addr, dup_status);
         }
       }
     }
-    if (forward) {
-      olsr_forward_message(m, in_if, from_addr);
-    }
+    olsr_forward_message(m, in_if, from_addr);
   }                             /* for olsr_msg */
 }
 
index a8e2929..56628c2 100644 (file)
 #ifndef _OLSR_MSG_PARSER
 #define _OLSR_MSG_PARSER
 
+#include "duplicate_set.h"
 #include "olsr_protocol.h"
 #include "lq_packet.h"
 
 #define PROMISCUOUS 0xffffffff
 
-#define MIN_PACKET_SIZE(ver)   ((int)(sizeof(uint8_t) * (((ver) == AF_INET) ? 4 : 7)))
+#define MIN_MESSAGE_SIZE()     ((int)(8 + olsr_cnf->ipsize))
 
 /* Function returns false if the message should not be forwarded */
-typedef bool parse_function(union olsr_message *, struct interface *, union olsr_ip_addr *);
+typedef void parse_function(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 
 struct parse_function_entry {
   uint32_t type;                       /* If set to PROMISCUOUS all messages will be received */
index dba0b0f..db7cdc8 100644 (file)
@@ -48,7 +48,8 @@
 #include "parser.h"
 #include "olsr_logging.h"
 
-static bool olsr_input_hello(union olsr_message *ser, struct interface *inif, union olsr_ip_addr *from);
+static void olsr_input_hello(union olsr_message *, struct interface *, union olsr_ip_addr *,
+    enum duplicate_status);
 
 static void process_message_neighbors(struct nbr_entry *, const struct lq_hello_message *);
 
@@ -207,7 +208,7 @@ olsr_deinit_package_process(void)
   olsr_parser_remove_function(&olsr_input_hna, HNA_MESSAGE);
 }
 
-static int
+static bool
 deserialize_hello(struct lq_hello_message *hello, const void *ser)
 {
   const unsigned char *limit;
@@ -218,7 +219,7 @@ deserialize_hello(struct lq_hello_message *hello, const void *ser)
   pkt_get_u8(&curr, &type);
   if (type != HELLO_MESSAGE && type != LQ_HELLO_MESSAGE) {
     /* No need to do anything more */
-    return 1;
+    return true;
   }
   pkt_get_reltime(&curr, &hello->comm.vtime);
   pkt_get_u16(&curr, &size);
@@ -257,7 +258,7 @@ deserialize_hello(struct lq_hello_message *hello, const void *ser)
       hello->neigh = neigh;
     }
   }
-  return 0;
+  return false;
 }
 
 
@@ -334,21 +335,14 @@ hello_tap(struct lq_hello_message *message, struct interface *in_if, const union
   destroy_lq_hello(message);
 }
 
-static bool
-olsr_input_hello(union olsr_message *msg, struct interface *inif, union olsr_ip_addr *from)
+static void
+olsr_input_hello(union olsr_message *msg, struct interface *inif, union olsr_ip_addr *from,
+    enum duplicate_status status __attribute__ ((unused)))
 {
   struct lq_hello_message hello;
-
-  if (msg == NULL) {
-    return false;
-  }
-  if (deserialize_hello(&hello, msg) != 0) {
-    return false;
+  if (!deserialize_hello(&hello, msg)) {
+    hello_tap(&hello, inif, from);
   }
-  hello_tap(&hello, inif, from);
-
-  /* Do not forward hello messages */
-  return false;
 }
 
 /*
index 4ea67d7..4da679a 100644 (file)
@@ -63,66 +63,8 @@ struct olsr_cookie_info *tc_mem_cookie = NULL;
 
 static uint32_t relevantTcCount = 0;
 
-/*
- * Sven-Ola 2007-Dec: These four constants include an assumption
- * on how long a typical olsrd mesh memorizes (TC) messages in the
- * RAM of all nodes and how many neighbour changes between TC msgs.
- * In Berlin, we encounter hop values up to 70 which means that
- * messages may live up to ~15 minutes cycling between nodes and
- * obviously breaking out of the timeout_dup() jail. It may be more
- * correct to dynamically adapt those constants, e.g. by using the
- * max hop number (denotes size-of-mesh) in some form or maybe
- * a factor indicating how many (old) versions of olsrd are on.
- */
-
-/* Value window for ansn, identifies old messages to be ignored */
-#define TC_ANSN_WINDOW 256
-
-/* Value window for seqno, identifies old messages to be ignored */
-#define TC_SEQNO_WINDOW 1024
-
-/* Enlarges the value window for upcoming ansn/seqno to be accepted */
-#define TC_ANSN_WINDOW_MULT 4
-
-/* Enlarges the value window for upcoming ansn/seqno to be accepted */
-#define TC_SEQNO_WINDOW_MULT 8
-
 static void olsr_cleanup_tc_entry(struct tc_entry *tc);
 
-static bool
-olsr_seq_inrange_low(int beg, int end, uint16_t seq)
-{
-  if (beg < 0) {
-    if (seq >= (uint16_t) beg || seq < end) {
-      return true;
-    }
-  } else if (end >= 0x10000) {
-    if (seq >= beg || seq < (uint16_t) end) {
-      return true;
-    }
-  } else if (seq >= beg && seq < end) {
-    return true;
-  }
-  return false;
-}
-
-static bool
-olsr_seq_inrange_high(int beg, int end, uint16_t seq)
-{
-  if (beg < 0) {
-    if (seq > (uint16_t) beg || seq <= end) {
-      return true;
-    }
-  } else if (end >= 0x10000) {
-    if (seq > beg || seq <= (uint16_t) end) {
-      return true;
-    }
-  } else if (seq > beg && seq <= end) {
-    return true;
-  }
-  return false;
-}
-
 /**
  * Add a new tc_entry to the tc tree
  *
@@ -834,8 +776,9 @@ olsr_calculate_tc_border(uint8_t lower_border,
  * as every call to pkt_get increases the packet offset and
  * hence the spot we are looking at.
  */
-bool
-olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute__ ((unused)), union olsr_ip_addr * from_addr)
+void
+olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute__ ((unused)),
+    union olsr_ip_addr * from_addr, enum duplicate_status status)
 {
   uint16_t size, msg_seq, ansn;
   uint8_t type, ttl, msg_hops, lower_border, upper_border;
@@ -851,14 +794,11 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
   int borderSet = 0;
 
   curr = (void *)msg;
-  if (!msg) {
-    return false;
-  }
 
   /* We are only interested in TC message types. */
   pkt_get_u8(&curr, &type);
   if ((type != LQ_TC_MESSAGE) && (type != TC_MESSAGE)) {
-    return false;
+    return;
   }
 
   /*
@@ -868,7 +808,7 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
    */
   if (check_neighbor_link(from_addr) != SYM_LINK) {
     OLSR_DEBUG(LOG_TC, "Received TC from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
-    return false;
+    return;
   }
 
   pkt_get_reltime(&curr, &vtime);
@@ -888,36 +828,10 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
 
   tc = olsr_lookup_tc_entry(&originator);
 
-  if (tc && 0 != tc->edge_tree.count) {
-    if (olsr_seq_inrange_high((int)tc->msg_seq - TC_SEQNO_WINDOW,
-                              tc->msg_seq, msg_seq) && olsr_seq_inrange_high((int)tc->ansn - TC_ANSN_WINDOW, tc->ansn, ansn)) {
-
-      /*
-       * Ignore already seen seq/ansn values (small window for mesh memory)
-       */
-      if ((tc->msg_seq == msg_seq) || (tc->ignored++ < 32)) {
-        return false;
-      }
-
-      OLSR_DEBUG(LOG_TC, "Ignored to much LQTC's for %s, restarting\n", olsr_ip_to_string(&buf, &originator));
-
-    } else if (!olsr_seq_inrange_high(tc->msg_seq, (int)tc->msg_seq + TC_SEQNO_WINDOW * TC_SEQNO_WINDOW_MULT, msg_seq)
-               || !olsr_seq_inrange_low(tc->ansn, (int)tc->ansn + TC_ANSN_WINDOW * TC_ANSN_WINDOW_MULT, ansn)) {
-
-      /*
-       * Only accept future seq/ansn values (large window for node reconnects).
-       * Restart in all other cases. Ignore a single stray message.
-       */
-      if (!tc->err_seq_valid) {
-        tc->err_seq = msg_seq;
-        tc->err_seq_valid = true;
-      }
-      if (tc->err_seq == msg_seq) {
-        return false;
-      }
-
-      OLSR_DEBUG(LOG_TC, "Detected node restart for %s\n", olsr_ip_to_string(&buf, &originator));
-    }
+  /* TCs can be splitted, so we are looking for ANSNs equal or higher */
+  if (tc && status != RESET_SEQNO_OLSR_MESSAGE && olsr_seqno_diff(ansn, tc->ansn) < 0) {
+    /* this TC is too old, discard it */
+    return;
   }
 
   /*
@@ -931,13 +845,13 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
    * Update the tc entry.
    */
   tc->msg_hops = msg_hops;
-  tc->msg_seq = msg_seq;
+  tc->tc_seq = msg_seq;
   tc->ansn = ansn;
   tc->ignored = 0;
   tc->err_seq_valid = false;
   tc->is_virtual = false;
 
-  OLSR_DEBUG(LOG_TC, "Processing TC from %s, seq 0x%04x\n", olsr_ip_to_string(&buf, &originator), tc->msg_seq);
+  OLSR_DEBUG(LOG_TC, "Processing TC from %s, seq 0x%04x\n", olsr_ip_to_string(&buf, &originator), tc->tc_seq);
 
   /*
    * Now walk the edge advertisements contained in the packet.
@@ -990,9 +904,6 @@ olsr_input_tc(union olsr_message * msg, struct interface * input_if __attribute_
     olsr_set_timer(&tc->edge_gc_timer, OLSR_TC_EDGE_GC_TIME,
                    OLSR_TC_EDGE_GC_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_tc_edge_gc, tc, tc_edge_gc_timer_cookie);
   }
-
-  /* Forward the message */
-  return true;
 }
 
 uint32_t
@@ -1007,6 +918,11 @@ olsr_delete_all_tc_entries(void) {
   struct tc_edge_entry *edge;
 
   /* first mark all nodes non-virtual and all edges virtual */
+  tc_myself->is_virtual = false;
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc_myself, edge) {
+    edge->is_virtual = 1;
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc_myself, edge)
+
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
     tc->is_virtual = false;
     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, edge) {
@@ -1015,6 +931,9 @@ olsr_delete_all_tc_entries(void) {
   }OLSR_FOR_ALL_TC_ENTRIES_END(tc)
 
   /* erase all edges */
+  OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc_myself, edge) {
+    olsr_delete_tc_edge_entry(edge);
+  } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc_myself, edge)
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, edge) {
       olsr_delete_tc_edge_entry(edge);
@@ -1022,6 +941,9 @@ olsr_delete_all_tc_entries(void) {
   }OLSR_FOR_ALL_TC_ENTRIES_END(tc)
 
   /* then remove all tc entries */
+  tc_myself->is_virtual = true;
+  olsr_delete_tc_entry(tc_myself);
+  tc_myself = NULL;
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
     tc->is_virtual = true;
     olsr_delete_tc_entry(tc);
index a1ca5cd..d0f1756 100644 (file)
@@ -48,6 +48,7 @@
 #include "lq_packet.h"
 #include "scheduler.h"
 #include "olsr_cookie.h"
+#include "duplicate_set.h"
 
 /*
  * This file holds the definitions for the link state database.
@@ -86,7 +87,9 @@ struct tc_entry {
   struct timer_entry *validity_timer;  /* tc validity time */
   uint32_t refcount;                   /* reference counter */
   bool is_virtual;                     /* true if tc is already timed out */
-  uint16_t msg_seq;                    /* sequence number of the tc message */
+  uint16_t tc_seq;                     /* sequence number of the tc message */
+  uint16_t mid_seq;                    /* sequence number of the mid message */
+  uint16_t hna_seq;                    /* sequence number of the hna message */
   uint8_t msg_hops;                    /* hopcount as per the tc message */
   uint8_t hops;                        /* SPF calculated hopcount */
   uint16_t ansn;                       /* ANSN number of the tc message */
@@ -156,7 +159,7 @@ void olsr_print_tc_table(void);
 void olsr_time_out_tc_set(void);
 
 /* tc msg input parser */
-bool olsr_input_tc(union olsr_message *, struct interface *, union olsr_ip_addr *from);
+void olsr_input_tc(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
 
 /* tc_entry manipulation */
 struct tc_entry *EXPORT(olsr_lookup_tc_entry) (const union olsr_ip_addr *);
index 7fae56c..18b6cdb 100644 (file)
@@ -59,6 +59,7 @@
 #include "log.h"
 #include "link_set.h"
 #include "../common/string.h"
+#include "../valgrind/valgrind.h"
 
 #include <signal.h>
 #include <sys/types.h>
@@ -348,7 +349,7 @@ chk_if_up(struct olsr_if_config *iface)
   }
   ifp = olsr_cookie_malloc(interface_mem_cookie);
 
-  /*
+   /*
    * Setup query block.
    */
   memset(&ifr, 0, sizeof(ifr));