2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
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() */
59 #include <netinet/in.h>
60 #include <netinet/ip6.h>
63 #include "plugin_util.h" /* set_plugin_int */
64 #include "defs.h" /* olsr_cnf, //OLSR_PRINTF */
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 */
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. */
78 /* -------------------------------------------------------------------------
79 * Function : PacketReceivedFromOLSR
80 * Description: Handle a received packet from a OLSR message
81 * Input : ipPacket into an unsigned char and the lenght of the packet
84 * Data Used : BmfInterfaces
85 * ------------------------------------------------------------------------- */
87 PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
89 struct ip *ipHeader; /* IP header inside the encapsulated IP packet */
90 struct ip6_hdr *ip6Header; /* IP header inside the encapsulated IP packet */
91 //union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
92 //union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
93 struct TBmfInterface *walker;
95 ipHeader = (struct ip *)ARM_NOWARN_ALIGN(encapsulationUdpData);
96 ip6Header = (struct ip6_hdr *)ARM_NOWARN_ALIGN(encapsulationUdpData);
98 //mcSrc.v4 = ipHeader->ip_src;
99 //mcDst.v4 = ipHeader->ip_dst;
100 //OLSR_DEBUG(LOG_PLUGINS, "MDNS PLUGIN got packet from OLSR message\n");
103 /* Check with each network interface what needs to be done on it */
104 for (walker = BmfInterfaces; walker != NULL; walker = walker->next) {
105 /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
106 if (walker->olsrIntf == NULL) {
108 struct sockaddr_ll dest;
110 memset(&dest, 0, sizeof(dest));
111 dest.sll_family = AF_PACKET;
112 if ((encapsulationUdpData[0] & 0xf0) == 0x40) {
113 dest.sll_protocol = htons(ETH_P_IP);
114 stripped_len = ntohs(ipHeader->ip_len);
116 if ((encapsulationUdpData[0] & 0xf0) == 0x60) {
117 dest.sll_protocol = htons(ETH_P_IPV6);
118 stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len
120 // Sven-Ola: Don't know how to handle the "stripped_len is uninitialized" condition, maybe exit(1) is better...?
121 if (0 == stripped_len) return;
122 //TODO: if packet is not IP die here
124 if (stripped_len > len) {
125 //OLSR_DEBUG(LOG_PLUGINS, "MDNS: Stripped len bigger than len ??\n");
127 dest.sll_ifindex = if_nametoindex(walker->ifName);
128 dest.sll_halen = IFHWADDRLEN;
130 /* Use all-ones as destination MAC address. When the IP destination is
131 * a multicast address, the destination MAC address should normally also
132 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
133 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
134 * seem to matter when the destination MAC address is set to all-ones
136 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
138 nBytesWritten = sendto(walker->capturingSkfd, encapsulationUdpData, stripped_len, 0, (struct sockaddr *)&dest, sizeof(dest));
139 if (nBytesWritten != stripped_len) {
140 BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
145 // "%s: --> unpacked and forwarded on \"%s\"\n",
146 // PLUGIN_NAME_SHORT,
149 } /* if (walker->olsrIntf == NULL) */
151 } /* PacketReceivedFromOLSR */
155 olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr)
157 union olsr_ip_addr originator;
159 //OLSR_DEBUG(LOG_PLUGINS, "MDNS PLUGIN: Received msg in parser\n");
160 /* Fetch the originator of the messsage */
161 if (olsr_cnf->ip_version == AF_INET) {
162 memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
163 size = ntohs(m->v4.olsr_msgsize);
165 memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
166 size = ntohs(m->v6.olsr_msgsize);
169 /* Check if message originated from this node.
170 * If so - back off */
171 if (ipequal(&originator, &olsr_cnf->main_addr))
174 /* Check that the neighbor this message was received from is symmetric.
175 * If not - back off*/
176 if (check_neighbor_link(ipaddr) != SYM_LINK) {
177 //struct ipaddr_str strbuf;
178 //OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
182 if (olsr_cnf->ip_version == AF_INET) {
183 PacketReceivedFromOLSR((unsigned char *)&m->v4.message, size - 12);
185 PacketReceivedFromOLSR((unsigned char *)&m->v6.message, size - 12 - 96);
187 //forward the message
191 //Sends a packet in the OLSR network
193 olsr_mdns_gen(unsigned char *packet, int len)
195 /* send buffer: huge */
198 union olsr_message *message = (union olsr_message *)buffer;
199 struct interface *ifn;
203 if ((aligned_size % 4) != 0) {
204 aligned_size = (aligned_size - (aligned_size % 4)) + 4;
208 if (olsr_cnf->ip_version == AF_INET) {
210 message->v4.olsr_msgtype = MESSAGE_TYPE;
211 message->v4.olsr_vtime = reltime_to_me(MDNS_VALID_TIME * MSEC_PER_SEC);
212 memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
213 //message->v4.ttl = MAX_TTL;
214 if (my_MDNS_TTL) message->v4.ttl = my_MDNS_TTL;
215 else message->v4.ttl = MAX_TTL;
216 message->v4.hopcnt = 0;
217 message->v4.seqno = htons(get_msg_seqno());
219 message->v4.olsr_msgsize = htons(aligned_size + 12);
221 memset(&message->v4.message, 0, aligned_size);
222 memcpy(&message->v4.message, packet, len);
223 aligned_size = aligned_size + 12;
226 message->v6.olsr_msgtype = MESSAGE_TYPE;
227 message->v6.olsr_vtime = reltime_to_me(MDNS_VALID_TIME * MSEC_PER_SEC);
228 memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
229 //message->v6.ttl = MAX_TTL;
230 if (my_MDNS_TTL) message->v6.ttl = my_MDNS_TTL;
231 else message->v6.ttl = MAX_TTL;
232 message->v6.hopcnt = 0;
233 message->v6.seqno = htons(get_msg_seqno());
235 message->v6.olsr_msgsize = htons(aligned_size + 12 + 96);
236 memset(&message->v6.message, 0, aligned_size);
237 memcpy(&message->v6.message, packet, len);
238 aligned_size = aligned_size + 12 + 96;
241 /* looping trough interfaces */
242 for (ifn = ifnet; ifn; ifn = ifn->int_next) {
243 //OLSR_PRINTF(1, "MDNS PLUGIN: Generating packet - [%s]\n", ifn->int_name);
245 if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
246 /* send data and try again */
248 if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
249 //OLSR_PRINTF(1, "MDNS PLUGIN: could not send on interface: %s\n", ifn->int_name);
255 /* -------------------------------------------------------------------------
256 * Function : BmfPError
257 * Description: Prints an error message at OLSR debug level 1.
258 * First the plug-in name is printed. Then (if format is not NULL
259 * and *format is not empty) the arguments are printed, followed
260 * by a colon and a blank. Then the message and a new-line.
261 * Input : format, arguments
265 * ------------------------------------------------------------------------- */
268 BmfPError(const char *format, ...)
270 #define MAX_STR_DESC 255
271 char strDesc[MAX_STR_DESC];
273 #if !defined REMOVE_LOG_DEBUG
274 //char *stringErr = strerror(errno);
276 /* Rely on short-circuit boolean evaluation */
277 if (format == NULL || *format == '\0') {
278 //OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", PLUGIN_NAME, stringErr);
282 va_start(arglist, format);
283 vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
286 strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
288 //OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", strDesc, stringErr);
292 /* -------------------------------------------------------------------------
293 * Function : MainAddressOf
294 * Description: Lookup the main address of a node
295 * Input : ip - IP address of the node
297 * Return : The main IP address of the node
299 * ------------------------------------------------------------------------- */
301 MainAddressOf(union olsr_ip_addr *ip)
303 union olsr_ip_addr *result;
305 /* TODO: mid_lookup_main_addr() is not thread-safe! */
306 result = mid_lookup_main_addr(ip);
307 if (result == NULL) {
311 } /* MainAddressOf */
314 /* -------------------------------------------------------------------------
315 * Function : BmfPacketCaptured
316 * Description: Handle a captured IP packet
317 * Input : intf - the network interface on which the packet was captured
318 * sllPkttype - the type of packet. Either PACKET_OUTGOING,
319 * PACKET_BROADCAST or PACKET_MULTICAST.
320 * encapsulationUdpData - space for the encapsulation header, followed by
321 * the captured IP packet
324 * Data Used : BmfInterfaces
325 * Notes : The IP packet is assumed to be captured on a socket of family
326 * PF_PACKET and type SOCK_DGRAM (cooked).
327 * ------------------------------------------------------------------------- */
330 //struct TBmfInterface* intf,
331 //unsigned char sllPkttype,
332 unsigned char *encapsulationUdpData, int nBytes)
334 union olsr_ip_addr dst; /* Destination IP address in captured packet */
335 struct ip *ipHeader; /* The IP header inside the captured IP packet */
336 struct ip6_hdr *ipHeader6; /* The IP header inside the captured IP packet */
337 struct udphdr *udpHeader;
340 if ((encapsulationUdpData[0] & 0xf0) == 0x40) { //IPV4
342 ipHeader = (struct ip *)ARM_NOWARN_ALIGN(encapsulationUdpData);
344 dst.v4 = ipHeader->ip_dst;
346 /* Only forward multicast packets. If configured, also forward local broadcast packets */
347 if (IsMulticast(&dst)) {
352 if (ipHeader->ip_p != SOL_UDP) {
354 //OLSR_PRINTF(1,"NON UDP PACKET\n");
357 udpHeader = (struct udphdr *)ARM_NOWARN_ALIGN(encapsulationUdpData + GetIpHeaderLength(encapsulationUdpData));
358 destPort = ntohs(udpHeader->dest);
359 if (destPort != 5353) {
364 else if ((encapsulationUdpData[0] & 0xf0) == 0x60) { //IPv6
366 ipHeader6 = (struct ip6_hdr *)ARM_NOWARN_ALIGN(encapsulationUdpData);
367 if (ipHeader6->ip6_dst.s6_addr[0] == 0xff) //Multicast
371 return; //not multicast
373 if (ipHeader6->ip6_nxt != SOL_UDP) {
375 //OLSR_PRINTF(1,"NON UDP PACKET\n");
378 udpHeader = (struct udphdr *)ARM_NOWARN_ALIGN(encapsulationUdpData + 40);
379 destPort = ntohs(udpHeader->dest);
380 if (destPort != 5353) {
385 return; //Is not IP packet
387 /* Check if the frame is captured on an OLSR-enabled interface */
388 //isFromOlsrIntf = (intf->olsrIntf != NULL); TODO: put again this check
390 // send the packet to OLSR forward mechanism
391 olsr_mdns_gen(encapsulationUdpData, nBytes);
392 } /* BmfPacketCaptured */
395 /* -------------------------------------------------------------------------
397 * Description: This function is registered with the OLSR scheduler and called when something is captured
402 * ------------------------------------------------------------------------- */
404 DoMDNS(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
406 unsigned char rxBuffer[BMF_BUFFER_SIZE];
408 struct sockaddr_ll pktAddr;
409 socklen_t addrLen = sizeof(pktAddr);
411 unsigned char *ipPacket;
413 /* Receive the captured Ethernet frame, leaving space for the BMF
414 * encapsulation header */
415 ipPacket = GetIpPacket(rxBuffer);
416 nBytes = recvfrom(skfd, ipPacket, BMF_BUFFER_SIZE, //TODO: understand how to change this
417 0, (struct sockaddr *)&pktAddr, &addrLen);
423 /* if (nBytes < 0) */
424 /* Check if the number of received bytes is large enough for an IP
425 * packet which contains at least a minimum-size IP header.
426 * Note: There is an apparent bug in the packet socket implementation in
427 * combination with VLAN interfaces. On a VLAN interface, the value returned
428 * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
429 * returned on a non-VLAN interface, for the same ethernet frame. */
430 if (nBytes < (int)sizeof(struct ip)) {
433 // "%s: captured frame too short (%d bytes) on \"%s\"\n",
441 if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
442 pktAddr.sll_pkttype == PACKET_MULTICAST || pktAddr.sll_pkttype == PACKET_BROADCAST) {
443 /* A multicast or broadcast packet was captured */
447 // "%s: captured frame (%d bytes) on \"%s\"\n",
451 //BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
452 BmfPacketCaptured(ipPacket, nBytes);
454 } /* if (pktAddr.sll_pkttype == ...) */
455 } /* if (skfd >= 0 && (FD_ISSET...)) */
459 InitMDNS(struct interface *skipThisIntf)
463 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
464 olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
465 //Creates captures sockets and register them to the OLSR scheduler
466 CreateBmfNetworkInterfaces(skipThisIntf);
471 /* -------------------------------------------------------------------------
472 * Function : CloseMDNS
473 * Description: Close the MDNS plugin and clean up
478 * ------------------------------------------------------------------------- */
482 CloseBmfNetworkInterfaces();