2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
\r
3 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
\r
4 * All rights reserved.
\r
6 * Redistribution and use in source and binary forms, with or without
\r
7 * modification, are permitted provided that the following conditions
\r
10 * * Redistributions of source code must retain the above copyright
\r
11 * notice, this list of conditions and the following disclaimer.
\r
12 * * Redistributions in binary form must reproduce the above copyright
\r
13 * notice, this list of conditions and the following disclaimer in
\r
14 * the documentation and/or other materials provided with the
\r
16 * * Neither the name of olsr.org, olsrd nor the names of its
\r
17 * contributors may be used to endorse or promote products derived
\r
18 * from this software without specific prior written permission.
\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
\r
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
\r
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
\r
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
\r
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
\r
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
\r
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
31 * POSSIBILITY OF SUCH DAMAGE.
\r
33 * Visit http://www.olsr.org for more information.
\r
35 * If you find this software useful feel free to make a donation
\r
36 * to the project. For more information see the website or contact
\r
37 * the copyright holders.
\r
44 /* System includes */
\r
45 #include <stddef.h> /* NULL */
\r
46 #include <sys/types.h> /* ssize_t */
\r
47 #include <string.h> /* strerror() */
\r
48 #include <stdarg.h> /* va_list, va_start, va_end */
\r
49 #include <errno.h> /* errno */
\r
50 #include <assert.h> /* assert() */
\r
53 #include <linux/if_ether.h> /* ETH_P_IP */
\r
54 #include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */
\r
55 //#include <pthread.h> /* pthread_t, pthread_create() */
\r
56 #include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
\r
57 #include <netinet/ip.h> /* struct ip */
\r
58 #include <netinet/udp.h> /* struct udphdr */
\r
59 #include <unistd.h> /* close() */
\r
61 #include <netinet/in.h>
\r
62 #include <netinet/ip6.h>
\r
66 /* OLSRD includes */
\r
67 #include "plugin_util.h" /* set_plugin_int */
\r
68 #include "defs.h" /* olsr_cnf, //OLSR_PRINTF */
\r
70 #include "olsr.h" /* //OLSR_PRINTF */
\r
71 #include "mid_set.h" /* mid_lookup_main_addr() */
\r
72 #include "link_set.h" /* get_best_link_to_neighbor() */
\r
73 #include "net_olsr.h" /* ipequal */
\r
74 #include "log.h" /* Teco: syslog */
\r
77 /* plugin includes */
\r
78 #include "NetworkInterfaces.h" /* NonOlsrInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
\r
79 //#include "Address.h" /* IsMulticast() */
\r
80 #include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
\r
81 #include "PacketHistory.h"
\r
85 int P2pdDuplicateTimeout = P2PD_VALID_TIME;
\r
87 /* List of UDP destination address and port information */
\r
88 struct UdpDestPort * UdpDestPortList = NULL;
\r
90 /* List of filter entries to check for duplicate messages
\r
92 struct node * dupFilterHead = NULL;
\r
93 struct node * dupFilterTail = NULL;
\r
95 clockid_t clockid = CLOCK_MONOTONIC;
\r
97 bool is_broadcast(const struct sockaddr_in addr);
\r
98 bool is_multicast(const struct sockaddr_in addr);
\r
100 /* -------------------------------------------------------------------------
\r
101 * Function : PacketReceivedFromOLSR
\r
102 * Description: Handle a received packet from a OLSR message
\r
103 * Input : ipPacket into an unsigned char and the lenght of the packet
\r
106 * Data Used : BmfInterfaces
\r
107 * ------------------------------------------------------------------------- */
\r
109 PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
\r
111 struct ip *ipHeader; /* IP header inside the encapsulated IP packet */
\r
112 struct ip6_hdr *ip6Header; /* IP header inside the encapsulated IP packet */
\r
113 struct NonOlsrInterface *walker;
\r
114 int stripped_len = 0;
\r
115 unsigned char * ipPacket;
\r
116 uint16_t ipPacketLen;
\r
118 ipHeader = (struct ip *)encapsulationUdpData;
\r
119 ip6Header = (struct ip6_hdr *)encapsulationUdpData;
\r
120 //OLSR_DEBUG(LOG_PLUGINS, "P2PD PLUGIN got packet from OLSR message\n");
\r
122 /* Check for duplicate IP packets now based on a hash */
\r
123 ipPacket = GetIpPacket(encapsulationUdpData);
\r
124 if (IsIpFragment(ipPacket))
\r
128 ipPacketLen = GetIpTotalLength(ipPacket);
\r
130 /* Calculate packet fingerprint */
\r
131 crc32 = PacketCrc32(ipPacket, ipPacketLen);
\r
133 /* Check if this packet was seen recently */
\r
134 if (CheckAndMarkRecentPacket(crc32))
\r
138 "%s: --> discarding: packet is duplicate\n",
\r
139 PLUGIN_NAME_SHORT);
\r
143 PrunePacketHistory(NULL);
\r
145 /* Check with each network interface what needs to be done on it */
\r
146 for (walker = nonOlsrInterfaces; walker != NULL; walker = walker->next) {
\r
147 /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
\r
148 if (walker->olsrIntf == NULL) {
\r
150 struct sockaddr_ll dest;
\r
152 memset(&dest, 0, sizeof(dest));
\r
153 dest.sll_family = AF_PACKET;
\r
154 if ((encapsulationUdpData[0] & 0xf0) == 0x40) {
\r
155 dest.sll_protocol = htons(ETH_P_IP);
\r
156 stripped_len = ntohs(ipHeader->ip_len);
\r
159 if ((encapsulationUdpData[0] & 0xf0) == 0x60) {
\r
160 dest.sll_protocol = htons(ETH_P_IPV6);
\r
161 stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len
\r
164 // Sven-Ola: Don't know how to handle the "stripped_len is uninitialized" condition, maybe exit(1) is better...?
\r
165 if (0 == stripped_len)
\r
168 //TODO: if packet is not IP die here
\r
170 if (stripped_len > len) {
\r
173 dest.sll_ifindex = if_nametoindex(walker->ifName);
\r
174 dest.sll_halen = IFHWADDRLEN;
\r
176 if (olsr_cnf->ip_version == AF_INET) {
\r
177 /* Use all-ones as destination MAC address. When the IP destination is
\r
178 * a multicast address, the destination MAC address should normally also
\r
179 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
\r
180 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
\r
181 * seem to matter when the destination MAC address is set to all-ones
\r
184 if (IsMulticastv4(ipHeader)) {
\r
185 dest.sll_addr[0] = 0x01;
\r
186 dest.sll_addr[1] = 0x00;
\r
187 dest.sll_addr[2] = 0x5E;
\r
188 dest.sll_addr[3] = (ipHeader->ip_dst.s_addr >> 16) & 0x7F;
\r
189 dest.sll_addr[4] = (ipHeader->ip_dst.s_addr >> 8) & 0xFF;
\r
190 dest.sll_addr[5] = ipHeader->ip_dst.s_addr & 0xFF;
\r
191 } else /* if (IsBroadcast(ipHeader)) */ {
\r
192 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
\r
194 } else /*(olsr_cnf->ip_version == AF_INET6) */ {
\r
195 if (IsMulticastv6(ip6Header)) {
\r
196 dest.sll_addr[0] = 0x33;
\r
197 dest.sll_addr[1] = 0x33;
\r
198 dest.sll_addr[2] = ip6Header->ip6_dst.s6_addr[12];
\r
199 dest.sll_addr[3] = ip6Header->ip6_dst.s6_addr[13];
\r
200 dest.sll_addr[4] = ip6Header->ip6_dst.s6_addr[14];
\r
201 dest.sll_addr[5] = ip6Header->ip6_dst.s6_addr[15];
\r
205 nBytesWritten = sendto(walker->capturingSkfd,
\r
206 encapsulationUdpData,
\r
209 (struct sockaddr *)&dest,
\r
211 if (nBytesWritten != stripped_len) {
\r
212 P2pdPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
\r
217 // "%s: --> unpacked and forwarded on \"%s\"\n",
\r
218 // PLUGIN_NAME_SHORT,
\r
219 // walker->ifName);
\r
221 } /* if (walker->olsrIntf == NULL) */
\r
223 } /* PacketReceivedFromOLSR */
\r
225 /* Highest-numbered open socket file descriptor. To be used as first
\r
226 * parameter in calls to select(...). */
\r
227 int HighestSkfd = -1;
\r
229 /* Set of socket file descriptors */
\r
233 p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m)
\r
235 struct node * curr;
\r
240 // Check whether any entries have aged
\r
243 struct DupFilterEntry *filter;
\r
244 struct node * next = curr->next; // Save the current pointer since curr may be destroyed
\r
246 filter = (struct DupFilterEntry*)curr->data;
\r
248 if ((filter->creationtime + P2pdDuplicateTimeout) < now)
\r
249 remove_node(head, tail, curr, true);
\r
251 // Skip to the next element
\r
255 // Now check whether there are any duplicates
\r
256 for (curr = *head; curr; curr = curr->next) {
\r
257 struct DupFilterEntry *filter = (struct DupFilterEntry*)curr->data;
\r
259 if (olsr_cnf->ip_version == AF_INET) {
\r
260 if (filter->address.v4.s_addr == m->v4.originator &&
\r
261 filter->msgtype == m->v4.olsr_msgtype &&
\r
262 filter->seqno == m->v4.seqno) {
\r
265 } else /* if (olsr_cnf->ip_version == AF_INET6) */ {
\r
266 if (memcmp(filter->address.v6.s6_addr,
\r
267 m->v6.originator.s6_addr,
\r
268 sizeof(m->v6.originator.s6_addr)) == 0 &&
\r
269 filter->msgtype == m->v6.olsr_msgtype &&
\r
270 filter->seqno == m->v6.seqno) {
\r
280 p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m)
\r
284 // Store a message into the database
\r
285 struct DupFilterEntry *new_dup = calloc(1, sizeof(struct DupFilterEntry));
\r
286 if (new_dup == NULL) {
\r
287 olsr_printf(1, "P2PD: Out of memory\n");
\r
293 new_dup->creationtime = now;
\r
294 if (olsr_cnf->ip_version == AF_INET) {
\r
295 new_dup->address.v4.s_addr = m->v4.originator;
\r
296 new_dup->msgtype = m->v4.olsr_msgtype;
\r
297 new_dup->seqno = m->v4.seqno;
\r
298 } else /* if (olsr_cnf->ip_version == AF_INET6) */ {
\r
299 memcpy(new_dup->address.v6.s6_addr,
\r
300 m->v6.originator.s6_addr,
\r
301 sizeof(m->v6.originator.s6_addr));
\r
302 new_dup->msgtype = m->v6.olsr_msgtype;
\r
303 new_dup->seqno = m->v6.seqno;
\r
306 // Add the element to the head of the list
\r
307 append_node(head, tail, new_dup);
\r
311 p2pd_is_duplicate_message(union olsr_message *msg)
\r
313 if(p2pd_message_seen(&dupFilterHead, &dupFilterTail, msg)) {
\r
317 p2pd_store_message(&dupFilterHead, &dupFilterTail, msg);
\r
323 olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr __attribute__ ((unused)))
\r
325 union olsr_ip_addr originator;
\r
329 //OLSR_DEBUG(LOG_PLUGINS, "P2PD PLUGIN: Received msg in parser\n");
\r
331 /* Fetch the originator of the messsage */
\r
332 if (olsr_cnf->ip_version == AF_INET) {
\r
333 memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
\r
334 vtime = me_to_reltime(m->v4.olsr_vtime);
\r
335 size = ntohs(m->v4.olsr_msgsize);
\r
337 memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
\r
338 vtime = me_to_reltime(m->v6.olsr_vtime);
\r
339 size = ntohs(m->v6.olsr_msgsize);
\r
342 /* Check if message originated from this node.
\r
343 * If so - back off */
\r
344 if (ipequal(&originator, &olsr_cnf->main_addr))
\r
345 return false; /* Don't forward either */
\r
347 /* Check for duplicate messages for processing */
\r
348 if (p2pd_is_duplicate_message(m))
\r
349 return true; /* Don't process but allow to be forwarded */
\r
351 if (olsr_cnf->ip_version == AF_INET) {
\r
352 PacketReceivedFromOLSR((unsigned char *)&m->v4.message, size - 12);
\r
354 PacketReceivedFromOLSR((unsigned char *)&m->v6.message, size - 12 - 96);
\r
360 //Sends a packet in the OLSR network
\r
362 olsr_p2pd_gen(unsigned char *packet, int len)
\r
364 /* send buffer: huge */
\r
365 char buffer[10240];
\r
367 union olsr_message *message = (union olsr_message *)buffer;
\r
368 struct interface *ifn;
\r
372 if ((aligned_size % 4) != 0) {
\r
373 aligned_size = (aligned_size - (aligned_size % 4)) + 4;
\r
377 if (olsr_cnf->ip_version == AF_INET) {
\r
379 message->v4.olsr_msgtype = P2PD_MESSAGE_TYPE;
\r
380 message->v4.olsr_vtime = reltime_to_me(P2PD_VALID_TIME * MSEC_PER_SEC);
\r
381 memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
\r
382 message->v4.ttl = P2pdTtl ? P2pdTtl : MAX_TTL;
\r
383 message->v4.hopcnt = 0;
\r
384 message->v4.seqno = htons(get_msg_seqno());
\r
385 message->v4.olsr_msgsize = htons(aligned_size + 12);
\r
386 memset(&message->v4.message, 0, aligned_size);
\r
387 memcpy(&message->v4.message, packet, len);
\r
388 aligned_size = aligned_size + 12;
\r
389 } else /* if (olsr_cnf->ip_version == AF_INET6) */ {
\r
391 message->v6.olsr_msgtype = P2PD_MESSAGE_TYPE;
\r
392 message->v6.olsr_vtime = reltime_to_me(P2PD_VALID_TIME * MSEC_PER_SEC);
\r
393 memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
\r
394 message->v6.ttl = P2pdTtl ? P2pdTtl : MAX_TTL;
\r
395 message->v6.hopcnt = 0;
\r
396 message->v6.seqno = htons(get_msg_seqno());
\r
397 message->v6.olsr_msgsize = htons(aligned_size + 12 + 96);
\r
398 memset(&message->v6.message, 0, aligned_size);
\r
399 memcpy(&message->v6.message, packet, len);
\r
400 aligned_size = aligned_size + 12 + 96;
\r
403 /* looping trough interfaces */
\r
404 for (ifn = ifnet; ifn; ifn = ifn->int_next) {
\r
405 //OLSR_PRINTF(1, "P2PD PLUGIN: Generating packet - [%s]\n", ifn->int_name);
\r
407 if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
\r
408 /* send data and try again */
\r
410 if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
\r
411 //OLSR_PRINTF(1, "P2PD PLUGIN: could not send on interface: %s\n", ifn->int_name);
\r
417 /* -------------------------------------------------------------------------
\r
418 * Function : P2pdPError
\r
419 * Description: Prints an error message at OLSR debug level 1.
\r
420 * First the plug-in name is printed. Then (if format is not NULL
\r
421 * and *format is not empty) the arguments are printed, followed
\r
422 * by a colon and a blank. Then the message and a new-line.
\r
423 * Input : format, arguments
\r
427 * ------------------------------------------------------------------------- */
\r
429 P2pdPError(const char *format, ...)
\r
431 #define MAX_STR_DESC 255
\r
432 char strDesc[MAX_STR_DESC];
\r
434 #if !defined REMOVE_LOG_DEBUG
\r
435 char *stringErr = strerror(errno);
\r
438 /* Rely on short-circuit boolean evaluation */
\r
439 if (format == NULL || *format == '\0') {
\r
440 //OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", PLUGIN_NAME, stringErr);
\r
444 va_start(arglist, format);
\r
445 vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
\r
448 strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
\r
450 #if !defined REMOVE_LOG_DEBUG
\r
451 OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", strDesc, stringErr);
\r
456 /* -------------------------------------------------------------------------
\r
457 * Function : MainAddressOf
\r
458 * Description: Lookup the main address of a node
\r
459 * Input : ip - IP address of the node
\r
461 * Return : The main IP address of the node
\r
463 * ------------------------------------------------------------------------- */
\r
464 union olsr_ip_addr *
\r
465 MainAddressOf(union olsr_ip_addr *ip)
\r
467 union olsr_ip_addr *result;
\r
469 /* TODO: mid_lookup_main_addr() is not thread-safe! */
\r
470 result = mid_lookup_main_addr(ip);
\r
471 if (result == NULL) {
\r
475 } /* MainAddressOf */
\r
478 /* -------------------------------------------------------------------------
\r
479 * Function : InUdpDestPortList
\r
480 * Description: Check whether the specified address and port is in the list of
\r
481 * configured UDP destination/port entries
\r
482 * Input : ip_version - IP version to use for this check
\r
483 * addr - address to check for in the list
\r
484 * port - port to check for in the list
\r
486 * Return : true if destination/port combination was found, false otherwise
\r
487 * Data Used : UdpDestPortList
\r
488 * ------------------------------------------------------------------------- */
\r
490 InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port)
\r
492 struct UdpDestPort *walker;
\r
494 for (walker = UdpDestPortList; walker; walker = walker->next) {
\r
495 if (walker->ip_version == ip_version) {
\r
496 if (ip_version == AF_INET) {
\r
497 if (addr->v4.s_addr == walker->address.v4.s_addr &&
\r
498 walker->port == port)
\r
499 return true; // Found so we can stop here
\r
500 } else /* ip_version == AF_INET6 */ {
\r
501 if (memcmp(addr->v6.s6_addr,
\r
502 walker->address.v6.s6_addr,
\r
503 sizeof(addr->v6.s6_addr) == 0) &&
\r
504 walker->port == port)
\r
505 return true; // Found so we can stop here
\r
512 /* -------------------------------------------------------------------------
\r
513 * Function : P2pdPacketCaptured
\r
514 * Description: Handle a captured IP packet
\r
515 * Input : encapsulationUdpData - space for the encapsulation header,
\r
516 * followed by the captured IP packet
\r
517 * nBytes - The number of bytes in the data packet
\r
520 * Data Used : P2pdInterfaces
\r
521 * Notes : The IP packet is assumed to be captured on a socket of family
\r
522 * PF_PACKET and type SOCK_DGRAM (cooked).
\r
523 * ------------------------------------------------------------------------- */
\r
525 P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
\r
527 union olsr_ip_addr src; /* Source IP address in captured packet */
\r
528 union olsr_ip_addr dst; /* Destination IP address in captured packet */
\r
529 union olsr_ip_addr *origIp; /* Main OLSR address of source of captured packet */
\r
530 struct ip *ipHeader; /* The IP header inside the captured IP packet */
\r
531 struct ip6_hdr *ipHeader6; /* The IP header inside the captured IP packet */
\r
532 struct udphdr *udpHeader;
\r
533 u_int16_t destPort;
\r
535 if ((encapsulationUdpData[0] & 0xf0) == 0x40) { //IPV4
\r
537 ipHeader = (struct ip *)encapsulationUdpData;
\r
539 dst.v4 = ipHeader->ip_dst;
\r
541 if (ipHeader->ip_p != SOL_UDP) {
\r
543 //OLSR_PRINTF(1,"NON UDP PACKET\n");
\r
547 // If we're dealing with a fragment we bail out here since there's no valid
\r
548 // UDP header in this message
\r
549 if (IsIpv4Fragment(ipHeader)) {
\r
553 udpHeader = (struct udphdr *)(encapsulationUdpData +
\r
554 GetIpHeaderLength(encapsulationUdpData));
\r
555 destPort = ntohs(udpHeader->dest);
\r
557 if (!InUdpDestPortList(AF_INET, &dst, destPort))
\r
560 else if ((encapsulationUdpData[0] & 0xf0) == 0x60) { //IPv6
\r
562 ipHeader6 = (struct ip6_hdr *)encapsulationUdpData;
\r
564 memcpy(&dst.v6, &ipHeader6->ip6_dst, sizeof(struct in6_addr));
\r
566 if (ipHeader6->ip6_dst.s6_addr[0] == 0xff) //Multicast
\r
570 return; //not multicast
\r
572 if (ipHeader6->ip6_nxt != SOL_UDP) {
\r
574 //OLSR_PRINTF(1,"NON UDP PACKET\n");
\r
578 // Check whether this is a IPv6 fragment
\r
579 if (IsIpv6Fragment(ipHeader6)) {
\r
583 udpHeader = (struct udphdr *)(encapsulationUdpData + 40);
\r
584 destPort = ntohs(udpHeader->dest);
\r
586 if (!InUdpDestPortList(AF_INET6, &dst, destPort))
\r
590 return; //Is not IP packet
\r
593 /* Lookup main address of source in the MID table of OLSR */
\r
594 origIp = MainAddressOf(&src);
\r
596 // send the packet to OLSR forward mechanism
\r
597 olsr_p2pd_gen(encapsulationUdpData, nBytes);
\r
598 } /* P2pdPacketCaptured */
\r
601 /* -------------------------------------------------------------------------
\r
602 * Function : DoP2pd
\r
603 * Description: This function is registered with the OLSR scheduler and called when something is captured
\r
608 * ------------------------------------------------------------------------- */
\r
610 DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
\r
612 unsigned char rxBuffer[P2PD_BUFFER_SIZE];
\r
614 struct sockaddr_ll pktAddr;
\r
615 socklen_t addrLen = sizeof(pktAddr);
\r
617 unsigned char *ipPacket;
\r
619 /* Receive the captured Ethernet frame, leaving space for the BMF
\r
620 * encapsulation header */
\r
621 ipPacket = GetIpPacket(rxBuffer);
\r
622 nBytes = recvfrom(skfd, ipPacket, P2PD_BUFFER_SIZE, //TODO: understand how to change this
\r
623 0, (struct sockaddr *)&pktAddr, &addrLen);
\r
629 /* if (nBytes < 0) */
\r
630 /* Check if the number of received bytes is large enough for an IP
\r
631 * packet which contains at least a minimum-size IP header.
\r
632 * Note: There is an apparent bug in the packet socket implementation in
\r
633 * combination with VLAN interfaces. On a VLAN interface, the value returned
\r
634 * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
\r
635 * returned on a non-VLAN interface, for the same ethernet frame. */
\r
636 if (nBytes < (int)sizeof(struct ip)) {
\r
639 // "%s: captured frame too short (%d bytes) on \"%s\"\n",
\r
642 // walker->ifName);
\r
647 if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
\r
648 pktAddr.sll_pkttype == PACKET_MULTICAST ||
\r
649 pktAddr.sll_pkttype == PACKET_BROADCAST) {
\r
650 /* A multicast or broadcast packet was captured */
\r
652 P2pdPacketCaptured(ipPacket, nBytes);
\r
654 } /* if (pktAddr.sll_pkttype == ...) */
\r
655 } /* if (skfd >= 0 && (FD_ISSET...)) */
\r
658 /* -------------------------------------------------------------------------
\r
659 * Function : InitP2pd
\r
660 * Description: Initialize the P2pd plugin
\r
661 * Input : skipThisInterface - pointer to interface to skip
\r
663 * Return : Always 0
\r
665 * ------------------------------------------------------------------------- */
\r
667 InitP2pd(struct interface *skipThisIntf)
\r
669 // Initialize hash table for hash based duplicate IP packet check
\r
670 InitPacketHistory();
\r
672 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
\r
673 //olsr_parser_add_function(&olsr_parser, PARSER_TYPE,1);
\r
674 olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
\r
676 //Creates captures sockets and register them to the OLSR scheduler
\r
677 CreateNonOlsrNetworkInterfaces(skipThisIntf);
\r
682 /* -------------------------------------------------------------------------
\r
683 * Function : CloseP2pd
\r
684 * Description: Close the P2pd plugin and clean up
\r
689 * ------------------------------------------------------------------------- */
\r
693 CloseNonOlsrNetworkInterfaces();
\r
696 /* -------------------------------------------------------------------------
\r
697 * Function : SetP2pdTtl
\r
698 * Description: Set the TTL for message from this plugin
\r
699 * Input : value - parameter value to evaluate
\r
701 * Return : Always 0
\r
702 * Data Used : P2pdTtl
\r
703 * ------------------------------------------------------------------------- */
\r
705 SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
\r
707 assert(value != NULL);
\r
708 P2pdTtl = atoi(value);
\r
713 bool is_broadcast(const struct sockaddr_in addr)
\r
715 if (addr.sin_addr.s_addr == 0xFFFFFFFF)
\r
721 bool is_multicast(const struct sockaddr_in addr)
\r
723 if ((htonl(addr.sin_addr.s_addr) & 0xE0000000) == 0xE0000000)
\r
729 /* -------------------------------------------------------------------------
\r
730 * Function : AddUdpDestPort
\r
731 * Description: Set the UDP destination/port combination as an entry in the
\r
733 * Input : value - parameter value to evaluate
\r
735 * Return : -1 on error condition, 0 if all is ok
\r
736 * Data Used : UdpDestPortList
\r
737 * ------------------------------------------------------------------------- */
\r
739 AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
\r
741 char destAddr[INET6_ADDRSTRLEN];
\r
744 struct UdpDestPort * new;
\r
745 struct sockaddr_in addr4;
\r
746 struct sockaddr_in6 addr6;
\r
747 int ip_version = AF_INET;
\r
750 assert(value != NULL);
\r
752 // Retrieve the data from the argument string passed
\r
753 memset(destAddr, 0, sizeof(destAddr));
\r
754 num = sscanf(value, "%45s %hd", destAddr, &destPort);
\r
756 olsr_printf(1, "Invalid argument for \"UdpDestPort\"");
\r
760 // Check whether we're dealing with an IPv4 or IPv6 address
\r
761 // When the string contains a ':' we can assume we're dealing with IPv6
\r
762 if (strchr(destAddr, (int)':')) {
\r
763 ip_version = AF_INET6;
\r
766 // Check whether the specified address was either IPv4 multicast,
\r
767 // IPv4 broadcast or IPv6 multicast.
\r
769 switch (ip_version) {
\r
771 res = inet_pton(AF_INET, destAddr, &addr4.sin_addr);
\r
772 if (!is_broadcast(addr4) && !is_multicast(addr4)) {
\r
773 olsr_printf(1, "WARNING: IPv4 address must be multicast or broadcast... ");
\r
777 res = inet_pton(AF_INET6, destAddr, &addr6.sin6_addr);
\r
778 if (addr6.sin6_addr.s6_addr[0] != 0xFF) {
\r
779 olsr_printf(1, "WARNING: IPv6 address must be multicast... ");
\r
784 // Determine whether it is a valid IP address
\r
786 olsr_printf(1, "Invalid address specified for \"UdpDestPort\"");
\r
790 // Create a new entry and link it into the chain
\r
791 new = calloc(1, sizeof(struct UdpDestPort));
\r
793 olsr_printf(1, "P2PD: Out of memory");
\r
797 new->ip_version = ip_version;
\r
798 switch (ip_version) {
\r
800 new->address.v4.s_addr = addr4.sin_addr.s_addr;
\r
803 memcpy(&new->address.v6.s6_addr, &addr6.sin6_addr.s6_addr, sizeof(sizeof(addr6.sin6_addr.s6_addr)));
\r
806 new->port = destPort;
\r
807 new->next = UdpDestPortList;
\r
808 UdpDestPortList = new;
\r
810 // And then we're done
\r