refactor linkset code
[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 #include "lq_plugin.h"
57
58 #include <stddef.h>
59
60 static void process_message_neighbors(struct neighbor_entry *,
61                                       const struct hello_message *);
62
63 static void linking_this_2_entries(struct neighbor_entry *,
64                                    struct neighbor_2_entry *, float);
65
66 static olsr_bool lookup_mpr_status(const struct hello_message *,
67                                    const struct interface *);
68
69
70 /**
71  *Processes an list of neighbors from an incoming HELLO message.
72  *@param neighbor the neighbor who sent the message.
73  *@param message the HELLO message
74  *@return nada
75  */
76 static void
77 process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message)
78 {
79   struct hello_neighbor        *message_neighbors;
80
81   for(message_neighbors = message->neighbors;
82       message_neighbors != NULL;
83       message_neighbors = message_neighbors->next)
84     {
85 #if !defined(NODEBUG) && defined(DEBUG)
86       struct ipaddr_str buf;
87 #endif
88       union olsr_ip_addr      *neigh_addr;
89       struct neighbor_2_entry *two_hop_neighbor;
90
91       /*
92        *check all interfaces
93        *so that we don't add ourselves to the
94        *2 hop list
95        *IMPORTANT!
96        */
97       if(if_ifwithaddr(&message_neighbors->address) != NULL)
98         continue;
99
100       /* Get the main address */
101       neigh_addr = mid_lookup_main_addr(&message_neighbors->address);
102
103       if (neigh_addr != NULL) {
104         message_neighbors->address = *neigh_addr;
105       }
106
107       if(((message_neighbors->status == SYM_NEIGH) ||
108           (message_neighbors->status == MPR_NEIGH)))
109         {
110           struct neighbor_2_list_entry *two_hop_neighbor_yet =
111             olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
112 #ifdef DEBUG
113           OLSR_PRINTF(7, "\tProcessing %s\n", olsr_ip_to_string(&buf, &message_neighbors->address));
114 #endif
115           if (two_hop_neighbor_yet != NULL)
116             {
117               /* Updating the holding time for this neighbor */
118               olsr_set_timer(&two_hop_neighbor_yet->nbr2_list_timer,
119                              message->vtime * MSEC_PER_SEC, OLSR_NBR2_LIST_JITTER,
120                              OLSR_TIMER_ONESHOT, &olsr_expire_nbr2_list,
121                              two_hop_neighbor_yet, 0);
122               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
123
124               // For link quality OLSR, reset the path link quality here.
125               // The path link quality will be calculated in the second pass, below.
126               // Keep the saved_path_link_quality for reference.
127
128               if (olsr_cnf->lq_level > 0)
129                 {
130                   // loop through the one-hop neighbors that see this
131                   // 'two_hop_neighbor'
132
133                   struct neighbor_list_entry *walker;
134
135                   for (walker = two_hop_neighbor->neighbor_2_nblist.next;
136                        walker != &two_hop_neighbor->neighbor_2_nblist;
137                        walker = walker->next)
138                     {
139                       // have we found the one-hop neighbor that sent the
140                       // HELLO message that we're current processing?
141
142                       if (walker->neighbor == neighbor)
143                         {
144                           walker->path_linkcost = LINK_COST_BROKEN;
145                         }
146                     }
147                 }
148             }
149           else
150             {
151               two_hop_neighbor =
152                 olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
153               if (two_hop_neighbor == NULL)
154                 {
155 #ifdef DEBUG
156                   OLSR_PRINTF(5, 
157                               "Adding 2 hop neighbor %s\n\n", 
158                               olsr_ip_to_string(&buf, &message_neighbors->address));
159 #endif
160                   changes_neighborhood = OLSR_TRUE;
161                   changes_topology = OLSR_TRUE;
162
163                   two_hop_neighbor =
164                     olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO");
165                   
166                   two_hop_neighbor->neighbor_2_nblist.next =
167                     &two_hop_neighbor->neighbor_2_nblist;
168
169                   two_hop_neighbor->neighbor_2_nblist.prev =
170                     &two_hop_neighbor->neighbor_2_nblist;
171
172                   two_hop_neighbor->neighbor_2_pointer = 0;
173                   
174                   two_hop_neighbor->neighbor_2_addr = message_neighbors->address;
175
176                   olsr_insert_two_hop_neighbor_table(two_hop_neighbor);
177
178                   linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
179                 }
180               else
181                 {
182                   /*
183                     linking to this two_hop_neighbor entry
184                   */    
185                   changes_neighborhood = OLSR_TRUE;
186                   changes_topology = OLSR_TRUE;
187                   
188                   linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime); 
189                 }
190             }
191         }
192     }
193
194   // Separate, second pass for link quality OLSR
195
196   if (olsr_cnf->lq_level > 0)
197     {
198           olsr_linkcost first_hop_pathcost;
199       struct link_entry *lnk =
200         get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
201
202       if(!lnk)
203         return;
204
205       // calculate first hop path quality
206       first_hop_pathcost = lnk->linkcost;
207       
208       // Second pass for link quality OLSR: calculate the best 2-hop
209       // path costs to all the 2-hop neighbors indicated in the
210       // HELLO message. Since the same 2-hop neighbor may be listed
211       // more than once in the same HELLO message (each at a possibly
212       // different quality) we want to select only the best one, not just
213       // the last one listed in the HELLO message.
214
215       for(message_neighbors = message->neighbors;
216           message_neighbors != NULL;
217           message_neighbors = message_neighbors->next)
218         {
219           if(if_ifwithaddr(&message_neighbors->address) != NULL)
220             continue;
221
222           if(((message_neighbors->status == SYM_NEIGH) ||
223               (message_neighbors->status == MPR_NEIGH)))
224             {
225               struct neighbor_list_entry *walker;
226               struct neighbor_2_entry *two_hop_neighbor;
227               struct neighbor_2_list_entry *two_hop_neighbor_yet =
228                 olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);
229
230               if(!two_hop_neighbor_yet)
231                 continue;
232
233               two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;
234
235               // loop through the one-hop neighbors that see this
236               // 'two_hop_neighbor'
237
238               for (walker = two_hop_neighbor->neighbor_2_nblist.next;
239                    walker != &two_hop_neighbor->neighbor_2_nblist;
240                    walker = walker->next)
241                 {
242                   // have we found the one-hop neighbor that sent the
243                   // HELLO message that we're current processing?
244
245                   if (walker->neighbor == neighbor)
246                     {
247                       olsr_linkcost new_second_hop_linkcost, new_path_linkcost;
248
249                       // the link cost between the 1-hop neighbour and the
250                       // 2-hop neighbour
251
252                       new_second_hop_linkcost = message_neighbors->cost;
253
254                       // the total cost for the route
255                       // "us --- 1-hop --- 2-hop"
256
257                       new_path_linkcost =
258                         first_hop_pathcost + new_second_hop_linkcost;
259
260                       // Only copy the link quality if it is better than what we have
261                       // for this 2-hop neighbor
262                       if (new_path_linkcost < walker->path_linkcost)
263                         {
264                           walker->second_hop_linkcost = new_second_hop_linkcost;
265                           walker->path_linkcost = new_path_linkcost;
266                           
267                           if (olsr_is_relevant_costchange(new_path_linkcost, walker->saved_path_linkcost))
268                             {
269                               walker->saved_path_linkcost = new_path_linkcost;
270
271                               if (olsr_cnf->lq_dlimit > 0)
272                               {
273                                 changes_neighborhood = OLSR_TRUE;
274                                 changes_topology = OLSR_TRUE;
275                               }
276
277                               else
278                                 OLSR_PRINTF(3, "Skipping Dijkstra (3)\n");
279                             }
280                         }
281                     }
282                 }
283             }
284         }
285     }
286 }
287
288 /**
289  *Links a one-hop neighbor with a 2-hop neighbor.
290  *
291  *@param neighbor the 1-hop neighbor
292  *@param two_hop_neighbor the 2-hop neighbor
293  *@return nada
294  */
295 static void
296 linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry *two_hop_neighbor, float vtime)
297 {
298   struct neighbor_list_entry    *list_of_1_neighbors = olsr_malloc(sizeof(struct neighbor_list_entry), "Link entries 1");
299   struct neighbor_2_list_entry  *list_of_2_neighbors = olsr_malloc(sizeof(struct neighbor_2_list_entry), "Link entries 2");
300
301   list_of_1_neighbors->neighbor = neighbor;
302
303   list_of_1_neighbors->path_linkcost = LINK_COST_BROKEN;
304   list_of_1_neighbors->saved_path_linkcost = LINK_COST_BROKEN;
305   list_of_1_neighbors->second_hop_linkcost = LINK_COST_BROKEN;
306
307   /* Queue */
308   two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
309   list_of_1_neighbors->next = two_hop_neighbor->neighbor_2_nblist.next;
310
311   two_hop_neighbor->neighbor_2_nblist.next = list_of_1_neighbors;
312   list_of_1_neighbors->prev = &two_hop_neighbor->neighbor_2_nblist;
313   list_of_2_neighbors->neighbor_2 = two_hop_neighbor;
314   list_of_2_neighbors->nbr2_nbr = neighbor; /* XXX refcount */
315   
316   olsr_change_timer(list_of_2_neighbors->nbr2_list_timer, vtime * MSEC_PER_SEC,
317                     OLSR_NBR2_LIST_JITTER, OLSR_TIMER_ONESHOT);
318
319   /* Queue */
320   neighbor->neighbor_2_list.next->prev = list_of_2_neighbors;
321   list_of_2_neighbors->next = neighbor->neighbor_2_list.next;
322   neighbor->neighbor_2_list.next = list_of_2_neighbors;
323   list_of_2_neighbors->prev = &neighbor->neighbor_2_list;
324   
325   /*increment the pointer counter*/
326   two_hop_neighbor->neighbor_2_pointer++;
327 }
328
329 /**
330  * Check if a hello message states this node as a MPR.
331  *
332  * @param message the message to check
333  * @param n_link the buffer to put the link status in
334  *
335  *@return 1 if we are selected as MPR 0 if not
336  */
337 static olsr_bool
338 lookup_mpr_status(const struct hello_message *message,
339                   const struct interface *in_if)
340 {  
341   struct hello_neighbor  *neighbors; 
342
343   for (neighbors = message->neighbors; neighbors; neighbors = neighbors->next) {
344     if (olsr_cnf->ip_version == AF_INET
345         ? ip4equal(&neighbors->address.v4, &in_if->ip_addr.v4)
346         : ip6equal(&neighbors->address.v6, &in_if->int6_addr.sin6_addr)) {
347
348       if (neighbors->link == SYM_LINK && neighbors->status == MPR_NEIGH) {
349         return OLSR_TRUE;
350       }
351       break;
352     }
353   }
354   /* Not found */
355   return OLSR_FALSE;
356 }
357
358 static int deserialize_hello(struct hello_message *hello, const void *ser) {
359         const unsigned char *limit;
360         olsr_u8_t type;
361         olsr_u16_t size;
362         
363         const unsigned char *curr = ser;
364         pkt_get_u8(&curr, &type);
365         if (type != HELLO_MESSAGE && type != LQ_HELLO_MESSAGE) {
366                 /* No need to do anything more */
367                 return 1;
368         }
369         pkt_get_double(&curr, &hello->vtime);
370         pkt_get_u16(&curr, &size);
371         pkt_get_ipaddress(&curr, &hello->source_addr);
372         
373         pkt_get_u8(&curr, &hello->ttl);
374         pkt_get_u8(&curr, &hello->hop_count);
375         pkt_get_u16(&curr, &hello->packet_seq_number);
376         pkt_ignore_u16(&curr);
377         
378         pkt_get_double(&curr, &hello->htime);
379         pkt_get_u8(&curr, &hello->willingness);
380         
381         hello->neighbors = NULL;
382         limit = ((const unsigned char *)ser) + size;
383         while (curr < limit) {
384                 const struct lq_hello_info_header *info_head = (const struct lq_hello_info_header *)curr;
385                 const unsigned char *limit2 = curr + ntohs(info_head->size);
386                 
387                 curr = (const unsigned char *)(info_head + 1);
388                 while (curr < limit2) {
389                         struct hello_neighbor *neigh = olsr_malloc_hello_neighbor("HELLO deserialization");
390                         pkt_get_ipaddress(&curr, &neigh->address);
391                         
392                         if (type == LQ_HELLO_MESSAGE) {
393                                 olsr_deserialize_hello_lq_pair(&curr, neigh);
394                         }
395                         neigh->link = EXTRACT_LINK(info_head->link_code);
396                         neigh->status = EXTRACT_STATUS(info_head->link_code);
397                         
398                         neigh->next = hello->neighbors;
399                         hello->neighbors = neigh;
400                 }
401         }
402         return 0;
403 }
404
405 void olsr_input_hello(union olsr_message *ser, struct interface *inif, union olsr_ip_addr *from) {
406         struct hello_message hello;
407         
408         if (ser == NULL) {
409                 return;
410         }
411         if (deserialize_hello(&hello, ser) != 0) {
412                 return;
413         }
414         olsr_hello_tap(&hello, inif, from);
415 }
416
417 /**
418  *Initializing the parser functions we are using
419  */
420 void
421 olsr_init_package_process(void)
422 {
423   if (olsr_cnf->lq_level == 0)
424     {
425       olsr_parser_add_function(&olsr_input_hello, HELLO_MESSAGE, 1);
426       olsr_parser_add_function(&olsr_input_tc, TC_MESSAGE, 1);
427     }
428   else
429     {
430       olsr_parser_add_function(&olsr_input_hello, LQ_HELLO_MESSAGE, 1);
431       olsr_parser_add_function(&olsr_input_tc, LQ_TC_MESSAGE, 1);
432     }
433
434   olsr_parser_add_function(&olsr_process_received_mid, MID_MESSAGE, 1);
435   olsr_parser_add_function(&olsr_process_received_hna, HNA_MESSAGE, 1);
436 }
437
438 void
439 olsr_hello_tap(struct hello_message *message,
440                struct interface *in_if,
441                const union olsr_ip_addr *from_addr)
442 {
443   struct neighbor_entry     *neighbor;
444
445   /*
446    * Update link status
447    */
448   struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if);
449
450   if (olsr_cnf->lq_level > 0)
451     {
452       struct hello_neighbor *walker;
453       // just in case our neighbor has changed its HELLO interval
454       olsr_update_packet_loss_hello_int(lnk, message->htime);
455
456       // find the input interface in the list of neighbor interfaces
457       for (walker = message->neighbors; walker != NULL; walker = walker->next)
458         if (ipequal(&walker->address, &in_if->ip_addr))
459           break;
460
461       // memorize our neighbour's idea of the link quality, so that we
462       // know the link quality in both directions
463       olsr_memorize_foreign_hello_lq(lnk, walker);
464
465       // update packet loss for link quality calculation
466       olsr_update_packet_loss(lnk);
467     }
468   
469   neighbor = lnk->neighbor;
470
471   /*
472    * Hysteresis
473    */
474   if(olsr_cnf->use_hysteresis)
475     {
476       /* Update HELLO timeout */
477       //printf("MESSAGE HTIME: %f\n", message->htime);
478       olsr_update_hysteresis_hello(lnk, message->htime);
479     }
480
481   /* Check if we are chosen as MPR */
482   if(lookup_mpr_status(message, in_if))
483     /* source_addr is always the main addr of a node! */
484     olsr_update_mprs_set(&message->source_addr, message->vtime);
485
486
487
488   /* Check willingness */
489   if(neighbor->willingness != message->willingness)
490     {
491 #ifndef NODEBUG
492       struct ipaddr_str buf;
493 #endif
494       OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", 
495                   olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr),
496                   neighbor->willingness,
497                   message->willingness);
498       /*
499        *If willingness changed - recalculate
500        */
501       neighbor->willingness = message->willingness;
502       changes_neighborhood = OLSR_TRUE;
503       changes_topology = OLSR_TRUE;
504     }
505
506
507   /* Don't register neighbors of neighbors that announces WILL_NEVER */
508   if(neighbor->willingness != WILL_NEVER)
509     process_message_neighbors(neighbor, message);
510
511   /* Process changes immedeatly in case of MPR updates */
512   olsr_process_changes();
513
514   olsr_free_hello_packet(message);
515
516   return;
517 }
518
519 /**
520  *Process a received(and parsed) MID message
521  *For every address check if there is a topology node
522  *registered with it and update its addresses.
523  *
524  *@param m the OLSR message received.
525  *@return 1 on success
526  */
527
528 void
529 olsr_process_received_mid(union olsr_message *m,
530                           struct interface *in_if __attribute__((unused)),
531                           union olsr_ip_addr *from_addr)
532 {
533 #if !defined(NODEBUG) && defined(DEBUG)
534   struct ipaddr_str buf;
535 #endif
536   struct mid_alias *tmp_adr;
537   struct mid_message message;
538
539   mid_chgestruct(&message, m);
540
541   if (!olsr_validate_address(&message.mid_origaddr)) {
542     olsr_free_mid_packet(&message);
543     return;
544   }
545
546 #ifdef DEBUG
547     OLSR_PRINTF(5, "Processing MID from %s...\n", olsr_ip_to_string(&buf, &message.mid_origaddr));
548 #endif
549     tmp_adr = message.mid_addr;
550
551     /*
552      *      If the sender interface (NB: not originator) of this message
553      *      is not in the symmetric 1-hop neighborhood of this node, the
554      *      message MUST be discarded.
555      */
556
557     if(check_neighbor_link(from_addr) != SYM_LINK) {
558 #ifndef NODEBUG
559       struct ipaddr_str buf;
560 #endif
561       OLSR_PRINTF(2, "Received MID from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
562       olsr_free_mid_packet(&message);
563       return;
564     }
565
566     /* Update the timeout of the MID */
567     olsr_update_mid_table(&message.mid_origaddr, (float)message.vtime);
568
569     while (tmp_adr) {
570       if (!mid_lookup_main_addr(&tmp_adr->alias_addr)){
571 #ifndef NODEBUG
572         struct ipaddr_str buf;
573 #endif
574         OLSR_PRINTF(1, "MID new: (%s, ", olsr_ip_to_string(&buf, &message.mid_origaddr));
575         OLSR_PRINTF(1, "%s)\n", olsr_ip_to_string(&buf, &tmp_adr->alias_addr));
576         insert_mid_alias(&message.mid_origaddr, &tmp_adr->alias_addr, (float)message.vtime);
577       }
578       tmp_adr = tmp_adr->next;
579     } 
580   
581     olsr_prune_aliases(&message.mid_origaddr, message.mid_addr);
582
583   olsr_forward_message(m, from_addr);
584   olsr_free_mid_packet(&message);
585 }
586
587
588 /**
589  *Process incoming HNA message.
590  *Forwards the message if that is to be done.
591  *
592  *@param m the incoming OLSR message
593  *the OLSR message.
594  *@return 1 on success
595  */
596
597 void
598 olsr_process_received_hna(union olsr_message *m,
599                           struct interface *in_if __attribute__((unused)),
600                           union olsr_ip_addr *from_addr)
601 {
602
603   olsr_u8_t          olsr_msgtype;
604   double             vtime;
605   olsr_u16_t         olsr_msgsize;
606   union olsr_ip_addr originator;
607   //olsr_u8_t          ttl; unused
608   olsr_u8_t          hop_count;
609   olsr_u16_t         packet_seq_number;
610
611   int                hnasize;
612   const olsr_u8_t    *curr, *curr_end;
613
614 #ifdef DEBUG
615   OLSR_PRINTF(5, "Processing HNA\n");
616 #endif
617
618   /* Check if everyting is ok */
619   if (!m) {
620     return;
621   }
622   curr = (const olsr_u8_t *)m;
623
624   /* olsr_msgtype */
625   pkt_get_u8(&curr, &olsr_msgtype);
626   if (olsr_msgtype != HNA_MESSAGE) {
627     OLSR_PRINTF(0, "not a HNA message!\n");
628     return;
629   }
630   /* Get vtime */
631   pkt_get_double(&curr, &vtime);
632
633   /* olsr_msgsize */
634   pkt_get_u16(&curr, &olsr_msgsize);
635   hnasize = olsr_msgsize - (olsr_cnf->ip_version == AF_INET ? offsetof(struct olsrmsg, message) : offsetof(struct olsrmsg6, message));
636   if (hnasize < 0) {
637     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)));
638     return;
639   }
640   if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
641     OLSR_PRINTF(0, "Illegal message size %d!\n", olsr_msgsize);
642     return;
643   }
644   curr_end = (const olsr_u8_t *)m + olsr_msgsize;
645
646   /* validate originator */
647   pkt_get_ipaddress(&curr, &originator);
648   //printf("HNA from %s\n\n", olsr_ip_to_string(&buf, &originator));
649
650   /* ttl */
651   pkt_ignore_u8(&curr);
652
653   /* hopcnt */
654   pkt_get_u8(&curr, &hop_count);
655
656   /* seqno */
657   pkt_get_u16(&curr, &packet_seq_number);
658
659     /*
660      *      If the sender interface (NB: not originator) of this message
661      *      is not in the symmetric 1-hop neighborhood of this node, the
662      *      message MUST be discarded.
663      */
664     if (check_neighbor_link(from_addr) != SYM_LINK) {
665 #ifndef NODEBUG
666       struct ipaddr_str buf;
667 #endif
668       OLSR_PRINTF(2, "Received HNA from NON SYM neighbor %s\n", olsr_ip_to_string(&buf, from_addr));
669       return;
670     }
671 #if 1
672     while (curr < curr_end) {
673       union olsr_ip_addr net;
674       olsr_u8_t prefixlen;
675       struct ip_prefix_list *entry;
676
677       pkt_get_ipaddress(&curr, &net);
678       pkt_get_prefixlen(&curr, &prefixlen);
679       entry = ip_prefix_list_find(olsr_cnf->hna_entries, &net, prefixlen);
680       if (entry == NULL) {
681         /* only update if it's not from us */
682         olsr_update_hna_entry(&originator, &net, prefixlen, vtime);
683       }
684     }
685 #else
686     while (hna_tmp) {
687       /* Don't add an HNA entry that we are advertising ourselves. */
688       if (!ip_prefix_list_find(olsr_cnf->hna_entries, &hna_tmp->net, hna_tmp->prefixlen)) {
689         olsr_update_hna_entry(&message.originator, &hna_tmp->net, hna_tmp->prefixlen, message.vtime);
690       }
691     }
692 #endif
693   olsr_forward_message(m, from_addr);
694 }
695
696 /*
697  * Local Variables:
698  * c-basic-offset: 2
699  * End:
700  */