mod_tcp_seg.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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(_U_ 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(_U_ void *d, struct pktq *pktq)
  62. {
  63. struct pkt *pkt, *new, *next;
  64. for (pkt = TAILQ_FIRST(pktq); pkt != TAILQ_END(pktq); pkt = next) {
  65. uint32_t seq;
  66. int hl, tl, len;
  67. u_char *p;
  68. uint16_t eth_type;
  69. uint8_t nxt;
  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. u_char *p1, *p2;
  97. new = pkt_new(pkt->pkt_buf_size);
  98. memcpy(new->pkt_eth, pkt->pkt_eth, (u_char*)pkt->pkt_eth_data - (u_char*)pkt->pkt_eth);
  99. p1 = p, p2 = NULL;
  100. len = MIN(pkt->pkt_end - p, tcp_seg_data.size);
  101. if (tcp_seg_data.overlap != 0 &&
  102. p + (len << 1) < pkt->pkt_end) {
  103. struct pkt tmp;
  104. u_char tmp_buf[pkt->pkt_buf_size];
  105. tmp.pkt_buf = tmp_buf;
  106. tmp.pkt_buf_size = pkt->pkt_buf_size;
  107. rand_strset(tcp_seg_data.rnd, tmp.pkt_buf,len);
  108. if (tcp_seg_data.overlap == FAVOR_OLD) {
  109. p1 = p + len;
  110. p2 = tmp.pkt_buf;
  111. } else if (tcp_seg_data.overlap == FAVOR_NEW) {
  112. p1 = tmp.pkt_buf;
  113. p2 = p + len;
  114. }
  115. len = tcp_seg_data.size;
  116. seq += tcp_seg_data.size;
  117. }
  118. memcpy(new->pkt_ip, pkt->pkt_ip, hl + tl);
  119. new->pkt_ip_data = new->pkt_eth_data + hl;
  120. new->pkt_tcp_data = new->pkt_ip_data + tl;
  121. memcpy(new->pkt_tcp_data, p1, len);
  122. new->pkt_end = new->pkt_tcp_data + len;
  123. if (eth_type == ETH_TYPE_IP) {
  124. new->pkt_ip->ip_id = rand_uint16(tcp_seg_data.rnd);
  125. new->pkt_ip->ip_len = htons(hl + tl + len);
  126. } else {
  127. new->pkt_ip6->ip6_plen = htons(tl + len);
  128. }
  129. new->pkt_tcp->th_seq = htonl(seq);
  130. inet_checksum(eth_type, new->pkt_ip, hl + tl + len);
  131. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  132. if (p2 != NULL) {
  133. new = pkt_dup(new);
  134. new->pkt_ts.tv_usec = 1;
  135. if (eth_type == ETH_TYPE_IP) {
  136. new->pkt_ip->ip_id = rand_uint16(tcp_seg_data.rnd);
  137. new->pkt_ip->ip_len = htons(hl + tl + (len << 1));
  138. } else if (eth_type == ETH_TYPE_IPV6) {
  139. new->pkt_ip6->ip6_plen = htons(tl + (len << 1));
  140. }
  141. new->pkt_tcp->th_seq = htonl(seq - len);
  142. memcpy(new->pkt_tcp_data, p, len);
  143. memcpy(new->pkt_tcp_data + len, p2, len);
  144. new->pkt_end = new->pkt_tcp_data + (len << 1);
  145. inet_checksum(eth_type, new->pkt_ip, hl + tl + (len << 1));
  146. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  147. p += len;
  148. }
  149. seq += len;
  150. }
  151. TAILQ_REMOVE(pktq, pkt, pkt_next);
  152. pkt_free(pkt);
  153. }
  154. return (0);
  155. }
  156. struct mod mod_tcp_seg = {
  157. "tcp_seg", /* name */
  158. "tcp_seg <size> [old|new]", /* usage */
  159. tcp_seg_open, /* open */
  160. tcp_seg_apply, /* apply */
  161. tcp_seg_close /* close */
  162. };