p2pd: fix GCC 6 warnings
[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_olsr *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) {
197     capturingSkfd = CreateCaptureSocket(ifName);
198     if (capturingSkfd < 0) {
199       free(newIf);
200       return 0;
201     }
202
203     nOpened++;
204   }
205
206   /* For ioctl operations on the network interface, use either capturingSkfd
207    * or encapsulatingSkfd, whichever is available */
208   ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
209
210   /* Retrieve the MAC address of the interface. */
211   memset(&ifr, 0, sizeof(struct ifreq));
212   strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
213   ifr.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
214   if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0) {
215     P2pdPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
216     if (capturingSkfd >= 0) {
217       close(capturingSkfd);
218     }
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       struct sockaddr* ifra = &ifr.ifr_addr;
248       newIf->intAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(ifra))->sin_addr;
249     }
250
251     /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
252     memset(&ifr, 0, sizeof(struct ifreq));
253     strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
254     ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
255     if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) {
256       P2pdPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
257
258       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
259     } else {
260       /* Downcast to correct sockaddr subtype */
261       struct sockaddr* ifrb = &ifr.ifr_broadaddr;
262       newIf->broadAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(ifrb))->sin_addr;
263     }
264   }
265
266   /* Initialize fragment history table */
267   //memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
268   //newIf->nextFragmentHistoryEntry = 0;
269
270   /* Reset counters */
271   //newIf->nNonOlsrPacketsRx = 0;
272   //newIf->nNonOlsrPacketsRxDup = 0;
273   //newIf->nNonOlsrPacketsTx = 0;
274
275   /* Add new NonOlsrInterface object to global list. OLSR interfaces are
276    * added at the front of the list, non-OLSR interfaces at the back. */
277   if (nonOlsrInterfaces == NULL) {
278     /* First NonOlsrInterface object in list */
279     newIf->next = NULL;
280     nonOlsrInterfaces = newIf;
281     lastNonOlsrInterface = newIf;
282   } else if (olsrIntf != NULL) {
283     /* Add new NonOlsrInterface object at front of list */
284     newIf->next = nonOlsrInterfaces;
285     nonOlsrInterfaces = newIf;
286   } else {
287     /* Add new NonOlsrInterface object at back of list */
288     newIf->next = NULL;
289     lastNonOlsrInterface->next = newIf;
290     lastNonOlsrInterface = newIf;
291   }
292
293   //OLSR_PRINTF(
294   //  8,
295   //  "%s: opened %d socket%s on %s interface \"%s\"\n",
296   //  PLUGIN_NAME_SHORT,
297   //  nOpened,
298   //  nOpened == 1 ? "" : "s",
299   //  olsrIntf != NULL ? "OLSR" : "non-OLSR",
300   //  ifName);
301
302   return nOpened;
303 }                               /* CreateInterface */
304
305 /* -------------------------------------------------------------------------
306  * Function   : CreateNonOlsrNetworkInterfaces
307  * Description: Create a list of NonOlsrInterface objects, one for each network
308  *              interface on which BMF runs
309  * Input      : skipThisIntf - network interface to skip, if seen
310  * Output     : none
311  * Return     : fail (-1) or success (0)
312  * Data Used  : none
313  * ------------------------------------------------------------------------- */
314 int
315 CreateNonOlsrNetworkInterfaces(struct interface_olsr *skipThisIntf)
316 {
317   int skfd;
318   struct ifconf ifc;
319   int numreqs = 30;
320   struct ifreq *ifr;
321   int n;
322   int nOpenedSockets = 0;
323
324   /* Clear input descriptor set */
325   FD_ZERO(&InputSet);
326
327   skfd = socket(PF_INET, SOCK_DGRAM, 0);
328   if (skfd < 0) {
329     P2pdPError("no inet socket available to retrieve interface list");
330     return -1;
331   }
332
333   /* Retrieve the network interface configuration list */
334   ifc.ifc_buf = NULL;
335   for (;;) {
336     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
337     ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
338
339     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
340       P2pdPError("ioctl(SIOCGIFCONF) error");
341
342       close(skfd);
343       free(ifc.ifc_buf);
344       return -1;
345     }
346     if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
347       /* Assume it overflowed; double the space and try again */
348       numreqs *= 2;
349       assert(numreqs < 1024);
350       continue;                 /* for (;;) */
351     }
352     break;                      /* for (;;) */
353   }                             /* for (;;) */
354
355   close(skfd);
356
357   /* For each item in the interface configuration list... */
358   ifr = ifc.ifc_req;
359   for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
360     struct interface_olsr *olsrIntf;
361     union olsr_ip_addr ipAddr;
362
363     /* Skip the BMF network interface itself */
364     //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
365     //{
366     //  continue; /* for (n = ...) */
367     //}
368
369     /* ...find the OLSR interface structure, if any */
370     {
371       struct sockaddr* ifra = &ifr->ifr_addr;
372       ipAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(ifra))->sin_addr;
373     }
374     olsrIntf = if_ifwithaddr(&ipAddr);
375
376     if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
377       continue;                 /* for (n = ...) */
378     }
379
380     if (olsrIntf == NULL && !IsNonOlsrIf(ifr->ifr_name)) {
381       /* Interface is neither OLSR interface, nor specified as non-OLSR
382        * interface in the plugin parameter list */
383       continue;                 /* for (n = ...) */
384     }
385
386     if (!IsNonOlsrIf(ifr->ifr_name)) {
387       //If the interface is not specified in the configuration file then go ahead
388       continue;                 /* for (n = ...) */
389     }
390     //TODO: asser if->ifr_name is not talking OLSR
391     //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
392     nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);
393
394   }                             /* for (n = ...) */
395
396   free(ifc.ifc_buf);
397
398   if (nonOlsrInterfaces == NULL) {
399     //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
400   } else {
401     //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
402   }
403   return 0;
404 }                               /* CreateNonOlsrNetworkInterfaces */
405
406 /* -------------------------------------------------------------------------
407  * Function   : AddInterface
408  * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
409  *              network interfaces
410  * Input      : newIntf - network interface to add
411  * Output     : none
412  * Return     : none
413  * Data Used  : none
414  * ------------------------------------------------------------------------- */
415 void
416 AddInterface(struct interface_olsr *newIntf)
417 {
418   /* int nOpened; */
419
420   assert(newIntf != NULL);
421
422   /* nOpened = */ (void)CreateInterface(newIntf->int_name, newIntf);
423
424   //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
425 }                               /* AddInterface */
426
427 /* -------------------------------------------------------------------------
428  * Function   : CloseNonOlsrNetworkInterfaces
429  * Description: Closes every socket on each network interface used by BMF
430  * Input      : none
431  * Output     : none
432  * Return     : none
433  * Data Used  : none
434  * Notes      : Closes
435  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
436  *              - for each BMF-enabled interface, the socket used for
437  *                capturing multicast packets
438  *              - for each OLSR-enabled interface, the socket used for
439  *                encapsulating packets
440  *              Also restores the network state to the situation before BMF
441  *              was started.
442  * ------------------------------------------------------------------------- */
443 void
444 CloseNonOlsrNetworkInterfaces(void)
445 {
446   int nClosed = 0;
447   u_int32_t totalOlsrPacketsRx = 0;
448   u_int32_t totalOlsrPacketsRxDup = 0;
449   u_int32_t totalOlsrPacketsTx = 0;
450   u_int32_t totalNonOlsrPacketsRx = 0;
451   u_int32_t totalNonOlsrPacketsRxDup = 0;
452   u_int32_t totalNonOlsrPacketsTx = 0;
453
454   /* Close all opened sockets */
455   struct NonOlsrInterface *nextIf = nonOlsrInterfaces;
456   while (nextIf != NULL) {
457     struct NonOlsrInterface *ifc = nextIf;
458     nextIf = ifc->next;
459
460     if (ifc->capturingSkfd >= 0) {
461       close(ifc->capturingSkfd);
462       nClosed++;
463     }
464     if (ifc->encapsulatingSkfd >= 0) {
465       close(ifc->encapsulatingSkfd);
466       nClosed++;
467     }
468     //OLSR_PRINTF(
469     //  7,
470     //  "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
471     //  PLUGIN_NAME_SHORT,
472     //  ifc->olsrIntf != NULL ? "OLSR" : "non-OLSR",
473     //  ifc->ifName,
474     //  ifc->nPacketsRx,
475     //  ifc->nPacketsRxDup,
476     //  ifc->nPacketsTx);
477
478     //OLSR_PRINTF(
479     //  1,
480     //  "%s: closed %s interface \"%s\"\n",
481     //  PLUGIN_NAME_SHORT,
482     //  ifc->olsrIntf != NULL ? "OLSR" : "non-OLSR",
483     //  ifc->ifName);
484
485     /* Add totals */
486     if (ifc->olsrIntf != NULL) {
487       totalOlsrPacketsRx                                += ifc->nPacketsRx;
488       totalOlsrPacketsRxDup                     += ifc->nPacketsRxDup;
489       totalOlsrPacketsTx                                += ifc->nPacketsTx;
490     } else {
491       totalNonOlsrPacketsRx             += ifc->nPacketsRx;
492       totalNonOlsrPacketsRxDup  += ifc->nPacketsRxDup;
493       totalNonOlsrPacketsTx                     += ifc->nPacketsTx;
494     }
495
496     free(ifc);
497   }                             /* while */
498
499   nonOlsrInterfaces = NULL;
500
501   //OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
502
503 }                               /* CloseNonOlsrNetworkInterfaces */
504
505 #define MAX_NON_OLSR_IFS 32
506 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
507 static int nNonOlsrIfs = 0;
508 /* -------------------------------------------------------------------------
509  * Function   : AddNonOlsrIf
510  * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
511  *              network interfaces
512  * Input      : ifName - network interface (e.g. "eth0")
513  *              data - not used
514  *              addon - not used
515  * Output     : none
516  * Return     : success (0) or fail (1)
517  * Data Used  : NonOlsrIfNames
518  * ------------------------------------------------------------------------- */
519 int
520 AddNonOlsrIf(const char *ifName, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
521 {
522   assert(ifName != NULL);
523
524   if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) {
525     //OLSR_PRINTF(
526     //  1,
527     //  "%s: too many non-OLSR interfaces specified, maximum is %d\n",
528     //  PLUGIN_NAME,
529     //  MAX_NON_OLSR_IFS);
530     return 1;
531   }
532
533   olsr_printf(1, "\nAdding interface '%s' to list of interface\n", ifName);
534   
535   strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
536   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0';     /* Ensures null termination */
537   nNonOlsrIfs++;
538   return 0;
539 }                               /* AddNonOlsrIf */
540
541 /* -------------------------------------------------------------------------
542  * Function   : IsNonOlsrIf
543  * Description: Checks if a network interface is OLSR-enabled
544  * Input      : ifName - network interface (e.g. "eth0")
545  * Output     : none
546  * Return     : true (1) or false (0)
547  * Data Used  : NonOlsrIfNames
548  * ------------------------------------------------------------------------- */
549 int
550 IsNonOlsrIf(const char *ifName)
551 {
552   int i;
553
554   assert(ifName != NULL);
555
556   for (i = 0; i < nNonOlsrIfs; i++) {
557     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0)
558       return 1;
559   }
560   return 0;
561 }                               /* IsNonOlsrIf */