source: examples/munge/munge.c @ 3840760

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 3840760 was 3840760, checked in by Daniel Lawson <dlawson@…>, 16 years ago

updated the examples/ and tools/ directories to correctly use trace_packet_create() now.

fixed a typo in format_wag (shouldn't use pcap_get_framing_length for wag!)

  • Property mode set to 100644
File size: 7.5 KB
Line 
1#define _GNU_SOURCE
2#include "libtrace.h"
3#include "lib/lib.h"
4#include <stdio.h>
5#include <unistd.h>
6#include <stdlib.h>
7#include <getopt.h>
8#include <stdbool.h>
9#include <stddef.h>
10#include <string.h>
11#include <pcap.h>
12#include <time.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        "-f --filter=expr       Apply a tcpdump filter\n"
25        "-b --start-time=date   Show only packets after this time\n"
26        "-f --end-time=date     Show only packets before this time\n"
27        ,argv0);
28        exit(0);
29}
30
31// Incrementally update a checksum
32void update_in_cksum(uint16_t *csum, uint16_t old, uint16_t new)
33{
34        uint32_t sum = (~htons(*csum) & 0xFFFF) 
35                     + (~htons(old) & 0xFFFF) 
36                     + htons(new);
37        sum = (sum & 0xFFFF) + (sum >> 16);
38        *csum = htons(~(sum + (sum >> 16)));
39}
40
41void update_in_cksum32(uint16_t *csum, uint32_t old, uint32_t new)
42{
43        update_in_cksum(csum,old>>16,new>>16);
44        update_in_cksum(csum,old&0xFFFF,new&0xFFFF);
45}
46
47struct libtrace_tcp *get_tcp_from_ip(struct libtrace_ip *ip)
48{
49#define SW_IP_OFFMASK 0xff1f
50        struct libtrace_tcp *tcpptr = 0;
51
52        if ((ip->ip_p == 6) && ((ip->ip_off & SW_IP_OFFMASK) == 0))  {
53                tcpptr = (struct libtrace_tcp *)((ptrdiff_t)ip+ (ip->ip_hl * 4));
54        }
55        return tcpptr;
56}
57
58struct libtrace_udp *get_udp_from_ip(struct libtrace_ip *ip)
59{
60        struct libtrace_udp *udpptr = 0;
61
62        if ((ip->ip_p == 17) && ((ip->ip_off & SW_IP_OFFMASK) == 0))  {
63                udpptr = (struct libtrace_udp *)((ptrdiff_t)ip+(ip->ip_hl*4));
64        }
65        return udpptr;
66}
67
68struct libtrace_icmp *get_icmp_from_ip(struct libtrace_ip *ip)
69{
70        struct libtrace_icmp *icmpptr = 0;
71
72        if ((ip->ip_p == 17) && ((ip->ip_off & SW_IP_OFFMASK) == 0))  {
73                icmpptr = (struct libtrace_icmp *)((ptrdiff_t)ip+(ip->ip_hl*4));
74        }
75        return icmpptr;
76}
77
78/* Ok this is remarkably complicated
79 *
80 * We want to change one, or the other IP address, while preserving the
81 * checksum.  TCP and UDP both include the faux header in their checksum
82 * calculations, so you have to update them too.  ICMP is even worse --
83 * it can include the original IP packet that caused the error!  So anonymise
84 * that too, but remember that it's travelling in the opposite direction so
85 * we need to encrypt the destination and source instead of the source and
86 * destination!
87 */
88void encrypt_ips(struct libtrace_ip *ip,bool enc_source,bool enc_dest)
89{
90        struct libtrace_tcp *tcp;
91        struct libtrace_udp *udp;
92        struct libtrace_icmp *icmp;
93
94        tcp=get_tcp_from_ip(ip);
95        udp=get_udp_from_ip(ip);
96        icmp=get_icmp_from_ip(ip);
97
98        if (enc_source) {
99                uint32_t old_ip=ip->ip_src.s_addr;
100                uint32_t new_ip=htonl(trace_enc_ip(
101                                        htonl(ip->ip_src.s_addr)
102                                        ));
103                update_in_cksum32(&ip->ip_sum,old_ip,new_ip);
104                if (tcp) update_in_cksum(&tcp->check,old_ip,new_ip);
105                if (udp) update_in_cksum(&udp->check,old_ip,new_ip);
106                ip->ip_src.s_addr = new_ip;
107        }
108
109        if (enc_dest) {
110                uint32_t old_ip=ip->ip_dst.s_addr;
111                uint32_t new_ip=htonl(trace_enc_ip(
112                                        htonl(ip->ip_dst.s_addr)
113                                        ));
114                update_in_cksum32(&ip->ip_sum,old_ip,new_ip);
115                if (tcp) update_in_cksum(&tcp->check,old_ip,new_ip);
116                if (udp) update_in_cksum(&udp->check,old_ip,new_ip);
117                ip->ip_dst.s_addr = new_ip;
118        }
119
120        if (icmp) {
121                /* These are error codes that return the IP packet internally */
122                if (icmp->type == 3 || icmp->type == 5 || icmp->type == 11) {
123                        encrypt_ips(
124                                        (struct libtrace_ip*)icmp+
125                                                sizeof(struct libtrace_icmp),
126                                        enc_dest,
127                                        enc_source);
128                }
129        }
130}
131
132double parse_date(const char *date)
133{
134        struct tm *parsed_time;
135
136        parsed_time=getdate(date);
137
138        if (parsed_time) {
139                return (double)mktime(parsed_time);
140        }
141
142        switch(getdate_err) {
143                case 1:
144                        fprintf(stderr,"Cannot parse date: The DATEMSK environmental variable is null or undefined\n");
145                        break;
146                case 2:
147                        fprintf(stderr,"The date template file '%s' cannot be opened for reading\n",getenv("DATEMSK"));
148                        break;
149                case 3:
150                        fprintf(stderr,"Failed to get file status information for '%s'\n",getenv("DATEMSK"));
151                        break;
152                case 4:
153                        fprintf(stderr,"%s: Not a regular file\n",getenv("DATEMSK"));
154                        break;
155                case 5:
156                        fprintf(stderr,"An error occured reading '%s'\n",getenv("DATEMSK"));
157                        break;
158                case 6:
159                        fprintf(stderr,"Out of memory reading '%s'\n",getenv("DATEMSK"));
160                        break;
161                case 7:
162                        fprintf(stderr,"Could not parse '%s'\n",date);
163                        break;
164                case 8:
165                        fprintf(stderr,"Invalid specification in '%s'\n",getenv("DATEMSK"));
166                        break;
167                default:
168                        fprintf(stderr,"Unable to parse date '%s': Unknown error\n",date);
169        }
170        exit(1);
171}
172
173int main(int argc, char *argv[]) 
174{
175        enum enc_type_t enc_type = ENC_NONE;
176        char *key = NULL;
177        struct libtrace_filter_t *filter = NULL;
178        struct libtrace_t *trace = 0;
179        struct libtrace_packet_t *packet = trace_packet_create();
180        struct libtrace_out_t *writer = 0;
181        bool enc_source = false;
182        bool enc_dest   = false;
183        double start_time = 0;
184        double end_time = 1e100;
185        char *output = 0;
186
187        if (argc<2)
188                usage(argv[0]);
189
190        while (1) {
191                int option_index;
192                struct option long_options[] = {
193                        { "encrypt-source",     0, 0, 's' },
194                        { "encrypt-dest",       0, 0, 'd' },
195                        { "cryptopan",          1, 0, 'c' },
196                        { "prefix",             1, 0, 'p' },
197                        { "filter",             1, 0, 'f' },
198                        { "start-time",         1, 0, 'b' },
199                        { "end-time",           1, 0, 'e' },
200                        { NULL,                 0, 0, 0 },
201                };
202
203                int c=getopt_long(argc, argv, "sb:c:de:p:f:",
204                                long_options, &option_index);
205
206                if (c==-1)
207                        break;
208
209                switch (c) {
210                        case 's': enc_source=true; break;
211                        case 'd': enc_dest  =true; break;
212                        case 'c':
213                                  if (key!=NULL) {
214                                          fprintf(stderr,"You can only have one encryption type and one key\n");
215                                          usage(argv[0]);
216                                  }
217                                  key=strdup(optarg);
218                                  enc_type = ENC_CRYPTOPAN;
219                                  break;
220                        case 'p':
221                                  if (key!=NULL) {
222                                          fprintf(stderr,"You can only have one encryption type and one key\n");
223                                          usage(argv[0]);
224                                  }
225                                  key=strdup(optarg);
226                                  enc_type = ENC_PREFIX_SUBSTITUTION;
227                                  break;
228                        case 'f':
229                                  if (filter!=NULL) {
230                                          fprintf(stderr,"You can only have one filter (use and!)\n");
231                                          usage(argv[0]);
232                                  }
233                                  filter=trace_bpf_setfilter(optarg);
234                                  break;
235                        case 'b': /* "begin" time */
236                                  start_time = parse_date(optarg);
237                                  break;
238                        case 'e': /* "end" time */
239                                  start_time = parse_date(optarg);
240                                  break;
241                        default:
242                                fprintf(stderr,"unknown option: %c\n",c);
243                                usage(argv[0]);
244
245                }
246
247        }
248
249        trace_enc_init(enc_type,key);
250
251        // open input uri
252        trace = trace_create(argv[optind]);
253        if (!trace) {
254                fprintf(stderr,"Cannot open %s\n",argv[optind]);
255                trace_perror(argv[optind]);
256                return 1;
257        }
258       
259        if (optind == argc) {
260                // no output specified, output in same format to stdout
261                asprintf(&output,"%s:-","erf");
262                writer = trace_output_create(output);
263        } else {
264                writer = trace_output_create(argv[optind +1]);
265        }
266        if (!writer) {
267                trace_perror("trace_output_create");
268                return 1;
269        }
270       
271       
272        for(;;) {
273                struct libtrace_ip *ipptr;
274                int psize;
275                double ts;
276                if ((psize = trace_read_packet(trace, &packet)) <= 0) {
277                        break;
278                }
279
280                /* Skip packets that don't match the filter */
281                if (filter && !trace_bpf_filter(filter,&packet)) {
282                        continue;
283                }
284
285                ts = trace_get_seconds(&packet);
286
287                /* skip packets before/after the time */
288                if (ts < start_time || ts > end_time) {
289                        continue;
290                }
291
292                ipptr = trace_get_ip(&packet);
293
294                if (ipptr && (enc_source || enc_dest))
295                        encrypt_ips(ipptr,enc_source,enc_dest);
296
297                /* TODO: Encrypt IP's in ARP packets */
298
299                trace_write_packet(writer,&packet);
300        }
301        return 0;
302}
Note: See TracBrowser for help on using the repository browser.