~kroq-gar78/ubuntu/precise/rsyslog/fix-846818

« back to all changes in this revision

Viewing changes to tests/tcpflood.c

  • Committer: Package Import Robot
  • Author(s): Scott Moser
  • Date: 2011-11-07 13:54:56 UTC
  • mfrom: (16.1.25 sid)
  • Revision ID: package-import@ubuntu.com-20111107135456-cwt6mu19ski1h2qf
Tags: 5.8.6-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - Run as rsyslog:rsyslog, set $FileOwner to syslog
  - Replace init script with debian/rsyslog.upstart.
  - debian/rsyslog.logrotate: Use reload command to restart rsyslog
  - debian/rsyslog.conf: enable $RepeatedMsgReduction 
    to avoid bloating the syslog file (LP #453444)
  - Add debian/rsyslog.dmesg.upstart to save initial dmesg into a file.
    Install it in debian/rules.
  - debian/50-default.conf: set of default rules for syslog (forwarded to
    Debian #603160). remove file in postrm on purge. manage with ucf.
  - debian/rules: build with LDFLAGS=""
* Dropped:
  - debian/patches/02-CVE-2011-3200.patch (fixed in upstream release)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 *      bytes as forth. Add -r to randomize the amount of extra
17
17
 *      data included in the range 1..(value of -d).
18
18
 * -r   randomize amount of extra data added (-d must be > 0)
 
19
 * -s   (silent) do not show progress indicator (never done on non-tty)
19
20
 * -f   support for testing dynafiles. If given, include a dynafile ID
20
21
 *      in the range 0..(f-1) as the SECOND field, shifting all field values
21
22
 *      one field to the right. Zero (default) disables this functionality.
32
33
 * -D   randomly drop and re-establish connections. Useful for stress-testing
33
34
 *      the TCP receiver.
34
35
 * -F   USASCII value for frame delimiter (in octet-stuffing mode), default LF
 
36
 * -R   number of times the test shall be run (very useful for gathering performance
 
37
 *      data and other repetitive things). Default: 1
 
38
 * -S   number of seconds to sleep between different runs (-R) Default: 30
 
39
 * -X   generate sTats data records. Default: off
 
40
 * -e   encode output in CSV (not yet everywhere supported)
 
41
 *      for performance data:
 
42
 *      each inidividual line has the runtime of one test
 
43
 *      the last line has 0 in field 1, followed by numberRuns,TotalRuntime,
 
44
 *      Average,min,max
 
45
 * -T   transport to use. Currently supported: "udp", "tcp" (default)
 
46
 *      Note: UDP supports a single target port, only
 
47
 * -W   wait time between sending batches of messages, in microseconds (Default: 0)
 
48
 * -b   number of messages within a batch (default: 100,000,000 millions)
 
49
 * -Y   use multiple threads, one per connection (which means 1 if one only connection
 
50
 *      is configured!)
 
51
 * -z   private key file for TLS mode
 
52
 * -Z   cert (public key) file for TLS mode
 
53
 * -L   loglevel to use for GnuTLS troubleshooting (0-off to 10-all, 0 default)
35
54
 *
36
55
 * Part of the testbench for rsyslog.
37
56
 *
66
85
#include <unistd.h>
67
86
#include <string.h>
68
87
#include <netinet/in.h>
 
88
#include <pthread.h>
69
89
#include <sys/resource.h>
 
90
#include <sys/time.h>
 
91
#include <errno.h>
 
92
#ifdef ENABLE_GNUTLS
 
93
#       include <gnutls/gnutls.h>
 
94
#       include <gcrypt.h>
 
95
        GCRY_THREAD_OPTION_PTHREAD_IMPL;
 
96
#endif
70
97
 
71
98
#define EXIT_FAILURE 1
72
99
#define INVALID_SOCKET -1
74
101
#define NETTEST_INPUT_CONF_FILE "nettest.input.conf" /* name of input file, must match $IncludeConfig in .conf files */
75
102
 
76
103
#define MAX_EXTRADATA_LEN 100*1024
 
104
#define MAX_SENDBUF 2 * MAX_EXTRADATA_LEN
77
105
 
78
106
static char *targetIP = "127.0.0.1";
79
107
static char *msgPRI = "167";
83
111
static int extraDataLen = 0; /* amount of extra data to add to message */
84
112
static int bRandomizeExtraData = 0; /* randomize amount of extra data added */
85
113
static int numMsgsToSend; /* number of messages to send */
86
 
static int numConnections = 1; /* number of connections to create */
 
114
static unsigned numConnections = 1; /* number of connections to create */
87
115
static int *sockArray;  /* array of sockets to use */
88
116
static int msgNum = 0;  /* initial message number to start with */
89
117
static int bShowProgress = 1; /* show progress messages */
 
118
static int bSilent = 0; /* completely silent operation */
90
119
static int bRandConnDrop = 0; /* randomly drop connections? */
91
120
static char *MsgToSend = NULL; /* if non-null, this is the actual message to send */
92
121
static int bBinaryFile = 0;     /* is -I file binary */
95
124
static char frameDelim = '\n';  /* default frame delimiter */
96
125
FILE *dataFP = NULL;            /* file pointer for data file, if used */
97
126
static long nConnDrops = 0;     /* counter: number of time connection was dropped (-D option) */
 
127
static int numRuns = 1;         /* number of times the test shall be run */
 
128
static int sleepBetweenRuns = 30; /* number of seconds to sleep between runs */
 
129
static int bStatsRecords = 0;   /* generate stats records */
 
130
static int bCSVoutput = 0;      /* generate output in CSV (where applicable) */
 
131
static long long batchsize = 100000000ll;
 
132
static int waittime = 0;
 
133
static int runMultithreaded = 0; /* run tests in multithreaded mode */
 
134
static int numThrds = 1;        /* number of threads to use */
 
135
static char *tlsCertFile = NULL;
 
136
static char *tlsKeyFile = NULL;
 
137
static int tlsLogLevel = 0;
 
138
 
 
139
#ifdef ENABLE_GNUTLS
 
140
static gnutls_session_t *sessArray;     /* array of TLS sessions to use */
 
141
static gnutls_certificate_credentials tlscred;
 
142
#endif
 
143
 
 
144
/* variables for managing multi-threaded operations */
 
145
int runningThreads;             /* number of threads currently running */
 
146
int doRun;                      /* shall sender thread begin to run? */
 
147
pthread_mutex_t thrdMgmt;       /* mutex for controling startup/shutdown */
 
148
pthread_cond_t condStarted;
 
149
pthread_cond_t condDoRun;
 
150
 
 
151
/* the following struct provides information for a generator instance (thread) */
 
152
struct instdata {
 
153
        /* lower and upper bounds for the thread in question */
 
154
        unsigned long long lower;
 
155
        unsigned long long numMsgs; /* number of messages to send */
 
156
        unsigned long long numSent; /* number of messages already sent */
 
157
        unsigned idx;   /**< index of fd to be used for sending */
 
158
        pthread_t thread; /**< thread processing this instance */
 
159
} *instarray = NULL;
 
160
 
 
161
/* the following structure is used to gather performance data */
 
162
struct runstats {
 
163
        unsigned long long totalRuntime;
 
164
        unsigned long minRuntime;
 
165
        unsigned long maxRuntime;
 
166
        int numRuns;
 
167
};
 
168
 
 
169
static int udpsock;                     /* socket for sending in UDP mode */
 
170
static struct sockaddr_in udpRcvr;      /* remote receiver in UDP mode */
 
171
 
 
172
static enum { TP_UDP, TP_TCP, TP_TLS } transport = TP_TCP;
 
173
 
 
174
/* forward definitions */
 
175
static void initTLSSess(int);
 
176
static int sendTLS(int i, char *buf, int lenBuf);
 
177
static void closeTLSSess(int __attribute__((unused)) i);
 
178
 
 
179
/* prepare send subsystem for UDP send */
 
180
static inline int
 
181
setupUDP(void)
 
182
{
 
183
        if((udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
 
184
                return 1;
 
185
 
 
186
        memset((char *) &udpRcvr, 0, sizeof(udpRcvr));
 
187
        udpRcvr.sin_family = AF_INET;
 
188
        udpRcvr.sin_port = htons(targetPort);
 
189
        if(inet_aton(targetIP, &udpRcvr.sin_addr)==0) {
 
190
                fprintf(stderr, "inet_aton() failed\n");
 
191
                return(1);
 
192
        }
 
193
 
 
194
        return 0;
 
195
}
98
196
 
99
197
 
100
198
/* open a single tcp connection
150
248
 */
151
249
int openConnections(void)
152
250
{
153
 
        int i;
 
251
        unsigned i;
154
252
        char msgBuf[128];
155
253
        size_t lenMsg;
156
254
 
 
255
        if(transport == TP_UDP)
 
256
                return setupUDP();
 
257
 
157
258
        if(bShowProgress)
158
259
                write(1, "      open connections", sizeof("      open connections")-1);
 
260
#       ifdef ENABLE_GNUTLS
 
261
        sessArray = calloc(numConnections, sizeof(gnutls_session_t));
 
262
#       endif
159
263
        sockArray = calloc(numConnections, sizeof(int));
160
264
        for(i = 0 ; i < numConnections ; ++i) {
161
265
                if(i % 10 == 0) {
166
270
                        printf("error in trying to open connection i=%d\n", i);
167
271
                        return 1;
168
272
                }
169
 
        }
170
 
        lenMsg = sprintf(msgBuf, "\r%5.5d open connections\n", i);
171
 
        write(1, msgBuf, lenMsg);
 
273
                if(transport == TP_TLS) {
 
274
                        initTLSSess(i);
 
275
                }
 
276
        }
 
277
        if(bShowProgress) {
 
278
                lenMsg = sprintf(msgBuf, "\r%5.5d open connections\n", i);
 
279
                write(1, msgBuf, lenMsg);
 
280
        }
172
281
 
173
282
        return 0;
174
283
}
183
292
 */
184
293
void closeConnections(void)
185
294
{
186
 
        int i;
 
295
        unsigned i;
187
296
        size_t lenMsg;
188
297
        struct linger ling;
189
298
        char msgBuf[128];
190
299
 
 
300
        if(transport == TP_UDP)
 
301
                return;
 
302
 
191
303
        if(bShowProgress)
192
304
                write(1, "      close connections", sizeof("      close connections")-1);
193
305
        for(i = 0 ; i < numConnections ; ++i) {
204
316
                        ling.l_onoff = 1;
205
317
                        ling.l_linger = 1;
206
318
                        setsockopt(sockArray[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
 
319
                        if(transport == TP_TLS)
 
320
                                closeTLSSess(i);
207
321
                        close(sockArray[i]);
208
322
                }
209
323
        }
210
 
        lenMsg = sprintf(msgBuf, "\r%5.5d close connections\n", i);
211
 
        write(1, msgBuf, lenMsg);
 
324
        if(bShowProgress) {
 
325
                lenMsg = sprintf(msgBuf, "\r%5.5d close connections\n", i);
 
326
                write(1, msgBuf, lenMsg);
 
327
        }
212
328
 
213
329
}
214
330
 
218
334
 * of constructing test messages. -- rgerhards, 2010-03-31
219
335
 */
220
336
static inline void
221
 
genMsg(char *buf, size_t maxBuf, int *pLenBuf)
 
337
genMsg(char *buf, size_t maxBuf, int *pLenBuf, struct instdata *inst)
222
338
{
223
339
        int edLen; /* actual extra data length to use */
224
340
        char extraData[MAX_EXTRADATA_LEN + 1];
225
341
        char dynFileIDBuf[128] = "";
226
 
        static int numMsgsGen = 0;
227
342
        int done;
228
343
 
229
344
        if(dataFP != NULL) {
262
377
                /* use fixed message format from command line */
263
378
                *pLenBuf = snprintf(buf, maxBuf, "%s\n", MsgToSend);
264
379
        }
265
 
 
266
 
        if(numMsgsGen++ >= numMsgsToSend)
267
 
                *pLenBuf = 0; /* indicate end of run */
268
 
 
269
 
finalize_it: ;
 
380
        ++inst->numSent;
 
381
 
 
382
finalize_it: /*EMPTY to keep the compiler happy */;
270
383
}
271
384
 
272
385
/* send messages to the tcp connections we keep open. We use
277
390
 * last. All messages in between are sent over random connections.
278
391
 * Note that message numbers start at 0.
279
392
 */
280
 
int sendMessages(void)
 
393
int sendMessages(struct instdata *inst)
281
394
{
282
 
        int i = 0;
 
395
        unsigned i = 0;
283
396
        int socknum;
284
397
        int lenBuf;
285
 
        int lenSend;
286
 
        char *statusText;
 
398
        int lenSend = 0;
 
399
        char *statusText = "";
287
400
        char buf[MAX_EXTRADATA_LEN + 1024];
 
401
        char sendBuf[MAX_SENDBUF];
 
402
        int offsSendBuf = 0;
288
403
 
289
 
        if(dataFile == NULL) {
290
 
                printf("Sending %d messages.\n", numMsgsToSend);
291
 
                statusText = "messages";
292
 
        } else {
293
 
                printf("Sending file '%s' %d times.\n", dataFile, numFileIterations);
294
 
                statusText = "kb";
 
404
        if(!bSilent) {
 
405
                if(dataFile == NULL) {
 
406
                        printf("Sending %llu messages.\n", inst->numMsgs);
 
407
                        statusText = "messages";
 
408
                } else {
 
409
                        printf("Sending file '%s' %d times.\n", dataFile,
 
410
                               numFileIterations);
 
411
                        statusText = "kb";
 
412
                }
295
413
        }
296
414
        if(bShowProgress)
297
415
                printf("\r%8.8d %s sent", 0, statusText);
298
 
        while(1) { /* broken inside loop! */
299
 
                if(i < numConnections)
300
 
                        socknum = i;
301
 
                else if(i >= numMsgsToSend - numConnections)
302
 
                        socknum = i - (numMsgsToSend - numConnections);
303
 
                else {
304
 
                        int rnd = rand();
305
 
                        socknum = rnd % numConnections;
306
 
                }
307
 
                genMsg(buf, sizeof(buf), &lenBuf); /* generate the message to send according to params */
308
 
                if(lenBuf == 0)
309
 
                        break; /* end of processing! */
310
 
                if(sockArray[socknum] == -1) {
311
 
                        /* connection was dropped, need to re-establish */
312
 
                        if(openConn(&(sockArray[socknum])) != 0) {
313
 
                                printf("error in trying to re-open connection %d\n", socknum);
314
 
                                exit(1);
315
 
                        }
316
 
                }
317
 
                lenSend = send(sockArray[socknum], buf, lenBuf, 0);
 
416
        while(i < inst->numMsgs) {
 
417
                if(runMultithreaded) {
 
418
                        socknum = inst->idx;
 
419
                } else {
 
420
                        if(i < numConnections)
 
421
                                socknum = i;
 
422
                        else if(i >= inst->numMsgs - numConnections) {
 
423
                                socknum = i - (inst->numMsgs - numConnections);
 
424
                        } else {
 
425
                                int rnd = rand();
 
426
                                socknum = rnd % numConnections;
 
427
                        }
 
428
                }
 
429
                genMsg(buf, sizeof(buf), &lenBuf, inst); /* generate the message to send according to params */
 
430
                if(transport == TP_TCP) {
 
431
                        if(sockArray[socknum] == -1) {
 
432
                                /* connection was dropped, need to re-establish */
 
433
                                if(openConn(&(sockArray[socknum])) != 0) {
 
434
                                        printf("error in trying to re-open connection %d\n", socknum);
 
435
                                        exit(1);
 
436
                                }
 
437
                        }
 
438
                        lenSend = send(sockArray[socknum], buf, lenBuf, 0);
 
439
                } else if(transport == TP_UDP) {
 
440
                        lenSend = sendto(udpsock, buf, lenBuf, 0, &udpRcvr, sizeof(udpRcvr));
 
441
                } else if(transport == TP_TLS) {
 
442
                        if(offsSendBuf + lenBuf < MAX_SENDBUF) {
 
443
                                memcpy(sendBuf+offsSendBuf, buf, lenBuf);
 
444
                                offsSendBuf += lenBuf;
 
445
                                lenSend = lenBuf; /* simulate "good" call */
 
446
                        } else {
 
447
                                lenSend = sendTLS(socknum, sendBuf, offsSendBuf);
 
448
                                lenSend = (lenSend == offsSendBuf) ? lenBuf : -1;
 
449
                                memcpy(sendBuf, buf, lenBuf);
 
450
                                offsSendBuf = lenBuf;
 
451
                        }
 
452
                }
318
453
                if(lenSend != lenBuf) {
319
454
                        printf("\r%5.5d\n", i);
320
455
                        fflush(stdout);
321
456
                        perror("send test data");
322
 
                        printf("send() failed at socket %d, index %d, msgNum %d\n",
323
 
                                sockArray[socknum], i, msgNum);
 
457
                        printf("send() failed at socket %d, index %d, msgNum %lld\n",
 
458
                                sockArray[socknum], i, inst->numSent);
324
459
                        fflush(stderr);
325
460
                        return(1);
326
461
                }
328
463
                        if(bShowProgress)
329
464
                                printf("\r%8.8d", i);
330
465
                }
331
 
                if(bRandConnDrop) {
 
466
                if(!runMultithreaded && bRandConnDrop) {
332
467
                        /* if we need to randomly drop connections, see if we 
333
468
                         * are a victim
334
469
                         */
338
473
                                sockArray[socknum] = -1;
339
474
                        }
340
475
                }
 
476
                if(inst->numSent % batchsize == 0) {
 
477
                        usleep(waittime);
 
478
                }
341
479
                ++msgNum;
342
480
                ++i;
343
481
        }
344
 
        printf("\r%8.8d %s sent\n", i, statusText);
345
 
 
346
 
        return 0;
347
 
}
348
 
 
 
482
        if(transport == TP_TLS && offsSendBuf != 0) {
 
483
                /* send remaining buffer */
 
484
                lenSend = sendTLS(socknum, sendBuf, offsSendBuf);
 
485
        }
 
486
        if(!bSilent)
 
487
                printf("\r%8.8d %s sent\n", i, statusText);
 
488
 
 
489
        return 0;
 
490
}
 
491
 
 
492
 
 
493
/* this is the thread that starts a generator
 
494
 */
 
495
static void *
 
496
thrdStarter(void *arg)
 
497
{
 
498
        struct instdata *inst = (struct instdata*) arg;
 
499
        pthread_mutex_lock(&thrdMgmt);
 
500
        runningThreads++;
 
501
        pthread_cond_signal(&condStarted);
 
502
        while(doRun == 0) {
 
503
                pthread_cond_wait(&condDoRun, &thrdMgmt);
 
504
        }
 
505
        pthread_mutex_unlock(&thrdMgmt);
 
506
        if(sendMessages(inst) != 0) {
 
507
                printf("error sending messages\n");
 
508
        }
 
509
        return NULL;
 
510
}
 
511
 
 
512
 
 
513
/* This function initializes the actual traffic generators. The function sets up all required
 
514
 * parameter blocks and starts threads. It returns when all threads are ready to run
 
515
 * and the main task must just enable them.
 
516
 */
 
517
static inline void
 
518
prepareGenerators()
 
519
{
 
520
        int i;
 
521
        long long msgsThrd;
 
522
        long long starting = 0;
 
523
        
 
524
        if(runMultithreaded) {
 
525
                bSilent = 1;
 
526
                numThrds = numConnections;
 
527
        } else {
 
528
                numThrds = 1;
 
529
        }
 
530
 
 
531
        runningThreads = 0;
 
532
        doRun = 0;
 
533
        pthread_mutex_init(&thrdMgmt, NULL);
 
534
        pthread_cond_init(&condStarted, NULL);
 
535
        pthread_cond_init(&condDoRun, NULL);
 
536
 
 
537
        if(instarray != NULL) {
 
538
                free(instarray);
 
539
        }
 
540
        instarray = calloc(numThrds, sizeof(struct instdata));
 
541
        msgsThrd = numMsgsToSend / numThrds;
 
542
 
 
543
        for(i = 0 ; i < numThrds ; ++i)  {
 
544
                instarray[i].lower = starting;
 
545
                instarray[i].numMsgs = msgsThrd;
 
546
                instarray[i].numSent = 0;
 
547
                instarray[i].idx = i;
 
548
                pthread_create(&(instarray[i].thread), NULL, thrdStarter, instarray + i); 
 
549
                /*printf("started thread %x\n", (unsigned) instarray[i].thread);*/
 
550
                starting += msgsThrd;
 
551
        }
 
552
}
 
553
 
 
554
/* Let all generators run. Threads must have been started. Here we wait until
 
555
 * all threads are initialized and then broadcast that they can begin to run.
 
556
 */
 
557
static inline void
 
558
runGenerators()
 
559
{
 
560
        pthread_mutex_lock(&thrdMgmt);
 
561
        while(runningThreads != numThrds){
 
562
                pthread_cond_wait(&condStarted, &thrdMgmt);
 
563
        }
 
564
        doRun = 1;
 
565
        pthread_cond_broadcast(&condDoRun);
 
566
        pthread_mutex_unlock(&thrdMgmt);
 
567
}
 
568
 
 
569
 
 
570
/* Wait for all traffic generators to stop.
 
571
 */
 
572
static inline void
 
573
waitGenerators()
 
574
{
 
575
        int i;
 
576
        for(i = 0 ; i < numThrds ; ++i)  {
 
577
                pthread_join(instarray[i].thread, NULL);
 
578
                /*printf("thread %x stopped\n", (unsigned) instarray[i].thread);*/
 
579
        }
 
580
        pthread_mutex_destroy(&thrdMgmt);
 
581
        pthread_cond_destroy(&condStarted);
 
582
        pthread_cond_destroy(&condDoRun);
 
583
}
 
584
 
 
585
/* functions related to computing statistics on the runtime of a test. This is
 
586
 * a separate function primarily not to mess up the test driver.
 
587
 * rgerhards, 2010-12-08
 
588
 */
 
589
static inline void
 
590
endTiming(struct timeval *tvStart, struct runstats *stats)
 
591
{
 
592
        long sec, usec;
 
593
        unsigned long runtime;
 
594
        struct timeval tvEnd;
 
595
 
 
596
        gettimeofday(&tvEnd, NULL);
 
597
        if(tvStart->tv_usec > tvEnd.tv_usec) {
 
598
                tvEnd.tv_sec--;
 
599
                tvEnd.tv_usec += 1000000;
 
600
        }
 
601
 
 
602
        sec = tvEnd.tv_sec - tvStart->tv_sec;
 
603
        usec = tvEnd.tv_usec - tvStart->tv_usec;
 
604
 
 
605
        runtime = sec * 1000 + (usec / 1000);
 
606
        stats->totalRuntime += runtime;
 
607
        if(runtime < stats->minRuntime)
 
608
                stats->minRuntime = runtime;
 
609
        if(runtime > stats->maxRuntime)
 
610
                stats->maxRuntime = runtime;
 
611
 
 
612
        if(!bSilent || bStatsRecords) {
 
613
                if(bCSVoutput) {
 
614
                        printf("%ld.%3.3ld\n", runtime / 1000, runtime % 1000);
 
615
                } else {
 
616
                        printf("runtime: %ld.%3.3ld\n", runtime / 1000, runtime % 1000);
 
617
                }
 
618
        }
 
619
}
 
620
 
 
621
 
 
622
/* generate stats summary record at end of run
 
623
 */
 
624
static inline void
 
625
genStats(struct runstats *stats)
 
626
{
 
627
        long unsigned avg;
 
628
        avg = stats->totalRuntime / stats->numRuns;
 
629
 
 
630
        if(bCSVoutput) {
 
631
                printf("#numRuns,TotalRuntime,AvgRuntime,MinRuntime,MaxRuntime\n");
 
632
                printf("%d,%llu.%3.3d,%lu.%3.3lu,%lu.%3.3lu,%lu.%3.3lu\n",
 
633
                        stats->numRuns,
 
634
                        stats->totalRuntime / 1000, (int) stats->totalRuntime % 1000,
 
635
                        avg / 1000, avg % 1000,
 
636
                        stats->minRuntime / 1000, stats->minRuntime % 1000,
 
637
                        stats->maxRuntime / 1000, stats->maxRuntime % 1000);
 
638
        } else {
 
639
                printf("Runs:     %d\n",   stats->numRuns);
 
640
                printf("Runtime:\n");
 
641
                printf("  total:  %llu.%3.3d\n", stats->totalRuntime / 1000,
 
642
                                                 (int) stats->totalRuntime % 1000);
 
643
                printf("  avg:    %lu.%3.3lu\n",  avg / 1000, avg % 1000);
 
644
                printf("  min:    %lu.%3.3lu\n",  stats->minRuntime / 1000, stats->minRuntime % 1000);
 
645
                printf("  max:    %lu.%3.3lu\n",  stats->maxRuntime / 1000, stats->maxRuntime % 1000);
 
646
                printf("All times are wallclock time.\n");
 
647
        }
 
648
}
 
649
 
 
650
 
 
651
/* Run the actual test. This function handles various meta-parameters, like
 
652
 * a specified number of iterations, performance measurement and so on...
 
653
 * rgerhards, 2010-12-08
 
654
 */
 
655
static int
 
656
runTests(void)
 
657
{
 
658
        struct timeval tvStart;
 
659
        struct runstats stats;
 
660
        int run;
 
661
 
 
662
        stats.totalRuntime = 0;
 
663
        stats.minRuntime = (unsigned long long) 0xffffffffffffffffll;
 
664
        stats.maxRuntime = 0;
 
665
        stats.numRuns = numRuns;
 
666
        run = 1;
 
667
        while(1) { /* loop broken inside */
 
668
                if(!bSilent)
 
669
                        printf("starting run %d\n", run);
 
670
                prepareGenerators();
 
671
                gettimeofday(&tvStart, NULL);
 
672
                runGenerators();
 
673
                waitGenerators();
 
674
                endTiming(&tvStart, &stats);
 
675
                if(run == numRuns)
 
676
                        break;
 
677
                if(!bSilent)
 
678
                        printf("sleeping %d seconds before next run\n", sleepBetweenRuns);
 
679
                sleep(sleepBetweenRuns);
 
680
                ++run;
 
681
        }
 
682
 
 
683
        if(bStatsRecords) {
 
684
                genStats(&stats);
 
685
        }
 
686
 
 
687
        return 0;
 
688
}
 
689
 
 
690
#       if defined(ENABLE_GNUTLS)
 
691
/* This defines a log function to be provided to GnuTLS. It hopefully
 
692
 * helps us track down hard to find problems.
 
693
 * rgerhards, 2008-06-20
 
694
 */
 
695
static void tlsLogFunction(int level, const char *msg)
 
696
{
 
697
        printf("GnuTLS (level %d): %s", level, msg);
 
698
 
 
699
}
 
700
 
 
701
 
 
702
/* global init GnuTLS
 
703
 */
 
704
static void
 
705
initTLS(void)
 
706
{
 
707
        int r;
 
708
 
 
709
        /* order of gcry_control and gnutls_global_init matters! */
 
710
        gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
 
711
        gnutls_global_init();
 
712
        /* set debug mode, if so required by the options */
 
713
        if(tlsLogLevel > 0) {
 
714
                gnutls_global_set_log_function(tlsLogFunction);
 
715
                gnutls_global_set_log_level(tlsLogLevel);
 
716
        }
 
717
 
 
718
        r = gnutls_certificate_allocate_credentials(&tlscred);
 
719
        if(r != GNUTLS_E_SUCCESS) {
 
720
                printf("error allocating credentials\n");
 
721
                gnutls_perror(r);
 
722
                exit(1);
 
723
        }
 
724
        r = gnutls_certificate_set_x509_key_file(tlscred, tlsCertFile, tlsKeyFile, GNUTLS_X509_FMT_PEM);
 
725
        if(r != GNUTLS_E_SUCCESS) {
 
726
                printf("error setting certificate files -- have you mixed up key and certificate?\n");
 
727
                printf("If in doubt, try swapping the files in -z/-Z\n");
 
728
                printf("Certifcate is: '%s'\n", tlsCertFile);
 
729
                printf("Key        is: '%s'\n", tlsKeyFile);
 
730
                gnutls_perror(r);
 
731
                r = gnutls_certificate_set_x509_key_file(tlscred, tlsKeyFile, tlsCertFile,
 
732
                                                         GNUTLS_X509_FMT_PEM);
 
733
                if(r == GNUTLS_E_SUCCESS) {
 
734
                        printf("Tried swapping files, this seems to work "
 
735
                               "(but results may be unpredictable!)\n");
 
736
                } else {
 
737
                        exit(1);
 
738
                }
 
739
        }
 
740
}
 
741
 
 
742
 
 
743
static void
 
744
initTLSSess(int i)
 
745
{
 
746
        int r;
 
747
        gnutls_init(sessArray + i, GNUTLS_CLIENT);
 
748
 
 
749
        /* Use default priorities */
 
750
        gnutls_set_default_priority(sessArray[i]);
 
751
 
 
752
        /* put our credentials to the current session */
 
753
        r = gnutls_credentials_set(sessArray[i], GNUTLS_CRD_CERTIFICATE, tlscred);
 
754
        if(r != GNUTLS_E_SUCCESS) {
 
755
                fprintf (stderr, "Setting credentials failed\n");
 
756
                gnutls_perror(r);
 
757
                exit(1);
 
758
        }
 
759
 
 
760
        /* NOTE: the following statement generates a cast warning, but there seems to
 
761
         * be no way around it with current GnuTLS. Do NOT try to "fix" the situation!
 
762
         */
 
763
        gnutls_transport_set_ptr(sessArray[i], (gnutls_transport_ptr_t) sockArray[i]);
 
764
 
 
765
        /* Perform the TLS handshake */
 
766
        r = gnutls_handshake(sessArray[i]);
 
767
        if(r < 0) {
 
768
                fprintf (stderr, "TLS Handshake failed\n");
 
769
                gnutls_perror(r);
 
770
                exit(1);
 
771
        }
 
772
}
 
773
 
 
774
static int
 
775
sendTLS(int i, char *buf, int lenBuf)
 
776
{
 
777
        int lenSent;
 
778
        int r;
 
779
 
 
780
        lenSent = 0;
 
781
        while(lenSent != lenBuf) {
 
782
                r = gnutls_record_send(sessArray[i], buf + lenSent, lenBuf - lenSent);
 
783
                if(r < 0)
 
784
                        break;
 
785
                lenSent += r;
 
786
        }
 
787
 
 
788
        return lenSent;
 
789
}
 
790
 
 
791
static void
 
792
closeTLSSess(int i)
 
793
{
 
794
        gnutls_bye(sessArray[i], GNUTLS_SHUT_RDWR);
 
795
        gnutls_deinit(sessArray[i]);
 
796
}
 
797
#       else    /* NO TLS available */
 
798
static void initTLS(void) {}
 
799
static void initTLSSess(int __attribute__((unused)) i) {}
 
800
static int sendTLS(int __attribute__((unused)) i, char __attribute__((unused)) *buf, int __attribute__((unused)) lenBuf) { return 0; }
 
801
static void closeTLSSess(int __attribute__((unused)) i) {}
 
802
#       endif
349
803
 
350
804
/* Run the test.
351
805
 * rgerhards, 2009-04-03
370
824
 
371
825
        setvbuf(stdout, buf, _IONBF, 48);
372
826
        
373
 
        if(!isatty(1))
374
 
                bShowProgress = 0;
375
 
 
376
 
        while((opt = getopt(argc, argv, "f:F:t:p:c:C:m:i:I:P:d:Dn:M:rB")) != -1) {
 
827
        while((opt = getopt(argc, argv, "b:ef:F:t:p:c:C:m:i:I:P:d:Dn:L:M:rsBR:S:T:XW:Yz:Z:")) != -1) {
377
828
                switch (opt) {
 
829
                case 'b':       batchsize = atoll(optarg);
 
830
                                break;
378
831
                case 't':       targetIP = optarg;
379
832
                                break;
380
833
                case 'p':       targetPort = atoi(optarg);
381
834
                                break;
382
835
                case 'n':       numTargetPorts = atoi(optarg);
383
836
                                break;
384
 
                case 'c':       numConnections = atoi(optarg);
 
837
                case 'c':       numConnections = (unsigned) atoi(optarg);
385
838
                                break;
386
839
                case 'C':       numFileIterations = atoi(optarg);
387
840
                                break;
406
859
                                break;
407
860
                case 'F':       frameDelim = atoi(optarg);
408
861
                                break;
 
862
                case 'L':       tlsLogLevel = atoi(optarg);
 
863
                                break;
409
864
                case 'M':       MsgToSend = optarg;
410
865
                                break;
411
866
                case 'I':       dataFile = optarg;
414
869
                                 */
415
870
                                numMsgsToSend = 1000000;
416
871
                                break;
 
872
                case 's':       bSilent = 1;
 
873
                                break;
417
874
                case 'B':       bBinaryFile = 1;
418
875
                                break;
 
876
                case 'R':       numRuns = atoi(optarg);
 
877
                                break;
 
878
                case 'S':       sleepBetweenRuns = atoi(optarg);
 
879
                                break;
 
880
                case 'X':       bStatsRecords = 1;
 
881
                                break;
 
882
                case 'e':       bCSVoutput = 1;
 
883
                                break;
 
884
                case 'T':       if(!strcmp(optarg, "udp")) {
 
885
                                        transport = TP_UDP;
 
886
                                } else if(!strcmp(optarg, "tcp")) {
 
887
                                        transport = TP_TCP;
 
888
                                } else if(!strcmp(optarg, "tls")) {
 
889
#                                       if defined(ENABLE_GNUTLS)
 
890
                                                transport = TP_TLS;
 
891
#                                       else
 
892
                                                fprintf(stderr, "compiled without TLS support: "
 
893
                                                        "\"-Ttls\" not supported!\n");
 
894
                                                exit(1);
 
895
#                                       endif
 
896
                                } else {
 
897
                                        fprintf(stderr, "unknown transport '%s'\n", optarg);
 
898
                                        exit(1);
 
899
                                }
 
900
                                break;
 
901
                case 'W':       waittime = atoi(optarg);
 
902
                                break;
 
903
                case 'Y':       runMultithreaded = 1;
 
904
                                break;
 
905
                case 'z':       tlsKeyFile = optarg;
 
906
                                break;
 
907
                case 'Z':       tlsCertFile = optarg;
 
908
                                break;
419
909
                default:        printf("invalid option '%c' or value missing - terminating...\n", opt);
420
910
                                exit (1);
421
911
                                break;
422
912
                }
423
913
        }
424
914
 
 
915
        if(bStatsRecords && waittime) {
 
916
                fprintf(stderr, "warning: generating performance stats and using a waittime "
 
917
                                "is somewhat contradictory!\n");
 
918
        }
 
919
 
 
920
        if(!isatty(1) || bSilent)
 
921
                bShowProgress = 0;
 
922
 
425
923
        if(numConnections > 20) {
426
924
                /* if we use many (whatever this means, 20 is randomly picked)
427
925
                 * connections, we need to make sure we have a high enough
428
926
                 * limit. -- rgerhards, 2010-03-25
429
927
                 */
430
 
                struct rlimit maxFiles;
431
928
                maxFiles.rlim_cur = numConnections + 20;
432
929
                maxFiles.rlim_max = numConnections + 20;
433
930
                if(setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) {
446
943
                }
447
944
        }
448
945
 
 
946
        if(transport == TP_TLS) {
 
947
                initTLS();
 
948
        }
 
949
 
449
950
        if(openConnections() != 0) {
450
951
                printf("error opening connections\n");
451
952
                exit(1);
452
953
        }
453
954
 
454
 
        if(sendMessages() != 0) {
455
 
                printf("error sending messages\n");
 
955
        if(runTests() != 0) {
 
956
                printf("error running tests\n");
456
957
                exit(1);
457
958
        }
458
959
 
459
960
        closeConnections(); /* this is important so that we do not finish too early! */
460
961
 
461
 
        if(nConnDrops > 0)
 
962
        if(nConnDrops > 0 && !bSilent)
462
963
                printf("-D option initiated %ld connection closures\n", nConnDrops);
463
964
 
464
 
        printf("End of tcpflood Run\n");
 
965
        if(!bSilent)
 
966
                printf("End of tcpflood Run\n");
465
967
 
466
968
        exit(ret);
467
969
}