ssl,dtls: use ProtocolVersion from Server Hello
[metze/wireshark/wip.git] / mkcap.c
1 /* mkcap.c
2  * A small program to generate the ASCII form of a capture with TCP
3  * segments of a reasonable nature. The payload is all zeros.
4  *
5  * By Ronnie Sahlberg and Richard Sharpe. From a program initially
6  * written by Ronnie.
7  * Copyright 2003 Ronnie Sahlberg and Richard Sharpe
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Using it to generate a capture file:
24  * ./mkcap [some-flags] > some-file
25  * text2pcap [some-other-flags] some-file some-file.cap
26  * For example:
27
28 ./mkcap -a 2500 -s 15 -I "02 03 04 05" -i "45 45 45 45" -P "00 14"  > ftp.cap.asci
29 text2pcap -t "%Y/%m/%d%t%H:%M:%S." ftp.cap.asci ftp.cap
30
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36
37 #define ETH_1 "00 00 9c fa 1d 74"
38 #define ETH_2 "00 1a b8 93 f6 71"
39 #define IP_1  "0a 01 01 17"
40 #define IP_2  "0a 01 01 ea"
41 #define PORT_1 "01 00"
42 #define PORT_2 "10 00"
43
44 char *eth_1 = ETH_1;
45 char *eth_2 = ETH_2;
46 char *ip_1 = IP_1;
47 char *ip_2 = IP_2;
48 char *port_1 = PORT_1;
49 char *port_2 = PORT_2;
50
51 int verbose = 0;
52
53 typedef enum {
54   normal = 0,
55   random_ack_drop = 1,
56   random_data_drop = 2,
57 } run_type_t;
58
59 typedef struct {
60   int drop_seg_start;
61   int drop_seg_count;
62 } seg_drop_t;
63
64 /*
65  * The array of which segments should be dropped ...
66  */
67 seg_drop_t *drops = NULL;
68 int seg_drop_count = 0;
69 /* The array of which ACKs should be dropped. This is complicated because
70  * An ack might not be generated for a segment because of delayed ACKs.
71  */
72 seg_drop_t *ack_drops = NULL;
73 int ack_drop_count = 0;
74
75 int total_bytes = 32768;
76 int run_type = 0;
77
78 int seq_2=0;
79 int seq_1=0;
80 int ts=0;
81 int jitter = 0;
82 int send_spacing = 10;
83 int ack_delay = 5000;
84 int tcp_nodelay = 0;
85 int tcp_delay_time = 1000; /* What is the real time here? */
86 /*
87  * If tcp_nodelay is set, then this is the amount of data left ...
88  */
89 int remaining_data = 0;
90 int snap_len = 1500;
91 int window = 32768;
92 int ssthresh = 16384;
93 int cwnd = 1460;
94 int used_win = 0;
95 int segment = 0;
96
97 #define SEG_ACK_LOST 1
98 #define SEG_SEG_LOST 2
99
100 struct seg_hist_s {
101   int seq_num;           /* First sequence number in segment     */
102   int len;               /* Number of bytes in segment           */
103   int ts;                /* Timestamp when sent                  */
104   int seg_num;           /* Segment number sent. This can change */
105                          /* but a retransmit will have a new seg */
106   int flags;             /* Flags as above for ack and seg loss  */
107   int acks_first_seq;    /* How many times we have seen an ack
108                             for the first seq number in this seg */
109 };
110
111 #define SEG_HIST_SIZE 128
112 struct seg_hist_s seg_hist[128];    /* This should be dynamic */
113 int next_slot = 0;
114 int first_slot = 0;
115
116 int delayed_ack = 1;          /* Default is delayed ACKs in use ...  */
117 int delayed_ack_wait = 30000; /* 30 mS before an ACK is generated if */
118                               /* no other traffic                    */
119
120 void
121 makeseg(char *eth1, char *eth2, char *ip1, char *ip2, char *p1, char *p2, int *s1, int *s2, char *flags, int len)
122 {
123   int i;
124
125   printf("2002/01/07 00:00:%02d.%06d\n", ts/1000000, ts%1000000);
126   printf("0000 %s %s 08 00\n", eth1, eth2);
127   printf("000e 45 00 %02x %02x 00 00 00 00 40 06 00 00 %s %s\n", (len+40)>>8, (len+40)&0xff, ip1, ip2);
128   printf("0022 %s %s %02x %02x %02x %02x %02x %02x %02x %02x 50 %s 80 00 00 00 00 00", p1, p2,
129          ((*s1)>>24)&0xff,
130          ((*s1)>>16)&0xff,
131          ((*s1)>>8)&0xff,
132          ((*s1))&0xff,
133          ((*s2)>>24)&0xff,
134          ((*s2)>>16)&0xff,
135          ((*s2)>>8)&0xff,
136          ((*s2))&0xff,
137          flags );
138   for(i=0;i<(len<(snap_len-40)?len:snap_len-40);i++)printf(" 00");
139   printf("\n");
140   printf("\n");
141   (*s1)+=len;
142 }
143
144 /*
145  * Figure out when the next ack is due ... here we must skip the acks for
146  * frames that are marked as ACKs dropped as well as the frames marked as
147  * frames dropped. These will be marked by the routine that generates ACKs.
148  * Returns a timestamp value. Returns 2^^31-1 if none are due at all
149  */
150 int next_ack_due()
151 {
152   int slot = next_slot;
153   int ack_lost = 0, seg_lost = 0;
154
155   if (next_slot == first_slot)
156     return ((1U<<31) - 1);
157
158   /*
159    * Figure out if we need to issue an ACK. We skip all outstanding packets
160    * that are marked as ack lost or packet lost.
161    *
162    * We would not usually come in here with a frame marked as lost or ack lost
163    * rather, we will come in here and specify that the ack was due at a
164    * certain time, and gen_next_ack would then determine that the ack
165    * should be lost or the packet lost.
166    */
167
168   /*
169    * Look for a seg slot that is not lost or dropped
170    */
171
172   while (seg_hist[slot].flags & (SEG_ACK_LOST || SEG_SEG_LOST)) {
173     if (seg_hist[slot].flags & SEG_ACK_LOST)
174       ack_lost++;
175     if (seg_hist[slot].flags & SEG_SEG_LOST)
176       seg_lost++;
177     slot = (slot + 1) % SEG_HIST_SIZE;
178   }
179
180   if (slot == next_slot)
181     return ((1U<<31) - 1);
182
183   /*
184    * If there is only one slot occupied, or a segment was lost then
185    * an ACK is due after the last [good] segment left plus ack_delay
186    */
187
188   if (slot == first_slot && next_slot == ((first_slot + 1) % SEG_HIST_SIZE))
189     return (seg_hist[first_slot].ts + ack_delay + jitter);
190
191   if (seg_lost)
192     return (seg_hist[slot].ts + ack_delay + jitter);
193
194   /*
195    * OK, now, either we have only seen lost acks, or there are more than
196    * one outstanding segments, so figure out when the ACK is due.
197    *
198    * If delayed ACK is in force, ACK is due after every second seg, but
199    * if we had a lost ack, then we must ignore 2*lost_ack segments. So,
200    * if there has not been that many segments sent, we return infinity
201    * as the next ACK time
202    */
203
204   if (ack_lost) {
205     if (delayed_ack) {
206       if (((first_slot + 1 + 2 * ack_lost) % SEG_HIST_SIZE) >= next_slot)
207         /* XXX: FIXME, what about when the window is closed */
208         /* XXX: FIXME, use the correct value for this       */
209         return ((1U<<31) - 1);
210       else
211         return seg_hist[(first_slot + 1 + 2 * ack_lost) % SEG_HIST_SIZE].ts +
212           ack_delay + jitter;
213     }
214     else
215       return seg_hist[slot].ts + ack_delay + jitter;
216   }
217   else {
218     if (delayed_ack)
219       return (seg_hist[(first_slot + 1)%SEG_HIST_SIZE].ts+ack_delay+jitter);
220     else
221       return (seg_hist[first_slot].ts+ack_delay+jitter);
222   }
223 }
224
225 /*
226  * Update the relevant info of the sent seg
227  */
228 add_seg_sent(int seq, int len)
229 {
230
231   /*
232    * Should check we have not wrapped around and run into the unacked
233    * stuff ...
234    */
235   /*if (next_slot == first_slot) ;*/
236
237   segment++;
238   seg_hist[next_slot].seq_num        = seq;
239   seg_hist[next_slot].len            = len;
240   seg_hist[next_slot].ts             = ts;
241   seg_hist[next_slot].seg_num        = segment;
242   seg_hist[next_slot].flags          = 0;
243   seg_hist[next_slot].acks_first_seq = 0;
244   used_win = used_win + len;          /* Update the window used */
245
246   /*
247    * Now, update next_slot ...
248    */
249
250   next_slot = (next_slot + 1) % SEG_HIST_SIZE;
251
252 }
253
254 /*
255  * Generate the next ack based on the above reasoning ...
256  */
257
258 #define NO_FORCE_ACK 0
259 #define FORCE_ACK 1
260
261 /*
262  * Generate the next ACK. If we did not generate an ACK, return 0,
263  * else return 1.
264  */
265 int
266 gen_next_ack(int force, int spacing)
267 {
268   int seq_to_ack, new_ts, data_acked;
269
270   /*
271    * We need to check if the segment that we are about to generate an
272    * ack for is a segment that should be dropped ... or an ack that should
273    * be dropped.
274    *
275    * Figure out what we are doing before freeing segments ...
276    */
277
278   seq_to_ack = seg_hist[first_slot].seq_num + seg_hist[first_slot].len;
279   used_win = used_win - seg_hist[first_slot].len;
280   data_acked = seg_hist[first_slot].len;
281   new_ts = seg_hist[first_slot].ts + ack_delay;
282   first_slot = (first_slot + 1) % SEG_HIST_SIZE;
283
284   /*
285    * If delayed ACK in force, then ACK the next segment if there is one
286    */
287   if (delayed_ack && (first_slot != next_slot)) {
288     seq_to_ack += seg_hist[first_slot].len;
289     used_win = used_win - seg_hist[first_slot].len;
290     data_acked += seg_hist[first_slot].len;
291     new_ts = seg_hist[first_slot].ts + ack_delay;
292     first_slot = (first_slot + 1) % SEG_HIST_SIZE;
293   }
294
295   /*
296    * We don't want time to go backward ...
297    */
298   if (new_ts + jitter <= ts)
299     ts++;
300   else
301     ts = new_ts + jitter;
302
303   jitter = (rand() % 10 - 5);  /* Update jitter ... */
304
305   makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &seq_to_ack, "10", 0);
306   /*
307    * Do we want the exponential part or the linear part?
308    */
309   if (cwnd >= ssthresh)
310     cwnd += (1460*data_acked)/cwnd;      /* is this right? */
311   else
312     cwnd = cwnd + data_acked;
313   if (verbose) fprintf(stderr, "Ack rcvd. ts: %d, data_acked: %d, cwnd: %d, window: %d\n",
314                        ts, data_acked, cwnd, window);
315   if (cwnd > window) cwnd = window;
316 }
317
318 void
319 makeackedrun(int len, int spacing, int ackdelay)
320 {
321   int next_ack_ts=0;
322   if (verbose) fprintf(stderr, "makeackedrun: Len=%d, spacing=%d, ackdelay=%d\n",
323                        len, spacing, ackdelay);
324   while(len>0){
325
326     /*
327      * Each time we output a segment, we should check to see if an
328      * ack is due back before the next segment is due ...
329      */
330     int seglen, saved_seq;
331     seglen=(len>1460)?1460:len;
332     /*
333      * Only output what is left in the cwnd.
334      * We assume there is space in the congestion window here
335      */
336     if (seglen > (cwnd - used_win)) seglen = cwnd - used_win;
337
338     len-=seglen;
339     saved_seq = seq_1;
340     if (verbose) fprintf(stderr, "Sending segment. ts: %d, jitter: %d\n", ts, jitter);
341     if(len){
342       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &seq_1, &seq_2, "10", seglen);
343     } else {
344       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &seq_1, &seq_2, "18", seglen);
345     }
346     add_seg_sent(saved_seq, seglen);
347
348     /*
349      * Now, if the window is closed, then we have to eject an
350      * ack, otherwise we can eject more data.
351      * Also, the other end will tend to ack two segments at
352      * a time ... and that ack might fall between two
353      * outgoing segments
354      */
355     jitter = (rand()%10) - 5; /* What if spacing too small */
356
357     if (verbose) fprintf(stderr, "used win: %d, cwnd: %d\n", used_win, cwnd);
358
359     if ((next_ack_ts = next_ack_due()) < ts + spacing + jitter) {
360       int old_ts = ts;
361
362       /*
363        * Generate the ack and retire the segments
364        * If delayed ACK in use, there should be two
365        * or more outstanding segments ...
366        */
367       if (verbose) fprintf(stderr, "Non forced ACK ...ts + spacing + jitter:%d, jitter: %d\n", ts + spacing + jitter, jitter);
368       gen_next_ack(NO_FORCE_ACK, spacing);
369       /*
370        * We don't want time to go backwards ...
371        */
372       if (old_ts + spacing + jitter <= ts)
373         ts++;
374       else
375         ts = old_ts + spacing + jitter;
376
377     } else if (used_win == cwnd) {
378
379       /*
380        * We need an ACK, so generate it and retire the
381        * segments and advance the ts to the time of the ack
382        */
383
384       if (verbose) fprintf(stderr, "Forced ACK ... \n");
385       gen_next_ack(FORCE_ACK, spacing);
386
387       ts+=(spacing+jitter);   /* Should not use spacing here */
388
389     }
390     else {
391       ts+=(spacing+jitter);
392     }
393
394     if (verbose) fprintf(stderr, "Next Ack Due: %d\n", next_ack_ts);
395   }
396
397 }
398
399
400 void
401 makeackedrundroppedtail8kb(int len, int spacing, int ackdelay)
402 {
403   int old_seq1;
404   int dropped_tail;
405   int i;
406   int num_dupes;
407   if (verbose) fprintf(stderr, "makeackedrundroppedtail8kB: Len=%d, spacing=%d, ackdelay=%d\n",
408                        len, spacing, ackdelay);
409   old_seq1=seq_1;
410   while(len>0){
411     int seglen;
412     seglen=(len>1460)?1460:len;
413     len-=seglen;
414     if(seglen==1460){
415       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &seq_1, &seq_2, "10", seglen);
416     } else {
417       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &seq_1, &seq_2, "18", seglen);
418     }
419     ts+=spacing;
420   }
421
422   ts+=ackdelay;
423
424   i=0;
425   num_dupes=-1;
426   dropped_tail=0;
427   while(old_seq1!=seq_1){
428     int ack_len;
429
430     ack_len=((seq_1-old_seq1)>2920)?2920:(seq_1-old_seq1);
431
432     i++;
433     if(i==6){
434       dropped_tail=old_seq1;
435     }
436     old_seq1+=ack_len;
437     if(i<6){
438       makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &old_seq1, "10", 0);
439     } else if (i==6) {
440       makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &dropped_tail, "10", 0);
441       num_dupes+=2;
442     } else {
443       makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &dropped_tail, "10", 0);
444       makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &dropped_tail, "10", 0);
445       num_dupes+=2;
446     }
447     ts+=spacing/2;
448   }
449
450   if(!dropped_tail){
451     return;
452   }
453
454   if(num_dupes<3){
455     int seglen;
456     ts+=1000000;
457     seglen=((seq_1-dropped_tail)>1460)?1460:(seq_1-dropped_tail);
458     if(seglen==1460){
459       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &dropped_tail, &seq_2, "10", seglen);
460     } else {
461       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &dropped_tail, &seq_2, "18", seglen);
462     }
463     ts+=ackdelay;
464
465     makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &seq_1, "10", 0);
466     ts+=spacing;
467     return;
468   }
469
470   while(dropped_tail!=seq_1){
471     int seglen;
472     int ack;
473     seglen=((seq_1-dropped_tail)>1460)?1460:(seq_1-dropped_tail);
474     if(seglen==1460){
475       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &dropped_tail, &seq_2, "10", seglen);
476     } else {
477       makeseg(eth_1, eth_2, ip_1, ip_2, port_1, port_2, &dropped_tail, &seq_2, "18", seglen);
478     }
479     ts+=ackdelay;
480
481     ack=dropped_tail;
482     makeseg(eth_2, eth_1, ip_2, ip_1, port_2, port_1, &seq_2, &ack, "10", 0);
483     ts+=spacing;
484   }
485 }
486
487 void usage()
488 {
489   fprintf(stderr, "Usage: mkcap [OPTIONS], where\n");
490   fprintf(stderr, "\t-a <ack-delay>        is the delay to an ACK (SRT)\n");
491   fprintf(stderr, "\t-b <bytes-to-send>    is the bytes to send on connection\n");
492   fprintf(stderr, "\t-i <ip-addr-hex>      is the sender IP address in hex\n");
493   fprintf(stderr, "\t-I <ip-addr-hex>      is the recipient IP address in hex\n");
494   fprintf(stderr, "\t-n <ISN>              is almost the ISN for the sender\n");
495   fprintf(stderr, "\t-N <ISN>              is almost the ISN for the recipient\n");
496   fprintf(stderr, "\t-p <port-number-hex>  is the port number for sender\n");
497   fprintf(stderr, "\t-P <port-number-hex>  is the port number for recipient\n");
498   fprintf(stderr, "\t-s <send-spacing>     is the send spacing\n");
499   fprintf(stderr, "\t-w <window-size>      is the window size\n");
500 }
501
502 int
503 all_digits(char *str)
504 {
505   int i;
506   if (!str || !(*str)) {
507     return 0;
508   }
509
510   for (i = 0; str[i]; i++) {
511     if (!g_ascii_isdigit(str[i]))
512       return 0;
513   }
514
515   return 1;
516 }
517
518 /*
519  * Process a list of drops. These are of the form:
520  *
521  * first_seg,seg_count[,first_seg,seg_count]*
522  */
523 void
524 process_drop_list(char *drop_list)
525 {
526   int commas=0;
527   char *tok, *save;
528
529   if (!drop_list || !(*drop_list)) {
530     fprintf(stderr, "Strange drop list. NULL or an empty string. No drops!\n");
531     return;
532   }
533   save = (char *)g_strdup(drop_list);
534
535   for (tok=(char *)strtok(drop_list, ","); tok; tok=(char *)strtok(NULL, ",")) {
536     commas++;
537   }
538
539   /* Now, we have commas, divide by two and round up */
540
541   seg_drop_count = (commas+1)/2;
542   drops = (seg_drop_t *)g_malloc(sizeof(seg_drop_t) * seg_drop_count);
543   if (!drops) {
544     fprintf(stderr, "Unable to allocate space for drops ... going without!\n");
545     seg_drop_count = 0;
546     g_free(save);
547     return;
548   }
549
550   /* Now, go through the list again and build the drop list. Any errors and */
551   /* we abort and print a usage message                                     */
552
553   commas = 0;
554   for (tok=(char *)strtok(save, ","); tok; tok=(char *)strtok(NULL, ",")) {
555     int num = atoi(tok);
556
557     if (!all_digits(tok)) {
558       fprintf(stderr, "Error in segment offset or count. Not all digits: %s\n",
559               tok);
560       fprintf(stderr, "No packet drops being performed!\n");
561       g_free(save);
562       g_free(drops);
563       seg_drop_count = 0; drops = NULL;
564       return;
565     }
566     if (num == 0) num = 1;
567     if (commas % 2)
568       drops[commas / 2].drop_seg_count = num;
569     else
570       drops[commas / 2].drop_seg_start = num;
571   }
572
573   g_free(save);
574
575 }
576
577 int
578 main(int argc, char *argv[])
579 {
580   int i;
581   int len;
582   int type;
583   int cnt;
584   extern char *optarg;
585   extern int optind;
586   int opt;
587
588   while ((opt = getopt(argc, argv, "a:b:d:Di:I:j:l:n:N:p:P:r:s:vw:")) != EOF) {
589     switch (opt) {
590     case 'a':
591       ack_delay = atoi(optarg);
592       break;
593
594     case 'b': /* Bytes ... */
595       total_bytes = atoi(optarg);
596       break;
597
598     case 'd': /* A list of drops to simulate */
599       process_drop_list(optarg);
600       break;
601
602     case 'D': /* Toggle tcp_nodelay */
603       tcp_nodelay = (tcp_nodelay + 1) % 1;
604       break;
605
606     case 'i':
607       ip_1 = optarg;
608       break;
609
610     case 'I':
611       ip_2 = optarg;
612       break;
613
614     case 'l':
615       snap_len = atoi(optarg);
616       break;
617
618     case 'n': /* ISN for send dirn, ie, seq_1 */
619       seq_1 = atoi(optarg);
620       break;
621
622     case 'N': /* ISN for recv dirn, ie, seq_2 */
623       seq_2 = atoi(optarg);
624       break;
625
626     case 'p':
627       port_1 = optarg;
628       break;
629
630     case 'P':
631       port_2 = optarg;
632       break;
633
634     case 'r':
635       run_type = atoi(optarg);
636       break;
637
638     case 's':
639       send_spacing = atoi(optarg);
640       break;
641
642     case 'v':
643       verbose++;
644       break;
645
646     case 'w':  /* Window ... */
647       window = atoi(optarg);
648       ssthresh = window / 2;   /* Have to recalc this ... */
649       break;
650
651     default:
652       usage();
653       break;
654     }
655   }
656
657   if (verbose) fprintf(stderr, "IP1: %s, IP2: %s, P1: %s, P2: %s, Ack Delay: %d, Send Spacing: %d\n",
658                        ip_1, ip_2, port_1, port_2, ack_delay, send_spacing);
659
660   /*return 0; */
661
662   if (run_type == 0) {
663     makeackedrun(total_bytes, send_spacing, ack_delay);
664   }
665   else {
666     for(cnt=0;cnt<200;cnt++){
667       type=rand()%150;
668       if(type<75){
669         int j;
670         j=5+rand()%10;
671         for(i=0;i<j;i++){
672           makeackedrun(32768, send_spacing, ack_delay);
673         }
674       } else if(type<90) {
675         int j;
676         j=4+rand()%4;
677         for(i=0;i<j;i++){
678           len=100+rand()&0xfff;
679           makeackedrun(len, send_spacing, ack_delay);
680         }
681       } else {
682         for(i=0;i<5;i++){
683           len=100+rand()&0x3fff+0x1fff;
684           makeackedrun(len, send_spacing, ack_delay);
685           /*makeackedrundroppedtail8kb(len, send_spacing, ack_delay);*/
686         }
687       }
688     }
689   }
690   return 0;
691 }
692
693 /*
694  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
695  *
696  * Local Variables:
697  * c-basic-offset: 2
698  * tab-width: 8
699  * indent-tabs-mode: nil
700  * End:
701  *
702  * ex: set shiftwidth=2 tabstop=8 expandtab:
703  * :indentSize=2:tabSize=8:noTabs=true:
704  */