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