Implementation of duplicate filter and UDP destination address/port filter (intermedi...
authorCaspar van Zon <CHW.van.Zon@mindef.nl>
Thu, 18 Mar 2010 13:26:55 +0000 (14:26 +0100)
committerCaspar van Zon <CHW.van.Zon@mindef.nl>
Thu, 18 Mar 2010 13:26:55 +0000 (14:26 +0100)
lib/p2pd/src/PacketHistory.c
lib/p2pd/src/olsrd_plugin.c
lib/p2pd/src/p2pd.c
lib/p2pd/src/p2pd.h

index 18f1269..3db6490 100644 (file)
@@ -255,7 +255,7 @@ int CheckAndMarkRecentPacket(u_int32_t crc32)
   } /* for */\r
 \r
   /* No duplicate entry found: create one */\r
-  newEntry = olsr_malloc(sizeof(struct TDupEntry), "BMF: TDupEntry");\r
+  newEntry = olsr_malloc(sizeof(struct TDupEntry), "OLSRD P2PD: TDupEntry");\r
   if (newEntry != NULL)\r
   {\r
     newEntry->crc32 = crc32;\r
index fd1ac25..deb3fb9 100644 (file)
@@ -111,6 +111,7 @@ static const struct olsrd_plugin_parameters plugin_parameters[] = {
   {.name = "NonOlsrIf",.set_plugin_parameter = &AddNonOlsrIf,.data = NULL},\r
   {.name = "P2pdTtl", .set_plugin_parameter = &SetP2pdTtl, .data = NULL },\r
   {.name = "UdpDestPort",.set_plugin_parameter = &AddUdpDestPort,.data = NULL},\r
+  {.name = "UseHashFilter",.set_plugin_parameter = &SetP2pdUseHashFilter,.data = NULL},\r
 };\r
 \r
 /* -------------------------------------------------------------------------\r
index 280c64d..438b69a 100644 (file)
 #include "mid_set.h"            /* mid_lookup_main_addr() */\r
 #include "link_set.h"           /* get_best_link_to_neighbor() */\r
 #include "net_olsr.h"           /* ipequal */\r
-#include "log.h"                /* Teco: syslog */\r
 #include "parser.h"\r
 \r
 /* plugin includes */\r
-#include "NetworkInterfaces.h"  /* NonOlsrInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */\r
+#include "NetworkInterfaces.h"  /* NonOlsrInterface,\r
+                                   CreateBmfNetworkInterfaces(),\r
+                                   CloseBmfNetworkInterfaces() */\r
 //#include "Address.h"          /* IsMulticast() */\r
-#include "Packet.h"             /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */\r
+#include "Packet.h"             /* ENCAP_HDR_LEN,\r
+                                   BMF_ENCAP_TYPE,\r
+                                   BMF_ENCAP_LEN etc. */\r
 #include "PacketHistory.h"\r
 #include "dllist.h"\r
 \r
-int P2pdTtl=0;\r
+int P2pdTtl                        = 0;\r
+int P2pdUseHash                    = 0;  /* Switch off hash filter by default */\r
 int P2pdDuplicateTimeout           = P2PD_VALID_TIME;\r
 \r
 /* List of UDP destination address and port information */\r
@@ -96,6 +100,10 @@ clockid_t clockid = CLOCK_MONOTONIC;
 \r
 bool is_broadcast(const struct sockaddr_in addr);\r
 bool is_multicast(const struct sockaddr_in addr);\r
+char * get_ipv4_str(uint32_t address, char *s, size_t maxlen);\r
+char * get_ipv6_str(unsigned char* address, char *s, size_t maxlen);\r
+void dump_packet(unsigned char* packet, int length);\r
+bool check_and_mark_recent_packet(unsigned char *data, int len);\r
 \r
 /* -------------------------------------------------------------------------\r
  * Function   : PacketReceivedFromOLSR\r
@@ -110,41 +118,23 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
 {\r
   struct ip *ipHeader;        /* IP header inside the encapsulated IP packet */\r
   struct ip6_hdr *ip6Header;  /* IP header inside the encapsulated IP packet */\r
+  struct udphdr *udpHeader;\r
   struct NonOlsrInterface *walker;\r
   int stripped_len = 0;\r
-  unsigned char * ipPacket;\r
-  uint16_t ipPacketLen;\r
-  uint32_t crc32;\r
+  union olsr_ip_addr destAddr;\r
+  int destPort;\r
+  bool isInList = false;\r
+\r
   ipHeader = (struct ip *)encapsulationUdpData;\r
   ip6Header = (struct ip6_hdr *)encapsulationUdpData;\r
   //OLSR_DEBUG(LOG_PLUGINS, "P2PD PLUGIN got packet from OLSR message\n");\r
 \r
-  /* Check for duplicate IP packets now based on a hash */\r
-  ipPacket = GetIpPacket(encapsulationUdpData);\r
-  if (IsIpFragment(ipPacket))\r
-  {\r
-    return;\r
-  }\r
-  ipPacketLen = GetIpTotalLength(ipPacket);\r
-\r
-  /* Calculate packet fingerprint */\r
-  crc32 = PacketCrc32(ipPacket, ipPacketLen);\r
-\r
-  /* Check if this packet was seen recently */\r
-  if (CheckAndMarkRecentPacket(crc32))\r
-  {\r
-    OLSR_PRINTF(\r
-      8,\r
-      "%s: --> discarding: packet is duplicate\n",\r
-      PLUGIN_NAME_SHORT);\r
+  if (check_and_mark_recent_packet(encapsulationUdpData, len))\r
     return;\r
-  }\r
-\r
-  PrunePacketHistory(NULL);\r
 \r
   /* Check with each network interface what needs to be done on it */\r
   for (walker = nonOlsrInterfaces; walker != NULL; walker = walker->next) {\r
-    /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */\r
+    /* To a non-OLSR interface: unpack encapsulated IP packet and forward it */\r
     if (walker->olsrIntf == NULL) {\r
       int nBytesWritten;\r
       struct sockaddr_ll dest;\r
@@ -155,21 +145,23 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
         dest.sll_protocol = htons(ETH_P_IP);\r
         stripped_len = ntohs(ipHeader->ip_len);\r
       }\r
-      \r
+\r
       if ((encapsulationUdpData[0] & 0xf0) == 0x60) {\r
         dest.sll_protocol = htons(ETH_P_IPV6);\r
-        stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len \r
+        stripped_len = 40 + ntohs(ip6Header->ip6_plen); // IPv6 Header size (40)\r
+                                                        // + payload_len\r
       }\r
-      \r
-      // Sven-Ola: Don't know how to handle the "stripped_len is uninitialized" condition, maybe exit(1) is better...?\r
+\r
+      // Sven-Ola: Don't know how to handle the "stripped_len is uninitialized"\r
+      // condition, maybe exit(1) is better...?\r
       if (0 == stripped_len)\r
         return;\r
-      \r
+\r
       //TODO: if packet is not IP die here\r
-      \r
+\r
       if (stripped_len > len) {\r
       }\r
-      \r
+\r
       dest.sll_ifindex = if_nametoindex(walker->ifName);\r
       dest.sll_halen = IFHWADDRLEN;\r
 \r
@@ -179,7 +171,8 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
          * be a multicast address. E.g., when the destination IP is 224.0.0.1,\r
          * the destination MAC should be 01:00:5e:00:00:01. However, it does not\r
          * seem to matter when the destination MAC address is set to all-ones\r
-         * in that case. */\r
+         * in that case.\r
+         */\r
 \r
         if (IsMulticastv4(ipHeader)) {\r
           dest.sll_addr[0] = 0x01;\r
@@ -202,6 +195,56 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
         }\r
       }\r
 \r
+      if (olsr_cnf->ip_version == AF_INET) {\r
+        // Determine the IP address and the port from the header information\r
+        if (ipHeader->ip_p == SOL_UDP && !IsIpv4Fragment(ipHeader)) {\r
+          udpHeader = (struct udphdr*)(encapsulationUdpData +\r
+                                       GetIpHeaderLength(encapsulationUdpData));\r
+          destAddr.v4.s_addr = ipHeader->ip_dst.s_addr;\r
+          destPort = htons(udpHeader->dest);\r
+          isInList = InUdpDestPortList(AF_INET, &destAddr, destPort);\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+          if (!isInList) {\r
+            char tmp[32];\r
+            OLSR_PRINTF(1,\r
+                        "%s: Not in dest/port list: %s:%d\n",\r
+                        PLUGIN_NAME_SHORT,\r
+                        get_ipv4_str(destAddr.v4.s_addr,\r
+                                     tmp,\r
+                                     sizeof(tmp)),\r
+                        destPort);\r
+          }\r
+#endif\r
+        }\r
+      } else /* (olsr_cnf->ip_version == AF_INET6) */ {\r
+        if (ip6Header->ip6_nxt == SOL_UDP && !IsIpv6Fragment(ip6Header)) {\r
+          udpHeader = (struct udphdr*)(encapsulationUdpData + 40);\r
+          memcpy(&destAddr.v6, &ip6Header->ip6_dst, sizeof(struct in6_addr));\r
+          destPort = htons(udpHeader->dest);\r
+          isInList = InUdpDestPortList(AF_INET6, &destAddr, destPort);\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+          if (!isInList) {\r
+            char tmp[64];\r
+            OLSR_PRINTF(1,\r
+                        "%s: Not in dest/port list: %s:%d\n",\r
+                        PLUGIN_NAME_SHORT,\r
+                        get_ipv6_str(destAddr.v6.s6_addr,\r
+                                     tmp,\r
+                                     sizeof(tmp)),\r
+                        destPort);\r
+          }\r
+#endif\r
+        }\r
+      }\r
+\r
+      if (!isInList) {\r
+        /* Address/port combination of this packet is not in the UDP dest/port\r
+         * list and will therefore be suppressed. I.e. just continue with the\r
+         * next interface to emit on.\r
+         */\r
+        continue;\r
+      }\r
+      \r
       nBytesWritten = sendto(walker->capturingSkfd,\r
                              encapsulationUdpData,\r
                              stripped_len,\r
@@ -209,7 +252,8 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
                              (struct sockaddr *)&dest,\r
                              sizeof(dest));\r
       if (nBytesWritten != stripped_len) {\r
-        P2pdPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);\r
+        P2pdPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"",\r
+                   walker->ifName);\r
       } else {\r
 \r
         //OLSR_PRINTF(\r
@@ -223,12 +267,23 @@ PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
 }                               /* PacketReceivedFromOLSR */\r
 \r
 /* Highest-numbered open socket file descriptor. To be used as first\r
- * parameter in calls to select(...). */\r
+ * parameter in calls to select(...).\r
+ */\r
 int HighestSkfd = -1;\r
 \r
 /* Set of socket file descriptors */\r
 fd_set InputSet;\r
 \r
