source: tools/traceanon/traceanon.c @ a8f2692

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

Tidy up a bazillion tiny warnings

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