From Henning Rogge <rogge@fgan.de>: join LQ and non-LQ Hello execution paths
[olsrd.git] / src / process_package.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include "process_package.h"
42 #include "ipcalc.h"
43 #include "defs.h"
44 #include "lq_packet.h"
45 #include "hysteresis.h"
46 #include "two_hop_neighbor_table.h"
47 #include "tc_set.h"
48 #include "mpr_selector_set.h"
49 #include "mid_set.h"
50 #include "olsr.h"
51 #include "parser.h"
52 #include "duplicate_set.h"
53 #include "rebuild_packet.h"
54 #include "scheduler.h"
55 #include "net_olsr.h"
56
57 #include <stddef.h>
58
59 static void process_message_neighbors(struct neighbor_entry *, const struct hello_message *);
60
61 static void linking_this_2_entries(struct neighbor_entry *, struct neighbor_2_entry *, float);
62
63 static int lookup_mpr_status(const struct hello_message *, const struct interface *);
64
65
66 /**
67  *Processes an list of neighbors from an incoming HELLO message.
68  *@param neighbor the neighbor who sent the message.
69  *@param message the HELLO message
70  *@return nada
71  */
72 static void
73 process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message)
74 {
75   struct hello_neighbor        *message_neighbors;
76
77   for(message_neighbors = message->neighbors;
78       message_neighbors != NULL;
79       message_neighbors = message_neighbors->next)
80     {
81 #if !defined(NODEBUG) && defined(DEBUG)
82       struct ipaddr_str buf;
83 #endif
84       union olsr_ip_addr      *neigh_addr;
85       struct neighbor_2_entry *two_hop_neighbor;
86
87       /*
88        *check all interfaces
89        *so that we don't add ourselves to the
90        *2 hop list
91        *IMPORTANT!
92        */
93       if(if_ifwithaddr(&message_neighbors->address) != NULL)
94         continue;
95
96       /* Get the main address */
97       neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
98
99       if (neigh_addr != NULL) {
100         message_neighbors->address = *neigh_addr;
101       }
102
103       if(((message_neighbors->status == SYM_NEIGH) ||
104           (message_neighbors->status == MPR_NEIGH)))
105         {
106           struct neighbor_2_list_entry *two_hop_neighbor_yet =
107             olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
108 #ifdef DEBUG
109           OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&buf, &message_neighbors->address));
110 #endif
111           if (two_hop_neighbor_yet != NULL)
112             {
113               /* Updating the holding time for this neighbor */
114               two_hop_neighbor_yet->neighbor_2_timer = GET_TIMESTAMP(message->vtime*1000);
115               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
116
117               // For link quality OLSR, reset the path link quality here.
118               // The path link quality will be calculated in the second pass, below.
119               // Keep the saved_path_link_quality for reference.
120
121               if (olsr_cnf->lq_level > 0)
122                 {
123                   // loop through the one-hop neighbors that see this
124                   // 'two_hop_neighbor'
125
126                   struct neighbor_list_entry *walker;
127
128                   for (walker = two_hop_neighbor->neighbor_2_nblist.next;
129                        walker != &two_hop_neighbor->neighbor_2_nblist;
130                        walker = walker->next)
131                     {
132                       // have we found the one-hop neighbor that sent the
133                       // HELLO message that we're current processing?
134
135                       if (walker->neighbor == neighbor)
136                         {
137                           walker->path_link_quality = 0.0;
138                         }
139                     }
140                 }
141             }
142           else
143             {
144               two_hop_neighbor =
145                 olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
146               if (two_hop_neighbor == NULL)
147                 {
148 #ifdef DEBUG
149                   OLSR_PRINTF(5, 
150                               "Adding 2 hop neighbor %s\n\n", 
151                               olsr_ip_to_string(&buf, &message_neighbors->address));
152 #endif
153                   changes_neighborhood = OLSR_TRUE;
154                   changes_topology = OLSR_TRUE;
155
156                   two_hop_neighbor =
157                     olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO");
158                   
159                   two_hop_neighbor->neighbor_2_nblist.next =
160                     &two_hop_neighbor->neighbor_2_nblist;
161
162                   two_hop_neighbor->neighbor_2_nblist.prev =
163                     &two_hop_neighbor->neighbor_2_nblist;
164
165                   two_hop_neighbor->neighbor_2_pointer = 0;
166                   
167                   two_hop_neighbor->neighbor_2_addr = message_neighbors->address;
168
169                   olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
170
171                   linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
172                 }
173               else
174                 {
175                   /*
176                     linking to this two_hop_neighbor entry
177                   */    
178                   changes_neighborhood = OLSR_TRUE;
179                   changes_topology = OLSR_TRUE;
180                   
181                   linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime); 
182                 }
183             }
184         }
185     }
186
187   // Separate, second and third pass for link quality OLSR
188
189   if (olsr_cnf->lq_level > 0)
190     {
191       struct link_entry *lnk =
192         get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
193
194       if(!lnk)
195         return;
196
197       // Second pass for link quality OLSR: calculate the best 2-hop
198       // path costs to all the 2-hop neighbors indicated in the
199       // HELLO message. Since the same 2-hop neighbor may be listed
200       // more than once in the same HELLO message (each at a possibly
201       // different quality) we want to select only the best one, not just
202       // the last one listed in the HELLO message.
203
204       for(message_neighbors = message->neighbors;
205           message_neighbors != NULL;
206           message_neighbors = message_neighbors->next)
207         {
208           if(if_ifwithaddr(&message_neighbors->address) != NULL)
209             continue;
210
211           if(((message_neighbors->status == SYM_NEIGH) ||
212               (message_neighbors->status == MPR_NEIGH)))
213             {
214               struct neighbor_list_entry *walker;
215               struct neighbor_2_entry *two_hop_neighbor;
216               struct neighbor_2_list_entry *two_hop_neighbor_yet =
217                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
218
219               if(!two_hop_neighbor_yet)
220                 continue;
221
222               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
223
224               // loop through the one-hop neighbors that see this
225               // 'two_hop_neighbor'
226
227               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
228                    walker != &two_hop_neighbor->neighbor_2_nblist;
229                    walker = walker->next)
230                 {
231                   // have we found the one-hop neighbor that sent the
232                   // HELLO message that we're current processing?
233
234                   if (walker->neighbor == neighbor)
235                     {
236                       double new_second_hop_link_quality, new_path_link_quality;
237
238                       // path link quality = link quality between us
239                       // and our one-hop neighbor x link quality between
240                       // our one-hop neighbor and the two-hop neighbor
241
242                       // let's compare this to ETX:
243
244                       // 1 / LQ1 + 1 / LQ2 < 1 / LQ3 + 1 / LQ4 <=>
245                       // LQ1 * LQ2 > LQ3 * LQ4
246
247                       // so comparing path link quality values with ">" is
248                       // equivalent to comparing ETX values with "<"
249
250                       // the link quality between the 1-hop neighbour and the
251                       // 2-hop neighbour
252
253                       new_second_hop_link_quality = 
254                         message_neighbors->link_quality *
255                         message_neighbors->neigh_link_quality;
256
257                       // the total quality for the route
258                       // "us --- 1-hop --- 2-hop"
259
260                       new_path_link_quality =
261                         new_second_hop_link_quality *
262                         lnk->loss_link_quality * lnk->neigh_link_quality;
263
264                       // Only copy the link quality if it is better than what we have
265                       // for this 2-hop neighbor
266                       if (new_path_link_quality > walker->path_link_quality)
267                         {
268                           walker->second_hop_link_quality = new_second_hop_link_quality;
269                           walker->path_link_quality = new_path_link_quality;
270                         }
271                     }
272                 }
273             }
274         }
275
276       // Third pass for link quality OLSR: check if the 2-hop path qualities have
277       // actually changed. If so, signal this through the 'changes_neighborhood'
278       // and 'changes_topology' booleans. Keep a 'saved_path_link_quality' for
279       // later reference.
280       for(message_neighbors = message->neighbors;
281           message_neighbors != NULL;
282           message_neighbors = message_neighbors->next)
283         {
284           if(if_ifwithaddr(&message_neighbors->address) != NULL)
285             continue;
286
287           if(((message_neighbors->status == SYM_NEIGH) ||
288               (message_neighbors->status == MPR_NEIGH)))
289             {
290               struct neighbor_list_entry *walker;
291               struct neighbor_2_entry *two_hop_neighbor;
292               struct neighbor_2_list_entry *two_hop_neighbor_yet =
293                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
294
295               if(!two_hop_neighbor_yet)
296                 continue;
297
298               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
299
300               // loop through the one-hop neighbors that see this
301               // 'two_hop_neighbor'
302
303               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
304                    walker != &two_hop_neighbor->neighbor_2_nblist;
305                    walker = walker->next)
306                 {
307                   // have we found the one-hop neighbor that sent the
308                   // HELLO message that we're current processing?
309
310                   if (walker->neighbor == neighbor)
311                     {
312                       double saved_lq, rel_lq;
313
314                       // saved previous total link quality
315
316                       saved_lq = walker->saved_path_link_quality;
317
318                       if (saved_lq == 0.0)
319                         saved_lq = -1.0;
320
321                       // if the link cost has changed by more than 10
322                       // percent, signal
323
324                       rel_lq = walker->path_link_quality / saved_lq;
325
326                       if (rel_lq > 1.1 || rel_lq < 0.9)
327                         {
328                           walker->saved_path_link_quality =
329                             walker->path_link_quality;
330
331                           if (olsr_cnf->lq_dlimit > 0)
332                           {
333                             changes_neighborhood = OLSR_TRUE;
334                             changes_topology = OLSR_TRUE;
335                           }
336
337                           else
338                             OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
339                         }
340                     }
341                 }
342             }
343         }
344     }
345 }
346
347 /**
348  *Links a one-hop neighbor with a 2-hop neighbor.
349  *
350  *@param neighbor the 1-hop neighbor
351  *@param two_hop_neighbor the 2-hop neighbor
352  *@return nada
353  */
354 static void
355 linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry *two_hop_neighbor, float vtime)
356 {
357   struct neighbor_list_entry    *list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
358   struct neighbor_2_list_entry  *list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
359
360   list_of_1_neighbors->neighbor = neighbor;
361
362   list_of_1_neighbors->path_link_quality = 0.0;
363   list_of_1_neighbors->saved_path_link_quality = 0.0;
364   list_of_1_neighbors->second_hop_link_quality = 0.0;
365
366   /* Queue */
367   two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
368   list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
369
370   two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
371   list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
372   list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
373   
374   list_of_2_neighbors->neighbor_2_timer = GET_TIMESTAMP(vtime*1000);
375
376   /* Queue */
377   neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
378   list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
379   neighbor->neighbor_2_list.next = list_of_2_neighbors;
380   list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
381   
382   /*increment the pointer counter*/
383   two_hop_neighbor->neighbor_2_pointer++;
384 }
385
386 /**
387  *Check if a hello message states this node as a MPR.
388  *
389  *@param message the message to check
390  *@param n_link the buffer to put the link status in
391  *@param n_status the buffer to put the status in
392  *
393  *@return 1 if we are selected as MPR 0 if not
394  */
395 static int
396 lookup_mpr_status(const struct hello_message *message, const struct interface *in_if)
397 {  
398   struct hello_neighbor  *neighbors; 
399   for (neighbors = message->neighbors; neighbors != NULL; neighbors = neighbors->next) {
400     //printf("(linkstatus)Checking %s ",olsr_ip_to_string(&buf, &neighbors->address));
401     //printf("against %s\n",olsr_ip_to_string(&buf, &main_addr));
402
403     if (olsr_cnf->ip_version == AF_INET
404               ? /* IPv4 */ ip4equal(&neighbors->address.v4, &in_if->ip_addr.v4)
405               : /* IPv6 */ ip6equal(&neighbors->address.v6, &in_if->int6_addr.sin6_addr)) {
406       //printf("ok");
407       if (neighbors->link == SYM_LINK && neighbors->status == MPR_NEIGH) {
408         return 1;
409       }
410       break;
411     }
412   }
413   /* Not found */
414   return 0;
415 }
416
417 static int deserialize_hello(struct hello_message *hello, const void *ser) {
418         const unsigned char *limit;
419         olsr_u8_t type;
420         olsr_u16_t size;
421         
422         const unsigned char *curr = ser;
423         pkt_get_u8(&curr, &type);
424         if (type != HELLO_MESSAGE && type != LQ_HELLO_MESSAGE) {
425                 /* No need to do anything more */
426                 return 1;
427         }
428         pkt_get_double(&curr, &hello->vtime);
429         pkt_get_u16(&curr, &size);
430         pkt_get_ipaddress(&curr, &hello->source_addr);
431         
432         pkt_get_u8(&curr, &hello->ttl);
433         pkt_get_u8(&curr, &hello->hop_count);
434         pkt_get_u16(&curr, &hello->packet_seq_number);
435         pkt_ignore_u16(&curr);
436         
437         pkt_get_double(&curr, &hello->htime);
438         pkt_get_u8(&curr, &hello->willingness);
439         
440         hello->neighbors = NULL;
441         limit = ((const unsigned char *)ser) + size;
442         while (curr < limit) {
443                 const struct lq_hello_info_header *info_head = (const struct lq_hello_info_header *)curr;
444                 const unsigned char *limit2 = curr + ntohs(info_head->size);
445                 
446                 curr = (const unsigned char *)(info_head + 1);
447                 while (curr < limit2) {
448                         struct hello_neighbor *neigh = olsr_malloc(sizeof(struct hello_neighbor), "HELLO deserialization");
449                         pkt_get_ipaddress(&curr, &neigh->address);
450                         
451                         if (type == LQ_HELLO_MESSAGE) {
452                                 pkt_get_lq(&curr, &neigh->link_quality);
453                                 pkt_get_lq(&curr, &neigh->neigh_link_quality);
454                                 pkt_ignore_u16(&curr);
455                         }
456                         neigh->link = EXTRACT_LINK(info_head->link_code);
457                         neigh->status = EXTRACT_STATUS(info_head->link_code);
458                         
459                         neigh->next = hello->neighbors;
460                         hello->neighbors = neigh;
461                 }
462         }
463         return 0;
464 }
465
466 void olsr_input_hello(union olsr_message *ser, struct interface *inif, union olsr_ip_addr *from) {
467         struct hello_message hello;
468         
469         if (ser == NULL) {
470                 return;
471         }
472         if (deserialize_hello(&hello, ser) != 0) {
473                 return;
474         }
475         olsr_hello_tap(&hello, inif, from);
476 }
477
478 /**
479  *Initializing the parser functions we are using
480  */
481 void
482 olsr_init_package_process(void)
483 {
484   if (olsr_cnf->lq_level == 0)
485     {
486       olsr_parser_add_function(&olsr_input_hello, HELLO_MESSAGE, 1);
487       olsr_parser_add_function(&olsr_input_tc, TC_MESSAGE, 1);
488     }
489   else
490     {
491       olsr_parser_add_function(&olsr_input_hello, LQ_HELLO_MESSAGE, 1);
492       olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
493     }
494
495   olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
496   olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
497 }
498
499 void
500 olsr_hello_tap(struct hello_message *message,
501                struct interface *in_if,
502                const union olsr_ip_addr *from_addr)
503 {
504   struct neighbor_entry     *neighbor;
505
506   /*
507    * Update link status
508    */
509   struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
510
511   if (olsr_cnf->lq_level > 0)
512     {
513       double saved_lq;
514       double rel_lq;
515       struct hello_neighbor *walker;
516       // just in case our neighbor has changed its HELLO interval
517       olsr_update_packet_loss_hello_int(lnk, message->htime);
518
519       // find the input interface in the list of neighbor interfaces
520
521       for (walker = message->neighbors; walker != NULL; walker = walker->next)
522         if (ipequal(&walker->address, &in_if->ip_addr))
523           break;
524
525       // the current reference link quality
526
527       saved_lq = lnk->saved_neigh_link_quality;
528
529       if (saved_lq == 0.0)
530         saved_lq = -1.0;
531
532       // memorize our neighbour's idea of the link quality, so that we
533       // know the link quality in both directions
534
535       if (walker != NULL)
536         lnk->neigh_link_quality = walker->link_quality;
537
538       else
539         lnk->neigh_link_quality = 0.0;
540
541       // if the link quality has changed by more than 10 percent,
542       // print the new link quality table
543
544       rel_lq = lnk->neigh_link_quality / saved_lq;
545
546       if (rel_lq > 1.1 || rel_lq < 0.9)
547         {
548           lnk->saved_neigh_link_quality = lnk->neigh_link_quality;
549
550           if (olsr_cnf->lq_dlimit > 0)
551           {
552             changes_neighborhood = OLSR_TRUE;
553             changes_topology = OLSR_TRUE;
554           }
555
556           else
557             OLSR_PRINTF(3, "Skipping Dijkstra (2)\n");
558
559           // create a new ANSN
560
561           // XXX - we should check whether we actually
562           // announce this neighbour
563
564           signal_link_changes(OLSR_TRUE);
565         }
566     }
567   
568   neighbor = lnk->neighbor;
569
570   /*
571    * Hysteresis
572    */
573   if(olsr_cnf->use_hysteresis)
574     {
575       /* Update HELLO timeout */
576       //printf("MESSAGE HTIME: %f\n", message->htime);
577       olsr_update_hysteresis_hello(lnk, message->htime);
578     }
579
580   /* Check if we are chosen as MPR */
581   if(lookup_mpr_status(message, in_if))
582     /* source_addr is always the main addr of a node! */
583     olsr_update_mprs_set(&message->source_addr, message->vtime);
584
585
586
587   /* Check willingness */
588   if(neighbor->willingness != message->willingness)
589     {
590 #ifndef NODEBUG
591       struct ipaddr_str buf;
592 #endif
593       OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
594                   olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr),
595                   neighbor->willingness,
596                   message->willingness);
597       /*
598        *If willingness changed - recalculate
599        */
600       neighbor->willingness = message->willingness;
601       changes_neighborhood = OLSR_TRUE;
602       changes_topology = OLSR_TRUE;
603     }
604
605
606   /* Don't register neighbors of neighbors that announces WILL_NEVER */
607   if(neighbor->willingness != WILL_NEVER)
608     process_message_neighbors(neighbor, message);
609
610   /* Process changes immedeatly in case of MPR updates */
611   olsr_process_changes();
612
613   olsr_free_hello_packet(message);
614
615   return;
616 }
617
618 /**
619  *Process a received(and parsed) MID message
620  *For every address check if there is a topology node
621  *registered with it and update its addresses.
622  *
623  *@param m the OLSR message received.
624  *@return 1 on success
625  */
626
627 void
628 olsr_process_received_mid(union olsr_message *m,
629                           struct interface *in_if,
630                           union olsr_ip_addr *from_addr)
631 {
632 #if !defined(NODEBUG) && defined(DEBUG)
633   struct ipaddr_str buf;
634 #endif
635   struct mid_alias *tmp_adr;
636   struct mid_message message;
637
638   mid_chgestruct(&message, m);
639
640   if (!olsr_validate_address(&message.mid_origaddr)) {
641     olsr_free_mid_packet(&message);
642     return;
643   }
644
645   if (olsr_check_dup_table_proc(&message.mid_origaddr, 
646                                 message.mid_seqno)) {
647
648 #ifdef DEBUG
649     OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&buf, &message.mid_origaddr));
650 #endif
651     tmp_adr = message.mid_addr;
652
653     /*
654      *      If the sender interface (NB: not originator) of this message
655      *      is not in the symmetric 1-hop neighborhood of this node, the
656      *      message MUST be discarded.
657      */
658
659     if(check_neighbor_link(from_addr) != SYM_LINK) {
660 #ifndef NODEBUG
661       struct ipaddr_str buf;
662 #endif
663       OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
664       olsr_free_mid_packet(&message);
665       return;
666     }
667
668     /* Update the timeout of the MID */
669     olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
670
671     while (tmp_adr) {
672       if (!mid_lookup_main_addr(&tmp_adr->alias_addr)){
673 #ifndef NODEBUG
674         struct ipaddr_str buf;
675 #endif
676         OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&buf, &message.mid_origaddr));
677         OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&buf, &tmp_adr->alias_addr));
678         insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
679       }
680       tmp_adr = tmp_adr->next;
681     } 
682   
683     olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
684   }
685
686   olsr_forward_message(m, 
687                        &message.mid_origaddr, 
688                        message.mid_seqno, 
689                        in_if,
690                        from_addr);
691   olsr_free_mid_packet(&message);
692 }
693
694
695 /**
696  *Process incoming HNA message.
697  *Forwards the message if that is to be done.
698  *
699  *@param m the incoming OLSR message
700  *the OLSR message.
701  *@return 1 on success
702  */
703
704 void
705 olsr_process_received_hna(union olsr_message *m,
706                           struct interface *in_if,
707                           union olsr_ip_addr *from_addr)
708 {
709
710   olsr_u8_t          olsr_msgtype;
711   double             vtime;
712   olsr_u16_t         olsr_msgsize;
713   union olsr_ip_addr originator;
714   //olsr_u8_t          ttl; unused
715   olsr_u8_t          hop_count;
716   olsr_u16_t         packet_seq_number;
717
718   int                hnasize;
719   const olsr_u8_t    *curr, *curr_end;
720
721 #ifdef DEBUG
722   OLSR_PRINTF(5, "Processing HNA\n");
723 #endif
724
725   /* Check if everyting is ok */
726   if (!m) {
727     return;
728   }
729   curr = (const olsr_u8_t *)m;
730
731   /* olsr_msgtype */
732   pkt_get_u8(&curr, &olsr_msgtype);
733   if (olsr_msgtype != HNA_MESSAGE) {
734     OLSR_PRINTF(0, "not a HNA message!\n");
735     return;
736   }
737   /* Get vtime */
738   pkt_get_double(&curr, &vtime);
739
740   /* olsr_msgsize */
741   pkt_get_u16(&curr, &olsr_msgsize);
742   hnasize = olsr_msgsize - (olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message));
743   if (hnasize < 0) {
744     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)));
745     return;
746   }
747   if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
748     OLSR_PRINTF(0, "Illegal message size %d!\n", olsr_msgsize);
749     return;
750   }
751   curr_end = (const olsr_u8_t *)m + olsr_msgsize;
752
753   /* validate originator */
754   pkt_get_ipaddress(&curr, &originator);
755   //printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator));
756
757   /* ttl */
758   pkt_ignore_u8(&curr);
759
760   /* hopcnt */
761   pkt_get_u8(&curr, &hop_count);
762
763   /* seqno */
764   pkt_get_u16(&curr, &packet_seq_number);
765
766   if (olsr_check_dup_table_proc(&originator, packet_seq_number)) {
767     /*
768      *      If the sender interface (NB: not originator) of this message
769      *      is not in the symmetric 1-hop neighborhood of this node, the
770      *      message MUST be discarded.
771      */
772     if (check_neighbor_link(from_addr) != SYM_LINK) {
773 #ifndef NODEBUG
774       struct ipaddr_str buf;
775 #endif
776       OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
777       return;
778     }
779 #if 1
780     while (curr < curr_end) {
781       union olsr_ip_addr net;
782       olsr_u8_t prefixlen;
783       struct ip_prefix_list *entry;
784
785       pkt_get_ipaddress(&curr, &net);
786       pkt_get_prefixlen(&curr, &prefixlen);
787       entry = ip_prefix_list_find(olsr_cnf->hna_entries, &net, prefixlen);
788       if (entry == NULL) {
789         /* only update if it's not from us */
790         olsr_update_hna_entry(&originator, &net, prefixlen, vtime);
791 #else
792     while (hna_tmp) {
793       /* Don't add an HNA entry that we are advertising ourselves. */
794       if (!ip_prefix_list_find(olsr_cnf->hna_entries, &hna_tmp->net, hna_tmp->prefixlen)) {
795         olsr_update_hna_entry(&message.originator, &hna_tmp->net, hna_tmp->prefixlen, message.vtime);
796 #endif
797       }
798     }
799   }
800   olsr_forward_message(m, 
801                        &originator, 
802                        packet_seq_number, 
803                        in_if,
804                        from_addr);
805 }