mod_tcp_seg.c 5.4 KB

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