512dd5fb2fe0b44077678b6fa560c9d8bc4ae601
[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     newIf->next = NULL;
289     BmfInterfaces = newIf;
290     LastBmfInterface = newIf;
291   } else if (olsrIntf != NULL) {
292     /* Add new TBmfInterface object at front of list */
293     newIf->next = BmfInterfaces;
294     BmfInterfaces = newIf;
295   } else {
296     /* Add new TBmfInterface object at back of list */
297     newIf->next = NULL;
298     LastBmfInterface->next = newIf;
299     LastBmfInterface = newIf;
300   }
301
302   //OLSR_PRINTF(
303   //  8,
304   //  "%s: opened %d socket%s on %s interface \"%s\"\n",
305   //  PLUGIN_NAME_SHORT,
306   //  nOpened,
307   //  nOpened == 1 ? "" : "s",
308   //  olsrIntf != NULL ? "OLSR" : "non-OLSR",
309   //  ifName);
310
311   return nOpened;
312 }                               /* CreateInterface */
313
314 /* -------------------------------------------------------------------------
315  * Function   : CreateBmfNetworkInterfaces
316  * Description: Create a list of TBmfInterface objects, one for each network
317  *              interface on which BMF runs
318  * Input      : skipThisIntf - network interface to skip, if seen
319  * Output     : none
320  * Return     : fail (-1) or success (0)
321  * Data Used  : none
322  * ------------------------------------------------------------------------- */
323 int
324 CreateBmfNetworkInterfaces(struct interface *skipThisIntf)
325 {
326   int skfd;
327   struct ifconf ifc;
328   int numreqs = 30;
329   struct ifreq *ifr;
330   int n;
331   int nOpenedSockets = 0;
332
333   /* Clear input descriptor set */
334   FD_ZERO(&InputSet);
335
336   skfd = socket(PF_INET, SOCK_DGRAM, 0);
337   if (skfd < 0) {
338     BmfPError("no inet socket available to retrieve interface list");
339     return -1;
340   }
341
342   /* Retrieve the network interface configuration list */
343   ifc.ifc_buf = NULL;
344   for (;;) {
345     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
346     ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
347
348     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
349       BmfPError("ioctl(SIOCGIFCONF) error");
350
351       close(skfd);
352       free(ifc.ifc_buf);
353       return -1;
354     }
355     if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
356       /* Assume it overflowed; double the space and try again */
357       numreqs *= 2;
358       assert(numreqs < 1024);
359       continue;                 /* for (;;) */
360     }
361     break;                      /* for (;;) */
362   }                             /* for (;;) */
363
364   close(skfd);
365
366   /* For each item in the interface configuration list... */
367   ifr = ifc.ifc_req;
368   for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
369     struct interface *olsrIntf;
370     union olsr_ip_addr ipAddr;
371
372     /* Skip the BMF network interface itself */
373     //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
374     //{
375     //  continue; /* for (n = ...) */
376     //}
377
378     /* ...find the OLSR interface structure, if any */
379     ipAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
380     olsrIntf = if_ifwithaddr(&ipAddr);
381
382     if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
383       continue;                 /* for (n = ...) */
384     }
385
386     if (olsrIntf == NULL && !IsNonOlsrBmfIf(ifr->ifr_name)) {
387       /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
388        * interface in the BMF plugin parameter list */
389       continue;                 /* for (n = ...) */
390     }
391
392     if (!IsNonOlsrBmfIf(ifr->ifr_name)) {
393       //If the interface is not specified in the configuration file then go ahead
394       continue;                 /* for (n = ...) */
395     }
396     //TODO: asser if->ifr_name is not talking OLSR
397     //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
398     nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);
399
400   }                             /* for (n = ...) */
401
402   free(ifc.ifc_buf);
403
404   if (BmfInterfaces == NULL) {
405     //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
406   } else {
407     //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
408   }
409   return 0;
410 }                               /* CreateBmfNetworkInterfaces */
411
412 /* -------------------------------------------------------------------------
413  * Function   : AddInterface
414  * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
415  *              network interfaces
416  * Input      : newIntf - network interface to add
417  * Output     : none
418  * Return     : none
419  * Data Used  : none
420  * ------------------------------------------------------------------------- */
421 void
422 AddInterface(struct interface *newIntf)
423 {
424   /* int nOpened; */
425
426   assert(newIntf != NULL);
427
428   /* nOpened = */ (void)CreateInterface(newIntf->int_name, newIntf);
429
430   //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
431 }                               /* AddInterface */
432
433 /* -------------------------------------------------------------------------
434  * Function   : CloseBmfNetworkInterfaces
435  * Description: Closes every socket on each network interface used by BMF
436  * Input      : none
437  * Output     : none
438  * Return     : none
439  * Data Used  : none
440  * Notes      : Closes
441  *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
442  *              - for each BMF-enabled interface, the socket used for
443  *                capturing multicast packets
444  *              - for each OLSR-enabled interface, the socket used for
445  *                encapsulating packets
446  *              Also restores the network state to the situation before BMF
447  *              was started.
448  * ------------------------------------------------------------------------- */
449 void
450 CloseBmfNetworkInterfaces(void)
451 {
452   int nClosed = 0;
453   u_int32_t totalOlsrBmfPacketsRx = 0;
454   u_int32_t totalOlsrBmfPacketsRxDup = 0;
455   u_int32_t totalOlsrBmfPacketsTx = 0;
456   u_int32_t totalNonOlsrBmfPacketsRx = 0;
457   u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
458   u_int32_t totalNonOlsrBmfPacketsTx = 0;
459
460   /* Close all opened sockets */
461   struct TBmfInterface *nextBmfIf = BmfInterfaces;
462   while (nextBmfIf != NULL) {
463     struct TBmfInterface *bmfIf = nextBmfIf;
464     nextBmfIf = bmfIf->next;
465
466     if (bmfIf->capturingSkfd >= 0) {
467       close(bmfIf->capturingSkfd);
468       nClosed++;
469     }
470     if (bmfIf->encapsulatingSkfd >= 0) {
471       close(bmfIf->encapsulatingSkfd);
472       nClosed++;
473     }
474     //OLSR_PRINTF(
475     //  7,
476     //  "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
477     //  PLUGIN_NAME_SHORT,
478     //  bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
479     //  bmfIf->ifName,
480     //  bmfIf->nBmfPacketsRx,
481     //  bmfIf->nBmfPacketsRxDup,
482     //  bmfIf->nBmfPacketsTx);
483
484     //OLSR_PRINTF(
485     //  1,
486     //  "%s: closed %s interface \"%s\"\n",
487     //  PLUGIN_NAME_SHORT,
488     //  bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
489     //  bmfIf->ifName);
490
491     /* Add totals */
492     if (bmfIf->olsrIntf != NULL) {
493       totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
494       totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
495       totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
496     } else {
497       totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
498       totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
499       totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
500     }
501
502     free(bmfIf);
503   }                             /* while */
504
505   BmfInterfaces = NULL;
506
507   //OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
508
509 }                               /* CloseBmfNetworkInterfaces */
510
511 #define MAX_NON_OLSR_IFS 32
512 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
513 static int nNonOlsrIfs = 0;
514 /* -------------------------------------------------------------------------
515  * Function   : AddNonOlsrBmfIf
516  * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
517  *              network interfaces
518  * Input      : ifName - network interface (e.g. "eth0")
519  *              data - not used
520  *              addon - not used
521  * Output     : none
522  * Return     : success (0) or fail (1)
523  * Data Used  : NonOlsrIfNames
524  * ------------------------------------------------------------------------- */
525 int
526 AddNonOlsrBmfIf(const char *ifName, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
527 {
528   assert(ifName != NULL);
529
530   if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) {
531     //OLSR_PRINTF(
532     //  1,
533     //  "%s: too many non-OLSR interfaces specified, maximum is %d\n",
534     //  PLUGIN_NAME,
535     //  MAX_NON_OLSR_IFS);
536     return 1;
537   }
538
539   strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
540   NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0';     /* Ensures null termination */
541   nNonOlsrIfs++;
542   return 0;
543 }                               /* AddNonOlsrBmfIf */
544
545
546 int
547 set_MDNS_TTL(const char *MDNS_TTL, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
548 {
549   assert(MDNS_TTL!= NULL);
550   my_MDNS_TTL = atoi(MDNS_TTL);
551   return 0;
552 }                               /* set_MDNS_TTL */
553 /* -------------------------------------------------------------------------
554  * Function   : IsNonOlsrBmfIf
555  * Description: Checks if a network interface is OLSR-enabled
556  * Input      : ifName - network interface (e.g. "eth0")
557  * Output     : none
558  * Return     : true (1) or false (0)
559  * Data Used  : NonOlsrIfNames
560  * ------------------------------------------------------------------------- */
561 int
562 IsNonOlsrBmfIf(const char *ifName)
563 {
564   int i;
565
566   assert(ifName != NULL);
567
568   for (i = 0; i < nNonOlsrIfs; i++) {
569     if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0)
570       return 1;
571   }
572   return 0;
573 }                               /* IsNonOlsrBmfIf */