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