#ifndef OUTPUT_H #define OUTPUT_H #include #include #include #include #include "massip-addr.h" #include "stack-src.h" #include "unusedparm.h" #include "masscan-app.h" #define MAX_BANNER_LENGTH 8192 struct Masscan; struct Output; enum ApplicationProtocol; enum PortStatus; /** * Output plugins * * The various means for writing output are essentially plugins. As new methods * are created, we just fill in a structure of function pointers. * TODO: this needs to be a loadable DLL, but in the meantime, it's just * internal structures. */ struct OutputType { const char *file_extension; void *(*create)(struct Output *out); void (*open)(struct Output *out, FILE *fp); void (*close)(struct Output *out, FILE *fp); void (*status)(struct Output *out, FILE *fp, time_t timestamp, int status, ipaddress ip, unsigned ip_proto, unsigned port, unsigned reason, unsigned ttl); void (*banner)(struct Output *out, FILE *fp, time_t timestamp, ipaddress ip, unsigned ip_proto, unsigned port, enum ApplicationProtocol proto, unsigned ttl, const unsigned char *px, unsigned length); }; /** * Masscan creates one "output" structure per thread. */ struct Output { const struct Masscan *masscan; char *filename; struct stack_src_t src[8]; FILE *fp; const struct OutputType *funcs; unsigned format; /** * The timestamp when this scan started. This is preserved in output files * because that's what nmap does, and a lot of tools parse this. */ time_t when_scan_started; /** * Whether we've started writing to a file yet. We are lazy writing * the file header until we've actually go something to write */ unsigned is_virgin_file:1; /** * used by json output to test if the first record has been seen, in order * to determine if it needs a , comma before the record */ unsigned is_first_record_seen:1; struct { time_t next; time_t last; unsigned period; unsigned offset; uint64_t filesize; uint64_t bytes_written; unsigned filecount; /* filesize rotates */ char *directory; } rotate; unsigned is_banner:1; /* --banners */ unsigned is_banner_rawudp:1; /* --rawudp */ unsigned is_gmt:1; /* --gmt */ unsigned is_interactive:1; /* echo to command line */ unsigned is_show_open:1; /* show open ports (default) */ unsigned is_show_closed:1; /* show closed ports */ unsigned is_show_host:1; /* show host status info, like up/down */ unsigned is_append:1; /* append to file */ struct { struct { uint64_t open; uint64_t closed; uint64_t banner; } tcp; struct { uint64_t open; uint64_t closed; } udp; struct { uint64_t open; uint64_t closed; } sctp; struct { uint64_t echo; uint64_t timestamp; } icmp; struct { uint64_t open; } arp; struct { uint64_t open; uint64_t closed; } oproto; } counts; struct { ipaddress ip; unsigned port; char *password; ptrdiff_t fd; uint64_t outstanding; unsigned state; } redis; struct { char *stylesheet; } xml; }; const char *name_from_ip_proto(unsigned ip_proto); const char *status_string(enum PortStatus x); const char *reason_string(int x, char *buffer, size_t sizeof_buffer); const char *normalize_string(const unsigned char *px, size_t length, char *buf, size_t buf_len); extern const struct OutputType text_output; extern const struct OutputType unicornscan_output; extern const struct OutputType xml_output; extern const struct OutputType json_output; extern const struct OutputType ndjson_output; extern const struct OutputType certs_output; extern const struct OutputType binary_output; extern const struct OutputType null_output; extern const struct OutputType redis_output; extern const struct OutputType hostonly_output; extern const struct OutputType grepable_output; /** * Creates an "output" object. This is called by the receive thread in order * to send "status" information (open/closed ports) and "banners" to either * the command-line or to files in specific formats, such as XML or Redis * @param masscan * The master configuration. * @param thread_index * When there are more than one receive threads, they are differentiated * by this index number. * @return * an output object that must eventually be destroyed by output_destroy(). */ struct Output * output_create(const struct Masscan *masscan, unsigned thread_index); void output_destroy(struct Output *output); void output_report_status(struct Output *output, time_t timestamp, int status, ipaddress ip, unsigned ip_proto, unsigned port, unsigned reason, unsigned ttl, const unsigned char mac[6]); typedef void (*OUTPUT_REPORT_BANNER)( struct Output *output, time_t timestamp, ipaddress ip, unsigned ip_proto, unsigned port, unsigned proto, unsigned ttl, const unsigned char *px, unsigned length); void output_report_banner( struct Output *output, time_t timestamp, ipaddress ip, unsigned ip_proto, unsigned port, unsigned proto, unsigned ttl, const unsigned char *px, unsigned length); /** * Regression tests this unit. * @return * 0 on success, or positive integer on failure */ int output_selftest(void); #endif