merge sven-ola's tree
[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
418 /**
419  *Initializing the parser functions we are using
420  */
421 void
422 olsr_init_package_process(void)
423 {
424   if (olsr_cnf->lq_level == 0)
425     {
426       olsr_parser_add_function(&olsr_process_received_hello, HELLO_MESSAGE, 1);
427       olsr_parser_add_function(&olsr_input_tc, TC_MESSAGE, 1);
428     }
429   else
430     {
431       olsr_parser_add_function(&olsr_input_lq_hello, LQ_HELLO_MESSAGE, 1);
432       olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
433     }
434
435   olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
436   olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
437 }
438
439 void
440 olsr_hello_tap(struct hello_message *message,
441                struct interface *in_if,
442                const union olsr_ip_addr *from_addr)
443 {
444   struct neighbor_entry     *neighbor;
445
446   /*
447    * Update link status
448    */
449   struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
450
451   if (olsr_cnf->lq_level > 0)
452     {
453       double saved_lq;
454       double rel_lq;
455       struct hello_neighbor *walker;
456       // just in case our neighbor has changed its HELLO interval
457       olsr_update_packet_loss_hello_int(lnk, message->htime);
458
459       // find the input interface in the list of neighbor interfaces
460
461       for (walker = message->neighbors; walker != NULL; walker = walker->next)
462         if (ipequal(&walker->address, &in_if->ip_addr))
463           break;
464
465       // the current reference link quality
466
467       saved_lq = lnk->saved_neigh_link_quality;
468
469       if (saved_lq == 0.0)
470         saved_lq = -1.0;
471
472       // memorize our neighbour's idea of the link quality, so that we
473       // know the link quality in both directions
474
475       if (walker != NULL)
476         lnk->neigh_link_quality = walker->link_quality;
477
478       else
479         lnk->neigh_link_quality = 0.0;
480
481       // if the link quality has changed by more than 10 percent,
482       // print the new link quality table
483
484       rel_lq = lnk->neigh_link_quality / saved_lq;
485
486       if (rel_lq > 1.1 || rel_lq < 0.9)
487         {
488           lnk->saved_neigh_link_quality = lnk->neigh_link_quality;
489
490           if (olsr_cnf->lq_dlimit > 0)
491           {
492             changes_neighborhood = OLSR_TRUE;
493             changes_topology = OLSR_TRUE;
494           }
495
496           else
497             OLSR_PRINTF(3, "Skipping Dijkstra (2)\n");
498
499           // create a new ANSN
500
501           // XXX - we should check whether we actually
502           // announce this neighbour
503
504           signal_link_changes(OLSR_TRUE);
505         }
506     }
507   
508   neighbor = lnk->neighbor;
509
510   /*
511    * Hysteresis
512    */
513   if(olsr_cnf->use_hysteresis)
514     {
515       /* Update HELLO timeout */
516       //printf("MESSAGE HTIME: %f\n", message->htime);
517       olsr_update_hysteresis_hello(lnk, message->htime);
518     }
519
520   /* Check if we are chosen as MPR */
521   if(lookup_mpr_status(message, in_if))
522     /* source_addr is always the main addr of a node! */
523     olsr_update_mprs_set(&message->source_addr, message->vtime);
524
525
526
527   /* Check willingness */
528   if(neighbor->willingness != message->willingness)
529     {
530 #ifndef NODEBUG
531       struct ipaddr_str buf;
532 #endif
533       OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
534                   olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr),
535                   neighbor->willingness,
536                   message->willingness);
537       /*
538        *If willingness changed - recalculate
539        */
540       neighbor->willingness = message->willingness;
541       changes_neighborhood = OLSR_TRUE;
542       changes_topology = OLSR_TRUE;
543     }
544
545
546   /* Don't register neighbors of neighbors that announces WILL_NEVER */
547   if(neighbor->willingness != WILL_NEVER)
548     process_message_neighbors(neighbor, message);
549
550   /* Process changes immedeatly in case of MPR updates */
551   olsr_process_changes();
552
553   olsr_free_hello_packet(message);
554
555   return;
556 }
557
558 /**
559  *Processes a received HELLO message. 
560  *
561  *@param m the incoming OLSR message
562  *@return 0 on sucess
563  */
564
565 void
566 olsr_process_received_hello(union olsr_message *m,
567                             struct interface *in_if,
568                             union olsr_ip_addr *from_addr)
569 {
570   struct hello_message      message;
571
572   hello_chgestruct(&message, m);
573
574   olsr_hello_tap(&message, in_if, from_addr);
575 }
576
577 /**
578  *Process a received(and parsed) MID message
579  *For every address check if there is a topology node
580  *registered with it and update its addresses.
581  *
582  *@param m the OLSR message received.
583  *@return 1 on success
584  */
585
586 void
587 olsr_process_received_mid(union olsr_message *m,
588                           struct interface *in_if,
589                           union olsr_ip_addr *from_addr)
590 {
591 #if !defined(NODEBUG) && defined(DEBUG)
592   struct ipaddr_str buf;
593 #endif
594   struct mid_alias *tmp_adr;
595   struct mid_message message;
596
597   mid_chgestruct(&message, m);
598
599   if (!olsr_validate_address(&message.mid_origaddr)) {
600     olsr_free_mid_packet(&message);
601     return;
602   }
603
604   if (olsr_check_dup_table_proc(&message.mid_origaddr, 
605                                 message.mid_seqno)) {
606
607 #ifdef DEBUG
608     OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&buf, &message.mid_origaddr));
609 #endif
610     tmp_adr = message.mid_addr;
611
612     /*
613      *      If the sender interface (NB: not originator) of this message
614      *      is not in the symmetric 1-hop neighborhood of this node, the
615      *      message MUST be discarded.
616      */
617
618     if(check_neighbor_link(from_addr) != SYM_LINK) {
619 #ifndef NODEBUG
620       struct ipaddr_str buf;
621 #endif
622       OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
623       olsr_free_mid_packet(&message);
624       return;
625     }
626
627     /* Update the timeout of the MID */
628     olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
629
630     while (tmp_adr) {
631       if (!mid_lookup_main_addr(&tmp_adr->alias_addr)){
632 #ifndef NODEBUG
633         struct ipaddr_str buf;
634 #endif
635         OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&buf, &message.mid_origaddr));
636         OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&buf, &tmp_adr->alias_addr));
637         insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
638       }
639       tmp_adr = tmp_adr->next;
640     } 
641   
642     olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
643   }
644
645   olsr_forward_message(m, 
646                        &message.mid_origaddr, 
647                        message.mid_seqno, 
648                        in_if,
649                        from_addr);
650   olsr_free_mid_packet(&message);
651 }
652
653
654 /**
655  *Process incoming HNA message.
656  *Forwards the message if that is to be done.
657  *
658  *@param m the incoming OLSR message
659  *the OLSR message.
660  *@return 1 on success
661  */
662
663 void
664 olsr_process_received_hna(union olsr_message *m,
665                           struct interface *in_if,
666                           union olsr_ip_addr *from_addr)
667 {
668
669   olsr_u8_t          olsr_msgtype;
670   double             vtime;
671   olsr_u16_t         olsr_msgsize;
672   union olsr_ip_addr originator;
673   //olsr_u8_t          ttl; unused
674   olsr_u8_t          hop_count;
675   olsr_u16_t         packet_seq_number;
676
677   int                hnasize;
678   const olsr_u8_t    *curr, *curr_end;
679
680 #ifdef DEBUG
681   OLSR_PRINTF(5, "Processing HNA\n");
682 #endif
683
684   /* Check if everyting is ok */
685   if (!m) {
686     return;
687   }
688   curr = (const olsr_u8_t *)m;
689
690   /* olsr_msgtype */
691   pkt_get_u8(&curr, &olsr_msgtype);
692   if (olsr_msgtype != HNA_MESSAGE) {
693     OLSR_PRINTF(0, "not a HNA message!\n");
694     return;
695   }
696   /* Get vtime */
697   pkt_get_double(&curr, &vtime);
698
699   /* olsr_msgsize */
700   pkt_get_u16(&curr, &olsr_msgsize);
701   hnasize = olsr_msgsize - (olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message));
702   if (hnasize < 0) {
703     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)));
704     return;
705   }
706   if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
707     OLSR_PRINTF(0, "Illegal message size %d!\n", olsr_msgsize);
708     return;
709   }
710   curr_end = (const olsr_u8_t *)m + olsr_msgsize;
711
712   /* validate originator */
713   pkt_get_ipaddress(&curr, &originator);
714   //printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator));
715
716   /* ttl */
717   pkt_ignore_u8(&curr);
718
719   /* hopcnt */
720   pkt_get_u8(&curr, &hop_count);
721
722   /* seqno */
723   pkt_get_u16(&curr, &packet_seq_number);
724
725   if (olsr_check_dup_table_proc(&originator, packet_seq_number)) {
726     /*
727      *      If the sender interface (NB: not originator) of this message
728      *      is not in the symmetric 1-hop neighborhood of this node, the
729      *      message MUST be discarded.
730      */
731     if (check_neighbor_link(from_addr) != SYM_LINK) {
732 #ifndef NODEBUG
733       struct ipaddr_str buf;
734 #endif
735       OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
736       return;
737     }
738 #if 1
739     while (curr < curr_end) {
740       union olsr_ip_addr net;
741       olsr_u8_t prefixlen;
742       struct ip_prefix_list *entry;
743
744       pkt_get_ipaddress(&curr, &net);
745       pkt_get_prefixlen(&curr, &prefixlen);
746       entry = ip_prefix_list_find(olsr_cnf->hna_entries, &net, prefixlen);
747       if (entry == NULL) {
748         /* only update if it's not from us */
749         olsr_update_hna_entry(&originator, &net, prefixlen, vtime);
750 #else
751     while (hna_tmp) {
752       /* Don't add an HNA entry that we are advertising ourselves. */
753       if (!ip_prefix_list_find(olsr_cnf->hna_entries, &hna_tmp->net, hna_tmp->prefixlen)) {
754         olsr_update_hna_entry(&message.originator, &hna_tmp->net, hna_tmp->prefixlen, message.vtime);
755 #endif
756       }
757     }
758   }
759   olsr_forward_message(m, 
760                        &originator, 
761                        packet_seq_number, 
762                        in_if,
763                        from_addr);
764 }