further progress

This commit is contained in:
Zakir Durumeric 2013-08-26 07:59:41 -04:00
parent 99312020ba
commit ea39b3bac4
11 changed files with 187 additions and 177 deletions

View File

@ -7,31 +7,14 @@
#include "../lib/logger.h"
int fs_split_string(char* in, int *len, char**results)
void gen_fielddef_set(fielddefset_t *fds, fieldset_t fs[], int len)
{
char** fields = calloc(MAX_FIELDS, sizeof(char*));
memset(fields, 0, sizeof(fields));
int retvlen = 0;
char *currloc = in;
// parse csv into a set of strings
while (1) {
size_t len = strcspn(currloc, ", ");
char *new = malloc(len+1);
if (fds->len + len > MAX_FIELDS) {
log_fatal("fieldset", "out of room in field def set");
}
(void)len;
*results = fields;
*len = retvlen;
(void)results;
return 0;
}
void combine_definitions()
{
fielddef_t *open = &(fds->fielddefs[fds->len]);
memcpy(open, fs, len*sizeof(fielddef_t));
fds->len += len;
}
fieldset_t *fs_new_fieldset(void)
@ -75,8 +58,27 @@ void fs_add_binary(fieldset_t *fs, const char *name, size_t len,
fs_add_word(fs, name, FS_BINARY, free_, len, value);
}
void fs_free(fieldset_t *fs)
uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index)
{
return (uint64_t) fs->fields[i].value;
}
char* fs_get_string_by_index(fieldset_t *fs, int index)
{
return (char*) fs->fields[i].value;
}
int fds_get_index_by_name(fielddefset_t *fds, char *name)
{
for (int i=0; i < fds->len; i++) {
if (!strcmp(fds->fielddefs[i].name, name)) {
return i;
}
}
return -1;
}
void fs_free(fieldset_t *fs)
for (int i=0; i < fs->len; i++) {
field_t *f = &(fs->fields[i]);
if (f->free_) {

View File

@ -8,6 +8,7 @@
#include <stdlib.h>
#include <stdint.h>
#include "types.h"
#ifndef _FIELDSET_H
#define _FIELDSET_H
@ -29,6 +30,11 @@ typedef struct field_def {
const char *desc;
} fielddef_t;
typedef struct fielddef_set {
fielddef_t fielddefs[MAX_FIELDS];
int len;
} fielddefset_t;
// the internal field type used by fieldset
typedef struct field {
const char *name;
@ -61,6 +67,14 @@ 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 fs_add_uint64(fieldset_t *fs, const char *name, uint64_t value);
void fs_add_string(fieldset_t *fs, const char *name, char *value, int free_);

View File

@ -82,33 +82,8 @@ void icmp_echo_print_packet(FILE *fp, void* packet)
ntohs(icmp_header->icmp_cksum),
ntohs(icmp_header->icmp_id),
ntohs(icmp_header->icmp_seq));
struct in_addr *s = (struct in_addr *) &(iph->saddr);
struct in_addr *d = (struct in_addr *) &(iph->daddr);
char srcip[20];
char dstip[20];
// inet_ntoa is a const char * so we if just call it in
// fprintf, you'll get back wrong results since we're
// calling it twice.
strncpy(srcip, inet_ntoa(*s), 19);
strncpy(dstip, inet_ntoa(*d), 19);
fprintf(fp, "ip { saddr: %s | daddr: %s | checksum: %u }\n",
srcip,
dstip,
ntohl(iph->check));
fprintf(fp, "eth { shost: %02x:%02x:%02x:%02x:%02x:%02x | "
"dhost: %02x:%02x:%02x:%02x:%02x:%02x }\n",
(int) ((unsigned char *) ethh->h_source)[0],
(int) ((unsigned char *) ethh->h_source)[1],
(int) ((unsigned char *) ethh->h_source)[2],
(int) ((unsigned char *) ethh->h_source)[3],
(int) ((unsigned char *) ethh->h_source)[4],
(int) ((unsigned char *) ethh->h_source)[5],
(int) ((unsigned char *) ethh->h_dest)[0],
(int) ((unsigned char *) ethh->h_dest)[1],
(int) ((unsigned char *) ethh->h_dest)[2],
(int) ((unsigned char *) ethh->h_dest)[3],
(int) ((unsigned char *) ethh->h_dest)[4],
(int) ((unsigned char *) ethh->h_dest)[5]);
fprintf_ip_header(fp, iph);
fprintf_eth_header(fp, ethh);
fprintf(fp, "------------------------------------------------------\n");
}

View File

@ -84,45 +84,18 @@ void synscan_print_packet(FILE *fp, void* packet)
ntohs(tcph->dest),
ntohl(tcph->seq),
ntohl(tcph->check));
struct in_addr *s = (struct in_addr *) &(iph->saddr);
struct in_addr *d = (struct in_addr *) &(iph->daddr);
char srcip[20];
char dstip[20];
// inet_ntoa is a const char * so we if just call it in
// fprintf, you'll get back wrong results since we're
// calling it twice.
strncpy(srcip, inet_ntoa(*s), 19);
strncpy(dstip, inet_ntoa(*d), 19);
fprintf(fp, "ip { saddr: %s | daddr: %s | checksum: %u }\n",
srcip,
dstip,
ntohl(iph->check));
fprintf(fp, "eth { shost: %02x:%02x:%02x:%02x:%02x:%02x | "
"dhost: %02x:%02x:%02x:%02x:%02x:%02x }\n",
(int) ((unsigned char *) ethh->h_source)[0],
(int) ((unsigned char *) ethh->h_source)[1],
(int) ((unsigned char *) ethh->h_source)[2],
(int) ((unsigned char *) ethh->h_source)[3],
(int) ((unsigned char *) ethh->h_source)[4],
(int) ((unsigned char *) ethh->h_source)[5],
(int) ((unsigned char *) ethh->h_dest)[0],
(int) ((unsigned char *) ethh->h_dest)[1],
(int) ((unsigned char *) ethh->h_dest)[2],
(int) ((unsigned char *) ethh->h_dest)[3],
(int) ((unsigned char *) ethh->h_dest)[4],
(int) ((unsigned char *) ethh->h_dest)[5]);
fprintf_ip_header(fp, iph);
fprintf_eth_header(fp, ethh);
fprintf(fp, "------------------------------------------------------\n");
}
int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len,
__attribute__((unused))uint32_t *src_ip, uint32_t *validation)
__attribute__((unused))uint32_t *src_ip,
uint32_t *validation)
{
if (ip_hdr->protocol != IPPROTO_TCP) {
return 0;
}
if ((4*ip_hdr->ihl + sizeof(struct tcphdr)) > len) {
// buffer not large enough to contain expected tcp header
return 0;
@ -130,27 +103,21 @@ int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len,
struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr + 4*ip_hdr->ihl);
uint16_t sport = tcp->source;
uint16_t dport = tcp->dest;
// validate source port
if (ntohs(sport) != zconf.target_port) {
return 0;
}
// validate destination port
if (!check_dst_port(ntohs(dport), num_ports, validation)) {
return 0;
}
// validate tcp acknowledgement number
if (htonl(tcp->ack_seq) != htonl(validation[0])+1) {
return 0;
}
return 1;
}
void synscan_process_packet(const u_char *packet,
__attribute__((unused)) uint32_t len, fieldset_t *fs)
{
@ -174,13 +141,18 @@ void synscan_process_packet(const u_char *packet,
}
static fielddef_t fields[] = {
{.name = "sport", .type = "int", .desc = "TCP source port"},
{.name = "dport", .type = "int", .desc = "TCP destination port"},
{.name = "sport", .type = "int", .desc = "TCP source port"},
{.name = "dport", .type = "int", .desc = "TCP destination port"},
{.name = "seqnum", .type = "int", .desc = "TCP sequence number"},
{.name = "acknum", .type = "int", .desc = "TCP acknowledgement number"},
{.name = "window", .type = "int", .desc = "TCP window"},
};
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",
@ -195,5 +167,6 @@ probe_module_t module_tcp_synscan = {
.process_packet = &synscan_process_packet,
.validate_packet = &synscan_validate_packet,
.close = NULL,
.helptext = help,
.fields = fields};

View File

@ -109,14 +109,17 @@ int udp_global_initialize(struct state_conf *conf) {
udp_send_msg[i] = (n & 0xff);
}
} else {
log_fatal("udp", "unknown UDP probe specification (expected file:/path, text:STRING, or hex:01020304)");
log_fatal("udp", "unknown UDP probe specification "
"(expected file:/path, text:STRING, "
"or hex:01020304)");
free(udp_send_msg);
free(args);
exit(1);
}
if (udp_send_msg_len > MAX_UDP_PAYLOAD_LEN) {
log_warn("udp", "warning: reducing UDP payload to %d bytes (from %d) to fit on the wire\n",
log_warn("udp", "warning: reducing UDP payload to %d "
"bytes (from %d) to fit on the wire\n",
MAX_UDP_PAYLOAD_LEN, udp_send_msg_len);
udp_send_msg_len = MAX_UDP_PAYLOAD_LEN;
}
@ -132,7 +135,6 @@ int udp_global_cleanup(__attribute__((unused)) struct state_conf *zconf,
return(0);
}
int udp_init_perthread(void* buf, macaddr_t *src,
macaddr_t *gw, __attribute__((unused)) port_h_t dst_port)
{
@ -158,9 +160,6 @@ int udp_init_perthread(void* buf, macaddr_t *src,
return EXIT_SUCCESS;
}
int udp_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
uint32_t *validation, int probe_num)
{
@ -188,34 +187,8 @@ void udp_print_packet(FILE *fp, void* packet)
ntohs(udph->source),
ntohs(udph->dest),
ntohl(udph->check));
//ip_header = (struct iphdr*)(&eth_header[1])
struct in_addr *s = (struct in_addr *) &(iph->saddr);
struct in_addr *d = (struct in_addr *) &(iph->daddr);
char srcip[20];
char dstip[20];
// inet_ntoa is a const char * so we if just call it in
// fprintf, you'll get back wrong results since we're
// calling it twice.
strncpy(srcip, inet_ntoa(*s), 19);
strncpy(dstip, inet_ntoa(*d), 19);
fprintf(fp, "ip { saddr: %s | daddr: %s | checksum: %u }\n",
srcip,
dstip,
ntohl(iph->check));
fprintf(fp, "eth { shost: %02x:%02x:%02x:%02x:%02x:%02x | "
"dhost: %02x:%02x:%02x:%02x:%02x:%02x }\n",
(int) ((unsigned char *) ethh->h_source)[0],
(int) ((unsigned char *) ethh->h_source)[1],
(int) ((unsigned char *) ethh->h_source)[2],
(int) ((unsigned char *) ethh->h_source)[3],
(int) ((unsigned char *) ethh->h_source)[4],
(int) ((unsigned char *) ethh->h_source)[5],
(int) ((unsigned char *) ethh->h_dest)[0],
(int) ((unsigned char *) ethh->h_dest)[1],
(int) ((unsigned char *) ethh->h_dest)[2],
(int) ((unsigned char *) ethh->h_dest)[3],
(int) ((unsigned char *) ethh->h_dest)[4],
(int) ((unsigned char *) ethh->h_dest)[5]);
fprintf_ip_header(fp, iph);
fprintf_eth_header(fp, ethh);
fprintf(fp, "------------------------------------------------------\n");
}

