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