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