hello reception: use link status ordering
authorFerry Huberts <ferry.huberts@pelagic.nl>
Mon, 30 Jan 2017 16:53:19 +0000 (17:53 +0100)
committerFerry Huberts <ferry.huberts@pelagic.nl>
Tue, 7 Feb 2017 12:37:43 +0000 (13:37 +0100)
See the explanation in the description of commit 2f38613.
This commit fixes the receive side of the described problem.

From this commit on 'broken' senders and 'fixed' receivers can
interoperate correctly.

The only case left unfixed is 'broken' senders and 'broken' receivers
(which is obviously unfixable), all other combinations are fixed.

'broken' = v0.6.6.1-136-g3d2fd73 <= olsrd < v0.9.5-82-g2f38613
'fixed'  = olsrd <  v0.6.6.1-136-g3d2fd73
           OR
           olsrd >= v0.9.5-82-g2f38613 (senders  )
           olsrd >= this commit        (receivers)

Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl>
src/process_package.c

index 94485f6..bd6932b 100644 (file)
@@ -317,10 +317,13 @@ lookup_mpr_status(const struct hello_message *message, const struct interface_ol
 static int
 deserialize_hello(struct hello_message *hello, const void *ser)
 {
+  static const int LINK_ORDER[] = HELLO_LINK_ORDER_ARRAY;
   const unsigned char *curr, *limit;
   uint8_t type;
   uint16_t size;
   struct ipaddr_str buf;
+  const unsigned char *curr_saved;
+  unsigned int idx;
 
   memset (hello, 0, sizeof(*hello));
 
@@ -345,29 +348,43 @@ deserialize_hello(struct hello_message *hello, const void *ser)
   hello->neighbors = NULL;
 
   limit = ((const unsigned char *)ser) + size;
-  while (curr < limit) {
-    const unsigned char *limit2 = curr;
-    uint8_t link_code;
-    uint16_t size2;
-
-    pkt_get_u8(&curr, &link_code);
-    pkt_ignore_u8(&curr);
-    pkt_get_u16(&curr, &size2);
-
-    limit2 += size2;
-    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);
+
+  curr_saved = curr;
+
+  for (idx = 0; idx < (sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0])); idx++) {
+    curr = curr_saved;
+
+    while (curr < limit) {
+      const unsigned char *limit2 = curr;
+      uint8_t link_code;
+      uint16_t size2;
+
+      pkt_get_u8(&curr, &link_code);
+      pkt_ignore_u8(&curr);
+      pkt_get_u16(&curr, &size2);
+
+      limit2 += size2;
+
+      if (EXTRACT_LINK(link_code) != LINK_ORDER[idx]) {
+        curr = limit2;
+        continue;
       }
-      neigh->link = EXTRACT_LINK(link_code);
-      neigh->status = EXTRACT_STATUS(link_code);
 
-      neigh->next = hello->neighbors;
-      hello->neighbors = neigh;
+      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(link_code);
+        neigh->status = EXTRACT_STATUS(link_code);
+
+        neigh->next = hello->neighbors;
+        hello->neighbors = neigh;
+      }
     }
   }
+
   return 0;
 }