Prepend custom Destination IP and Source IP (ipv4 or ipv6) in the pcap. Bug 5650 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5650)

svn path=/trunk/; revision=49964
This commit is contained in:
Michael Mann 2013-06-16 16:50:17 +00:00
parent 27598e20a2
commit 75420f4ab2
2 changed files with 180 additions and 9 deletions

View 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

View File

@ -141,6 +141,22 @@
#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,11 +676,42 @@ 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));
}
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 */
@ -620,19 +719,13 @@ write_current_packet(gboolean cont)
guint16 x16;
guint32 u;
/* 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));
/* 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);