mod_ip_chaff.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * mod_ip_chaff.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id$
  7. */
  8. #include "config.h"
  9. #include "mod.h"
  10. #include "pkt.h"
  11. #include "randutil.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #define CHAFF_TYPE_DUP 1
  16. #define CHAFF_TYPE_OPT 2
  17. #define CHAFF_TYPE_TTL 3
  18. struct ip_chaff_data {
  19. rand_t *rnd;
  20. int type;
  21. int ttl;
  22. struct pktq *pktq;
  23. };
  24. void *
  25. ip_chaff_close(void *d)
  26. {
  27. struct ip_chaff_data *data = (struct ip_chaff_data *)d;
  28. if (data != NULL) {
  29. rand_close(data->rnd);
  30. free(data);
  31. }
  32. return (NULL);
  33. }
  34. void *
  35. ip_chaff_open(int argc, char *argv[])
  36. {
  37. struct ip_chaff_data *data;
  38. if (argc < 2)
  39. return (NULL);
  40. if ((data = calloc(1, sizeof(*data))) == NULL)
  41. return (NULL);
  42. data->rnd = rand_open();
  43. if (strcasecmp(argv[1], "dup") == 0) {
  44. data->type = CHAFF_TYPE_DUP;
  45. } else if (strcasecmp(argv[1], "opt") == 0) {
  46. data->type = CHAFF_TYPE_OPT;
  47. } else if ((data->ttl = strtol(argv[1], NULL, 10)) >= 0 && data->ttl < 256) {
  48. data->type = CHAFF_TYPE_TTL;
  49. } else
  50. return (ip_chaff_close(data));
  51. return (data);
  52. }
  53. int
  54. ip_chaff_apply(void *d, struct pktq *pktq)
  55. {
  56. struct ip_chaff_data *data = (struct ip_chaff_data *)d;
  57. struct pkt *pkt, *new, *next;
  58. struct ip_opt opt;
  59. int i;
  60. for (pkt = TAILQ_FIRST(pktq); pkt != TAILQ_END(pktq); pkt = next) {
  61. next = TAILQ_NEXT(pkt, pkt_next);
  62. uint16_t eth_type = htons(pkt->pkt_eth->eth_type);
  63. if (pkt->pkt_ip_data == NULL)
  64. continue;
  65. new = pkt_dup(pkt);
  66. rand_strset(data->rnd, new->pkt_ip_data, new->pkt_end - new->pkt_ip_data + 1);
  67. switch (data->type) {
  68. case CHAFF_TYPE_DUP:
  69. new->pkt_ts.tv_usec = 1;
  70. if (eth_type == ETH_TYPE_IP) {
  71. ip_checksum(new->pkt_ip, new->pkt_ip_data - new->pkt_eth_data);
  72. }
  73. break;
  74. case CHAFF_TYPE_OPT:
  75. if (eth_type == ETH_TYPE_IP) {
  76. opt.opt_type = 0x42;
  77. opt.opt_len = IP_OPT_LEN;
  78. i = ip_add_option(new->pkt_ip, new->pkt_buf_size - ETH_HDR_LEN, IP_PROTO_IP, &opt, opt.opt_len);
  79. /* XXX - whack opt with random crap */
  80. *(uint32_t *)new->pkt_ip_data = rand_uint32(data->rnd);
  81. new->pkt_ip_data += i;
  82. new->pkt_end += i;
  83. ip_checksum(new->pkt_ip, new->pkt_ip_data - new->pkt_eth_data);
  84. } else if (eth_type == ETH_TYPE_IPV6) {
  85. continue;
  86. }
  87. /* fall through */
  88. case CHAFF_TYPE_TTL:
  89. if (eth_type == ETH_TYPE_IP) {
  90. new->pkt_ip->ip_ttl = data->ttl;
  91. ip_checksum(new->pkt_ip, new->pkt_ip_data - new->pkt_eth_data);
  92. } else if (eth_type == ETH_TYPE_IPV6) {
  93. pkt->pkt_ip6->ip6_hlim = data->ttl;
  94. }
  95. break;
  96. }
  97. /* Minimal random reordering - for ipv4 and ipv6 */
  98. if ((new->pkt_ip_data[0] & 1) == 0)
  99. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  100. else
  101. TAILQ_INSERT_AFTER(pktq, pkt, new, pkt_next);
  102. }
  103. return (0);
  104. }
  105. struct mod mod_ip_chaff = {
  106. "ip_chaff", /* name */
  107. "ip_chaff dup|opt|<ttl>", /* usage */
  108. ip_chaff_open, /* open */
  109. ip_chaff_apply, /* apply */
  110. ip_chaff_close /* close */
  111. };