Changeset 2006
- Timestamp:
- 04/30/08 21:46:55 (7 months ago)
- Location:
- trunk
- Files:
-
- 12 modified
- 4 copied
-
configure.ac (modified) (4 diffs)
-
src/Makefile.am (modified) (3 diffs)
-
src/common.h (modified) (1 diff)
-
src/common/Makefile.am (modified) (2 diffs)
-
src/common/rdtsc.c (copied) (copied from features/performance/src/common/rdtsc.c)
-
src/common/rdtsc.h (copied) (copied from features/performance/src/common/rdtsc.h)
-
src/common/timer.c (modified) (1 diff)
-
src/common/timer.h (modified) (7 diffs)
-
src/defines.h.in (modified) (2 diffs)
-
src/send_packets.c (modified) (17 diffs)
-
src/sleep.c (copied) (copied from features/performance/src/sleep.c) (3 diffs)
-
src/sleep.h (copied) (copied from features/performance/src/sleep.h)
-
src/tcpprep.c (modified) (1 diff)
-
src/tcpreplay.c (modified) (5 diffs)
-
src/tcpreplay.h (modified) (5 diffs)
-
src/tcpreplay_opts.def (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/configure.ac
r2004 r2006 68 68 AUTOGEN_MAJOR=`echo ${AUTOGEN_VERSION} | ${SED} 's|^\([[0-9]]\)\.[[0-9]]|\1|'` 69 69 AUTOGEN_MINOR=`echo ${AUTOGEN_VERSION} | ${SED} 's|^\([[0-9]]\)\.\([[0-9]]\)|\2|'` 70 if test ((${AUTOGEN_MAJOR} -eq 5 && ${AUTOGEN_MINOR} -lt 9) || ${AUTOGEN_MAJOR} -lt 5); then70 if ( ${AUTOGEN_MAJOR} -eq 5 && ${AUTOGEN_MINOR} -lt 9 ) || ${AUTOGEN_MAJOR} -lt 5 ; then 71 71 AC_MSG_RESULT(no) 72 72 AC_MSG_WARN([${AUTOGEN} is too old (${AUTOGEN_VERSION}) for building from SVN. Please upgrade to 5.9)]) … … 1085 1085 disable_pcap_findalldevs=no 1086 1086 1087 1087 osx_frameworks=no 1088 1088 dnl these need to be dynamic based on OS 1089 1089 case $host in … … 1112 1112 disable_pcap_findalldevs=yes 1113 1113 fi 1114 AC_DEFINE([HAVE_ABSOLUTE_TIME], [1], [Have OS X UpTime()/AbsoluteTime high-precision timing]) 1115 osx_frameworks=yes 1114 1116 AC_MSG_RESULT(Apple OS X) 1115 1117 ;; … … 1134 1136 esac]) 1135 1137 1138 AM_CONDITIONAL([ENABLE_OSX_FRAMEWORKS], test "$osx_frameworks" == "yes") 1136 1139 1137 1140 AC_ARG_WITH(testnic2, -
trunk/src/Makefile.am
r1965 r2006 60 60 61 61 tcpreplay_LDADD += ./common/libcommon.a $(LIBSTRL) @LNETLIB@ @LPCAPLIB@ $(LIBOPTS_LDADD) 62 tcpreplay_SOURCES += send_packets.c signal_handler.c tcpreplay.c 62 tcpreplay_SOURCES += send_packets.c signal_handler.c tcpreplay.c sleep.c 63 64 if ENABLE_OSX_FRAMEWORKS 65 tcpreplay_LDFLAGS = -framework CoreServices -framework Carbon 66 endif 63 67 64 68 tcpreplay_OBJECTS: tcpreplay_opts.h … … 94 98 tcpbridge_LDADD = ./tcpedit/libtcpedit.a ./common/libcommon.a \ 95 99 $(LIBSTRL) @LNETLIB@ @LPCAPLIB@ $(LIBOPTS_LDADD) @DMALLOC_LIB@ 96 tcpbridge_SOURCES = tcpbridge_opts.c tcpbridge.c bridge.c send_packets.c 100 if ENABLE_OSX_FRAMEWORKS 101 tcpbridge_LDFLAGS = -framework CoreServices -framework Carbon 102 endif 103 tcpbridge_SOURCES = tcpbridge_opts.c tcpbridge.c bridge.c send_packets.c sleep.c 97 104 tcpbridge_OBJECTS: tcpbridge_opts.h 98 105 tcpbridge_opts.h: tcpbridge_opts.c … … 104 111 tcpreplay_edit_opts.h tcprewrite.h tcprewrite_opts.h tcpprep_opts.h \ 105 112 tcpprep_opts.def tcprewrite_opts.def tcpreplay_opts.def \ 106 tcpbridge_opts.def tcpbridge.h tcpbridge_opts.h tcpr.h 113 tcpbridge_opts.def tcpbridge.h tcpbridge_opts.h tcpr.h sleep.h 107 114 108 115 -
trunk/src/common.h
r1757 r2006 16 16 #include "common/utils.h" 17 17 #include "common/xX.h" 18 #include "common/rdtsc.h" 18 19 #include "common/tcpdump.h" 19 20 #include "common/timer.h" -
trunk/src/common/Makefile.am
r1961 r2006 15 15 fakepcap.c fakepcapnav.c fakepoll.c xX.c utils.c \ 16 16 timer.c svn_version.c abort.c sendpacket.c \ 17 dlt_names.c mac.c interface.c 17 dlt_names.c mac.c interface.c rdtsc.c 18 18 19 19 if ENABLE_TCPDUMP … … 28 28 fakepcap.h fakepcapnav.h fakepoll.h xX.h utils.h \ 29 29 tcpdump.h timer.h abort.h pcap_dlt.h sendpacket.h \ 30 dlt_names.h mac.h interface.h 30 dlt_names.h mac.h interface.h rdtsc.h 31 31 32 32 MOSTLYCLEANFILES = *~ -
trunk/src/common/timer.c
r1897 r2006 57 57 } 58 58 59 /* 60 * converts a float to a timeval structure 61 * converted to a #define 62 void 63 float2timer(float time, struct timeval *tvp) 59 /* Divide tvs by div, storing the result in tvs */ 60 void timesdiv(struct timespec *tvs, float div) 64 61 { 65 float n; 62 double interval; 63 64 if (div == 0 || div == 1) 65 return; 66 67 interval = ((double)tvs->tv_sec * 1000000000 + tvs->tv_nsec) / (double)div; 68 tvs->tv_sec = interval / (int)1000000000; 69 tvs->tv_nsec = interval - (tvs->tv_nsec * 1000000000); 70 } 66 71 67 n = time;68 69 tvp->tv_sec = n;70 71 n -= tvp->tv_sec;72 tvp->tv_usec = n * 100000;73 74 }75 */ -
trunk/src/common/timer.h
r1854 r2006 43 43 #include <math.h> 44 44 45 #ifdef HAVE_ABSOLUTE_TIME 46 #include <CoreServices/CoreServices.h> 47 #endif 48 49 /* AbsoluteTime methods */ 50 #ifndef NonZero 51 #define NonZero(x) ((x).hi | (x).lo) 52 #endif 53 #ifndef SetZero 54 #define SetZero(x) do { (x).hi = 0 ; (x).lo = 0; } while(0) 55 #endif 56 #ifndef CopyAbsolute 57 #define CopyAbsolute(x, y) do { (x).lo = (y).lo ; (x).hi = (y).hi; } while (0) 58 #endif 59 #ifndef AbsoluteCmp 60 #define AbsoluteCmp(left, right, cmp) \ 61 (((left)->hi == (right)->hi) ? \ 62 ((left)->lo cmp (right)->lo) : \ 63 ((left)->hi cmp (right)->hi)) 64 #endif 65 45 66 /* 46 * 1 sec = 1,000,000 microsec 67 * 1 sec = 1,0000 millisec (ms) 68 * 1 sec = 1,000,000 microsec (us) 69 * 1 sec = 1,000,000,000 nanosec (ns) 70 * 1 millisec = 1,000 microsec 47 71 * 1 microsec = 1,000 nanosec 48 * 1 sec = 1,000,000,000 nanosec49 72 */ 50 73 51 74 void timerdiv(struct timeval *tvp, float div); 75 void timesdiv(struct timespec *tvs, float div); 52 76 53 77 /* convert float time to struct timeval *tvp */ … … 57 81 tvp->tv_sec = time; \ 58 82 tvp->tv_usec = (time - tvp->tv_sec) * 100000; \ 59 } while (0) ;83 } while (0) 60 84 #endif 61 85 … … 67 91 #endif 68 92 93 #ifndef TIMESPEC_TO_TIMEVAL 94 #define TIMESPEC_TO_TIMEVAL(tv, ts) { \ 95 (tv)->tv_sec = (ts)->tv_sec; \ 96 (tv)->tv_usec = (ts)->tv_nsec / 1000; } 97 #endif 98 99 #ifndef ROUND_TIMESPEC_TO_MICROSEC 100 #define ROUND_TIMESPEC_TO_MICROSEC(ts) \ 101 do { \ 102 (ts)->tv_nsec = ((((ts)->tv_nsec / 1000) + ((ts)->tv_nsec % 1000 >= 500 ? 1 : 0)) * 1000); \ 103 } while (0) 104 #endif 105 106 107 69 108 /* zero out a timer */ 70 109 #ifndef timerclear … … 72 111 #endif 73 112 113 /* zero out a timespec */ 114 #ifndef timesclear 115 #define timesclear(tvs) (tvs)->tv_sec = (tvs)->tv_nsec = 0 116 #endif 117 74 118 /* is timer non-zero? */ 75 119 #ifndef timerisset 76 120 #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) 77 121 #endif 122 123 /* is timespec non-zero? */ 124 #ifndef timesisset 125 #define timesisset(tvs) ((tvs)->tv_sec || (tvs)->tv_nsec) 126 #endif 127 78 128 79 129 /* add tvp and uvp and store in vvp */ … … 103 153 #endif 104 154 155 #ifndef timessub 156 #define timessub(tsp, usp, vsp) \ 157 do { \ 158 (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ 159 (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ 160 if ((vsp)->tv_nsec < 0) { \ 161 (vsp)->tv_sec--; \ 162 (vsp)->tv_nsec += 1000000000; \ 163 } \ 164 } while (0) 165 #endif 166 105 167 /* compare tvp and uvp using cmp */ 106 168 #ifndef timercmp … … 109 171 ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ 110 172 ((tvp)->tv_sec cmp (uvp)->tv_sec)) 173 #endif 174 175 #ifndef timescmp 176 #define timescmp(tsp, usp, cmp) \ 177 (((tsp)->tv_sec == (usp)->tv_sec) ? \ 178 ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ 179 ((tsp)->tv_sec cmp (usp)->tv_sec)) 111 180 #endif 112 181 … … 122 191 } while(0) 123 192 124 125 /* device tvp by x. store in tvp */ 126 #define timerdiv2(tvp, x) \ 127 do { \ 128 (tvp)->tv_sec = (tvp)->tv_sec / x; \ 129 (tvp)->tv_usec = (tvp)->tv_usec / x; \ 130 } while(0) 131 132 #endif 133 193 #ifdef HAVE_ABSOLUTE_TIME 194 typedef AbsoluteTime delta_t; 195 #else 196 typedef struct timeval delta_t; 197 #endif 198 199 /* 200 * starts a timer so we can figure out how much time has passed 201 * when we call get_delta_timer() 202 */ 203 static inline void 204 start_delta_time(delta_t *ctx) 205 { 206 #ifdef HAVE_ABSOLUTE_TIME 207 *ctx = UpTime(); 208 #else 209 gettimeofday(ctx, NULL); 210 #endif 211 } 212 213 /* 214 * returns the amount of time that has passed since the 215 * last time you called start_delta_time() 216 */ 217 static inline void 218 get_delta_time(delta_t *ctx, struct timespec *ret) 219 { 220 /* OS X has absolute time */ 221 #ifdef HAVE_ABSOLUTE_TIME 222 AbsoluteTime now, delta; 223 Nanoseconds nano; 224 225 now = UpTime(); 226 227 if (! NonZero(*ctx)) { 228 timesclear(ret); 229 } else { 230 delta = SubAbsoluteFromAbsolute(now, *ctx); 231 nano = AbsoluteToNanoseconds(delta); 232 NANOSEC_TO_TIMESPEC(UnsignedWideToUInt64(nano) / 10, ret); 233 } 234 235 /* Everyone else just uses gettimeofday */ 236 #else 237 struct timeval now, delta; 238 239 gettimeofday(&now, NULL); 240 241 if (!timerisset(ctx)) { 242 timesclear(ret); 243 } else { 244 timersub(&now, ctx, &delta); 245 TIMEVAL_TO_TIMESPEC(&delta, ret); 246 } 247 #endif 248 } 249 250 #endif /* _TIMER_H_ */ -
trunk/src/defines.h.in
r1945 r2006 162 162 163 163 /* struct timeval print structs */ 164 #define TIMEVAL_FORMAT "%lu.%06lu" 164 #define TIMEVAL_FORMAT "%lus %luusec" 165 #define TIMESPEC_FORMAT "%lus %lunsec" 165 166 166 167 /* force a word or half-word swap on both Big and Little endian systems */ … … 232 233 233 234 235 /* Time converters */ 236 #define SEC_TO_MILLISEC(x) (x * 1000) 237 #define SEC_TO_MICROSEC(x) (x * 1000000) 238 #define SEC_TO_NANOSEC(x) ((u_int64_t)x * 1000000000) 239 240 #define MILLISEC_TO_SEC(x) (x / 1000) 241 #define MICROSEC_TO_SEC(x) (x / 1000000) 242 #define NANOSEC_TO_SEC(x) ((u_int64_t)x / 1000000000) 243 244 #define TIMEVAL_TO_MILLISEC(x) (((x)->tv_sec * 1000) + ((x)->tv_usec / 1000)) 245 #define TIMEVAL_TO_MICROSEC(x) (((x)->tv_sec * 1000000) + (x)->tv_usec) 246 #define TIMEVAL_TO_NANOSEC(x) ((u_int64_t)((x)->tv_sec * 1000000000) + ((u_int64_t)(x)->tv_usec * 1000)) 247 248 #define MILLISEC_TO_TIMEVAL(x, tv) \ 249 do { \ 250 (tv)->tv_sec = (x) / 1000; \ 251 (tv)->tv_usec = (x * 1000) - ((tv)->tv_sec * 1000000); \ 252 } while(0) 253 254 #define MICROSEC_TO_TIMEVAL(x, tv) \ 255 do { \ 256 (tv)->tv_sec = (x) / 1000000; \ 257 (tv)->tv_usec = (x) - ((tv)->tv_sec * 1000000); \ 258 } while(0) 259 260 #define NANOSEC_TO_TIMEVAL(x, tv) \ 261 do { \ 262 (tv)->tv_sec = (x) / 1000000000; \ 263 (tv)->tv_usec = ((x) % 1000000000) / 1000); \ 264 } while(0) 265 266 #define NANOSEC_TO_TIMESPEC(x, ts) \ 267 do { \ 268 (ts)->tv_sec = (x) / 1000000000; \ 269 (ts)->tv_nsec = (x) % 1000000000; \ 270 } while(0) 271 272 #define TIMESPEC_TO_MILLISEC(x) (((x)->tv_sec * 1000) + ((x)->tv_nsec / 1000000)) 273 #define TIMESPEC_TO_MICROSEC(x) (((x)->tv_sec * 1000000) + (x)->tv_nsec / 1000) 274 #define TIMESPEC_TO_NANOSEC(x) ((u_int64_t)((x)->tv_sec * 1000000000) + ((u_int64_t)(x)->tv_nsec)) 275 234 276 #endif /* DEFINES */ -
trunk/src/send_packets.c
r1898 r2006 2 2 3 3 /* 4 * Copyright (c) 2001-200 7Aaron Turner.4 * Copyright (c) 2001-2008 Aaron Turner. 5 5 * All rights reserved. 6 6 * … … 31 31 */ 32 32 33 #define ADJUSTER_OFFSET 5 /* number of usec to compensate for packet timing */ 33 34 34 35 #include "config.h" … … 59 60 60 61 #include "send_packets.h" 62 #include "sleep.h" 61 63 62 64 extern tcpreplay_opt_t options; … … 69 71 #endif 70 72 71 static void do_sleep(struct timeval *time, struct timeval *last, int len, int accurate, 72 sendpacket_t *sp, COUNTER counter); 73 static u_int32_t sleep_loop(struct timeval time); 74 static u_char *get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, int file_idx, packet_cache_t **prev_packet); 73 static void do_sleep(struct timeval *time, struct timeval *last, int len, 74 int accurate, sendpacket_t *sp, COUNTER counter, delta_t *ctx); 75 static const u_char *get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, 76 int file_idx, packet_cache_t **prev_packet); 77 static u_int32_t get_user_count(sendpacket_t *sp, COUNTER counter); 75 78 76 79 /** … … 92 95 struct pcap_pkthdr *pkthdr_ptr; 93 96 #endif 94 97 delta_t delta_ctx; 98 95 99 /* register signals */ 96 100 didsig = 0; … … 160 164 /* 161 165 * we have to cast the ts, since OpenBSD sucks 162 * had to be special and use bpf_timeval 166 * had to be special and use bpf_timeval. 167 * Only sleep if we're not in top speed mode (-t) 163 168 */ 164 do_sleep((struct timeval *)&pkthdr.ts, &last, pktlen, options.accurate, sp, packetnum); 165 169 if (options.speed.mode != SPEED_TOPSPEED) 170 do_sleep((struct timeval *)&pkthdr.ts, &last, pktlen, options.accurate, sp, packetnum, &delta_ctx); 171 172 /* mark the time when we send the packet */ 173 start_delta_time(&delta_ctx); 174 166 175 /* write packet out on network */ 167 176 if (sendpacket(sp, pktdata, pktlen) < (int)pktlen) 168 177 warnx("Unable to send packet: %s", sendpacket_geterr(sp)); 169 178 170 179 /* 171 180 * track the time of the "last packet sent". Again, because of OpenBSD … … 194 203 * will be updated as new entries are added (or retrieved) from the cache list. 195 204 */ 196 static u_char *205 static const u_char * 197 206 get_next_packet(pcap_t *pcap, struct pcap_pkthdr *pkthdr, int file_idx, 198 207 packet_cache_t **prev_packet) … … 233 242 * We should read the pcap file, and cache the results 234 243 */ 235 pktdata = pcap_next(pcap, pkthdr);244 pktdata = (u_char *)pcap_next(pcap, pkthdr); 236 245 if (pktdata != NULL) { 237 246 if (*prev_packet == NULL) { … … 263 272 * Read pcap file as normal 264 273 */ 265 pktdata = pcap_next(pcap, pkthdr);274 pktdata = (u_char *)pcap_next(pcap, pkthdr); 266 275 } 267 276 277 /* this get's casted to a const on the way out */ 268 278 return pktdata; 269 279 } … … 310 320 */ 311 321 static void 312 do_sleep(struct timeval *time, struct timeval *last, int len, int accurate, sendpacket_t *sp,313 COUNTER counter)322 do_sleep(struct timeval *time, struct timeval *last, int len, int accurate, 323 sendpacket_t *sp, COUNTER counter, delta_t *delta_ctx) 314 324 { 315 325 static struct timeval didsleep = { 0, 0 }; … … 318 328 static struct timeval totalsleep = { 0, 0 }; 319 329 #endif 320 struct timeval nap, now, delta; 321 struct timespec ignore, sleep; 330 struct timespec adjuster = { 0, 0 }; 331 static struct timespec nap = { 0, 0 }, delta_time = {0, 0}; 332 struct timeval nap_for, now, sleep_until; 333 struct timespec nap_this_time; 334 static int32_t nsec_adjuster = -1, nsec_times = -1; 322 335 float n; 323 struct pollfd poller[1]; /* use poll to read from the keyboard */ 324 char input[EBUF_SIZE]; 325 static u_int32_t send = 0; /* remember # of packets to send btw calls */ 326 u_int32_t loop; 327 328 /* just return if topspeed */ 329 if (options.speed.mode == SPEED_TOPSPEED) 336 static u_int32_t send = 0; /* accellerator. # of packets to send w/o sleeping */ 337 u_int64_t ppnsec; /* packets per usec */ 338 339 340 #ifdef TCPREPLAY 341 adjuster.tv_nsec = OPT_VALUE_SLEEP_ACCEL * 1000; 342 dbgx(2, "Adjuster: " TIMEVAL_FORMAT, adjuster.tv_sec, adjuster.tv_nsec); 343 #else 344 adjuster.tv_nsec = 0; 345 #endif 346 347 /* acclerator time? */ 348 if (send > 0) { 349 send --; 330 350 return; 331 332 dbgx(3, "Last time: " TIMEVAL_FORMAT, last->tv_sec, last->tv_usec); 333 334 if (gettimeofday(&now, NULL) < 0) { 351 } 352 353 dbgx(4, "Last time: " TIMEVAL_FORMAT, last->tv_sec, last->tv_usec); 354 355 if (gettimeofday(&now, NULL) < 0) 335 356 errx(1, "Error gettimeofday: %s", strerror(errno)); 336 } 337 338 dbgx(3, "Now time: " TIMEVAL_FORMAT, now.tv_sec, now.tv_usec); 357 358 dbgx(4, "Now time: " TIMEVAL_FORMAT, now.tv_sec, now.tv_usec); 339 359 340 360 /* First time through for this file */ 341 361 if (pkts_sent == 0 || ((options.speed.mode != SPEED_MBPSRATE) && (counter == 0))) { 342 362 start = now; 343 timerclear(& delta);363 timerclear(&sleep_until); 344 364 timerclear(&didsleep); 345 365 } 346 366 else { 347 timersub(&now, &start, & delta);367 timersub(&now, &start, &sleep_until); 348 368 } 349 369 350 370 switch(options.speed.mode) { 371 /* 372 * If top speed, you shouldn't even be here, but handle it anyways 373 */ 374 case SPEED_TOPSPEED: 375 notice("you shouldn't call do_sleep() in top speed mode."); 376 return; 377 break; 378 351 379 case SPEED_MULTIPLIER: 352 380 /* … … 354 382 */ 355 383 if (timerisset(last) && timercmp(time, last, >)) { 356 timersub(time, last, &nap); 357 timerdiv(&nap, options.speed.speed); 384 timersub(time, last, &nap_for); 385 TIMEVAL_TO_TIMESPEC(&nap_for, &nap); 386 timesdiv(&nap, options.speed.speed); 358 387 } 359 388 else { … … 363 392 * last packet. 364 393 */ 365 time rclear(&nap);366 } 394 timesclear(&nap); 395 } 367 396 break; 368 397 … … 375 404 n = (float)len / (options.speed.speed * 1024 * 1024 / 8); /* convert Mbps to bps */ 376 405 nap.tv_sec = n; 377 nap.tv_usec = (n - nap.tv_sec) * 1000000; 406 nap.tv_nsec = (n - nap.tv_sec) * 1000000000; 407 378 408 dbgx(3, "packet size %d\t\tequals %f bps\t\tnap " TIMEVAL_FORMAT, len, n, 379 nap.tv_sec, nap.tv_ usec);409 nap.tv_sec, nap.tv_nsec); 380 410 } 381 411 else { 382 timerclear(&nap); 412 /* don't sleep at all for the first packet */ 413 timesclear(&nap); 383 414 } 384 415 break; 385 416 386 417 case SPEED_PACKETRATE: 387 /* run in packets/sec */ 388 n = 1 / options.speed.speed; 389 nap.tv_sec = n; 390 n -= nap.tv_sec; 391 nap.tv_usec = n * 1000000; 392 break; 393 418 /* only need to calculate this the first time */ 419 if (! timesisset(&nap)) { 420 /* run in packets/sec */ 421 ppnsec = 1000000000 / options.speed.speed; 422 NANOSEC_TO_TIMESPEC(ppnsec, &nap); 423 dbgx(1, "sending 1 packet per %lu nsec", nap.tv_nsec); 424 } 425 break; 426 394 427 case SPEED_ONEATATIME: 395 428 /* do we skip prompting for a key press? */ 396 429 if (send == 0) { 397 printf("**** Next packet #" COUNTER_SPEC " out %s. How many packets do you wish to send? ", 398 counter, (sp == options.intf1 ? options.intf1_name : options.intf2_name)); 399 fflush(NULL); 400 poller[0].fd = STDIN_FILENO; 401 poller[0].events = POLLIN | POLLPRI | POLLNVAL; 402 poller[0].revents = 0; 403 404 if (fcntl(0, F_SETFL, fcntl(0, F_GETFL) & ~O_NONBLOCK)) 405 errx(1, "Unable to clear non-blocking flag on stdin: %s", strerror(errno)); 406 407 /* wait for the input */ 408 if (poll(poller, 1, -1) < 0) 409 errx(1, "Error reading user input from stdin: %s", strerror(errno)); 410 411 /* 412 * read to the end of the line or EBUF_SIZE, 413 * Note, if people are stupid, and type in more text then EBUF_SIZE 414 * then the next fgets() will pull in that data, which will have poor 415 * results. fuck them. 416 */ 417 if (fgets(input, sizeof(input), stdin) == NULL) { 418 errx(1, "Unable to process user input for fd %d: %s", fileno(stdin), strerror(errno)); 419 } else if (strlen(input) > 1) { 420 send = strtoul(input, NULL, 0); 421 } 422 423 /* how many packets should we send? */ 424 if (send == 0) { 425
