/* $Id$ */ /* * Copyright (c) 2001-2010 Aaron Turner * Copyright (c) 2013-2024 Fred Klassen - AppNeta * * The Tcpreplay Suite of tools is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or with the authors permission any later version. * * The Tcpreplay Suite is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the Tcpreplay Suite. If not, see . */ #include "tcpprep_api.h" #include "config.h" #include "common.h" #include "tcpprep_opts.h" #include #include #include extern void print_comment(const char *); extern void print_info(const char *); extern void print_stats(const char *); /** * \brief Initialize a new tcpprep context * * Allocates memory and stuff like that. Always returns a buffer or completely * fails by calling exit() on malloc failure. */ tcpprep_t * tcpprep_init() { tcpprep_t *ctx; int i; ctx = safe_malloc(sizeof(tcpprep_t)); ctx->options = safe_malloc(sizeof(tcpprep_opt_t)); ctx->options->bpf.optimize = BPF_OPTIMIZE; for (i = DEFAULT_LOW_SERVER_PORT; i <= DEFAULT_HIGH_SERVER_PORT; i++) { ctx->options->services.tcp[i] = 1; ctx->options->services.udp[i] = 1; } return ctx; } /** * Closes & free's all memory related to a tcpprep context */ void tcpprep_close(tcpprep_t *ctx) { tcpr_cache_t *cache, *cache_nxt; tcpr_cidr_t *cidr, *cidr_nxt; tcpprep_opt_t *options; assert(ctx); options = ctx->options; if (options->pcap != NULL) pcap_close(options->pcap); #ifdef ENABLE_VERBOSE safe_free(options->tcpdump_args); #endif safe_free(options->comment); safe_free(options->maclist); cache = options->cachedata; while (cache != NULL) { cache_nxt = cache->next; safe_free(cache); cache = cache_nxt; } cidr = options->cidrdata; while (cidr != NULL) { cidr_nxt = cidr->next; safe_free(cidr); cidr = cidr_nxt; } if (options->xX.list) free_list(options->xX.list); if (options->xX.cidr) safe_free(options->xX.cidr); regfree(&options->preg); safe_free(options); safe_free(ctx->outfile); safe_free(ctx->pcapfile); safe_free(ctx); } /** * \brief When using AutoOpts, call to do post argument processing * Used to process the autoopts arguments */ int tcpprep_post_args(tcpprep_t *ctx, int argc, char *argv[]) { char myargs[MYARGS_LEN]; size_t bufsize; char *endptr; char *tempstr; memset(myargs, 0, MYARGS_LEN); /* print_comment and print_info don't return */ if (HAVE_OPT(PRINT_COMMENT)) print_comment(OPT_ARG(PRINT_COMMENT)); if (HAVE_OPT(PRINT_INFO)) print_info(OPT_ARG(PRINT_INFO)); if (HAVE_OPT(PRINT_STATS)) print_stats(OPT_ARG(PRINT_STATS)); if (!HAVE_OPT(CACHEFILE) && !HAVE_OPT(PCAP)) err(-1, "Must specify an output cachefile (-o) and input pcap (-i)"); if (!ctx->options->mode) err(-1, "Must specify a processing mode: -a, -c, -r, -p"); #ifdef DEBUG if (HAVE_OPT(DBUG)) debug = OPT_VALUE_DBUG; #endif if (HAVE_OPT(SUPPRESS_WARNINGS)) print_warnings = 0; #ifdef ENABLE_VERBOSE if (HAVE_OPT(VERBOSE)) { ctx->options->verbose = 1; } if (HAVE_OPT(DECODE)) ctx->tcpdump.args = safe_strdup(OPT_ARG(DECODE)); #endif /* * if we are to include the cli args, then prep it for the * cache file header */ if (!ctx->options->nocomment) { int i; /* copy all of our args to myargs */ for (i = 1; i < argc; i++) { /* skip the -C */ if (strcmp(argv[i], "-C") == 0) { i += 2; continue; } strlcat(myargs, argv[i], MYARGS_LEN); strlcat(myargs, " ", MYARGS_LEN); } /* remove trailing space */ myargs[strlen(myargs) - 1] = 0; dbgx(1, "Comment args length: %zu", strlen(myargs)); } /* setup or options.comment buffer so that we get args\ncomment */ if (ctx->options->comment != NULL) { strlcat(myargs, "\n", MYARGS_LEN); bufsize = strlen(ctx->options->comment) + strlen(myargs) + 1; ctx->options->comment = (char *)safe_realloc(ctx->options->comment, bufsize); tempstr = strdup(ctx->options->comment); strlcpy(ctx->options->comment, myargs, bufsize); strlcat(ctx->options->comment, tempstr, bufsize); safe_free(tempstr); } else { bufsize = strlen(myargs) + 1; ctx->options->comment = (char *)safe_malloc(bufsize); strlcpy(ctx->options->comment, myargs, bufsize); } dbgx(1, "Final comment length: %zu", strlen(ctx->options->comment)); /* copy over our min/max mask */ ctx->options->min_mask = OPT_VALUE_MINMASK; ctx->options->max_mask = OPT_VALUE_MAXMASK; if (ctx->options->min_mask <= ctx->options->max_mask) errx(-1, "Min network mask len (%d) must be less then max network mask len (%d)", ctx->options->min_mask, ctx->options->max_mask); ctx->options->ratio = strtod(OPT_ARG(RATIO), &endptr); if (endptr == OPT_ARG(RATIO)) err(-1, "Ratio supplied is not a number."); if (ctx->options->ratio < 0) err(-1, "Ratio must be a non-negative number."); return 0; }