Allow an optional offset to be specified when chopping bytes from packets.

svn path=/trunk/; revision=51845
This commit is contained in:
Chris Maynard 2013-09-08 20:29:26 +00:00
parent 1b009df749
commit 54adc0d2ff
3 changed files with 99 additions and 29 deletions

View File

@ -9,7 +9,7 @@ B<editcap>
S<[ B<-A> E<lt>start timeE<gt> ]>
S<[ B<-B> E<lt>stop timeE<gt> ]>
S<[ B<-c> E<lt>packets per fileE<gt> ]>
S<[ B<-C> E<lt>choplenE<gt> ]>
S<[ B<-C> [offset:]E<lt>choplenE<gt> ]>
S<[ B<-E> E<lt>error probabilityE<gt> ]>
S<[ B<-F> E<lt>file formatE<gt> ]>
S<[ B<-h> ]>
@ -89,15 +89,20 @@ be created with a suffix -nnnnn, starting with 00000. If the specified
number of packets is written to the output file, the next output file is
opened. The default is to use a single output file.
=item -C E<lt>choplenE<gt>
=item -C [offset:]E<lt>choplenE<gt>
Sets the chop length to use when writing the packet data. Each packet is
chopped by <choplen> bytes of data. Positive values chop at the packet
beginning while negative values chop at the packet end.
This is useful for chopping headers for decapsulation of an entire capture or
in the rare case that the conversion between two file formats leaves some random
bytes at the end of each packet.
If the optional offset precedes the <choplen>, then the bytes chopped will be
offset from that value. Positve offsets are from the packet beginning, while
negative offsets are from the packet end.
This is useful for chopping headers for decapsulation of an entire capture,
removing tunneling headers, or in the rare case that the conversion between two
file formats leaves some random bytes at the end of each packet. Another use is
for removing vlan tags.
NOTE: This option can be used more than once, effectively allowing you to chop
bytes from the beginning of a packet as well as from the end of a packet in a
@ -347,6 +352,10 @@ To introduce 5% random errors in a capture file use:
editcap -E 0.05 capture.pcap capture_error.pcap
To remove vlan tags from an Ethernet-encapsulated capture file use:
editcap -L -C 12:4 capture_vlan.pcap capture_no_vlan.pcap
=head1 SEE ALSO
pcap(3), wireshark(1), tshark(1), mergecap(1), dumpcap(1), capinfos(1),

View File

@ -35,6 +35,9 @@ since version 1.10:
* You can now pass the -C <choplen> option to editcap multiple times, which
allows you to chop bytes from the beginning of a packet as well as at the end
of a packet in a single step.
* You can now specify an optional offset to the -C option for editcap, which
allows you to start chopping from that offset instead of from the absolute
packet beginning or end.
=== New Protocol Support

106
editcap.c
View File