+/* -------------------------------------------------------------------------\r
+ * Function   : p2pd_message_seen\r
+ * Description: Check whether the current message has been seen before\r
+ * Input      : head - start of the list to check for the message\r
+ *              tail - end of the list to check for the message\r
+ *              m    - message to check for in the list\r
+ * Output     : none\r
+ * Return     : true if message was found, false otherwise\r
+ * Data Used  : P2pdDuplicateTimeout\r
+ * ------------------------------------------------------------------------- */\r
 bool\r
 p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m)\r
 {\r
@@ -236,46 +291,57 @@ p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m)
   time_t now;\r
 \r
   now = time(NULL);\r
-  \r
+\r
   // Check whether any entries have aged\r
   curr = *head;\r
   while (curr) {\r
     struct DupFilterEntry *filter;\r
-    struct node * next = curr->next; // Save the current pointer since curr may be destroyed\r
-    \r
+    struct node * next = curr->next; // Save the current pointer since curr may\r
+                                     // be destroyed\r
+\r
     filter = (struct DupFilterEntry*)curr->data;\r
-    \r
+\r
     if ((filter->creationtime + P2pdDuplicateTimeout) < now)\r
       remove_node(head, tail, curr, true);\r
-      \r
+\r
     // Skip to the next element\r
     curr = next;\r
   }\r
