mod_tcp_seg.c 3.5 KB

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