source: tools/traceanon/traceanon.c @ 49f147b

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 49f147b was 49f147b, checked in by Perry Lorier <perry@…>, 16 years ago

Add traceanon to cvs (based heavily on the munge code)

  • Property mode set to 100644
File size: 6.5 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 <pcap.h>
11#include <time.h>
12#include "ipenc.h"
13
14
15void usage(char *argv0)
16{
17        fprintf(stderr,"Usage:\n"
18        "%s flags inputfile outputfile\n"
19        "-s --encrypt-source    Encrypt the source addresses\n"
20        "-d --encrypt-dest      Encrypt the destination addresses\n"
21        "-c --cryptopan=key     Encrypt the addresses with the cryptopan\n"
22        "                       prefix preserving\n"
23        "-p --prefix=C.I.D.R/bits Substitute the prefix of the address\n"
24        ,argv0);
25        exit(1);
26}
27
28// Incrementally update a checksum
29void 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
38void update_in_cksum32(uint16_t *csum, uint32_t old, uint32_t new)
39{
40        update_in_cksum(csum,old>>16,new>>16);
41        update_in_cksum(csum,old&0xFFFF,new&0xFFFF);
42}
43
44/* Ok this is remarkably complicated
45 *
46 * We want to change one, or the other IP address, while preserving the
47 * checksum.  TCP and UDP both include the faux header in their checksum
48 * calculations, so you have to update them too.  ICMP is even worse --
49 * it can include the original IP packet that caused the error!  So anonymise
50 * that too, but remember that it's travelling in the opposite direction so
51 * we need to encrypt the destination and source instead of the source and
52 * destination!
53 */
54void 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_cksum(&tcp->check,old_ip,new_ip);
71                if (udp) update_in_cksum(&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_cksum(&tcp->check,old_ip,new_ip);
82                if (udp) update_in_cksum(&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 internally */
88                if (icmp->type == 3 || icmp->type == 5 || icmp->type == 11) {
89                        encrypt_ips(
90                                        (struct libtrace_ip*)icmp+
91                                                sizeof(struct libtrace_icmp),
92                                        enc_dest,
93                                        enc_source);
94                }
95        }
96}
97
98double parse_date(const char *date)
99{
100        struct tm *parsed_time;
101
102        parsed_time=getdate(date);
103
104        if (parsed_time) {
105                return (double)mktime(parsed_time);
106        }
107
108        switch(getdate_err) {
109                case 1:
110                        fprintf(stderr,"Cannot parse date: The DATEMSK environmental variable is null or undefined\n");
111                        break;
112                case 2:
113                        fprintf(stderr,"The date template file '%s' cannot be opened for reading\n",getenv("DATEMSK"));
114                        break;
115                case 3:
116                        fprintf(stderr,"Failed to get file status information for '%s'\n",getenv("DATEMSK"));
117                        break;
118                case 4:
119                        fprintf(stderr,"%s: Not a regular file\n",getenv("DATEMSK"));
120                        break;
121                case 5:
122                        fprintf(stderr,"An error occured reading '%s'\n",getenv("DATEMSK"));
123                        break;
124                case 6:
125                        fprintf(stderr,"Out of memory reading '%s'\n",getenv("DATEMSK"));
126                        break;
127                case 7:
128                        fprintf(stderr,"Could not parse '%s'\n",date);
129                        break;
130                case 8:
131                        fprintf(stderr,"Invalid specification in '%s'\n",getenv("DATEMSK"));
132                        break;
133                default:
134                        fprintf(stderr,"Unable to parse date '%s': Unknown error\n",date);
135        }
136        exit(1);
137}
138
139int main(int argc, char *argv[]) 
140{
141        enum enc_type_t enc_type = ENC_NONE;
142        char *key = NULL;
143        struct libtrace_filter_t *filter = NULL;
144        struct libtrace_t *trace = 0;
145        struct libtrace_packet_t packet;
146        struct libtrace_out_t *writer = 0;
147        bool enc_source = false;
148        bool enc_dest   = false;
149        double start_time = 0;
150        double end_time = 1e100;
151        char *output = 0;
152
153        if (argc<2)
154                usage(argv[0]);
155
156        while (1) {
157                int option_index;
158                struct option long_options[] = {
159                        { "encrypt-source",     0, 0, 's' },
160                        { "encrypt-dest",       0, 0, 'd' },
161                        { "cryptopan",          1, 0, 'c' },
162                        { "prefix",             1, 0, 'p' },
163                        { "filter",             1, 0, 'f' },
164                        { "start-time",         1, 0, 'b' },
165                        { "end-time",           1, 0, 'e' },
166                        { NULL,                 0, 0, 0 },
167                };
168
169                int c=getopt_long(argc, argv, "sb:c:de:p:f:",
170                                long_options, &option_index);
171
172                if (c==-1)
173                        break;
174
175                switch (c) {
176                        case 's': enc_source=true; break;
177                        case 'd': enc_dest  =true; break;
178                        case 'c':
179                                  if (key!=NULL) {
180                                          fprintf(stderr,"You can only have one encryption type and one key\n");
181                                          usage(argv[0]);
182                                  }
183                                  key=strdup(optarg);
184                                  enc_type = ENC_CRYPTOPAN;
185                                  break;
186                        case 'p':
187                                  if (key!=NULL) {
188                                          fprintf(stderr,"You can only have one encryption type and one key\n");
189                                          usage(argv[0]);
190                                  }
191                                  key=strdup(optarg);
192                                  enc_type = ENC_PREFIX_SUBSTITUTION;
193                                  break;
194                        case 'f':
195                                  if (filter!=NULL) {
196                                          fprintf(stderr,"You can only have one filter (use and!)\n");
197                                          usage(argv[0]);
198                                  }
199                                  filter=trace_bpf_setfilter(optarg);
200                                  break;
201                        case 'b': /* "begin" time */
202                                  start_time = parse_date(optarg);
203                                  break;
204                        case 'e': /* "end" time */
205                                  start_time = parse_date(optarg);
206                                  break;
207                        default:
208                                fprintf(stderr,"unknown option: %c\n",c);
209                                usage(argv[0]);
210
211                }
212
213        }
214
215        enc_init(enc_type,key);
216
217        // open input uri
218        trace = trace_create(argv[optind]);
219        if (!trace) {
220                fprintf(stderr,"Cannot open %s\n",argv[optind]);
221                trace_perror(argv[optind]);
222                return 1;
223        }
224       
225        if (optind == argc) {
226                // no output specified, output in same format to stdout
227                asprintf(&output,"%s:-","erf");
228                writer = trace_output_create(output);
229        } else {
230                writer = trace_output_create(argv[optind +1]);
231        }
232        if (!writer) {
233                trace_perror("trace_output_create");
234                return 1;
235        }
236       
237       
238        for(;;) {
239                struct libtrace_ip *ipptr;
240                int psize;
241                double ts;
242                if ((psize = trace_read_packet(trace, &packet)) <= 0) {
243                        break;
244                }
245
246                /* Skip packets that don't match the filter */
247                if (filter && !trace_bpf_filter(filter,&packet)) {
248                        continue;
249                }
250
251                ts = trace_get_seconds(&packet);
252
253                /* skip packets before/after the time */
254                if (ts < start_time || ts > end_time) {
255                        continue;
256                }
257
258                ipptr = trace_get_ip(&packet);
259
260                if (ipptr && (enc_source || enc_dest))
261                        encrypt_ips(ipptr,enc_source,enc_dest);
262
263                /* TODO: Encrypt IP's in ARP packets */
264
265                trace_write_packet(writer,&packet);
266        }
267        return 0;
268}
Note: See TracBrowser for help on using the repository browser.