source: tools/traceanon/traceanon.c @ 6374f4e

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 6374f4e was 71ff20e, checked in by Shane Alcock <salcock@…>, 12 years ago
  • traceanon now replaces checksums with zeroes - TODO: maybe re-calculate checksums to what they would be with the new IP addresses
  • Property mode set to 100644
File size: 6.2 KB
Line 
1#define _GNU_SOURCE
2#include "libtrace.h"
3#include <stdio.h>
4#include <unistd.h>
5#include <stdlib.h>
6#include <getopt.h>
7#include <stdbool.h>
8#include <stddef.h>
9#include <string.h>
10#include <time.h>
11#include "ipenc.h"
12
13
14static void usage(char *argv0)
15{
16        fprintf(stderr,"Usage:\n"
17        "%s flags inputfile outputfile\n"
18        "-s --encrypt-source    Encrypt the source addresses\n"
19        "-d --encrypt-dest      Encrypt the destination addresses\n"
20        "-c --cryptopan=key     Encrypt the addresses with the cryptopan\n"
21        "                       prefix preserving\n"
22        "-p --prefix=C.I.D.R/bits Substitute the prefix of the address\n"
23        "-H --libtrace-help     Print libtrace runtime documentation\n"
24        ,argv0);
25        exit(1);
26}
27
28/* Incrementally update a checksum */
29static void update_in_cksum(uint16_t *csum, uint16_t old, uint16_t new)
30{
31        uint32_t sum = (~htons(*csum) & 0xFFFF) 
32                     + (~htons(old) & 0xFFFF) 
33                     + htons(new);
34        sum = (sum & 0xFFFF) + (sum >> 16);
35        *csum = htons(~(sum + (sum >> 16)));
36}
37
38static void update_in_cksum32(uint16_t *csum, uint32_t old, uint32_t new)
39{
40        update_in_cksum(csum,(uint16_t)(old>>16),(uint16_t)(new>>16));
41        update_in_cksum(csum,(uint16_t)(old&0xFFFF),(uint16_t)(new&0xFFFF));
42}
43
44/* Ok this is remarkably complicated
45 *
46 * We want to change one, or the other IP address, while preserving
47 * the checksum.  TCP and UDP both include the faux header in their
48 * checksum calculations, so you have to update them too.  ICMP is
49 * even worse -- it can include the original IP packet that caused the
50 * error!  So anonymise that too, but remember that it's travelling in
51 * the opposite direction so we need to encrypt the destination and
52 * source instead of the source and destination!
53 */
54static void encrypt_ips(struct libtrace_ip *ip,bool enc_source,bool enc_dest)
55{
56        struct libtrace_tcp *tcp;
57        struct libtrace_udp *udp;
58        struct libtrace_icmp *icmp;
59
60        tcp=trace_get_tcp_from_ip(ip,NULL);
61        udp=trace_get_udp_from_ip(ip,NULL);
62        icmp=trace_get_icmp_from_ip(ip,NULL);
63
64        if (enc_source) {
65                uint32_t old_ip=ip->ip_src.s_addr;
66                uint32_t new_ip=htonl(enc_ip(
67                                        htonl(ip->ip_src.s_addr)
68                                        ));
69                update_in_cksum32(&ip->ip_sum,old_ip,new_ip);
70                if (tcp) update_in_cksum32(&tcp->check,old_ip,new_ip);
71                if (udp) update_in_cksum32(&udp->check,old_ip,new_ip);
72                ip->ip_src.s_addr = new_ip;
73        }
74
75        if (enc_dest) {
76                uint32_t old_ip=ip->ip_dst.s_addr;
77                uint32_t new_ip=htonl(enc_ip(
78                                        htonl(ip->ip_dst.s_addr)
79                                        ));
80                update_in_cksum32(&ip->ip_sum,old_ip,new_ip);
81                if (tcp) update_in_cksum32(&tcp->check,old_ip,new_ip);
82                if (udp) update_in_cksum32(&udp->check,old_ip,new_ip);
83                ip->ip_dst.s_addr = new_ip;
84        }
85
86        if (icmp) {
87                /* These are error codes that return the IP packet
88                 * internally
89                 */
90                if (icmp->type == 3 
91                                || icmp->type == 5 
92                                || icmp->type == 11) {
93                        encrypt_ips(
94                                (struct libtrace_ip*)icmp+
95                                        sizeof(struct libtrace_icmp),
96                                enc_dest,
97                                enc_source);
98                }
99        }
100}
101
102int main(int argc, char *argv[]) 
103{
104        enum enc_type_t enc_type = ENC_NONE;
105        char *key = NULL;
106        struct libtrace_t *trace = 0;
107        struct libtrace_packet_t *packet = trace_create_packet();
108        struct libtrace_out_t *writer = 0;
109        bool enc_source = false;
110        bool enc_dest   = false;
111        char *output = 0;
112        int level = 1;
113
114        if (argc<2)
115                usage(argv[0]);
116
117        while (1) {
118                int option_index;
119                struct option long_options[] = {
120                        { "encrypt-source",     0, 0, 's' },
121                        { "encrypt-dest",       0, 0, 'd' },
122                        { "cryptopan",          1, 0, 'c' },
123                        { "prefix",             1, 0, 'p' },
124                        { "compression-level",  1, 0, 'z' },
125                        { "libtrace-help",      0, 0, 'H' },
126                        { NULL,                 0, 0, 0   },
127                };
128
129                int c=getopt_long(argc, argv, "z:sc:dp:H",
130                                long_options, &option_index);
131
132                if (c==-1)
133                        break;
134
135                switch (c) {
136                        case 'z': level = atoi(optarg); break;
137                        case 's': enc_source=true; break;
138                        case 'd': enc_dest  =true; break;
139                        case 'c':
140                                  if (key!=NULL) {
141                                          fprintf(stderr,"You can only have one encryption type and one key\n");
142                                          usage(argv[0]);
143                                  }
144                                  key=strdup(optarg);
145                                  enc_type = ENC_CRYPTOPAN;
146                                  break;
147                        case 'p':
148                                  if (key!=NULL) {
149                                          fprintf(stderr,"You can only have one encryption type and one key\n");
150                                          usage(argv[0]);
151                                  }
152                                  key=strdup(optarg);
153                                  enc_type = ENC_PREFIX_SUBSTITUTION;
154                                  break;
155                        case 'H':
156                                  trace_help(); 
157                                  exit(1); 
158                                  break;
159                        default:
160                                fprintf(stderr,"unknown option: %c\n",c);
161                                usage(argv[0]);
162
163                }
164
165        }
166
167        enc_init(enc_type,key);
168
169        /* open input uri */
170        trace = trace_create(argv[optind]);
171        if (trace_is_err(trace)) {
172                trace_perror(trace,argv[optind]);
173                trace_destroy(trace);
174                return 1;
175        }
176
177        if (optind +1>= argc) {
178                /* no output specified, output in same format to
179                 * stdout
180                 */
181                output = strdup("erf:-");
182                writer = trace_create_output(output);
183        } else {
184                writer = trace_create_output(argv[optind +1]);
185        }
186        if (trace_is_err_output(writer)) {
187                trace_perror_output(writer,"trace_create_output");
188                trace_destroy_output(writer);
189                trace_destroy(trace);
190                return 1;
191        }
192       
193        if (trace_config_output(writer, TRACE_OPTION_OUTPUT_COMPRESS, 
194                                &level) == -1) {
195                trace_perror_output(writer, "Configuring compression level");
196                trace_destroy_output(writer);
197                trace_destroy(trace);
198                return 1;
199        }
200
201        if (trace_start(trace)==-1) {
202                trace_perror(trace,"trace_start");
203                return 1;
204        }
205        if (trace_start_output(writer)==-1) {
206                trace_perror_output(writer,"trace_start_output");
207        }
208        for(;;) {
209                struct libtrace_ip *ipptr;
210                libtrace_udp_t *udp = NULL;
211                libtrace_tcp_t *tcp = NULL;
212
213                int psize;
214                psize = trace_read_packet(trace, packet);
215                if (psize == 0) {
216                        break;
217                }
218                if (psize < 0) {
219                        trace_perror(trace,"read_packet");
220                        break;
221                }
222
223                ipptr = trace_get_ip(packet);
224
225                if (ipptr && (enc_source || enc_dest)) {
226                        encrypt_ips(ipptr,enc_source,enc_dest);
227                        ipptr->ip_sum = 0;
228                }
229
230                /* Replace checksums so that IP encryption cannot be
231                 * reversed */
232
233                /* XXX replace with nice use of trace_get_transport() */
234
235                udp = trace_get_udp(packet);
236                if (udp && (enc_source || enc_dest)) {
237                        udp->check = 0;
238                } 
239
240                tcp = trace_get_tcp(packet);
241                if (tcp && (enc_source || enc_dest)) {
242                        tcp->check = 0;
243                }
244
245                /* TODO: Encrypt IP's in ARP packets */
246
247                if (trace_write_packet(writer,packet)==-1) {
248                        trace_perror_output(writer,"writer");
249                        break;
250                }
251        }
252        trace_destroy_packet(packet);
253        trace_destroy(trace);
254        trace_destroy_output(writer);
255        return 0;
256}
Note: See TracBrowser for help on using the repository browser.