1 /*
2 * scamper_tbit.c
3 *
4 * Copyright (C) 2009-2010 Ben Stasiewicz
5 * Copyright (C) 2010-2011 The University of Waikato
6 * Copyright (C) 2012 Matthew Luckie
7 * Copyright (C) 2012,2015 The Regents of the University of California
8 * Copyright (C) 2021 Matthew Luckie
9 *
10 * Authors: Ben Stasiewicz, Matthew Luckie
11 *
12 * $Id: scamper_tbit.c,v 1.51 2021/08/29 08:55:39 mjl Exp $
13 *
14 * This file implements algorithms described in the tbit-1.0 source code,
15 * as well as the papers:
16 *
17 * "On Inferring TCP Behaviour"
18 * by Jitendra Padhye and Sally Floyd
19 * "Measuring the Evolution of Transport Protocols in the Internet"
20 * by Alberto Medina, Mark Allman, and Sally Floyd.
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation, version 2.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 *
35 */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 #include "internal.h"
41
42 #include "scamper_addr.h"
43 #include "scamper_list.h"
44 #include "scamper_tbit.h"
45 #include "utils.h"
46
47 typedef struct tqe
48 {
49 int off;
50 scamper_tbit_tcpqe_t *qe;
51 } tqe_t;
52
53 struct scamper_tbit_tcpq
54 {
55 uint32_t seq;
56 tqe_t **tqes;
57 int tqec;
58 };
59
scamper_tbit_data_seqoff(uint32_t rcv_nxt,uint32_t seq)60 int scamper_tbit_data_seqoff(uint32_t rcv_nxt, uint32_t seq)
61 {
62 if(seq >= rcv_nxt)
63 return seq - rcv_nxt;
64 return TCP_MAX_SEQNUM - rcv_nxt + seq + 1;
65 }
66
tqe_cmp(const tqe_t * a,const tqe_t * b)67 static int tqe_cmp(const tqe_t *a, const tqe_t *b)
68 {
69 if(a->off < b->off) return -1;
70 if(a->off > b->off) return 1;
71 if(a->qe->len < b->qe->len) return -1;
72 if(a->qe->len > b->qe->len) return 1;
73 return 0;
74 }
75
scamper_tbit_fo_setcookie(scamper_tbit_t * tbit,uint8_t * cookie,uint8_t len)76 int scamper_tbit_fo_setcookie(scamper_tbit_t *tbit,uint8_t *cookie,uint8_t len)
77 {
78 if((tbit->fo_cookie = memdup(cookie, len)) == NULL)
79 return -1;
80 tbit->fo_cookielen = len;
81 return 0;
82 }
83
scamper_tbit_fo_getcookie(scamper_tbit_t * tbit,uint8_t * c,uint8_t * l)84 int scamper_tbit_fo_getcookie(scamper_tbit_t *tbit, uint8_t *c, uint8_t *l)
85 {
86 uint8_t u8, v, iphlen, tcphlen, *pktptr;
87 scamper_tbit_pkt_t *pkt;
88 uint32_t i;
89
90 for(i=0; i<tbit->pktc; i++)
91 {
92 pkt = tbit->pkts[i];
93 if(pkt->dir != SCAMPER_TBIT_PKT_DIR_RX)
94 continue;
95
96 v = (pkt->data[0] >> 4);
97 if(v == 4)
98 {
99 iphlen = (pkt->data[0] & 0xf) * 4;
100 if(pkt->data[9] != IPPROTO_TCP)
101 continue;
102 if((bytes_ntohs(pkt->data+6) & 0x1fff) != 0)
103 continue;
104 }
105 else if(v == 6)
106 {
107 iphlen = 40;
108 u8 = pkt->data[6];
109 for(;;)
110 {
111 switch(u8)
112 {
113 case IPPROTO_HOPOPTS:
114 case IPPROTO_DSTOPTS:
115 case IPPROTO_ROUTING:
116 if(pkt->data[iphlen+1] == 0 ||
117 255 - iphlen <= (pkt->data[iphlen+1] * 8) + 8)
118 break;
119 u8 = pkt->data[iphlen+0];
120 iphlen += (pkt->data[iphlen+1] * 8) + 8;
121 continue;
122
123 case IPPROTO_FRAGMENT:
124 if(255 - iphlen <= 8)
125 break;
126 if((bytes_ntohs(pkt->data+iphlen+2) & 0xfff8) != 0)
127 break;
128 u8 = pkt->data[iphlen+0];
129 iphlen += 8;
130 continue;
131 }
132 break;
133 }
134 if(u8 != IPPROTO_TCP)
135 continue;
136 }
137 else continue;
138
139 if((pkt->data[iphlen+13] & (TH_SYN|TH_ACK)) != (TH_SYN|TH_ACK))
140 continue;
141
142 tcphlen = ((pkt->data[iphlen+12] & 0xf0) >> 4) * 4;
143 u8 = 20;
144 while(u8 < tcphlen)
145 {
146 pktptr = pkt->data + iphlen + u8;
147 if(pktptr[0] == 0)
148 break;
149 if(pktptr[1] == 1) {
150 u8++; continue;
151 }
152
153 if(pktptr[1] == 0 || u8 + pktptr[1] > tcphlen)
154 break;
155
156 if(pktptr[0] == 34 && pktptr[1] > 2 && pktptr[1] <= 18)
157 {
158 *l = pktptr[1] - 2;
159 memcpy(c, pktptr+2, *l);
160 return 1;
161 }
162 else if(pktptr[0] == 254 && pktptr[1] > 4 && pktptr[1] <= 20 &&
163 pktptr[2] == 0xF9 && pktptr[3] == 0x89)
164 {
165 *l = pktptr[1] - 4;
166 memcpy(c, pktptr+4, *l);
167 return 1;
168 }
169 u8 += pktptr[1];
170 }
171 }
172
173 return 0;
174 }
175
scamper_tbit_tcpqe_free(scamper_tbit_tcpqe_t * qe,void (* ff)(void *))176 void scamper_tbit_tcpqe_free(scamper_tbit_tcpqe_t *qe, void (*ff)(void *))
177 {
178 if(qe == NULL) return;
179 if(ff != NULL && qe->data != NULL)
180 ff(qe->data);
181 free(qe);
182 return;
183 }
184
185 /*
186 * scamper_tbit_tcpq_tail
187 *
188 * returns the sequence number at the tail of the tcpq, even if there
189 * are gaps in the tcpq.
190 */
scamper_tbit_tcpq_tail(const scamper_tbit_tcpq_t * tcpq)191 uint32_t scamper_tbit_tcpq_tail(const scamper_tbit_tcpq_t *tcpq)
192 {
193 uint32_t range = 0, edge, u32;
194 scamper_tbit_tcpqe_t *qe;
195 int i;
196
197 for(i=0; i<tcpq->tqec; i++)
198 {
199 qe = tcpq->tqes[i]->qe;
200 edge = qe->seq + qe->len;
201 if((u32 = scamper_tbit_data_seqoff(tcpq->seq, edge)) > range)
202 range = u32;
203 }
204
205 return tcpq->seq + range;
206 }
207
scamper_tbit_tcpq_alloc(uint32_t isn)208 scamper_tbit_tcpq_t *scamper_tbit_tcpq_alloc(uint32_t isn)
209 {
210 scamper_tbit_tcpq_t *q;
211 if((q = malloc_zero(sizeof(scamper_tbit_tcpq_t))) == NULL)
212 goto err;
213 q->seq = isn;
214 return q;
215 err:
216 scamper_tbit_tcpq_free(q, NULL);
217 return NULL;
218 }
219
scamper_tbit_tcpq_flush(scamper_tbit_tcpq_t * q,void (* ff)(void *))220 void scamper_tbit_tcpq_flush(scamper_tbit_tcpq_t *q, void (*ff)(void *))
221 {
222 tqe_t *tqe;
223 int i;
224
225 if(q->tqes == NULL)
226 return;
227
228 for(i=0; i<q->tqec; i++)
229 {
230 tqe = q->tqes[i];
231 scamper_tbit_tcpqe_free(tqe->qe, ff);
232 free(tqe);
233 }
234 free(q->tqes);
235 q->tqes = NULL;
236 q->tqec = 0;
237 return;
238 }
239
scamper_tbit_tcpq_free(scamper_tbit_tcpq_t * q,void (* ff)(void *))240 void scamper_tbit_tcpq_free(scamper_tbit_tcpq_t *q, void (*ff)(void *))
241 {
242 if(q == NULL)
243 return;
244 if(q->tqes != NULL)
245 scamper_tbit_tcpq_flush(q, ff);
246 free(q);
247 return;
248 }
249
scamper_tbit_tcpq_seg(scamper_tbit_tcpq_t * q,uint32_t * seq,uint16_t * len)250 int scamper_tbit_tcpq_seg(scamper_tbit_tcpq_t *q, uint32_t *seq, uint16_t *len)
251 {
252 tqe_t *tqe;
253 assert(q->tqec >= 0);
254 if(q->tqec == 0)
255 return -1;
256 tqe = q->tqes[0];
257 assert(q->seq + tqe->off == tqe->qe->seq);
258 *seq = tqe->qe->seq;
259 *len = tqe->qe->len;
260 return 0;
261 }
262
scamper_tbit_tcpq_pop(scamper_tbit_tcpq_t * q)263 scamper_tbit_tcpqe_t *scamper_tbit_tcpq_pop(scamper_tbit_tcpq_t *q)
264 {
265 scamper_tbit_tcpqe_t *qe;
266 uint16_t len;
267 tqe_t *tqe;
268 int i, off;
269
270 if(q->tqec == 0)
271 return NULL;
272
273 tqe = q->tqes[0];
274 qe = tqe->qe;
275 free(tqe);
276
277 if(--q->tqec > 0)
278 memmove(q->tqes, q->tqes+1, sizeof(tqe_t *) * q->tqec);
279
280 off = scamper_tbit_data_seqoff(q->seq, qe->seq);
281 if(off < 0 && off + qe->len <= 0)
282 return qe;
283
284 len = qe->len + off;
285 for(i=0; i<q->tqec; i++)
286 q->tqes[i]->off -= len;
287 q->seq += len;
288
289 return qe;
290 }
291
scamper_tbit_tcpq_add(scamper_tbit_tcpq_t * q,uint32_t seq,uint8_t flags,uint16_t len,uint8_t * data)292 int scamper_tbit_tcpq_add(scamper_tbit_tcpq_t *q, uint32_t seq,
293 uint8_t flags, uint16_t len, uint8_t *data)
294 {
295 tqe_t *tqe;
296
297 assert(scamper_tbit_data_inrange(q->seq, seq, len) != 0);
298 if((tqe = malloc_zero(sizeof(tqe_t))) == NULL)
299 goto err;
300 if((tqe->qe = malloc_zero(sizeof(scamper_tbit_tcpqe_t))) == NULL)
301 goto err;
302 tqe->off = scamper_tbit_data_seqoff(q->seq, seq);
303 tqe->qe->seq = seq;
304 tqe->qe->flags = flags;
305 tqe->qe->len = len;
306 tqe->qe->data = data;
307 if(array_insert((void ***)&q->tqes,&q->tqec,tqe,(array_cmp_t)tqe_cmp) != 0)
308 goto err;
309 return 0;
310
311 err:
312 if(tqe != NULL)
313 {
314 scamper_tbit_tcpqe_free(tqe->qe, NULL);
315 free(tqe);
316 }
317 return -1;
318 }
319
scamper_tbit_tcpq_sack(scamper_tbit_tcpq_t * q,uint32_t * sack,int count)320 int scamper_tbit_tcpq_sack(scamper_tbit_tcpq_t *q, uint32_t *sack, int count)
321 {
322 uint32_t left, right;
323 scamper_tbit_tcpqe_t *qe;
324 int i, off, c = 0;
325
326 assert(q->tqec >= 0);
327 if(q->tqec == 0)
328 return 0;
329
330 qe = q->tqes[0]->qe;
331 if(qe->len == 0)
332 return 0;
333
334 left = qe->seq;
335 right = qe->seq + qe->len;
336 assert(scamper_tbit_data_seqoff(q->seq, left) > 0);
337
338 for(i=1; i<q->tqec && c < count; i++)
339 {
340 qe = q->tqes[i]->qe;
341 if(qe->len == 0)
342 continue;
343 if((off = scamper_tbit_data_seqoff(right, qe->seq)) <= 0)
344 {
345 off = abs(off);
346 if(qe->len > off)
347 right = right + qe->len - off;
348 continue;
349 }
350
351 sack[c*2] = left;
352 sack[(c*2)+1] = right;
353 c++;
354
355 left = qe->seq;
356 right = qe->seq + qe->len;
357 }
358
359 if(c < count)
360 {
361 sack[c*2] = left;
362 sack[(c*2)+1] = right;
363 c++;
364 }
365
366 return c;
367 }
368
369 /*
370 * scamper_tbit_data_inrange:
371 *
372 * rcv_nxt <= beginning sequence number of segment < rcv_nxt + rcv_wnd OR
373 * rcv_nxt <= ending sequence number of segment < rcv_nxt + rcv_wnd
374 */
scamper_tbit_data_inrange(uint32_t rcv_nxt,uint32_t seq,uint16_t len)375 int scamper_tbit_data_inrange(uint32_t rcv_nxt, uint32_t seq, uint16_t len)
376 {
377 if((SEQ_LEQ(rcv_nxt, seq) && SEQ_LT(seq, rcv_nxt + 65535)) ||
378 (SEQ_LEQ(rcv_nxt, seq+len-1) && SEQ_LT(seq+len-1, rcv_nxt + 65535)))
379 return 1;
380 return 0;
381 }
382
scamper_tbit_pkt_iplen(const scamper_tbit_pkt_t * pkt)383 int scamper_tbit_pkt_iplen(const scamper_tbit_pkt_t *pkt)
384 {
385 uint8_t v = pkt->data[0] >> 4;
386 int rc = -1;
387
388 if(v == 4)
389 rc = bytes_ntohs(pkt->data+2);
390 else if(v == 6)
391 rc = bytes_ntohs(pkt->data+4) + 40;
392
393 return rc;
394 }
395
scamper_tbit_pkt_iph(const scamper_tbit_pkt_t * pkt,uint8_t * proto,uint8_t * iphlen,uint16_t * iplen)396 int scamper_tbit_pkt_iph(const scamper_tbit_pkt_t *pkt,
397 uint8_t *proto, uint8_t *iphlen, uint16_t *iplen)
398 {
399 uint8_t v = pkt->data[0] >> 4;
400
401 if(v == 4)
402 {
403 *iphlen = (pkt->data[0] & 0xf) * 4;
404 *iplen = bytes_ntohs(pkt->data+2);
405 *proto = pkt->data[9];
406 return 0;
407 }
408
409 if(v == 6)
410 {
411 *iphlen = 40;
412 *iplen = bytes_ntohs(pkt->data+4) + 40;
413 *proto = pkt->data[6];
414 for(;;)
415 {
416 switch(*proto)
417 {
418 case IPPROTO_HOPOPTS:
419 case IPPROTO_DSTOPTS:
420 case IPPROTO_ROUTING:
421 if(pkt->data[(*iphlen)+1] == 0 ||
422 255 - *iphlen <= (pkt->data[(*iphlen)+1] * 8) + 8)
423 return -1;
424 *proto = pkt->data[*iphlen];
425 *iphlen += (pkt->data[(*iphlen)+1] * 8) + 8;
426 continue;
427 case IPPROTO_FRAGMENT:
428 if(255 - *iphlen <= 8)
429 return -1;
430 *proto = pkt->data[*iphlen];
431 if((bytes_ntohs(pkt->data+(*iphlen)+2) & 0xfff8) != 0) /* off */
432 return -1;
433 if((pkt->data[(*iphlen)+3] & 0x1) != 0) /* mf */
434 return -1;
435 *iphlen += 8;
436 continue;
437 }
438 break;
439 }
440 return 0;
441 }
442
443 return -1;
444 }
445
scamper_tbit_pkt_tcpdatabytes(const scamper_tbit_pkt_t * pkt,uint16_t * bc)446 int scamper_tbit_pkt_tcpdatabytes(const scamper_tbit_pkt_t *pkt, uint16_t *bc)
447 {
448 uint8_t iphlen, tcphlen, proto;
449 uint16_t iplen;
450
451 if(scamper_tbit_pkt_iph(pkt, &proto, &iphlen, &iplen) != 0)
452 return -1;
453 if(proto != IPPROTO_TCP)
454 return -1;
455 tcphlen = ((pkt->data[iphlen+12] & 0xf0) >> 4) * 4;
456 *bc = iplen - iphlen - tcphlen;
457 return 0;
458 }
459
scamper_tbit_pkt_tcpack(const scamper_tbit_pkt_t * pkt,uint32_t * ack)460 int scamper_tbit_pkt_tcpack(const scamper_tbit_pkt_t *pkt, uint32_t *ack)
461 {
462 uint8_t iphlen, proto;
463 uint16_t iplen;
464 if(scamper_tbit_pkt_iph(pkt, &proto, &iphlen, &iplen) != 0)
465 return -1;
466 if(proto != IPPROTO_TCP || (pkt->data[iphlen+13] & TH_ACK) == 0)
467 return -1;
468 *ack = bytes_ntohl(pkt->data+iphlen+8);
469 return 0;
470 }
471
scamper_tbit_icw_size(const scamper_tbit_t * tbit,uint32_t * icw_out)472 int scamper_tbit_icw_size(const scamper_tbit_t *tbit, uint32_t *icw_out)
473 {
474 const scamper_tbit_icw_t *icw = tbit->data;
475 const scamper_tbit_pkt_t *pkt;
476 scamper_tbit_tcpq_t *q = NULL;
477 uint32_t i, u32, seq, start_seq;
478 uint16_t iplen, datalen;
479 uint8_t proto, iphlen, tcphlen, flags, start_seq_c = 0;
480 int rc = -1;
481
482 if(tbit->result != SCAMPER_TBIT_RESULT_ICW_SUCCESS ||
483 tbit->pktc < 1)
484 goto done;
485
486 for(i=1; i<tbit->pktc; i++)
487 {
488 pkt = tbit->pkts[i];
489 if(pkt->dir == SCAMPER_TBIT_PKT_DIR_RX)
490 break;
491 }
492 if(i == tbit->pktc ||
493 scamper_tbit_pkt_iph(pkt, &proto, &iphlen, &iplen) != 0 ||
494 proto != IPPROTO_TCP ||
495 (pkt->data[iphlen+13] & (TH_SYN|TH_ACK)) != (TH_SYN|TH_ACK))
496 goto done;
497
498 start_seq = bytes_ntohl(pkt->data+iphlen+4) + icw->start_seq;
499 if((q = scamper_tbit_tcpq_alloc(start_seq)) == NULL)
500 goto done;
501
502 for(i++; i<tbit->pktc; i++)
503 {
504 pkt = tbit->pkts[i];
505 if(pkt->dir != SCAMPER_TBIT_PKT_DIR_RX)
506 continue;
507 if(scamper_tbit_pkt_iph(pkt, &proto, &iphlen, &iplen) != 0)
508 break;
509 if(proto != IPPROTO_TCP)
510 break;
511 seq = bytes_ntohl(pkt->data+iphlen+4);
512 tcphlen = ((pkt->data[iphlen+12] & 0xf0) >> 4) * 4;
513 flags = pkt->data[iphlen+13];
514
515 if((datalen = iplen - iphlen - tcphlen) == 0 && (flags & TH_FIN) == 0)
516 continue;
517 if(scamper_tbit_data_inrange(start_seq, seq, datalen) == 0)
518 continue;
519
520 if(seq == start_seq)
521 {
522 start_seq_c++;
523 if(start_seq_c == 2)
524 {
525 u32 = scamper_tbit_tcpq_tail(q);
526 *icw_out = scamper_tbit_data_seqoff(start_seq, u32);
527 rc = 0;
528 break;
529 }
530 }
531
532 if(scamper_tbit_tcpq_add(q, seq, flags, datalen, NULL) != 0)
533 break;
534 }
535
536 done:
537 scamper_tbit_tcpq_free(q, NULL);
538 return rc;
539 }
540
scamper_tbit_stats(const scamper_tbit_t * tbit,scamper_tbit_stats_t * stats)541 int scamper_tbit_stats(const scamper_tbit_t *tbit, scamper_tbit_stats_t *stats)
542 {
543 const scamper_tbit_pkt_t *pkt, *syn;
544 scamper_tbit_tcpq_t *q = NULL;
545 scamper_tbit_tcpqe_t *qe;
546 uint32_t rcv_nxt, seq;
547 uint16_t iplen, datalen, len;
548 uint8_t proto, iphlen, tcphlen, flags;
549 uint32_t i;
550 int off, seenfin = 0;
551
552 memset(stats, 0, sizeof(scamper_tbit_stats_t));
553 if(tbit->pktc < 1)
554 return 0;
555
556 /* to begin with, look for a SYN/ACK */
557 syn = tbit->pkts[0];
558 for(i=1; i<tbit->pktc; i++)
559 {
560 pkt = tbit->pkts[i];
561 if(pkt->dir == SCAMPER_TBIT_PKT_DIR_RX)
562 break;
563 }
564 if(i == tbit->pktc)
565 return 0;
566
567 if(scamper_tbit_pkt_iph(pkt, &proto, &iphlen, &iplen) != 0)
568 goto err;
569 if(proto != IPPROTO_TCP)
570 goto err;
571 if((pkt->data[iphlen+13] & (TH_SYN|TH_ACK)) != (TH_SYN|TH_ACK))
572 goto err;
573
574 timeval_diff_tv(&stats->synack_rtt, &syn->tv, &pkt->tv);
575 rcv_nxt = bytes_ntohl(pkt->data+iphlen+4) + 1;
576
577 if((q = scamper_tbit_tcpq_alloc(rcv_nxt)) == NULL)
578 goto err;
579
580 for(i++; i<tbit->pktc; i++)
581 {
582 pkt = tbit->pkts[i];
583 if(pkt->dir != SCAMPER_TBIT_PKT_DIR_RX)
584 continue;
585 if(scamper_tbit_pkt_iph(pkt, &proto, &iphlen, &iplen) != 0)
586 goto err;
587 if(proto != IPPROTO_TCP)
588 goto err;
589 seq = bytes_ntohl(pkt->data+iphlen+4);
590 tcphlen = ((pkt->data[iphlen+12] & 0xf0) >> 4) * 4;
591 flags = pkt->data[iphlen+13];
592 if((datalen = iplen - iphlen - tcphlen) == 0 && (flags & TH_FIN) == 0)
593 continue;
594
595 stats->rx_totalsize += (iplen - iphlen - tcphlen);
596
597 /* skip over a packet out of range */
598 if(scamper_tbit_data_inrange(rcv_nxt, seq, datalen) == 0)
599 continue;
600
601 if(scamper_tbit_tcpq_add(q, seq, flags, datalen, NULL) != 0)
602 goto err;
603
604 while(scamper_tbit_tcpq_seg(q, &seq, &datalen) == 0)
605 {
606 if(scamper_tbit_data_inrange(rcv_nxt, seq, datalen) == 0)
607 {
608 scamper_tbit_tcpqe_free(scamper_tbit_tcpq_pop(q), NULL);
609 continue;
610 }
611
612 /* can't process this packet yet */
613 if((off = scamper_tbit_data_seqoff(rcv_nxt, seq)) > 0)
614 break;
615
616 qe = scamper_tbit_tcpq_pop(q);
617 flags = qe->flags;
618 scamper_tbit_tcpqe_free(qe, NULL);
619 len = datalen + off;
620 rcv_nxt += len;
621 stats->rx_xfersize += len;
622
623 if((flags & TH_FIN) != 0)
624 {
625 timeval_diff_tv(&stats->xfertime, &syn->tv, &pkt->tv);
626 seenfin = 1;
627 }
628 }
629 }
630
631 if(seenfin == 0)
632 goto err;
633
634 scamper_tbit_tcpq_free(q, NULL);
635 return 0;
636
637 err:
638 scamper_tbit_tcpq_free(q, NULL);
639 return -1;
640 }
641
scamper_tbit_type2str(const scamper_tbit_t * tbit,char * buf,size_t len)642 char *scamper_tbit_type2str(const scamper_tbit_t *tbit, char *buf, size_t len)
643 {
644 static char *t[] = {
645 NULL,
646 "pmtud",
647 "ecn",
648 "null",
649 "sack-rcvr",
650 "icw",
651 "abc",
652 "blind-data",
653 "blind-rst",
654 "blind-syn",
655 "blind-fin",
656 };
657
658 if(tbit->type >= sizeof(t) / sizeof(char *) || t[tbit->type] == NULL)
659 {
660 snprintf(buf, len, "%d", tbit->type);
661 return buf;
662 }
663
664 return t[tbit->type];
665 }
666
scamper_tbit_res2str(const scamper_tbit_t * tbit,char * buf,size_t len)667 char *scamper_tbit_res2str(const scamper_tbit_t *tbit, char *buf, size_t len)
668 {
669 static char *t[] = {
670 "none", /* 0 */
671 "tcp-noconn",
672 "tcp-rst",
673 "tcp-error",
674 "sys-error",
675 "aborted",
676 "tcp-noconn-rst",
677 "halted",
678 "tcp-badopt",
679 "tcp-fin",
680 "tcp-zerowin", /* 10 */
681 NULL,
682 NULL,
683 NULL,
684 NULL,
685 NULL,
686 NULL,
687 NULL,
688 NULL,
689 NULL,
690 "pmtud-noack", /* 20 */
691 "pmtud-nodata",
692 "pmtud-toosmall",
693 "pmtud-nodf",
694 "pmtud-fail",
695 "pmtud-success",
696 "pmtud-cleardf",
697 NULL,
698 NULL,
699 NULL,
700 "ecn-success", /* 30 */
701 "ecn-incapable",
702 "ecn-badsynack",
703 "ecn-noece",
704 "ecn-noack",
705 "ecn-nodata",
706 NULL,
707 NULL,
708 NULL,
709 NULL,
710 "null-success", /* 40 */
711 "null-nodata",
712 NULL,
713 NULL,
714 NULL,
715 NULL,
716 NULL,
717 NULL,
718 NULL,
719 NULL,
720 "sack-incapable", /* 50 */
721 "sack-rcvr-success",
722 "sack-rcvr-shifted",
723 "sack-rcvr-timeout",
724 "sack-rcvr-nosack",
725 NULL,
726 NULL,
727 NULL,
728 NULL,
729 NULL,
730 "icw-success", /* 60 */
731 "icw-tooshort",
732 NULL,
733 NULL,
734 NULL,
735 NULL,
736 NULL,
737 NULL,
738 NULL,
739 NULL,
740 "abc-success", /* 70 */
741 "abc-tooshort",
742 "abc-badicw",
743 NULL,
744 NULL,
745 NULL,
746 NULL,
747 NULL,
748 NULL,
749 NULL,
750 "blind-accepted", /* 80 */
751 "blind-challenge",
752 "blind-ignored",
753 "blind-rst",
754 "blind-synnew",
755 };
756
757 if(tbit->result >= sizeof(t) / sizeof(char *) || t[tbit->result] == NULL)
758 {
759 snprintf(buf, len, "%d", tbit->result);
760 return buf;
761 }
762
763 return t[tbit->result];
764 }
765
scamper_tbit_pkt_alloc(uint8_t dir,uint8_t * data,uint16_t len,struct timeval * tv)766 scamper_tbit_pkt_t *scamper_tbit_pkt_alloc(uint8_t dir, uint8_t *data,
767 uint16_t len, struct timeval *tv)
768 {
769 scamper_tbit_pkt_t *pkt;
770
771 if((pkt = malloc_zero(sizeof(scamper_tbit_pkt_t))) == NULL)
772 goto err;
773
774 pkt->dir = dir;
775 if(len != 0 && data != NULL)
776 {
777 if((pkt->data = memdup(data, len)) == NULL)
778 goto err;
779 pkt->len = len;
780 }
781 if(tv != NULL) timeval_cpy(&pkt->tv, tv);
782 return pkt;
783
784 err:
785 free(pkt);
786 return NULL;
787 }
788
scamper_tbit_pkt_free(scamper_tbit_pkt_t * pkt)789 void scamper_tbit_pkt_free(scamper_tbit_pkt_t *pkt)
790 {
791 if(pkt == NULL)
792 return;
793 if(pkt->data != NULL) free(pkt->data);
794 free(pkt);
795 return;
796 }
797
scamper_tbit_pkts_alloc(scamper_tbit_t * tbit,uint32_t count)798 int scamper_tbit_pkts_alloc(scamper_tbit_t *tbit, uint32_t count)
799 {
800 size_t size = count * sizeof(scamper_tbit_pkt_t *);
801 if((tbit->pkts = (scamper_tbit_pkt_t **)malloc_zero(size)) == NULL)
802 return -1;
803 return 0;
804 }
805
scamper_tbit_record_pkt(scamper_tbit_t * tbit,scamper_tbit_pkt_t * pkt)806 int scamper_tbit_record_pkt(scamper_tbit_t *tbit, scamper_tbit_pkt_t *pkt)
807 {
808 size_t len = (tbit->pktc + 1) * sizeof(scamper_tbit_pkt_t *);
809
810 /* Add a new element to the pkts array */
811 if(realloc_wrap((void**)&tbit->pkts, len) != 0)
812 return -1;
813
814 tbit->pkts[tbit->pktc++] = pkt;
815 return 0;
816 }
817
scamper_tbit_app_http_alloc(uint8_t type,char * host,char * file)818 scamper_tbit_app_http_t *scamper_tbit_app_http_alloc(uint8_t type,
819 char *host, char *file)
820 {
821 scamper_tbit_app_http_t *http;
822
823 if((http = malloc_zero(sizeof(scamper_tbit_app_http_t))) == NULL ||
824 (host != NULL && (http->host = strdup(host)) == NULL) ||
825 (file != NULL && (http->file = strdup(file)) == NULL))
826 {
827 if(http == NULL) return NULL;
828 if(http->host != NULL) free(http->host);
829 if(http->file != NULL) free(http->file);
830 free(http);
831 return NULL;
832 }
833
834 http->type = type;
835 return http;
836 }
837
scamper_tbit_app_http_free(scamper_tbit_app_http_t * http)838 void scamper_tbit_app_http_free(scamper_tbit_app_http_t *http)
839 {
840 if(http == NULL)
841 return;
842 if(http->host != NULL) free(http->host);
843 if(http->file != NULL) free(http->file);
844 free(http);
845 return;
846 }
847
scamper_tbit_app_bgp_alloc(void)848 scamper_tbit_app_bgp_t *scamper_tbit_app_bgp_alloc(void)
849 {
850 return malloc_zero(sizeof(scamper_tbit_app_bgp_t));
851 }
852
scamper_tbit_app_bgp_free(scamper_tbit_app_bgp_t * bgp)853 void scamper_tbit_app_bgp_free(scamper_tbit_app_bgp_t *bgp)
854 {
855 if(bgp == NULL)
856 return;
857 free(bgp);
858 return;
859 }
860
scamper_tbit_pmtud_alloc(void)861 scamper_tbit_pmtud_t *scamper_tbit_pmtud_alloc(void)
862 {
863 return malloc_zero(sizeof(scamper_tbit_pmtud_t));
864 }
865
scamper_tbit_pmtud_free(scamper_tbit_pmtud_t * pmtud)866 void scamper_tbit_pmtud_free(scamper_tbit_pmtud_t *pmtud)
867 {
868 if(pmtud == NULL)
869 return;
870 if(pmtud->ptbsrc != NULL)
871 scamper_addr_free(pmtud->ptbsrc);
872 free(pmtud);
873 return;
874 }
875
scamper_tbit_null_alloc(void)876 scamper_tbit_null_t *scamper_tbit_null_alloc(void)
877 {
878 return malloc_zero(sizeof(scamper_tbit_null_t));
879 }
880
scamper_tbit_null_free(scamper_tbit_null_t * null)881 void scamper_tbit_null_free(scamper_tbit_null_t *null)
882 {
883 if(null == NULL)
884 return;
885 free(null);
886 return;
887 }
888
scamper_tbit_icw_alloc(void)889 scamper_tbit_icw_t *scamper_tbit_icw_alloc(void)
890 {
891 return malloc_zero(sizeof(scamper_tbit_icw_t));
892 }
893
scamper_tbit_icw_free(scamper_tbit_icw_t * icw)894 void scamper_tbit_icw_free(scamper_tbit_icw_t *icw)
895 {
896 free(icw);
897 return;
898 }
899
scamper_tbit_blind_alloc(void)900 scamper_tbit_blind_t *scamper_tbit_blind_alloc(void)
901 {
902 return malloc_zero(sizeof(scamper_tbit_blind_t));
903 }
904
scamper_tbit_blind_free(scamper_tbit_blind_t * blind)905 void scamper_tbit_blind_free(scamper_tbit_blind_t *blind)
906 {
907 if(blind == NULL)
908 return;
909 free(blind);
910 return;
911 }
912
913 /* Free the tbit object. */
scamper_tbit_free(scamper_tbit_t * tbit)914 void scamper_tbit_free(scamper_tbit_t *tbit)
915 {
916 uint32_t i;
917
918 if(tbit == NULL)
919 return;
920
921 if(tbit->src != NULL) scamper_addr_free(tbit->src);
922 if(tbit->dst != NULL) scamper_addr_free(tbit->dst);
923 if(tbit->list != NULL) scamper_list_free(tbit->list);
924 if(tbit->cycle != NULL) scamper_cycle_free(tbit->cycle);
925
926 if(tbit->fo_cookie != NULL) free(tbit->fo_cookie);
927
928 /* Free the recorded packets */
929 if(tbit->pkts != NULL)
930 {
931 for(i=0; i<tbit->pktc; i++)
932 scamper_tbit_pkt_free(tbit->pkts[i]);
933 free(tbit->pkts);
934 }
935
936 /* Free protocol specific data */
937 if(tbit->app_data != NULL)
938 {
939 if(tbit->app_proto == SCAMPER_TBIT_APP_HTTP)
940 scamper_tbit_app_http_free(tbit->app_data);
941 }
942
943 /* Free test-specific data */
944 if(tbit->data != NULL)
945 {
946 if(tbit->type == SCAMPER_TBIT_TYPE_PMTUD)
947 scamper_tbit_pmtud_free(tbit->data);
948 else if(tbit->type == SCAMPER_TBIT_TYPE_NULL)
949 scamper_tbit_null_free(tbit->data);
950 else if(tbit->type == SCAMPER_TBIT_TYPE_ICW)
951 scamper_tbit_icw_free(tbit->data);
952 else if(tbit->type == SCAMPER_TBIT_TYPE_BLIND_RST ||
953 tbit->type == SCAMPER_TBIT_TYPE_BLIND_SYN ||
954 tbit->type == SCAMPER_TBIT_TYPE_BLIND_DATA ||
955 tbit->type == SCAMPER_TBIT_TYPE_BLIND_FIN)
956 scamper_tbit_blind_free(tbit->data);
957 }
958
959 free(tbit);
960 return;
961 }
962
scamper_tbit_alloc(void)963 scamper_tbit_t *scamper_tbit_alloc(void)
964 {
965 return (scamper_tbit_t *)malloc_zero(sizeof(scamper_tbit_t));
966 }
967