tcpreplay.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* $Id: tcpreplay.c 1556 2006-07-31 06:12:01Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2005 Aaron Turner <aturner@pobox.com>.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include "defines.h"
  33. #include "common.h"
  34. #include <ctype.h>
  35. #include <fcntl.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sys/types.h>
  40. #include <unistd.h>
  41. #include <errno.h>
  42. #include "tcpreplay.h"
  43. #include "tcpreplay_opts.h"
  44. #include "send_packets.h"
  45. #include "signal_handler.h"
  46. tcpreplay_opt_t options;
  47. struct timeval begin, end;
  48. COUNTER bytes_sent, failed, pkts_sent;
  49. int cache_bit, cache_byte;
  50. volatile int didsig;
  51. #ifdef HAVE_TCPDUMP
  52. /* tcpdump handle */
  53. tcpdump_t tcpdump;
  54. #endif
  55. #ifdef DEBUG
  56. int debug = 0;
  57. #endif
  58. void replay_file(char *path);
  59. void usage(void);
  60. void init(void);
  61. void post_args(void);
  62. int
  63. main(int argc, char *argv[])
  64. {
  65. int i, optct = 0;
  66. init(); /* init our globals */
  67. optct = optionProcess(&tcpreplayOptions, argc, argv);
  68. argc -= optct;
  69. argv += optct;
  70. post_args();
  71. for (i = 0; i < argc; i++)
  72. options.files[i] = safe_strdup(argv[i]);
  73. /* init the signal handlers */
  74. init_signal_handlers();
  75. if (gettimeofday(&begin, NULL) < 0)
  76. err(1, "gettimeofday() failed");
  77. /* main loop for non-bridge mode */
  78. if (options.loop > 0) {
  79. while (options.loop--) { /* limited loop */
  80. /* process each pcap file in order */
  81. for (i = 0; i < argc; i++) {
  82. /* reset cache markers for each iteration */
  83. cache_byte = 0;
  84. cache_bit = 0;
  85. replay_file(argv[i]);
  86. }
  87. }
  88. }
  89. else {
  90. /* loop forever */
  91. while (1) {
  92. for (i = 0; i < argc; i++) {
  93. /* reset cache markers for each iteration */
  94. cache_byte = 0;
  95. cache_bit = 0;
  96. replay_file(argv[i]);
  97. }
  98. }
  99. }
  100. if (bytes_sent > 0)
  101. packet_stats(&begin, &end, bytes_sent, pkts_sent, failed);
  102. return 0;
  103. } /* main() */
  104. /*
  105. * replay a pcap file out an interface
  106. */
  107. void
  108. replay_file(char *path)
  109. {
  110. pcap_t *pcap = NULL;
  111. char ebuf[PCAP_ERRBUF_SIZE];
  112. #ifdef HAVE_TCPDUMP
  113. if (options.verbose) {
  114. tcpdump.filename = path;
  115. tcpdump_open(&tcpdump);
  116. }
  117. #endif
  118. notice("processing file: %s", path);
  119. /* close stdin if reading from it (needed for some OS's) */
  120. if (strncmp(path, "-", 1) == 0)
  121. if (close(1) == -1)
  122. warnx("unable to close stdin: %s", strerror(errno));
  123. if ((pcap = pcap_open_offline(path, ebuf)) == NULL)
  124. errx(1, "Error opening pcap file: %s", ebuf);
  125. send_packets(pcap);
  126. pcap_close(pcap);
  127. #ifdef HAVE_TCPDUMP
  128. tcpdump_close(&tcpdump);
  129. #endif
  130. }
  131. /*
  132. * Initialize globals
  133. */
  134. void
  135. init(void)
  136. {
  137. bytes_sent = failed = pkts_sent = 0;
  138. memset(&options, 0, sizeof(options));
  139. /* replay packets only once */
  140. options.loop = 1;
  141. /* Default mode is to replay pcap once in real-time */
  142. options.speed.mode = SPEED_MULTIPLIER;
  143. options.speed.speed = 1.0;
  144. /* set the default MTU size */
  145. options.mtu = DEFAULT_MTU;
  146. /* disable limit send */
  147. options.limit_send = -1;
  148. #ifdef HAVE_TCPDUMP
  149. /* clear out tcpdump struct */
  150. memset(&tcpdump, '\0', sizeof(tcpdump_t));
  151. #endif
  152. cache_bit = cache_byte = 0;
  153. if (fcntl(STDERR_FILENO, F_SETFL, O_NONBLOCK) < 0)
  154. warnx("Unable to set STDERR to non-blocking: %s", strerror(errno));
  155. }
  156. /*
  157. * post processes the args and puts them into our options
  158. */
  159. void
  160. post_args(void)
  161. {
  162. char *temp;
  163. char ebuf[SENDPACKET_ERRBUF_SIZE];
  164. #ifdef DEBUG
  165. if (HAVE_OPT(DBUG))
  166. debug = OPT_VALUE_DBUG;
  167. #else
  168. if (HAVE_OPT(DBUG))
  169. warn("not configured with --enable-debug. Debugging disabled.");
  170. #endif
  171. options.loop = OPT_VALUE_LOOP;
  172. /* Currently disabled
  173. if (HAVE_OPT(LIMIT))
  174. options.limit_send = OPT_VALUE_LIMIT;
  175. */
  176. if (HAVE_OPT(TOPSPEED)) {
  177. options.speed.mode = SPEED_TOPSPEED;
  178. options.speed.speed = 0.0;
  179. } else if (HAVE_OPT(PPS)) {
  180. options.speed.mode = SPEED_PACKETRATE;
  181. options.speed.speed = (float)OPT_VALUE_PPS;
  182. } else if (HAVE_OPT(ONEATATIME)) {
  183. options.speed.mode = SPEED_ONEATATIME;
  184. options.speed.speed = 0.0;
  185. } else if (HAVE_OPT(MBPS)) {
  186. options.speed.mode = SPEED_MBPSRATE;
  187. options.speed.speed = atof(OPT_ARG(MBPS));
  188. } else if (HAVE_OPT(MULTIPLIER)) {
  189. options.speed.mode = SPEED_MULTIPLIER;
  190. options.speed.speed = atof(OPT_ARG(MULTIPLIER));
  191. }
  192. #ifdef HAVE_TCPDUMP
  193. if (HAVE_OPT(VERBOSE))
  194. options.verbose = 1;
  195. if (HAVE_OPT(DECODE))
  196. tcpdump.args = safe_strdup(OPT_ARG(DECODE));
  197. #endif
  198. if (HAVE_OPT(ACCURATE))
  199. options.accurate = 1;
  200. if (HAVE_OPT(PKTLEN))
  201. warn("--pktlen may cause problems. Use with caution.");
  202. options.intf1_name = (char *)safe_malloc(strlen(OPT_ARG(INTF1)) + 1);
  203. strncpy(options.intf1_name, OPT_ARG(INTF1), strlen(OPT_ARG(INTF1)));
  204. /* open interfaces for writing */
  205. if ((options.intf1 = sendpacket_open(options.intf1_name, ebuf)) == NULL)
  206. errx(1, "Can't open %s: %s", options.intf1_name, ebuf);
  207. if (HAVE_OPT(INTF2)) {
  208. options.intf2_name = (char *)safe_malloc(strlen(OPT_ARG(INTF2)) + 1);
  209. strncpy(options.intf2_name, OPT_ARG(INTF2), strlen(OPT_ARG(INTF2)));
  210. /* open interface for writing */
  211. if ((options.intf2 = sendpacket_open(options.intf2_name, ebuf)) == NULL)
  212. errx(1, "Can't open %s: %s", options.intf2_name, ebuf);
  213. }
  214. if (HAVE_OPT(CACHEFILE)) {
  215. temp = safe_strdup(OPT_ARG(CACHEFILE));
  216. options.cache_packets = read_cache(&options.cachedata, temp,
  217. &options.comment);
  218. free(temp);
  219. }
  220. notice("sending out %s %s", options.intf1_name,
  221. options.intf2_name == NULL ? "" : options.intf2_name);
  222. }
  223. /*
  224. Local Variables:
  225. mode:c
  226. indent-tabs-mode:nil
  227. c-basic-offset:4
  228. End:
  229. */