-  \r
+\r
   // Now check whether there are any duplicates\r
   for (curr = *head; curr; curr = curr->next) {\r
     struct DupFilterEntry *filter = (struct DupFilterEntry*)curr->data;\r
-    \r
+\r
     if (olsr_cnf->ip_version == AF_INET) {\r
-      if (filter->address.v4.s_addr  == m->v4.originator &&\r
-          filter->msgtype            == m->v4.olsr_msgtype &&\r
-          filter->seqno              == m->v4.seqno) {\r
+      if (filter->address.v4.s_addr == m->v4.originator &&\r
+          filter->msgtype == m->v4.olsr_msgtype &&\r
+          filter->seqno == m->v4.seqno) {\r
           return true;\r
       }\r
     } else /* if (olsr_cnf->ip_version == AF_INET6) */ {\r
       if (memcmp(filter->address.v6.s6_addr,\r
                  m->v6.originator.s6_addr,\r
                  sizeof(m->v6.originator.s6_addr)) == 0 &&\r
-          filter->msgtype            == m->v6.olsr_msgtype &&\r
-          filter->seqno              == m->v6.seqno) {\r
+          filter->msgtype == m->v6.olsr_msgtype &&\r
+          filter->seqno == m->v6.seqno) {\r
           return true;\r
       }\r
     }\r
   }\r
-  \r
+\r
   return false;\r
 }\r
 \r
+/* -------------------------------------------------------------------------\r
+ * Function   : p2pd_store_message\r
+ * Description: Store a new message in the duplicate message check list\r
+ * Input      : head - start of the list to add the message to\r
+ *              tail - end of the list to add the message to\r
+ *              m    - message to add to the list\r
+ * Output     : none\r
+ * Return     : nothing\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
 void\r
 p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m)\r
 {\r
@@ -284,29 +350,37 @@ p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m
   // Store a message into the database\r
   struct DupFilterEntry *new_dup = calloc(1, sizeof(struct DupFilterEntry));\r
   if (new_dup == NULL) {\r
-    olsr_printf(1, "P2PD: Out of memory\n");\r
+    OLSR_PRINTF(1, "%s: Out of memory\n", PLUGIN_NAME_SHORT);\r
     return;\r
   }\r
 \r
   now = time(NULL);\r
-  \r
+\r
   new_dup->creationtime = now;\r
   if (olsr_cnf->ip_version == AF_INET) {\r
     new_dup->address.v4.s_addr = m->v4.originator;\r
-    new_dup->msgtype = m->v4.olsr_msgtype;\r
-    new_dup->seqno = m->v4.seqno;\r
+    new_dup->msgtype           = m->v4.olsr_msgtype;\r
+    new_dup->seqno             = m->v4.seqno;\r
   } else /* if (olsr_cnf->ip_version == AF_INET6) */ {\r
     memcpy(new_dup->address.v6.s6_addr,\r
            m->v6.originator.s6_addr,\r
            sizeof(m->v6.originator.s6_addr));\r
-    new_dup->msgtype = m->v6.olsr_msgtype;\r
-    new_dup->seqno = m->v6.seqno;\r
+    new_dup->msgtype           = m->v6.olsr_msgtype;\r
+    new_dup->seqno             = m->v6.seqno;\r
   }\r
