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