send_packets.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /* $Id: send_packets.c 1462 2006-04-13 05:10:27Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2004 Aaron Turner.
  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 <sys/time.h>
  35. #include <sys/types.h>
  36. #include <signal.h>
  37. #include <string.h>
  38. #include <netinet/in.h>
  39. #include "tcpreplay.h"
  40. #ifdef TCPREPLAY
  41. #include "tcpreplay_opts.h"
  42. #endif
  43. #include "send_packets.h"
  44. extern tcpreplay_opt_t options;
  45. extern struct timeval begin, end;
  46. extern COUNTER bytes_sent, failed, pkts_sent;
  47. extern volatile int didsig;
  48. #ifdef HAVE_TCPDUMP
  49. extern tcpdump_t tcpdump;
  50. #endif
  51. #ifdef DEBUG
  52. extern int debug;
  53. #endif
  54. static void do_sleep(struct timeval *time, struct timeval *last, int len, libnet_t *l);
  55. /*
  56. * the main loop function. This is where we figure out
  57. * what to do with each packet
  58. */
  59. void
  60. send_packets(pcap_t *pcap)
  61. {
  62. struct timeval last = { 0, 0 };
  63. COUNTER packetnum = 0;
  64. struct pcap_pkthdr pkthdr;
  65. const u_char *pktdata = NULL;
  66. libnet_t *l = options.intf1;
  67. int ret; /* libnet return code */
  68. u_int32_t pktlen;
  69. /* register signals */
  70. didsig = 0;
  71. if (!options.speed.mode == SPEED_ONEATATIME) {
  72. (void)signal(SIGINT, catcher);
  73. }
  74. else {
  75. (void)signal(SIGINT, break_now);
  76. }
  77. /* MAIN LOOP
  78. * Keep sending while we have packets or until
  79. * we've sent enough packets
  80. */
  81. while ((pktdata = pcap_next(pcap, &pkthdr)) != NULL) {
  82. /* die? */
  83. if (didsig)
  84. break_now(0);
  85. dbgx(2, "packets sent " COUNTER_SPEC, pkts_sent);
  86. packetnum++;
  87. #ifdef TCPREPLAY
  88. /* do we use the snaplen (caplen) or the "actual" packet len? */
  89. pktlen = HAVE_OPT(PKTLEN) ? pkthdr.len : pkthdr.caplen;
  90. #elif TCPBRIDGE
  91. pktlen = pkthdr.caplen;
  92. #else
  93. #error WTF??? We should not be here!
  94. #endif
  95. dbgx(2, "packet " COUNTER_SPEC " caplen %d", packetnum, pktlen);
  96. /* Dual nic processing */
  97. if (options.intf2 != NULL) {
  98. l = (libnet_t *) cache_mode(options.cachedata, packetnum);
  99. /* sometimes we should not send the packet */
  100. if (l == CACHE_NOSEND)
  101. continue;
  102. }
  103. /* do we need to print the packet via tcpdump? */
  104. #ifdef HAVE_TCPDUMP
  105. if (options.verbose)
  106. tcpdump_print(&tcpdump, &pkthdr, pktdata);
  107. #endif
  108. /*
  109. * we have to cast the ts, since OpenBSD sucks
  110. * had to be special and use bpf_timeval
  111. */
  112. do_sleep((struct timeval *)&pkthdr.ts, &last, pktlen, l);
  113. /* write packet out on network */
  114. do {
  115. ret = libnet_adv_write_link(l, pktdata, pktlen);
  116. if (ret == -1) {
  117. /* Make note of failed writes due to full buffers */
  118. if (errno == ENOBUFS) {
  119. failed++;
  120. } else {
  121. errx(1, "Unable to send packet: %s", strerror(errno));
  122. }
  123. }
  124. /* keep trying if fail, unless user Ctrl-C's */
  125. } while (ret == -1 && !didsig);
  126. bytes_sent += pktlen;
  127. pkts_sent++;
  128. /*
  129. * track the time of the "last packet sent". Again, because of OpenBSD
  130. * we have to do a mempcy rather then assignment
  131. */
  132. memcpy(&last, &pkthdr.ts, sizeof(struct timeval));
  133. } /* while */
  134. }
  135. /*
  136. * determines based upon the cachedata which interface the given packet
  137. * should go out. Also rewrites any layer 2 data we might need to adjust.
  138. * Returns a void cased pointer to the options.intfX of the corresponding
  139. * interface.
  140. */
  141. void *
  142. cache_mode(char *cachedata, COUNTER packet_num)
  143. {
  144. void *l = NULL;
  145. int result;
  146. if (packet_num > options.cache_packets)
  147. err(1, "Exceeded number of packets in cache file.");
  148. result = check_cache(cachedata, packet_num);
  149. if (result == CACHE_NOSEND) {
  150. dbgx(2, "Cache: Not sending packet " COUNTER_SPEC ".", packet_num);
  151. return CACHE_NOSEND;
  152. }
  153. else if (result == CACHE_PRIMARY) {
  154. dbgx(2, "Cache: Sending packet " COUNTER_SPEC " out primary interface.", packet_num);
  155. l = options.intf1;
  156. }
  157. else if (result == CACHE_SECONDARY) {
  158. dbgx(2, "Cache: Sending packet " COUNTER_SPEC " out secondary interface.", packet_num);
  159. l = options.intf2;
  160. }
  161. else {
  162. err(1, "check_cache() returned an error. Aborting...");
  163. }
  164. return l;
  165. }
  166. /*
  167. * Given the timestamp on the current packet and the last packet sent,
  168. * calculate the appropriate amount of time to sleep and do so.
  169. */
  170. static void
  171. do_sleep(struct timeval *time, struct timeval *last, int len, libnet_t *l)
  172. {
  173. static struct timeval didsleep = { 0, 0 };
  174. static struct timeval start = { 0, 0 };
  175. struct timeval nap, now, delta;
  176. struct timespec ignore, sleep;
  177. float n;
  178. struct pollfd poller[1]; /* use poll to read from the keyboard */
  179. char input[EBUF_SIZE];
  180. static u_int32_t send = 0; /* remember # of packets to send btw calls */
  181. /* just return if topspeed */
  182. if (options.speed.mode == SPEED_TOPSPEED)
  183. return;
  184. dbgx(3, "Last time: " TIMEVAL_FORMAT, last->tv_sec, last->tv_usec);
  185. if (gettimeofday(&now, NULL) < 0) {
  186. errx(1, "Error gettimeofday: %s", strerror(errno));
  187. }
  188. dbgx(3, "Now time: " TIMEVAL_FORMAT, now.tv_sec, now.tv_usec);
  189. /* First time through for this file */
  190. if (!timerisset(last)) {
  191. start = now;
  192. timerclear(&delta);
  193. timerclear(&didsleep);
  194. }
  195. else {
  196. timersub(&now, &start, &delta);
  197. }
  198. switch(options.speed.mode) {
  199. case SPEED_MULTIPLIER:
  200. /*
  201. * Replay packets a factor of the time they were originally sent.
  202. */
  203. if (timerisset(last) && timercmp(time, last, >)) {
  204. timersub(time, last, &nap);
  205. timerdiv(&nap, options.speed.speed);
  206. }
  207. else {
  208. /*
  209. * Don't sleep if this is our first packet, or if the
  210. * this packet appears to have been sent before the
  211. * last packet.
  212. */
  213. timerclear(&nap);
  214. }
  215. break;
  216. case SPEED_MBPSRATE:
  217. /*
  218. * Ignore the time supplied by the capture file and send data at
  219. * a constant 'rate' (bytes per second).
  220. */
  221. if (timerisset(last)) {
  222. n = (float)len / (options.speed.speed * 1024 * 1024 / 8); /* convert Mbps to bps */
  223. nap.tv_sec = n;
  224. nap.tv_usec = (n - nap.tv_sec) * 1000000;
  225. dbgx(3, "packet size %d\t\tequals %f bps\t\tnap " TIMEVAL_FORMAT, len, n,
  226. nap.tv_sec, nap.tv_usec);
  227. }
  228. else {
  229. timerclear(&nap);
  230. }
  231. break;
  232. case SPEED_PACKETRATE:
  233. /* run in packets/sec */
  234. n = 1 / options.speed.speed;
  235. nap.tv_sec = n;
  236. n -= nap.tv_sec;
  237. nap.tv_usec = n * 1000000;
  238. break;
  239. case SPEED_ONEATATIME:
  240. /* do we skip prompting for a key press? */
  241. if (send == 0) {
  242. printf("**** How many packets do you wish to send? (next packet out %s): ",
  243. l == options.intf1 ? options.intf1_name : options.intf2_name);
  244. fflush(NULL);
  245. poller[0].fd = STDIN_FILENO;
  246. poller[0].events = POLLIN;
  247. poller[0].revents = 0;
  248. /* wait for the input */
  249. if (poll(poller, 1, -1) < 0)
  250. errx(1, "Error reading from stdin: %s", strerror(errno));
  251. /*
  252. * read to the end of the line or EBUF_SIZE,
  253. * Note, if people are stupid, and type in more text then EBUF_SIZE
  254. * then the next fgets() will pull in that data, which will have poor
  255. * results. fuck them.
  256. */
  257. fgets(input, sizeof(input), stdin);
  258. if (strlen(input) > 1) {
  259. send = strtoul(input, NULL, 0);
  260. }
  261. /* how many packets should we send? */
  262. if (send == 0) {
  263. dbg(1, "Input was less then 1 or non-numeric, assuming 1");
  264. /* assume send only one packet */
  265. send = 1;
  266. }
  267. }
  268. /* decrement our send counter */
  269. printf("Sending packet out: %s\n",
  270. l == options.intf1 ? options.intf1_name : options.intf2_name);
  271. send --;
  272. /* leave do_sleep() */
  273. return;
  274. break;
  275. default:
  276. errx(1, "Unknown/supported speed mode: %d", options.speed.mode);
  277. break;
  278. }
  279. timeradd(&didsleep, &nap, &didsleep);
  280. dbgx(4, "I will sleep " TIMEVAL_FORMAT, nap.tv_sec, nap.tv_usec);
  281. if (timercmp(&didsleep, &delta, >)) {
  282. timersub(&didsleep, &delta, &nap);
  283. sleep.tv_sec = nap.tv_sec;
  284. sleep.tv_nsec = nap.tv_usec * 1000; /* convert ms to ns */
  285. if (nanosleep(&sleep, &ignore) == -1) {
  286. warnx("nanosleep error: %s", strerror(errno));
  287. }
  288. }
  289. }
  290. /*
  291. Local Variables:
  292. mode:c
  293. indent-tabs-mode:nil
  294. c-basic-offset:4
  295. End:
  296. */