-  \r
+\r
   // Add the element to the head of the list\r
   append_node(head, tail, new_dup);\r
 }\r
 \r
+/* -------------------------------------------------------------------------\r
+ * Function   : p2pd_is_duplicate_message\r
+ * Description: Check whether the specified message is a duplicate\r
+ * Input      : msg - message to check for in the list of duplicate messages\r
+ * Output     : none\r
+ * Return     : true if message was found, false otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
 bool\r
 p2pd_is_duplicate_message(union olsr_message *msg)\r
 {\r
@@ -315,19 +389,32 @@ p2pd_is_duplicate_message(union olsr_message *msg)
   }\r
 \r
   p2pd_store_message(&dupFilterHead, &dupFilterTail, msg);\r
-  \r
+\r
   return false;\r
 }\r
 \r
+/* -------------------------------------------------------------------------\r
+ * Function   : olsr_parser\r
+ * Description: Function to be passed to the parser engine. This function\r
+ *              processes the incoming message and passes it on if necessary.\r
+ * Input      : m      - message to parse\r
+ *              in_if  - interface to use (unused in this application)\r
+ *              ipaddr - IP-address to use (unused in this application)\r
+ * Output     : none\r
+ * Return     : false if message should be supressed, true otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
 bool\r
-olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr __attribute__ ((unused)))\r
+olsr_parser(union olsr_message *m,\r
+            struct interface *in_if __attribute__ ((unused)),\r
+            union olsr_ip_addr *ipaddr __attribute__ ((unused)))\r
 {\r
   union olsr_ip_addr originator;\r
   int size;\r
   uint32_t vtime;\r
 \r
   //OLSR_DEBUG(LOG_PLUGINS, "P2PD PLUGIN: Received msg in parser\n");\r
-  \r
+\r
        /* Fetch the originator of the messsage */\r
   if (olsr_cnf->ip_version == AF_INET) {\r
     memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);\r
@@ -357,7 +444,15 @@ olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unuse
        return true;\r
 }\r
 \r
-//Sends a packet in the OLSR network\r
+/* -------------------------------------------------------------------------\r
+ * Function   : olsr_p2pd_gen\r
+ * Description: Sends a packet in the OLSR network\r
+ * Input      : packet - packet to send in the OLSR network\r
+ *              len    - length of the packet to send\r
+ * Output     : none\r
+ * Return     : nothing\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
 void\r
 olsr_p2pd_gen(unsigned char *packet, int len)\r
 {\r
@@ -366,7 +461,7 @@ olsr_p2pd_gen(unsigned char *packet, int len)
   int aligned_size;\r
   union olsr_message *message = (union olsr_message *)buffer;\r
   struct interface *ifn;\r
-  \r
+\r
   aligned_size=len;\r
 \r
   if ((aligned_size % 4) != 0) {\r
@@ -400,15 +495,15 @@ olsr_p2pd_gen(unsigned char *packet, int len)
     aligned_size = aligned_size + 12 + 96;\r
   }\r
 \r
-  /* looping trough interfaces */\r
+  /* looping through interfaces */\r
   for (ifn = ifnet; ifn; ifn = ifn->int_next) {\r
-    //OLSR_PRINTF(1, "P2PD PLUGIN: Generating packet - [%s]\n", ifn->int_name);\r
+    //OLSR_PRINTF(1, "%s: Generating packet - [%s]\n", PLUGIN_NAME_SHORT, ifn->int_name);\r
 \r
     if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {\r
       /* send data and try again */\r
       net_output(ifn);\r
       if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {\r
-        //OLSR_PRINTF(1, "P2PD PLUGIN: could not send on interface: %s\n", ifn->int_name);\r
+        //OLSR_PRINTF(1, "%s: could not send on interface: %s\n", PLUGIN_NAME_SHORT, ifn->int_name);\r
       }\r
     }\r
   }\r
@@ -446,7 +541,7 @@ P2pdPError(const char *format, ...)
     va_end(arglist);\r
 \r
     strDesc[MAX_STR_DESC - 1] = '\0';   /* Ensures null termination */\r
-    \r
+\r
 #if !defined REMOVE_LOG_DEBUG\r
     OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", strDesc, stringErr);\r
 #endif\r
