Prepend custom Destination IP and Source IP (ipv4 or ipv6) in the pcap. Bug 5650...
authorMichael Mann <mmann78@netscape.net>
Sun, 16 Jun 2013 16:50:17 +0000 (16:50 -0000)
committerMichael Mann <mmann78@netscape.net>
Sun, 16 Jun 2013 16:50:17 +0000 (16:50 -0000)
svn path=/trunk/; revision=49964

doc/text2pcap.pod
text2pcap.c

index 0f4198811c843659ea431cf959adee0075df7517..498e190e14e455e16606865686290f52a1a1f3ba 100644 (file)
@@ -218,6 +218,21 @@ IP or Ethernet headers. Note that appropriate Ethernet and IP headers
 are automatically also included with each packet.
 Example: I<-u1000,69> to make the packets look like TFTP/UDP packets.
 
+=item -4 E<lt>srcipE<gt>,E<lt>destipE<gt>
+
+Prepend dummy IP header with specified IPv4 dest and source address.
+This option should be accompanied by one of the following options: -i, -s, -S, -T, -u
+Use this option to apply "custom" IP addresses.
+Example: I<-4 10.0.0.1,10.0.0.2> to use 10.0.0.1 and 10.0.0.2 for all IP packets.
+
+=item -6 E<lt>srcipE<gt>,E<lt>destipE<gt>
+
+Prepend dummy IP header with specified IPv6 dest and source address.
+This option should be accompanied by one of the following options: -i, -s, -S, -T, -u
+Use this option to apply "custom" IP addresses.
+Example: I<-6 fe80:0:0:0:202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334> to 
+use fe80:0:0:0:202:b3ff:fe1e:8329 and 2001:0db8:85a3:0000:0000:8a2e:0370:7334 for all IP packets.
+
 =back
 
 =head1 SEE ALSO
index 860e9219d7239125c0dce786a2fa4136d78ac215..119d105846f76da607288417885d43d22dec6a94 100644 (file)
 #include <wsutil/unicode-utils.h>
 #endif /* _WIN32 */
 
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>       /* needed to define AF_ values on Windows */
+#endif
+
+#ifdef NEED_INET_ATON_H
+# include "wsutil/inet_aton.h"
+#endif
+
+#ifdef NEED_INET_V6DEFS_H
+# include "wsutil/inet_v6defs.h"
+#endif
+
 /*--- Options --------------------------------------------------------------------*/
 
 /* File format */
@@ -157,8 +173,16 @@ static guint32 hdr_ethernet_proto = 0;
 
 /* Dummy IP header */
 static int hdr_ip = FALSE;
+static int hdr_ipv6 = FALSE;
 static long hdr_ip_proto = 0;
 