View File

@ -6,7 +6,6 @@
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
#include "packet.h"
#include <stdlib.h>
@ -36,6 +35,41 @@ void print_macaddr(struct ifreq* i)
(int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[5]);
}
void fprintf_ip_header(FILE *fp, struct iphdr *iph)
{
struct in_addr *s = (struct in_addr *) &(iph->saddr);
struct in_addr *d = (struct in_addr *) &(iph->daddr);
char srcip[20];
char dstip[20];
// inet_ntoa is a const char * so we if just call it in
// fprintf, you'll get back wrong results since we're
// calling it twice.
strncpy(srcip, inet_ntoa(*s), 19);
strncpy(dstip, inet_ntoa(*d), 19);
fprintf(fp, "ip { saddr: %s | daddr: %s | checksum: %u }\n",
srcip,
dstip,
ntohl(iph->check));
}
void fprintf_eth_header(FILE *fp, struct ethhdr *ethh)
{
fprintf(fp, "eth { shost: %02x:%02x:%02x:%02x:%02x:%02x | "
"dhost: %02x:%02x:%02x:%02x:%02x:%02x }\n",
(int) ((unsigned char *) ethh->h_source)[0],
(int) ((unsigned char *) ethh->h_source)[1],
(int) ((unsigned char *) ethh->h_source)[2],
(int) ((unsigned char *) ethh->h_source)[3],
(int) ((unsigned char *) ethh->h_source)[4],
(int) ((unsigned char *) ethh->h_source)[5],
(int) ((unsigned char *) ethh->h_dest)[0],
(int) ((unsigned char *) ethh->h_dest)[1],
(int) ((unsigned char *) ethh->h_dest)[2],
(int) ((unsigned char *) ethh->h_dest)[3],
(int) ((unsigned char *) ethh->h_dest)[4],
(int) ((unsigned char *) ethh->h_dest)[5]);
}
void make_eth_header(struct ethhdr *ethh, macaddr_t *src, macaddr_t *dst)
{
memcpy(ethh->h_source, src, ETH_ALEN);

View File

@ -31,7 +31,6 @@ probe_module_t* probe_modules[] = {
// 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++) {
@ -76,6 +75,8 @@ fielddef_t ip_fields[] = {
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."}
}
@ -87,9 +88,8 @@ void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip)
fs_add_uint64(fs, "ttl", ntohl(ip->ttl));
}
void fs_add_system_fields(fieldset_t *fs)
void fs_add_system_fields(fieldset_t *fs, int is_repeat, int in_cooldown)
{
}

