tcpprep_api.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2017 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "config.h"
  20. #include "defines.h"
  21. #include "common.h"
  22. #include <ctype.h>
  23. #include <fcntl.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <sys/types.h>
  28. #include <unistd.h>
  29. #include <errno.h>
  30. #include <stdarg.h>
  31. #include "tcpprep_api.h"
  32. #include "tcpprep_opts.h"
  33. extern void print_comment(const char *);
  34. extern void print_info(const char *);
  35. extern void print_stats(const char *);
  36. /**
  37. * \brief Initialize a new tcpprep context
  38. *
  39. * Allocates memory and stuff like that. Always returns a buffer or completely
  40. * fails by calling exit() on malloc failure.
  41. */
  42. tcpprep_t *
  43. tcpprep_init()
  44. {
  45. tcpprep_t *ctx;
  46. int i;
  47. ctx = safe_malloc(sizeof(tcpprep_t));
  48. ctx->options = safe_malloc(sizeof(tcpprep_opt_t));
  49. ctx->options->bpf.optimize = BPF_OPTIMIZE;
  50. for (i = DEFAULT_LOW_SERVER_PORT; i <= DEFAULT_HIGH_SERVER_PORT; i++) {
  51. ctx->options->services.tcp[i] = 1;
  52. ctx->options->services.udp[i] = 1;
  53. }
  54. return ctx;
  55. }
  56. /**
  57. * Closes & free's all memory related to a tcpprep context
  58. */
  59. void
  60. tcpprep_close(tcpprep_t *ctx)
  61. {
  62. tcpr_cache_t *cache, *cache_nxt;
  63. tcpr_cidr_t *cidr, *cidr_nxt;
  64. tcpprep_opt_t *options;
  65. assert(ctx);
  66. options = ctx->options;
  67. if (options->pcap != NULL)
  68. pcap_close(options->pcap);
  69. #ifdef ENABLE_VERBOSE
  70. safe_free(options->tcpdump_args);
  71. #endif
  72. safe_free(options->comment);
  73. safe_free(options->maclist);
  74. cache = options->cachedata;
  75. while (cache != NULL) {
  76. cache_nxt = cache->next;
  77. safe_free(cache);
  78. cache = cache_nxt;
  79. }
  80. cidr = options->cidrdata;
  81. while (cidr != NULL) {
  82. cidr_nxt = cidr->next;
  83. safe_free(cidr);
  84. cidr = cidr_nxt;
  85. }
  86. safe_free(options);
  87. safe_free(ctx->outfile);
  88. safe_free(ctx->pcapfile);
  89. safe_free(ctx);
  90. }
  91. /**
  92. * Specify the pcap file to process
  93. */
  94. int
  95. tcpprep_set_pcap_file(tcpprep_t *ctx, char *value)
  96. {
  97. assert(ctx);
  98. assert(value);
  99. ctx->pcapfile = safe_strdup(value);
  100. return 0;
  101. }
  102. /**
  103. * Specify the tcpprep cache file to generate
  104. */
  105. int
  106. tcpprep_set_output_file(tcpprep_t *ctx, char *value)
  107. {
  108. assert(ctx);
  109. assert(value);
  110. ctx->outfile = safe_strdup(value);
  111. return 0;
  112. }
  113. /**
  114. * Specify a cache file comment
  115. */
  116. int
  117. tcpprep_set_comment(tcpprep_t *ctx, char *value)
  118. {
  119. assert(ctx);
  120. assert(value);
  121. ctx->options->comment = safe_strdup(value);
  122. return 0;
  123. }
  124. /**
  125. * \brief Disable comments in the tcpprep cachefile
  126. *
  127. * Indicate that there should not be any comment or option info
  128. * embedded in the generated tcpprep cache file
  129. */
  130. int
  131. tcpprep_set_nocomment(tcpprep_t *ctx, bool value)
  132. {
  133. assert(ctx);
  134. ctx->options->nocomment = value;
  135. return 0;
  136. }
  137. /**
  138. * Specify the tcpprep main mode
  139. */
  140. int
  141. tcpprep_set_mode(tcpprep_t *ctx, tcpprep_mode_t value)
  142. {
  143. assert(ctx);
  144. ctx->options->mode = value;
  145. return 0;
  146. }
  147. /**
  148. * Specify the submode for automode
  149. */
  150. int
  151. tcpprep_set_automode(tcpprep_t *ctx, tcpprep_mode_t value)
  152. {
  153. assert(ctx);
  154. ctx->options->automode = value;
  155. return 0;
  156. }
  157. /**
  158. * Set the minimum CIDR mask length for auto modes
  159. */
  160. int
  161. tcpprep_set_min_mask(tcpprep_t *ctx, int value)
  162. {
  163. assert(ctx);
  164. ctx->options->min_mask = value;
  165. return 0;
  166. }
  167. /**
  168. * Set the maximum CIDR mask length for auto modes
  169. */
  170. int
  171. tcpprep_set_max_mask(tcpprep_t *ctx, int value)
  172. {
  173. assert(ctx);
  174. ctx->options->max_mask = value;
  175. return 0;
  176. }
  177. /**
  178. * Set the client/server ratio for auto modes
  179. */
  180. int
  181. tcpprep_set_ratio(tcpprep_t *ctx, double value)
  182. {
  183. assert(ctx);
  184. ctx->options->ratio = value;
  185. return 0;
  186. }
  187. /**
  188. * Specify the regex for regex mode
  189. */
  190. int
  191. tcpprep_set_regex(tcpprep_t *ctx, char *value)
  192. {
  193. int regex_error;
  194. char ebuf[EBUF_SIZE];
  195. assert(ctx);
  196. if ((regex_error = regcomp(&ctx->options->preg, value,
  197. REG_EXTENDED|REG_NOSUB))) {
  198. regerror(regex_error, &ctx->options->preg, ebuf, EBUF_SIZE);
  199. tcpprep_seterr(ctx, "Unable to compile regex (%s): %s", value, regex_error);
  200. return -1;
  201. }
  202. return 0;
  203. }
  204. /**
  205. * Override default: Send all non-IP traffic out the secondary interface
  206. */
  207. int
  208. tcpprep_set_nonip_is_secondary(tcpprep_t *ctx, bool value)
  209. {
  210. assert(ctx);
  211. ctx->options->nonip = value;
  212. return 0;
  213. }
  214. #ifdef ENABLE_VERBOSE
  215. /**
  216. * Enable verbose (tcpdump)
  217. */
  218. int
  219. tcpprep_set_verbose(tcpprep_t *ctx, bool value)
  220. {
  221. assert(ctx);
  222. ctx->options->verbose = value;
  223. return 0;
  224. }
  225. /**
  226. * Specify tcpdump args for verbose = ON
  227. */
  228. int
  229. tcpprep_set_tcpdump_args(tcpprep_t *ctx, char *value)
  230. {
  231. assert(ctx);
  232. ctx->options->tcpdump_args = safe_strdup(value);
  233. return 0;
  234. }
  235. /**
  236. * Specify path to tcpdump binary
  237. */
  238. int
  239. tcpprep_set_tcpdump(tcpprep_t *ctx, tcpdump_t *value)
  240. {
  241. assert(ctx);
  242. memcpy(&ctx->tcpdump, value, sizeof(tcpdump_t));
  243. return 0;
  244. }
  245. #endif
  246. /**
  247. * \brief Returns a string describing the last error.
  248. *
  249. * Value when the last call does not result in an error is undefined
  250. * (may be NULL, may be garbage)
  251. */
  252. char *
  253. tcpprep_geterr(tcpprep_t *ctx)
  254. {
  255. assert(ctx);
  256. return(ctx->errstr);
  257. }
  258. /**
  259. * \brief Returns a string describing the last warning.
  260. *
  261. * Value when the last call does not result in an warning is undefined
  262. * (may be NULL, may be garbage)
  263. */
  264. char *
  265. tcpprep_getwarn(tcpprep_t *ctx)
  266. {
  267. assert(ctx);
  268. return(ctx->warnstr);
  269. }
  270. /**
  271. * \brief Internal function to set the tcpprep error string
  272. *
  273. * Used to set the error string when there is an error, result is retrieved
  274. * using tcpedit_geterr(). You shouldn't ever actually call this, but use
  275. * tcpreplay_seterr() which is a macro wrapping this instead.
  276. */
  277. void
  278. __tcpprep_seterr(tcpprep_t *ctx, const char *func, const int line,
  279. const char *file, const char *fmt, ...)
  280. {
  281. va_list ap;
  282. char errormsg[TCPREPLAY_ERRSTR_LEN];
  283. assert(ctx);
  284. va_start(ap, fmt);
  285. if (fmt != NULL) {
  286. (void)vsnprintf(errormsg,
  287. (TCPREPLAY_ERRSTR_LEN - 1), fmt, ap);
  288. }
  289. va_end(ap);
  290. snprintf(ctx->errstr, (TCPREPLAY_ERRSTR_LEN -1), "From %s:%s() line %d:\n%s",
  291. file, func, line, errormsg);
  292. }
  293. /**
  294. * \brief Internal function to set the tcpedit warning string
  295. *
  296. * Used to set the warning string when there is an non-fatal issue, result is
  297. * retrieved using tcpedit_getwarn().
  298. */
  299. void
  300. tcpprep_setwarn(tcpprep_t *ctx, const char *fmt, ...)
  301. {
  302. va_list ap;
  303. assert(ctx);
  304. va_start(ap, fmt);
  305. if (fmt != NULL)
  306. (void)vsnprintf(ctx->warnstr, (TCPREPLAY_ERRSTR_LEN - 1), fmt, ap);
  307. va_end(ap);
  308. }
  309. /**
  310. * \brief When using AutoOpts, call to do post argument processing
  311. * Used to process the autoopts arguments
  312. */
  313. int
  314. tcpprep_post_args(tcpprep_t *ctx, int argc, char *argv[])
  315. {
  316. char myargs[MYARGS_LEN];
  317. int i, bufsize;
  318. char *tempstr;
  319. memset(myargs, 0, MYARGS_LEN);
  320. /* print_comment and print_info don't return */
  321. if (HAVE_OPT(PRINT_COMMENT))
  322. print_comment(OPT_ARG(PRINT_COMMENT));
  323. if (HAVE_OPT(PRINT_INFO))
  324. print_info(OPT_ARG(PRINT_INFO));
  325. if (HAVE_OPT(PRINT_STATS))
  326. print_stats(OPT_ARG(PRINT_STATS));
  327. if (! HAVE_OPT(CACHEFILE) && ! HAVE_OPT(PCAP))
  328. err(-1, "Must specify an output cachefile (-o) and input pcap (-i)");
  329. if (! ctx->options->mode)
  330. err(-1, "Must specify a processing mode: -a, -c, -r, -p");
  331. #ifdef DEBUG
  332. if (HAVE_OPT(DBUG))
  333. debug = OPT_VALUE_DBUG;
  334. #endif
  335. #ifdef ENABLE_VERBOSE
  336. if (HAVE_OPT(VERBOSE)) {
  337. ctx->options->verbose = 1;
  338. }
  339. if (HAVE_OPT(DECODE))
  340. ctx->tcpdump.args = safe_strdup(OPT_ARG(DECODE));
  341. #endif
  342. /*
  343. * if we are to include the cli args, then prep it for the
  344. * cache file header
  345. */
  346. if (! ctx->options->nocomment) {
  347. /* copy all of our args to myargs */
  348. for (i = 1; i < argc; i ++) {
  349. /* skip the -C <comment> */
  350. if (strcmp(argv[i], "-C") == 0) {
  351. i += 2;
  352. continue;
  353. }
  354. strlcat(myargs, argv[i], MYARGS_LEN);
  355. strlcat(myargs, " ", MYARGS_LEN);
  356. }
  357. /* remove trailing space */
  358. myargs[strlen(myargs) - 1] = 0;
  359. dbgx(1, "Comment args length: %zu", strlen(myargs));
  360. }
  361. /* setup or options.comment buffer so that that we get args\ncomment */
  362. if (ctx->options->comment != NULL) {
  363. strlcat(myargs, "\n", MYARGS_LEN);
  364. bufsize = strlen(ctx->options->comment) + strlen(myargs) + 1;
  365. ctx->options->comment = (char *)safe_realloc(ctx->options->comment,
  366. bufsize);
  367. tempstr = strdup(ctx->options->comment);
  368. strlcpy(ctx->options->comment, myargs, bufsize);
  369. strlcat(ctx->options->comment, tempstr, bufsize);
  370. safe_free(tempstr);
  371. } else {
  372. bufsize = strlen(myargs) + 1;
  373. ctx->options->comment = (char *)safe_malloc(bufsize);
  374. strlcpy(ctx->options->comment, myargs, bufsize);
  375. }
  376. dbgx(1, "Final comment length: %zu", strlen(ctx->options->comment));
  377. /* copy over our min/max mask */
  378. ctx->options->min_mask = OPT_VALUE_MINMASK;
  379. ctx->options->max_mask = OPT_VALUE_MAXMASK;
  380. if (!(ctx->options->min_mask > ctx->options->max_mask))
  381. errx(-1, "Min network mask len (%d) must be less then max network mask len (%d)",
  382. ctx->options->min_mask, ctx->options->max_mask);
  383. ctx->options->ratio = atof(OPT_ARG(RATIO));
  384. if (ctx->options->ratio < 0)
  385. err(-1, "Ratio must be a non-negative number.");
  386. return 0;
  387. }