mod_tcp_seg.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * mod_tcp_seg.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id: mod_tcp_seg.c 2191 2009-02-01 21:34:27Z aturner $
  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. #ifndef MIN
  18. #define MIN(a,b) (((a)<(b))?(a):(b))
  19. #endif
  20. #define FAVOR_OLD 1
  21. #define FAVOR_NEW 2
  22. static struct tcp_seg_data {
  23. rand_t *rnd;
  24. int size;
  25. int overlap;
  26. } tcp_seg_data;
  27. void *
  28. tcp_seg_close(void *d)
  29. {
  30. if (tcp_seg_data.rnd != NULL)
  31. rand_close(tcp_seg_data.rnd);
  32. tcp_seg_data.size = 0;
  33. return (NULL);
  34. }
  35. void *
  36. tcp_seg_open(int argc, char *argv[])
  37. {
  38. if (argc < 2) {
  39. warn("need segment <size> in bytes");
  40. return (NULL);
  41. }
  42. tcp_seg_data.rnd = rand_open();
  43. if ((tcp_seg_data.size = atoi(argv[1])) == 0) {
  44. warnx("invalid segment size '%s'", argv[1]);
  45. return (tcp_seg_close(&tcp_seg_data));
  46. }
  47. if (argc == 3) {
  48. if (strcmp(argv[2], "old") == 0 ||
  49. strcmp(argv[2], "win32") == 0)
  50. tcp_seg_data.overlap = FAVOR_OLD;
  51. else if (strcmp(argv[2], "new") == 0 ||
  52. strcmp(argv[2], "unix") == 0)
  53. tcp_seg_data.overlap = FAVOR_NEW;
  54. else
  55. return (tcp_seg_close(&tcp_seg_data));
  56. }
  57. return (&tcp_seg_data);
  58. }
  59. int
  60. tcp_seg_apply(void *d, struct pktq *pktq)
  61. {
  62. struct pkt *pkt, *new, *next, tmp;
  63. uint32_t seq;
  64. int hl, tl, len;
  65. u_char *p, *p1, *p2;
  66. for (pkt = TAILQ_FIRST(pktq); pkt != TAILQ_END(pktq); pkt = next) {
  67. next = TAILQ_NEXT(pkt, pkt_next);
  68. if (pkt->pkt_ip == NULL || pkt->pkt_ip->ip_p != IP_PROTO_TCP ||
  69. pkt->pkt_tcp == NULL || pkt->pkt_tcp_data == NULL ||
  70. (pkt->pkt_tcp->th_flags & TH_ACK) == 0 ||
  71. pkt->pkt_end - pkt->pkt_tcp_data <= tcp_seg_data.size)
  72. continue;
  73. hl = pkt->pkt_ip->ip_hl << 2;
  74. tl = pkt->pkt_tcp->th_off << 2;
  75. seq = ntohl(pkt->pkt_tcp->th_seq);
  76. for (p = pkt->pkt_tcp_data; p < pkt->pkt_end; p += len) {
  77. new = pkt_new();
  78. p1 = p, p2 = NULL;
  79. len = MIN(pkt->pkt_end - p, tcp_seg_data.size);
  80. if (tcp_seg_data.overlap != 0 &&
  81. p + (len << 1) < pkt->pkt_end) {
  82. rand_strset(tcp_seg_data.rnd, tmp.pkt_buf,len);
  83. if (tcp_seg_data.overlap == FAVOR_OLD) {
  84. p1 = p + len;
  85. p2 = tmp.pkt_buf;
  86. } else if (tcp_seg_data.overlap == FAVOR_NEW) {
  87. p1 = tmp.pkt_buf;
  88. p2 = p + len;
  89. }
  90. len = tcp_seg_data.size;
  91. seq += tcp_seg_data.size;
  92. }
  93. memcpy(new->pkt_ip, pkt->pkt_ip, hl + tl);
  94. new->pkt_ip_data = new->pkt_eth_data + hl;
  95. new->pkt_tcp_data = new->pkt_ip_data + tl;
  96. memcpy(new->pkt_tcp_data, p1, len);
  97. new->pkt_end = new->pkt_tcp_data + len;
  98. new->pkt_ip->ip_id = rand_uint16(tcp_seg_data.rnd);
  99. new->pkt_ip->ip_len = htons(hl + tl + len);
  100. new->pkt_tcp->th_seq = htonl(seq);
  101. ip_checksum(new->pkt_ip, hl + tl + len);
  102. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  103. if (p2 != NULL) {
  104. new = pkt_dup(new);
  105. new->pkt_ts.tv_usec = 1;
  106. new->pkt_ip->ip_id =
  107. rand_uint16(tcp_seg_data.rnd);
  108. new->pkt_ip->ip_len = htons(hl + tl +
  109. (len << 1));
  110. new->pkt_tcp->th_seq = htonl(seq - len);
  111. memcpy(new->pkt_tcp_data, p, len);
  112. memcpy(new->pkt_tcp_data + len, p2, len);
  113. new->pkt_end = new->pkt_tcp_data + (len << 1);
  114. ip_checksum(new->pkt_ip, hl + tl + (len << 1));
  115. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  116. p += len;
  117. }
  118. seq += len;
  119. }
  120. TAILQ_REMOVE(pktq, pkt, pkt_next);
  121. pkt_free(pkt);
  122. }
  123. return (0);
  124. }
  125. struct mod mod_tcp_seg = {
  126. "tcp_seg", /* name */
  127. "tcp_seg <size> [old|new]", /* usage */
  128. tcp_seg_open, /* open */
  129. tcp_seg_apply, /* apply */
  130. tcp_seg_close /* close */
  131. };