source: examples/tutorial/ipdist.c @ 774b237

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

ipdist added gnuplot of results, Added ability to exclude network prefix

  • Property mode set to 100644
File size: 5.5 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 xrange [0:255]",
36                            "set xtics 0,10,255",
37                            "set output 'ipdist.png'",
38                            "plot 'ipdist.tmp' using 1:2 title 'Source Address' with boxes, 'ipdist.tmp' using 1:3 title 'Destination Address' with boxes",
39                            "replot"};
40        /* Open pipe to gnuplot */
41        FILE *gnuplot = popen("gnuplot -persistent", "w");
42        /* send all commands to gnuplot */
43        for(i=0;i<6;i++) {
44                fprintf(gnuplot, "%s \n", commands[i]);
45        }
46        pclose(gnuplot);
47}
48
49/* Checks if address is part of a excluded subnet. */
50static int network_excluded(uint32_t address) {
51
52        int i;
53        for(i=0;i<exclude_networks_count;i++) {
54                /* Convert address into a network address */
55                uint32_t net_addr = address & exclude[i].mask;
56
57                /* If this matches the network address from the excluded list we need to exclude this
58                   address. */
59                if(net_addr == exclude[i].network) {
60                        return 1;
61                }
62        }
63
64        /* If we got this far the address should not be excluded */
65        return 0;
66}
67
68static void process_ip(struct sockaddr *ip, int srcaddr) {
69
70        /* Checks if the ip is of type IPv4 */
71        if (ip->sa_family == AF_INET) {
72
73                /* IPv4 - cast the generic sockaddr to a sockaddr_in */
74                struct sockaddr_in *v4 = (struct sockaddr_in *)ip;
75                /* Get in_addr from sockaddr */
76                struct in_addr ip4 = (struct in_addr)v4->sin_addr;
77                /* Ensure the address is in network byte order */
78                uint32_t address = htonl(ip4.s_addr);
79
80                /* Check if the address is part of an excluded network.
81                   This is performed before splitting the into octets so if performed over entire address. */
82                if(network_excluded(address) == 0) {
83
84                        /* Split the IPv4 address into each octet */
85                        uint8_t octet[4];
86                        octet[0] = (address & 0xff000000) >> 24;
87                        octet[1] = (address & 0x00ff0000) >> 16;
88                        octet[2] = (address & 0x0000ff00) >> 8;
89                        octet[3] = (address & 0x000000ff);
90
91                        /* check if the supplied address was a source or destination, increment
92                           the correct one */
93                        if(srcaddr) {
94                                srcaddrcount[octet[0]]++;
95                        } else {
96                                dstaddrcount[octet[0]]++;
97                        }
98                }
99
100        }
101}
102
103static void per_packet(libtrace_packet_t *packet) {
104        struct sockaddr_storage addr;
105        struct sockaddr *address;
106
107        /* Get the source IP address */
108        address = trace_get_source_address(packet, (struct sockaddr *)&addr);
109        /* If a source ip address was found */
110        if(address != NULL) {
111                process_ip(address, 1);
112        }
113
114        /* Get the destination IP address */
115        address = trace_get_destination_address(packet, (struct sockaddr *)&addr);
116        /* If a destination ip address was found */
117        if(address != NULL) {
118                process_ip(address, 0);
119        }
120
121}
122
123int main(int argc, char *argv[]) {
124
125        libtrace_t *trace = NULL;
126        libtrace_packet_t *packet = NULL;
127
128        /* Ensure the input URI was supplied */
129        if(argc < 2) {
130                fprintf(stderr, "Usage: %s inputURI\n", argv[0]);
131                return 1;
132        }
133
134        /* initialize address arrays */
135        int i;
136        for(i=0; i<256; i++) {
137                srcaddrcount[i] = 0;
138                dstaddrcount[i] = 0;
139        }
140
141        /* Setup excluded networks if any were supplied */
142        exclude_networks_count = argc-2;
143        exclude = malloc(sizeof(struct exclude_networks)*(argc-2));
144        if(exclude == NULL) {
145                fprintf(stderr, "Unable to allocate memory");
146                return 1;
147        }
148
149        char delim[] = "/";
150        // Convert supplied address and mask to a exclude_network structure
151        for(i=2;i<argc;i++) {
152                char *address = strtok(argv[i], delim);
153                char *mask = strtok(NULL, delim);
154
155                /* right shift so netmask is in network byte order */
156                exclude[i-2].mask = 0xffffffff << (32 - atoi(mask));
157
158                struct in_addr addr;
159                /* Convert address string into uint32_t */
160                inet_aton(address, &addr);
161                /* Ensure its saved in network byte order */
162                exclude[i-2].address = htonl(addr.s_addr);
163
164                /* Calculate the network address */
165                exclude[i-2].network = exclude[i-2].address & exclude[i-2].mask;
166        }
167
168        /* Create the packet structure */
169        packet = trace_create_packet();
170
171        /* Create the trace */
172        trace = trace_create(argv[1]);
173
174        /* Ensure no error has occured creating the trace */
175        if(trace_is_err(trace)) {
176                trace_perror(trace, "Opening trace file");
177                return 1;
178        }
179
180        /* Start the trace, if it errors return */
181        if(trace_start(trace) == -1) {
182                trace_perror(trace, "Starting trace");
183                trace_destroy(trace);
184                return 1;
185        }
186
187        /* Proccess each packet in the trace */
188        while(trace_read_packet(trace,packet)>0) {
189                per_packet(packet);
190        }
191
192        /* If trace is error after proccessing packets it failed to process
193           the entire trace */
194        if(trace_is_err(trace)) {
195                trace_perror(trace, packet);
196                return 1;
197        }
198
199        /* free memory used to hold excluded networks */
200        free(exclude);
201
202        /* Print results */
203        plot_results();
204
205        trace_destroy(trace);
206        trace_destroy_packet(packet);
207        //libtrace_cleanup(trace, packet);
208        return 0;
209}
Note: See TracBrowser for help on using the repository browser.