View File

@ -37,12 +37,14 @@ typedef struct probe_module {
probe_classify_packet_cb process_packet;
probe_close_cb close;
fielddef_t *fields;
const char *helptext;
} probe_module_t;
probe_module_t* get_probe_module_by_name(const char*);
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);
#endif // HEADER_PROBE_MODULES_H

View File

@ -27,11 +27,13 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <assert.h>
#include "../lib/logger.h"
#include "state.h"
#include "validate.h"
#include "fieldset.h"
#include "probe_modules/probe_modules.h"
#include "output_modules/output_modules.h"
@ -92,9 +94,16 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
}
int is_repeat = check_ip(src_ip);
response_type_t *r = zconf.probe_module->classify_packet(bytes, buflen);
if (r->is_success) {
fieldset_t *fs = fs_new_fieldset();
fs_add_ip_fields(fs, ip_hdr);
zconf.probe_module->process_packet(bytes, buflen, fs);
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);
if (is_success) {
zrecv.success_total++;
if (!is_repeat) {
zrecv.success_unique++;
@ -106,19 +115,15 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
zrecv.cooldown_unique++;
}
}
if (zconf.output_module && zconf.output_module->success_ip) {
zconf.output_module->success_ip(
ip_hdr->saddr, ip_hdr->daddr,
r->name, is_repeat, zsend.complete, bytes, buflen);
}
} else {
zrecv.failure_total++;
if (zconf.output_module && zconf.output_module->other_ip) {
zconf.output_module->other_ip(
ip_hdr->saddr, ip_hdr->daddr,
r->name, is_repeat, zsend.complete, bytes, buflen);
}
}
//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);
//}
if (zconf.output_module && zconf.output_module->update
&& !(zrecv.success_unique % zconf.output_module->update_interval)) {

View File

@ -13,20 +13,26 @@
#include <netinet/ether.h>
#include <net/if.h>
#include "types.h"
#include "fieldset.h"
#ifndef _STATE_H
#define _STATE_H
#define MAX_PACKET_SIZE 4096
typedef uint32_t ipaddr_n_t; // IPv4 address network order
typedef uint32_t ipaddr_h_t; // IPv4 address host order
typedef uint16_t port_n_t; // port network order
typedef uint16_t port_h_t; // port host order
typedef unsigned char macaddr_t;
struct probe_module;
struct output_module;
struct fieldset_conf {
fielddefset_t defs;
int *translation;
int translation_len;
int success_index;
int classification_index;
};
// global configuration
struct state_conf {
int log_level;
@ -73,6 +79,7 @@ struct state_conf {
char *whitelist_filename;
char *raw_output_fields;
char **output_fields;
struct fieldset_conf fs_conf;
int output_fields_len;
int dryrun;
int summary;
@ -81,6 +88,7 @@ struct state_conf {
};
extern struct state_conf zconf;
// global sender stats
struct state_send {
double start;

View File

@ -367,6 +367,59 @@ int main(int argc, char *argv[])
if (cmdline_parser_required(&args, CMDLINE_PARSER_PACKAGE) != 0) {
exit(EXIT_FAILURE);
}
// parse the provided probe and output module s.t. that we can support
// other command-line helpers (e.g. probe help)
zconf.output_module = get_output_module_by_name(args.output_module_arg);
if (!zconf.output_module) {
fprintf(stderr, "%s: specified output module (%s) does not exist\n",
CMDLINE_PARSER_PACKAGE, args.output_module_arg);
exit(EXIT_FAILURE);
}
zconf.probe_module = get_probe_module_by_name(args.probe_module_arg);
if (!zconf.probe_module) {
fprintf(stderr, "%s: specified probe module (%s) does not exist\n",
CMDLINE_PARSER_PACKAGE, args.probe_module_arg);
exit(EXIT_FAILURE);
}
// now that we know the probe module, let's find what it supports
memset(zconf.fs_conf, 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));
// 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) {
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) {
log_fatal("fieldset", "probe module does not supply "
"required packet classification field.");
}
// process the list of requested output fields.
if (args.output_fields_given) {
zconf.raw_output_fields = args.output_fields_arg;
} else {
zconf.raw_output_fields = (char*) "saddr";
}
fs_split_string(args.output_fields_arg, &(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",
zconf.output_fields[i]);
}
// generate a translation that can be used to convert output
// from a probe module to the input for an output module
SET_IF_GIVEN(zconf.output_filename, output_file);
SET_IF_GIVEN(zconf.blacklist_filename, blacklist_file);
@ -385,36 +438,7 @@ int main(int argc, char *argv[])
zconf.senders = args.sender_threads_arg;
zconf.log_level = args.verbosity_arg;
zconf.output_module = get_output_module_by_name(args.output_module_arg);
if (!zconf.output_module) {
fprintf(stderr, "%s: specified output module (%s) does not exist\n",
CMDLINE_PARSER_PACKAGE, args.output_module_arg);
exit(EXIT_FAILURE);
}
zconf.probe_module = get_probe_module_by_name(args.probe_module_arg);
if (!zconf.probe_module) {
fprintf(stderr, "%s: specified probe module (%s) does not exist\n",
CMDLINE_PARSER_PACKAGE, args.probe_module_arg);
exit(EXIT_FAILURE);
}
// we need to generate a master fielddef list
// process the list of output fields.
if (args.output_fields_given) {
zconf.raw_output_fields = zopt.output_fields;
fs_split_string(zopt.output_fields, &(zconf.output_fields),
&(zconf.output_fields_len));
} else {
zconf.output_fields = {"saddr"};
zconf.num_output_fields = 1;
}
// check the list of requested fields to see if they are available
// with the selected probe module.
for (int i=0; i < zonf.num_output_fields; i++) {
fs_check
}
if (zconf.probe_module->port_args) {
if (args.source_port_given) {