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<-A> E<lt>start timeE<gt> ]>
S<[ B<-B> E<lt>stop timeE<gt> ]> S<[ B<-B> E<lt>stop timeE<gt> ]>
S<[ B<-c> E<lt>packets per fileE<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<-E> E<lt>error probabilityE<gt> ]>
S<[ B<-F> E<lt>file formatE<gt> ]> S<[ B<-F> E<lt>file formatE<gt> ]>
S<[ B<-h> ]> 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 number of packets is written to the output file, the next output file is
opened. The default is to use a single output file. 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 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 chopped by <choplen> bytes of data. Positive values chop at the packet
beginning while negative values chop at the packet end. beginning while negative values chop at the packet end.
This is useful for chopping headers for decapsulation of an entire capture or If the optional offset precedes the <choplen>, then the bytes chopped will be
in the rare case that the conversion between two file formats leaves some random offset from that value. Positve offsets are from the packet beginning, while
bytes at the end of each packet. 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 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 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 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 =head1 SEE ALSO
pcap(3), wireshark(1), tshark(1), mergecap(1), dumpcap(1), capinfos(1), 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 * 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 allows you to chop bytes from the beginning of a packet as well as at the end
of a packet in a single step. 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 === New Protocol Support

106
editcap.c
View File

@ -730,9 +730,13 @@ usage(gboolean is_error)
fprintf(output, "\n"); fprintf(output, "\n");
fprintf(output, "Packet manipulation:\n"); fprintf(output, "Packet manipulation:\n");
fprintf(output, " -s <snaplen> truncate each packet to max. <snaplen> bytes of data.\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, " 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, " -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, " -t <time adjustment> adjust the timestamp of each packet;\n");
fprintf(output, " <time adjustment> is in relative seconds (e.g. -0.5).\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 */ guint32 snaplen = 0; /* No limit */
int choplen_begin = 0; /* No chop at beginning */ int choplen_begin = 0; /* No chop at beginning */
int choplen_end = 0; /* No chop at end */ 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; gboolean adjlen = FALSE;
wtap_dumper *pdh = NULL; wtap_dumper *pdh = NULL;
unsigned int count = 1; unsigned int count = 1;
@ -962,18 +968,37 @@ main(int argc, char *argv[])
case 'C': case 'C':
{ {
int choplen; int choplen = 0, chopoff = 0;
choplen = (int)strtol(optarg, &p, 10); switch (sscanf(optarg, "%d:%d", &chopoff, &choplen)) {
if (p == optarg || *p != '\0') { case 1: /* only the chop length was specififed */
fprintf(stderr, "editcap: \"%s\" isn't a valid chop length\n", 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); optarg);
exit(1); exit(1);
break;
} }
if (choplen > 0) if (choplen > 0)
choplen_begin += choplen; choplen_begin += choplen;
else if (choplen < 0) else if (choplen < 0)
choplen_end += choplen; choplen_end += choplen;
if (chopoff > 0)
chopoff_begin += chopoff;
else if (chopoff < 0)
chopoff_end += chopoff;
break; 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; snap_phdr = *phdr;
if (((signed int) phdr->caplen + choplen_end) > 0)
snap_phdr.caplen += choplen_end; if (chopoff_begin > 0) {
else memmove(&buf[chopoff_begin], &buf[chopoff_begin + choplen_begin],
snap_phdr.caplen = 0; snap_phdr.caplen - choplen_begin);
}
else {
buf += choplen_begin;
}
snap_phdr.caplen -= choplen_begin;
if (adjlen) { if (adjlen) {
if (((signed int) phdr->len + choplen_end) > 0) if (phdr->len > (guint32)choplen_begin) {
snap_phdr.len += choplen_end; snap_phdr.len -= choplen_begin;
else } else {
snap_phdr.len = 0; snap_phdr.len = 0;
}
} }
phdr = &snap_phdr; 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; snap_phdr = *phdr;
if (phdr->caplen > (unsigned int) choplen_begin) {
snap_phdr.caplen -= choplen_begin; if (chopoff_end < 0) {
buf += choplen_begin; memmove(&buf[(gint)snap_phdr.caplen + (choplen_end + chopoff_end)],
} else &buf[(gint)snap_phdr.caplen + chopoff_end], -chopoff_end);
snap_phdr.caplen = 0; }
snap_phdr.caplen += choplen_end;
if (adjlen) { if (adjlen) {
if (phdr->len > (unsigned int) choplen_begin) { if (((signed int) phdr->len + choplen_end) > 0) {
snap_phdr.len -= choplen_begin; snap_phdr.len += choplen_end;
} else } else {
snap_phdr.len = 0; snap_phdr.len = 0;
}
} }
phdr = &snap_phdr; phdr = &snap_phdr;
} }