source: tools/traceanon/traceanon.c @ fc0f131

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

Add better error handling to tools

  • Property mode set to 100644
File size: 5.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
14void 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        ,argv0);
24        trace_help();
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
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 */
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
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
113        if (argc<2)
114                usage(argv[0]);
115
116        while (1) {
117                int option_index;
118                struct option long_options[] = {
119                        { "encrypt-source",     0, 0, 's' },
120                        { "encrypt-dest",       0, 0, 'd' },
121                        { "cryptopan",          1, 0, 'c' },
122                        { "prefix",             1, 0, 'p' },
123                        { NULL,                 0, 0, 0 },
124                };
125
126                int c=getopt_long(argc, argv, "sc:dp:",
127                                long_options, &option_index);
128
129                if (c==-1)
130                        break;
131
132                switch (c) {
133                        case 's': enc_source=true; break;
134                        case 'd': enc_dest  =true; break;
135                        case 'c':
136                                  if (key!=NULL) {
137                                          fprintf(stderr,"You can only have one encryption type and one key\n");
138                                          usage(argv[0]);
139                                  }
140                                  key=strdup(optarg);
141                                  enc_type = ENC_CRYPTOPAN;
142                                  break;
143                        case 'p':
144                                  if (key!=NULL) {
145                                          fprintf(stderr,"You can only have one encryption type and one key\n");
146                                          usage(argv[0]);
147                                  }
148                                  key=strdup(optarg);
149                                  enc_type = ENC_PREFIX_SUBSTITUTION;
150                                  break;
151                        default:
152                                fprintf(stderr,"unknown option: %c\n",c);
153                                usage(argv[0]);
154
155                }
156
157        }
158
159        enc_init(enc_type,key);
160
161        /* open input uri */
162        trace = trace_create(argv[optind]);
163        if (trace_is_err(trace)) {
164                trace_perror(trace,argv[optind]);
165                trace_destroy(trace);
166                return 1;
167        }
168
169        if (optind +1>= argc) {
170                /* no output specified, output in same format to
171                 * stdout
172                 */
173                asprintf(&output,"%s:-","erf");
174                writer = trace_create_output(output);
175        } else {
176                writer = trace_create_output(argv[optind +1]);
177        }
178        if (trace_is_err_output(writer)) {
179                trace_perror_output(writer,"trace_create_output");
180                trace_destroy_output(writer);
181                trace_destroy(trace);
182                return 1;
183        }
184       
185        if (trace_start(trace)==-1) {
186                trace_perror(trace,"trace_start");
187                return 1;
188        }
189        if (trace_start_output(writer)==-1) {
190                trace_perror_output(writer,"trace_start_output");
191        }
192        for(;;) {
193                struct libtrace_ip *ipptr;
194                int psize;
195                psize = trace_read_packet(trace, packet);
196                if (psize == 0) {
197                        break;
198                }
199                if (psize < 0) {
200                        trace_perror(trace,"read_packet");
201                        break;
202                }
203
204                ipptr = trace_get_ip(packet);
205
206                if (ipptr && (enc_source || enc_dest))
207                        encrypt_ips(ipptr,enc_source,enc_dest);
208
209                /* TODO: Encrypt IP's in ARP packets */
210
211                if (trace_write_packet(writer,packet)==-1) {
212                        trace_perror_output(writer,"writer");
213                        break;
214                }
215        }
216        trace_destroy_packet(packet);
217        trace_destroy(trace);
218        trace_destroy_output(writer);
219        return 0;
220}
Note: See TracBrowser for help on using the repository browser.