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