/* * 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 #include "../../lib/logger.h" #include "../fieldset.h" #include "output_modules.h" static FILE *file = NULL; int csv_init(struct state_conf *conf, char **fields, int fieldlens) { 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 CSV output file %s", conf->output_filename); } } } else { file = stdout; log_info("csv", "no output file selected, will use stdout"); } if (fieldlens > 1 && file) { log_debug("csv", "more than one field, will add headers"); for (int i=0; i < fieldlens; i++) { if (i) { fprintf(file, ","); } fprintf(file, "%s", fields[i]); } fprintf(file, "\n"); } check_and_log_file_error(file, "csv"); 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]); } check_and_log_file_error(f, "csv"); } int csv_process(fieldset_t *fs) { if (!file) { return EXIT_SUCCESS; } for (int i=0; i < fs->len; i++) { field_t *f = &(fs->fields[i]); if (i) { fprintf(file, ","); } if (f->type == FS_STRING) { if (strchr((char*) f->value.ptr, ',')) { fprintf(file, "\"%s\"", (char*) f->value.ptr); } else { fprintf(file, "%s", (char*) f->value.ptr); } } else if (f->type == FS_UINT64) { fprintf(file, "%" PRIu64, (uint64_t) f->value.num); } else if (f->type == FS_BINARY) { hex_encode(file, (unsigned char*) f->value.ptr, f->len); } else if (f->type == FS_NULL) { // do nothing } else { log_fatal("csv", "received unknown output type"); } } fprintf(file, "\n"); fflush(file); check_and_log_file_error(file, "csv"); return EXIT_SUCCESS; } output_module_t module_csv_file = { .name = "csv", .filter_duplicates = 0, // framework should not filter out duplicates .filter_unsuccessful = 0, // framework should not filter out unsuccessful .init = &csv_init, .start = NULL, .update = NULL, .update_interval = 0, .close = &csv_close, .process_ip = &csv_process, .helptext = "Outputs one or more output fields as a comma-delimited file. By default, the " "probe module does not filter out duplicates or limit to successful fields, " "but rather includes all received packets. Fields can be controlled by " "setting --output-fields. Filtering out failures and duplicate packets can " "be achieved by setting an --output-filter." };