From 67aa6f0ab05fc26d34657635740d137c2b0aa153 Mon Sep 17 00:00:00 2001 From: Zakir Durumeric Date: Tue, 27 Aug 2013 12:03:24 -0400 Subject: [PATCH] adding generic csv output module --- lib/logger.c | 1 + src/Makefile | 5 +- src/fieldset.c | 7 +- src/fieldset.h | 13 ++-- src/output_modules/module_csv.c | 94 +++++++++++++++++++++++++ src/output_modules/module_simple_file.c | 1 - src/output_modules/output_modules.c | 14 ++-- src/output_modules/output_modules.h | 18 ++--- src/probe_modules/module_icmp_echo.c | 3 +- src/probe_modules/module_tcp_synscan.c | 17 ++--- src/probe_modules/packet.h | 2 + src/probe_modules/probe_modules.c | 58 ++++++++------- src/probe_modules/probe_modules.h | 30 +++++--- src/recv.c | 13 ++-- src/state.h | 4 +- src/zmap.c | 86 +++++++++++++--------- 16 files changed, 252 insertions(+), 114 deletions(-) create mode 100644 src/output_modules/module_csv.c diff --git a/lib/logger.c b/lib/logger.c index 8a797e7..c1ff213 100644 --- a/lib/logger.c +++ b/lib/logger.c @@ -53,6 +53,7 @@ static int LogLogVA(enum LogLevel level, const char *loggerName, if (loggerName || logMessage) { fputs("\n", log_output_stream); } + fflush(log_output_stream); } return 0; } diff --git a/src/Makefile b/src/Makefile index 6301977..1ae5e35 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,9 +31,10 @@ EXTRALDFLAGS= $(LDHARDENING) CFLAGS+=-Wall $(INCLUDE) $(EXTRACFLAGS) LDFLAGS+=$(EXTRALDFLAGS) -modules=module_tcp_synscan.o module_icmp_echo.o module_udp.o #ADD YOUR MODULE HERE +probemodules=module_tcp_synscan.o module_icmp_echo.o #module_udp.o #ADD YOUR PROBE MODULE HERE +outputmodules= module_csv.o #module_simple_file.o module_extended_file.o module_csv.o #ADD YOUR OUTPUT MODULE HERE -objects=constraint.o blacklist.o cyclic.o logger.o send.o recv.o state.o monitor.o zopt.o zmap.o random.o output_modules.o module_simple_file.o module_extended_file.o packet.o probe_modules.o ${modules} validate.o rijndael-alg-fst.o get_gateway.o aesrand.o fieldset.o +objects=constraint.o blacklist.o cyclic.o logger.o send.o recv.o state.o monitor.o zopt.o zmap.o random.o output_modules.o packet.o probe_modules.o ${probemodules} ${outputmodules} validate.o rijndael-alg-fst.o get_gateway.o aesrand.o fieldset.o ifeq ($(REDIS), true) LDLIBS+=-lhiredis diff --git a/src/fieldset.c b/src/fieldset.c index 25752fa..b560074 100644 --- a/src/fieldset.c +++ b/src/fieldset.c @@ -7,7 +7,7 @@ #include "../lib/logger.h" -void gen_fielddef_set(fielddefset_t *fds, fieldset_t fs[], int len) +void gen_fielddef_set(fielddefset_t *fds, fielddef_t fs[], int len) { if (fds->len + len > MAX_FIELDS) { log_fatal("fieldset", "out of room in field def set"); @@ -60,12 +60,12 @@ void fs_add_binary(fieldset_t *fs, const char *name, size_t len, uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index) { - return (uint64_t) fs->fields[i].value; + return (uint64_t) fs->fields[index].value; } char* fs_get_string_by_index(fieldset_t *fs, int index) { - return (char*) fs->fields[i].value; + return (char*) fs->fields[index].value; } int fds_get_index_by_name(fielddefset_t *fds, char *name) @@ -79,6 +79,7 @@ int fds_get_index_by_name(fielddefset_t *fds, char *name) } void fs_free(fieldset_t *fs) +{ for (int i=0; i < fs->len; i++) { field_t *f = &(fs->fields[i]); if (f->free_) { diff --git a/src/fieldset.h b/src/fieldset.h index d733dee..5ed2136 100644 --- a/src/fieldset.h +++ b/src/fieldset.h @@ -10,8 +10,8 @@ #include #include "types.h" -#ifndef _FIELDSET_H -#define _FIELDSET_H +#ifndef FIELDSET_H +#define FIELDSET_H // maximum number of records that can be stored in a fieldset #define MAX_FIELDS 128 @@ -67,13 +67,11 @@ typedef struct translation { fieldset_t *fs_new_fieldset(void); -uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index); - char* fs_get_string_by_index(fieldset_t *fs, int index); int fds_get_index_by_name(fielddefset_t *fds, char *name); -void gen_fielddef_set(fielddefset_t *fds, fieldset_t fs[], int len); +void gen_fielddef_set(fielddefset_t *fds, fielddef_t fs[], int len); void fs_add_uint64(fieldset_t *fs, const char *name, uint64_t value); @@ -82,10 +80,13 @@ void fs_add_string(fieldset_t *fs, const char *name, char *value, int free_); void fs_add_binary(fieldset_t *fs, const char *name, size_t len, void *value, int free_); +uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index); + void fs_free(fieldset_t *fs); translation_t *fs_generate_fieldset_translation(); fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t); -#endif +#endif // FIELDSET_H + diff --git a/src/output_modules/module_csv.c b/src/output_modules/module_csv.c new file mode 100644 index 0000000..4c5ccfc --- /dev/null +++ b/src/output_modules/module_csv.c @@ -0,0 +1,94 @@ +/* + * ZMap Copyright 2013 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "../../lib/logger.h" +#include "../fieldset.h" + +#include "output_modules.h" + +static FILE *file = NULL; + +int csv_init(struct state_conf *conf, fielddefset_t *fds) +{ + assert(conf); + if (conf->output_filename) { + if (!strcmp(conf->output_filename, "-")) { + file = stdout; + } else { + if (!(file = fopen(conf->output_filename, "w"))) { + log_fatal("csv", "could not open output file (%s)", + conf->output_filename); + } + } + } + // add output headers + for (int i=0; i < fds->len; i++) { + if (i) { + fprintf(file, ", "); + } + fprintf(file, "%s", fds->fielddefs[i].name); + } + return EXIT_SUCCESS; +} + +int csv_close(__attribute__((unused)) struct state_conf* c, + __attribute__((unused)) struct state_send* s, + __attribute__((unused)) struct state_recv* r) +{ + if (file) { + fflush(file); + fclose(file); + } + return EXIT_SUCCESS; +} + +static void hex_encode(FILE *f, unsigned char* readbuf, size_t len) +{ + for(size_t i=0; i < len; i++) { + fprintf(f, "%02x", readbuf[i]); + } +} + +int csv_process(fieldset_t *fs) +{ + for (int i=0; i < fs->len; i++) { + field_t *f = &(fs->fields[i]); + if (i) { + fprintf(file, ", "); + } + if (f->type == FS_STRING) { + fprintf(file, "%s", (char*) f->value); + } else if (f->type == FS_UINT64) { + fprintf(file, "%lu", (uint64_t) f->value); + } else if (f->type == FS_BINARY) { + hex_encode(file, (unsigned char*) f->value, f->len); + } + } + fprintf(file, "\n"); + return EXIT_SUCCESS; +} + +output_module_t module_csv_file = { + .name = "csv", + .init = &csv_init, + .start = NULL, + .update = NULL, + .update_interval = 0, + .close = &csv_close, + .process_ip = &csv_process, +}; + diff --git a/src/output_modules/module_simple_file.c b/src/output_modules/module_simple_file.c index 2061972..beb62bf 100644 --- a/src/output_modules/module_simple_file.c +++ b/src/output_modules/module_simple_file.c @@ -6,7 +6,6 @@ * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ - #include #include #include diff --git a/src/output_modules/output_modules.c b/src/output_modules/output_modules.c index 49032a8..a9c4382 100644 --- a/src/output_modules/output_modules.c +++ b/src/output_modules/output_modules.c @@ -12,20 +12,21 @@ #include "output_modules.h" -extern output_module_t module_simple_file; -extern output_module_t module_extended_file; +//extern output_module_t module_simple_file; +//extern output_module_t module_extended_file; +extern output_module_t module_csv_file; // ADD YOUR MODULE HERE #ifdef REDIS extern output_module_t module_redis; #endif - output_module_t* output_modules[] = { - &module_simple_file, - &module_extended_file, + &module_csv_file + //&module_simple_file, + //&module_extended_file, #ifdef REDIS - &module_redis, + //&module_redis, #endif // ADD YOUR MODULE HERE }; @@ -50,3 +51,4 @@ void print_output_modules(void) printf("%s\n", output_modules[i]->name); } } + diff --git a/src/output_modules/output_modules.h b/src/output_modules/output_modules.h index bfda3f4..64acd5d 100644 --- a/src/output_modules/output_modules.h +++ b/src/output_modules/output_modules.h @@ -10,35 +10,31 @@ #define HEADER_OUTPUT_MODULES_H #include "../state.h" +#include "../fieldset.h" // called at scanner initialization -typedef int (*output_init_cb)(struct state_conf *); +typedef int (*output_init_cb)(struct state_conf *, fielddefset_t *fds); // called on packet receipt -typedef int (*output_packet_cb)(ipaddr_n_t src_ip, ipaddr_n_t dst_ip, - const char* response_type, - int is_repeat, int in_cooldown, - const u_char* packetbuf, size_t buflen); +typedef int (*output_packet_cb)(fieldset_t *fs); // called periodically during the scan -typedef int (*output_update_cb)(struct state_conf*, struct state_send*, struct state_recv*); - +typedef int (*output_update_cb)(struct state_conf*, + struct state_send*, struct state_recv*); typedef struct output_module { const char *name; unsigned update_interval; - output_init_cb init; output_update_cb start; output_update_cb update; output_update_cb close; - output_packet_cb success_ip; - output_packet_cb other_ip; - + output_packet_cb process_ip; } output_module_t; output_module_t* get_output_module_by_name(const char*); + void print_output_modules(void); #endif // HEADER_OUTPUT_MODULES_H diff --git a/src/probe_modules/module_icmp_echo.c b/src/probe_modules/module_icmp_echo.c index cb6e9a4..e3d5607 100644 --- a/src/probe_modules/module_icmp_echo.c +++ b/src/probe_modules/module_icmp_echo.c @@ -185,5 +185,6 @@ probe_module_t module_icmp_echo = { .process_packet = &icmp_echo_process_packet, .validate_packet = &icmp_validate_packet, .close = NULL, - .fields = fields}; + .fields = fields, + .numfields = 6}; diff --git a/src/probe_modules/module_tcp_synscan.c b/src/probe_modules/module_tcp_synscan.c index a8f2e23..c578c4a 100644 --- a/src/probe_modules/module_tcp_synscan.c +++ b/src/probe_modules/module_tcp_synscan.c @@ -146,14 +146,10 @@ static fielddef_t fields[] = { {.name = "seqnum", .type = "int", .desc = "TCP sequence number"}, {.name = "acknum", .type = "int", .desc = "TCP acknowledgement number"}, {.name = "window", .type = "int", .desc = "TCP window"}, + {.name = "classification", .type="string", .desc = "packet classification"}, + {.name = "success", .type="int", .desc = "is response considered success"} }; -const char *help = - "Probe module that sends a TCP SYN packet to a specific " - "port. Possible classifications are: synack and rst. A " - "SYN-ACK packet is considered a success and a reset packet " - "is considered a failed response."; - probe_module_t module_tcp_synscan = { .name = "tcp_synscan", .packet_length = 54, @@ -167,6 +163,11 @@ probe_module_t module_tcp_synscan = { .process_packet = &synscan_process_packet, .validate_packet = &synscan_validate_packet, .close = NULL, - .helptext = help, - .fields = fields}; + .helptext = "Probe module that sends a TCP SYN packet to a specific " + "port. Possible classifications are: synack and rst. A " + "SYN-ACK packet is considered a success and a reset packet " + "is considered a failed response.", + + .fields = fields, + .numfields = 7}; diff --git a/src/probe_modules/packet.h b/src/probe_modules/packet.h index 2acb3b0..91fa0b6 100644 --- a/src/probe_modules/packet.h +++ b/src/probe_modules/packet.h @@ -20,6 +20,8 @@ void make_tcp_header(struct tcphdr*, port_h_t); void make_icmp_header(struct icmp *); void make_udp_header(struct udphdr *udp_header, port_h_t dest_port, uint16_t len); +void fprintf_ip_header(FILE *fp, struct iphdr *iph); +void fprintf_eth_header(FILE *fp, struct ethhdr *ethh); static inline unsigned short in_checksum(unsigned short *ip_pkt, int len) { diff --git a/src/probe_modules/probe_modules.c b/src/probe_modules/probe_modules.c index 27a3238..d9aa94f 100644 --- a/src/probe_modules/probe_modules.c +++ b/src/probe_modules/probe_modules.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -16,24 +17,26 @@ #include #include +#include "../../lib/logger.h" #include "../fieldset.h" #include "probe_modules.h" extern probe_module_t module_tcp_synscan; extern probe_module_t module_icmp_echo; -extern probe_module_t module_udp; +//extern probe_module_t module_udp; // ADD YOUR MODULE HERE probe_module_t* probe_modules[] = { &module_tcp_synscan, &module_icmp_echo, - &module_udp +// &module_udp // ADD YOUR MODULE HERE }; probe_module_t* get_probe_module_by_name(const char* name) { - for (int i=0; i < (int) (sizeof(probe_modules)/sizeof(probe_modules[0])); i++) { + int len = (int) (sizeof(probe_modules)/sizeof(probe_modules[0])); + for (int i=0; i < len; i++) { if (!strcmp(probe_modules[i]->name, name)) { return probe_modules[i]; } @@ -43,18 +46,12 @@ probe_module_t* get_probe_module_by_name(const char* name) void print_probe_modules(void) { - for (int i=0; i < (int) (sizeof(probe_modules)/sizeof(probe_modules[0])); i++) { + int len = (int) (sizeof(probe_modules)/sizeof(probe_modules[0])); + for (int i=0; i < len; i++) { printf("%s\n", probe_modules[i]->name); } } -void print_probe_module_fields(probe_module_t *p) -{ - for (int i=0; i < (int) (sizeof(p->fields)/sizeof(p->fields[0])); i++) { - - } -} - char *make_ip_str(uint32_t ip) { struct in_addr t; @@ -66,20 +63,6 @@ char *make_ip_str(uint32_t ip) return retv; } -fielddef_t ip_fields[] = { - {.name="saddr", .type="string", .desc="source IP address of response"}, - {.name="daddr", .type="string", .desc="destination IP address of response"}, - {.name="ipid", .type="int", .desc="IP identification number of response"}, - {.name="ttl", .type="int", .desc="time-to-live of response packet"} -} - -fielddef_t sys_fields[] = { - {.name="repeat", .type="int", .desc="Is response a repeat response from host"}, - {.name="cooldown", .type="int", .desc="Was response received during the cooldown period"}, - - {.name="timestamp-str", .type="string", .desc="timestamp of when response arrived in ISO8601 format."} -} - void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip) { fs_add_string(fs, "saddr", make_ip_str(ip->saddr), 1); @@ -88,8 +71,33 @@ void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip) fs_add_uint64(fs, "ttl", ntohl(ip->ttl)); } +#define TIMESTR_LEN 50 + void fs_add_system_fields(fieldset_t *fs, int is_repeat, int in_cooldown) { + fs_add_uint64(fs, "repeat", is_repeat); + fs_add_uint64(fs, "cooldown", in_cooldown); + char *timestr = malloc(TIMESTR_LEN+1); + if (!timestr) { + log_fatal("recv", "unable to allocate memory for " + "timestamp string in fieldset."); + } + time_t now = time(0); + strftime(timestr, TIMESTR_LEN, "%Y-%m-%dT%H:%M:%S%z", + localtime(&now)); + fs_add_string(fs, "timestamp-str", timestr, 1); } +fielddef_t ip_fields[] = { + {.name="saddr", .type="string", .desc="source IP address of response"}, + {.name="daddr", .type="string", .desc="destination IP address of response"}, + {.name="ipid", .type="int", .desc="IP identification number of response"}, + {.name="ttl", .type="int", .desc="time-to-live of response packet"} +}; + +fielddef_t sys_fields[] = { + {.name="repeat", .type="int", .desc="Is response a repeat response from host"}, + {.name="cooldown", .type="int", .desc="Was response received during the cooldown period"}, + {.name="timestamp-str", .type="string", .desc="timestamp of when response arrived in ISO8601 format."} +}; diff --git a/src/probe_modules/probe_modules.h b/src/probe_modules/probe_modules.h index b077af7..4f8ea5a 100644 --- a/src/probe_modules/probe_modules.h +++ b/src/probe_modules/probe_modules.h @@ -1,8 +1,8 @@ #include "../state.h" #include "../fieldset.h" -#ifndef HEADER_PROBE_MODULES_H -#define HEADER_PROBE_MODULES_H +#ifndef PROBE_MODULES_H +#define PROBE_MODULES_H typedef struct probe_response_type { const uint8_t is_success; @@ -10,14 +10,21 @@ typedef struct probe_response_type { } response_type_t; typedef int (*probe_global_init_cb)(struct state_conf *); -typedef int (*probe_thread_init_cb)(void* packetbuf, macaddr_t* src_mac, macaddr_t* gw_mac, port_n_t src_port); -typedef int (*probe_make_packet_cb)(void* packetbuf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip, - uint32_t *validation, int probe_num); -typedef void (*probe_print_packet_cb)(FILE *, void* packetbuf); -typedef int (*probe_close_cb)(struct state_conf*, struct state_send*, struct state_recv*); -typedef int (*probe_validate_packet_cb)(const struct iphdr *ip_hdr, uint32_t len, uint32_t *src_ip, uint32_t *validation); +typedef int (*probe_thread_init_cb)(void* packetbuf, macaddr_t* src_mac, + macaddr_t* gw_mac, port_n_t src_port); -typedef void (*probe_classify_packet_cb)(const u_char* packetbuf, uint32_t len, fieldset_t*); +typedef int (*probe_make_packet_cb)(void* packetbuf, ipaddr_n_t src_ip, + ipaddr_n_t dst_ip, + uint32_t *validation, int probe_num); + +typedef void (*probe_print_packet_cb)(FILE *, void* packetbuf); +typedef int (*probe_close_cb)(struct state_conf*, + struct state_send*, struct state_recv*); +typedef int (*probe_validate_packet_cb)(const struct iphdr *ip_hdr, + uint32_t len, uint32_t *src_ip, uint32_t *validation); + +typedef void (*probe_classify_packet_cb)(const u_char* packetbuf, + uint32_t len, fieldset_t*); typedef struct probe_module { const char *name; @@ -37,6 +44,7 @@ typedef struct probe_module { probe_classify_packet_cb process_packet; probe_close_cb close; fielddef_t *fields; + int numfields; const char *helptext; } probe_module_t; @@ -47,4 +55,8 @@ void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip); void fs_add_system_fields(fieldset_t *fs, int is_repeat, int in_cooldown); void print_probe_modules(void); +extern fielddef_t ip_fields[]; +extern fielddef_t sys_fields[]; + #endif // HEADER_PROBE_MODULES_H + diff --git a/src/recv.c b/src/recv.c index 76370cd..820d938 100644 --- a/src/recv.c +++ b/src/recv.c @@ -101,7 +101,7 @@ void packet_cb(u_char __attribute__((__unused__)) *user, fs_add_system_fields(fs, is_repeat, zsend.complete); int success_index = zconf.fsconf.success_index; assert(success_index < fs->len); - int is_success = fs_get_uint64_byindex(success_index); + int is_success = fs_get_uint64_by_index(fs, success_index); if (is_success) { zrecv.success_total++; @@ -119,12 +119,13 @@ void packet_cb(u_char __attribute__((__unused__)) *user, } else { zrecv.failure_total++; } - //if (zconf.output_module && zconf.output_module->process_record) { - // //zconf.output_module->success_ip( - // // ip_hdr->saddr, ip_hdr->daddr, - // // r->name, is_repeat, zsend.complete, bytes, buflen); - //} + // we need to translate the data provided by the probe module + // into a fieldset that can be used by the output module + + if (zconf.output_module && zconf.output_module->process_ip) { + zconf.output_module->process_ip(fs); + } if (zconf.output_module && zconf.output_module->update && !(zrecv.success_unique % zconf.output_module->update_interval)) { zconf.output_module->update(&zconf, &zsend, &zrecv); diff --git a/src/state.h b/src/state.h index efba852..84aee6f 100644 --- a/src/state.h +++ b/src/state.h @@ -26,13 +26,13 @@ struct output_module; struct fieldset_conf { fielddefset_t defs; + fielddefset_t outdefs; int *translation; int translation_len; int success_index; int classification_index; }; - // global configuration struct state_conf { int log_level; @@ -79,7 +79,7 @@ struct state_conf { char *whitelist_filename; char *raw_output_fields; char **output_fields; - struct fieldset_conf fs_conf; + struct fieldset_conf fsconf; int output_fields_len; int dryrun; int summary; diff --git a/src/zmap.c b/src/zmap.c index 3766d33..59684dc 100644 --- a/src/zmap.c +++ b/src/zmap.c @@ -10,18 +10,19 @@ #include #include - +#include +#include #include #include -#include #include -#include + #include #include #include #include #include + #include #include "../lib/logger.h" @@ -32,9 +33,10 @@ #include "recv.h" #include "state.h" #include "monitor.h" +#include "get_gateway.h" + #include "output_modules/output_modules.h" #include "probe_modules/probe_modules.h" -#include "get_gateway.h" pthread_mutex_t cpu_affinity_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t recv_ready_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -55,15 +57,17 @@ static void fs_split_string(char* in, int *len, char***results) currloc++; } else { char *new = malloc(len+1); + assert(new); strncpy(new, currloc, len); new[len] = '\0'; fields[retvlen++] = new; + assert(fields[retvlen-1]); } + if (len == strlen(currloc)) { + break; + } currloc += len; - if (currloc == in + (size_t) strlen(in)) { - break; - } - } + } *results = fields; *len = retvlen; } @@ -160,7 +164,6 @@ static void summary(void) static void start_zmap(void) { - log_init(stderr, zconf.log_level); log_info("zmap", "started"); // finish setting up configuration @@ -208,7 +211,7 @@ static void start_zmap(void) // initialization if (zconf.output_module && zconf.output_module->init) { - zconf.output_module->init(&zconf); + zconf.output_module->init(&zconf, &zconf.fsconf.outdefs); } if (send_init()) { exit(EXIT_FAILURE); @@ -216,7 +219,6 @@ static void start_zmap(void) if (zconf.output_module && zconf.output_module->start) { zconf.output_module->start(&zconf, &zsend, &zrecv); } - // start threads pthread_t *tsend, trecv, tmon; int r = pthread_create(&trecv, NULL, start_recv, NULL); @@ -331,12 +333,25 @@ int parse_mac(macaddr_t *out, char *in) int main(int argc, char *argv[]) { + struct gengetopt_args_info args; struct cmdline_parser_params *params; params = cmdline_parser_params_create(); params->initialize = 1; params->override = 0; params->check_required = 0; + + SET_BOOL(zconf.dryrun, dryrun); + SET_BOOL(zconf.quiet, quiet); + SET_BOOL(zconf.summary, summary); + zconf.cooldown_secs = args.cooldown_time_arg; + zconf.senders = args.sender_threads_arg; + zconf.log_level = args.verbosity_arg; + + log_init(stderr, zconf.log_level); + log_trace("zmap", "zmap main thread started"); + + if (cmdline_parser_ext(argc, argv, &args, params) != 0) { exit(EXIT_SUCCESS); } @@ -383,26 +398,35 @@ int main(int argc, char *argv[]) } // now that we know the probe module, let's find what it supports - memset(zconf.fs_conf, 0, sizeof(struct fieldset_conf)); + memset(&zconf.fsconf, 0, sizeof(struct fieldset_conf)); // the set of fields made available to a user is constructed // of IP header fields + probe module fields + system fields - fielddefset_t *fds = &(zconf.fs_conf.defs); - gen_fieldset_def(fds, &(ip_fields), - sizeof(ip_fields)/sizeof(fielddef_t)); - gen_fieldset_def(fds, &(zconf.probe_module->fields), - sizeof(zconf.probe_module->fields)/sizeof(fielddef_t)); - gen_fieldset_def(fds, &(sys_fields), - sizeof(sys_fields)/sizeof(fielddef_t)); + fielddefset_t *fds = &(zconf.fsconf.defs); + gen_fielddef_set(fds, (fielddef_t*) &(ip_fields), + 4); + gen_fielddef_set(fds, zconf.probe_module->fields, + zconf.probe_module->numfields); + gen_fielddef_set(fds, (fielddef_t*) &(sys_fields), + 3); + if (args.list_output_fields_given) { + for (int i = 0; i < fds->len; i++) { + printf("%s (%s): %s\n", fds->fielddefs[i].name, + fds->fielddefs[i].type, + fds->fielddefs[i].desc); + } + exit(EXIT_SUCCESS); + } + // find the fields we need for the framework - zconf.fs_conf.success_index = - fs_get_index_by_name(fds, "success"); - if (zconf.fs_conf.success_index < 0) { + zconf.fsconf.success_index = + fds_get_index_by_name(fds, (char*) "success"); + if (zconf.fsconf.success_index < 0) { log_fatal("fieldset", "probe module does not supply " "required success field."); } - zconf.fs_conf.classification_index = - fs_get_index_by_name(fds, "classification"); - if (zconf.fs_conf.classification_index < 0) { + zconf.fsconf.classification_index = + fds_get_index_by_name(fds, (char*) "classification"); + if (zconf.fsconf.classification_index < 0) { log_fatal("fieldset", "probe module does not supply " "required packet classification field."); } @@ -412,10 +436,11 @@ int main(int argc, char *argv[]) } else { zconf.raw_output_fields = (char*) "saddr"; } - fs_split_string(args.output_fields_arg, &(zconf.output_fields_len), + fs_split_string(zconf.raw_output_fields, &(zconf.output_fields_len), &(zconf.output_fields)); for (int i=0; i < zconf.output_fields_len; i++) { - log_trace("zmap", "requested output field (%i): %s", + log_debug("zmap", "requested output field (%i): %s", + i, zconf.output_fields[i]); } // generate a translation that can be used to convert output @@ -431,13 +456,6 @@ int main(int argc, char *argv[]) SET_IF_GIVEN(zconf.max_results, max_results); SET_IF_GIVEN(zconf.rate, rate); SET_IF_GIVEN(zconf.packet_streams, probes); - SET_BOOL(zconf.dryrun, dryrun); - SET_BOOL(zconf.quiet, quiet); - SET_BOOL(zconf.summary, summary); - zconf.cooldown_secs = args.cooldown_time_arg; - zconf.senders = args.sender_threads_arg; - zconf.log_level = args.verbosity_arg; - if (zconf.probe_module->port_args) {