source: examples/tutorial/ipdist.c @ 7d86ee2

develop
Last change on this file since 7d86ee2 was 7d86ee2, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Added some error checking

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/* Program reads a trace file and counts the first octet of the source and destination
2 * addresses
3 */
4#include "libtrace.h"
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/socket.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11
12uint64_t srcaddrcount[256];
13uint64_t dstaddrcount[256];
14
15struct exclude_networks {
16        uint32_t address;
17        uint32_t mask;
18        uint32_t network;
19};
20struct exclude_networks *exclude;
21int exclude_networks_count = 0;
22
23static void plot_results() {
24
25        /* Push all the data into a tmp file for gnuplot */
26        FILE *tmp = fopen("ipdist.tmp", "w");
27        int i;
28        for(i=0;i<255;i++) {
29                fprintf(tmp, "%d %d %d\n", i, srcaddrcount[i], dstaddrcount[i]);
30        }
31        fclose(tmp);
32
33        /* Commands that need to be sent to gnuplot */
34        char *commands[] = {"set term png size 1280,960",
35                            "set title 'IP Distrubtion'",
36                            "set xrange [0:255]",
37                            "set xlabel 'Prefix'",
38                            "set ylabel 'Hits'",
39                            "set xtics 0,10,255",
40                            "set output 'ipdist.png'",
41                            "plot 'ipdist.tmp' using 1:2 title 'Source Address' with boxes, 'ipdist.tmp' using 1:3 title 'Destination Address' with boxes",
42                            "replot"};
43        /* Open pipe to gnuplot */
44        FILE *gnuplot = popen("gnuplot -persistent", "w");
45        /* send all commands to gnuplot */
46        for(i=0;i<9;i++) {
47                fprintf(gnuplot, "%s \n", commands[i]);
48        }
49        pclose(gnuplot);
50}
51
52/* Checks if address is part of a excluded subnet. */
53static int network_excluded(uint32_t address) {
54
55        int i;
56        for(i=0;i<exclude_networks_count;i++) {
57                /* Convert address into a network address */
58                uint32_t net_addr = address & exclude[i].mask;
59
60                /* If this matches the network address from the excluded list we need to exclude this
61                   address. */
62                if(net_addr == exclude[i].network) {
63                        return 1;
64                }
65        }
66
67        /* If we got this far the address should not be excluded */
68        return 0;
69}
70
71static void process_ip(struct sockaddr *ip, int srcaddr) {
72
73        /* Checks if the ip is of type IPv4 */
74        if (ip->sa_family == AF_INET) {
75
76                /* IPv4 - cast the generic sockaddr to a sockaddr_in */
77                struct sockaddr_in *v4 = (struct sockaddr_in *)ip;
78                /* Get in_addr from sockaddr */
79                struct in_addr ip4 = (struct in_addr)v4->sin_addr;
80                /* Ensure the address is in network byte order */
81                uint32_t address = htonl(ip4.s_addr);
82
83                /* Check if the address is part of an excluded network. */
84                if(network_excluded(address) == 0) {
85
86                        /* Split the IPv4 address into each octet */
87                        uint8_t octet[4];
88                        octet[0] = (address & 0xff000000) >> 24;
89                        octet[1] = (address & 0x00ff0000) >> 16;
90                        octet[2] = (address & 0x0000ff00) >> 8;
91                        octet[3] = (address & 0x000000ff);
92
93                        /* check if the supplied address was a source or destination,
94                           increment the correct one */
95                        if(srcaddr) {
96                                srcaddrcount[octet[0]]++;
97                        } else {
98                                dstaddrcount[octet[0]]++;
99                        }
100                }
101        }
102}
103
104static void per_packet(libtrace_packet_t *packet) {
105        struct sockaddr_storage addr;
106        struct sockaddr *address;
107
108        /* Get the source IP address */
109        address = trace_get_source_address(packet, (struct sockaddr *)&addr);
110        /* If a source ip address was found */
111        if(address != NULL) {
112                process_ip(address, 1);
113        }
114
115        /* Get the destination IP address */
116        address = trace_get_destination_address(packet, (struct sockaddr *)&addr);
117        /* If a destination ip address was found */
118        if(address != NULL) {
119                process_ip(address, 0);
120        }
121}
122
123static void libtrace_cleanup(libtrace_t *trace, libtrace_packet_t *packet) {
124        /* Only destroy trace and packet if they are not NULL */
125        if(trace) {
126                trace_destroy(trace);
127        }
128        if(packet) {
129                trace_destroy_packet(packet);
130        }
131}
132
133int main(int argc, char *argv[]) {
134
135        libtrace_t *trace = NULL;
136        libtrace_packet_t *packet = NULL;
137
138        /* Ensure the input URI was supplied */
139        if(argc < 2) {
140                fprintf(stderr, "Usage: %s inputURI [excluded networks]\n", argv[0]);
141                fprintf(stderr, "       eg. ./ipdist input.erf 210.10.3.0/24 70.5.0.0/16\n");
142                return 1;
143        }
144
145        /* initialize address arrays */
146        int i;
147        for(i=0; i<256; i++) {
148                srcaddrcount[i] = 0;
149                dstaddrcount[i] = 0;
150        }
151
152        /* Setup excluded networks if any were supplied */
153        exclude_networks_count = argc-2;
154        exclude = malloc(sizeof(struct exclude_networks)*(argc-2));
155        if(exclude == NULL) {
156                fprintf(stderr, "Unable to allocate memory");
157                return 1;
158        }
159
160        char delim[] = "/";
161        // Convert supplied address and mask to a exclude_network structure
162        for(i=0;i<argc-2;i++) {
163                char *address = strtok(argv[i+2], delim);
164                char *mask = strtok(NULL, delim);
165
166                /* Check the subnet mask is valid */
167                if(atoi(mask) == 0 || atoi(mask) > 32 || atoi(mask) < 0) {
168                        fprintf(stderr, "Invalid subnet mask: %s\n", mask);
169                        return 1;
170                }
171                /* right shift so netmask is in network byte order */
172                exclude[i].mask = 0xffffffff << (32 - atoi(mask));
173
174                struct in_addr addr;
175                /* Convert address string into uint32_t and check its valid*/
176                if(inet_aton(address, &addr) == 0) {
177                        fprintf(stderr, "Invalid exclude address: %s\n", address);
178                        return 1;
179                }
180                /* Ensure its saved in network byte order */
181                exclude[i].address = htonl(addr.s_addr);
182
183                /* Calculate the network address */
184                exclude[i].network = exclude[i].address & exclude[i].mask;
185        }
186
187        /* Create the packet structure */
188        packet = trace_create_packet();
189        /* Ensure no error has occured creating the packet */
190        if(packet == NULL) {
191                perror("Creating libtrace packet");
192                libtrace_cleanup(trace, packet);
193                return 1;
194        }
195
196        /* Create the trace */
197        trace = trace_create(argv[1]);
198        /* Ensure no error has occured creating the trace */
199        if(trace_is_err(trace)) {
200                trace_perror(trace, "Opening trace file");
201                libtrace_cleanup(trace, packet);
202                return 1;
203        }
204
205        /* Start the trace, if it errors return */
206        if(trace_start(trace) == -1) {
207                trace_perror(trace, "Starting trace");
208                libtrace_cleanup(trace, packet);
209                return 1;
210        }
211
212        /* Proccess each packet in the trace */
213        while(trace_read_packet(trace,packet)>0) {
214                per_packet(packet);
215        }
216
217        /* If trace is error after proccessing packets it failed to process
218           the entire trace */
219        if(trace_is_err(trace)) {
220                trace_perror(trace, packet);
221                libtrace_cleanup(trace, packet);
222                return 1;
223        }
224
225        /* free memory used to hold excluded networks */
226        free(exclude);
227
228        /* Print results */
229        plot_results();
230
231        /* cleanup */
232        libtrace_cleanup(trace, packet);
233
234        return 0;
235}
Note: See TracBrowser for help on using the repository browser.