@ -730,9 +730,13 @@ usage(gboolean is_error)
fprintf(output, "\n");
fprintf(output, "Packet manipulation:\n");
fprintf(output, " -s <snaplen> truncate each packet to max. <snaplen> bytes of data.\n");
fprintf(output, " -C <choplen> chop each packet by <choplen> bytes. Positive values\n");
fprintf(output, " -C [offset:]<choplen> chop each packet by <choplen> bytes. Positive values\n");
fprintf(output, " chop at the packet beginning, negative values at the\n");
fprintf(output, " packet end. You can use this option more than once.\n");
fprintf(output, " packet end. If an optional offset precedes the length,\n");
fprintf(output, " then the bytes chopped will be offset from that value.\n");
fprintf(output, " Positve offsets are from the packet beginning,\n");
fprintf(output, " negative offsets are from the packet end. You can use\n");
fprintf(output, " this option more than once.\n");
fprintf(output, " -L adjust the frame length when chopping and/or snapping\n");
fprintf(output, " -t <time adjustment> adjust the timestamp of each packet;\n");
fprintf(output, " <time adjustment> is in relative seconds (e.g. -0.5).\n");
@ -861,6 +865,8 @@ main(int argc, char *argv[])
guint32 snaplen = 0; /* No limit */
int choplen_begin = 0; /* No chop at beginning */
int choplen_end = 0; /* No chop at end */
int chopoff_begin = 0; /* Offset when chop from beginning */
int chopoff_end = 0; /* Offset when chop from end */
gboolean adjlen = FALSE;
wtap_dumper *pdh = NULL;
unsigned int count = 1;
@ -962,18 +968,37 @@ main(int argc, char *argv[])
case 'C':
{
int choplen;
int choplen = 0, chopoff = 0;
choplen = (int)strtol(optarg, &p, 10);
if (p == optarg || *p != '\0') {
fprintf(stderr, "editcap: \"%s\" isn't a valid chop length\n",
switch (sscanf(optarg, "%d:%d", &chopoff, &choplen)) {
case 1: /* only the chop length was specififed */
choplen = chopoff;
chopoff = 0;
break;
case 2: /* both an offset and chop length was specified */
/* While the following would technically not be a problem, it's
* probably not what the user wanted, so treat it as an error */
if ((choplen > 0 && chopoff < 0) || (choplen < 0 && chopoff > 0)) {
fprintf(stderr, "editcap: \"%s\" isn't a valid chop offset:length\n",
optarg);
exit(1);
}
break;
default:
fprintf(stderr, "editcap: \"%s\" isn't a valid chop length or offset:length\n",
optarg);
exit(1);
exit(1);
break;
}
if (choplen > 0)
choplen_begin += choplen;
else if (choplen < 0)
choplen_end += choplen;
if (chopoff > 0)
chopoff_begin += chopoff;
else if (chopoff < 0)
chopoff_end += chopoff;
break;
}
@ -1302,33 +1327,66 @@ main(int argc, char *argv[])
}
}
if (choplen_end < 0) {
/* CHOP */
/* If we're not chopping anything from one side, then the offset for
* that side is meaningless. */
if (choplen_begin == 0)
chopoff_begin = 0;
if (choplen_end == 0)
chopoff_end = 0;
/* Make sure we don't chop off more than we have available */
if (phdr->caplen < (guint32)(chopoff_begin - chopoff_end)) {
choplen_begin = 0;
choplen_end = 0;
}
if ((guint32)(choplen_begin - choplen_end) >
(phdr->caplen - (guint32)(chopoff_begin - chopoff_end))) {
choplen_begin = phdr->caplen - (chopoff_begin - chopoff_end);
choplen_end = 0;
}
/* Handle chopping from the beginning. Note that if a beginning offset
* was specified, we need to keep that piece */
if (choplen_begin > 0) {
snap_phdr = *phdr;
if (((signed int) phdr->caplen + choplen_end) > 0)
snap_phdr.caplen += choplen_end;
else
snap_phdr.caplen = 0;
if (chopoff_begin > 0) {
memmove(&buf[chopoff_begin], &buf[chopoff_begin + choplen_begin],
snap_phdr.caplen - choplen_begin);
}
else {
buf += choplen_begin;
}
snap_phdr.caplen -= choplen_begin;
if (adjlen) {
if (((signed int) phdr->len + choplen_end) > 0)
snap_phdr.len += choplen_end;
else
if (phdr->len > (guint32)choplen_begin) {
snap_phdr.len -= choplen_begin;
} else {
snap_phdr.len = 0;
}
}
phdr = &snap_phdr;
}
if (choplen_begin > 0) {
/* Handle chopping from the end. Note that if an ending offset
* was specified, we need to keep that piece */
if (choplen_end < 0) {
snap_phdr = *phdr;
if (phdr->caplen > (unsigned int) choplen_begin) {
snap_phdr.caplen -= choplen_begin;
buf += choplen_begin;
} else
snap_phdr.caplen = 0;
if (chopoff_end < 0) {
memmove(&buf[(gint)snap_phdr.caplen + (choplen_end + chopoff_end)],
&buf[(gint)snap_phdr.caplen + chopoff_end], -chopoff_end);
}
snap_phdr.caplen += choplen_end;
if (adjlen) {
if (phdr->len > (unsigned int) choplen_begin) {
snap_phdr.len -= choplen_begin;
} else
if (((signed int) phdr->len + choplen_end) > 0) {
snap_phdr.len += choplen_end;
} else {
snap_phdr.len = 0;
}
}
phdr = &snap_phdr;
}