send_packets.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /* $Id: send_packets.c 2008 2008-05-01 18:39:05Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2008 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 <errno.h>
  40. #include <stdlib.h>
  41. #include <unistd.h>
  42. #include <fcntl.h>
  43. #include "tcpreplay.h"
  44. #ifdef TCPREPLAY
  45. #include "tcpreplay_opts.h"
  46. #ifdef TCPREPLAY_EDIT
  47. #include "tcpedit/tcpedit.h"
  48. extern tcpedit_t *tcpedit;
  49. #endif
  50. #endif /* TCPREPLAY */
  51. #include "send_packets.h"
  52. #include "sleep.h"
  53. extern tcpreplay_opt_t options;
  54. extern struct timeval begin, end;
  55. extern COUNTER bytes_sent, failed, pkts_sent;
  56. extern volatile int didsig;
  57. #ifdef DEBUG
  58. extern int debug;
  59. #endif
  60. static void do_sleep(struct timeval *time, struct timeval *last, int len,
  61. int accurate, sendpacket_t *sp, COUNTER counter, delta_t *ctx);
  62. static const u_char *get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr,
  63. int file_idx, packet_cache_t **prev_packet);
  64. static u_int32_t get_user_count(sendpacket_t *sp, COUNTER counter);
  65. /**
  66. * the main loop function for tcpreplay. This is where we figure out
  67. * what to do with each packet
  68. */
  69. void
  70. send_packets(pcap_t *pcap, int cache_file_idx)
  71. {
  72. struct timeval last = { 0, 0 };
  73. COUNTER packetnum = 0;
  74. struct pcap_pkthdr pkthdr;
  75. const u_char *pktdata = NULL;
  76. sendpacket_t *sp = options.intf1;
  77. u_int32_t pktlen;
  78. packet_cache_t *cached_packet = NULL;
  79. packet_cache_t **prev_packet = NULL;
  80. #if defined TCPREPLAY && defined TCPREPLAY_EDIT
  81. struct pcap_pkthdr *pkthdr_ptr;
  82. #endif
  83. delta_t delta_ctx;
  84. /* register signals */
  85. didsig = 0;
  86. if (options.speed.mode != SPEED_ONEATATIME) {
  87. (void)signal(SIGINT, catcher);
  88. } else {
  89. (void)signal(SIGINT, break_now);
  90. }
  91. if (options.enable_file_cache) {
  92. prev_packet = &cached_packet;
  93. } else {
  94. prev_packet = NULL;
  95. }
  96. /* MAIN LOOP
  97. * Keep sending while we have packets or until
  98. * we've sent enough packets
  99. */
  100. while ((pktdata = get_next_packet(pcap, &pkthdr, cache_file_idx, prev_packet)) != NULL) {
  101. /* die? */
  102. if (didsig)
  103. break_now(0);
  104. /* stop sending based on the limit -L? */
  105. if (options.limit_send > 0 && pkts_sent >= options.limit_send)
  106. return;
  107. packetnum++;
  108. #ifdef TCPREPLAY
  109. /* do we use the snaplen (caplen) or the "actual" packet len? */
  110. pktlen = HAVE_OPT(PKTLEN) ? pkthdr.len : pkthdr.caplen;
  111. #elif TCPBRIDGE
  112. pktlen = pkthdr.caplen;
  113. #else
  114. #error WTF??? We should not be here!
  115. #endif
  116. dbgx(2, "packet " COUNTER_SPEC " caplen %d", packetnum, pktlen);
  117. /* Dual nic processing */
  118. if (options.intf2 != NULL) {
  119. sp = (sendpacket_t *) cache_mode(options.cachedata, packetnum);
  120. /* sometimes we should not send the packet */
  121. if (sp == TCPR_DIR_NOSEND)
  122. continue;
  123. }
  124. /* do we need to print the packet via tcpdump? */
  125. #ifdef ENABLE_VERBOSE
  126. if (options.verbose)
  127. tcpdump_print(options.tcpdump, &pkthdr, pktdata);
  128. #endif
  129. #if defined TCPREPLAY && defined TCPREPLAY_EDIT
  130. pkthdr_ptr = &pkthdr;
  131. if (tcpedit_packet(tcpedit, &pkthdr_ptr, &pktdata, sp->cache_dir) == -1) {
  132. errx(1, "Error editing packet #" COUNTER_SPEC ": %s", packetnum, tcpedit_geterr(tcpedit));
  133. }
  134. pktlen = HAVE_OPT(PKTLEN) ? pkthdr_ptr->len : pkthdr_ptr->caplen;
  135. #endif
  136. /*
  137. * we have to cast the ts, since OpenBSD sucks
  138. * had to be special and use bpf_timeval.
  139. * Only sleep if we're not in top speed mode (-t)
  140. */
  141. if (options.speed.mode != SPEED_TOPSPEED)
  142. do_sleep((struct timeval *)&pkthdr.ts, &last, pktlen, options.accurate, sp, packetnum, &delta_ctx);
  143. /* mark the time when we send the packet */
  144. start_delta_time(&delta_ctx);
  145. /* write packet out on network */
  146. if (sendpacket(sp, pktdata, pktlen) < (int)pktlen)
  147. warnx("Unable to send packet: %s", sendpacket_geterr(sp));
  148. /*
  149. * track the time of the "last packet sent". Again, because of OpenBSD
  150. * we have to do a mempcy rather then assignment.
  151. *
  152. * A number of 3rd party tools generate bad timestamps which go backwards
  153. * in time. Hence, don't update the "last" unless pkthdr.ts > last
  154. */
  155. if (timercmp(&last, &pkthdr.ts, <))
  156. memcpy(&last, &pkthdr.ts, sizeof(struct timeval));
  157. pkts_sent ++;
  158. bytes_sent += pktlen;
  159. } /* while */
  160. if (options.enable_file_cache) {
  161. options.file_cache[cache_file_idx].cached = TRUE;
  162. }
  163. }
  164. /**
  165. * Gets the next packet to be sent out. This will either read from the pcap file
  166. * or will retrieve the packet from the internal cache.
  167. *
  168. * The parameter prev_packet is used as the parent of the new entry in the cache list.
  169. * This should be NULL on the first call to this function for each file and
  170. * will be updated as new entries are added (or retrieved) from the cache list.
  171. */
  172. static const u_char *
  173. get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, int file_idx,
  174. packet_cache_t **prev_packet)
  175. {
  176. u_char *pktdata = NULL;
  177. u_int32_t pktlen;
  178. /* pcap may be null in cache mode! */
  179. /* packet_cache_t may be null in file read mode! */
  180. assert(pkthdr);
  181. /*
  182. * Check if we're caching files
  183. */
  184. if (options.enable_file_cache && (prev_packet != NULL)) {
  185. /*
  186. * Yes we are caching files - has this one been cached?
  187. */
  188. if (options.file_cache[file_idx].cached) {
  189. if (*prev_packet == NULL) {
  190. /*
  191. * Get the first packet in the cache list directly from the file
  192. */
  193. *prev_packet = options.file_cache[file_idx].packet_cache;
  194. } else {
  195. /*
  196. * Get the next packet in the cache list
  197. */
  198. *prev_packet = (*prev_packet)->next;
  199. }
  200. if (*prev_packet != NULL) {
  201. pktdata = (*prev_packet)->pktdata;
  202. memcpy(pkthdr, &((*prev_packet)->pkthdr), sizeof(struct pcap_pkthdr));
  203. }
  204. } else {
  205. /*
  206. * We should read the pcap file, and cache the results
  207. */
  208. pktdata = (u_char *)pcap_next(pcap, pkthdr);
  209. if (pktdata != NULL) {
  210. if (*prev_packet == NULL) {
  211. /*
  212. * Create the first packet in the list
  213. */
  214. *prev_packet = safe_malloc(sizeof(packet_cache_t));
  215. options.file_cache[file_idx].packet_cache = *prev_packet;
  216. } else {
  217. /*
  218. * Add a packet to the end of the list
  219. */
  220. (*prev_packet)->next = safe_malloc(sizeof(packet_cache_t));
  221. *prev_packet = (*prev_packet)->next;
  222. }
  223. if (*prev_packet != NULL) {
  224. (*prev_packet)->next = NULL;
  225. pktlen = pkthdr->len;
  226. (*prev_packet)->pktdata = safe_malloc(pktlen);
  227. memcpy((*prev_packet)->pktdata, pktdata, pktlen);
  228. memcpy(&((*prev_packet)->pkthdr), pkthdr, sizeof(struct pcap_pkthdr));
  229. }
  230. }
  231. }
  232. } else {
  233. /*
  234. * Read pcap file as normal
  235. */
  236. pktdata = (u_char *)pcap_next(pcap, pkthdr);
  237. }
  238. /* this get's casted to a const on the way out */
  239. return pktdata;
  240. }
  241. /**
  242. * determines based upon the cachedata which interface the given packet
  243. * should go out. Also rewrites any layer 2 data we might need to adjust.
  244. * Returns a void cased pointer to the options.intfX of the corresponding
  245. * interface.
  246. */
  247. void *
  248. cache_mode(char *cachedata, COUNTER packet_num)
  249. {
  250. void *sp = NULL;
  251. int result;
  252. if (packet_num > options.cache_packets)
  253. err(1, "Exceeded number of packets in cache file.");
  254. result = check_cache(cachedata, packet_num);
  255. if (result == TCPR_DIR_NOSEND) {
  256. dbgx(2, "Cache: Not sending packet " COUNTER_SPEC ".", packet_num);
  257. return TCPR_DIR_NOSEND;
  258. }
  259. else if (result == TCPR_DIR_C2S) {
  260. dbgx(2, "Cache: Sending packet " COUNTER_SPEC " out primary interface.", packet_num);
  261. sp = options.intf1;
  262. }
  263. else if (result == TCPR_DIR_S2C) {
  264. dbgx(2, "Cache: Sending packet " COUNTER_SPEC " out secondary interface.", packet_num);
  265. sp = options.intf2;
  266. }
  267. else {
  268. err(1, "check_cache() returned an error. Aborting...");
  269. }
  270. return sp;
  271. }
  272. /**
  273. * Given the timestamp on the current packet and the last packet sent,
  274. * calculate the appropriate amount of time to sleep and do so.
  275. */
  276. static void
  277. do_sleep(struct timeval *time, struct timeval *last, int len, int accurate,
  278. sendpacket_t *sp, COUNTER counter, delta_t *delta_ctx)
  279. {
  280. static struct timeval didsleep = { 0, 0 };
  281. static struct timeval start = { 0, 0 };
  282. #ifdef DEBUG
  283. static struct timeval totalsleep = { 0, 0 };
  284. #endif
  285. struct timespec adjuster = { 0, 0 };
  286. static struct timespec nap = { 0, 0 }, delta_time = {0, 0};
  287. struct timeval nap_for, now, sleep_until;
  288. struct timespec nap_this_time;
  289. static int32_t nsec_adjuster = -1, nsec_times = -1;
  290. float n;
  291. static u_int32_t send = 0; /* accellerator. # of packets to send w/o sleeping */
  292. u_int64_t ppnsec; /* packets per usec */
  293. #ifdef TCPREPLAY
  294. adjuster.tv_nsec = OPT_VALUE_SLEEP_ACCEL * 1000;
  295. dbgx(2, "Adjuster: " TIMEVAL_FORMAT, adjuster.tv_sec, adjuster.tv_nsec);
  296. #else
  297. adjuster.tv_nsec = 0;
  298. #endif
  299. /* acclerator time? */
  300. if (send > 0) {
  301. send --;
  302. return;
  303. }
  304. dbgx(4, "Last time: " TIMEVAL_FORMAT, last->tv_sec, last->tv_usec);
  305. if (gettimeofday(&now, NULL) < 0)
  306. errx(1, "Error gettimeofday: %s", strerror(errno));
  307. dbgx(4, "Now time: " TIMEVAL_FORMAT, now.tv_sec, now.tv_usec);
  308. /* First time through for this file */
  309. if (pkts_sent == 0 || ((options.speed.mode != SPEED_MBPSRATE) && (counter == 0))) {
  310. start = now;
  311. timerclear(&sleep_until);
  312. timerclear(&didsleep);
  313. }
  314. else {
  315. timersub(&now, &start, &sleep_until);
  316. }
  317. switch(options.speed.mode) {
  318. /*
  319. * If top speed, you shouldn't even be here, but handle it anyways
  320. */
  321. case SPEED_TOPSPEED:
  322. notice("you shouldn't call do_sleep() in top speed mode.");
  323. return;
  324. break;
  325. case SPEED_MULTIPLIER:
  326. /*
  327. * Replay packets a factor of the time they were originally sent.
  328. */
  329. if (timerisset(last) && timercmp(time, last, >)) {
  330. timersub(time, last, &nap_for);
  331. TIMEVAL_TO_TIMESPEC(&nap_for, &nap);
  332. timesdiv(&nap, options.speed.speed);
  333. }
  334. else {
  335. /*
  336. * Don't sleep if this is our first packet, or if the
  337. * this packet appears to have been sent before the
  338. * last packet.
  339. */
  340. timesclear(&nap);
  341. }
  342. break;
  343. case SPEED_MBPSRATE:
  344. /*
  345. * Ignore the time supplied by the capture file and send data at
  346. * a constant 'rate' (bytes per second).
  347. */
  348. if (pkts_sent != 0) {
  349. n = (float)len / (options.speed.speed * 1024 * 1024 / 8); /* convert Mbps to bps */
  350. nap.tv_sec = n;
  351. nap.tv_nsec = (n - nap.tv_sec) * 1000000000;
  352. dbgx(3, "packet size %d\t\tequals %f bps\t\tnap " TIMEVAL_FORMAT, len, n,
  353. nap.tv_sec, nap.tv_nsec);
  354. }
  355. else {
  356. /* don't sleep at all for the first packet */
  357. timesclear(&nap);
  358. }
  359. break;
  360. case SPEED_PACKETRATE:
  361. /* only need to calculate this the first time */
  362. if (! timesisset(&nap)) {
  363. /* run in packets/sec */
  364. ppnsec = 1000000000 / options.speed.speed;
  365. NANOSEC_TO_TIMESPEC(ppnsec, &nap);
  366. dbgx(1, "sending 1 packet per %lu nsec", nap.tv_nsec);
  367. }
  368. break;
  369. case SPEED_ONEATATIME:
  370. /* do we skip prompting for a key press? */
  371. if (send == 0) {
  372. send = get_user_count(sp, counter);
  373. }
  374. /* decrement our send counter */
  375. printf("Sending packet " COUNTER_SPEC " out: %s\n", counter,
  376. sp == options.intf1 ? options.intf1_name : options.intf2_name);
  377. send --;
  378. /* leave do_sleep() */
  379. return;
  380. break;
  381. default:
  382. errx(1, "Unknown/supported speed mode: %d", options.speed.mode);
  383. break;
  384. }
  385. /*
  386. * since we apply the adjuster to the sleep time, we can't modify nap
  387. */
  388. nap_this_time.tv_sec = nap.tv_sec;
  389. nap_this_time.tv_nsec = nap.tv_nsec;
  390. if (accurate != ACCURATE_ABS_TIME) {
  391. switch (options.speed.mode) {
  392. /* Mbps & Multipler are dynamic timings, so we round to the nearest usec */
  393. case SPEED_MBPSRATE:
  394. case SPEED_MULTIPLIER:
  395. ROUND_TIMESPEC_TO_MICROSEC(&nap_this_time);
  396. break;
  397. /* Packets/sec is static, so we weight packets for .1usec accuracy */
  398. case SPEED_PACKETRATE:
  399. if (nsec_adjuster < 0)
  400. nsec_adjuster = (nap_this_time.tv_nsec % 10000) / 1000;
  401. /* update in the range of 0-9 */
  402. nsec_times = (nsec_times + 1) % 10;
  403. if (nsec_times < nsec_adjuster) {
  404. /* sorta looks like a no-op, but gives us a nice round usec number */
  405. nap_this_time.tv_nsec = (nap_this_time.tv_nsec / 1000 * 1000) + 1000;
  406. } else {
  407. nap_this_time.tv_nsec -= (nap_this_time.tv_nsec % 1000);
  408. }
  409. dbgx(3, "(%ld)\tnsec_times = %ld\tnap adjust: %lu -> %lu", nsec_adjuster, nsec_times, nap.tv_nsec, nap_this_time.tv_nsec);
  410. break;
  411. default:
  412. errx(1, "Unknown/supported speed mode: %d", options.speed.mode);
  413. }
  414. }
  415. get_delta_time(delta_ctx, &delta_time);
  416. dbgx(2, "delta: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec);
  417. if (timesisset(&delta_time)) {
  418. if (timescmp(&nap_this_time, &delta_time, >)) {
  419. timessub(&nap_this_time, &delta_time, &nap_this_time);
  420. dbgx(3, "timesub: %lu %lu", delta_time.tv_sec, delta_time.tv_nsec);
  421. } else {
  422. timesclear(&nap_this_time);
  423. dbgx(3, "timesclear: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec);
  424. }
  425. }
  426. /* apply the adjuster... */
  427. if (timesisset(&adjuster)) {
  428. if (timescmp(&nap_this_time, &adjuster, >)) {
  429. timessub(&nap_this_time, &adjuster, &nap_this_time);
  430. } else {
  431. timesclear(&nap_this_time);
  432. }
  433. }
  434. dbgx(2, "Sleeping: " TIMESPEC_FORMAT, nap_this_time.tv_sec, nap_this_time.tv_nsec);
  435. /* don't sleep if nap = {0, 0} */
  436. if (!timesisset(&nap_this_time))
  437. return;
  438. /*
  439. * Depending on the accurate method & packet rate computation method
  440. * We have multiple methods of sleeping, pick the right one...
  441. */
  442. switch (accurate) {
  443. #ifdef HAVE_SELECT
  444. case ACCURATE_SELECT:
  445. select_sleep(nap_this_time);
  446. break;
  447. #endif
  448. #ifdef HAVE_IOPERM
  449. case ACCURATE_IOPORT:
  450. ioport_sleep(nap_this_time);
  451. break;
  452. #endif
  453. #ifdef HAVE_RDTSC
  454. case ACCURATE_RDTSC:
  455. rdtsc_sleep(nap_this_time);
  456. break;
  457. #endif
  458. #ifdef HAVE_ABSOLUTE_TIME
  459. case ACCURATE_ABS_TIME:
  460. absolute_time_sleep(nap_this_time);
  461. break;
  462. #endif
  463. case ACCURATE_GTOD:
  464. gettimeofday_sleep(nap_this_time);
  465. break;
  466. case ACCURATE_NANOSLEEP:
  467. nanosleep_sleep(nap_this_time);
  468. break;
  469. /*
  470. timeradd(&didsleep, &nap_this_time, &didsleep);
  471. dbgx(4, "I will sleep " TIMEVAL_FORMAT, nap_this_time.tv_sec, nap_this_time.tv_usec);
  472. if (timercmp(&didsleep, &sleep_until, >)) {
  473. timersub(&didsleep, &sleep_until, &nap_this_time);
  474. TIMEVAL_TO_TIMESPEC(&nap_this_time, &sleep);
  475. dbgx(4, "Sleeping " TIMEVAL_FORMAT, nap_this_time.tv_sec, nap_this_time.tv_usec);
  476. #ifdef DEBUG
  477. timeradd(&totalsleep, &nap_this_time, &totalsleep);
  478. #endif
  479. if (nanosleep(&sleep, &ignore) == -1) {
  480. warnx("nanosleep error: %s", strerror(errno));
  481. }
  482. }
  483. break;
  484. */
  485. default:
  486. errx(1, "Unknown timer mode %d", accurate);
  487. }
  488. #ifdef DEBUG
  489. dbgx(4, "Total sleep time: " TIMEVAL_FORMAT, totalsleep.tv_sec, totalsleep.tv_usec);
  490. #endif
  491. dbgx(2, "sleep delta: " TIMESPEC_FORMAT, delta_time.tv_sec, delta_time.tv_nsec);
  492. }
  493. /**
  494. * this function will keep calling gettimeofday() until it returns
  495. * >= time. This should be a lot more accurate then using nanosleep(),
  496. * but at the cost of being more CPU intensive.
  497. */
  498. static u_int32_t
  499. get_user_count(sendpacket_t *sp, COUNTER counter)
  500. {
  501. struct pollfd poller[1]; /* use poll to read from the keyboard */
  502. char input[EBUF_SIZE];
  503. u_int32_t send = 0;
  504. printf("**** Next packet #" COUNTER_SPEC " out %s. How many packets do you wish to send? ",
  505. counter, (sp == options.intf1 ? options.intf1_name : options.intf2_name));
  506. fflush(NULL);
  507. poller[0].fd = STDIN_FILENO;
  508. poller[0].events = POLLIN | POLLPRI | POLLNVAL;
  509. poller[0].revents = 0;
  510. if (fcntl(0, F_SETFL, fcntl(0, F_GETFL) & ~O_NONBLOCK))
  511. errx(1, "Unable to clear non-blocking flag on stdin: %s", strerror(errno));
  512. /* wait for the input */
  513. if (poll(poller, 1, -1) < 0)
  514. errx(1, "Error reading user input from stdin: %s", strerror(errno));
  515. /*
  516. * read to the end of the line or EBUF_SIZE,
  517. * Note, if people are stupid, and type in more text then EBUF_SIZE
  518. * then the next fgets() will pull in that data, which will have poor
  519. * results. fuck them.
  520. */
  521. if (fgets(input, sizeof(input), stdin) == NULL) {
  522. errx(1, "Unable to process user input for fd %d: %s", fileno(stdin), strerror(errno));
  523. } else if (strlen(input) > 1) {
  524. send = strtoul(input, NULL, 0);
  525. }
  526. /* how many packets should we send? */
  527. if (send == 0) {
  528. dbg(1, "Input was less then 1 or non-numeric, assuming 1");
  529. /* assume send only one packet */
  530. send = 1;
  531. }
  532. return send;
  533. }
  534. /*
  535. Local Variables:
  536. mode:c
  537. indent-tabs-mode:nil
  538. c-basic-offset:4
  539. End:
  540. */