@@ -490,7 +585,7 @@ bool
 InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port)\r
 {\r
   struct UdpDestPort *walker;\r
-  \r
+\r
   for (walker = UdpDestPortList; walker; walker = walker->next) {\r
     if (walker->ip_version == ip_version) {\r
       if (ip_version == AF_INET) {\r
@@ -498,10 +593,10 @@ InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port)
             walker->port == port)\r
           return true;  // Found so we can stop here\r
       } else /* ip_version == AF_INET6 */ {\r
-        if (memcmp(addr->v6.s6_addr,\r
+        if ((memcmp(addr->v6.s6_addr,\r
                    walker->address.v6.s6_addr,\r
-                   sizeof(addr->v6.s6_addr) == 0) &&\r
-            walker->port == port)\r
+                   sizeof(addr->v6.s6_addr)) == 0) &&\r
+            (walker->port == port))\r
           return true;  // Found so we can stop here\r
       }\r
     }\r
@@ -512,7 +607,7 @@ InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port)
 /* -------------------------------------------------------------------------\r
  * Function   : P2pdPacketCaptured\r
  * Description: Handle a captured IP packet\r
- * Input      : encapsulationUdpData - space for the encapsulation header, \r
+ * Input      : encapsulationUdpData - space for the encapsulation header,\r
  *              followed by the captured IP packet\r
  *              nBytes - The number of bytes in the data packet\r
  * Output     : none\r
@@ -540,29 +635,43 @@ P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
 \r
     if (ipHeader->ip_p != SOL_UDP) {\r
       /* Not UDP */\r
-      //OLSR_PRINTF(1,"NON UDP PACKET\n");\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+      OLSR_PRINTF(1,"%s: NON UDP PACKET\n", PLUGIN_NAME_SHORT);\r
+#endif\r
       return;                   /* for */\r
     }\r
 \r
     // If we're dealing with a fragment we bail out here since there's no valid\r
     // UDP header in this message\r
     if (IsIpv4Fragment(ipHeader)) {\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+      OLSR_PRINTF(1, "%s: Is IPv4 fragment\n", PLUGIN_NAME_SHORT);\r
+#endif\r
       return;\r
     }\r
-    \r
+\r
+    if (check_and_mark_recent_packet(encapsulationUdpData, nBytes))\r
+      return;\r
+\r
     udpHeader = (struct udphdr *)(encapsulationUdpData +\r
                                   GetIpHeaderLength(encapsulationUdpData));\r
     destPort = ntohs(udpHeader->dest);\r
-    \r
-    if (!InUdpDestPortList(AF_INET, &dst, destPort))\r
+\r
+    if (!InUdpDestPortList(AF_INET, &dst, destPort)) {\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+      char tmp[32];\r
+      OLSR_PRINTF(1, "%s: Not in dest/port list: %s:%d\n", PLUGIN_NAME_SHORT,\r
+                  get_ipv4_str(dst.v4.s_addr, tmp, sizeof(tmp)), destPort);\r
+#endif\r
        return;\r
+    }\r
   }                            //END IPV4\r
   else if ((encapsulationUdpData[0] & 0xf0) == 0x60) {  //IPv6\r
 \r
     ipHeader6 = (struct ip6_hdr *)encapsulationUdpData;\r
-    \r
+\r
     memcpy(&dst.v6, &ipHeader6->ip6_dst, sizeof(struct in6_addr));\r
-    \r
+\r
     if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)  //Multicast\r
     {\r
       //Continue\r
@@ -571,20 +680,32 @@ P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
     }\r
     if (ipHeader6->ip6_nxt != SOL_UDP) {\r
       /* Not UDP */\r
-      //OLSR_PRINTF(1,"NON UDP PACKET\n");\r
+      //OLSR_PRINTF(1,"%s: NON UDP PACKET\n", PLUGIN_NAME_SHORT);\r
       return;                   /* for */\r
     }\r
-    \r
+\r
     // Check whether this is a IPv6 fragment\r
     if (IsIpv6Fragment(ipHeader6)) {\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+      OLSR_PRINTF(1, "%s: Is IPv6 fragment\n", PLUGIN_NAME_SHORT);\r
+#endif\r
       return;\r
     }\r
-    \r
+\r
+    if (check_and_mark_recent_packet(encapsulationUdpData, nBytes))\r
+      return;\r
+\r
     udpHeader = (struct udphdr *)(encapsulationUdpData + 40);\r
     destPort = ntohs(udpHeader->dest);\r
 \r
