mod_tcp_seg.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * mod_tcp_seg.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id$
  7. */
  8. #include "config.h"
  9. #include "defines.h"
  10. #include "common.h"
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "mod.h"
  15. #include "pkt.h"
  16. #include "randutil.h"
  17. #include "iputil.h"
  18. #ifndef MIN
  19. #define MIN(a,b) (((a)<(b))?(a):(b))
  20. #endif
  21. #define FAVOR_OLD 1
  22. #define FAVOR_NEW 2
  23. static struct tcp_seg_data {
  24. rand_t *rnd;
  25. int size;
  26. int overlap;
  27. } tcp_seg_data;
  28. void *
  29. tcp_seg_close(void *d)
  30. {
  31. if (tcp_seg_data.rnd != NULL)
  32. rand_close(tcp_seg_data.rnd);
  33. tcp_seg_data.size = 0;
  34. return (NULL);
  35. }
  36. void *
  37. tcp_seg_open(int argc, char *argv[])
  38. {
  39. if (argc < 2) {
  40. warn("need segment <size> in bytes");
  41. return (NULL);
  42. }
  43. tcp_seg_data.rnd = rand_open();
  44. if ((tcp_seg_data.size = atoi(argv[1])) == 0) {
  45. warnx("invalid segment size '%s'", argv[1]);
  46. return (tcp_seg_close(&tcp_seg_data));
  47. }
  48. if (argc == 3) {
  49. if (strcmp(argv[2], "old") == 0 ||
  50. strcmp(argv[2], "win32") == 0)
  51. tcp_seg_data.overlap = FAVOR_OLD;
  52. else if (strcmp(argv[2], "new") == 0 ||
  53. strcmp(argv[2], "unix") == 0)
  54. tcp_seg_data.overlap = FAVOR_NEW;
  55. else
  56. return (tcp_seg_close(&tcp_seg_data));
  57. }
  58. return (&tcp_seg_data);
  59. }
  60. int
  61. tcp_seg_apply(void *d, struct pktq *pktq)
  62. {
  63. struct pkt *pkt, *new, *next, tmp;
  64. uint32_t seq;
  65. int hl, tl, len;
  66. u_char *p, *p1, *p2;
  67. uint16_t eth_type;
  68. uint8_t nxt;
  69. for (pkt = TAILQ_FIRST(pktq); pkt != TAILQ_END(pktq); pkt = next) {
  70. next = TAILQ_NEXT(pkt, pkt_next);
  71. eth_type = htons(pkt->pkt_eth->eth_type);
  72. if (pkt->pkt_ip == NULL)
  73. continue;
  74. if (eth_type == ETH_TYPE_IP) {
  75. nxt = pkt->pkt_ip->ip_p;
  76. } else if (eth_type == ETH_TYPE_IPV6) {
  77. nxt = pkt->pkt_ip6->ip6_nxt;
  78. } else {
  79. continue;
  80. }
  81. if (nxt != IP_PROTO_TCP ||
  82. pkt->pkt_tcp == NULL || pkt->pkt_tcp_data == NULL ||
  83. (pkt->pkt_tcp->th_flags & TH_ACK) == 0 ||
  84. pkt->pkt_end - pkt->pkt_tcp_data <= tcp_seg_data.size)
  85. continue;
  86. if (eth_type == ETH_TYPE_IP) {
  87. hl = pkt->pkt_ip->ip_hl << 2;
  88. } else if (eth_type == ETH_TYPE_IPV6) {
  89. hl = IP6_HDR_LEN;
  90. } else {
  91. continue;
  92. }
  93. tl = pkt->pkt_tcp->th_off << 2;
  94. seq = ntohl(pkt->pkt_tcp->th_seq);
  95. for (p = pkt->pkt_tcp_data; p < pkt->pkt_end; p += len) {
  96. new = pkt_new();
  97. memcpy(new->pkt_eth, pkt->pkt_eth, (u_char*)pkt->pkt_eth_data - (u_char*)pkt->pkt_eth);
  98. p1 = p, p2 = NULL;
  99. len = MIN(pkt->pkt_end - p, tcp_seg_data.size);
  100. if (tcp_seg_data.overlap != 0 &&
  101. p + (len << 1) < pkt->pkt_end) {
  102. rand_strset(tcp_seg_data.rnd, tmp.pkt_buf,len);
  103. if (tcp_seg_data.overlap == FAVOR_OLD) {
  104. p1 = p + len;
  105. p2 = tmp.pkt_buf;
  106. } else if (tcp_seg_data.overlap == FAVOR_NEW) {
  107. p1 = tmp.pkt_buf;
  108. p2 = p + len;
  109. }
  110. len = tcp_seg_data.size;
  111. seq += tcp_seg_data.size;
  112. }
  113. memcpy(new->pkt_ip, pkt->pkt_ip, hl + tl);
  114. new->pkt_ip_data = new->pkt_eth_data + hl;
  115. new->pkt_tcp_data = new->pkt_ip_data + tl;
  116. memcpy(new->pkt_tcp_data, p1, len);
  117. new->pkt_end = new->pkt_tcp_data + len;
  118. if (eth_type == ETH_TYPE_IP) {
  119. new->pkt_ip->ip_id = rand_uint16(tcp_seg_data.rnd);
  120. new->pkt_ip->ip_len = htons(hl + tl + len);
  121. } else {
  122. new->pkt_ip6->ip6_plen = htons(tl + len);
  123. }
  124. new->pkt_tcp->th_seq = htonl(seq);
  125. inet_checksum(eth_type, new->pkt_ip, hl + tl + len);
  126. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  127. if (p2 != NULL) {
  128. new = pkt_dup(new);
  129. new->pkt_ts.tv_usec = 1;
  130. if (eth_type == ETH_TYPE_IP) {
  131. new->pkt_ip->ip_id = rand_uint16(tcp_seg_data.rnd);
  132. new->pkt_ip->ip_len = htons(hl + tl + (len << 1));
  133. } else if (eth_type == ETH_TYPE_IPV6) {
  134. new->pkt_ip6->ip6_plen = htons(tl + (len << 1));
  135. }
  136. new->pkt_tcp->th_seq = htonl(seq - len);
  137. memcpy(new->pkt_tcp_data, p, len);
  138. memcpy(new->pkt_tcp_data + len, p2, len);
  139. new->pkt_end = new->pkt_tcp_data + (len << 1);
  140. inet_checksum(eth_type, new->pkt_ip, hl + tl + (len << 1));
  141. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  142. p += len;
  143. }
  144. seq += len;
  145. }
  146. TAILQ_REMOVE(pktq, pkt, pkt_next);
  147. pkt_free(pkt);
  148. }
  149. return (0);
  150. }
  151. struct mod mod_tcp_seg = {
  152. "tcp_seg", /* name */
  153. "tcp_seg <size> [old|new]", /* usage */
  154. tcp_seg_open, /* open */
  155. tcp_seg_apply, /* apply */
  156. tcp_seg_close /* close */
  157. };