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