-    if (!InUdpDestPortList(AF_INET6, &dst, destPort))\r
+    if (!InUdpDestPortList(AF_INET6, &dst, destPort)) {\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+      char tmp[64];\r
+      OLSR_PRINTF(1, "%s: Not in dest/port list: %s:%d\n", PLUGIN_NAME_SHORT,\r
+                  get_ipv6_str(dst.v6.s6_addr, tmp, sizeof(tmp)), destPort);\r
+#endif\r
       return;\r
+    }\r
   }                             //END IPV6\r
   else {\r
     return;                     //Is not IP packet\r
@@ -600,14 +721,17 @@ P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
 \r
 /* -------------------------------------------------------------------------\r
  * Function   : DoP2pd\r
- * Description: This function is registered with the OLSR scheduler and called when something is captured\r
+ * Description: This function is registered with the OLSR scheduler and called\r
+ *              when something is captured\r
  * Input      : none\r
  * Output     : none\r
  * Return     : none\r
  * Data Used  :\r
  * ------------------------------------------------------------------------- */\r
 void\r
-DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))\r
+DoP2pd(int skfd,\r
+       void *data __attribute__ ((unused)),\r
+       unsigned int flags __attribute__ ((unused)))\r
 {\r
   unsigned char rxBuffer[P2PD_BUFFER_SIZE];\r
   if (skfd >= 0) {\r
@@ -619,8 +743,12 @@ DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attri
     /* Receive the captured Ethernet frame, leaving space for the BMF\r
      * encapsulation header */\r
     ipPacket = GetIpPacket(rxBuffer);\r
-    nBytes = recvfrom(skfd, ipPacket, P2PD_BUFFER_SIZE,  //TODO: understand how to change this\r
+    nBytes = recvfrom(skfd, ipPacket, P2PD_BUFFER_SIZE,\r
                       0, (struct sockaddr *)&pktAddr, &addrLen);\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+    OLSR_PRINTF(1, "%s: Received %d bytes\n", PLUGIN_NAME_SHORT, nBytes);\r
+#endif\r
+\r
     if (nBytes < 0) {\r
 \r
       return;                   /* for */\r
@@ -637,7 +765,7 @@ DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attri
       ////OLSR_PRINTF(\r
       //              1,\r
       //              "%s: captured frame too short (%d bytes) on \"%s\"\n",\r
-      //              PLUGIN_NAME,\r
+      //              PLUGIN_NAME_SHORT,\r
       //              nBytes,\r
       //              walker->ifName);\r
 \r
@@ -647,8 +775,12 @@ DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attri
     if (pktAddr.sll_pkttype == PACKET_OUTGOING ||\r
         pktAddr.sll_pkttype == PACKET_MULTICAST ||\r
         pktAddr.sll_pkttype == PACKET_BROADCAST) {\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+      OLSR_PRINTF(1, "%s: Multicast or broadcast packet was captured.\n",\r
+                  PLUGIN_NAME_SHORT);\r
+      dump_packet(ipPacket, nBytes);\r
+#endif\r
       /* A multicast or broadcast packet was captured */\r
-\r
       P2pdPacketCaptured(ipPacket, nBytes);\r
 \r
     }                           /* if (pktAddr.sll_pkttype == ...) */\r
@@ -666,13 +798,15 @@ DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attri
 int\r
 InitP2pd(struct interface *skipThisIntf)\r
 {\r
-  // Initialize hash table for hash based duplicate IP packet check\r
-  InitPacketHistory();\r
-  \r
+  if (P2pdUseHash) {\r
+    // Initialize hash table for hash based duplicate IP packet check\r
+    InitPacketHistory();\r
+  }\r
+\r
   //Tells OLSR to launch olsr_parser when the packets for this plugin arrive\r
   //olsr_parser_add_function(&olsr_parser, PARSER_TYPE,1);\r
   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);\r
-  \r
+\r
   //Creates captures sockets and register them to the OLSR scheduler\r
   CreateNonOlsrNetworkInterfaces(skipThisIntf);\r
 \r
@@ -702,7 +836,9 @@ CloseP2pd(void)
  * Data Used  : P2pdTtl\r
  * ------------------------------------------------------------------------- */\r
 int\r
-SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))\r
+SetP2pdTtl(const char *value,\r
+           void *data __attribute__ ((unused)),\r
+           set_plugin_parameter_addon addon __attribute__ ((unused)))\r
 {\r
   assert(value != NULL);\r
   P2pdTtl = atoi(value);\r
@@ -710,20 +846,25 @@ SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_pa
   return 0;\r
 }\r
 \r
-bool is_broadcast(const struct sockaddr_in addr)\r
-{\r
-  if (addr.sin_addr.s_addr == 0xFFFFFFFF)\r
-    return true;\r
-    \r
-  return false;\r
-}\r
-\r
-bool is_multicast(const struct sockaddr_in addr)\r
+/* -------------------------------------------------------------------------\r
+ * Function   : SetP2pdUseHashFilter\r
+ * Description: Set the Hash filter flag for this plug-in\r
+ * Input      : value - parameter value to evaluate\r
+ *              data  - data associated with this parameter (unused in this app)\r
+ *              addon - additional parameter data\r
+ * Output     : none\r
+ * Return     : Always 0\r
+ * Data Used  : P2pdUseHash\r
+ * ------------------------------------------------------------------------- */\r
+int\r
+SetP2pdUseHashFilter(const char *value,\r
+                     void *data __attribute__ ((unused)),\r
+                     set_plugin_parameter_addon addon __attribute__ ((unused)))\r
 {\r
-  if ((htonl(addr.sin_addr.s_addr) & 0xE0000000) == 0xE0000000)\r
-    return true;\r
-\r
-  return false;\r
+  assert(value != NULL);\r
+  P2pdUseHash = atoi(value);\r
+  \r
+  return 0;\r
 }\r
 \r
 /* -------------------------------------------------------------------------\r
@@ -736,7 +877,9 @@ bool is_multicast(const struct sockaddr_in addr)
  * Data Used  : UdpDestPortList\r
  * ------------------------------------------------------------------------- */\r
 int\r
-AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))\r
+AddUdpDestPort(const char *value,\r
+               void *data __attribute__ ((unused)),\r
+               set_plugin_parameter_addon addon __attribute__ ((unused)))\r
 {\r
   char destAddr[INET6_ADDRSTRLEN];\r
   uint16_t destPort;\r
@@ -746,17 +889,18 @@ AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugi
   struct sockaddr_in6     addr6;\r
   int                     ip_version   = AF_INET;\r
   int                     res;\r
-  \r
+\r
   assert(value != NULL);\r
-  \r
+\r
   // Retrieve the data from the argument string passed\r
   memset(destAddr, 0, sizeof(destAddr));\r
   num = sscanf(value, "%45s %hd", destAddr, &destPort);\r
   if (num != 2) {\r
-    olsr_printf(1, "Invalid argument for \"UdpDestPort\"");\r
+    OLSR_PRINTF(1, "%s: Invalid argument for \"UdpDestPort\"",\r
+                PLUGIN_NAME_SHORT);\r
     return -1;\r
   }\r
-       \r
+\r
   // Check whether we're dealing with an IPv4 or IPv6 address\r
   // When the string contains a ':' we can assume we're dealing with IPv6\r
   if (strchr(destAddr, (int)':')) {\r
@@ -770,44 +914,189 @@ AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugi
   case AF_INET:\r
     res = inet_pton(AF_INET, destAddr, &addr4.sin_addr);\r
     if (!is_broadcast(addr4) && !is_multicast(addr4)) {\r
-      olsr_printf(1, "WARNING: IPv4 address must be multicast or broadcast... ");\r
+      OLSR_PRINTF(1,"WARNING: IPv4 address must be multicast or broadcast... ");\r
     }\r
     break;\r
   case AF_INET6:\r
     res = inet_pton(AF_INET6, destAddr, &addr6.sin6_addr);\r
     if (addr6.sin6_addr.s6_addr[0] != 0xFF) {\r
-      olsr_printf(1, "WARNING: IPv6 address must be multicast... ");\r
+      OLSR_PRINTF(1,"WARNING: IPv6 address must be multicast... ");\r
       return -1;\r
     }\r
     break;\r
   }\r
   // Determine whether it is a valid IP address\r
   if (res == 0) {\r
-    olsr_printf(1, "Invalid address specified for \"UdpDestPort\"");\r
+    OLSR_PRINTF(1, "Invalid address specified for \"UdpDestPort\"");\r
     return -1;\r
   }\r
-       \r
+\r
   // Create a new entry and link it into the chain\r
   new = calloc(1, sizeof(struct UdpDestPort));\r
   if (new == NULL) {\r
-    olsr_printf(1, "P2PD: Out of memory");\r
+    OLSR_PRINTF(1, "%s: Out of memory", PLUGIN_NAME_SHORT);\r
     return -1;\r
   }\r
-       \r
+\r
   new->ip_version = ip_version;\r
   switch (ip_version) {\r
   case AF_INET:\r
     new->address.v4.s_addr = addr4.sin_addr.s_addr;\r
     break;\r
   case AF_INET6:\r
-    memcpy(&new->address.v6.s6_addr, &addr6.sin6_addr.s6_addr, sizeof(sizeof(addr6.sin6_addr.s6_addr)));\r
+    memcpy(&new->address.v6.s6_addr,\r
+           &addr6.sin6_addr.s6_addr,\r
+           sizeof(addr6.sin6_addr.s6_addr));\r
     break;\r
   }\r
   new->port = destPort;\r
   new->next = UdpDestPortList;\r
   UdpDestPortList = new;\r
-       \r
+\r
   // And then we're done\r
   return 0;\r
 }\r
 \r
