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