-
Notifications
You must be signed in to change notification settings - Fork 294
Using libtcpedit
libtcpedit (src/tcpedit/) is the packet-rewriting engine shared by tcprewrite,
tcpbridge, and tcpreplay-edit — see CLAUDE.md's architecture notes. This page is for
embedding it in your own program, rather than using it through those CLI tools. Verified
against 4.6.0-beta1's public API (src/tcpedit/tcpedit.h, tcpedit_api.h,
tcpedit_types.h).
There are two ways to configure a tcpedit_t context:
- Let AutoOpts parse CLI options for you and hand them to libtcpedit (
tcpedit_post_args()). - Call the configuration API directly (
tcpedit_set_*()), if you're not using AutoOpts — e.g. building a GUI, or need to run on a platform AutoOpts doesn't support.
This is the pattern every one of this project's own binaries uses. Simplified from
tcprewrite.c's actual main():
#include "tcprewrite.h"
#include "tcprewrite_opts.h"
#include "tcpedit/tcpedit.h"
tcprewrite_opt_t options;
tcpedit_t *tcpedit;
int main(int argc, char *argv[])
{
int optct, rcode;
/* AutoOpts parses tcprewrite's own arguments */
optct = optionProcess(&tcprewriteOptions, argc, argv);
argc -= optct;
argv += optct;
post_args(argc, argv);
/* init the tcpedit context with the input pcap's DLT */
if (tcpedit_init(&tcpedit, pcap_datalink(options.pin)) < 0) {
errx(1, "Error initializing tcpedit: %s", tcpedit_geterr(tcpedit));
}
/* let tcpedit parse the libtcpedit-specific args AutoOpts already collected */
rcode = tcpedit_post_args(tcpedit);
if (rcode < 0) {
errx(1, "Unable to parse args: %s", tcpedit_geterr(tcpedit));
} else if (rcode == 1) {
warnx("%s", tcpedit_geterr(tcpedit));
}
/* validate the options against the DLT type(s) actually seen */
if (tcpedit_validate(tcpedit) < 0) {
errx(1, "Unable to edit packets given options/DLT types:\n%s", tcpedit_geterr(tcpedit));
}
/* rewrite_packets() is tcprewrite's own loop — libtcpedit doesn't drive pcap I/O for you */
if (rewrite_packets(tcpedit, options.pin, options.pout) != 0)
errx(1, "Error rewriting packets: %s", tcpedit_geterr(tcpedit));
tcpedit_close(&tcpedit);
pcap_dump_close(options.pout);
pcap_close(options.pin);
return 0;
}Note tcpedit_init() takes the input pcap's DLT directly (pcap_datalink(options.pin)),
and tcpedit_close() takes a tcpedit_t ** (it frees the context and nulls your pointer)
— both have changed shape since this guide was first written in 2009, so don't copy old
snippets verbatim; check src/tcpedit/tcpedit.h for the current signatures.
libtcpedit itself doesn't read/write pcap files or drive a packet loop — that's on the
caller (rewrite_packets() above is tcprewrite.c's own function, not part of the
library). libtcpedit's job is turning one packet's bytes plus your configured rewrite
rules into new packet bytes.
Skip tcpedit_post_args() and instead call the tcpedit_set_*() functions in
tcpedit_api.h directly, still bracketed by tcpedit_init()/tcpedit_validate():
tcpedit_set_fixcsum(tcpedit, true);
tcpedit_set_mtu(tcpedit, 1500);
/* ... */Layer 3+ options are set this way directly. Layer 2/DLT options are per-plugin — first select an output DLT plugin:
tcpedit_set_encoder_dltplugin_byname(tcpedit, "enet"); /* or _byid() with a DLT_* value */then call that plugin's own setters, declared in its <name>_api.h (e.g.
src/tcpedit/plugins/dlt_en10mb/en10mb_api.h for Ethernet, dlt_hdlc/hdlc_api.h,
dlt_user/user_api.h, ...).
Every setter returns TCPEDIT_OK or TCPEDIT_ERROR (tcpedit_types.h) — on error, call
tcpedit_geterr() for details.
See also: DLT Plugin Developer Guide (writing a new DLT plugin) and Tcpedit Plugin Architecture (the design rationale behind the plugin system).
Adapted from the old libtcpedit page on the legacy Trac wiki (tcpreplay.synfin.net, no
longer reachable), rewritten against the current API after finding the 2009 example's
tcpedit_init()/tcpedit_close() call shapes no longer match.