Add p2dp plugin (generalized mdns), thanks to Teco Boot <teco@inf-net.nl>
[olsrd.git] / lib / p2pd / src / NetworkInterfaces.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
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
42 #include "NetworkInterfaces.h"
43
44 /* System includes */
45 #include <stddef.h>             /* NULL */
46 #include <syslog.h>             /* syslog() */
47 #include <string.h>             /* strerror(), strchr(), strcmp() */
48 #include <errno.h>              /* errno */
49 #include <unistd.h>             /* close() */
50 #include <sys/ioctl.h>          /* ioctl() */
51 #include <fcntl.h>              /* fcntl() */
52 #include <assert.h>             /* assert() */
53 #include <net/if.h>             /* socket(), ifreq, if_indextoname(), if_nametoindex() */
54 #include <netinet/in.h>         /* htons() */
55 #include <linux/if_ether.h>     /* ETH_P_IP */
56 #include <linux/if_packet.h>    /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
57 #include <linux/if_tun.h>       /* IFF_TAP */
58 #include <netinet/ip.h>         /* struct ip */
59 #include <netinet/udp.h>        /* SOL_UDP */
60 #include <stdlib.h>             /* atoi, malloc */
61
62 /* OLSRD includes */
63 #include "olsr.h"               /* OLSR_PRINTF() */
64 #include "ipcalc.h"
65 #include "defs.h"               /* olsr_cnf */
66 #include "link_set.h"           /* get_link_set() */
67 #include "tc_set.h"             /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
68 #include "net_olsr.h"           /* ipequal */
69 #include "lq_plugin.h"
70 //#include "olsr_ip_prefix_list.h"
71
72 /* Plugin includes */
73 #include "Packet.h"             /* IFHWADDRLEN */
74 #include "p2pd.h"               /* PLUGIN_NAME, MainAddressOf() */
75 //#include "Address.h"            /* IsMulticast() */
76
77
78 /* List of network interface objects used by BMF plugin */
79 struct NonOlsrInterface *nonOlsrInterfaces = NULL;
80 struct NonOlsrInterface *lastNonOlsrInterface = NULL;
81
82 /* -------------------------------------------------------------------------
83  * Function   : CreateCaptureSocket
84  * Description: Create socket for promiscuously capturing multicast IP traffic
85  * Input      : ifname - network interface (e.g. "eth0")
86  * Output     : none
87  * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
88  * Data Used  : none
89  * Notes      : The socket is a cooked IP packet socket, bound to the specified
90  *              network interface
91  * ------------------------------------------------------------------------- */
92 int
93 CreateCaptureSocket(const char *ifName)
94 {
95   int ifIndex = if_nametoindex(ifName);
96   struct packet_mreq mreq;
97   struct ifreq req;
98   struct sockaddr_ll bindTo;
99   int skfd = 0;
100   /* Open cooked IP packet socket */
101   if (olsr_cnf->ip_version == AF_INET) {
102     skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
103   } else {
104     skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
105   }
106   if (skfd < 0) {
107     P2pdPError("socket(PF_PACKET) error");
108     return -1;
109   }
110
111   /* Set interface to promiscuous mode */
112   memset(&mreq, 0, sizeof(struct packet_mreq));
113   mreq.mr_ifindex = ifIndex;
114   mreq.mr_type = PACKET_MR_PROMISC;
115   if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
116     P2pdPError("setsockopt(PACKET_MR_PROMISC) error");
117     close(skfd);
118     return -1;
119   }
120
121   /* Get hardware (MAC) address */
122   memset(&req, 0, sizeof(struct ifreq));
123   strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
124   req.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
125   if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0) {
126     P2pdPError("error retrieving MAC address");
127     close(skfd);
128     return -1;
129   }
130
131   /* Bind the socket to the specified interface */
132   memset(&bindTo, 0, sizeof(bindTo));
133   bindTo.sll_family = AF_PACKET;
134   if (olsr_cnf->ip_version == AF_INET) {
135     bindTo.sll_protocol = htons(ETH_P_IP);
136   } else {
137     bindTo.sll_protocol = htons(ETH_P_IPV6);
138   }
139   bindTo.sll_ifindex = ifIndex;
140   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
141   bindTo.sll_halen = IFHWADDRLEN;
142
143   if (bind(skfd, (struct sockaddr *)&bindTo, sizeof(bindTo)) < 0) {
144     P2pdPError("bind() error");
145     close(skfd);
146     return -1;
147   }
148
149   /* Set socket to blocking operation */
150   if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) {
151     P2pdPError("fcntl() error");
152     close(skfd);
153     return -1;
154   }
155   //AddDescriptorToInputSet(skfd);
156   add_olsr_socket(skfd, (socket_handler_func)&DoP2pd, NULL, NULL, SP_PR_READ);
157
158   return skfd;
159 }                               /* CreateCaptureSocket */
160
161 /* -------------------------------------------------------------------------
162  * Function   : CreateInterface
163  * Description: Create a new NonOlsrInterface object and adds it to the global
164  *              nonOlsrInterfaces list
165  * Input      : ifName - name of the network interface (e.g. "eth0")
166  *            : olsrIntf - OLSR interface object of the network interface, or
167  *                NULL if the network interface is not OLSR-enabled
168  * Output     : none
169  * Return     : the number of opened sockets
170  * Data Used  : nonOlsrInterfaces, lastNonOlsrInterface
171  * ------------------------------------------------------------------------- */
172
173 //FOR MDNS IS ALWAYS CALLED WITH NULL AS SECOND ARG
174
175 static int
176 CreateInterface(const char *ifName, struct interface *olsrIntf)
177 {
178   int capturingSkfd = -1;
179   int encapsulatingSkfd = -1;
180   int listeningSkfd = -1;
181   int ioctlSkfd;
182   struct ifreq ifr;
183   int nOpened = 0;
184   struct NonOlsrInterface *newIf = malloc(sizeof(struct NonOlsrInterface));
185
186   assert(ifName != NULL);
187
188   if (newIf == NULL) {
189     return 0;
190   }
191 //TODO: assert interface is not talking OLSR
192
193
194   /* Create socket for capturing and sending of multicast packets on
195    * non-OLSR interfaces, and on OLSR-interfaces if configured. */
196   if ((olsrIntf == NULL)) {
197     capturingSkfd = CreateCaptureSocket(ifName);
198     if (capturingSkfd < 0) {
199       close(encapsulatingSkfd);
200       free(newIf);
201       return 0;
202     }
203
204     nOpened++;
205   }
206
207   /* For ioctl operations on the network interface, use either capturingSkfd
208    * or encapsulatingSkfd, whichever is available */
209   ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
210
211   /* Retrieve the MAC address of the interface. */
212   memset(&ifr, 0, sizeof(struct ifreq));
213   strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
214   ifr.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
215   if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0) {
216     P2pdPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
217     close(capturingSkfd);
218     close(encapsulatingSkfd);
219     free(newIf);
220     return 0;
221   }
222
223   /* Copy data into NonOlsrInterface object */
224   newIf->capturingSkfd = capturingSkfd;
225   newIf->encapsulatingSkfd = encapsulatingSkfd;
226   newIf->listeningSkfd = listeningSkfd;
227   memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
228   memcpy(newIf->ifName, ifName, IFNAMSIZ);
229   newIf->olsrIntf = olsrIntf;
230   if (olsrIntf != NULL) {
231     /* For an OLSR-interface, copy the interface address and broadcast
232      * address from the OLSR interface object. Downcast to correct sockaddr
233      * subtype. */
234     newIf->intAddr.v4 = olsrIntf->int_addr.sin_addr;
235     newIf->broadAddr.v4 = olsrIntf->int_broadaddr.sin_addr;
236   } else {
237     /* For a non-OLSR interface, retrieve the IP address ourselves */
238     memset(&ifr, 0, sizeof(struct ifreq));
239     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
240     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
241     if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) {
242       P2pdPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
243
244       newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
245     } else {
246       /* Downcast to correct sockaddr subtype */
247       newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
248     }
249
250     /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
251     memset(&ifr, 0, sizeof(struct ifreq));
252     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
253     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
254     if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) {
255       P2pdPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
256
257       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
258     } else {
259       /* Downcast to correct sockaddr subtype */
260       newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
261     }
262   }
263
264   /* Initialize fragment history table */
265   //memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
266   //newIf->nextFragmentHistoryEntry = 0;
267
268   /* Reset counters */
269   //newIf->nNonOlsrPacketsRx = 0;
270   //newIf->nNonOlsrPacketsRxDup = 0;
271   //newIf->nNonOlsrPacketsTx = 0;
272
273   /* Add new NonOlsrInterface object to global list. OLSR interfaces are
274    * added at the front of the list, non-OLSR interfaces at the back. */
275   if (nonOlsrInterfaces == NULL) {
276     /* First NonOlsrInterface object in list */
277     nonOlsrInterfaces = newIf;
278     lastNonOlsrInterface = newIf;
279   } else if (olsrIntf != NULL) {
280     /* Add new NonOlsrInterface object at front of list */
281     newIf->next = nonOlsrInterfaces;
282     nonOlsrInterfaces = newIf;
283   } else {
284     /* Add new NonOlsrInterface object at back of list */
285     newIf->next = NULL;
286     lastNonOlsrInterface->next = newIf;
287     lastNonOlsrInterface = newIf;
288   }
289
290   //OLSR_PRINTF(
291   //  8,
292   //  "%s: opened %d socket%s on %s interface \"%s\"\n",
293   //  PLUGIN_NAME_SHORT,
294   //  nOpened,
295   //  nOpened == 1 ? "" : "s",
296   //  olsrIntf != NULL ? "OLSR" : "non-OLSR",
297   //  ifName);
298
299   return nOpened;
300 }                               /* CreateInterface */
301
302 /* -------------------------------------------------------------------------
303  * Function   : CreateNonOlsrNetworkInterfaces
304  * Description: Create a list of NonOlsrInterface objects, one for each network
305  *              interface on which BMF runs
306  * Input      : skipThisIntf - network interface to skip, if seen
307  * Output     : none
308  * Return     : fail (-1) or success (0)
309  * Data Used  : none
310  * ------------------------------------------------------------------------- */
311 int
312 CreateNonOlsrNetworkInterfaces(struct interface *skipThisIntf)
313 {
314   int skfd;
315   struct ifconf ifc;
316   int numreqs = 30;
317   struct ifreq *ifr;
318   int n;
319   int nOpenedSockets = 0;
320
321   /* Clear input descriptor set */
322   FD_ZERO(&InputSet);
323
324   skfd = socket(PF_INET, SOCK_DGRAM, 0);
325   if (skfd < 0) {
326     P2pdPError("no inet socket available to retrieve interface list");
327     return -1;
328   }
329
330   /* Retrieve the network interface configuration list */
331   ifc.ifc_buf = NULL;
332   for (;;) {
333     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
334     ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
335
336     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
337       P2pdPError("ioctl(SIOCGIFCONF) error");
338
339       close(skfd);
340       free(ifc.ifc_buf);
341       return -1;
342     }
343     if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
344       /* Assume it overflowed; double the space and try again */
345       numreqs *= 2;
346       assert(numreqs < 1024);
347       continue;                 /* for (;;) */
348     }
349     break;                      /* for (;;) */
350   }                             /* for (;;) */
351
352   close(skfd);
353
354   /* For each item in the interface configuration list... */
355   ifr = ifc.ifc_req;
356   for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
357     struct interface *olsrIntf;
358     union olsr_ip_addr ipAddr;
359
360     /* Skip the BMF network interface itself */
361     //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
362     //{
363     //  continue; /* for (n = ...) */
364     //}
365
366     /* ...find the OLSR interface structure, if any */
367     ipAddr.v4 = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
368     olsrIntf = if_ifwithaddr(&ipAddr);
369
370     if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
371       continue;                 /* for (n = ...) */
372     }
373
374     if (olsrIntf == NULL && !IsNonOlsrIf(ifr->ifr_name)) {
375       /* Interface is neither OLSR interface, nor specified as non-OLSR
376        * interface in the plugin parameter list */
377       continue;                 /* for (n = ...) */
378     }
379
380     if (!IsNonOlsrIf(ifr->ifr_name)) {
381       //If the interface is not specified in the configuration file then go ahead
382       continue;                 /* for (n = ...) */
383     }
384     //TODO: asser if->ifr_name is not talking OLSR
385     //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
386     nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);
387
388   }                             /* for (n = ...) */
389
390   free(ifc.ifc_buf);
391
392   if (nonOlsrInterfaces == NULL) {
393     //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
394   } else {
395     //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
396   }
397   return 0;
398 }                               /* CreateNonOlsrNetworkInterfaces */
399
400 /* -------------------------------------------------------------------------
401  * Function   : AddInterface
402  * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
403  *              network interfaces
404  * Input      : newIntf - network interface to add
405  * Output     : none
406  * Return     : none
407  * Data Used  : none
408  * ------------------------------------------------------------------------- */
409 void
410 AddInterface(struct interface *newIntf)
411 {
412   int nOpened;
413
414   assert(newIntf != NULL);
415
416   nOpened = CreateInterface(newIntf->int_name, newIntf);
417
418   //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
419 }                               /* AddInterface */
420
421 /* -------------------------------------------------------------------------
422  * Function   : CloseNonOlsrNetworkInterfaces
423  * Description: Closes every socket on each network interface used by BMF
424  * Input      : none
425  * Output     : none
426  * Return     : none
427  * Data Used  : none
428  * Notes      : Closes
429  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
430  *              - for each BMF-enabled interface, the socket used for
431  *                capturing multicast packets
432  *              - for each OLSR-enabled interface, the socket used for
433  *                encapsulating packets
434  *              Also restores the network state to the situation before BMF
435  *              was started.
436  * ------------------------------------------------------------------------- */
437 void
438 CloseNonOlsrNetworkInterfaces(void)
439 {
440   int nClosed = 0;
441   u_int32_t totalOlsrPacketsRx = 0;
442   u_int32_t totalOlsrPacketsRxDup = 0;
443   u_int32_t totalOlsrPacketsTx = 0;
444   u_int32_t totalNonOlsrPacketsRx = 0;
445   u_int32_t totalNonOlsrPacketsRxDup = 0;
446   u_int32_t totalNonOlsrPacketsTx = 0;
447
448   /* Close all opened sockets */
449   struct NonOlsrInterface *nextIf = nonOlsrInterfaces;
450   while (nextIf != NULL) {
451     struct NonOlsrInterface *ifc = nextIf;
452     nextIf = ifc->next;
453
454     if (ifc->capturingSkfd >= 0) {
455       close(ifc->capturingSkfd);
456       nClosed++;
457     }
458     if (ifc->encapsulatingSkfd >= 0) {
459       close(ifc->encapsulatingSkfd);
460       nClosed++;
461     }
462     //OLSR_PRINTF(
463     //  7,
464     //  "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
465     //  PLUGIN_NAME_SHORT,
466     //  ifc->olsrIntf != NULL ? "OLSR" : "non-OLSR",
467     //  ifc->ifName,
468     //  ifc->nPacketsRx,
469     //  ifc->nPacketsRxDup,
470     //  ifc->nPacketsTx);
471
472     //OLSR_PRINTF(
473     //  1,
474     //  "%s: closed %s interface \"%s\"\n",
475     //  PLUGIN_NAME_SHORT,
476     //  ifc->olsrIntf != NULL ? "OLSR" : "non-OLSR",
477     //  ifc->ifName);
478
479     /* Add totals */
480     if (ifc->olsrIntf != NULL) {
481       totalOlsrPacketsRx                                += ifc->nPacketsRx;
482       totalOlsrPacketsRxDup                     += ifc->nPacketsRxDup;
483       totalOlsrPacketsTx                                += ifc->nPacketsTx;
484     } else {
485       totalNonOlsrPacketsRx             += ifc->nPacketsRx;
486       totalNonOlsrPacketsRxDup  += ifc->nPacketsRxDup;
487       totalNonOlsrPacketsTx                     += ifc->nPacketsTx;
488     }
489
490     free(ifc);
491   }                             /* while */
492
493   nonOlsrInterfaces = NULL;
494
495   //OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
496
497 }                               /* CloseNonOlsrNetworkInterfaces */
498
499 #define MAX_NON_OLSR_IFS 32
500 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
501 static int nNonOlsrIfs = 0;
502 /* -------------------------------------------------------------------------
503  * Function   : AddNonOlsrIf
504  * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
505  *              network interfaces
506  * Input      : ifName - network interface (e.g. "eth0")
507  *              data - not used
508  *              addon - not used
509  * Output     : none
510  * Return     : success (0) or fail (1)
511  * Data Used  : NonOlsrIfNames
512  * ------------------------------------------------------------------------- */
513 int
514 AddNonOlsrIf(const char *ifName, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
515 {
516   assert(ifName != NULL);
517
518   if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) {
519     //OLSR_PRINTF(
520     //  1,
521     //  "%s: too many non-OLSR interfaces specified, maximum is %d\n",
522     //  PLUGIN_NAME,
523     //  MAX_NON_OLSR_IFS);
524     return 1;
525   }
526
527   olsr_printf(1, "\nAdding interface '%s' to list of interface\n", ifName);
528   
529   strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
530   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0';     /* Ensures null termination */
531   nNonOlsrIfs++;
532   return 0;
533 }                               /* AddNonOlsrIf */
534
535 /* -------------------------------------------------------------------------
536  * Function   : IsNonOlsrIf
537  * Description: Checks if a network interface is OLSR-enabled
538  * Input      : ifName - network interface (e.g. "eth0")
539  * Output     : none
540  * Return     : true (1) or false (0)
541  * Data Used  : NonOlsrIfNames
542  * ------------------------------------------------------------------------- */
543 int
544 IsNonOlsrIf(const char *ifName)
545 {
546   int i;
547
548   assert(ifName != NULL);
549
550   for (i = 0; i < nNonOlsrIfs; i++) {
551     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0)
552       return 1;
553   }
554   return 0;
555 }                               /* IsNonOlsrIf */