mod_ip_chaff.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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 <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "mod.h"
  13. #include "pkt.h"
  14. #include "randutil.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 = atoi(argv[1])) >= 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,
  67. new->pkt_end - new->pkt_ip_data + 1);
  68. switch (data->type) {
  69. case CHAFF_TYPE_DUP:
  70. new->pkt_ts.tv_usec = 1;
  71. if (eth_type == ETH_TYPE_IP) {
  72. ip_checksum(new->pkt_ip, new->pkt_ip_data -
  73. new->pkt_eth_data);
  74. }
  75. break;
  76. case CHAFF_TYPE_OPT:
  77. if (eth_type == ETH_TYPE_IP) {
  78. opt.opt_type = 0x42;
  79. opt.opt_len = IP_OPT_LEN;
  80. i = ip_add_option(new->pkt_ip,
  81. new->pkt_buf_size - ETH_HDR_LEN, IP_PROTO_IP,
  82. &opt, opt.opt_len);
  83. /* XXX - whack opt with random crap */
  84. *(uint32_t *)new->pkt_ip_data = rand_uint32(data->rnd);
  85. new->pkt_ip_data += i;
  86. new->pkt_end += i;
  87. ip_checksum(new->pkt_ip, new->pkt_ip_data -
  88. new->pkt_eth_data);
  89. } else if (eth_type == ETH_TYPE_IPV6) {
  90. continue;
  91. }
  92. /* no break */
  93. case CHAFF_TYPE_TTL:
  94. if (eth_type == ETH_TYPE_IP) {
  95. new->pkt_ip->ip_ttl = data->ttl;
  96. ip_checksum(new->pkt_ip, new->pkt_ip_data -
  97. new->pkt_eth_data);
  98. } else if (eth_type == ETH_TYPE_IPV6) {
  99. pkt->pkt_ip6->ip6_hlim = data->ttl;
  100. }
  101. break;
  102. }
  103. /* Minimal random reordering - for ipv4 and ipv6 */
  104. if ((new->pkt_ip_data[0] & 1) == 0)
  105. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  106. else
  107. TAILQ_INSERT_AFTER(pktq, pkt, new, pkt_next);
  108. }
  109. return (0);
  110. }
  111. struct mod mod_ip_chaff = {
  112. "ip_chaff", /* name */
  113. "ip_chaff dup|opt|<ttl>", /* usage */
  114. ip_chaff_open, /* open */
  115. ip_chaff_apply, /* apply */
  116. ip_chaff_close /* close */
  117. };