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