mdns: fix three alignment warnings
[olsrd.git] / lib / mdns / src / mdns.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 "mdns.h"
43
44 /* System includes */
45 #include <stddef.h>             /* NULL */
46 #include <sys/types.h>          /* ssize_t */
47 #include <string.h>             /* strerror() */
48 #include <stdarg.h>             /* va_list, va_start, va_end */
49 #include <errno.h>              /* errno */
50 #include <assert.h>             /* assert() */
51 #include <linux/if_ether.h>     /* ETH_P_IP */
52 #include <linux/if_packet.h>    /* struct sockaddr_ll, PACKET_MULTICAST */
53 //#include <pthread.h> /* pthread_t, pthread_create() */
54 #include <signal.h>             /* sigset_t, sigfillset(), sigdelset(), SIGINT */
55 #include <netinet/ip.h>         /* struct ip */
56 #include <netinet/udp.h>        /* struct udphdr */
57 #include <unistd.h>             /* close() */
58
59 #include <netinet/in.h>
60 #include <netinet/ip6.h>
61
62 /* OLSRD includes */
63 #include "plugin_util.h"        /* set_plugin_int */
64 #include "defs.h"               /* olsr_cnf, //OLSR_PRINTF */
65 #include "ipcalc.h"
66 #include "olsr.h"               /* //OLSR_PRINTF */
67 #include "mid_set.h"            /* mid_lookup_main_addr() */
68 #include "link_set.h"           /* get_best_link_to_neighbor() */
69 #include "net_olsr.h"           /* ipequal */
70
71 /* plugin includes */
72 #include "NetworkInterfaces.h"  /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
73 #include "Address.h"            /* IsMulticast() */
74 #include "Packet.h"             /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
75 #include "list_backport.h"
76 #include "RouterElection.h"
77 #include "list_backport.h"
78
79 #define OLSR_FOR_ALL_FILTEREDNODES_ENTRIES(n, iterator) listbackport_for_each_element_safe(&ListOfFilteredHosts, n, list, iterator)
80
81 #define IPH_HL(hdr) (((hdr)->ip_hl)*4)
82
83 struct list_entity ListOfFilteredHosts;
84 int FHListInit = 0;
85
86 static uint16_t ip_checksum(char* data, int len)
87 {
88     uint sum = 0;
89     if ((len & 1) == 0)
90         len = len >> 1;
91     else
92         len = (len >> 1) + 1;
93     while (len > 0) {
94         sum += *((unsigned short int*)(void *)data);
95         data += sizeof(unsigned short int);
96         len--;
97     }
98     sum = (sum >> 16) + (sum & 0xffff);
99     sum += (sum >> 16);
100     return(~sum);
101 }
102
103
104 /* -------------------------------------------------------------------------
105  * Function   : PacketReceivedFromOLSR
106  * Description: Handle a received packet from a OLSR message
107  * Input      : ipPacket into an unsigned char and the lenght of the packet
108  * Output     : none
109  * Return     : none
110  * Data Used  : BmfInterfaces
111  * ------------------------------------------------------------------------- */
112 static void
113 PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
114 {
115   struct ip *ipHeader;                 /* IP header inside the encapsulated IP packet */
116   struct ip6_hdr *ip6Header;                 /* IP header inside the encapsulated IP packet */
117   //union olsr_ip_addr mcSrc;            /* Original source of the encapsulated multicast packet */
118   //union olsr_ip_addr mcDst;            /* Multicast destination of the encapsulated packet */
119   struct TBmfInterface *walker;
120   int stripped_len = 0;
121   uint16_t csum_ip;
122   ipHeader = (struct ip *)ARM_NOWARN_ALIGN(encapsulationUdpData);
123   ip6Header = (struct ip6_hdr *)ARM_NOWARN_ALIGN(encapsulationUdpData);
124
125   //mcSrc.v4 = ipHeader->ip_src;
126   //mcDst.v4 = ipHeader->ip_dst;
127   //OLSR_DEBUG(LOG_PLUGINS, "MDNS PLUGIN got packet from OLSR message\n");
128
129
130   /* Check with each network interface what needs to be done on it */
131   for (walker = BmfInterfaces; walker != NULL; walker = walker->next) {
132     /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
133     if (walker->olsrIntf == NULL) {
134       int nBytesWritten;
135       struct sockaddr_ll dest;
136
137       memset(&dest, 0, sizeof(dest));
138       dest.sll_family = AF_PACKET;
139       if ((encapsulationUdpData[0] & 0xf0) == 0x40) {
140         dest.sll_protocol = htons(ETH_P_IP);
141         stripped_len = ntohs(ipHeader->ip_len);
142         if(my_TTL_Check)
143                 ipHeader->ip_ttl = (u_int8_t) 1; //setting up TTL to 1 to avoid mdns packets flood 
144         }
145         //Recalculate IP Checksum
146         ipHeader->ip_sum=0x0000;
147         csum_ip = ip_checksum((char*)ipHeader, IPH_HL(ipHeader));
148         ipHeader->ip_sum=csum_ip;
149
150       if ((encapsulationUdpData[0] & 0xf0) == 0x60) {
151         dest.sll_protocol = htons(ETH_P_IPV6);
152         stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len 
153         if(my_TTL_Check)
154                 ip6Header->ip6_hops = (uint8_t) 1; //setting up Hop Limit to 1 to avoid mdns packets flood
155         }
156       // Sven-Ola: Don't know how to handle the "stripped_len is uninitialized" condition, maybe exit(1) is better...?
157       if (0 == stripped_len) return;
158       //TODO: if packet is not IP die here
159       
160       if (stripped_len > len) {
161         //OLSR_DEBUG(LOG_PLUGINS, "MDNS: Stripped len bigger than len ??\n");
162         }
163       dest.sll_ifindex = if_nametoindex(walker->ifName);
164       dest.sll_halen = IFHWADDRLEN;
165
166       /* Use all-ones as destination MAC address. When the IP destination is
167        * a multicast address, the destination MAC address should normally also
168        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
169        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
170        * seem to matter when the destination MAC address is set to all-ones
171        * in that case. */
172       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
173       
174       if(walker->isActive == 0) {            //Don't forward packet if isn't master router
175        OLSR_PRINTF(1,"Not forwarding mDNS packet to interface %s because this router is not master\n",walker->ifName);
176        return;
177        }
178       nBytesWritten = sendto(walker->capturingSkfd, encapsulationUdpData, stripped_len, 0, (struct sockaddr *)&dest, sizeof(dest));
179       if (nBytesWritten != stripped_len) {
180         BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
181       } else {
182
183         //OLSR_PRINTF(
184         //  2,
185         //  "%s: --> unpacked and forwarded on \"%s\"\n",
186         //  PLUGIN_NAME_SHORT,
187         //  walker->ifName);
188       }
189     }                           /* if (walker->olsrIntf == NULL) */
190   }
191 }                               /* PacketReceivedFromOLSR */
192
193
194 bool
195 olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr)
196 {
197   union olsr_ip_addr originator;
198   int size;
199   //OLSR_DEBUG(LOG_PLUGINS, "MDNS PLUGIN: Received msg in parser\n");
200   /* Fetch the originator of the messsage */
201   if (olsr_cnf->ip_version == AF_INET) {
202     memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
203     size = ntohs(m->v4.olsr_msgsize);
204   } else {
205     memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
206     size = ntohs(m->v6.olsr_msgsize);
207   }
208
209   /* Check if message originated from this node.
210    *         If so - back off */
211   if (ipequal(&originator, &olsr_cnf->main_addr))
212     return false;
213
214   /* Check that the neighbor this message was received from is symmetric.
215    *         If not - back off*/
216   if (check_neighbor_link(ipaddr) != SYM_LINK) {
217     //struct ipaddr_str strbuf;
218     //OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
219     return false;
220   }
221
222   if (olsr_cnf->ip_version == AF_INET) {
223     PacketReceivedFromOLSR((unsigned char *)&m->v4.message, size - 12);
224   } else {
225     PacketReceivedFromOLSR((unsigned char *)&m->v6.message, size - 12 - 96);
226   }
227 //forward the message
228 return true;
229 }
230
231 //Sends a packet in the OLSR network
232 void
233 olsr_mdns_gen(unsigned char *packet, int len)
234 {
235   /* send buffer: huge */
236   char buffer[10240];
237   int aligned_size;
238   union olsr_message *message = (union olsr_message *)buffer;
239   struct interface *ifn;
240   
241   aligned_size=len;
242
243 if ((aligned_size % 4) != 0) {
244     aligned_size = (aligned_size - (aligned_size % 4)) + 4;
245   }
246
247   /* fill message */
248   if (olsr_cnf->ip_version == AF_INET) {
249     /* IPv4 */
250     message->v4.olsr_msgtype = MESSAGE_TYPE;
251     message->v4.olsr_vtime = reltime_to_me(MDNS_VALID_TIME * MSEC_PER_SEC);
252     memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
253     //message->v4.ttl = MAX_TTL;
254     if (my_MDNS_TTL) message->v4.ttl = my_MDNS_TTL;
255     else message->v4.ttl = MAX_TTL;
256     message->v4.hopcnt = 0;
257     message->v4.seqno = htons(get_msg_seqno());
258
259     message->v4.olsr_msgsize = htons(aligned_size + 12);
260
261     memset(&message->v4.message, 0, aligned_size);
262     memcpy(&message->v4.message, packet, len);
263     aligned_size = aligned_size + 12;
264   } else {
265     /* IPv6 */
266     message->v6.olsr_msgtype = MESSAGE_TYPE;
267     message->v6.olsr_vtime = reltime_to_me(MDNS_VALID_TIME * MSEC_PER_SEC);
268     memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
269     //message->v6.ttl = MAX_TTL;
270     if (my_MDNS_TTL) message->v6.ttl = my_MDNS_TTL;
271     else message->v6.ttl = MAX_TTL;
272     message->v6.hopcnt = 0;
273     message->v6.seqno = htons(get_msg_seqno());
274
275     message->v6.olsr_msgsize = htons(aligned_size + 12 + 96);
276     memset(&message->v6.message, 0, aligned_size);
277     memcpy(&message->v6.message, packet, len);
278     aligned_size = aligned_size + 12 + 96;
279   }
280
281   /* looping trough interfaces */
282  for (ifn = ifnet; ifn; ifn = ifn->int_next) {
283     //OLSR_PRINTF(1, "MDNS PLUGIN: Generating packet - [%s]\n", ifn->int_name);
284
285     if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
286       /* send data and try again */
287       net_output(ifn);
288       if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
289         //OLSR_PRINTF(1, "MDNS PLUGIN: could not send on interface: %s\n", ifn->int_name);
290       }
291     }
292   }
293 }
294
295 /* -------------------------------------------------------------------------
296  * Function   : BmfPError
297  * Description: Prints an error message at OLSR debug level 1.
298  *              First the plug-in name is printed. Then (if format is not NULL
299  *              and *format is not empty) the arguments are printed, followed
300  *              by a colon and a blank. Then the message and a new-line.
301  * Input      : format, arguments
302  * Output     : none
303  * Return     : none
304  * Data Used  : none
305  * ------------------------------------------------------------------------- */
306
307 void
308 BmfPError(const char *format, ...)
309 {
310 #define MAX_STR_DESC 255
311   char strDesc[MAX_STR_DESC];
312
313 #if !defined REMOVE_LOG_DEBUG
314   //char *stringErr = strerror(errno);
315 #endif /* !defined REMOVE_LOG_DEBUG */
316   /* Rely on short-circuit boolean evaluation */
317   if (format == NULL || *format == '\0') {
318     //OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", PLUGIN_NAME, stringErr);
319   } else {
320     va_list arglist;
321
322     va_start(arglist, format);
323     vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
324     va_end(arglist);
325
326     strDesc[MAX_STR_DESC - 1] = '\0';   /* Ensures null termination */
327
328     //OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", strDesc, stringErr);
329   }
330 }                               /* BmfPError */
331
332 /* -------------------------------------------------------------------------
333  * Function   : MainAddressOf
334  * Description: Lookup the main address of a node
335  * Input      : ip - IP address of the node
336  * Output     : none
337  * Return     : The main IP address of the node
338  * Data Used  : none
339  * ------------------------------------------------------------------------- */
340 union olsr_ip_addr *
341 MainAddressOf(union olsr_ip_addr *ip)
342 {
343   union olsr_ip_addr *result;
344
345   /* TODO: mid_lookup_main_addr() is not thread-safe! */
346   result = mid_lookup_main_addr(ip);
347   if (result == NULL) {
348     result = ip;
349   }
350   return result;
351 }                               /* MainAddressOf */
352
353 int
354 AddFilteredHost(const char *FilteredHost, void *data __attribute__ ((unused)), 
355                 set_plugin_parameter_addon addon __attribute__ ((unused))){
356
357   int res = 0;
358   struct FilteredHost *tmp;
359   tmp = (struct FilteredHost *) malloc(sizeof(struct FilteredHost));
360   listbackport_init_node(&tmp->list);
361
362   if(FHListInit == 0){
363     listbackport_init_head(&ListOfFilteredHosts);
364     FHListInit = 1;
365   }
366
367   if(olsr_cnf->ip_version == AF_INET){
368     res = inet_pton(AF_INET, FilteredHost, &tmp->host.v4);
369     if(res > 0){
370       listbackport_add_tail(&ListOfFilteredHosts, &tmp->list);
371     }
372     else
373       free(tmp);
374   }
375   else{
376     res = inet_pton(AF_INET6, FilteredHost, &tmp->host.v6);
377     if(res > 0)
378       listbackport_add_tail(&ListOfFilteredHosts, &tmp->list);
379     else
380       free(tmp);
381   }
382
383   return 0;
384 }
385
386 int
387 isInFilteredList(union olsr_ip_addr *src){
388
389   struct FilteredHost *tmp, *iterator;
390   struct ipaddr_str buf1;
391   struct ipaddr_str buf2;
392   
393   if(FHListInit == 0){
394     listbackport_init_head(&ListOfFilteredHosts);
395     FHListInit = 1;
396   }
397
398
399   if(listbackport_is_empty(&ListOfFilteredHosts)) {
400     OLSR_PRINTF(2,"Accept packet captured because of filtered hosts ACL: List Empty\n");
401     return 0;
402   }
403
404   OLSR_FOR_ALL_FILTEREDNODES_ENTRIES(tmp, iterator){
405     OLSR_PRINTF(2, "Checking host: %s against list entry: %s\n", olsr_ip_to_string(&buf1, src), olsr_ip_to_string(&buf2, &tmp->host) );
406     if(olsr_cnf->ip_version == AF_INET){
407       if(memcmp(&tmp->host.v4, &src->v4, sizeof(struct in_addr)) == 0)
408         return 1;
409     }
410     else{
411       if(memcmp(&tmp->host.v6, &src->v6, sizeof(struct in6_addr)) == 0)
412         return 1;
413     }
414   }
415
416   OLSR_PRINTF(2,"Accept packet captured because of filtered hosts ACL: Did not find any match in list\n");
417   return 0;
418 }
419
420 /* -------------------------------------------------------------------------
421  * Function   : BmfPacketCaptured
422  * Description: Handle a captured IP packet
423  * Input      : intf - the network interface on which the packet was captured
424  *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
425  *                PACKET_BROADCAST or PACKET_MULTICAST.
426  *              encapsulationUdpData - space for the encapsulation header, followed by
427  *                the captured IP packet
428  * Output     : none
429  * Return     : none
430  * Data Used  : BmfInterfaces
431  * Notes      : The IP packet is assumed to be captured on a socket of family
432  *              PF_PACKET and type SOCK_DGRAM (cooked).
433  * ------------------------------------------------------------------------- */
434 static void
435 BmfPacketCaptured(
436                    //struct TBmfInterface* intf,
437                    //unsigned char sllPkttype,
438                    unsigned char *encapsulationUdpData, int nBytes)
439 {
440   union olsr_ip_addr dst;              /* Destination IP address in captured packet */
441   union olsr_ip_addr src;              
442   struct ip *ipHeader;                 /* The IP header inside the captured IP packet */
443   struct ip6_hdr *ipHeader6;           /* The IP header inside the captured IP packet */
444   struct udphdr *udpHeader;
445   u_int16_t destPort;
446
447   if ((encapsulationUdpData[0] & 0xf0) == 0x40) {       //IPV4
448
449     ipHeader = (struct ip *)ARM_NOWARN_ALIGN(encapsulationUdpData);
450
451     dst.v4 = ipHeader->ip_dst;
452     src.v4 = ipHeader->ip_src;
453
454     /* Only forward multicast packets. If configured, also forward local broadcast packets */
455     if (IsMulticast(&dst)) {
456       /* continue */
457     } else {
458       return;
459     }
460     if (ipHeader->ip_p != SOL_UDP) {
461       /* Not UDP */
462       //OLSR_PRINTF(1,"NON UDP PACKET\n");
463       return;                   /* for */
464     }
465     udpHeader = (struct udphdr *)ARM_NOWARN_ALIGN(encapsulationUdpData + GetIpHeaderLength(encapsulationUdpData));
466     destPort = ntohs(udpHeader->dest);
467     if (destPort != 5353) {
468       return;
469     }
470     if(my_TTL_Check) {
471         if(((u_int8_t) ipHeader->ip_ttl) <= ((u_int8_t) 1)) {   // Discard mdns packet with TTL limit 1 or less
472         OLSR_PRINTF(1,"Discarding packet captured with TTL = 1\n");
473         return;
474         }
475     }
476
477     if (isInFilteredList(&src)) {
478       OLSR_PRINTF(1,"Discarding packet captured because of filtered hosts ACL\n");
479       return;
480     }
481
482   }                             //END IPV4
483
484   else if ((encapsulationUdpData[0] & 0xf0) == 0x60) {  //IPv6
485
486     ipHeader6 = (struct ip6_hdr *)ARM_NOWARN_ALIGN(encapsulationUdpData);
487
488     //TODO: mettere dentro src.v6 l'indirizzo IPv6
489
490     if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)  //Multicast
491     {
492       //Continua
493     } else {
494       return;                   //not multicast
495     }
496     if (ipHeader6->ip6_nxt != SOL_UDP) {
497       /* Not UDP */
498       //OLSR_PRINTF(1,"NON UDP PACKET\n");
499       return;                   /* for */
500     }
501     udpHeader = (struct udphdr *)ARM_NOWARN_ALIGN(encapsulationUdpData + 40);
502     destPort = ntohs(udpHeader->dest);
503     if (destPort != 5353) {
504       return;
505     }
506     if(my_TTL_Check) {
507         if(((uint8_t) ipHeader6->ip6_hops) <= ((uint8_t) 1)) { // Discard mdns packet with hop limit 1 or less
508         OLSR_PRINTF(1,"Discarding packet captured with TTL = 1\n");
509         return;
510         }
511         }
512   
513     if (isInFilteredList(&src)) {
514       OLSR_PRINTF(1,"Discarding packet captured because of filtered hosts ACL\n");
515       return;
516     }
517
518   }                             //END IPV6
519   else
520     return;                     //Is not IP packet
521
522   /* Check if the frame is captured on an OLSR-enabled interface */
523   //isFromOlsrIntf = (intf->olsrIntf != NULL); TODO: put again this check
524
525   // send the packet to OLSR forward mechanism
526   olsr_mdns_gen(encapsulationUdpData, nBytes);
527 }                               /* BmfPacketCaptured */
528
529
530 /* -------------------------------------------------------------------------
531  * Function   : DoMDNS
532  * Description: This function is registered with the OLSR scheduler and called when something is captured
533  * Input      : none
534  * Output     : none
535  * Return     : none
536  * Data Used  :
537  * ------------------------------------------------------------------------- */
538 void
539 DoMDNS(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
540 {
541   unsigned char rxBuffer[BMF_BUFFER_SIZE];
542   if (skfd >= 0) {
543     struct sockaddr_ll pktAddr;
544     socklen_t addrLen = sizeof(pktAddr);
545     int nBytes;
546     unsigned char *ipPacket;
547     struct TBmfInterface *walker;
548
549     /* Receive the captured Ethernet frame, leaving space for the BMF
550      * encapsulation header */
551     ipPacket = GetIpPacket(rxBuffer);
552     nBytes = recvfrom(skfd, ipPacket, BMF_BUFFER_SIZE,  //TODO: understand how to change this
553                       0, (struct sockaddr *)&pktAddr, &addrLen);
554     if (nBytes < 0) {
555
556       return;                   /* for */
557     }
558
559     /* if (nBytes < 0) */
560     /* Check if the number of received bytes is large enough for an IP
561      * packet which contains at least a minimum-size IP header.
562      * Note: There is an apparent bug in the packet socket implementation in
563      * combination with VLAN interfaces. On a VLAN interface, the value returned
564      * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
565      * returned on a non-VLAN interface, for the same ethernet frame. */
566     if (nBytes < (int)sizeof(struct ip)) {
567       ////OLSR_PRINTF(
568       //              1,
569       //              "%s: captured frame too short (%d bytes) on \"%s\"\n",
570       //              PLUGIN_NAME,
571       //              nBytes,
572       //              walker->ifName);
573
574       return;                   /* for */
575     }
576
577     for(walker = BmfInterfaces; walker != NULL; walker = walker->next){ //if the router isn't the master for this interface
578       if(skfd == walker->capturingSkfd && walker->isActive == 0) {      //discard mdns packets
579          OLSR_PRINTF(1,"Not capturing mDNS packet from interface %s because this router is not master\n",walker->ifName);
580          return;
581       }
582     }
583
584     if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
585         pktAddr.sll_pkttype == PACKET_MULTICAST || pktAddr.sll_pkttype == PACKET_BROADCAST) {
586       /* A multicast or broadcast packet was captured */
587
588       ////OLSR_PRINTF(
589       //              1,
590       //              "%s: captured frame (%d bytes) on \"%s\"\n",
591       //              PLUGIN_NAME,
592       //              nBytes,
593       //              walker->ifName);
594       //BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
595       BmfPacketCaptured(ipPacket, nBytes);
596
597     }                           /* if (pktAddr.sll_pkttype == ...) */
598   }                             /* if (skfd >= 0 && (FD_ISSET...)) */
599 }                               /* DoMDNS */
600
601 int
602 InitMDNS(struct interface *skipThisIntf)
603 {
604   //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
605   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
606   //Creates captures sockets and register them to the OLSR scheduler
607   CreateBmfNetworkInterfaces(skipThisIntf);
608   InitRouterList(NULL);
609
610   return 1;
611 }                               /* InitMDNS */
612
613 /* -------------------------------------------------------------------------
614  * Function   : CloseMDNS
615  * Description: Close the MDNS plugin and clean up
616  * Input      : none
617  * Output     : none
618  * Return     : none
619  * Data Used  :
620  * ------------------------------------------------------------------------- */
621 void
622 CloseMDNS(void)
623 {
624   CloseBmfNetworkInterfaces();
625 }
626
627 void DoElection(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
628 {
629   static const char * rxBufferPrefix = "$REP";
630   static const ssize_t rxBufferPrefixLength = 4;
631   unsigned char rxBuffer[HELLO_BUFFER_SIZE];
632   ssize_t rxCount;
633   union olsr_sockaddr sender;
634   socklen_t senderSize = sizeof(sender);
635   struct RtElHelloPkt *rcvPkt;
636   struct RouterListEntry *listEntry;
637   struct RouterListEntry6 *listEntry6;
638
639   OLSR_PRINTF(1,"Packet Received \n");
640
641   if (skfd >= 0) {
642     memset(&sender, 0, senderSize);
643     rxCount = recvfrom(skfd, &rxBuffer[0], (sizeof(rxBuffer) - 1), 0,
644                 (struct sockaddr *)&sender, &senderSize);
645     if(rxCount < 0){
646       BmfPError("Receive error in %s, ignoring message.", __func__);
647       return;
648     }
649
650   /* make sure the string is null terminated */
651   rxBuffer[rxCount] = '\0';
652
653   /* do not process when this message doesn't start with $REP */
654   if ((rxCount < rxBufferPrefixLength) || (strncmp((char *) rxBuffer,
655                   rxBufferPrefix, rxBufferPrefixLength) != 0))
656     return;
657
658   if ( rxCount < (int)sizeof(struct RtElHelloPkt))
659     return;                                     // too small to be a hello pkt
660   else
661     rcvPkt = (struct RtElHelloPkt *)ARM_NOWARN_ALIGN(rxBuffer);
662
663   if (rcvPkt->ipFamily == AF_INET){
664     listEntry = (struct RouterListEntry *)malloc(sizeof(struct RouterListEntry));
665     if(ParseElectionPacket(rcvPkt, listEntry, skfd)){
666       OLSR_PRINTF(1,"processing ipv4 packet \n");
667       if(UpdateRouterList(listEntry))
668         free(listEntry);
669     }
670     else{
671       free(listEntry);
672       return;                                   //packet not valid
673     }
674   }
675   else{
676     listEntry6 = (struct RouterListEntry6 *)malloc(sizeof(struct RouterListEntry6));
677     if(ParseElectionPacket6(rcvPkt, listEntry6, skfd)){
678       OLSR_PRINTF(1,"processing ipv6 packet");
679       if(UpdateRouterList6(listEntry6))
680         free(listEntry6);
681     }
682     else{
683       free(listEntry6);
684       return;                                   //packet not valid
685     }
686   }
687   
688   }
689  return;
690 }