From 952f6cefa16218b695ca6bc3d4f9ad1b1cefbaae Mon Sep 17 00:00:00 2001 From: Zakir Durumeric Date: Mon, 19 Aug 2013 04:42:25 -0400 Subject: [PATCH] building fieldset and probe modules --- src/Makefile | 2 +- src/fieldset.c | 53 ++---------------- src/fieldset.h | 77 ++++++++++++++++++++++++++ src/probe_modules/module_icmp_echo.c | 42 +++++++------- src/probe_modules/module_tcp_synscan.c | 45 ++++----------- src/probe_modules/probe_modules.c | 35 ++++++++++++ src/probe_modules/probe_modules.h | 11 ++-- 7 files changed, 159 insertions(+), 106 deletions(-) diff --git a/src/Makefile b/src/Makefile index 72eb0d5..eeffc0b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,7 +35,7 @@ LDFLAGS+=$(EXTRALDFLAGS) modules=module_tcp_synscan.o module_icmp_echo.o module_udp.o #ADD YOUR 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 +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 ifeq ($(REDIS), true) LDLIBS+=-lhiredis diff --git a/src/fieldset.c b/src/fieldset.c index b83303d..7c0de51 100644 --- a/src/fieldset.c +++ b/src/fieldset.c @@ -7,55 +7,12 @@ #include "../lib/logger.h" -// maximum number of records that can be stored in a fieldset -#define MAX_FIELDS 128 - -// types of data that can be stored in a field -#define FS_STRING 0 -#define FS_UINT64 1 -#define FS_BINARY 2 - -// definition of a field that's provided by a probe module -// these are used so that users can ask at the command-line -// what fields are available for consumption -typedef struct field_def { - const char *name; - const char *type; - const char *desc; -} field_def_t; - -// the internal field type used by fieldset -typedef struct field { - const char *name; - int type; - int free_; - size_t len; - void *value; -} field_t; - -// data structure that is populated by the probe module -// and translated into the data structure that's passed -// to the output module -typedef struct fieldset { - int len; - field_t fields[MAX_FIELDS]; -} fieldset_t; - -// we pass a different fieldset to an output module than -// the probe module generates for us because a user may -// only want certain fields and will expect them in a certain -// order. We generate a translated fieldset that contains -// only the fields we want to export to the output module. -// a translation specifies how to efficiently convert the fs -// povided by the probe module to the fs for the output module. -typedef struct translation { - int len; - int translation[MAX_FIELDS]; -} translation_t; int fs_split_string(int *len, char**results) { - + (void)len; + (void)results; + return 0; } fieldset_t *fs_new_fieldset(void) @@ -112,7 +69,7 @@ void fs_free(fieldset_t *fs) translation_t *fs_generate_fieldset_translation() { - + return NULL; } fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t) @@ -126,4 +83,6 @@ fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t) memcpy(&(retv->fields[i]), &(fs->fields[o]), sizeof(field_t)); } retv->len = t->len; + return retv; } + diff --git a/src/fieldset.h b/src/fieldset.h index e69de29..5c47990 100644 --- a/src/fieldset.h +++ b/src/fieldset.h @@ -0,0 +1,77 @@ +/* + * 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 + +#ifndef _FIELDSET_H +#define _FIELDSET_H + +// maximum number of records that can be stored in a fieldset +#define MAX_FIELDS 128 + +// types of data that can be stored in a field +#define FS_STRING 0 +#define FS_UINT64 1 +#define FS_BINARY 2 + +// definition of a field that's provided by a probe module +// these are used so that users can ask at the command-line +// what fields are available for consumption +typedef struct field_def { + const char *name; + const char *type; + const char *desc; +} fielddef_t; + +// the internal field type used by fieldset +typedef struct field { + const char *name; + int type; + int free_; + size_t len; + void *value; +} field_t; + +// data structure that is populated by the probe module +// and translated into the data structure that's passed +// to the output module +typedef struct fieldset { + int len; + field_t fields[MAX_FIELDS]; +} fieldset_t; + +// we pass a different fieldset to an output module than +// the probe module generates for us because a user may +// only want certain fields and will expect them in a certain +// order. We generate a translated fieldset that contains +// only the fields we want to export to the output module. +// a translation specifies how to efficiently convert the fs +// povided by the probe module to the fs for the output module. +typedef struct translation { + int len; + int translation[MAX_FIELDS]; +} translation_t; + + +fieldset_t *fs_new_fieldset(void); + +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_); + +void fs_add_binary(fieldset_t *fs, const char *name, size_t len, + void *value, int free_); + +void fs_free(fieldset_t *fs); + +translation_t *fs_generate_fieldset_translation(); + +fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t); + +#endif diff --git a/src/probe_modules/module_icmp_echo.c b/src/probe_modules/module_icmp_echo.c index be12eb3..50907ad 100644 --- a/src/probe_modules/module_icmp_echo.c +++ b/src/probe_modules/module_icmp_echo.c @@ -158,38 +158,46 @@ int icmp_validate_packet(const struct iphdr *ip_hdr, } void icmp_echo_process_packet(const u_char *packet, - __attribute__((unused)) uint32_t len, fieldset *fs) + __attribute__((unused)) uint32_t len, fieldset_t *fs) { struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)]; - struct icmp *icmp_hdr = (struct icmp*)((char *)ip_hdr - + sizeof(struct iphdr)); - + struct icmphdr *icmp_hdr = (struct icmphdr*)((char *)ip_hdr + 4 *ip_hdr->ihl); fs_add_uint64(fs, "type", ntohs(icmp_hdr->type)); fs_add_uint64(fs, "code", ntohs(icmp_hdr->code)); fs_add_uint64(fs, "icmp-id", ntohs(icmp_hdr->un.echo.id)); fs_add_uint64(fs, "seq", ntohs(icmp_hdr->un.echo.sequence)); - switch (icmp_hdr->icmp_type) { + switch (icmp_hdr->type) { case ICMP_ECHOREPLY: - fs_add_string(fs, "classification", "echoreply", 0); + fs_add_string(fs, "classification", (char*) "echoreply", 0); fs_add_uint64(fs, "success", 1); case ICMP_UNREACH: - fs_add_string(fs, "classification", "unreach", 0); + fs_add_string(fs, "classification", (char*) "unreach", 0); fs_add_uint64(fs, "success", 0); case ICMP_SOURCEQUENCH: - fs_add_string(fs, "classification", "sourcequench", 0); + fs_add_string(fs, "classification", (char*) "sourcequench", 0); fs_add_uint64(fs, "success", 0); case ICMP_REDIRECT: - fs_add_string(fs, "classification", "redirect", 0); + fs_add_string(fs, "classification", (char*) "redirect", 0); fs_add_uint64(fs, "success", 0); case ICMP_TIMXCEED: - fs_add_string(fs, "classification", "timxceed", 0); + fs_add_string(fs, "classification", (char*) "timxceed", 0); fs_add_uint64(fs, "success", 0); default: - fs_add_string(fs, "classification", "other", 0); + fs_add_string(fs, "classification", (char*) "other", 0); fs_add_uint64(fs, "success", 0); } } +fielddef_t fields[] = { + {.name="type", .type="int", .desc="icmp message type"}, + {.name="code", .type="int", .desc="icmp message sub type code"}, + {.name="icmp-id", .type="int", .desc="icmp id number"}, + {.name="seq", .type="int", .desc="icmp sequence number"}, + {.name="classification", .type="string", .desc="probe module classification"}, + {.name="success", .type="int", .desc="did probe module classify response as success"} +}; + + probe_module_t module_icmp_echo = { .name = "icmp_echoscan", .packet_length = 62, @@ -199,16 +207,8 @@ probe_module_t module_icmp_echo = { .thread_initialize = &icmp_echo_init_perthread, .make_packet = &icmp_echo_make_packet, .print_packet = &icmp_echo_print_packet, - .process_response = &icmp_echo_process_response, + .process_packet = &icmp_echo_process_packet, .validate_packet = &icmp_validate_packet, .close = NULL, - .fields = { - {.name "type", .type="int", .desc="icmp message type"}, - {.name "code", .type="int", .desc="icmp message sub type code"}, - {.name "icmp-id", .type="int", .desc="icmp id number"}, - {.name "seq", .type="int", .desc="icmp sequence number"}, - {.name="classification", .type="string", .desc="probe module classification"}, - {.name="success", .type="int", .desc="did probe module classify response as success"} - } -}; + .fields = fields}; diff --git a/src/probe_modules/module_tcp_synscan.c b/src/probe_modules/module_tcp_synscan.c index 24da7c2..448a678 100644 --- a/src/probe_modules/module_tcp_synscan.c +++ b/src/probe_modules/module_tcp_synscan.c @@ -149,29 +149,7 @@ int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len, return 1; } -void fs_add_sys_fields(fieldset_t *fs) -{ -} - -char *make_ip_str(uint32_t ip) -{ - struct in_addr t; - t.saddr = ip; - const char *temp = inet_ntoa(t); - char *retv = malloc(strlen(temp)+1); - assert (retv); - strcpy(retv, temp); - return retv; -} - -void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip) -{ - fs_add_string(fs, "saddr", make_ip_str(ip->saddr), 1); - fs_add_string(fs, "daddr", make_ip_str(ip->daddr), 1); - fs_add_uint64(fs, "ipid", ntohl(ip->id); - fs_add_uint64(fs, "ttl", ntohl(ip->ttl); -} void synscan_process_packet(const u_char *packet, __attribute__((unused)) uint32_t len, fieldset_t *fs) @@ -187,15 +165,23 @@ void synscan_process_packet(const u_char *packet, fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->window)); if (tcp->rst) { // RST packet - fs_add_string(fs, "classification", "rst", 0); + fs_add_string(fs, "classification", (char*) "rst", 0); fs_add_uint64(fs, "success", 0); } else { // SYNACK packet - fs_add_string(fs, "classification", "synack", 0); + fs_add_string(fs, "classification", (char*) "synack", 0); fs_add_uint64(fs, "success", 1); } - return } +static fielddef_t fields[] = { + {.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"}, +}; + + probe_module_t module_tcp_synscan = { .name = "tcp_synscan", .packet_length = 54, @@ -209,12 +195,5 @@ probe_module_t module_tcp_synscan = { .process_packet = &synscan_process_packet, .validate_packet = &synscan_validate_packet, .close = NULL, - .fields = { - {.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"}, - } -}; + .fields = fields}; diff --git a/src/probe_modules/probe_modules.c b/src/probe_modules/probe_modules.c index f67e831..de3c618 100644 --- a/src/probe_modules/probe_modules.c +++ b/src/probe_modules/probe_modules.c @@ -8,7 +8,15 @@ #include #include +#include +#include +#include +#include +#include +#include + +#include "../fieldset.h" #include "probe_modules.h" extern probe_module_t module_tcp_synscan; @@ -40,3 +48,30 @@ void print_probe_modules(void) 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; + t.s_addr = ip; + const char *temp = inet_ntoa(t); + char *retv = malloc(strlen(temp)+1); + assert (retv); + strcpy(retv, temp); + return retv; +} + +void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip) +{ + fs_add_string(fs, "saddr", make_ip_str(ip->saddr), 1); + fs_add_string(fs, "daddr", make_ip_str(ip->daddr), 1); + fs_add_uint64(fs, "ipid", ntohl(ip->id)); + fs_add_uint64(fs, "ttl", ntohl(ip->ttl)); +} + diff --git a/src/probe_modules/probe_modules.h b/src/probe_modules/probe_modules.h index 18f8438..613c1e2 100644 --- a/src/probe_modules/probe_modules.h +++ b/src/probe_modules/probe_modules.h @@ -1,4 +1,5 @@ #include "../state.h" +#include "../fieldset.h" #ifndef HEADER_PROBE_MODULES_H #define HEADER_PROBE_MODULES_H @@ -14,9 +15,10 @@ typedef int (*probe_make_packet_cb)(void* packetbuf, ipaddr_n_t src_ip, ipaddr_n 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 response_type_t* (*probe_classify_packet_cb)(const u_char* packetbuf, uint32_t len); 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; size_t packet_length; @@ -27,19 +29,20 @@ typedef struct probe_module { // source and target port numbers? uint8_t port_args; - response_type_t *responses; - probe_global_init_cb global_initialize; probe_thread_init_cb thread_initialize; probe_make_packet_cb make_packet; probe_print_packet_cb print_packet; probe_validate_packet_cb validate_packet; - probe_classify_packet_cb classify_packet; + probe_classify_packet_cb process_packet; probe_close_cb close; + fielddef_t *fields; + } probe_module_t; probe_module_t* get_probe_module_by_name(const char*); + void print_probe_modules(void); #endif // HEADER_PROBE_MODULES_H