+/* -------------------------------------------------------------------------\r
+ * Function   : get_ipv4_str\r
+ * Description: Convert the specified address to an IPv4 compatible string\r
+ * Input      : address - IPv4 address to convert to string\r
+ *              s       - string buffer to contain the resulting string\r
+ *              maxlen  - maximum length of the string buffer\r
+ * Output     : none\r
+ * Return     : Pointer to the string buffer containing the result\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+char *\r
+get_ipv4_str(uint32_t address, char *s, size_t maxlen)\r
+{\r
+  struct sockaddr_in v4;\r
+\r
+  v4.sin_addr.s_addr = address;\r
+  inet_ntop(AF_INET, &v4.sin_addr, s, maxlen);\r
+\r
+  return s;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : get_ipv6_str\r
+ * Description: Convert the specified address to an IPv4 compatible string\r
+ * Input      : address - IPv6 address to convert to string\r
+ *              s       - string buffer to contain the resulting string\r
+ *              maxlen  - maximum length of the string buffer\r
+ * Output     : none\r
+ * Return     : Pointer to the string buffer containing the result\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+char *\r
+get_ipv6_str(unsigned char* address, char *s, size_t maxlen)\r
+{\r
+  struct sockaddr_in6 v6;\r
+\r
+  memcpy(v6.sin6_addr.s6_addr, address, sizeof(v6.sin6_addr.s6_addr));\r
+  inet_ntop(AF_INET6, &v6.sin6_addr, s, maxlen);\r
+\r
+  return s;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : is_broadcast\r
+ * Description: Check whether the address represents a broadcast address\r
+ * Input      : addr - IPv4 address to check\r
+ * Output     : none\r
+ * Return     : true if broadcast address, false otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+bool\r
+is_broadcast(const struct sockaddr_in addr)\r
+{\r
+  if (addr.sin_addr.s_addr == 0xFFFFFFFF)\r
+    return true;\r
+\r
+  return false;\r
+}\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : is_multicast\r
+ * Description: Check whether the address represents a multicast address\r
+ * Input      : addr - IPv4 address to check\r
+ * Output     : none\r
+ * Return     : true if broadcast address, false otherwise\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+bool\r
+is_multicast(const struct sockaddr_in addr)\r
+{\r
+  if ((htonl(addr.sin_addr.s_addr) & 0xE0000000) == 0xE0000000)\r
+    return true;\r
+\r
+  return false;\r
+}\r
+\r
+#ifdef INCLUDE_DEBUG_OUTPUT\r
+/* -------------------------------------------------------------------------\r
+ * Function   : dump_packet\r
+ * Description: Dump the specified data as hex output\r
+ * Input      : packet - packet to dump to output\r
+ *              length - length of the data in the packet\r
+ * Output     : none\r
+ * Return     : nothing\r
+ * Data Used  : none\r
+ * ------------------------------------------------------------------------- */\r
+void\r
+dump_packet(unsigned char* packet, int length)\r
+{\r
+  int idx;\r
+\r
+  OLSR_PRINTF(1, "%s: ", PLUGIN_NAME_SHORT);\r
+  for (idx = 0; idx < length; idx++) {\r
+    if (idx > 0 && ((idx % 16) == 0))\r
+      OLSR_PRINTF(1, "\n%s: ", PLUGIN_NAME_SHORT);\r
+    OLSR_PRINTF(1, "%2.2X ", packet[idx]);\r
+  }\r
+  OLSR_PRINTF(1, "\n");\r
+}\r
+#endif\r
+\r
+/* -------------------------------------------------------------------------\r
+ * Function   : check_and_mark_recent_packet\r
+ * Description: Wrapper function for the Hash based duplicate check\r
+ * Input      : data - pointer to a packet of data to be checked\r
+ * Output     : none\r
+ * Return     : true if duplicate packet, false otherwise\r
+ * Data Used  : P2pdUseHash\r
+ * ------------------------------------------------------------------------- */\r
+bool\r
+check_and_mark_recent_packet(unsigned char *data,\r
+                             int len __attribute__ ((unused)))\r
+{\r
+  unsigned char * ipPacket;\r
+  uint16_t ipPacketLen;\r
+  uint32_t crc32;\r
+\r
+  /* If we don't use this filter bail out here */\r
+  if (!P2pdUseHash)\r
+    return false;\r
+    \r
+  /* Clean up the hash table each time before we check it */\r
+  PrunePacketHistory(NULL);\r
+\r
+  /* Check for duplicate IP packets now based on a hash */\r
+  ipPacket = GetIpPacket(data);\r
+  ipPacketLen = GetIpTotalLength(ipPacket);\r
+\r
+  /* Calculate packet fingerprint */\r
+  crc32 = PacketCrc32(ipPacket, ipPacketLen);\r
+\r
+  /* Check if this packet was seen recently */\r
+  if (CheckAndMarkRecentPacket(crc32))\r
+  {\r
+    OLSR_PRINTF(\r
+      8,\r
+      "%s: --> discarding: packet is duplicate\n",\r
+      PLUGIN_NAME_SHORT);\r
+    return true;\r
+  }\r
+\r
+  return false;\r
+}\r
index 0e16b54..18ad562 100644 (file)
@@ -44,6 +44,9 @@
 \r
 #define REMOVE_LOG_DEBUG\r
 \r
+// Either #define or #undef the following line to include extra debugging\r
+#undef INCLUDE_DEBUG_OUTPUT\r
+\r
 #include "olsrd_plugin.h"             /* union set_plugin_parameter_addon */\r
 #include "duplicate_set.h"\r
 //#include "socket_parser.h"\r
@@ -94,6 +97,8 @@ void CloseP2pd(void);
 int SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));\r
 int AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));\r
 bool InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port);\r
+int SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));\r
+int SetP2pdUseHashFilter(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));\r
 bool p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m);\r
 void p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m);\r
 bool p2pd_is_duplicate_message(union olsr_message *msg);\r