Duplicate IP usage detection for OLSRd
authorHenning Rogge <hrogge@googlemail.com>
Wed, 13 Jan 2010 13:40:13 +0000 (14:40 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Wed, 13 Jan 2010 13:40:13 +0000 (14:40 +0100)
src/duplicate_handler.c [new file with mode: 0644]
src/duplicate_handler.h [new file with mode: 0644]
src/hna_set.c
src/mid_set.c
src/olsr.c
src/olsr.h
src/parser.c

diff --git a/src/duplicate_handler.c b/src/duplicate_handler.c
new file mode 100644 (file)
index 0000000..db12a85
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * duplicate_handler.c
+ *
+ *  Created on: 11.01.2010
+ *      Author: henning
+ */
+
+#include "common/list.h"
+#include "defs.h"
+#include "ipcalc.h"
+#include "log.h"
+#include "olsr.h"
+#include "scheduler.h"
+#include "duplicate_handler.h"
+
+#ifndef NO_DUPLICATE_DETECTION_HANDLER
+
+static struct list_node duplicate_handler_head;
+static uint32_t spam_orig_counter, spam_hna_counter, spam_mid_counter;
+
+static struct timer_entry *duplicate_spam_timer;
+
+static void handle_duplicate_spam_timer(void __attribute__ ((unused)) *no) {
+  if (spam_orig_counter > MAX_SYSLOG_EACH_HOUR) {
+    olsr_syslog(OLSR_LOG_INFO, "Skipped %u originator duplicate warnings.", spam_orig_counter - MAX_SYSLOG_EACH_HOUR);
+  }
+  if (spam_hna_counter > MAX_SYSLOG_EACH_HOUR) {
+    olsr_syslog(OLSR_LOG_INFO, "Skipped %u hna duplicate warnings.", spam_hna_counter - MAX_SYSLOG_EACH_HOUR);
+  }
+  if (spam_mid_counter > MAX_SYSLOG_EACH_HOUR) {
+    olsr_syslog(OLSR_LOG_INFO, "Skipped %u mid duplicate warnings.", spam_mid_counter - MAX_SYSLOG_EACH_HOUR);
+  }
+  spam_orig_counter = 0;
+  spam_hna_counter = 0;
+  spam_mid_counter = 0;
+}
+
+
+void olsr_duplicate_handler_init(void) {
+  list_head_init(&duplicate_handler_head);
+
+  spam_orig_counter = 0;
+  spam_hna_counter = 0;
+  spam_mid_counter = 0;
+
+  olsr_set_timer(&duplicate_spam_timer, 3600*1000, 0, OLSR_TIMER_PERIODIC,
+                 &handle_duplicate_spam_timer, NULL, 0);
+}
+
+void olsr_add_duplicate_handler(struct duplicate_handler *h) {
+  list_add_before(&duplicate_handler_head, &h->node);
+}
+
+void olsr_remove_duplicate_handler(struct duplicate_handler *h) {
+  list_remove(&h->node);
+}
+
+void olsr_test_originator_collision(uint8_t msgType, uint16_t seqno) {
+  struct list_node *n;
+
+  if (!olsr_is_bad_duplicate_msg_seqno(seqno)) {
+    return;
+  }
+
+  if (++spam_orig_counter < MAX_SYSLOG_EACH_HOUR) {
+    struct ipaddr_str buf;
+
+    olsr_syslog(OLSR_LOG_INFO, "You might have another node with main ip %s in the mesh!",
+        olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+  }
+
+  for (n=duplicate_handler_head.next; n != &duplicate_handler_head; n = n->next) {
+    struct duplicate_handler *h = (struct duplicate_handler *)n;
+
+    h->originator_collision(msgType);
+  }
+}
+
+void olsr_handle_hna_collision(union olsr_ip_addr *hna, union olsr_ip_addr *orig) {
+  struct list_node *n;
+
+  if (++spam_hna_counter < MAX_SYSLOG_EACH_HOUR) {
+    struct ipaddr_str buf1, buf2;
+
+    olsr_syslog(OLSR_LOG_INFO, "Node %s is publishing your ip %s as HNA!",
+        olsr_ip_to_string(&buf1, orig), olsr_ip_to_string(&buf2, hna));
+  }
+
+  for (n=duplicate_handler_head.next; n != &duplicate_handler_head; n = n->next) {
+    struct duplicate_handler *h = (struct duplicate_handler *)n;
+
+    h->hna_collision(hna, orig);
+  }
+}
+
+void olsr_handle_mid_collision(union olsr_ip_addr *mid, union olsr_ip_addr *orig) {
+  struct list_node *n;
+
+  if (++spam_mid_counter < MAX_SYSLOG_EACH_HOUR) {
+    struct ipaddr_str buf1, buf2;
+
+    olsr_syslog(OLSR_LOG_INFO, "Node %s is publishing your ip %s as MID!",
+        olsr_ip_to_string(&buf1, orig), olsr_ip_to_string(&buf2, mid));
+  }
+
+  for (n=duplicate_handler_head.next; n != &duplicate_handler_head; n = n->next) {
+    struct duplicate_handler *h = (struct duplicate_handler *)n;
+
+    h->mid_collision(mid, orig);
+  }
+}
+
+#endif
diff --git a/src/duplicate_handler.h b/src/duplicate_handler.h
new file mode 100644 (file)
index 0000000..1b071ab
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * duplicate_handler.h
+ *
+ *  Created on: 11.01.2010
+ *      Author: henning
+ */
+
+#ifndef DUPLICATE_HANDLER_H_
+#define DUPLICATE_HANDLER_H_
+
+#include "defs.h"
+#include "olsr.h"
+#include "common/list.h"
+
+#ifndef NO_DUPLICATE_DETECTION_HANDLER
+#define MAX_SYSLOG_EACH_HOUR 10
+
+struct duplicate_handler {
+  struct list_node node;
+
+  void (*originator_collision)(uint8_t msgType);
+  void (*hna_collision)(union olsr_ip_addr *hna, union olsr_ip_addr *orig);
+  void (*mid_collision)(union olsr_ip_addr *mid, union olsr_ip_addr *orig);
+};
+
+void olsr_duplicate_handler_init(void);
+
+void olsr_add_duplicate_handler(struct duplicate_handler *);
+void olsr_remove_duplicate_handler(struct duplicate_handler *);
+
+void olsr_test_originator_collision(uint8_t msgType, uint16_t seqno);
+void olsr_handle_hna_collision(union olsr_ip_addr *hna, union olsr_ip_addr *orig);
+void olsr_handle_mid_collision(union olsr_ip_addr *mid, union olsr_ip_addr *orig);
+#endif
+#endif /* DUPLICATE_HANDLER_H_ */
index 0569ca8..21f3645 100644 (file)
@@ -46,6 +46,7 @@
 #include "net_olsr.h"
 #include "tc_set.h"
 #include "parser.h"
+#include "duplicate_handler.h"
 
 struct hna_entry hna_set[HASHSIZE];
 struct olsr_cookie_info *hna_net_timer_cookie = NULL;
@@ -428,28 +429,35 @@ olsr_input_hna(union olsr_message *m, struct interface *in_if __attribute__ ((un
     OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
     return false;
   }
-#if 1
   while (curr < curr_end) {
     union olsr_ip_addr net;
     uint8_t prefixlen;
     struct ip_prefix_list *entry;
+    struct interface *ifs;
+    bool stop = false;
 
     pkt_get_ipaddress(&curr, &net);
     pkt_get_prefixlen(&curr, &prefixlen);
+
+#ifndef NO_DUPLICATE_DETECTION_HANDLER
+    for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
+      if (ipequal(&ifs->ip_addr, &net)) {
+      /* ignore your own main IP as an incoming MID */
+        olsr_handle_hna_collision(&net, &originator);
+        stop = true;
+        break;
+      }
+    }
+    if (stop) {
+      continue;
+    }
+#endif
     entry = ip_prefix_list_find(olsr_cnf->hna_entries, &net, prefixlen);
     if (entry == NULL) {
       /* only update if it's not from us */
       olsr_update_hna_entry(&originator, &net, prefixlen, vtime);
     }
   }
-#else
-  while (hna_tmp) {
-    /* Don't add an HNA entry that we are advertising ourselves. */
-    if (!ip_prefix_list_find(olsr_cnf->hna_entries, &hna_tmp->net, hna_tmp->prefixlen)) {
-      olsr_update_hna_entry(&message.originator, &hna_tmp->net, hna_tmp->prefixlen, message.vtime);
-    }
-  }
-#endif
   /* Forward the message */
   return true;
 }
index fc86122..dab392c 100644 (file)
@@ -52,6 +52,7 @@
 #include "tc_set.h"
 #include "packet.h"             /* struct mid_alias */
 #include "net_olsr.h"
+#include "duplicate_handler.h"
 
 struct mid_entry mid_set[HASHSIZE];
 struct mid_address reverse_mid_set[HASHSIZE];
@@ -591,7 +592,22 @@ olsr_input_mid(union olsr_message *m, struct interface *in_if __attribute__ ((un
   /* Update the timeout of the MID */
   olsr_update_mid_table(&message.mid_origaddr, message.vtime);
 
-  while (tmp_adr) {
+  for (;tmp_adr; tmp_adr = tmp_adr->next) {
+#ifndef NO_DUPLICATE_DETECTION_HANDLER
+    struct interface *ifs;
+    bool stop = false;
+    for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
+      if (ipequal(&ifs->ip_addr, &tmp_adr->alias_addr)) {
+      /* ignore your own main IP as an incoming MID */
+        olsr_handle_mid_collision(&tmp_adr->alias_addr, &message.mid_origaddr);
+        stop = true;
+        break;
+      }
+    }
+    if (stop) {
+      continue;
+    }
+#endif
     if (!mid_lookup_main_addr(&tmp_adr->alias_addr)) {
       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));
@@ -599,7 +615,6 @@ olsr_input_mid(union olsr_message *m, struct interface *in_if __attribute__ ((un
     } else {
       olsr_insert_routing_table(&tmp_adr->alias_addr, olsr_cnf->maxplen, &message.mid_origaddr, OLSR_RT_ORIGIN_MID);
     }
-    tmp_adr = tmp_adr->next;
   }
 
   olsr_prune_aliases(&message);
index 43fcd07..d70f8d7 100644 (file)
@@ -63,6 +63,7 @@
 #include "common/avl.h"
 #include "net_olsr.h"
 #include "lq_plugin.h"
+#include "duplicate_handler.h"
 
 #include <stdarg.h>
 #include <signal.h>
@@ -138,6 +139,19 @@ get_msg_seqno(void)
   return message_seqno++;
 }
 
+bool
+olsr_is_bad_duplicate_msg_seqno(uint16_t seqno) {
+  int32_t diff = (int32_t) seqno - (int32_t) message_seqno;
+
+  if (diff < -32768) {
+    diff += 65536;
+  }
+  else if (diff > 32767) {
+    diff -= 65536;
+  }
+  return diff > 0;
+}
+
 void
 register_pcf(int (*f) (int, int, int))
 {
@@ -293,9 +307,9 @@ olsr_init_tables(void)
   /* Initialize HNA set */
   olsr_init_hna_set();
 
-#if 0
-  /* Initialize Layer 1/2 database */
-  olsr_initialize_layer12();
+  /* Initialize duplicate handler */
+#ifndef NO_DUPLICATE_DETECTION_HANDLER
+  olsr_duplicate_handler_init();
 #endif
 
   /* Start periodic SPF and RIB recalculation */
index 02c8c6a..b03f703 100644 (file)
@@ -63,6 +63,8 @@ void init_msg_seqno(void);
 
 uint16_t get_msg_seqno(void);
 
+bool olsr_is_bad_duplicate_msg_seqno(uint16_t seqno);
+
 int olsr_forward_message(union olsr_message *, struct interface *, union olsr_ip_addr *);
 
 void set_buffer_timer(struct interface *);
index c7d6114..f7e61be 100644 (file)
@@ -53,6 +53,7 @@
 #include "log.h"
 #include "print_packet.h"
 #include "net_olsr.h"
+#include "duplicate_handler.h"
 
 #ifdef WIN32
 #undef EWOULDBLOCK
@@ -274,6 +275,7 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
   union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
   int count;
   int msgsize;
+  uint16_t seqno;
   struct parse_function_entry *entry;
   struct packetparser_function_entry *packetparser;
 
@@ -305,11 +307,6 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
   if (disp_pack_in)
     print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
 
-  if (olsr_cnf->ip_version == AF_INET)
-    msgsize = ntohs(m->v4.olsr_msgsize);
-  else
-    msgsize = ntohs(m->v6.olsr_msgsize);
-
   /*
    * Hysteresis update - for every OLSR package
    */
@@ -325,14 +322,19 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
 
   for (; count > 0; m = (union olsr_message *)((char *)m + (msgsize))) {
     bool forward = true;
+    bool validated;
 
     if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version) + 8)
       break;
 
-    if (olsr_cnf->ip_version == AF_INET)
+    if (olsr_cnf->ip_version == AF_INET) {
       msgsize = ntohs(m->v4.olsr_msgsize);
-    else
+      seqno = ntohs(m->v4.seqno);
+    }
+    else {
       msgsize = ntohs(m->v6.olsr_msgsize);
+      seqno = ntohs(m->v6.seqno);
+    }
 
     if ((msgsize % 4) != 0) {
       struct ipaddr_str buf;
@@ -378,15 +380,18 @@ parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip
      */
 
     /* Should be the same for IPv4 and IPv6 */
-    if (ipequal((union olsr_ip_addr *)&m->v4.originator, &olsr_cnf->main_addr)
-        || !olsr_validate_address((union olsr_ip_addr *)&m->v4.originator)) {
+    validated = olsr_validate_address((union olsr_ip_addr *)&m->v4.originator);
+    if (ipequal((union olsr_ip_addr *)&m->v4.originator, &olsr_cnf->main_addr) || !validated) {
 #ifdef DEBUG
       struct ipaddr_str buf;
-#endif
-#ifdef DEBUG
       OLSR_PRINTF(3, "Not processing message originating from %s!\n",
                   olsr_ip_to_string(&buf, (union olsr_ip_addr *)&m->v4.originator));
 #endif
+#ifndef NO_DUPLICATE_DETECTION_HANDLER
+      if (validated) {
+        olsr_test_originator_collision(m->v4.olsr_msgtype, seqno);
+      }
+#endif
       continue;
     }