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