1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
/* Libtrace program designed to demonstrate the use of the trace_get_source_*
* shortcut functions.
*
* This code also contains examples of sockaddr manipulation.
*/
#include "libtrace.h"
#include <stdio.h>
#include <inttypes.h>
#include <assert.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* This is not the nicest way to print a 6 byte MAC address, but it is
* effective. Libtrace will have provided us a pointer to the start of the
* MAC address within the packet, so we can just use array indices to grab
* each byte of the MAC address in turn */
static inline void print_mac(uint8_t *mac) {
printf("%02x:%02x:%02x:%02x:%02x:%02x ", mac[0], mac[1], mac[2], mac[3],
mac[4], mac[5]);
}
/* Given a sockaddr containing an IP address, prints the IP address to stdout
* using the common string representation for that address type */
static inline void print_ip(struct sockaddr *ip) {
char str[20];
/* Check the sockaddr family so we can cast it to the appropriate
* address type, IPv4 or IPv6 */
if (ip->sa_family == AF_INET) {
/* IPv4 - cast the generic sockaddr to a sockaddr_in */
struct sockaddr_in *v4 = (struct sockaddr_in *)ip;
/* Use inet_ntop to convert the address into a string using
* dotted decimal notation */
printf("%s ", inet_ntop(AF_INET, &(v4->sin_addr), str, 20));
}
if (ip->sa_family == AF_INET6) {
/* IPv6 - cast the generic sockaddr to a sockaddr_in6 */
struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip;
/* Use inet_ntop to convert the address into a string using
* IPv6 address notation */
printf("%s ", inet_ntop(AF_INET6, &(v6->sin6_addr), str, 20));
}
}
static void per_packet(libtrace_packet_t *packet)
{
struct sockaddr_storage addr;
struct sockaddr *addr_ptr;
uint16_t port;
uint8_t *mac;
/* Get the source mac */
mac = trace_get_source_mac(packet);
/* If this packet does not contain a MAC address, print "NULL" */
if (mac == NULL)
printf("NULL ");
else
print_mac(mac);
/* Get the source IP address */
/* Note that we pass a casted sockaddr_storage into this function. This
* is because we do not know if the IP address we get back will be a
* v4 or v6 address. v6 addresses are much larger than v4 addresses and
* will not fit within a sockaddr_in structure used for storing IPv4
* addresses, leading to memory corruption and segmentation faults.
*
* The safest way to avoid this problem is to use a sockaddr_storage
* which is guaranteed to be large enough to contain any known address
* format.
*/
addr_ptr = trace_get_source_address(packet, (struct sockaddr *)&addr);
/* No IP address? Print "NULL" instead */
if (addr_ptr == NULL)
printf("NULL ");
else
print_ip(addr_ptr);
/* Get the source port */
port = trace_get_source_port(packet);
/* If the port is zero, libtrace has told us that there is no
* legitimate port number present in the packet */
if (port == 0)
printf("NULL\n");
else
/* Port numbers are simply 16 bit values so we don't need to
* do anything special to print them. trace_get_source_port()
* even converts it into host byte order for us */
printf("%u\n", port);
}
static void libtrace_cleanup(libtrace_t *trace, libtrace_packet_t *packet) {
/* It's very important to ensure that we aren't trying to destroy
* a NULL structure, so each of the destroy calls will only occur
* if the structure exists */
if (trace)
trace_destroy(trace);
if (packet)
trace_destroy_packet(packet);
}
int main(int argc, char *argv[])
{
/* This is essentially the same main function from readdemo.c */
libtrace_t *trace = NULL;
libtrace_packet_t *packet = NULL;
/* Ensure we have at least one argument after the program name */
if (argc < 2) {
fprintf(stderr, "Usage: %s inputURI\n", argv[0]);
return 1;
}
packet = trace_create_packet();
if (packet == NULL) {
perror("Creating libtrace packet");
libtrace_cleanup(trace, packet);
return 1;
}
trace = trace_create(argv[1]);
if (trace_is_err(trace)) {
trace_perror(trace,"Opening trace file");
libtrace_cleanup(trace, packet);
return 1;
}
if (trace_start(trace) == -1) {
trace_perror(trace,"Starting trace");
libtrace_cleanup(trace, packet);
return 1;
}
while (trace_read_packet(trace,packet)>0) {
per_packet(packet);
}
if (trace_is_err(trace)) {
trace_perror(trace,"Reading packets");
libtrace_cleanup(trace, packet);
return 1;
}
libtrace_cleanup(trace, packet);
return 0;
}
|