+/* Destination and source addresses for IP header */
+static unsigned long hdr_ip_dest_addr = 0;
+static unsigned long hdr_ip_src_addr = 0;
+static guint8 hdr_ipv6_dest_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static guint8 hdr_ipv6_src_addr[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static guint8 NO_IPv6_ADDRESS[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
 /* Dummy UDP header */
 static int hdr_udp = FALSE;
 static guint32 hdr_dest_port = 0;
@@ -300,6 +324,44 @@ static struct {         /* pseudo header for checksum calculation */
     guint16 length;
 } pseudoh;
 
+
+/* headers taken from glibc */
+
+/* IPv6 address */
+struct hdr_in6_addr
+{
+    union
+    {
+       guint8  __u6_addr8[16];
+       guint16 __u6_addr16[8];
+       guint32 __u6_addr32[4];
+    } __in6_u;
+};
+
+typedef struct {
+        union  {
+                struct ip6_hdrctl {
+                        guint32 ip6_un1_flow;   /* 24 bits of flow-ID */
+                        guint16 ip6_un1_plen;   /* payload length */
+                        guint8  ip6_un1_nxt;    /* next header */
+                        guint8  ip6_un1_hlim;   /* hop limit */
+                } ip6_un1;
+                guint8 ip6_un2_vfc;       /* 4 bits version, 4 bits priority */
+        } ip6_ctlun;
+        struct hdr_in6_addr ip6_src;      /* source address */
+        struct hdr_in6_addr ip6_dst;      /* destination address */
+} hdr_ipv6_t;
+
+static hdr_ipv6_t HDR_IPv6;
+
+static struct {                 /* pseudo header ipv6 for checksum calculation */
+        struct  hdr_in6_addr src_addr6;
+        struct  hdr_in6_addr dst_addr6;
+        guint32 protocol;
+        guint32 zero;
+} pseudoh6;
+
+
 typedef struct {
     guint16 source_port;
     guint16 dest_port;
@@ -590,6 +652,12 @@ write_current_packet(gboolean cont)
     if (curr_offset > header_length) {
         /* Write the packet */
 
+        /* if defined IPv6 we should rewrite hdr_ethernet_proto anyways */
+        if(hdr_ipv6) {
+            hdr_ethernet_proto = 0x86DD;
+            hdr_ip = FALSE;
+        }
+
         /* Compute packet length */
         length = curr_offset;
         if (hdr_sctp) {
@@ -608,31 +676,56 @@ write_current_packet(gboolean cont)
 
         /* Write IP header */
         if (hdr_ip) {
+            if(hdr_ip_src_addr) HDR_IP.src_addr = hdr_ip_src_addr;
+            if(hdr_ip_dest_addr) HDR_IP.dest_addr = hdr_ip_dest_addr;
+
             HDR_IP.packet_length = g_htons(length - ip_offset + padding_length);
             HDR_IP.protocol = (guint8) hdr_ip_proto;
             HDR_IP.hdr_checksum = 0;
             HDR_IP.hdr_checksum = in_checksum(&HDR_IP, sizeof(HDR_IP));
             write_bytes((const char *)&HDR_IP, sizeof(HDR_IP));
+        } else if (hdr_ipv6) {
+            if(memcmp(hdr_ipv6_src_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
+                memcpy(&HDR_IPv6.ip6_src, &hdr_ipv6_src_addr, sizeof(struct hdr_in6_addr));
+            if(memcmp(hdr_ipv6_dest_addr, NO_IPv6_ADDRESS, sizeof(struct hdr_in6_addr)))
+                memcpy(&HDR_IPv6.ip6_dst, &hdr_ipv6_dest_addr, sizeof(struct hdr_in6_addr));
+
+            HDR_IPv6.ip6_ctlun.ip6_un2_vfc &= 0x0F;
+            HDR_IPv6.ip6_ctlun.ip6_un2_vfc |= (6<< 4);
+            HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen = g_htons(length - ip_offset + padding_length);
+            HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_nxt  = (guint8) hdr_ip_proto;
+            HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_hlim = 32;
+            write_bytes((const char *)&HDR_IPv6, sizeof(HDR_IPv6));
+
+            /* initialize pseudo ipv6 header for checksum calculation */
+            pseudoh6.src_addr6  = HDR_IPv6.ip6_src;
+            pseudoh6.dst_addr6  = HDR_IPv6.ip6_dst;
+            pseudoh6.zero       = 0;
+            pseudoh6.protocol   = (guint8) hdr_ip_proto;
+            pseudoh.length      = g_htons(length - g_ntohs(HDR_IPv6.ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(HDR_UDP));
         }
 
-        /* Write UDP header */
-        if (hdr_udp) {
-            guint16 x16;
-            guint32 u;
-
+        if(!hdr_ipv6) {
             /* initialize pseudo header for checksum calculation */
             pseudoh.src_addr    = HDR_IP.src_addr;
             pseudoh.dest_addr   = HDR_IP.dest_addr;
             pseudoh.zero        = 0;
             pseudoh.protocol    = (guint8) hdr_ip_proto;
             pseudoh.length      = g_htons(length - header_length + sizeof(HDR_UDP));
+        }
+
+        /* Write UDP header */
+        if (hdr_udp) {
+            guint16 x16;
+            guint32 u;
+
             /* initialize the UDP header */
             HDR_UDP.source_port = g_htons(hdr_src_port);
             HDR_UDP.dest_port = g_htons(hdr_dest_port);
-            HDR_UDP.length = g_htons(length - header_length + sizeof(HDR_UDP));
+            HDR_UDP.length      = pseudoh.length;
             HDR_UDP.checksum = 0;
             /* Note: g_ntohs()/g_htons() macro arg may be eval'd twice so calc value before invoking macro */
-            x16  = in_checksum(&pseudoh, sizeof(pseudoh));
+            x16  = hdr_ipv6 ? in_checksum(&pseudoh6, sizeof(pseudoh6)) : in_checksum(&pseudoh, sizeof(pseudoh));
             u    = g_ntohs(x16);
             x16  = in_checksum(&HDR_UDP, sizeof(HDR_UDP));
             u   += g_ntohs(x16);
@@ -1330,6 +1423,12 @@ usage (void)
             "                         (in DECIMAL).\n"
             "                         Automatically prepends Ethernet header as well.\n"
             "                         Example: -i 46\n"
+            "  -4 <srcip>,<destip>    prepend dummy IPv4 header with specified\n"
+            "                         dest and source address.\n"
+            "                         Example: -4 10.0.0.1,10.0.0.2\n"
+            "  -6 <srcip>,<destip>    replace IPv6 header with specified\n"
+            "                         dest and source address.\n"
+            "                         Example: -6 fe80:0:0:0:202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334\n"
             "  -u <srcp>,<destp>      prepend dummy UDP header with specified\n"
             "                         source and destination ports (in DECIMAL).\n"
             "                         Automatically prepends Ethernet & IP headers as well.\n"
@@ -1375,7 +1474,7 @@ parse_options (int argc, char *argv[])
 #endif /* _WIN32 */
 
     /* Scan CLI parameters */
-    while ((c = getopt(argc, argv, "Ddhqe:i:l:m:no:u:s:S:t:T:a")) != -1) {
+    while ((c = getopt(argc, argv, "Ddhqe:i:l:m:no:u:s:S:t:T:a:4:6:")) != -1) {
         switch(c) {
         case '?': usage(); break;
         case 'h': usage(); break;
@@ -1555,6 +1654,60 @@ parse_options (int argc, char *argv[])
             identify_ascii = TRUE;
             break;
 
+        case '4':
+        case '6':
+            p = strchr(optarg, ',');
+
+            if (!p) {
+                fprintf(stderr, "Bad source param addr for '-%c'\n", c);
+                usage();
+            }
+
+            *p = '\0';
+            if(c == '6')
+            {
+                hdr_ipv6 = TRUE;
+                hdr_ethernet_proto = 0x86DD;
+            }
+            else
+            {
+                hdr_ip = TRUE;
+                hdr_ethernet_proto = 0x800;
+            }
+            hdr_ethernet = TRUE;
+
+            if (hdr_ipv6 == TRUE) {
+                if(inet_pton( AF_INET6, optarg, hdr_ipv6_src_addr) <= 0) {
+                        fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
+                        usage();
+                }
+            } else {
+                if(inet_pton( AF_INET, optarg, &hdr_ip_src_addr) <= 0) {
+                        fprintf(stderr, "Bad src addr -%c '%s'\n", c, p);
+                        usage();
+                }
+            }
+
+            p++;
+            if (*p == '\0') {
+                fprintf(stderr, "No dest addr specified for '-%c'\n", c);
+                usage();
+            }
+
+            if (hdr_ipv6 == TRUE) {
+                if(inet_pton( AF_INET6, p, hdr_ipv6_dest_addr) <= 0) {
+                        fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
+                        usage();
+                }
+            } else {
+                if(inet_pton( AF_INET, p, &hdr_ip_dest_addr) <= 0) {
+                        fprintf(stderr, "Bad dest addr for -%c '%s'\n", c, p);
+                        usage();
+                }
+            }
+            break;
+
+
         default:
             usage();
         }
@@ -1649,6 +1802,9 @@ main(int argc, char *argv[])
     if (hdr_ip) {
         ip_offset = header_length;
         header_length += (int)sizeof(HDR_IP);
+    } else if (hdr_ipv6) {
+        ip_offset = header_length;
+        header_length += (int)sizeof(HDR_IPv6);
     }
     if (hdr_sctp) {
         header_length += (int)sizeof(HDR_SCTP);