* [ulogd PATCH 0/8] make progress ulogd_output_IPFIX @ 2014-03-08 1:03 Ken-ichirou MATSUZAWA 2014-03-08 1:07 ` [PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA ` (10 more replies) 0 siblings, 11 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:03 UTC (permalink / raw) To: The netfilter developer mailinglist Hello, If there is someone who is working on ulogd_output_IPFIX, please let me know. I need it and would work on it. This patch series make progress, not work completely, just print IPFIX packet format. Would you review this? I think this has four issues. * Install nfct_bitmask in libnetfilter_conntrack This needs libnetfilter_conntrack patch I'll send after. * Send only one dataset, not multiple at once And it (will) send a message each time when output_ipfix() is called. It's not efficient sending. * No options template and data Do we need these scope data? 4. Specific Reporting Requiremt in RFC7011, says MAY be implemented * Template retransmit timing It send template per messages specified in config file. I took a glance softflowd and follow that. Thanks. ^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 1/8] ipfix: use nfct_bitmask 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA @ 2014-03-08 1:07 ` Ken-ichirou MATSUZAWA 2014-03-23 18:55 ` Eric Leblond 2014-03-08 1:09 ` [PATCH 2/8] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA ` (9 subsequent siblings) 10 siblings, 1 reply; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:07 UTC (permalink / raw) To: The netfilter developer mailinglist from libnetfilter_conntrack instead of original --- output/Makefile.am | 6 ++- output/ulogd_output_IPFIX.c | 107 ++++++-------------------------------------- 2 files changed, 18 insertions(+), 95 deletions(-) diff --git a/output/Makefile.am b/output/Makefile.am index ff851ad..92f1233 100644 --- a/output/Makefile.am +++ b/output/Makefile.am @@ -7,7 +7,7 @@ SUBDIRS= pcap mysql pgsql sqlite3 dbi pkglib_LTLIBRARIES = ulogd_output_LOGEMU.la ulogd_output_SYSLOG.la \ ulogd_output_OPRINT.la ulogd_output_GPRINT.la \ ulogd_output_NACCT.la ulogd_output_XML.la \ - ulogd_output_GRAPHITE.la + ulogd_output_GRAPHITE.la ulogd_output_IPFIX.la if HAVE_JANSSON pkglib_LTLIBRARIES += ulogd_output_JSON.la @@ -42,3 +42,7 @@ ulogd_output_JSON_la_SOURCES = ulogd_output_JSON.c ulogd_output_JSON_la_LIBADD = ${libjansson_LIBS} ulogd_output_JSON_la_LDFLAGS = -avoid-version -module endif + +ulogd_output_IPFIX_la_SOURCES = ulogd_output_IPFIX.c +ulogd_output_IPFIX_la_LDFLAGS = -avoid-version -module +ulogd_output_IPFIX_la_LIBADD = ${LIBNETFILTER_CONNTRACK_LIBS} diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 761d272..01ac9a0 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -36,6 +36,8 @@ #include <sys/socket.h> #include <netdb.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + #include <ulogd/linuxlist.h> #ifdef IPPROTO_SCTP @@ -68,89 +70,6 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 -/* bitmask stuff */ -struct bitmask { - int size_bits; - char *buf; -}; - -#define SIZE_OCTETS(x) ((x/8)+1) - -void bitmask_clear(struct bitmask *bm) -{ - memset(bm->buf, 0, SIZE_OCTETS(bm->size_bits)); -} - -struct bitmask *bitmask_alloc(unsigned int num_bits) -{ - struct bitmask *bm; - unsigned int size_octets = SIZE_OCTETS(num_bits); - - bm = malloc(sizeof(*bm) + size_octets); - if (!bm) - return NULL; - - bm->size_bits = num_bits; - bm->buf = (void *)bm + sizeof(*bm); - - bitmask_clear(bm); - - return bm; -} - -void bitmask_free(struct bitmask *bm) -{ - free(bm); -} - -int bitmask_set_bit_to(struct bitmask *bm, unsigned int bits, int to) -{ - unsigned int byte = bits / 8; - unsigned int bit = bits % 8; - unsigned char *ptr; - - if (byte > SIZE_OCTETS(bm->size_bits)) - return -EINVAL; - - if (to == 0) - bm->buf[byte] &= ~(1 << bit); - else - bm->buf[byte] |= (1 << bit); - - return 0; -} - -#define bitmask_clear_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 0) - -#define bitmask_set_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 1) - -int bitmasks_equal(const struct bitmask *bm1, const struct bitmask *bm2) -{ - if (bm1->size_bits != bm2->size_bits) - return -1; - - if (!memcmp(bm1->buf, bm2->buf, SIZE_OCTETS(bm1->size_bits))) - return 1; - else - return 0; -} - -struct bitmask *bitmask_dup(const struct bitmask *bm_orig) -{ - struct bitmask *bm_new; - int size = sizeof(*bm_new) + SIZE_OCTETS(bm_orig->size_bits); - - bm_new = malloc(size); - if (!bm_new) - return NULL; - - memcpy(bm_new, bm_orig, size); - - return bm_new; -} - static struct config_keyset ipfix_kset = { .num_ces = 3, .ces = { @@ -185,7 +104,7 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; - struct bitmask *bitmask; + struct nfct_bitmask *bitmask; unsigned int total_length; /* length of the DATA */ char *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; @@ -201,7 +120,7 @@ struct ipfix_instance { struct ipfix_template *tmpl; unsigned int tmpl_len; - struct bitmask *valid_bitmask; /* bitmask of valid keys */ + struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ unsigned int total_length; /* total size of all data elements */ }; @@ -212,7 +131,7 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ipfix_templ_rec_hdr *rhdr; @@ -226,7 +145,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; memset(tmpl, 0, size); - tmpl->bitmask = bitmask_dup(bm); + tmpl->bitmask = nfct_bitmask_clone(bm); if (!tmpl->bitmask) { free(tmpl); return NULL; @@ -288,14 +207,14 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *tmpl; /* FIXME: this can be done more efficient! */ llist_for_each_entry(tmpl, &ii->template_list, list) { - if (bitmasks_equal(bm, tmpl->bitmask)) + if (nfct_bitmask_equal(bm, tmpl->bitmask)) return tmpl; } return NULL; @@ -313,13 +232,13 @@ static int output_ipfix(struct ulogd_pluginstance *upi) * ulogd core could very easily flush it after every packet, * too. */ - bitmask_clear(ii->valid_bitmask); + nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = upi->input.keys[i].u.source; if (key->flags & ULOGD_RETF_VALID) - bitmask_set_bit(ii->valid_bitmask, i); + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -430,7 +349,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) ulogd_log(ULOGD_DEBUG, "starting ipfix\n"); - ii->valid_bitmask = bitmask_alloc(pi->input.num_keys); + ii->valid_bitmask = nfct_bitmask_new(pi->input.num_keys); if (!ii->valid_bitmask) return -ENOMEM; @@ -443,7 +362,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) return 0; out_bm_free: - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return ret; @@ -455,7 +374,7 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) close(ii->fd); - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return 0; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH 1/8] ipfix: use nfct_bitmask 2014-03-08 1:07 ` [PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA @ 2014-03-23 18:55 ` Eric Leblond 0 siblings, 0 replies; 45+ messages in thread From: Eric Leblond @ 2014-03-23 18:55 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Hi, On Sat, 2014-03-08 at 10:07 +0900, Ken-ichirou MATSUZAWA wrote: > from libnetfilter_conntrack instead of original > --- > output/Makefile.am | 6 ++- > output/ulogd_output_IPFIX.c | 107 ++++++-------------------------------------- > 2 files changed, 18 insertions(+), 95 deletions(-) > > diff --git a/output/Makefile.am b/output/Makefile.am > index ff851ad..92f1233 100644 > --- a/output/Makefile.am > +++ b/output/Makefile.am > @@ -7,7 +7,7 @@ SUBDIRS= pcap mysql pgsql sqlite3 dbi > pkglib_LTLIBRARIES = ulogd_output_LOGEMU.la ulogd_output_SYSLOG.la \ > ulogd_output_OPRINT.la ulogd_output_GPRINT.la \ > ulogd_output_NACCT.la ulogd_output_XML.la \ > - ulogd_output_GRAPHITE.la > + ulogd_output_GRAPHITE.la ulogd_output_IPFIX.la > > if HAVE_JANSSON > pkglib_LTLIBRARIES += ulogd_output_JSON.la > @@ -42,3 +42,7 @@ ulogd_output_JSON_la_SOURCES = ulogd_output_JSON.c > ulogd_output_JSON_la_LIBADD = ${libjansson_LIBS} > ulogd_output_JSON_la_LDFLAGS = -avoid-version -module > endif > + > +ulogd_output_IPFIX_la_SOURCES = ulogd_output_IPFIX.c > +ulogd_output_IPFIX_la_LDFLAGS = -avoid-version -module > +ulogd_output_IPFIX_la_LIBADD = ${LIBNETFILTER_CONNTRACK_LIBS} > diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c > index 761d272..01ac9a0 100644 > --- a/output/ulogd_output_IPFIX.c > +++ b/output/ulogd_output_IPFIX.c > @@ -36,6 +36,8 @@ > #include <sys/socket.h> > #include <netdb.h> > > +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> This means that your code is dependant of libnetfilter_conntrack being available on the system. As it is possible to build ulogd with --disable-nfct configure flags, you need to make the build of IPFIX conditional to the use of NFCT. By the way providing a message at the end of configure run to indicate if IPFIX module is built would be really nice (see echo call at end of configure.ac). BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 2/8] ipfix: fix enterprise bit handling 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA 2014-03-08 1:07 ` [PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA @ 2014-03-08 1:09 ` Ken-ichirou MATSUZAWA 2014-03-08 1:10 ` [PATCH 3/8] ipfix: some cleanups Ken-ichirou MATSUZAWA ` (8 subsequent siblings) 10 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:09 UTC (permalink / raw) To: The netfilter developer mailinglist If this bit is zero, the Information Element identifier identifies an Information Element in IANA-IPFIX, and the four-octet Enterprise Number field MUST NOT be present. --- output/ulogd_output_IPFIX.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 01ac9a0..333d532 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -182,15 +182,15 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, struct ipfix_ietf_field *field = (struct ipfix_ietf_field *) tmpl->tmpl_cur; - field->type = htons(key->ipfix.field_id | 0x8000000); + field->type = htons(key->ipfix.field_id); field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } else { struct ipfix_vendor_field *field = (struct ipfix_vendor_field *) tmpl->tmpl_cur; + field->type = htons(key->ipfix.field_id | 0x8000); field->enterprise_num = htonl(key->ipfix.vendor); - field->type = htons(key->ipfix.field_id); field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 3/8] ipfix: some cleanups 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA 2014-03-08 1:07 ` [PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-03-08 1:09 ` [PATCH 2/8] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA @ 2014-03-08 1:10 ` Ken-ichirou MATSUZAWA 2014-03-08 1:12 ` [PATCH 4/8] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA ` (7 subsequent siblings) 10 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:10 UTC (permalink / raw) To: The netfilter developer mailinglist remove unused variables. use unsigned int to supress gcc warning. change struct field name from total_length to data_length. make same bitmask key. change tmpl_cur to void * to calc size. --- output/ulogd_output_IPFIX.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 333d532..7ba8712 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -105,8 +105,8 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; struct nfct_bitmask *bitmask; - unsigned int total_length; /* length of the DATA */ - char *tmpl_cur; /* cursor into current template position */ + unsigned int data_length; /* length of the DATA */ + void *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; }; @@ -116,13 +116,7 @@ struct ipfix_instance { int sock_proto; /* protocol (IPPROTO_*) */ struct llist_head template_list; - - struct ipfix_template *tmpl; - unsigned int tmpl_len; - struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ - - unsigned int total_length; /* total size of all data elements */ }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -133,8 +127,6 @@ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) { - struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; - struct ipfix_templ_rec_hdr *rhdr; struct ulogd_ipfix_template *tmpl; unsigned int i, j; int size = sizeof(struct ulogd_ipfix_template) @@ -156,7 +148,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, tmpl->tmpl_cur = tmpl->tmpl.buf; - tmpl->total_length = 0; + tmpl->data_length = 0; for (i = 0, j = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; @@ -194,7 +186,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } - tmpl->total_length += length; + tmpl->data_length += length; j++; } @@ -224,8 +216,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; - unsigned int total_size; - int i; + unsigned int total_size, i; /* FIXME: it would be more cache efficient if the IS_VALID * flags would be a separate bitmask outside of the array. @@ -235,10 +226,17 @@ static int output_ipfix(struct ulogd_pluginstance *upi) nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { - struct ulogd_key *key = upi->input.keys[i].u.source; + struct ulogd_key *key = &upi->input.keys[i]; + int length = ulogd_key_size(key); - if (key->flags & ULOGD_RETF_VALID) - nfct_bitmask_set_bit(ii->valid_bitmask, i); + if (length < 0 || length > 0xfffe) + continue; + if (!(key->u.source->flags & ULOGD_RETF_VALID)) + continue; + if (key->ipfix.field_id == 0) + continue; + + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -253,7 +251,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) llist_add(&template->list, &ii->template_list); } - total_size = template->total_length; + total_size = template->data_length; /* decide if it's time to retransmit our template and (optionally) * prepend it into the to-be-sent IPFIX message */ @@ -382,8 +380,6 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) static void signal_handler_ipfix(struct ulogd_pluginstance *pi, int signal) { - struct ipfix_instance *li = (struct ipfix_instance *) &pi->private; - switch (signal) { case SIGHUP: ulogd_log(ULOGD_NOTICE, "ipfix: reopening connection\n"); -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 4/8] ipfix: add functions for ipfix dataset creation 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (2 preceding siblings ...) 2014-03-08 1:10 ` [PATCH 3/8] ipfix: some cleanups Ken-ichirou MATSUZAWA @ 2014-03-08 1:12 ` Ken-ichirou MATSUZAWA 2014-03-08 1:13 ` [PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA ` (6 subsequent siblings) 10 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:12 UTC (permalink / raw) To: The netfilter developer mailinglist ulogd_key_putn() put key's value in network byteorder. put_data_records() creates ipfix data records buffer. --- output/ulogd_output_IPFIX.c | 84 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 7ba8712..16cae74 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -63,6 +63,19 @@ struct sctp_sndrcvinfo { }; #endif +#include <byteswap.h> +#if __BYTE_ORDER == __BIG_ENDIAN +# ifndef __be64_to_cpu +# define __be64_to_cpu(x) (x) +# endif +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# ifndef __be64_to_cpu +# define __be64_to_cpu(x) __bswap_64(x) +# endif +# endif +#endif + #include <ulogd/ulogd.h> #include <ulogd/conffile.h> #include <ulogd/linuxlist.h> @@ -195,8 +208,6 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return tmpl; } - - static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) @@ -212,6 +223,75 @@ find_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; } +static int ulogd_key_putn(struct ulogd_key *key, void *buf) +{ + int ret; + + switch (key->type) { + case ULOGD_RET_INT8: + case ULOGD_RET_UINT8: + case ULOGD_RET_BOOL: + *(u_int8_t *)buf = ikey_get_u8(key); + ret = 1; + break; + case ULOGD_RET_INT16: + case ULOGD_RET_UINT16: + *(u_int16_t *)buf = htons(ikey_get_u16(key)); + ret = 2; + break; + case ULOGD_RET_INT32: + case ULOGD_RET_UINT32: + case ULOGD_RET_IPADDR: + *(u_int32_t *)buf = htonl(ikey_get_u32(key)); + ret = 4; + break; + case ULOGD_RET_INT64: + case ULOGD_RET_UINT64: + *(u_int64_t *)buf = __be64_to_cpu(ikey_get_u64(key)); + ret = 8; + break; + case ULOGD_RET_IP6ADDR: + memcpy(buf, ikey_get_u128(key), 16); + ret = 16; + break; + case ULOGD_RET_STRING: + ret = strlen(key->u.value.ptr); + memcpy(buf, key->u.value.ptr, ret); + break; + case ULOGD_RET_RAW: + ulogd_log(ULOGD_NOTICE, "put raw data in network byte order " + "`%s' type 0x%x\n", key->name, key->type); + ret = key->len; + memcpy(buf, key->u.value.ptr, ret); + break; + default: + ulogd_log(ULOGD_ERROR, "don't know sizeof unknown key " + "`%s' type 0x%x\n", key->name, key->type); + ret = -1; + break; + } + + return ret; +} + +static int put_data_records(struct ulogd_pluginstance *upi, + struct ulogd_ipfix_template *tmpl, void *buf) +{ + int ret; + unsigned int i, len = 0; + + for (i = 0; i < upi->input.num_keys; i++) { + if (!nfct_bitmask_test_bit(tmpl->bitmask, i)) + continue; + ret = ulogd_key_putn(&upi->input.keys[i], buf + len); + if (ret < 0) + return ret; + len += ret; + } + + return len; +} + static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 5/8] ipfix: add function for ipfix message creation 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (3 preceding siblings ...) 2014-03-08 1:12 ` [PATCH 4/8] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA @ 2014-03-08 1:13 ` Ken-ichirou MATSUZAWA 2014-03-23 20:06 ` Eric Leblond 2014-03-08 1:15 ` [PATCH 6/8] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA ` (5 subsequent siblings) 10 siblings, 1 reply; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:13 UTC (permalink / raw) To: The netfilter developer mailinglist This function creates ipfix message, template and data part but not scope. Header sequence is kept by struct ipfix_instance, domain id is specified by config file. The returned value has no export time so caller set this and free the value after using it. --- include/ulogd/ipfix_protocol.h | 8 ++++- output/ulogd_output_IPFIX.c | 71 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/include/ulogd/ipfix_protocol.h b/include/ulogd/ipfix_protocol.h index 5d7e46a..266897e 100644 --- a/include/ulogd/ipfix_protocol.h +++ b/include/ulogd/ipfix_protocol.h @@ -15,7 +15,13 @@ struct ipfix_msg_hdr { u_int16_t length; u_int32_t export_time; u_int32_t seq; - u_int32_t source_id; + u_int32_t domain_id; +}; + +/* Section 3.3.2 */ +struct ipfix_set_hdr { + u_int16_t set_id; + u_int16_t length; }; /* Section 3.4.1 */ diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 16cae74..c950fe2 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <unistd.h> #include <string.h> #include <errno.h> @@ -84,7 +85,7 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 static struct config_keyset ipfix_kset = { - .num_ces = 3, + .num_ces = 4, .ces = { { .key = "host", @@ -103,12 +104,19 @@ static struct config_keyset ipfix_kset = { .options = CONFIG_OPT_NONE, .u = { .string = "udp" }, }, + { + .key = "domain_id", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 0, + }, }, }; #define host_ce(x) (x->ces[0]) #define port_ce(x) (x->ces[1]) #define proto_ce(x) (x->ces[2]) +#define domain_ce(x) (x->ces[3]) struct ipfix_template { struct ipfix_templ_rec_hdr hdr; @@ -130,6 +138,7 @@ struct ipfix_instance { struct llist_head template_list; struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ + u_int32_t seq; }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -292,6 +301,66 @@ static int put_data_records(struct ulogd_pluginstance *upi, return len; } +static struct ipfix_msg_hdr *build_ipfix_msg(struct ulogd_pluginstance *upi, + struct ulogd_ipfix_template *template, + bool need_template) +{ + struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; + u_int16_t tmpl_len; + struct ipfix_msg_hdr *msg_hdr; + struct ipfix_templ_rec_hdr *tmpl_hdr; + struct ipfix_set_hdr *data_hdr, *tmpl_set_hdr; + void *buf; + int msglen, ret; + + msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) + + template->data_length; + if (need_template) + msglen = msglen + sizeof(struct ipfix_set_hdr) + + (template->tmpl_cur - (void *)&template->tmpl); + buf = malloc(msglen); + if (buf == NULL) + return NULL; + memset(buf, 0, msglen); + + /* ipfix msg header */ + msg_hdr = buf; + msg_hdr->version = htons(10); + msg_hdr->length = htons(msglen); + msg_hdr->seq = htonl(ii->seq++); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + if (need_template) { + /* put set header and template records */ + tmpl_set_hdr = buf + sizeof(*msg_hdr); + tmpl_set_hdr->set_id = htons(2); + tmpl_len = template->tmpl_cur - (void *)&template->tmpl; + tmpl_set_hdr->length = htons(sizeof(*tmpl_set_hdr) + tmpl_len); + tmpl_hdr = (void *)tmpl_set_hdr + sizeof(*tmpl_set_hdr); + memcpy((void *)tmpl_hdr, (void *)&template->tmpl, tmpl_len); + data_hdr = (void *)tmpl_hdr + tmpl_len; + } else { + data_hdr = buf + sizeof(*msg_hdr); + } + + /* put set header and data records */ + data_hdr->set_id = template->tmpl.hdr.templ_id; /* already ordered */ + data_hdr->length = htons(sizeof(*data_hdr) + template->data_length); + ret = put_data_records(upi, template, (void *)data_hdr + sizeof(*data_hdr)); + if (ret < 0) { + ulogd_log(ULOGD_ERROR, "could not build ipfix dataset"); + goto free_buf; + } else if (ret > msglen) { + ulogd_log(ULOGD_ERROR, "overflowed on building ipfix dataset"); + goto free_buf; + } + + return msg_hdr; + +free_buf: + free(buf); + return NULL; +} + static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH 5/8] ipfix: add function for ipfix message creation 2014-03-08 1:13 ` [PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA @ 2014-03-23 20:06 ` Eric Leblond 0 siblings, 0 replies; 45+ messages in thread From: Eric Leblond @ 2014-03-23 20:06 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Hello, On Sat, 2014-03-08 at 10:13 +0900, Ken-ichirou MATSUZAWA wrote: > This function creates ipfix message, template and data part but not scope. > Header sequence is kept by struct ipfix_instance, domain id is specified > by config file. The returned value has no export time so caller set this > and free the value after using it. > > --- > include/ulogd/ipfix_protocol.h | 8 ++++- > output/ulogd_output_IPFIX.c | 71 +++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 77 insertions(+), 2 deletions(-) > > diff --git a/include/ulogd/ipfix_protocol.h b/include/ulogd/ipfix_protocol.h > index 5d7e46a..266897e 100644 > --- a/include/ulogd/ipfix_protocol.h > +++ b/include/ulogd/ipfix_protocol.h > @@ -15,7 +15,13 @@ struct ipfix_msg_hdr { ... > + > + msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) > + + template->data_length; > + if (need_template) > + msglen = msglen + sizeof(struct ipfix_set_hdr) > + + (template->tmpl_cur - (void *)&template->tmpl); > + buf = malloc(msglen); I don't like this malloc because ulogd will do an allocation for each messages. If the size of the message has a global limit (looks like it should be the case) it is possible to use a buffer attached to the ulogd instance and to write the message in this buffer. BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 6/8] ipfix: decide whether prepending template by send times 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (4 preceding siblings ...) 2014-03-08 1:13 ` [PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA @ 2014-03-08 1:15 ` Ken-ichirou MATSUZAWA 2014-03-08 1:17 ` [PATCH 7/8] ipfix: print ipfix message Ken-ichirou MATSUZAWA ` (4 subsequent siblings) 10 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:15 UTC (permalink / raw) To: The netfilter developer mailinglist specified in config file and kept it until_template in struct ulogd_ipfix_template --- output/ulogd_output_IPFIX.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index c950fe2..92db5c0 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -85,7 +85,7 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 static struct config_keyset ipfix_kset = { - .num_ces = 4, + .num_ces = 5, .ces = { { .key = "host", @@ -110,6 +110,12 @@ static struct config_keyset ipfix_kset = { .options = CONFIG_OPT_NONE, .u.value = 0, }, + { + .key = "send_template_per", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 16, + }, }, }; @@ -117,6 +123,7 @@ static struct config_keyset ipfix_kset = { #define port_ce(x) (x->ces[1]) #define proto_ce(x) (x->ces[2]) #define domain_ce(x) (x->ces[3]) +#define template_per_ce(x) (x->ces[4]) struct ipfix_template { struct ipfix_templ_rec_hdr hdr; @@ -129,6 +136,7 @@ struct ulogd_ipfix_template { unsigned int data_length; /* length of the DATA */ void *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; + int until_template; /* decide if it's time to retransmit our template */ }; struct ipfix_instance { @@ -171,6 +179,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, tmpl->tmpl_cur = tmpl->tmpl.buf; tmpl->data_length = 0; + tmpl->until_template = template_per_ce(upi->config_kset).u.value; for (i = 0, j = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; @@ -365,7 +374,8 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; - unsigned int total_size, i; + unsigned int i; + bool need_template = false; /* FIXME: it would be more cache efficient if the IS_VALID * flags would be a separate bitmask outside of the array. @@ -398,16 +408,12 @@ static int output_ipfix(struct ulogd_pluginstance *upi) return ULOGD_IRET_ERR; } llist_add(&template->list, &ii->template_list); + need_template = true; } - total_size = template->data_length; - - /* decide if it's time to retransmit our template and (optionally) - * prepend it into the to-be-sent IPFIX message */ - if (0 /* FIXME */) { - /* add size of template */ - //total_size += (template->tmpl_cur - (void *)&template->tmpl); - total_size += sizeof(template->tmpl); + if (template->until_template-- == 0) { + need_template = true; + template->until_template = template_per_ce(upi->config_kset).u.value; } return ULOGD_IRET_OK; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 7/8] ipfix: print ipfix message 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (5 preceding siblings ...) 2014-03-08 1:15 ` [PATCH 6/8] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA @ 2014-03-08 1:17 ` Ken-ichirou MATSUZAWA 2014-03-08 1:19 ` [PATCH 8/8] ipfix: build headers with template Ken-ichirou MATSUZAWA ` (3 subsequent siblings) 10 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:17 UTC (permalink / raw) To: The netfilter developer mailinglist by messy ipfix_fprintf_ functions. --- output/ulogd_output_IPFIX.c | 226 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 92db5c0..7d1a9bf 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -31,6 +31,7 @@ #include <stdbool.h> #include <unistd.h> #include <string.h> +#include <time.h> #include <errno.h> #include <sys/types.h> @@ -152,6 +153,8 @@ struct ipfix_instance { #define ULOGD_IPFIX_TEMPL_BASE 1024 static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; +static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr); + /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, @@ -374,6 +377,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; + struct ipfix_msg_hdr *ipfix_msg; unsigned int i; bool need_template = false; @@ -416,6 +420,15 @@ static int output_ipfix(struct ulogd_pluginstance *upi) template->until_template = template_per_ce(upi->config_kset).u.value; } + ipfix_msg = build_ipfix_msg(upi, template, need_template); + if (ipfix_msg == NULL) + return ULOGD_IRET_ERR; + + ipfix_msg->export_time = htonl((u_int32_t)(time(NULL))); + ipfix_fprintf_header(stdout, ipfix_msg); + fprintf(stdout, "\n"); + + free(ipfix_msg); return ULOGD_IRET_OK; } @@ -614,3 +627,216 @@ void init(void) { ulogd_register_plugin(&ipfix_plugin); } + +static int ipfix_fprintf_ietf_field(FILE *fd, const struct ipfix_ietf_field *field, int len); +static int ipfix_fprintf_vendor_field(FILE *fd, const struct ipfix_vendor_field *field, int len); + +static int ipfix_fprintf_ietf_field(FILE *fd, const struct ipfix_ietf_field *field, + int len) +{ + int ret; + void *ptr; + + if (len < (int)sizeof(*field)) { + fprintf(fd, "ERROR ietf field: too short buflen for IETF field: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "|0 Information Emement id: %5d | Field Length: %5d |\n", + ntohs(field->type), ntohs(field->length)); + + len -= sizeof(*field); + if (len == 0) + return sizeof(*field); + + ptr = (void *)field + sizeof(*field); + if (*(u_int8_t *)ptr & 0x80) + ret = ipfix_fprintf_vendor_field(fd, ptr, len); + else + ret = ipfix_fprintf_ietf_field(fd, ptr, len); + + if (ret == -1) + return -1; + return ret + sizeof(*field); +} + +static int ipfix_fprintf_vendor_field(FILE *fd, const struct ipfix_vendor_field *field, + int len) +{ + int ret; + void *ptr; + + if (len < (int)sizeof(*field)) { + fprintf(fd, "ERROR vendor field: too short buflen for vendor field: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "|1 Information Emement id: %5d | Field Length: %5d |\n", + ntohs(field->type) & 0x7fff, ntohs(field->length)); + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Enterprise Number: %10d |\n", + ntohl(field->enterprise_num)); + + len -= sizeof(*field); + if (len == 0) + return sizeof(*field); + + ptr = (void *)field + sizeof(*field); + if (*(u_int8_t *)ptr & 0x80) /* vendor */ + ret = ipfix_fprintf_vendor_field(fd, ptr, len); + else /* ietf */ + ret = ipfix_fprintf_ietf_field(fd, ptr, len); + + if (ret == -1) + return -1; + return ret + sizeof(*field); +} + +static int ipfix_fprintf_data_records(FILE *fd, const void *data, int len) +{ + int i; + + fprintf(fd, "+-----------------------------------------------------------------+\n"); + /* don't say messy...*/ + for (i = 0; i < len; i += 4) { + switch (len - i - 4) { + case -3: + fprintf(fd, "| 0x%02x |\n", + *(u_int8_t *)(data + i)); + break; + case -2: + fprintf(fd, "| 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1)); + break; + case -1: + fprintf(fd, "| 0x%02x 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1), *(u_int8_t *)(data + i + 2)); + break; + default: + fprintf(fd, "| 0x%02x 0x%02x 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1), + *(u_int8_t *)(data + i + 2), *(u_int8_t *)(data + i + 3)); + break; + } + } + return len; +} + +static int ipfix_fprintf_template_records(FILE *fd, const struct ipfix_templ_rec_hdr *hdr, + int len) +{ + int ret; + void *field; + + if (len < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR template records: too short buflen for template record: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Template ID: %5d | Field Count: %5d |\n", + ntohs(hdr->templ_id), ntohs(hdr->field_count)); + + len -= sizeof(*hdr); + if (len == 0) + return sizeof(*hdr); + + field = (void *)hdr + sizeof(*hdr); + if (*(u_int8_t *)field & 0x80) + ret = ipfix_fprintf_vendor_field(fd, field, len); + else + ret = ipfix_fprintf_ietf_field(fd, field, len); + + if (ret == -1) + return -1; + return ret + sizeof(*hdr); +} + +static int ipfix_fprintf_set_header(FILE *fd, const struct ipfix_set_hdr *hdr, int len) +{ + int ret, setlen, total_len; + void *ptr; + + if (len < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR set header: too short buflen for set header: %d\n", len); + return -1; + } + setlen = ntohs(hdr->length); + if (len < setlen) { + fprintf(fd, "ERROR set header: buflen: %d is smaller than set length field: %d\n", len, setlen); + /* return -1; */ + } + if (setlen < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR set header: too short set length field: %d\n", setlen); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Set ID: %5d | Length: %5d |\n", + ntohs(hdr->set_id), setlen); + + setlen -= sizeof(*hdr); + ptr = (void *)hdr + sizeof(*hdr); + total_len = sizeof(*hdr); + + switch (ntohs(hdr->set_id)) { + case 2: + ret = ipfix_fprintf_template_records(fd, ptr, setlen); + break; + case 3: + /* XXX: ret = ipfix_fprintf_options_template_records(fd, ptr, setlen); */ + fprintf(fd, "ERROR: options template is not implemented yet, sorry"); + ret = setlen; + break; + default: + ret = ipfix_fprintf_data_records(fd, ptr, setlen); + break; + } + + if (ret == -1 || ret != setlen) + return -1; + + fprintf(fd, "+-----------------------------------------------------------------+\n"); + return total_len + ret; +} + +static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr) +{ + int ret, len; + char outstr[20]; + void *ptr; + time_t t = (time_t)(ntohl(hdr->export_time)); + struct tm *tmp = localtime(&t); + + /* XXX: tmp == NULL and strftime == 0 */ + strftime(outstr, sizeof(outstr), "%F %T", tmp); + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Version Number: %5d | Length: %5d |\n", + ntohs(hdr->version), ntohs(hdr->length)); + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Exoprt Time: %10d |\t%s\n", + ntohl(hdr->export_time), outstr); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + fprintf(fd, "| Sequence Number: %10d |\n", + ntohl(hdr->seq)); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + fprintf(fd, "| Observation Domain ID: %10d |\n", + ntohl(hdr->domain_id)); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + + len = ntohs(hdr->length) - sizeof(*hdr); + ptr = (void *)hdr + sizeof(*hdr); + + while (len > 0) { + ret = ipfix_fprintf_set_header(fd, ptr, len); + if (ret == -1) + return -1; + len -= ret; + ptr += ret; + } + + return ntohs(hdr->length) - len; +} -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 8/8] ipfix: build headers with template 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (6 preceding siblings ...) 2014-03-08 1:17 ` [PATCH 7/8] ipfix: print ipfix message Ken-ichirou MATSUZAWA @ 2014-03-08 1:19 ` Ken-ichirou MATSUZAWA 2014-03-08 1:24 ` [libnetfilter_conntrack PATCH] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA ` (2 subsequent siblings) 10 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:19 UTC (permalink / raw) To: The netfilter developer mailinglist Based on assumption that we send only two types packet, one has template set and data set, another has data set only. Theses templates including message header, set header and template records are put in struct ulogd_ipfix_template as struct ipfix_msg_hdr. Another assumption is that we can send only one dataset, cannot send muliple datasets at onece. It's better to not include dataset buffer, alloc it each time and use gather sendmsg to send multiple set with pre- allocated headers. --- output/ulogd_output_IPFIX.c | 228 +++++++++++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 87 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 7d1a9bf..f1c1de0 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -126,18 +126,13 @@ static struct config_keyset ipfix_kset = { #define domain_ce(x) (x->ces[3]) #define template_per_ce(x) (x->ces[4]) -struct ipfix_template { - struct ipfix_templ_rec_hdr hdr; - char buf[0]; -}; - struct ulogd_ipfix_template { struct llist_head list; struct nfct_bitmask *bitmask; - unsigned int data_length; /* length of the DATA */ - void *tmpl_cur; /* cursor into current template position */ - struct ipfix_template tmpl; - int until_template; /* decide if it's time to retransmit our template */ + int until_template; /* decide if it's time to retransmit our template */ + int tmpl_data_msg_len, data_only_msg_len; + struct ipfix_msg_hdr *tmpl_data_msg; /* include records, set header of template, data */ + struct ipfix_msg_hdr *data_only_msg; /* include records, set header of data */ }; struct ipfix_instance { @@ -155,36 +150,15 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr); -/* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * -build_template_for_bitmask(struct ulogd_pluginstance *upi, +alloc_ulogd_ipfix_template(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) { struct ulogd_ipfix_template *tmpl; - unsigned int i, j; - int size = sizeof(struct ulogd_ipfix_template) - + (upi->input.num_keys * sizeof(struct ipfix_vendor_field)); - - tmpl = malloc(size); - if (!tmpl) - return NULL; - memset(tmpl, 0, size); - - tmpl->bitmask = nfct_bitmask_clone(bm); - if (!tmpl->bitmask) { - free(tmpl); - return NULL; - } - - /* initialize template header */ - tmpl->tmpl.hdr.templ_id = htons(next_template_id++); - - tmpl->tmpl_cur = tmpl->tmpl.buf; - - tmpl->data_length = 0; - tmpl->until_template = template_per_ce(upi->config_kset).u.value; + unsigned int i; + int tmpl_len = 0, data_len = 0; - for (i = 0, j = 0; i < upi->input.num_keys; i++) { + for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; int length = ulogd_key_size(key); @@ -204,27 +178,130 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, continue; } + if (key->ipfix.vendor == IPFIX_VENDOR_IETF) + tmpl_len += sizeof(struct ipfix_ietf_field); + else + tmpl_len += sizeof(struct ipfix_vendor_field); + + data_len += length; + } + + tmpl = calloc(sizeof(struct ulogd_ipfix_template), 1); + if (tmpl == NULL) + return NULL; + + tmpl->bitmask = nfct_bitmask_clone(bm); + if (!tmpl->bitmask) + goto free_tmpl; + + tmpl->data_only_msg_len = sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr) + data_len; + tmpl->tmpl_data_msg_len = tmpl->data_only_msg_len + + sizeof(struct ipfix_templ_rec_hdr) + + sizeof(struct ipfix_set_hdr) + tmpl_len; + + tmpl->tmpl_data_msg = malloc(tmpl->tmpl_data_msg_len); + if (tmpl->tmpl_data_msg == NULL) + goto free_bitmask; + memset(tmpl->tmpl_data_msg, 0, tmpl->tmpl_data_msg_len); + + tmpl->data_only_msg = malloc(tmpl->data_only_msg_len); + if (tmpl->data_only_msg == NULL) + goto free_tmpl_data_msg; + memset(tmpl->data_only_msg, 0, tmpl->data_only_msg_len); + + return tmpl; + +free_tmpl_data_msg: + free(tmpl->tmpl_data_msg); +free_bitmask: + free(tmpl->bitmask); +free_tmpl: + free(tmpl); + + return NULL; +} + +/* Build the IPFIX template from the input keys */ +struct ulogd_ipfix_template * +build_template_for_bitmask(struct ulogd_pluginstance *upi, + struct nfct_bitmask *bm) +{ + struct ulogd_ipfix_template *tmpl; + struct ipfix_msg_hdr *msg_hdr; + struct ipfix_templ_rec_hdr *tmpl_hdr; + struct ipfix_set_hdr *set_hdr; + unsigned int i, field_count; + void *ptr; + + tmpl = alloc_ulogd_ipfix_template(upi, bm); + if (tmpl == NULL) + return NULL; + + tmpl->until_template = template_per_ce(upi->config_kset).u.value; + + /* build template records */ + ptr = (void *)tmpl->tmpl_data_msg + sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr) + sizeof(struct ipfix_templ_rec_hdr); + for (i = 0, field_count = 0; i < upi->input.num_keys; i++) { + struct ulogd_key *key = &upi->input.keys[i]; + int length = ulogd_key_size(key); + + if (!(key->u.source->flags & ULOGD_RETF_VALID)) + continue; + if (length < 0 || length > 0xfffe) + continue; + if (key->ipfix.field_id == 0) + continue; + if (key->ipfix.vendor == IPFIX_VENDOR_IETF) { - struct ipfix_ietf_field *field = - (struct ipfix_ietf_field *) tmpl->tmpl_cur; + struct ipfix_ietf_field *field = (struct ipfix_ietf_field *)ptr; field->type = htons(key->ipfix.field_id); field->length = htons(length); - tmpl->tmpl_cur += sizeof(*field); + ptr += sizeof(*field); } else { - struct ipfix_vendor_field *field = - (struct ipfix_vendor_field *) tmpl->tmpl_cur; + struct ipfix_vendor_field *field =(struct ipfix_vendor_field *)ptr; field->type = htons(key->ipfix.field_id | 0x8000); - field->enterprise_num = htonl(key->ipfix.vendor); field->length = htons(length); - tmpl->tmpl_cur += sizeof(*field); + field->enterprise_num = htonl(key->ipfix.vendor); + ptr += sizeof(*field); } - tmpl->data_length += length; - j++; + field_count++; } - tmpl->tmpl.hdr.field_count = htons(j); + /** initialize ipfix message header with template and data */ + msg_hdr = tmpl->tmpl_data_msg; + msg_hdr->version = htons(10); + msg_hdr->length = htons(tmpl->tmpl_data_msg_len); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + + /* initialize template set header */ + set_hdr = (void *)msg_hdr + sizeof(*msg_hdr); + set_hdr->set_id = htons(2); + set_hdr->length = htons(tmpl->tmpl_data_msg_len - tmpl->data_only_msg_len); + + /* initialize template record header */ + tmpl_hdr = (void *)set_hdr + sizeof(*set_hdr); + tmpl_hdr->templ_id = htons(next_template_id++); + tmpl_hdr->field_count = htons(field_count); + + /* initialize data set header */ + set_hdr = ptr; + set_hdr->set_id = tmpl_hdr->templ_id; + set_hdr->length = htons(tmpl->data_only_msg_len - sizeof(struct ipfix_msg_hdr)); + + /** initialize ipfix message header with data only */ + msg_hdr = tmpl->data_only_msg; + msg_hdr->version = htons(10); + msg_hdr->length = htons(tmpl->data_only_msg_len); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + + /* initialize data set header */ + set_hdr = (void *)msg_hdr + sizeof(*msg_hdr); + set_hdr->set_id = tmpl_hdr->templ_id; + set_hdr->length = htons(tmpl->data_only_msg_len - sizeof(struct ipfix_msg_hdr)); return tmpl; } @@ -318,59 +395,36 @@ static struct ipfix_msg_hdr *build_ipfix_msg(struct ulogd_pluginstance *upi, bool need_template) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; - u_int16_t tmpl_len; struct ipfix_msg_hdr *msg_hdr; - struct ipfix_templ_rec_hdr *tmpl_hdr; - struct ipfix_set_hdr *data_hdr, *tmpl_set_hdr; - void *buf; - int msglen, ret; - - msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) - + template->data_length; - if (need_template) - msglen = msglen + sizeof(struct ipfix_set_hdr) - + (template->tmpl_cur - (void *)&template->tmpl); - buf = malloc(msglen); - if (buf == NULL) - return NULL; - memset(buf, 0, msglen); + void *data_records; + int ret, data_len; - /* ipfix msg header */ - msg_hdr = buf; - msg_hdr->version = htons(10); - msg_hdr->length = htons(msglen); - msg_hdr->seq = htonl(ii->seq++); - msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); if (need_template) { - /* put set header and template records */ - tmpl_set_hdr = buf + sizeof(*msg_hdr); - tmpl_set_hdr->set_id = htons(2); - tmpl_len = template->tmpl_cur - (void *)&template->tmpl; - tmpl_set_hdr->length = htons(sizeof(*tmpl_set_hdr) + tmpl_len); - tmpl_hdr = (void *)tmpl_set_hdr + sizeof(*tmpl_set_hdr); - memcpy((void *)tmpl_hdr, (void *)&template->tmpl, tmpl_len); - data_hdr = (void *)tmpl_hdr + tmpl_len; + int tmpl_len = template->tmpl_data_msg_len - template->data_only_msg_len; + msg_hdr = template->tmpl_data_msg; + data_records = (void *)msg_hdr + sizeof(struct ipfix_msg_hdr) + + tmpl_len + sizeof(struct ipfix_set_hdr); } else { - data_hdr = buf + sizeof(*msg_hdr); + msg_hdr = template->data_only_msg; + data_records = (void *)msg_hdr + sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr); } + msg_hdr->seq = htonl(ii->seq++); + + data_len = template->data_only_msg_len - sizeof(struct ipfix_msg_hdr) + - sizeof(struct ipfix_set_hdr); + memset(data_records, 0, data_len); - /* put set header and data records */ - data_hdr->set_id = template->tmpl.hdr.templ_id; /* already ordered */ - data_hdr->length = htons(sizeof(*data_hdr) + template->data_length); - ret = put_data_records(upi, template, (void *)data_hdr + sizeof(*data_hdr)); + ret = put_data_records(upi, template, data_records); if (ret < 0) { ulogd_log(ULOGD_ERROR, "could not build ipfix dataset"); - goto free_buf; - } else if (ret > msglen) { + return NULL; + } else if (ret > data_len) { ulogd_log(ULOGD_ERROR, "overflowed on building ipfix dataset"); - goto free_buf; + return NULL; } return msg_hdr; - -free_buf: - free(buf); - return NULL; } static int output_ipfix(struct ulogd_pluginstance *upi) @@ -415,10 +469,11 @@ static int output_ipfix(struct ulogd_pluginstance *upi) need_template = true; } - if (template->until_template-- == 0) { + if (template->until_template == 0) { need_template = true; template->until_template = template_per_ce(upi->config_kset).u.value; } + template->until_template--; ipfix_msg = build_ipfix_msg(upi, template, need_template); if (ipfix_msg == NULL) @@ -428,7 +483,6 @@ static int output_ipfix(struct ulogd_pluginstance *upi) ipfix_fprintf_header(stdout, ipfix_msg); fprintf(stdout, "\n"); - free(ipfix_msg); return ULOGD_IRET_OK; } -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [libnetfilter_conntrack PATCH] conntrack: introduce clear and equal functions for bitmask object 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (7 preceding siblings ...) 2014-03-08 1:19 ` [PATCH 8/8] ipfix: build headers with template Ken-ichirou MATSUZAWA @ 2014-03-08 1:24 ` Ken-ichirou MATSUZAWA 2014-03-08 9:25 ` Florian Westphal 2014-03-23 18:50 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA 10 siblings, 1 reply; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-08 1:24 UTC (permalink / raw) To: The netfilter developer mailinglist This patch adds two functions, useful for ulogd IPFIX output module. --- .../libnetfilter_conntrack.h | 2 ++ src/conntrack/api.c | 31 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index d4542ba..a5e6a91 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -286,6 +286,8 @@ void nfct_bitmask_set_bit(struct nfct_bitmask *, unsigned int bit); int nfct_bitmask_test_bit(const struct nfct_bitmask *, unsigned int bit); void nfct_bitmask_unset_bit(struct nfct_bitmask *, unsigned int bit); void nfct_bitmask_destroy(struct nfct_bitmask *); +void nfct_bitmask_clear(struct nfct_bitmask *); +int nfct_bitmask_equal(const struct nfct_bitmask *, const struct nfct_bitmask *); /* connlabel name <-> bit translation mapping */ struct nfct_labelmap; diff --git a/src/conntrack/api.c b/src/conntrack/api.c index 224be86..fc4c58f 100644 --- a/src/conntrack/api.c +++ b/src/conntrack/api.c @@ -1704,6 +1704,37 @@ void nfct_bitmask_destroy(struct nfct_bitmask *b) free(b); } +/* + * nfct_bitmask_clear - clear a bitmask object + * + * \param b pointer to the bitmask object to clear + */ +void nfct_bitmask_clear(struct nfct_bitmask *b) +{ + unsigned int bytes = b->words * sizeof(b->bits[0]); + memset(b->bits, 0, bytes); +} + +/* + * nfct_bitmask_equal - compare two bitmask objects + * + * \param b1 pointer to a valid bitmask object + * \param b2 pointer to a valid bitmask object + * + * If both bitmask object are equal, this function returns 1, otherwise + * -1 or 0 is returned. + */ +int nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2) +{ + if (b1->words != b2->words) + return -1; + + if (!memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0]))) + return 1; + else + return 0; +} + /** * @} */ -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [libnetfilter_conntrack PATCH] conntrack: introduce clear and equal functions for bitmask object 2014-03-08 1:24 ` [libnetfilter_conntrack PATCH] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA @ 2014-03-08 9:25 ` Florian Westphal 0 siblings, 0 replies; 45+ messages in thread From: Florian Westphal @ 2014-03-08 9:25 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Ken-ichirou MATSUZAWA <chamaken@gmail.com> wrote: > This patch adds two functions, useful for ulogd IPFIX > output module. I am ok with this patch. Once the ulogd patches have been reviewed/accepted this can be applied to libnf-ct. Will need lib versioning bump before next release of library. ^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 0/8] make progress ulogd_output_IPFIX 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (8 preceding siblings ...) 2014-03-08 1:24 ` [libnetfilter_conntrack PATCH] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA @ 2014-03-23 18:50 ` Eric Leblond 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA 10 siblings, 1 reply; 45+ messages in thread From: Eric Leblond @ 2014-03-23 18:50 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Hello, On Sat, 2014-03-08 at 10:03 +0900, Ken-ichirou MATSUZAWA wrote: > Hello, > > If there is someone who is working on ulogd_output_IPFIX, please let me > know. I need it and would work on it. Thanks lot for working on it. > This patch series make progress, not work completely, just print IPFIX > packet format. Would you review this? I think this has four issues. > > * Install nfct_bitmask in libnetfilter_conntrack > This needs libnetfilter_conntrack patch I'll send after. Not an issue because Florian did accept your patch. > * Send only one dataset, not multiple at once > And it (will) send a message each time when output_ipfix() is called. > It's not efficient sending. I don't think there is possibly issue with starting with that implementation and then provide a better one later. > * No options template and data > Do we need these scope data? > 4. Specific Reporting Requiremt in RFC7011, says MAY be implemented IPFIX is in ulogd wanted feature list since so long that this is not an issue if we don't implement the extended feature. The only point is to be able to interact cleanly with IPFIX collector in the market. > * Template retransmit timing > It send template per messages specified in config file. > I took a glance softflowd and follow that. Good idea to mimic an existing software. Some generic points regarding this patchset: * There is some whitespace errors please fix them when resending * I need the Signed-off-by line in your patch (for the same reason as in Linux https://www.kernel.org/doc/Documentation/SubmittingPatches) More comments to come in reply to individual patches. BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 0/8] make progress ulogd_output_IPFIX 2014-03-23 18:50 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond @ 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA 2014-03-26 12:16 ` [ulogd PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA ` (8 more replies) 0 siblings, 9 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:11 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist Hello Eric. Thank you for taking your time to see it and your reply. > Some generic points regarding this patchset: I'm resending all with following it, sorry for your inconvenience And you wrote... > Subject: Re: [PATCH 1/8] ipfix: use nfct_bitmask > available on the system. As it is possible to build ulogd with > --disable-nfct configure flags, you need to make the build of IPFIX I see. I should have seen input/Makefile.am before, thank you. > Subject: Re: [PATCH 5/8] ipfix: add function for ipfix message creation > I don't like this malloc because ulogd will do an allocation for each I think we can fix allocation sizes for each of template and I worked at PATCH 8/8 but you could not see it because the patches format were invalid, sorry. Thanks. ^ permalink raw reply [flat|nested] 45+ messages in thread
* [ulogd PATCH 1/8] ipfix: use nfct_bitmask 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA @ 2014-03-26 12:16 ` Ken-ichirou MATSUZAWA 2014-03-26 12:18 ` [ulogd PATCH 2/8] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA ` (7 subsequent siblings) 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:16 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist from libnetfilter_conntrack instead of original Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- configure.ac | 1 + output/Makefile.am | 10 +++++ output/ulogd_output_IPFIX.c | 107 ++++++-------------------------------------- 3 files changed, 24 insertions(+), 94 deletions(-) diff --git a/configure.ac b/configure.ac index 544a256..be98f63 100644 --- a/configure.ac +++ b/configure.ac @@ -164,5 +164,6 @@ Ulogd configuration: SQLITE3 plugin: ${enable_sqlite3} DBI plugin: ${enable_dbi} JSON plugin: ${enable_jansson} + IPFIX plugin: ${enable_nfct} " echo "You can now run 'make' and 'make install'" diff --git a/output/Makefile.am b/output/Makefile.am index ff851ad..a706c95 100644 --- a/output/Makefile.am +++ b/output/Makefile.am @@ -13,6 +13,10 @@ if HAVE_JANSSON pkglib_LTLIBRARIES += ulogd_output_JSON.la endif +if BUILD_NFCT +pkglib_LTLIBRARIES += ulogd_output_IPFIX.la +endif + ulogd_output_GPRINT_la_SOURCES = ulogd_output_GPRINT.c ulogd_output_GPRINT_la_LDFLAGS = -avoid-version -module @@ -42,3 +46,9 @@ ulogd_output_JSON_la_SOURCES = ulogd_output_JSON.c ulogd_output_JSON_la_LIBADD = ${libjansson_LIBS} ulogd_output_JSON_la_LDFLAGS = -avoid-version -module endif + +if BUILD_NFCT +ulogd_output_IPFIX_la_SOURCES = ulogd_output_IPFIX.c +ulogd_output_IPFIX_la_LDFLAGS = -avoid-version -module +ulogd_output_IPFIX_la_LIBADD = ${LIBNETFILTER_CONNTRACK_LIBS} +endif diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 761d272..01ac9a0 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -36,6 +36,8 @@ #include <sys/socket.h> #include <netdb.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + #include <ulogd/linuxlist.h> #ifdef IPPROTO_SCTP @@ -68,89 +70,6 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 -/* bitmask stuff */ -struct bitmask { - int size_bits; - char *buf; -}; - -#define SIZE_OCTETS(x) ((x/8)+1) - -void bitmask_clear(struct bitmask *bm) -{ - memset(bm->buf, 0, SIZE_OCTETS(bm->size_bits)); -} - -struct bitmask *bitmask_alloc(unsigned int num_bits) -{ - struct bitmask *bm; - unsigned int size_octets = SIZE_OCTETS(num_bits); - - bm = malloc(sizeof(*bm) + size_octets); - if (!bm) - return NULL; - - bm->size_bits = num_bits; - bm->buf = (void *)bm + sizeof(*bm); - - bitmask_clear(bm); - - return bm; -} - -void bitmask_free(struct bitmask *bm) -{ - free(bm); -} - -int bitmask_set_bit_to(struct bitmask *bm, unsigned int bits, int to) -{ - unsigned int byte = bits / 8; - unsigned int bit = bits % 8; - unsigned char *ptr; - - if (byte > SIZE_OCTETS(bm->size_bits)) - return -EINVAL; - - if (to == 0) - bm->buf[byte] &= ~(1 << bit); - else - bm->buf[byte] |= (1 << bit); - - return 0; -} - -#define bitmask_clear_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 0) - -#define bitmask_set_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 1) - -int bitmasks_equal(const struct bitmask *bm1, const struct bitmask *bm2) -{ - if (bm1->size_bits != bm2->size_bits) - return -1; - - if (!memcmp(bm1->buf, bm2->buf, SIZE_OCTETS(bm1->size_bits))) - return 1; - else - return 0; -} - -struct bitmask *bitmask_dup(const struct bitmask *bm_orig) -{ - struct bitmask *bm_new; - int size = sizeof(*bm_new) + SIZE_OCTETS(bm_orig->size_bits); - - bm_new = malloc(size); - if (!bm_new) - return NULL; - - memcpy(bm_new, bm_orig, size); - - return bm_new; -} - static struct config_keyset ipfix_kset = { .num_ces = 3, .ces = { @@ -185,7 +104,7 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; - struct bitmask *bitmask; + struct nfct_bitmask *bitmask; unsigned int total_length; /* length of the DATA */ char *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; @@ -201,7 +120,7 @@ struct ipfix_instance { struct ipfix_template *tmpl; unsigned int tmpl_len; - struct bitmask *valid_bitmask; /* bitmask of valid keys */ + struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ unsigned int total_length; /* total size of all data elements */ }; @@ -212,7 +131,7 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ipfix_templ_rec_hdr *rhdr; @@ -226,7 +145,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; memset(tmpl, 0, size); - tmpl->bitmask = bitmask_dup(bm); + tmpl->bitmask = nfct_bitmask_clone(bm); if (!tmpl->bitmask) { free(tmpl); return NULL; @@ -288,14 +207,14 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *tmpl; /* FIXME: this can be done more efficient! */ llist_for_each_entry(tmpl, &ii->template_list, list) { - if (bitmasks_equal(bm, tmpl->bitmask)) + if (nfct_bitmask_equal(bm, tmpl->bitmask)) return tmpl; } return NULL; @@ -313,13 +232,13 @@ static int output_ipfix(struct ulogd_pluginstance *upi) * ulogd core could very easily flush it after every packet, * too. */ - bitmask_clear(ii->valid_bitmask); + nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = upi->input.keys[i].u.source; if (key->flags & ULOGD_RETF_VALID) - bitmask_set_bit(ii->valid_bitmask, i); + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -430,7 +349,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) ulogd_log(ULOGD_DEBUG, "starting ipfix\n"); - ii->valid_bitmask = bitmask_alloc(pi->input.num_keys); + ii->valid_bitmask = nfct_bitmask_new(pi->input.num_keys); if (!ii->valid_bitmask) return -ENOMEM; @@ -443,7 +362,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) return 0; out_bm_free: - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return ret; @@ -455,7 +374,7 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) close(ii->fd); - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return 0; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 2/8] ipfix: fix enterprise bit handling 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA 2014-03-26 12:16 ` [ulogd PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA @ 2014-03-26 12:18 ` Ken-ichirou MATSUZAWA 2014-03-26 12:19 ` [ulogd PATCH 3/8] ipfix: some cleanups Ken-ichirou MATSUZAWA ` (6 subsequent siblings) 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:18 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist If this bit is zero, the Information Element identifier identifies an Information Element in IANA-IPFIX, and the four-octet Enterprise Number field MUST NOT be present. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 01ac9a0..333d532 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -182,15 +182,15 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, struct ipfix_ietf_field *field = (struct ipfix_ietf_field *) tmpl->tmpl_cur; - field->type = htons(key->ipfix.field_id | 0x8000000); + field->type = htons(key->ipfix.field_id); field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } else { struct ipfix_vendor_field *field = (struct ipfix_vendor_field *) tmpl->tmpl_cur; + field->type = htons(key->ipfix.field_id | 0x8000); field->enterprise_num = htonl(key->ipfix.vendor); - field->type = htons(key->ipfix.field_id); field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 3/8] ipfix: some cleanups 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA 2014-03-26 12:16 ` [ulogd PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-03-26 12:18 ` [ulogd PATCH 2/8] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA @ 2014-03-26 12:19 ` Ken-ichirou MATSUZAWA 2014-03-26 12:23 ` [ulogd PATCH 4/8] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA ` (5 subsequent siblings) 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:19 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist remove unused variables. use unsigned int to supress gcc warning. change struct field name from total_length to data_length. make same bitmask key. change tmpl_cur to void * to calc size. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 333d532..7ba8712 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -105,8 +105,8 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; struct nfct_bitmask *bitmask; - unsigned int total_length; /* length of the DATA */ - char *tmpl_cur; /* cursor into current template position */ + unsigned int data_length; /* length of the DATA */ + void *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; }; @@ -116,13 +116,7 @@ struct ipfix_instance { int sock_proto; /* protocol (IPPROTO_*) */ struct llist_head template_list; - - struct ipfix_template *tmpl; - unsigned int tmpl_len; - struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ - - unsigned int total_length; /* total size of all data elements */ }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -133,8 +127,6 @@ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) { - struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; - struct ipfix_templ_rec_hdr *rhdr; struct ulogd_ipfix_template *tmpl; unsigned int i, j; int size = sizeof(struct ulogd_ipfix_template) @@ -156,7 +148,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, tmpl->tmpl_cur = tmpl->tmpl.buf; - tmpl->total_length = 0; + tmpl->data_length = 0; for (i = 0, j = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; @@ -194,7 +186,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } - tmpl->total_length += length; + tmpl->data_length += length; j++; } @@ -224,8 +216,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; - unsigned int total_size; - int i; + unsigned int total_size, i; /* FIXME: it would be more cache efficient if the IS_VALID * flags would be a separate bitmask outside of the array. @@ -235,10 +226,17 @@ static int output_ipfix(struct ulogd_pluginstance *upi) nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { - struct ulogd_key *key = upi->input.keys[i].u.source; + struct ulogd_key *key = &upi->input.keys[i]; + int length = ulogd_key_size(key); - if (key->flags & ULOGD_RETF_VALID) - nfct_bitmask_set_bit(ii->valid_bitmask, i); + if (length < 0 || length > 0xfffe) + continue; + if (!(key->u.source->flags & ULOGD_RETF_VALID)) + continue; + if (key->ipfix.field_id == 0) + continue; + + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -253,7 +251,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) llist_add(&template->list, &ii->template_list); } - total_size = template->total_length; + total_size = template->data_length; /* decide if it's time to retransmit our template and (optionally) * prepend it into the to-be-sent IPFIX message */ @@ -382,8 +380,6 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) static void signal_handler_ipfix(struct ulogd_pluginstance *pi, int signal) { - struct ipfix_instance *li = (struct ipfix_instance *) &pi->private; - switch (signal) { case SIGHUP: ulogd_log(ULOGD_NOTICE, "ipfix: reopening connection\n"); -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 4/8] ipfix: add functions for ipfix dataset creation 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA ` (2 preceding siblings ...) 2014-03-26 12:19 ` [ulogd PATCH 3/8] ipfix: some cleanups Ken-ichirou MATSUZAWA @ 2014-03-26 12:23 ` Ken-ichirou MATSUZAWA 2014-03-26 12:25 ` [ulogd PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA ` (4 subsequent siblings) 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:23 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist ulogd_key_putn() put key's value in network byteorder. put_data_records() creates ipfix data records buffer. # fixed that ipv4 address value was put by htonl() in ulogd_key_putn() Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 87 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 7ba8712..f032b50 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -63,6 +63,19 @@ struct sctp_sndrcvinfo { }; #endif +#include <byteswap.h> +#if __BYTE_ORDER == __BIG_ENDIAN +# ifndef __be64_to_cpu +# define __be64_to_cpu(x) (x) +# endif +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# ifndef __be64_to_cpu +# define __be64_to_cpu(x) __bswap_64(x) +# endif +# endif +#endif + #include <ulogd/ulogd.h> #include <ulogd/conffile.h> #include <ulogd/linuxlist.h> @@ -195,8 +208,6 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return tmpl; } - - static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) @@ -212,6 +223,78 @@ find_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; } +static int ulogd_key_putn(struct ulogd_key *key, void *buf) +{ + int ret; + + switch (key->type) { + case ULOGD_RET_INT8: + case ULOGD_RET_UINT8: + case ULOGD_RET_BOOL: + *(u_int8_t *)buf = ikey_get_u8(key); + ret = 1; + break; + case ULOGD_RET_INT16: + case ULOGD_RET_UINT16: + *(u_int16_t *)buf = htons(ikey_get_u16(key)); + ret = 2; + break; + case ULOGD_RET_INT32: + case ULOGD_RET_UINT32: + *(u_int32_t *)buf = htonl(ikey_get_u32(key)); + ret = 4; + break; + case ULOGD_RET_IPADDR: + *(u_int32_t *)buf = ikey_get_u32(key); + ret = 4; + break; + case ULOGD_RET_INT64: + case ULOGD_RET_UINT64: + *(u_int64_t *)buf = __be64_to_cpu(ikey_get_u64(key)); + ret = 8; + break; + case ULOGD_RET_IP6ADDR: + memcpy(buf, ikey_get_u128(key), 16); + ret = 16; + break; + case ULOGD_RET_STRING: + ret = strlen(key->u.value.ptr); + memcpy(buf, key->u.value.ptr, ret); + break; + case ULOGD_RET_RAW: + ulogd_log(ULOGD_NOTICE, "put raw data in network byte order " + "`%s' type 0x%x\n", key->name, key->type); + ret = key->len; + memcpy(buf, key->u.value.ptr, ret); + break; + default: + ulogd_log(ULOGD_ERROR, "unknown size - key " + "`%s' type 0x%x\n", key->name, key->type); + ret = -1; + break; + } + + return ret; +} + +static int put_data_records(struct ulogd_pluginstance *upi, + struct ulogd_ipfix_template *tmpl, void *buf) +{ + int ret; + unsigned int i, len = 0; + + for (i = 0; i < upi->input.num_keys; i++) { + if (!nfct_bitmask_test_bit(tmpl->bitmask, i)) + continue; + ret = ulogd_key_putn(&upi->input.keys[i], buf + len); + if (ret < 0) + return ret; + len += ret; + } + + return len; +} + static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 5/8] ipfix: add function for ipfix message creation 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA ` (3 preceding siblings ...) 2014-03-26 12:23 ` [ulogd PATCH 4/8] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA @ 2014-03-26 12:25 ` Ken-ichirou MATSUZAWA 2014-03-26 12:26 ` [ulogd PATCH 6/8] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA ` (3 subsequent siblings) 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:25 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist This function creates ipfix message, template and data part but not scope. Header sequence is kept by struct ipfix_instance, domain id is specified by config file. The returned value has no export time so caller set this and free the value after using it. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- include/ulogd/ipfix_protocol.h | 8 ++++- output/ulogd_output_IPFIX.c | 71 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/include/ulogd/ipfix_protocol.h b/include/ulogd/ipfix_protocol.h index 5d7e46a..266897e 100644 --- a/include/ulogd/ipfix_protocol.h +++ b/include/ulogd/ipfix_protocol.h @@ -15,7 +15,13 @@ struct ipfix_msg_hdr { u_int16_t length; u_int32_t export_time; u_int32_t seq; - u_int32_t source_id; + u_int32_t domain_id; +}; + +/* Section 3.3.2 */ +struct ipfix_set_hdr { + u_int16_t set_id; + u_int16_t length; }; /* Section 3.4.1 */ diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index f032b50..8246ed3 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <unistd.h> #include <string.h> #include <errno.h> @@ -84,7 +85,7 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 static struct config_keyset ipfix_kset = { - .num_ces = 3, + .num_ces = 4, .ces = { { .key = "host", @@ -103,12 +104,19 @@ static struct config_keyset ipfix_kset = { .options = CONFIG_OPT_NONE, .u = { .string = "udp" }, }, + { + .key = "domain_id", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 0, + }, }, }; #define host_ce(x) (x->ces[0]) #define port_ce(x) (x->ces[1]) #define proto_ce(x) (x->ces[2]) +#define domain_ce(x) (x->ces[3]) struct ipfix_template { struct ipfix_templ_rec_hdr hdr; @@ -130,6 +138,7 @@ struct ipfix_instance { struct llist_head template_list; struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ + u_int32_t seq; }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -295,6 +304,66 @@ static int put_data_records(struct ulogd_pluginstance *upi, return len; } +static struct ipfix_msg_hdr *build_ipfix_msg(struct ulogd_pluginstance *upi, + struct ulogd_ipfix_template *template, + bool need_template) +{ + struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; + u_int16_t tmpl_len; + struct ipfix_msg_hdr *msg_hdr; + struct ipfix_templ_rec_hdr *tmpl_hdr; + struct ipfix_set_hdr *data_hdr, *tmpl_set_hdr; + void *buf; + int msglen, ret; + + msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) + + template->data_length; + if (need_template) + msglen = msglen + sizeof(struct ipfix_set_hdr) + + (template->tmpl_cur - (void *)&template->tmpl); + buf = malloc(msglen); + if (buf == NULL) + return NULL; + memset(buf, 0, msglen); + + /* ipfix msg header */ + msg_hdr = buf; + msg_hdr->version = htons(10); + msg_hdr->length = htons(msglen); + msg_hdr->seq = htonl(ii->seq++); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + if (need_template) { + /* put set header and template records */ + tmpl_set_hdr = buf + sizeof(*msg_hdr); + tmpl_set_hdr->set_id = htons(2); + tmpl_len = template->tmpl_cur - (void *)&template->tmpl; + tmpl_set_hdr->length = htons(sizeof(*tmpl_set_hdr) + tmpl_len); + tmpl_hdr = (void *)tmpl_set_hdr + sizeof(*tmpl_set_hdr); + memcpy((void *)tmpl_hdr, (void *)&template->tmpl, tmpl_len); + data_hdr = (void *)tmpl_hdr + tmpl_len; + } else { + data_hdr = buf + sizeof(*msg_hdr); + } + + /* put set header and data records */ + data_hdr->set_id = template->tmpl.hdr.templ_id; /* already ordered */ + data_hdr->length = htons(sizeof(*data_hdr) + template->data_length); + ret = put_data_records(upi, template, (void *)data_hdr + sizeof(*data_hdr)); + if (ret < 0) { + ulogd_log(ULOGD_ERROR, "could not build ipfix dataset"); + goto free_buf; + } else if (ret > msglen) { + ulogd_log(ULOGD_ERROR, "overflowed on building ipfix dataset"); + goto free_buf; + } + + return msg_hdr; + +free_buf: + free(buf); + return NULL; +} + static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 6/8] ipfix: decide whether prepending template by send times 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA ` (4 preceding siblings ...) 2014-03-26 12:25 ` [ulogd PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA @ 2014-03-26 12:26 ` Ken-ichirou MATSUZAWA 2014-03-26 12:28 ` [ulogd PATCH 7/8] ipfix: print ipfix message Ken-ichirou MATSUZAWA ` (2 subsequent siblings) 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:26 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist specified in config file and kept it until_template in struct ulogd_ipfix_template Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 8246ed3..9e8f140 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -85,7 +85,7 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 static struct config_keyset ipfix_kset = { - .num_ces = 4, + .num_ces = 5, .ces = { { .key = "host", @@ -110,6 +110,12 @@ static struct config_keyset ipfix_kset = { .options = CONFIG_OPT_NONE, .u.value = 0, }, + { + .key = "send_template_per", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 16, + }, }, }; @@ -117,6 +123,7 @@ static struct config_keyset ipfix_kset = { #define port_ce(x) (x->ces[1]) #define proto_ce(x) (x->ces[2]) #define domain_ce(x) (x->ces[3]) +#define template_per_ce(x) (x->ces[4]) struct ipfix_template { struct ipfix_templ_rec_hdr hdr; @@ -129,6 +136,7 @@ struct ulogd_ipfix_template { unsigned int data_length; /* length of the DATA */ void *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; + int until_template; /* decide if it's time to retransmit our template */ }; struct ipfix_instance { @@ -171,6 +179,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, tmpl->tmpl_cur = tmpl->tmpl.buf; tmpl->data_length = 0; + tmpl->until_template = template_per_ce(upi->config_kset).u.value; for (i = 0, j = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; @@ -368,7 +377,8 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; - unsigned int total_size, i; + unsigned int i; + bool need_template = false; /* FIXME: it would be more cache efficient if the IS_VALID * flags would be a separate bitmask outside of the array. @@ -401,16 +411,12 @@ static int output_ipfix(struct ulogd_pluginstance *upi) return ULOGD_IRET_ERR; } llist_add(&template->list, &ii->template_list); + need_template = true; } - total_size = template->data_length; - - /* decide if it's time to retransmit our template and (optionally) - * prepend it into the to-be-sent IPFIX message */ - if (0 /* FIXME */) { - /* add size of template */ - //total_size += (template->tmpl_cur - (void *)&template->tmpl); - total_size += sizeof(template->tmpl); + if (template->until_template-- == 0) { + need_template = true; + template->until_template = template_per_ce(upi->config_kset).u.value; } return ULOGD_IRET_OK; -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 7/8] ipfix: print ipfix message 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA ` (5 preceding siblings ...) 2014-03-26 12:26 ` [ulogd PATCH 6/8] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA @ 2014-03-26 12:28 ` Ken-ichirou MATSUZAWA 2014-03-26 12:30 ` [ulogd PATCH 8/8] ipfix: build headers with template Ken-ichirou MATSUZAWA 2014-04-19 13:36 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:28 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist by messy ipfix_fprintf_ functions. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 226 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 9e8f140..ffb8e6e 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -31,6 +31,7 @@ #include <stdbool.h> #include <unistd.h> #include <string.h> +#include <time.h> #include <errno.h> #include <sys/types.h> @@ -152,6 +153,8 @@ struct ipfix_instance { #define ULOGD_IPFIX_TEMPL_BASE 1024 static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; +static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr); + /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, @@ -377,6 +380,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; + struct ipfix_msg_hdr *ipfix_msg; unsigned int i; bool need_template = false; @@ -419,6 +423,15 @@ static int output_ipfix(struct ulogd_pluginstance *upi) template->until_template = template_per_ce(upi->config_kset).u.value; } + ipfix_msg = build_ipfix_msg(upi, template, need_template); + if (ipfix_msg == NULL) + return ULOGD_IRET_ERR; + + ipfix_msg->export_time = htonl((u_int32_t)(time(NULL))); + ipfix_fprintf_header(stdout, ipfix_msg); + fprintf(stdout, "\n"); + + free(ipfix_msg); return ULOGD_IRET_OK; } @@ -617,3 +630,216 @@ void init(void) { ulogd_register_plugin(&ipfix_plugin); } + +static int ipfix_fprintf_ietf_field(FILE *fd, const struct ipfix_ietf_field *field, int len); +static int ipfix_fprintf_vendor_field(FILE *fd, const struct ipfix_vendor_field *field, int len); + +static int ipfix_fprintf_ietf_field(FILE *fd, const struct ipfix_ietf_field *field, + int len) +{ + int ret; + void *ptr; + + if (len < (int)sizeof(*field)) { + fprintf(fd, "ERROR ietf field: too short buflen for IETF field: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "|0 Information Emement id: %5d | Field Length: %5d |\n", + ntohs(field->type), ntohs(field->length)); + + len -= sizeof(*field); + if (len == 0) + return sizeof(*field); + + ptr = (void *)field + sizeof(*field); + if (*(u_int8_t *)ptr & 0x80) + ret = ipfix_fprintf_vendor_field(fd, ptr, len); + else + ret = ipfix_fprintf_ietf_field(fd, ptr, len); + + if (ret == -1) + return -1; + return ret + sizeof(*field); +} + +static int ipfix_fprintf_vendor_field(FILE *fd, const struct ipfix_vendor_field *field, + int len) +{ + int ret; + void *ptr; + + if (len < (int)sizeof(*field)) { + fprintf(fd, "ERROR vendor field: too short buflen for vendor field: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "|1 Information Emement id: %5d | Field Length: %5d |\n", + ntohs(field->type) & 0x7fff, ntohs(field->length)); + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Enterprise Number: %10d |\n", + ntohl(field->enterprise_num)); + + len -= sizeof(*field); + if (len == 0) + return sizeof(*field); + + ptr = (void *)field + sizeof(*field); + if (*(u_int8_t *)ptr & 0x80) /* vendor */ + ret = ipfix_fprintf_vendor_field(fd, ptr, len); + else /* ietf */ + ret = ipfix_fprintf_ietf_field(fd, ptr, len); + + if (ret == -1) + return -1; + return ret + sizeof(*field); +} + +static int ipfix_fprintf_data_records(FILE *fd, const void *data, int len) +{ + int i; + + fprintf(fd, "+-----------------------------------------------------------------+\n"); + /* don't say messy...*/ + for (i = 0; i < len; i += 4) { + switch (len - i - 4) { + case -3: + fprintf(fd, "| 0x%02x |\n", + *(u_int8_t *)(data + i)); + break; + case -2: + fprintf(fd, "| 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1)); + break; + case -1: + fprintf(fd, "| 0x%02x 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1), *(u_int8_t *)(data + i + 2)); + break; + default: + fprintf(fd, "| 0x%02x 0x%02x 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1), + *(u_int8_t *)(data + i + 2), *(u_int8_t *)(data + i + 3)); + break; + } + } + return len; +} + +static int ipfix_fprintf_template_records(FILE *fd, const struct ipfix_templ_rec_hdr *hdr, + int len) +{ + int ret; + void *field; + + if (len < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR template records: too short buflen for template record: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Template ID: %5d | Field Count: %5d |\n", + ntohs(hdr->templ_id), ntohs(hdr->field_count)); + + len -= sizeof(*hdr); + if (len == 0) + return sizeof(*hdr); + + field = (void *)hdr + sizeof(*hdr); + if (*(u_int8_t *)field & 0x80) + ret = ipfix_fprintf_vendor_field(fd, field, len); + else + ret = ipfix_fprintf_ietf_field(fd, field, len); + + if (ret == -1) + return -1; + return ret + sizeof(*hdr); +} + +static int ipfix_fprintf_set_header(FILE *fd, const struct ipfix_set_hdr *hdr, int len) +{ + int ret, setlen, total_len; + void *ptr; + + if (len < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR set header: too short buflen for set header: %d\n", len); + return -1; + } + setlen = ntohs(hdr->length); + if (len < setlen) { + fprintf(fd, "ERROR set header: buflen: %d is smaller than set length field: %d\n", len, setlen); + /* return -1; */ + } + if (setlen < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR set header: too short set length field: %d\n", setlen); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Set ID: %5d | Length: %5d |\n", + ntohs(hdr->set_id), setlen); + + setlen -= sizeof(*hdr); + ptr = (void *)hdr + sizeof(*hdr); + total_len = sizeof(*hdr); + + switch (ntohs(hdr->set_id)) { + case 2: + ret = ipfix_fprintf_template_records(fd, ptr, setlen); + break; + case 3: + /* XXX: ret = ipfix_fprintf_options_template_records(fd, ptr, setlen); */ + fprintf(fd, "ERROR: options template is not implemented yet, sorry"); + ret = setlen; + break; + default: + ret = ipfix_fprintf_data_records(fd, ptr, setlen); + break; + } + + if (ret == -1 || ret != setlen) + return -1; + + fprintf(fd, "+-----------------------------------------------------------------+\n"); + return total_len + ret; +} + +static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr) +{ + int ret, len; + char outstr[20]; + void *ptr; + time_t t = (time_t)(ntohl(hdr->export_time)); + struct tm *tmp = localtime(&t); + + /* XXX: tmp == NULL and strftime == 0 */ + strftime(outstr, sizeof(outstr), "%F %T", tmp); + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Version Number: %5d | Length: %5d |\n", + ntohs(hdr->version), ntohs(hdr->length)); + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Exoprt Time: %10d |\t%s\n", + ntohl(hdr->export_time), outstr); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + fprintf(fd, "| Sequence Number: %10d |\n", + ntohl(hdr->seq)); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + fprintf(fd, "| Observation Domain ID: %10d |\n", + ntohl(hdr->domain_id)); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + + len = ntohs(hdr->length) - sizeof(*hdr); + ptr = (void *)hdr + sizeof(*hdr); + + while (len > 0) { + ret = ipfix_fprintf_set_header(fd, ptr, len); + if (ret == -1) + return -1; + len -= ret; + ptr += ret; + } + + return ntohs(hdr->length) - len; +} -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 8/8] ipfix: build headers with template 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA ` (6 preceding siblings ...) 2014-03-26 12:28 ` [ulogd PATCH 7/8] ipfix: print ipfix message Ken-ichirou MATSUZAWA @ 2014-03-26 12:30 ` Ken-ichirou MATSUZAWA 2014-04-19 13:36 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond 8 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-03-26 12:30 UTC (permalink / raw) To: Eric Leblond; +Cc: The netfilter developer mailinglist Based on assumption that we send only two types packet, one has template set and data set, another has data set only. Theses templates including message header, set header and template records are put in struct ulogd_ipfix_template as struct ipfix_msg_hdr. Another assumption is that we can send only one dataset, cannot send muliple datasets at onece. It's better to not include dataset buffer, alloc it each time and use gather sendmsg to send multiple set with pre- allocated headers. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 228 +++++++++++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 87 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index ffb8e6e..13f388f 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -126,18 +126,13 @@ static struct config_keyset ipfix_kset = { #define domain_ce(x) (x->ces[3]) #define template_per_ce(x) (x->ces[4]) -struct ipfix_template { - struct ipfix_templ_rec_hdr hdr; - char buf[0]; -}; - struct ulogd_ipfix_template { struct llist_head list; struct nfct_bitmask *bitmask; - unsigned int data_length; /* length of the DATA */ - void *tmpl_cur; /* cursor into current template position */ - struct ipfix_template tmpl; - int until_template; /* decide if it's time to retransmit our template */ + int until_template; /* decide if it's time to retransmit our template */ + int tmpl_data_msg_len, data_only_msg_len; + struct ipfix_msg_hdr *tmpl_data_msg; /* include records, set header of template, data */ + struct ipfix_msg_hdr *data_only_msg; /* include records, set header of data */ }; struct ipfix_instance { @@ -155,36 +150,15 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr); -/* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * -build_template_for_bitmask(struct ulogd_pluginstance *upi, +alloc_ulogd_ipfix_template(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) { struct ulogd_ipfix_template *tmpl; - unsigned int i, j; - int size = sizeof(struct ulogd_ipfix_template) - + (upi->input.num_keys * sizeof(struct ipfix_vendor_field)); - - tmpl = malloc(size); - if (!tmpl) - return NULL; - memset(tmpl, 0, size); - - tmpl->bitmask = nfct_bitmask_clone(bm); - if (!tmpl->bitmask) { - free(tmpl); - return NULL; - } - - /* initialize template header */ - tmpl->tmpl.hdr.templ_id = htons(next_template_id++); - - tmpl->tmpl_cur = tmpl->tmpl.buf; - - tmpl->data_length = 0; - tmpl->until_template = template_per_ce(upi->config_kset).u.value; + unsigned int i; + int tmpl_len = 0, data_len = 0; - for (i = 0, j = 0; i < upi->input.num_keys; i++) { + for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; int length = ulogd_key_size(key); @@ -204,27 +178,130 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, continue; } + if (key->ipfix.vendor == IPFIX_VENDOR_IETF) + tmpl_len += sizeof(struct ipfix_ietf_field); + else + tmpl_len += sizeof(struct ipfix_vendor_field); + + data_len += length; + } + + tmpl = calloc(sizeof(struct ulogd_ipfix_template), 1); + if (tmpl == NULL) + return NULL; + + tmpl->bitmask = nfct_bitmask_clone(bm); + if (!tmpl->bitmask) + goto free_tmpl; + + tmpl->data_only_msg_len = sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr) + data_len; + tmpl->tmpl_data_msg_len = tmpl->data_only_msg_len + + sizeof(struct ipfix_templ_rec_hdr) + + sizeof(struct ipfix_set_hdr) + tmpl_len; + + tmpl->tmpl_data_msg = malloc(tmpl->tmpl_data_msg_len); + if (tmpl->tmpl_data_msg == NULL) + goto free_bitmask; + memset(tmpl->tmpl_data_msg, 0, tmpl->tmpl_data_msg_len); + + tmpl->data_only_msg = malloc(tmpl->data_only_msg_len); + if (tmpl->data_only_msg == NULL) + goto free_tmpl_data_msg; + memset(tmpl->data_only_msg, 0, tmpl->data_only_msg_len); + + return tmpl; + +free_tmpl_data_msg: + free(tmpl->tmpl_data_msg); +free_bitmask: + free(tmpl->bitmask); +free_tmpl: + free(tmpl); + + return NULL; +} + +/* Build the IPFIX template from the input keys */ +struct ulogd_ipfix_template * +build_template_for_bitmask(struct ulogd_pluginstance *upi, + struct nfct_bitmask *bm) +{ + struct ulogd_ipfix_template *tmpl; + struct ipfix_msg_hdr *msg_hdr; + struct ipfix_templ_rec_hdr *tmpl_hdr; + struct ipfix_set_hdr *set_hdr; + unsigned int i, field_count; + void *ptr; + + tmpl = alloc_ulogd_ipfix_template(upi, bm); + if (tmpl == NULL) + return NULL; + + tmpl->until_template = template_per_ce(upi->config_kset).u.value; + + /* build template records */ + ptr = (void *)tmpl->tmpl_data_msg + sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr) + sizeof(struct ipfix_templ_rec_hdr); + for (i = 0, field_count = 0; i < upi->input.num_keys; i++) { + struct ulogd_key *key = &upi->input.keys[i]; + int length = ulogd_key_size(key); + + if (!(key->u.source->flags & ULOGD_RETF_VALID)) + continue; + if (length < 0 || length > 0xfffe) + continue; + if (key->ipfix.field_id == 0) + continue; + if (key->ipfix.vendor == IPFIX_VENDOR_IETF) { - struct ipfix_ietf_field *field = - (struct ipfix_ietf_field *) tmpl->tmpl_cur; + struct ipfix_ietf_field *field = (struct ipfix_ietf_field *)ptr; field->type = htons(key->ipfix.field_id); field->length = htons(length); - tmpl->tmpl_cur += sizeof(*field); + ptr += sizeof(*field); } else { - struct ipfix_vendor_field *field = - (struct ipfix_vendor_field *) tmpl->tmpl_cur; + struct ipfix_vendor_field *field =(struct ipfix_vendor_field *)ptr; field->type = htons(key->ipfix.field_id | 0x8000); - field->enterprise_num = htonl(key->ipfix.vendor); field->length = htons(length); - tmpl->tmpl_cur += sizeof(*field); + field->enterprise_num = htonl(key->ipfix.vendor); + ptr += sizeof(*field); } - tmpl->data_length += length; - j++; + field_count++; } - tmpl->tmpl.hdr.field_count = htons(j); + /** initialize ipfix message header with template and data */ + msg_hdr = tmpl->tmpl_data_msg; + msg_hdr->version = htons(10); + msg_hdr->length = htons(tmpl->tmpl_data_msg_len); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + + /* initialize template set header */ + set_hdr = (void *)msg_hdr + sizeof(*msg_hdr); + set_hdr->set_id = htons(2); + set_hdr->length = htons(tmpl->tmpl_data_msg_len - tmpl->data_only_msg_len); + + /* initialize template record header */ + tmpl_hdr = (void *)set_hdr + sizeof(*set_hdr); + tmpl_hdr->templ_id = htons(next_template_id++); + tmpl_hdr->field_count = htons(field_count); + + /* initialize data set header */ + set_hdr = ptr; + set_hdr->set_id = tmpl_hdr->templ_id; + set_hdr->length = htons(tmpl->data_only_msg_len - sizeof(struct ipfix_msg_hdr)); + + /** initialize ipfix message header with data only */ + msg_hdr = tmpl->data_only_msg; + msg_hdr->version = htons(10); + msg_hdr->length = htons(tmpl->data_only_msg_len); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + + /* initialize data set header */ + set_hdr = (void *)msg_hdr + sizeof(*msg_hdr); + set_hdr->set_id = tmpl_hdr->templ_id; + set_hdr->length = htons(tmpl->data_only_msg_len - sizeof(struct ipfix_msg_hdr)); return tmpl; } @@ -321,59 +398,36 @@ static struct ipfix_msg_hdr *build_ipfix_msg(struct ulogd_pluginstance *upi, bool need_template) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; - u_int16_t tmpl_len; struct ipfix_msg_hdr *msg_hdr; - struct ipfix_templ_rec_hdr *tmpl_hdr; - struct ipfix_set_hdr *data_hdr, *tmpl_set_hdr; - void *buf; - int msglen, ret; - - msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) - + template->data_length; - if (need_template) - msglen = msglen + sizeof(struct ipfix_set_hdr) - + (template->tmpl_cur - (void *)&template->tmpl); - buf = malloc(msglen); - if (buf == NULL) - return NULL; - memset(buf, 0, msglen); + void *data_records; + int ret, data_len; - /* ipfix msg header */ - msg_hdr = buf; - msg_hdr->version = htons(10); - msg_hdr->length = htons(msglen); - msg_hdr->seq = htonl(ii->seq++); - msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); if (need_template) { - /* put set header and template records */ - tmpl_set_hdr = buf + sizeof(*msg_hdr); - tmpl_set_hdr->set_id = htons(2); - tmpl_len = template->tmpl_cur - (void *)&template->tmpl; - tmpl_set_hdr->length = htons(sizeof(*tmpl_set_hdr) + tmpl_len); - tmpl_hdr = (void *)tmpl_set_hdr + sizeof(*tmpl_set_hdr); - memcpy((void *)tmpl_hdr, (void *)&template->tmpl, tmpl_len); - data_hdr = (void *)tmpl_hdr + tmpl_len; + int tmpl_len = template->tmpl_data_msg_len - template->data_only_msg_len; + msg_hdr = template->tmpl_data_msg; + data_records = (void *)msg_hdr + sizeof(struct ipfix_msg_hdr) + + tmpl_len + sizeof(struct ipfix_set_hdr); } else { - data_hdr = buf + sizeof(*msg_hdr); + msg_hdr = template->data_only_msg; + data_records = (void *)msg_hdr + sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr); } + msg_hdr->seq = htonl(ii->seq++); + + data_len = template->data_only_msg_len - sizeof(struct ipfix_msg_hdr) + - sizeof(struct ipfix_set_hdr); + memset(data_records, 0, data_len); - /* put set header and data records */ - data_hdr->set_id = template->tmpl.hdr.templ_id; /* already ordered */ - data_hdr->length = htons(sizeof(*data_hdr) + template->data_length); - ret = put_data_records(upi, template, (void *)data_hdr + sizeof(*data_hdr)); + ret = put_data_records(upi, template, data_records); if (ret < 0) { ulogd_log(ULOGD_ERROR, "could not build ipfix dataset"); - goto free_buf; - } else if (ret > msglen) { + return NULL; + } else if (ret > data_len) { ulogd_log(ULOGD_ERROR, "overflowed on building ipfix dataset"); - goto free_buf; + return NULL; } return msg_hdr; - -free_buf: - free(buf); - return NULL; } static int output_ipfix(struct ulogd_pluginstance *upi) @@ -418,10 +472,11 @@ static int output_ipfix(struct ulogd_pluginstance *upi) need_template = true; } - if (template->until_template-- == 0) { + if (template->until_template == 0) { need_template = true; template->until_template = template_per_ce(upi->config_kset).u.value; } + template->until_template--; ipfix_msg = build_ipfix_msg(upi, template, need_template); if (ipfix_msg == NULL) @@ -431,7 +486,6 @@ static int output_ipfix(struct ulogd_pluginstance *upi) ipfix_fprintf_header(stdout, ipfix_msg); fprintf(stdout, "\n"); - free(ipfix_msg); return ULOGD_IRET_OK; } -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 0/8] make progress ulogd_output_IPFIX 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA ` (7 preceding siblings ...) 2014-03-26 12:30 ` [ulogd PATCH 8/8] ipfix: build headers with template Ken-ichirou MATSUZAWA @ 2014-04-19 13:36 ` Eric Leblond 2014-04-22 11:56 ` [ulogd PATCH 1/8 resend] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-04-22 12:03 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA 8 siblings, 2 replies; 45+ messages in thread From: Eric Leblond @ 2014-04-19 13:36 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Hello, Sorry for the delay in the review. On Wed, 2014-03-26 at 21:11 +0900, Ken-ichirou MATSUZAWA wrote: > Hello Eric. > > Thank you for taking your time to see it and your reply. > > > Some generic points regarding this patchset: > > I'm resending all with following it, sorry for your inconvenience > And you wrote... > > > Subject: Re: [PATCH 1/8] ipfix: use nfct_bitmask > > available on the system. As it is possible to build ulogd with > > --disable-nfct configure flags, you need to make the build of IPFIX I've just realized this means you won't be able to build IPFIX module if you don't have a new version of libnetfilter_conntrack. I don't want to dump once again the required version of the libs. So you should add a check on nfct_bitmask in the configure.ac to be sure you will be able to build IPFIX. > I see. I should have seen input/Makefile.am before, thank you. > > > Subject: Re: [PATCH 5/8] ipfix: add function for ipfix message creation > > I don't like this malloc because ulogd will do an allocation for each > > I think we can fix allocation sizes for each of template and I worked > at PATCH 8/8 but you could not see it because the patches format were > invalid, sorry. I'm basically ok with the patchset if we omit the nfct_bitmask issue. I've just fixed two remaining whitespace issues and I can provide you the updated patchset if you want. BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* [ulogd PATCH 1/8 resend] ipfix: use nfct_bitmask 2014-04-19 13:36 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond @ 2014-04-22 11:56 ` Ken-ichirou MATSUZAWA 2014-04-22 12:03 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA 1 sibling, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-22 11:56 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel from libnetfilter_conntrack instead of original Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- configure.ac | 12 +++++ output/Makefile.am | 10 +++++ output/ulogd_output_IPFIX.c | 107 ++++++-------------------------------------- 3 files changed, 35 insertions(+), 94 deletions(-) diff --git a/configure.ac b/configure.ac index 522c345..bd46323 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,17 @@ AC_ARG_ENABLE(nfct, AS_IF([test "x$enable_nfct" = "xyes"], [ PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.2]) AC_DEFINE([BUILD_NFCT], [1], [Building nfct module]) + + AC_MSG_CHECKING([does nfct_bitmask have clear and equal]) + AC_CACHE_VAL(ac_cv_nfct_bitmask_clear_equal, + AC_TRY_COMPILE( + [ #include <libnetfilter_conntrack/libnetfilter_conntrack.h>], + [ struct nfct_bitmask *b = nrct_bitmask_new(8); + nfct_bitmask_clear(b); nfct_bitmask_equal(b, b); ], + ac_cv_nfct_bitmask_clear_equal=yes, + ac_cv_nfct_bitmask_clear_equal=no)) + AC_MSG_RESULT($ac_cv_nfct_bitmask_clear_equal) + AM_CONDITIONAL([BUILD_IPFIX], [test "x$ac_cv_nfct_bitmask_clear_equal" = "xyes"]) ]) AM_CONDITIONAL([BUILD_NFCT], [test "x$enable_nfct" = "xyes"]) AC_ARG_ENABLE(nfacct, @@ -164,5 +175,6 @@ Ulogd configuration: SQLITE3 plugin: ${enable_sqlite3} DBI plugin: ${enable_dbi} JSON plugin: ${enable_jansson} + IPFIX plugin: ${ac_cv_nfct_bitmask_clear_equal} " echo "You can now run 'make' and 'make install'" diff --git a/output/Makefile.am b/output/Makefile.am index ff851ad..0cb4a20 100644 --- a/output/Makefile.am +++ b/output/Makefile.am @@ -13,6 +13,10 @@ if HAVE_JANSSON pkglib_LTLIBRARIES += ulogd_output_JSON.la endif +if BUILD_IPFIX +pkglib_LTLIBRARIES += ulogd_output_IPFIX.la +endif + ulogd_output_GPRINT_la_SOURCES = ulogd_output_GPRINT.c ulogd_output_GPRINT_la_LDFLAGS = -avoid-version -module @@ -42,3 +46,9 @@ ulogd_output_JSON_la_SOURCES = ulogd_output_JSON.c ulogd_output_JSON_la_LIBADD = ${libjansson_LIBS} ulogd_output_JSON_la_LDFLAGS = -avoid-version -module endif + +if BUILD_IPFIX +ulogd_output_IPFIX_la_SOURCES = ulogd_output_IPFIX.c +ulogd_output_IPFIX_la_LDFLAGS = -avoid-version -module +ulogd_output_IPFIX_la_LIBADD = ${LIBNETFILTER_CONNTRACK_LIBS} +endif diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 761d272..01ac9a0 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -36,6 +36,8 @@ #include <sys/socket.h> #include <netdb.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + #include <ulogd/linuxlist.h> #ifdef IPPROTO_SCTP @@ -68,89 +70,6 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 -/* bitmask stuff */ -struct bitmask { - int size_bits; - char *buf; -}; - -#define SIZE_OCTETS(x) ((x/8)+1) - -void bitmask_clear(struct bitmask *bm) -{ - memset(bm->buf, 0, SIZE_OCTETS(bm->size_bits)); -} - -struct bitmask *bitmask_alloc(unsigned int num_bits) -{ - struct bitmask *bm; - unsigned int size_octets = SIZE_OCTETS(num_bits); - - bm = malloc(sizeof(*bm) + size_octets); - if (!bm) - return NULL; - - bm->size_bits = num_bits; - bm->buf = (void *)bm + sizeof(*bm); - - bitmask_clear(bm); - - return bm; -} - -void bitmask_free(struct bitmask *bm) -{ - free(bm); -} - -int bitmask_set_bit_to(struct bitmask *bm, unsigned int bits, int to) -{ - unsigned int byte = bits / 8; - unsigned int bit = bits % 8; - unsigned char *ptr; - - if (byte > SIZE_OCTETS(bm->size_bits)) - return -EINVAL; - - if (to == 0) - bm->buf[byte] &= ~(1 << bit); - else - bm->buf[byte] |= (1 << bit); - - return 0; -} - -#define bitmask_clear_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 0) - -#define bitmask_set_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 1) - -int bitmasks_equal(const struct bitmask *bm1, const struct bitmask *bm2) -{ - if (bm1->size_bits != bm2->size_bits) - return -1; - - if (!memcmp(bm1->buf, bm2->buf, SIZE_OCTETS(bm1->size_bits))) - return 1; - else - return 0; -} - -struct bitmask *bitmask_dup(const struct bitmask *bm_orig) -{ - struct bitmask *bm_new; - int size = sizeof(*bm_new) + SIZE_OCTETS(bm_orig->size_bits); - - bm_new = malloc(size); - if (!bm_new) - return NULL; - - memcpy(bm_new, bm_orig, size); - - return bm_new; -} - static struct config_keyset ipfix_kset = { .num_ces = 3, .ces = { @@ -185,7 +104,7 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; - struct bitmask *bitmask; + struct nfct_bitmask *bitmask; unsigned int total_length; /* length of the DATA */ char *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; @@ -201,7 +120,7 @@ struct ipfix_instance { struct ipfix_template *tmpl; unsigned int tmpl_len; - struct bitmask *valid_bitmask; /* bitmask of valid keys */ + struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ unsigned int total_length; /* total size of all data elements */ }; @@ -212,7 +131,7 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ipfix_templ_rec_hdr *rhdr; @@ -226,7 +145,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; memset(tmpl, 0, size); - tmpl->bitmask = bitmask_dup(bm); + tmpl->bitmask = nfct_bitmask_clone(bm); if (!tmpl->bitmask) { free(tmpl); return NULL; @@ -288,14 +207,14 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *tmpl; /* FIXME: this can be done more efficient! */ llist_for_each_entry(tmpl, &ii->template_list, list) { - if (bitmasks_equal(bm, tmpl->bitmask)) + if (nfct_bitmask_equal(bm, tmpl->bitmask)) return tmpl; } return NULL; @@ -313,13 +232,13 @@ static int output_ipfix(struct ulogd_pluginstance *upi) * ulogd core could very easily flush it after every packet, * too. */ - bitmask_clear(ii->valid_bitmask); + nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = upi->input.keys[i].u.source; if (key->flags & ULOGD_RETF_VALID) - bitmask_set_bit(ii->valid_bitmask, i); + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -430,7 +349,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) ulogd_log(ULOGD_DEBUG, "starting ipfix\n"); - ii->valid_bitmask = bitmask_alloc(pi->input.num_keys); + ii->valid_bitmask = nfct_bitmask_new(pi->input.num_keys); if (!ii->valid_bitmask) return -ENOMEM; @@ -443,7 +362,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) return 0; out_bm_free: - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return ret; @@ -455,7 +374,7 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) close(ii->fd); - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return 0; -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 0/8] make progress ulogd_output_IPFIX 2014-04-19 13:36 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond 2014-04-22 11:56 ` [ulogd PATCH 1/8 resend] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA @ 2014-04-22 12:03 ` Ken-ichirou MATSUZAWA 2014-04-22 15:20 ` Eric Leblond 1 sibling, 1 reply; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-22 12:03 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel Hello, I have just resent patches related to theses. On Sat, Apr 19, 2014 at 03:36:33PM +0200, Eric Leblond wrote: > dump once again the required version of the libs. So you should add a > check on nfct_bitmask in the configure.ac to be sure you will be able to > build IPFIX. I did it by compiling, or should I check lib version? > I've just fixed two remaining whitespace issues and I can provide you > the updated patchset if you want. I think I fixed it. if not, would you send updated patchset? Thanks, ^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 0/8] make progress ulogd_output_IPFIX 2014-04-22 12:03 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA @ 2014-04-22 15:20 ` Eric Leblond 0 siblings, 0 replies; 45+ messages in thread From: Eric Leblond @ 2014-04-22 15:20 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: netfilter-devel Hi, On Tue, 2014-04-22 at 21:03 +0900, Ken-ichirou MATSUZAWA wrote: > Hello, > > I have just resent patches related to theses. > > On Sat, Apr 19, 2014 at 03:36:33PM +0200, Eric Leblond wrote: > > dump once again the required version of the libs. So you should add a > > check on nfct_bitmask in the configure.ac to be sure you will be able to > > build IPFIX. > > I did it by compiling, or should I check lib version? No function check should be enough as the code is only needing one single function. > > I've just fixed two remaining whitespace issues and I can provide you > > the updated patchset if you want. > > I think I fixed it. if not, would you send updated patchset? I'm sending it to you. BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* [ulogd PATCH 0/13] make progress ulogd_output_IPFIX 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA ` (9 preceding siblings ...) 2014-03-23 18:50 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond @ 2014-04-28 11:39 ` Ken-ichirou MATSUZAWA 2014-04-28 11:42 ` [libnetfilter_conntrack PATCH 1/13] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA ` (12 more replies) 10 siblings, 13 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:39 UTC (permalink / raw) To: The netfilter developer mailinglist Hello, Would you review IPFIX patchset? Compared with previous one, change: * configure.ac check if new libnetfilter_conntrack bitmask functions exists or not. * ulogd_output_IPFIX.c remove odd space add: * ulogd_inpflow_NFCT.c - fix field id of "flow.end.usec" - introduce IPFIX_VENDOR_REVERSE field from RFC5103 - introduce new key "flow.(start|end).mcsec for flow(Start|End)MicroSecond - add debug symbol for yafscii Thanks, ^ permalink raw reply [flat|nested] 45+ messages in thread
* [libnetfilter_conntrack PATCH 1/13] conntrack: introduce clear and equal functions for bitmask object 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA @ 2014-04-28 11:42 ` Ken-ichirou MATSUZAWA 2014-04-28 11:44 ` [ulogd PATCH 2/13] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA ` (11 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:42 UTC (permalink / raw) To: The netfilter developer mailinglist This patch adds two functions, useful for ulogd IPFIX output module. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- .../libnetfilter_conntrack.h | 2 ++ src/conntrack/api.c | 31 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index d4542ba..a5e6a91 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -286,6 +286,8 @@ void nfct_bitmask_set_bit(struct nfct_bitmask *, unsigned int bit); int nfct_bitmask_test_bit(const struct nfct_bitmask *, unsigned int bit); void nfct_bitmask_unset_bit(struct nfct_bitmask *, unsigned int bit); void nfct_bitmask_destroy(struct nfct_bitmask *); +void nfct_bitmask_clear(struct nfct_bitmask *); +int nfct_bitmask_equal(const struct nfct_bitmask *, const struct nfct_bitmask *); /* connlabel name <-> bit translation mapping */ struct nfct_labelmap; diff --git a/src/conntrack/api.c b/src/conntrack/api.c index 09270ee..c601efc 100644 --- a/src/conntrack/api.c +++ b/src/conntrack/api.c @@ -1702,6 +1702,37 @@ void nfct_bitmask_destroy(struct nfct_bitmask *b) free(b); } +/* + * nfct_bitmask_clear - clear a bitmask object + * + * \param b pointer to the bitmask object to clear + */ +void nfct_bitmask_clear(struct nfct_bitmask *b) +{ + unsigned int bytes = b->words * sizeof(b->bits[0]); + memset(b->bits, 0, bytes); +} + +/* + * nfct_bitmask_equal - compare two bitmask objects + * + * \param b1 pointer to a valid bitmask object + * \param b2 pointer to a valid bitmask object + * + * If both bitmask object are equal, this function returns 1, otherwise + * -1 or 0 is returned. + */ +int nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2) +{ + if (b1->words != b2->words) + return -1; + + if (!memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0]))) + return 1; + else + return 0; +} + /** * @} */ -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 2/13] ipfix: use nfct_bitmask 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA 2014-04-28 11:42 ` [libnetfilter_conntrack PATCH 1/13] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA @ 2014-04-28 11:44 ` Ken-ichirou MATSUZAWA 2014-04-28 11:45 ` [ulogd PATCH 3/13] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA ` (10 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:44 UTC (permalink / raw) To: The netfilter developer mailinglist from libnetfilter_conntrack instead of original Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- configure.ac | 12 +++++ output/Makefile.am | 10 +++++ output/ulogd_output_IPFIX.c | 107 ++++++-------------------------------------- 3 files changed, 35 insertions(+), 94 deletions(-) diff --git a/configure.ac b/configure.ac index 522c345..bd46323 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,17 @@ AC_ARG_ENABLE(nfct, AS_IF([test "x$enable_nfct" = "xyes"], [ PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.2]) AC_DEFINE([BUILD_NFCT], [1], [Building nfct module]) + + AC_MSG_CHECKING([does nfct_bitmask have clear and equal]) + AC_CACHE_VAL(ac_cv_nfct_bitmask_clear_equal, + AC_TRY_COMPILE( + [ #include <libnetfilter_conntrack/libnetfilter_conntrack.h>], + [ struct nfct_bitmask *b = nrct_bitmask_new(8); + nfct_bitmask_clear(b); nfct_bitmask_equal(b, b); ], + ac_cv_nfct_bitmask_clear_equal=yes, + ac_cv_nfct_bitmask_clear_equal=no)) + AC_MSG_RESULT($ac_cv_nfct_bitmask_clear_equal) + AM_CONDITIONAL([BUILD_IPFIX], [test "x$ac_cv_nfct_bitmask_clear_equal" = "xyes"]) ]) AM_CONDITIONAL([BUILD_NFCT], [test "x$enable_nfct" = "xyes"]) AC_ARG_ENABLE(nfacct, @@ -164,5 +175,6 @@ Ulogd configuration: SQLITE3 plugin: ${enable_sqlite3} DBI plugin: ${enable_dbi} JSON plugin: ${enable_jansson} + IPFIX plugin: ${ac_cv_nfct_bitmask_clear_equal} " echo "You can now run 'make' and 'make install'" diff --git a/output/Makefile.am b/output/Makefile.am index ff851ad..0cb4a20 100644 --- a/output/Makefile.am +++ b/output/Makefile.am @@ -13,6 +13,10 @@ if HAVE_JANSSON pkglib_LTLIBRARIES += ulogd_output_JSON.la endif +if BUILD_IPFIX +pkglib_LTLIBRARIES += ulogd_output_IPFIX.la +endif + ulogd_output_GPRINT_la_SOURCES = ulogd_output_GPRINT.c ulogd_output_GPRINT_la_LDFLAGS = -avoid-version -module @@ -42,3 +46,9 @@ ulogd_output_JSON_la_SOURCES = ulogd_output_JSON.c ulogd_output_JSON_la_LIBADD = ${libjansson_LIBS} ulogd_output_JSON_la_LDFLAGS = -avoid-version -module endif + +if BUILD_IPFIX +ulogd_output_IPFIX_la_SOURCES = ulogd_output_IPFIX.c +ulogd_output_IPFIX_la_LDFLAGS = -avoid-version -module +ulogd_output_IPFIX_la_LIBADD = ${LIBNETFILTER_CONNTRACK_LIBS} +endif diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 761d272..01ac9a0 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -36,6 +36,8 @@ #include <sys/socket.h> #include <netdb.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + #include <ulogd/linuxlist.h> #ifdef IPPROTO_SCTP @@ -68,89 +70,6 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 -/* bitmask stuff */ -struct bitmask { - int size_bits; - char *buf; -}; - -#define SIZE_OCTETS(x) ((x/8)+1) - -void bitmask_clear(struct bitmask *bm) -{ - memset(bm->buf, 0, SIZE_OCTETS(bm->size_bits)); -} - -struct bitmask *bitmask_alloc(unsigned int num_bits) -{ - struct bitmask *bm; - unsigned int size_octets = SIZE_OCTETS(num_bits); - - bm = malloc(sizeof(*bm) + size_octets); - if (!bm) - return NULL; - - bm->size_bits = num_bits; - bm->buf = (void *)bm + sizeof(*bm); - - bitmask_clear(bm); - - return bm; -} - -void bitmask_free(struct bitmask *bm) -{ - free(bm); -} - -int bitmask_set_bit_to(struct bitmask *bm, unsigned int bits, int to) -{ - unsigned int byte = bits / 8; - unsigned int bit = bits % 8; - unsigned char *ptr; - - if (byte > SIZE_OCTETS(bm->size_bits)) - return -EINVAL; - - if (to == 0) - bm->buf[byte] &= ~(1 << bit); - else - bm->buf[byte] |= (1 << bit); - - return 0; -} - -#define bitmask_clear_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 0) - -#define bitmask_set_bit(bm, bit) \ - bitmask_set_bit_to(bm, bit, 1) - -int bitmasks_equal(const struct bitmask *bm1, const struct bitmask *bm2) -{ - if (bm1->size_bits != bm2->size_bits) - return -1; - - if (!memcmp(bm1->buf, bm2->buf, SIZE_OCTETS(bm1->size_bits))) - return 1; - else - return 0; -} - -struct bitmask *bitmask_dup(const struct bitmask *bm_orig) -{ - struct bitmask *bm_new; - int size = sizeof(*bm_new) + SIZE_OCTETS(bm_orig->size_bits); - - bm_new = malloc(size); - if (!bm_new) - return NULL; - - memcpy(bm_new, bm_orig, size); - - return bm_new; -} - static struct config_keyset ipfix_kset = { .num_ces = 3, .ces = { @@ -185,7 +104,7 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; - struct bitmask *bitmask; + struct nfct_bitmask *bitmask; unsigned int total_length; /* length of the DATA */ char *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; @@ -201,7 +120,7 @@ struct ipfix_instance { struct ipfix_template *tmpl; unsigned int tmpl_len; - struct bitmask *valid_bitmask; /* bitmask of valid keys */ + struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ unsigned int total_length; /* total size of all data elements */ }; @@ -212,7 +131,7 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ipfix_templ_rec_hdr *rhdr; @@ -226,7 +145,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; memset(tmpl, 0, size); - tmpl->bitmask = bitmask_dup(bm); + tmpl->bitmask = nfct_bitmask_clone(bm); if (!tmpl->bitmask) { free(tmpl); return NULL; @@ -288,14 +207,14 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, - struct bitmask *bm) + struct nfct_bitmask *bm) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *tmpl; /* FIXME: this can be done more efficient! */ llist_for_each_entry(tmpl, &ii->template_list, list) { - if (bitmasks_equal(bm, tmpl->bitmask)) + if (nfct_bitmask_equal(bm, tmpl->bitmask)) return tmpl; } return NULL; @@ -313,13 +232,13 @@ static int output_ipfix(struct ulogd_pluginstance *upi) * ulogd core could very easily flush it after every packet, * too. */ - bitmask_clear(ii->valid_bitmask); + nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = upi->input.keys[i].u.source; if (key->flags & ULOGD_RETF_VALID) - bitmask_set_bit(ii->valid_bitmask, i); + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -430,7 +349,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) ulogd_log(ULOGD_DEBUG, "starting ipfix\n"); - ii->valid_bitmask = bitmask_alloc(pi->input.num_keys); + ii->valid_bitmask = nfct_bitmask_new(pi->input.num_keys); if (!ii->valid_bitmask) return -ENOMEM; @@ -443,7 +362,7 @@ static int start_ipfix(struct ulogd_pluginstance *pi) return 0; out_bm_free: - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return ret; @@ -455,7 +374,7 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) close(ii->fd); - bitmask_free(ii->valid_bitmask); + nfct_bitmask_destroy(ii->valid_bitmask); ii->valid_bitmask = NULL; return 0; -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 3/13] ipfix: fix enterprise bit handling 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA 2014-04-28 11:42 ` [libnetfilter_conntrack PATCH 1/13] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA 2014-04-28 11:44 ` [ulogd PATCH 2/13] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA @ 2014-04-28 11:45 ` Ken-ichirou MATSUZAWA 2014-04-28 11:46 ` [ulogd PATCH 4/13] ipfix: some cleanups Ken-ichirou MATSUZAWA ` (9 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:45 UTC (permalink / raw) To: The netfilter developer mailinglist If this bit is zero, the Information Element identifier identifies an Information Element in IANA-IPFIX, and the four-octet Enterprise Number field MUST NOT be present. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 01ac9a0..333d532 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -182,15 +182,15 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, struct ipfix_ietf_field *field = (struct ipfix_ietf_field *) tmpl->tmpl_cur; - field->type = htons(key->ipfix.field_id | 0x8000000); + field->type = htons(key->ipfix.field_id); field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } else { struct ipfix_vendor_field *field = (struct ipfix_vendor_field *) tmpl->tmpl_cur; + field->type = htons(key->ipfix.field_id | 0x8000); field->enterprise_num = htonl(key->ipfix.vendor); - field->type = htons(key->ipfix.field_id); field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 4/13] ipfix: some cleanups 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (2 preceding siblings ...) 2014-04-28 11:45 ` [ulogd PATCH 3/13] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA @ 2014-04-28 11:46 ` Ken-ichirou MATSUZAWA 2014-04-28 11:48 ` [ulogd PATCH 5/13] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA ` (8 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:46 UTC (permalink / raw) To: The netfilter developer mailinglist remove unused variables. use unsigned int to supress gcc warning. change struct field name from total_length to data_length. make same bitmask key. change tmpl_cur to void * to calc size. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 333d532..7ba8712 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -105,8 +105,8 @@ struct ipfix_template { struct ulogd_ipfix_template { struct llist_head list; struct nfct_bitmask *bitmask; - unsigned int total_length; /* length of the DATA */ - char *tmpl_cur; /* cursor into current template position */ + unsigned int data_length; /* length of the DATA */ + void *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; }; @@ -116,13 +116,7 @@ struct ipfix_instance { int sock_proto; /* protocol (IPPROTO_*) */ struct llist_head template_list; - - struct ipfix_template *tmpl; - unsigned int tmpl_len; - struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ - - unsigned int total_length; /* total size of all data elements */ }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -133,8 +127,6 @@ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) { - struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; - struct ipfix_templ_rec_hdr *rhdr; struct ulogd_ipfix_template *tmpl; unsigned int i, j; int size = sizeof(struct ulogd_ipfix_template) @@ -156,7 +148,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, tmpl->tmpl_cur = tmpl->tmpl.buf; - tmpl->total_length = 0; + tmpl->data_length = 0; for (i = 0, j = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; @@ -194,7 +186,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, field->length = htons(length); tmpl->tmpl_cur += sizeof(*field); } - tmpl->total_length += length; + tmpl->data_length += length; j++; } @@ -224,8 +216,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; - unsigned int total_size; - int i; + unsigned int total_size, i; /* FIXME: it would be more cache efficient if the IS_VALID * flags would be a separate bitmask outside of the array. @@ -235,10 +226,17 @@ static int output_ipfix(struct ulogd_pluginstance *upi) nfct_bitmask_clear(ii->valid_bitmask); for (i = 0; i < upi->input.num_keys; i++) { - struct ulogd_key *key = upi->input.keys[i].u.source; + struct ulogd_key *key = &upi->input.keys[i]; + int length = ulogd_key_size(key); - if (key->flags & ULOGD_RETF_VALID) - nfct_bitmask_set_bit(ii->valid_bitmask, i); + if (length < 0 || length > 0xfffe) + continue; + if (!(key->u.source->flags & ULOGD_RETF_VALID)) + continue; + if (key->ipfix.field_id == 0) + continue; + + nfct_bitmask_set_bit(ii->valid_bitmask, i); } /* lookup template ID for this bitmask */ @@ -253,7 +251,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) llist_add(&template->list, &ii->template_list); } - total_size = template->total_length; + total_size = template->data_length; /* decide if it's time to retransmit our template and (optionally) * prepend it into the to-be-sent IPFIX message */ @@ -382,8 +380,6 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) static void signal_handler_ipfix(struct ulogd_pluginstance *pi, int signal) { - struct ipfix_instance *li = (struct ipfix_instance *) &pi->private; - switch (signal) { case SIGHUP: ulogd_log(ULOGD_NOTICE, "ipfix: reopening connection\n"); -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 5/13] ipfix: add functions for ipfix dataset creation 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (3 preceding siblings ...) 2014-04-28 11:46 ` [ulogd PATCH 4/13] ipfix: some cleanups Ken-ichirou MATSUZAWA @ 2014-04-28 11:48 ` Ken-ichirou MATSUZAWA 2014-04-28 11:49 ` [ulogd PATCH 6/13] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA ` (7 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:48 UTC (permalink / raw) To: The netfilter developer mailinglist ulogd_key_putn() put key's value in network byteorder. put_data_records() creates ipfix data records buffer. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 87 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 7ba8712..f032b50 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -63,6 +63,19 @@ struct sctp_sndrcvinfo { }; #endif +#include <byteswap.h> +#if __BYTE_ORDER == __BIG_ENDIAN +# ifndef __be64_to_cpu +# define __be64_to_cpu(x) (x) +# endif +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# ifndef __be64_to_cpu +# define __be64_to_cpu(x) __bswap_64(x) +# endif +# endif +#endif + #include <ulogd/ulogd.h> #include <ulogd/conffile.h> #include <ulogd/linuxlist.h> @@ -195,8 +208,6 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, return tmpl; } - - static struct ulogd_ipfix_template * find_template_for_bitmask(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) @@ -212,6 +223,78 @@ find_template_for_bitmask(struct ulogd_pluginstance *upi, return NULL; } +static int ulogd_key_putn(struct ulogd_key *key, void *buf) +{ + int ret; + + switch (key->type) { + case ULOGD_RET_INT8: + case ULOGD_RET_UINT8: + case ULOGD_RET_BOOL: + *(u_int8_t *)buf = ikey_get_u8(key); + ret = 1; + break; + case ULOGD_RET_INT16: + case ULOGD_RET_UINT16: + *(u_int16_t *)buf = htons(ikey_get_u16(key)); + ret = 2; + break; + case ULOGD_RET_INT32: + case ULOGD_RET_UINT32: + *(u_int32_t *)buf = htonl(ikey_get_u32(key)); + ret = 4; + break; + case ULOGD_RET_IPADDR: + *(u_int32_t *)buf = ikey_get_u32(key); + ret = 4; + break; + case ULOGD_RET_INT64: + case ULOGD_RET_UINT64: + *(u_int64_t *)buf = __be64_to_cpu(ikey_get_u64(key)); + ret = 8; + break; + case ULOGD_RET_IP6ADDR: + memcpy(buf, ikey_get_u128(key), 16); + ret = 16; + break; + case ULOGD_RET_STRING: + ret = strlen(key->u.value.ptr); + memcpy(buf, key->u.value.ptr, ret); + break; + case ULOGD_RET_RAW: + ulogd_log(ULOGD_NOTICE, "put raw data in network byte order " + "`%s' type 0x%x\n", key->name, key->type); + ret = key->len; + memcpy(buf, key->u.value.ptr, ret); + break; + default: + ulogd_log(ULOGD_ERROR, "unknown size - key " + "`%s' type 0x%x\n", key->name, key->type); + ret = -1; + break; + } + + return ret; +} + +static int put_data_records(struct ulogd_pluginstance *upi, + struct ulogd_ipfix_template *tmpl, void *buf) +{ + int ret; + unsigned int i, len = 0; + + for (i = 0; i < upi->input.num_keys; i++) { + if (!nfct_bitmask_test_bit(tmpl->bitmask, i)) + continue; + ret = ulogd_key_putn(&upi->input.keys[i], buf + len); + if (ret < 0) + return ret; + len += ret; + } + + return len; +} + static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 6/13] ipfix: add function for ipfix message creation 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (4 preceding siblings ...) 2014-04-28 11:48 ` [ulogd PATCH 5/13] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA @ 2014-04-28 11:49 ` Ken-ichirou MATSUZAWA 2014-04-28 11:50 ` [ulogd PATCH 7/13] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA ` (6 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:49 UTC (permalink / raw) To: The netfilter developer mailinglist This function creates ipfix message, template and data part but not scope. Header sequence is kept by struct ipfix_instance, domain id is specified by config file. The returned value has no export time so caller set this and free the value after using it. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- include/ulogd/ipfix_protocol.h | 8 ++++- output/ulogd_output_IPFIX.c | 71 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/include/ulogd/ipfix_protocol.h b/include/ulogd/ipfix_protocol.h index 5d7e46a..266897e 100644 --- a/include/ulogd/ipfix_protocol.h +++ b/include/ulogd/ipfix_protocol.h @@ -15,7 +15,13 @@ struct ipfix_msg_hdr { u_int16_t length; u_int32_t export_time; u_int32_t seq; - u_int32_t source_id; + u_int32_t domain_id; +}; + +/* Section 3.3.2 */ +struct ipfix_set_hdr { + u_int16_t set_id; + u_int16_t length; }; /* Section 3.4.1 */ diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index f032b50..8246ed3 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <unistd.h> #include <string.h> #include <errno.h> @@ -84,7 +85,7 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 static struct config_keyset ipfix_kset = { - .num_ces = 3, + .num_ces = 4, .ces = { { .key = "host", @@ -103,12 +104,19 @@ static struct config_keyset ipfix_kset = { .options = CONFIG_OPT_NONE, .u = { .string = "udp" }, }, + { + .key = "domain_id", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 0, + }, }, }; #define host_ce(x) (x->ces[0]) #define port_ce(x) (x->ces[1]) #define proto_ce(x) (x->ces[2]) +#define domain_ce(x) (x->ces[3]) struct ipfix_template { struct ipfix_templ_rec_hdr hdr; @@ -130,6 +138,7 @@ struct ipfix_instance { struct llist_head template_list; struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ + u_int32_t seq; }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -295,6 +304,66 @@ static int put_data_records(struct ulogd_pluginstance *upi, return len; } +static struct ipfix_msg_hdr *build_ipfix_msg(struct ulogd_pluginstance *upi, + struct ulogd_ipfix_template *template, + bool need_template) +{ + struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; + u_int16_t tmpl_len; + struct ipfix_msg_hdr *msg_hdr; + struct ipfix_templ_rec_hdr *tmpl_hdr; + struct ipfix_set_hdr *data_hdr, *tmpl_set_hdr; + void *buf; + int msglen, ret; + + msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) + + template->data_length; + if (need_template) + msglen = msglen + sizeof(struct ipfix_set_hdr) + + (template->tmpl_cur - (void *)&template->tmpl); + buf = malloc(msglen); + if (buf == NULL) + return NULL; + memset(buf, 0, msglen); + + /* ipfix msg header */ + msg_hdr = buf; + msg_hdr->version = htons(10); + msg_hdr->length = htons(msglen); + msg_hdr->seq = htonl(ii->seq++); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + if (need_template) { + /* put set header and template records */ + tmpl_set_hdr = buf + sizeof(*msg_hdr); + tmpl_set_hdr->set_id = htons(2); + tmpl_len = template->tmpl_cur - (void *)&template->tmpl; + tmpl_set_hdr->length = htons(sizeof(*tmpl_set_hdr) + tmpl_len); + tmpl_hdr = (void *)tmpl_set_hdr + sizeof(*tmpl_set_hdr); + memcpy((void *)tmpl_hdr, (void *)&template->tmpl, tmpl_len); + data_hdr = (void *)tmpl_hdr + tmpl_len; + } else { + data_hdr = buf + sizeof(*msg_hdr); + } + + /* put set header and data records */ + data_hdr->set_id = template->tmpl.hdr.templ_id; /* already ordered */ + data_hdr->length = htons(sizeof(*data_hdr) + template->data_length); + ret = put_data_records(upi, template, (void *)data_hdr + sizeof(*data_hdr)); + if (ret < 0) { + ulogd_log(ULOGD_ERROR, "could not build ipfix dataset"); + goto free_buf; + } else if (ret > msglen) { + ulogd_log(ULOGD_ERROR, "overflowed on building ipfix dataset"); + goto free_buf; + } + + return msg_hdr; + +free_buf: + free(buf); + return NULL; +} + static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 7/13] ipfix: decide whether prepending template by send times 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (5 preceding siblings ...) 2014-04-28 11:49 ` [ulogd PATCH 6/13] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA @ 2014-04-28 11:50 ` Ken-ichirou MATSUZAWA 2014-04-28 11:51 ` [ulogd PATCH 8/13] ipfix: print ipfix message Ken-ichirou MATSUZAWA ` (5 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:50 UTC (permalink / raw) To: The netfilter developer mailinglist specified in config file and kept it until_template in struct ulogd_ipfix_template Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 8246ed3..4dc4a6c 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -85,7 +85,7 @@ struct sctp_sndrcvinfo { #define IPFIX_DEFAULT_TCPUDP_PORT 4739 static struct config_keyset ipfix_kset = { - .num_ces = 4, + .num_ces = 5, .ces = { { .key = "host", @@ -110,6 +110,12 @@ static struct config_keyset ipfix_kset = { .options = CONFIG_OPT_NONE, .u.value = 0, }, + { + .key = "send_template_per", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 16, + }, }, }; @@ -117,6 +123,7 @@ static struct config_keyset ipfix_kset = { #define port_ce(x) (x->ces[1]) #define proto_ce(x) (x->ces[2]) #define domain_ce(x) (x->ces[3]) +#define template_per_ce(x) (x->ces[4]) struct ipfix_template { struct ipfix_templ_rec_hdr hdr; @@ -129,6 +136,7 @@ struct ulogd_ipfix_template { unsigned int data_length; /* length of the DATA */ void *tmpl_cur; /* cursor into current template position */ struct ipfix_template tmpl; + int until_template; /* decide if it's time to retransmit our template */ }; struct ipfix_instance { @@ -171,6 +179,7 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, tmpl->tmpl_cur = tmpl->tmpl.buf; tmpl->data_length = 0; + tmpl->until_template = template_per_ce(upi->config_kset).u.value; for (i = 0, j = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; @@ -368,7 +377,8 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; - unsigned int total_size, i; + unsigned int i; + bool need_template = false; /* FIXME: it would be more cache efficient if the IS_VALID * flags would be a separate bitmask outside of the array. @@ -401,16 +411,12 @@ static int output_ipfix(struct ulogd_pluginstance *upi) return ULOGD_IRET_ERR; } llist_add(&template->list, &ii->template_list); + need_template = true; } - total_size = template->data_length; - - /* decide if it's time to retransmit our template and (optionally) - * prepend it into the to-be-sent IPFIX message */ - if (0 /* FIXME */) { - /* add size of template */ - //total_size += (template->tmpl_cur - (void *)&template->tmpl); - total_size += sizeof(template->tmpl); + if (template->until_template-- == 0) { + need_template = true; + template->until_template = template_per_ce(upi->config_kset).u.value; } return ULOGD_IRET_OK; -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 8/13] ipfix: print ipfix message 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (6 preceding siblings ...) 2014-04-28 11:50 ` [ulogd PATCH 7/13] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA @ 2014-04-28 11:51 ` Ken-ichirou MATSUZAWA 2014-04-28 11:52 ` [ulogd PATCH 9/13] ipfix: build headers with template Ken-ichirou MATSUZAWA ` (4 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:51 UTC (permalink / raw) To: The netfilter developer mailinglist by messy ipfix_fprintf_ functions. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 226 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 4dc4a6c..b705f03 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -31,6 +31,7 @@ #include <stdbool.h> #include <unistd.h> #include <string.h> +#include <time.h> #include <errno.h> #include <sys/types.h> @@ -152,6 +153,8 @@ struct ipfix_instance { #define ULOGD_IPFIX_TEMPL_BASE 1024 static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; +static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr); + /* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * build_template_for_bitmask(struct ulogd_pluginstance *upi, @@ -377,6 +380,7 @@ static int output_ipfix(struct ulogd_pluginstance *upi) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; struct ulogd_ipfix_template *template; + struct ipfix_msg_hdr *ipfix_msg; unsigned int i; bool need_template = false; @@ -419,6 +423,15 @@ static int output_ipfix(struct ulogd_pluginstance *upi) template->until_template = template_per_ce(upi->config_kset).u.value; } + ipfix_msg = build_ipfix_msg(upi, template, need_template); + if (ipfix_msg == NULL) + return ULOGD_IRET_ERR; + + ipfix_msg->export_time = htonl((u_int32_t)(time(NULL))); + ipfix_fprintf_header(stdout, ipfix_msg); + fprintf(stdout, "\n"); + + free(ipfix_msg); return ULOGD_IRET_OK; } @@ -617,3 +630,216 @@ void init(void) { ulogd_register_plugin(&ipfix_plugin); } + +static int ipfix_fprintf_ietf_field(FILE *fd, const struct ipfix_ietf_field *field, int len); +static int ipfix_fprintf_vendor_field(FILE *fd, const struct ipfix_vendor_field *field, int len); + +static int ipfix_fprintf_ietf_field(FILE *fd, const struct ipfix_ietf_field *field, + int len) +{ + int ret; + void *ptr; + + if (len < (int)sizeof(*field)) { + fprintf(fd, "ERROR ietf field: too short buflen for IETF field: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "|0 Information Emement id: %5d | Field Length: %5d |\n", + ntohs(field->type), ntohs(field->length)); + + len -= sizeof(*field); + if (len == 0) + return sizeof(*field); + + ptr = (void *)field + sizeof(*field); + if (*(u_int8_t *)ptr & 0x80) + ret = ipfix_fprintf_vendor_field(fd, ptr, len); + else + ret = ipfix_fprintf_ietf_field(fd, ptr, len); + + if (ret == -1) + return -1; + return ret + sizeof(*field); +} + +static int ipfix_fprintf_vendor_field(FILE *fd, const struct ipfix_vendor_field *field, + int len) +{ + int ret; + void *ptr; + + if (len < (int)sizeof(*field)) { + fprintf(fd, "ERROR vendor field: too short buflen for vendor field: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "|1 Information Emement id: %5d | Field Length: %5d |\n", + ntohs(field->type) & 0x7fff, ntohs(field->length)); + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Enterprise Number: %10d |\n", + ntohl(field->enterprise_num)); + + len -= sizeof(*field); + if (len == 0) + return sizeof(*field); + + ptr = (void *)field + sizeof(*field); + if (*(u_int8_t *)ptr & 0x80) /* vendor */ + ret = ipfix_fprintf_vendor_field(fd, ptr, len); + else /* ietf */ + ret = ipfix_fprintf_ietf_field(fd, ptr, len); + + if (ret == -1) + return -1; + return ret + sizeof(*field); +} + +static int ipfix_fprintf_data_records(FILE *fd, const void *data, int len) +{ + int i; + + fprintf(fd, "+-----------------------------------------------------------------+\n"); + /* don't say messy...*/ + for (i = 0; i < len; i += 4) { + switch (len - i - 4) { + case -3: + fprintf(fd, "| 0x%02x |\n", + *(u_int8_t *)(data + i)); + break; + case -2: + fprintf(fd, "| 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1)); + break; + case -1: + fprintf(fd, "| 0x%02x 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1), *(u_int8_t *)(data + i + 2)); + break; + default: + fprintf(fd, "| 0x%02x 0x%02x 0x%02x 0x%02x |\n", + *(u_int8_t *)(data + i), *(u_int8_t *)(data + i + 1), + *(u_int8_t *)(data + i + 2), *(u_int8_t *)(data + i + 3)); + break; + } + } + return len; +} + +static int ipfix_fprintf_template_records(FILE *fd, const struct ipfix_templ_rec_hdr *hdr, + int len) +{ + int ret; + void *field; + + if (len < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR template records: too short buflen for template record: %d\n", len); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Template ID: %5d | Field Count: %5d |\n", + ntohs(hdr->templ_id), ntohs(hdr->field_count)); + + len -= sizeof(*hdr); + if (len == 0) + return sizeof(*hdr); + + field = (void *)hdr + sizeof(*hdr); + if (*(u_int8_t *)field & 0x80) + ret = ipfix_fprintf_vendor_field(fd, field, len); + else + ret = ipfix_fprintf_ietf_field(fd, field, len); + + if (ret == -1) + return -1; + return ret + sizeof(*hdr); +} + +static int ipfix_fprintf_set_header(FILE *fd, const struct ipfix_set_hdr *hdr, int len) +{ + int ret, setlen, total_len; + void *ptr; + + if (len < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR set header: too short buflen for set header: %d\n", len); + return -1; + } + setlen = ntohs(hdr->length); + if (len < setlen) { + fprintf(fd, "ERROR set header: buflen: %d is smaller than set length field: %d\n", len, setlen); + /* return -1; */ + } + if (setlen < (int)sizeof(*hdr)) { + fprintf(fd, "ERROR set header: too short set length field: %d\n", setlen); + return -1; + } + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Set ID: %5d | Length: %5d |\n", + ntohs(hdr->set_id), setlen); + + setlen -= sizeof(*hdr); + ptr = (void *)hdr + sizeof(*hdr); + total_len = sizeof(*hdr); + + switch (ntohs(hdr->set_id)) { + case 2: + ret = ipfix_fprintf_template_records(fd, ptr, setlen); + break; + case 3: + /* XXX: ret = ipfix_fprintf_options_template_records(fd, ptr, setlen); */ + fprintf(fd, "ERROR: options template is not implemented yet, sorry"); + ret = setlen; + break; + default: + ret = ipfix_fprintf_data_records(fd, ptr, setlen); + break; + } + + if (ret == -1 || ret != setlen) + return -1; + + fprintf(fd, "+-----------------------------------------------------------------+\n"); + return total_len + ret; +} + +static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr) +{ + int ret, len; + char outstr[20]; + void *ptr; + time_t t = (time_t)(ntohl(hdr->export_time)); + struct tm *tmp = localtime(&t); + + /* XXX: tmp == NULL and strftime == 0 */ + strftime(outstr, sizeof(outstr), "%F %T", tmp); + + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Version Number: %5d | Length: %5d |\n", + ntohs(hdr->version), ntohs(hdr->length)); + fprintf(fd, "+--------------------------------+--------------------------------+\n"); + fprintf(fd, "| Exoprt Time: %10d |\t%s\n", + ntohl(hdr->export_time), outstr); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + fprintf(fd, "| Sequence Number: %10d |\n", + ntohl(hdr->seq)); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + fprintf(fd, "| Observation Domain ID: %10d |\n", + ntohl(hdr->domain_id)); + fprintf(fd, "+-----------------------------------------------------------------+\n"); + + len = ntohs(hdr->length) - sizeof(*hdr); + ptr = (void *)hdr + sizeof(*hdr); + + while (len > 0) { + ret = ipfix_fprintf_set_header(fd, ptr, len); + if (ret == -1) + return -1; + len -= ret; + ptr += ret; + } + + return ntohs(hdr->length) - len; +} -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 9/13] ipfix: build headers with template 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (7 preceding siblings ...) 2014-04-28 11:51 ` [ulogd PATCH 8/13] ipfix: print ipfix message Ken-ichirou MATSUZAWA @ 2014-04-28 11:52 ` Ken-ichirou MATSUZAWA 2014-04-28 11:53 ` [ulogd PATCH 10/13] nfct: fix ipfix field_id of flow.end.usec Ken-ichirou MATSUZAWA ` (3 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:52 UTC (permalink / raw) To: The netfilter developer mailinglist Based on assumption that we send only two types packet, one has template set and data set, another has data set only. Theses templates including message header, set header and template records are put in struct ulogd_ipfix_template as struct ipfix_msg_hdr. Another assumption is that we can send only one dataset, cannot send muliple datasets at onece. It's better to not include dataset buffer, alloc it each time and use gather sendmsg to send multiple set with pre- allocated headers. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 228 +++++++++++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 87 deletions(-) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index b705f03..2c77264 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -126,18 +126,13 @@ static struct config_keyset ipfix_kset = { #define domain_ce(x) (x->ces[3]) #define template_per_ce(x) (x->ces[4]) -struct ipfix_template { - struct ipfix_templ_rec_hdr hdr; - char buf[0]; -}; - struct ulogd_ipfix_template { struct llist_head list; struct nfct_bitmask *bitmask; - unsigned int data_length; /* length of the DATA */ - void *tmpl_cur; /* cursor into current template position */ - struct ipfix_template tmpl; - int until_template; /* decide if it's time to retransmit our template */ + int until_template; /* decide if it's time to retransmit our template */ + int tmpl_data_msg_len, data_only_msg_len; + struct ipfix_msg_hdr *tmpl_data_msg; /* include records, set header of template, data */ + struct ipfix_msg_hdr *data_only_msg; /* include records, set header of data */ }; struct ipfix_instance { @@ -155,36 +150,15 @@ static u_int16_t next_template_id = ULOGD_IPFIX_TEMPL_BASE; static int ipfix_fprintf_header(FILE *fd, const struct ipfix_msg_hdr *hdr); -/* Build the IPFIX template from the input keys */ struct ulogd_ipfix_template * -build_template_for_bitmask(struct ulogd_pluginstance *upi, +alloc_ulogd_ipfix_template(struct ulogd_pluginstance *upi, struct nfct_bitmask *bm) { struct ulogd_ipfix_template *tmpl; - unsigned int i, j; - int size = sizeof(struct ulogd_ipfix_template) - + (upi->input.num_keys * sizeof(struct ipfix_vendor_field)); - - tmpl = malloc(size); - if (!tmpl) - return NULL; - memset(tmpl, 0, size); - - tmpl->bitmask = nfct_bitmask_clone(bm); - if (!tmpl->bitmask) { - free(tmpl); - return NULL; - } - - /* initialize template header */ - tmpl->tmpl.hdr.templ_id = htons(next_template_id++); - - tmpl->tmpl_cur = tmpl->tmpl.buf; - - tmpl->data_length = 0; - tmpl->until_template = template_per_ce(upi->config_kset).u.value; + unsigned int i; + int tmpl_len = 0, data_len = 0; - for (i = 0, j = 0; i < upi->input.num_keys; i++) { + for (i = 0; i < upi->input.num_keys; i++) { struct ulogd_key *key = &upi->input.keys[i]; int length = ulogd_key_size(key); @@ -204,27 +178,130 @@ build_template_for_bitmask(struct ulogd_pluginstance *upi, continue; } + if (key->ipfix.vendor == IPFIX_VENDOR_IETF) + tmpl_len += sizeof(struct ipfix_ietf_field); + else + tmpl_len += sizeof(struct ipfix_vendor_field); + + data_len += length; + } + + tmpl = calloc(sizeof(struct ulogd_ipfix_template), 1); + if (tmpl == NULL) + return NULL; + + tmpl->bitmask = nfct_bitmask_clone(bm); + if (!tmpl->bitmask) + goto free_tmpl; + + tmpl->data_only_msg_len = sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr) + data_len; + tmpl->tmpl_data_msg_len = tmpl->data_only_msg_len + + sizeof(struct ipfix_templ_rec_hdr) + + sizeof(struct ipfix_set_hdr) + tmpl_len; + + tmpl->tmpl_data_msg = malloc(tmpl->tmpl_data_msg_len); + if (tmpl->tmpl_data_msg == NULL) + goto free_bitmask; + memset(tmpl->tmpl_data_msg, 0, tmpl->tmpl_data_msg_len); + + tmpl->data_only_msg = malloc(tmpl->data_only_msg_len); + if (tmpl->data_only_msg == NULL) + goto free_tmpl_data_msg; + memset(tmpl->data_only_msg, 0, tmpl->data_only_msg_len); + + return tmpl; + +free_tmpl_data_msg: + free(tmpl->tmpl_data_msg); +free_bitmask: + free(tmpl->bitmask); +free_tmpl: + free(tmpl); + + return NULL; +} + +/* Build the IPFIX template from the input keys */ +struct ulogd_ipfix_template * +build_template_for_bitmask(struct ulogd_pluginstance *upi, + struct nfct_bitmask *bm) +{ + struct ulogd_ipfix_template *tmpl; + struct ipfix_msg_hdr *msg_hdr; + struct ipfix_templ_rec_hdr *tmpl_hdr; + struct ipfix_set_hdr *set_hdr; + unsigned int i, field_count; + void *ptr; + + tmpl = alloc_ulogd_ipfix_template(upi, bm); + if (tmpl == NULL) + return NULL; + + tmpl->until_template = template_per_ce(upi->config_kset).u.value; + + /* build template records */ + ptr = (void *)tmpl->tmpl_data_msg + sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr) + sizeof(struct ipfix_templ_rec_hdr); + for (i = 0, field_count = 0; i < upi->input.num_keys; i++) { + struct ulogd_key *key = &upi->input.keys[i]; + int length = ulogd_key_size(key); + + if (!(key->u.source->flags & ULOGD_RETF_VALID)) + continue; + if (length < 0 || length > 0xfffe) + continue; + if (key->ipfix.field_id == 0) + continue; + if (key->ipfix.vendor == IPFIX_VENDOR_IETF) { - struct ipfix_ietf_field *field = - (struct ipfix_ietf_field *) tmpl->tmpl_cur; + struct ipfix_ietf_field *field = (struct ipfix_ietf_field *)ptr; field->type = htons(key->ipfix.field_id); field->length = htons(length); - tmpl->tmpl_cur += sizeof(*field); + ptr += sizeof(*field); } else { - struct ipfix_vendor_field *field = - (struct ipfix_vendor_field *) tmpl->tmpl_cur; + struct ipfix_vendor_field *field =(struct ipfix_vendor_field *)ptr; field->type = htons(key->ipfix.field_id | 0x8000); - field->enterprise_num = htonl(key->ipfix.vendor); field->length = htons(length); - tmpl->tmpl_cur += sizeof(*field); + field->enterprise_num = htonl(key->ipfix.vendor); + ptr += sizeof(*field); } - tmpl->data_length += length; - j++; + field_count++; } - tmpl->tmpl.hdr.field_count = htons(j); + /** initialize ipfix message header with template and data */ + msg_hdr = tmpl->tmpl_data_msg; + msg_hdr->version = htons(10); + msg_hdr->length = htons(tmpl->tmpl_data_msg_len); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + + /* initialize template set header */ + set_hdr = (void *)msg_hdr + sizeof(*msg_hdr); + set_hdr->set_id = htons(2); + set_hdr->length = htons(tmpl->tmpl_data_msg_len - tmpl->data_only_msg_len); + + /* initialize template record header */ + tmpl_hdr = (void *)set_hdr + sizeof(*set_hdr); + tmpl_hdr->templ_id = htons(next_template_id++); + tmpl_hdr->field_count = htons(field_count); + + /* initialize data set header */ + set_hdr = ptr; + set_hdr->set_id = tmpl_hdr->templ_id; + set_hdr->length = htons(tmpl->data_only_msg_len - sizeof(struct ipfix_msg_hdr)); + + /** initialize ipfix message header with data only */ + msg_hdr = tmpl->data_only_msg; + msg_hdr->version = htons(10); + msg_hdr->length = htons(tmpl->data_only_msg_len); + msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); + + /* initialize data set header */ + set_hdr = (void *)msg_hdr + sizeof(*msg_hdr); + set_hdr->set_id = tmpl_hdr->templ_id; + set_hdr->length = htons(tmpl->data_only_msg_len - sizeof(struct ipfix_msg_hdr)); return tmpl; } @@ -321,59 +398,36 @@ static struct ipfix_msg_hdr *build_ipfix_msg(struct ulogd_pluginstance *upi, bool need_template) { struct ipfix_instance *ii = (struct ipfix_instance *) &upi->private; - u_int16_t tmpl_len; struct ipfix_msg_hdr *msg_hdr; - struct ipfix_templ_rec_hdr *tmpl_hdr; - struct ipfix_set_hdr *data_hdr, *tmpl_set_hdr; - void *buf; - int msglen, ret; - - msglen = sizeof(struct ipfix_msg_hdr) + sizeof(struct ipfix_set_hdr) - + template->data_length; - if (need_template) - msglen = msglen + sizeof(struct ipfix_set_hdr) - + (template->tmpl_cur - (void *)&template->tmpl); - buf = malloc(msglen); - if (buf == NULL) - return NULL; - memset(buf, 0, msglen); + void *data_records; + int ret, data_len; - /* ipfix msg header */ - msg_hdr = buf; - msg_hdr->version = htons(10); - msg_hdr->length = htons(msglen); - msg_hdr->seq = htonl(ii->seq++); - msg_hdr->domain_id = htonl(domain_ce(upi->config_kset).u.value); if (need_template) { - /* put set header and template records */ - tmpl_set_hdr = buf + sizeof(*msg_hdr); - tmpl_set_hdr->set_id = htons(2); - tmpl_len = template->tmpl_cur - (void *)&template->tmpl; - tmpl_set_hdr->length = htons(sizeof(*tmpl_set_hdr) + tmpl_len); - tmpl_hdr = (void *)tmpl_set_hdr + sizeof(*tmpl_set_hdr); - memcpy((void *)tmpl_hdr, (void *)&template->tmpl, tmpl_len); - data_hdr = (void *)tmpl_hdr + tmpl_len; + int tmpl_len = template->tmpl_data_msg_len - template->data_only_msg_len; + msg_hdr = template->tmpl_data_msg; + data_records = (void *)msg_hdr + sizeof(struct ipfix_msg_hdr) + + tmpl_len + sizeof(struct ipfix_set_hdr); } else { - data_hdr = buf + sizeof(*msg_hdr); + msg_hdr = template->data_only_msg; + data_records = (void *)msg_hdr + sizeof(struct ipfix_msg_hdr) + + sizeof(struct ipfix_set_hdr); } + msg_hdr->seq = htonl(ii->seq++); + + data_len = template->data_only_msg_len - sizeof(struct ipfix_msg_hdr) + - sizeof(struct ipfix_set_hdr); + memset(data_records, 0, data_len); - /* put set header and data records */ - data_hdr->set_id = template->tmpl.hdr.templ_id; /* already ordered */ - data_hdr->length = htons(sizeof(*data_hdr) + template->data_length); - ret = put_data_records(upi, template, (void *)data_hdr + sizeof(*data_hdr)); + ret = put_data_records(upi, template, data_records); if (ret < 0) { ulogd_log(ULOGD_ERROR, "could not build ipfix dataset"); - goto free_buf; - } else if (ret > msglen) { + return NULL; + } else if (ret > data_len) { ulogd_log(ULOGD_ERROR, "overflowed on building ipfix dataset"); - goto free_buf; + return NULL; } return msg_hdr; - -free_buf: - free(buf); - return NULL; } static int output_ipfix(struct ulogd_pluginstance *upi) @@ -418,10 +472,11 @@ static int output_ipfix(struct ulogd_pluginstance *upi) need_template = true; } - if (template->until_template-- == 0) { + if (template->until_template == 0) { need_template = true; template->until_template = template_per_ce(upi->config_kset).u.value; } + template->until_template--; ipfix_msg = build_ipfix_msg(upi, template, need_template); if (ipfix_msg == NULL) @@ -431,7 +486,6 @@ static int output_ipfix(struct ulogd_pluginstance *upi) ipfix_fprintf_header(stdout, ipfix_msg); fprintf(stdout, "\n"); - free(ipfix_msg); return ULOGD_IRET_OK; } -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 10/13] nfct: fix ipfix field_id of flow.end.usec 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (8 preceding siblings ...) 2014-04-28 11:52 ` [ulogd PATCH 9/13] ipfix: build headers with template Ken-ichirou MATSUZAWA @ 2014-04-28 11:53 ` Ken-ichirou MATSUZAWA 2014-04-28 11:54 ` [ulogd PATCH 11/13] nfct/ipfix: introduce new vendor id Ken-ichirou MATSUZAWA ` (2 subsequent siblings) 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:53 UTC (permalink / raw) To: The netfilter developer mailinglist Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- input/flow/ulogd_inpflow_NFCT.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c index 899b7e3..0b64a45 100644 --- a/input/flow/ulogd_inpflow_NFCT.c +++ b/input/flow/ulogd_inpflow_NFCT.c @@ -399,7 +399,7 @@ static struct ulogd_key nfct_okeys[] = { .name = "flow.end.usec", .ipfix = { .vendor = IPFIX_VENDOR_IETF, - .field_id = IPFIX_flowEndSeconds, + .field_id = IPFIX_flowEndMicroSeconds, }, }, { -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 11/13] nfct/ipfix: introduce new vendor id 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (9 preceding siblings ...) 2014-04-28 11:53 ` [ulogd PATCH 10/13] nfct: fix ipfix field_id of flow.end.usec Ken-ichirou MATSUZAWA @ 2014-04-28 11:54 ` Ken-ichirou MATSUZAWA 2014-04-28 11:56 ` [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp Ken-ichirou MATSUZAWA 2014-04-28 11:57 ` [ulogd PATCH 13/13] ipfix: add debug symbol for yafscii Ken-ichirou MATSUZAWA 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:54 UTC (permalink / raw) To: The netfilter developer mailinglist IPFIX_VENDOR_REVERSE, defined in RFC 5103 6.1 Reverse Information Element Private Enterprise Number. And use it at counter in nfct. Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- include/ulogd/ipfix_protocol.h | 3 +++ input/flow/ulogd_inpflow_NFCT.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/ulogd/ipfix_protocol.h b/include/ulogd/ipfix_protocol.h index 266897e..86a0e84 100644 --- a/include/ulogd/ipfix_protocol.h +++ b/include/ulogd/ipfix_protocol.h @@ -9,6 +9,9 @@ /* defined in http://www.iana.org/assignments/enterprise-numbers */ #define IPFIX_VENDOR_NETFILTER 21373 /* FIXME: htonl? */ +/* defined in RFC 5103 IPFIX Biflow Export */ +#define IPFIX_VENDOR_REVERSE 29305 + /* Section 3.1 */ struct ipfix_msg_hdr { u_int16_t version; diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c index 0b64a45..4f4301e 100644 --- a/input/flow/ulogd_inpflow_NFCT.c +++ b/input/flow/ulogd_inpflow_NFCT.c @@ -309,7 +309,7 @@ static struct ulogd_key nfct_okeys[] = { .flags = ULOGD_RETF_NONE, .name = "reply.raw.pktlen", .ipfix = { - .vendor = IPFIX_VENDOR_IETF, + .vendor = IPFIX_VENDOR_REVERSE, .field_id = IPFIX_octetTotalCount, /* FIXME: this could also be octetDeltaCount */ }, @@ -319,7 +319,7 @@ static struct ulogd_key nfct_okeys[] = { .flags = ULOGD_RETF_NONE, .name = "reply.raw.pktcount", .ipfix = { - .vendor = IPFIX_VENDOR_IETF, + .vendor = IPFIX_VENDOR_REVERSE, .field_id = IPFIX_packetTotalCount, /* FIXME: this could also be packetDeltaCount */ }, -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (10 preceding siblings ...) 2014-04-28 11:54 ` [ulogd PATCH 11/13] nfct/ipfix: introduce new vendor id Ken-ichirou MATSUZAWA @ 2014-04-28 11:56 ` Ken-ichirou MATSUZAWA 2014-06-01 10:28 ` Eric Leblond 2014-04-28 11:57 ` [ulogd PATCH 13/13] ipfix: add debug symbol for yafscii Ken-ichirou MATSUZAWA 12 siblings, 1 reply; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:56 UTC (permalink / raw) To: The netfilter developer mailinglist Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- input/flow/ulogd_inpflow_NFCT.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c index 4f4301e..b31c46f 100644 --- a/input/flow/ulogd_inpflow_NFCT.c +++ b/input/flow/ulogd_inpflow_NFCT.c @@ -186,8 +186,10 @@ enum nfct_keys { NFCT_CT_EVENT, NFCT_FLOW_START_SEC, NFCT_FLOW_START_USEC, + NFCT_FLOW_START_MCSEC, NFCT_FLOW_END_SEC, NFCT_FLOW_END_USEC, + NFCT_FLOW_END_MCSEC, NFCT_OOB_FAMILY, NFCT_OOB_PROTOCOL, NFCT_CT, @@ -379,6 +381,11 @@ static struct ulogd_key nfct_okeys[] = { .type = ULOGD_RET_UINT32, .flags = ULOGD_RETF_NONE, .name = "flow.start.usec", + }, + { + .type = ULOGD_RET_UINT64, + .flags = ULOGD_RETF_NONE, + .name = "flow.start.mcsec", .ipfix = { .vendor = IPFIX_VENDOR_IETF, .field_id = IPFIX_flowStartMicroSeconds, @@ -397,6 +404,11 @@ static struct ulogd_key nfct_okeys[] = { .type = ULOGD_RET_UINT32, .flags = ULOGD_RETF_NONE, .name = "flow.end.usec", + }, + { + .type = ULOGD_RET_UINT64, + .flags = ULOGD_RETF_NONE, + .name = "flow.end.mcsec", .ipfix = { .vendor = IPFIX_VENDOR_IETF, .field_id = IPFIX_flowEndMicroSeconds, @@ -485,6 +497,13 @@ static int compare(const void *data1, const void *data2) return nfct_cmp(u1->ct, ct, NFCT_CMP_ORIG | NFCT_CMP_REPL); } +static inline uint64_t tv2ntp(const struct timeval t) +{ + /* RFC7101 - 6.1.10. dateTimeNanoseconds */ + return (uint64_t) (t.tv_sec << 32) + + (t.tv_usec << 32) / (NSEC_PER_SEC / 1000); +} + /* only the main_upi plugin instance contains the correct private data. */ static int propagate_ct(struct ulogd_pluginstance *main_upi, struct ulogd_pluginstance *upi, @@ -579,12 +598,16 @@ static int propagate_ct(struct ulogd_pluginstance *main_upi, ts->time[START].tv_sec); okey_set_u32(&ret[NFCT_FLOW_START_USEC], ts->time[START].tv_usec); + okey_set_u64(&ret[NFCT_FLOW_START_MCSEC], + tv2ntp(ts->time[START])); } if (ts->time[STOP].tv_sec) { okey_set_u32(&ret[NFCT_FLOW_END_SEC], ts->time[STOP].tv_sec); okey_set_u32(&ret[NFCT_FLOW_END_USEC], ts->time[STOP].tv_usec); + okey_set_u64(&ret[NFCT_FLOW_END_MCSEC], + tv2ntp(ts->time[STOP])); } } okey_set_ptr(&ret[NFCT_CT], cpi->ct); -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp 2014-04-28 11:56 ` [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp Ken-ichirou MATSUZAWA @ 2014-06-01 10:28 ` Eric Leblond 2014-06-02 9:52 ` Pablo Neira Ayuso 0 siblings, 1 reply; 45+ messages in thread From: Eric Leblond @ 2014-06-01 10:28 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Hi, First of all, sorry for the delay in the review. Don't hesitate to ping me back to speed up the answer. I'm agree with most of your patches but not with this one: * It causes useless computation for most output supporting NFCT (which don't use this value). * It will also cause the log all keys module like JSON to log a supplementary (ad useless) fields It will be better to introduce a new filter module. That will produce the wanted key from the existing timestamp key. On Mon, 2014-04-28 at 20:56 +0900, Ken-ichirou MATSUZAWA wrote: > Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> > --- > input/flow/ulogd_inpflow_NFCT.c | 23 +++++++++++++++++++++++ > 1 file changed, 23 insertions(+) > > diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c > index 4f4301e..b31c46f 100644 > --- a/input/flow/ulogd_inpflow_NFCT.c > +++ b/input/flow/ulogd_inpflow_NFCT.c > @@ -186,8 +186,10 @@ enum nfct_keys { > NFCT_CT_EVENT, > NFCT_FLOW_START_SEC, > NFCT_FLOW_START_USEC, > + NFCT_FLOW_START_MCSEC, > NFCT_FLOW_END_SEC, > NFCT_FLOW_END_USEC, > + NFCT_FLOW_END_MCSEC, > NFCT_OOB_FAMILY, > NFCT_OOB_PROTOCOL, > NFCT_CT, > @@ -379,6 +381,11 @@ static struct ulogd_key nfct_okeys[] = { > .type = ULOGD_RET_UINT32, > .flags = ULOGD_RETF_NONE, > .name = "flow.start.usec", > + }, > + { > + .type = ULOGD_RET_UINT64, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.start.mcsec", > .ipfix = { > .vendor = IPFIX_VENDOR_IETF, > .field_id = IPFIX_flowStartMicroSeconds, > @@ -397,6 +404,11 @@ static struct ulogd_key nfct_okeys[] = { > .type = ULOGD_RET_UINT32, > .flags = ULOGD_RETF_NONE, > .name = "flow.end.usec", > + }, > + { > + .type = ULOGD_RET_UINT64, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.end.mcsec", > .ipfix = { > .vendor = IPFIX_VENDOR_IETF, > .field_id = IPFIX_flowEndMicroSeconds, > @@ -485,6 +497,13 @@ static int compare(const void *data1, const void *data2) > return nfct_cmp(u1->ct, ct, NFCT_CMP_ORIG | NFCT_CMP_REPL); > } > > +static inline uint64_t tv2ntp(const struct timeval t) > +{ > + /* RFC7101 - 6.1.10. dateTimeNanoseconds */ > + return (uint64_t) (t.tv_sec << 32) > + + (t.tv_usec << 32) / (NSEC_PER_SEC / 1000); > +} > + > /* only the main_upi plugin instance contains the correct private data. */ > static int propagate_ct(struct ulogd_pluginstance *main_upi, > struct ulogd_pluginstance *upi, > @@ -579,12 +598,16 @@ static int propagate_ct(struct ulogd_pluginstance *main_upi, > ts->time[START].tv_sec); > okey_set_u32(&ret[NFCT_FLOW_START_USEC], > ts->time[START].tv_usec); > + okey_set_u64(&ret[NFCT_FLOW_START_MCSEC], > + tv2ntp(ts->time[START])); > } > if (ts->time[STOP].tv_sec) { > okey_set_u32(&ret[NFCT_FLOW_END_SEC], > ts->time[STOP].tv_sec); > okey_set_u32(&ret[NFCT_FLOW_END_USEC], > ts->time[STOP].tv_usec); > + okey_set_u64(&ret[NFCT_FLOW_END_MCSEC], > + tv2ntp(ts->time[STOP])); > } > } > okey_set_ptr(&ret[NFCT_CT], cpi->ct); BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp 2014-06-01 10:28 ` Eric Leblond @ 2014-06-02 9:52 ` Pablo Neira Ayuso 2014-06-02 12:51 ` Ken-ichirou MATSUZAWA 0 siblings, 1 reply; 45+ messages in thread From: Pablo Neira Ayuso @ 2014-06-02 9:52 UTC (permalink / raw) To: Eric Leblond; +Cc: Ken-ichirou MATSUZAWA, The netfilter developer mailinglist On Sun, Jun 01, 2014 at 12:28:32PM +0200, Eric Leblond wrote: > On Mon, 2014-04-28 at 20:56 +0900, Ken-ichirou MATSUZAWA wrote: > > Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> > > --- > > input/flow/ulogd_inpflow_NFCT.c | 23 +++++++++++++++++++++++ > > 1 file changed, 23 insertions(+) > > > > diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c > > index 4f4301e..b31c46f 100644 > > --- a/input/flow/ulogd_inpflow_NFCT.c > > +++ b/input/flow/ulogd_inpflow_NFCT.c > > @@ -186,8 +186,10 @@ enum nfct_keys { > > NFCT_CT_EVENT, > > NFCT_FLOW_START_SEC, > > NFCT_FLOW_START_USEC, > > + NFCT_FLOW_START_MCSEC, Perhaps you can consolidate this and provide just one single keys in milliseconds? > > NFCT_FLOW_END_SEC, > > NFCT_FLOW_END_USEC, > > + NFCT_FLOW_END_MCSEC, > > NFCT_OOB_FAMILY, > > NFCT_OOB_PROTOCOL, > > NFCT_CT, It will just need to adapt other extensions to use it. ^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp 2014-06-02 9:52 ` Pablo Neira Ayuso @ 2014-06-02 12:51 ` Ken-ichirou MATSUZAWA 2014-06-02 18:59 ` Eric Leblond 0 siblings, 1 reply; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-06-02 12:51 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: Eric Leblond, The netfilter developer mailinglist Hello, I thought it may be better to introduce a new filter too as Eric suggested and I need uptime for netflow v9, then I'd written it. Appended patch can be applied after some patches which I've not sent. On Mon, Jun 02, 2014 at 11:52:37AM +0200, Pablo Neira Ayuso wrote: > Perhaps you can consolidate this and provide just one single keys in > milliseconds? I intend to resend this patch later, or should I consolidate usec to single u64 out key in NFCT plugin? This filter creates IPFIX_flow(Start|End)MicroSeconds and IPFIX_flow(Start|End)SysUpTime from "flow.(start|end).sec" and "flow.(start|end).usec". Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- filter/Makefile.am | 6 +- filter/ulogd_filter_TIMECONV.c | 283 ++++++++++++++++++++++++++++++++++++++++ input/flow/ulogd_inpflow_NFCT.c | 8 -- 3 files changed, 288 insertions(+), 9 deletions(-) create mode 100644 filter/ulogd_filter_TIMECONV.c diff --git a/filter/Makefile.am b/filter/Makefile.am index 4077e98..cde943c 100644 --- a/filter/Makefile.am +++ b/filter/Makefile.am @@ -7,7 +7,8 @@ pkglib_LTLIBRARIES = ulogd_filter_IFINDEX.la ulogd_filter_PWSNIFF.la \ ulogd_filter_PRINTPKT.la ulogd_filter_PRINTFLOW.la \ ulogd_filter_IP2STR.la ulogd_filter_IP2BIN.la \ ulogd_filter_HWHDR.la ulogd_filter_MARK.la \ - ulogd_filter_IP2HBIN.la ulogd_filter_PACKICMP.la + ulogd_filter_IP2HBIN.la ulogd_filter_PACKICMP.la \ + ulogd_filter_TIMECONV.la ulogd_filter_IFINDEX_la_SOURCES = ulogd_filter_IFINDEX.c ulogd_filter_IFINDEX_la_LDFLAGS = -avoid-version -module @@ -39,3 +40,6 @@ ulogd_filter_PRINTFLOW_la_LDFLAGS = -avoid-version -module ulogd_filter_PACKICMP_la_SOURCES = ulogd_filter_PACKICMP.c ulogd_filter_PACKICMP_la_LDFLAGS = -avoid-version -module + +ulogd_filter_TIMECONV_la_SOURCES = ulogd_filter_TIMECONV.c +ulogd_filter_TIMECONV_la_LDFLAGS = -avoid-version -module diff --git a/filter/ulogd_filter_TIMECONV.c b/filter/ulogd_filter_TIMECONV.c new file mode 100644 index 0000000..0d0072f --- /dev/null +++ b/filter/ulogd_filter_TIMECONV.c @@ -0,0 +1,283 @@ +/* ulogd_filter_TIMECONV.c + * + * ulogd interpreter plugin for IPFIX / Netflow v9 to create + * IPFIX_flow(Start|End)MicroSeconds, IPFIX_flow(Start|End)SysUpTime + * + * (C) 2014 by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define _GNU_SOURCE /* for memmem() */ + +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <ulogd/ulogd.h> +#include <ulogd/ipfix_protocol.h> + +#ifndef NSEC_PER_SEC +#define NSEC_PER_SEC 1000000000L +#endif + +#define PROC_TIMER_LIST "/proc/timer_list" + +struct timeconv_priv { + uint64_t rtoffset; /* in ns */ + void (*setfunc)(struct ulogd_key *, uint64_t, + uint32_t, uint32_t, uint32_t, uint32_t); +}; + +enum { + CONFKEY_USEC64, + CONFKEY_UPTIME, +}; + +static struct config_keyset config_keys = { + .num_ces = 2, + .ces = { + { + .key = "usec64", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 1, + }, + { + .key = "uptime", + .type = CONFIG_TYPE_INT, + .options = CONFIG_OPT_NONE, + .u.value = 1, + }, + }, +}; + +#define usec64_ce(x) ((x)->ces[CONFKEY_USEC64]) +#define uptime_ce(x) ((x)->ces[CONFKEY_UPTIME]) + +enum { + IKEY_FLOW_START_SEC, + IKEY_FLOW_START_USEC, + IKEY_FLOW_END_SEC, + IKEY_FLOW_END_USEC, + IKEY_MAX = IKEY_FLOW_END_USEC, +}; + +static struct ulogd_key input_keys[] = { + [IKEY_FLOW_START_SEC] = { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "flow.start.sec", + }, + [IKEY_FLOW_START_USEC] = { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "flow.start.usec", + }, + [IKEY_FLOW_END_SEC] = { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "flow.end.sec", + }, + [IKEY_FLOW_END_USEC] = { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "flow.end.usec", + }, +}; + +enum output_key_index { + OKEY_FLOW_START_USEC64, + OKEY_FLOW_END_USEC64, + OKEY_FLOW_START_UPTIME, + OKEY_FLOW_END_UPTIME, + OKEY_MAX = OKEY_FLOW_END_UPTIME, +}; + +static struct ulogd_key output_keys[] = { + [OKEY_FLOW_START_USEC64] = { + .type = ULOGD_RET_UINT64, + .flags = ULOGD_RETF_NONE, + .name = "flow.start.useconds", + .ipfix = { + .vendor = IPFIX_VENDOR_IETF, + .field_id = IPFIX_flowStartMicroSeconds, + }, + }, + [OKEY_FLOW_END_USEC64] = { + .type = ULOGD_RET_UINT64, + .flags = ULOGD_RETF_NONE, + .name = "flow.end.useconds", + .ipfix = { + .vendor = IPFIX_VENDOR_IETF, + .field_id = IPFIX_flowEndMicroSeconds, + }, + }, + [OKEY_FLOW_START_UPTIME] = { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "flow.start.uptime", + .ipfix = { + .vendor = IPFIX_VENDOR_IETF, + .field_id = IPFIX_flowStartSysUpTime, + }, + }, + [OKEY_FLOW_END_UPTIME] = { + .type = ULOGD_RET_UINT32, + .flags = ULOGD_RETF_NONE, + .name = "flow.end.uptime", + .ipfix = { + .vendor = IPFIX_VENDOR_IETF, + .field_id = IPFIX_flowEndSysUpTime, + }, + }, +}; + +static inline uint64_t conv_ntp_us(uint32_t sec, uint32_t usec) +{ + /* RFC7011 - 6.1.10. dateTimeMicroseconds */ + return (((uint64_t) sec << 32) + + ((uint64_t) usec << 32) / (NSEC_PER_SEC / 1000)) + & ~0x7ff; +} + +void set_ntp(struct ulogd_key *okeys, uint64_t offset, + uint32_t start_sec, uint32_t start_usec, + uint32_t end_sec, uint32_t end_usec) +{ + okey_set_u64(&okeys[OKEY_FLOW_START_USEC64], + conv_ntp_us(start_sec, start_usec)); + okey_set_u64(&okeys[OKEY_FLOW_END_USEC64], + conv_ntp_us(end_sec, end_usec)); + +} + +static inline uint32_t conv_uptime(uint64_t offset, uint32_t sec, uint32_t usec) +{ + return (sec - offset / NSEC_PER_SEC) * 1000 + + usec / 1000 - (offset % NSEC_PER_SEC) / 1000000; +} + +void set_uptime(struct ulogd_key *okeys, uint64_t offset, + uint32_t start_sec, uint32_t start_usec, + uint32_t end_sec, uint32_t end_usec) +{ + okey_set_u32(&okeys[OKEY_FLOW_START_UPTIME], + conv_uptime(offset, start_sec, start_usec)); + okey_set_u32(&okeys[OKEY_FLOW_END_UPTIME], + conv_uptime(offset, end_sec, end_usec)); +} +void set_ntp_uptime(struct ulogd_key *okeys, uint64_t offset, + uint32_t start_sec, uint32_t start_usec, + uint32_t end_sec, uint32_t end_usec) +{ + set_ntp(okeys, offset, start_sec, start_usec, end_sec, end_usec); + set_uptime(okeys, offset, start_sec, start_usec, end_sec, end_usec); +} + +static int interp_timeconv(struct ulogd_pluginstance *upi) +{ + struct timeconv_priv *priv = + (struct timeconv_priv *)upi->private; + struct ulogd_key *inp = upi->input.keys; + + if (!pp_is_valid(inp, IKEY_FLOW_START_SEC) + || !pp_is_valid(inp, IKEY_FLOW_START_USEC) + || !pp_is_valid(inp, IKEY_FLOW_END_SEC) + || !pp_is_valid(inp, IKEY_FLOW_END_USEC)) + return ULOGD_IRET_ERR; + + priv->setfunc(upi->output.keys, priv->rtoffset, + ikey_get_u32(&inp[IKEY_FLOW_START_SEC]), + ikey_get_u32(&inp[IKEY_FLOW_START_USEC]), + ikey_get_u32(&inp[IKEY_FLOW_END_SEC]), + ikey_get_u32(&inp[IKEY_FLOW_END_USEC])); + + return ULOGD_IRET_OK; +} + +static int configure_timeconv(struct ulogd_pluginstance *upi, + struct ulogd_pluginstance_stack *stack) +{ + return config_parse_file(upi->id, upi->config_kset); +} + +static int start_timeconv(struct ulogd_pluginstance *upi) +{ + struct timeconv_priv *priv = + (struct timeconv_priv *)upi->private; + int fd; + ssize_t nread; + char buf[4096]; /* XXX: MAGIC NUMBER */ + char *s = "ktime_get_real\n .offset: "; + void *p; + size_t slen = strlen(s); + + /* get rt offset */ + fd = open(PROC_TIMER_LIST, O_RDONLY); + if (fd == -1) + return -1; + nread = read(fd, buf, sizeof(buf)); + close(fd); + if (nread == -1) + return -1; + p = memmem(buf, nread, s, slen); + if (p == NULL) + return -1; + if (sscanf(p + slen, " %"PRIu64, &priv->rtoffset) == EOF) + return -1; + + /* select set function */ + if (usec64_ce(upi->config_kset).u.value) + if (uptime_ce(upi->config_kset).u.value) + priv->setfunc = &set_ntp_uptime; + else + priv->setfunc = &set_ntp; + else if (uptime_ce(upi->config_kset).u.value) + priv->setfunc = &set_uptime; + else + return -1; + + return 0; +} + +static struct ulogd_plugin timeconv_plugin = { + .name = "TIMECONV", + .input = { + .keys = input_keys, + .num_keys = ARRAY_SIZE(input_keys), + .type = ULOGD_DTYPE_PACKET | ULOGD_DTYPE_FLOW, + }, + .output = { + .keys = output_keys, + .num_keys = ARRAY_SIZE(output_keys), + .type = ULOGD_DTYPE_PACKET | ULOGD_DTYPE_FLOW, + }, + .config_kset = &config_keys, + .interp = &interp_timeconv, + .configure = &configure_timeconv, + .start = &start_timeconv, + .priv_size = sizeof(struct timeconv_priv), + .version = VERSION, +}; + +void __attribute__ ((constructor)) init(void); + +void init(void) +{ + ulogd_register_plugin(&timeconv_plugin); +} diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c index fce5273..cb3bf45 100644 --- a/input/flow/ulogd_inpflow_NFCT.c +++ b/input/flow/ulogd_inpflow_NFCT.c @@ -442,10 +442,6 @@ static struct ulogd_key nfct_okeys[] = { .type = ULOGD_RET_UINT32, .flags = ULOGD_RETF_NONE, .name = "flow.start.usec", - .ipfix = { - .vendor = IPFIX_VENDOR_IETF, - .field_id = IPFIX_flowStartMicroSeconds, - }, }, { .type = ULOGD_RET_UINT32, @@ -460,10 +456,6 @@ static struct ulogd_key nfct_okeys[] = { .type = ULOGD_RET_UINT32, .flags = ULOGD_RETF_NONE, .name = "flow.end.usec", - .ipfix = { - .vendor = IPFIX_VENDOR_IETF, - .field_id = IPFIX_flowEndMicroSeconds, - }, }, { .type = ULOGD_RET_UINT8, -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp 2014-06-02 12:51 ` Ken-ichirou MATSUZAWA @ 2014-06-02 18:59 ` Eric Leblond 0 siblings, 0 replies; 45+ messages in thread From: Eric Leblond @ 2014-06-02 18:59 UTC (permalink / raw) To: Ken-ichirou MATSUZAWA; +Cc: The netfilter developer mailinglist Hello, On Mon, 2014-06-02 at 21:51 +0900, Ken-ichirou MATSUZAWA wrote: > Hello, > > I thought it may be better to introduce a new filter too as Eric > suggested and I need uptime for netflow v9, then I'd written it. > Appended patch can be applied after some patches which I've not > sent. It looks ok. Some comments inline. > > On Mon, Jun 02, 2014 at 11:52:37AM +0200, Pablo Neira Ayuso wrote: > > Perhaps you can consolidate this and provide just one single keys in > > milliseconds? > > I intend to resend this patch later, or should I consolidate usec > to single u64 out key in NFCT plugin? > > This filter creates IPFIX_flow(Start|End)MicroSeconds and > IPFIX_flow(Start|End)SysUpTime from "flow.(start|end).sec" and > "flow.(start|end).usec". > > Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> > --- > filter/Makefile.am | 6 +- > filter/ulogd_filter_TIMECONV.c | 283 ++++++++++++++++++++++++++++++++++++++++ > input/flow/ulogd_inpflow_NFCT.c | 8 -- > 3 files changed, 288 insertions(+), 9 deletions(-) > create mode 100644 filter/ulogd_filter_TIMECONV.c > > diff --git a/filter/Makefile.am b/filter/Makefile.am > index 4077e98..cde943c 100644 > --- a/filter/Makefile.am > +++ b/filter/Makefile.am > @@ -7,7 +7,8 @@ pkglib_LTLIBRARIES = ulogd_filter_IFINDEX.la ulogd_filter_PWSNIFF.la \ > ulogd_filter_PRINTPKT.la ulogd_filter_PRINTFLOW.la \ > ulogd_filter_IP2STR.la ulogd_filter_IP2BIN.la \ > ulogd_filter_HWHDR.la ulogd_filter_MARK.la \ > - ulogd_filter_IP2HBIN.la ulogd_filter_PACKICMP.la > + ulogd_filter_IP2HBIN.la ulogd_filter_PACKICMP.la \ > + ulogd_filter_TIMECONV.la > > ulogd_filter_IFINDEX_la_SOURCES = ulogd_filter_IFINDEX.c > ulogd_filter_IFINDEX_la_LDFLAGS = -avoid-version -module > @@ -39,3 +40,6 @@ ulogd_filter_PRINTFLOW_la_LDFLAGS = -avoid-version -module > > ulogd_filter_PACKICMP_la_SOURCES = ulogd_filter_PACKICMP.c > ulogd_filter_PACKICMP_la_LDFLAGS = -avoid-version -module > + > +ulogd_filter_TIMECONV_la_SOURCES = ulogd_filter_TIMECONV.c > +ulogd_filter_TIMECONV_la_LDFLAGS = -avoid-version -module > diff --git a/filter/ulogd_filter_TIMECONV.c b/filter/ulogd_filter_TIMECONV.c > new file mode 100644 > index 0000000..0d0072f > --- /dev/null > +++ b/filter/ulogd_filter_TIMECONV.c > @@ -0,0 +1,283 @@ > +/* ulogd_filter_TIMECONV.c > + * > + * ulogd interpreter plugin for IPFIX / Netflow v9 to create > + * IPFIX_flow(Start|End)MicroSeconds, IPFIX_flow(Start|End)SysUpTime > + * > + * (C) 2014 by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 > + * as published by the Free Software Foundation > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + * > + */ > + > +#define _GNU_SOURCE /* for memmem() */ > + > +#include <unistd.h> > +#include <string.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > + > +#include <ulogd/ulogd.h> > +#include <ulogd/ipfix_protocol.h> > + > +#ifndef NSEC_PER_SEC > +#define NSEC_PER_SEC 1000000000L > +#endif > + > +#define PROC_TIMER_LIST "/proc/timer_list" > + > +struct timeconv_priv { > + uint64_t rtoffset; /* in ns */ > + void (*setfunc)(struct ulogd_key *, uint64_t, > + uint32_t, uint32_t, uint32_t, uint32_t); > +}; > + > +enum { > + CONFKEY_USEC64, > + CONFKEY_UPTIME, > +}; > + > +static struct config_keyset config_keys = { > + .num_ces = 2, > + .ces = { > + { > + .key = "usec64", > + .type = CONFIG_TYPE_INT, > + .options = CONFIG_OPT_NONE, > + .u.value = 1, > + }, > + { > + .key = "uptime", > + .type = CONFIG_TYPE_INT, > + .options = CONFIG_OPT_NONE, > + .u.value = 1, > + }, > + }, > +}; > + > +#define usec64_ce(x) ((x)->ces[CONFKEY_USEC64]) > +#define uptime_ce(x) ((x)->ces[CONFKEY_UPTIME]) > + > +enum { > + IKEY_FLOW_START_SEC, > + IKEY_FLOW_START_USEC, > + IKEY_FLOW_END_SEC, > + IKEY_FLOW_END_USEC, > + IKEY_MAX = IKEY_FLOW_END_USEC, > +}; > + > +static struct ulogd_key input_keys[] = { > + [IKEY_FLOW_START_SEC] = { > + .type = ULOGD_RET_UINT32, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.start.sec", > + }, > + [IKEY_FLOW_START_USEC] = { > + .type = ULOGD_RET_UINT32, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.start.usec", > + }, > + [IKEY_FLOW_END_SEC] = { > + .type = ULOGD_RET_UINT32, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.end.sec", > + }, > + [IKEY_FLOW_END_USEC] = { > + .type = ULOGD_RET_UINT32, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.end.usec", > + }, > +}; > + > +enum output_key_index { > + OKEY_FLOW_START_USEC64, > + OKEY_FLOW_END_USEC64, > + OKEY_FLOW_START_UPTIME, > + OKEY_FLOW_END_UPTIME, > + OKEY_MAX = OKEY_FLOW_END_UPTIME, > +}; > + > +static struct ulogd_key output_keys[] = { > + [OKEY_FLOW_START_USEC64] = { > + .type = ULOGD_RET_UINT64, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.start.useconds", > + .ipfix = { > + .vendor = IPFIX_VENDOR_IETF, > + .field_id = IPFIX_flowStartMicroSeconds, > + }, > + }, > + [OKEY_FLOW_END_USEC64] = { > + .type = ULOGD_RET_UINT64, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.end.useconds", > + .ipfix = { > + .vendor = IPFIX_VENDOR_IETF, > + .field_id = IPFIX_flowEndMicroSeconds, > + }, > + }, > + [OKEY_FLOW_START_UPTIME] = { > + .type = ULOGD_RET_UINT32, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.start.uptime", > + .ipfix = { > + .vendor = IPFIX_VENDOR_IETF, > + .field_id = IPFIX_flowStartSysUpTime, > + }, > + }, > + [OKEY_FLOW_END_UPTIME] = { > + .type = ULOGD_RET_UINT32, > + .flags = ULOGD_RETF_NONE, > + .name = "flow.end.uptime", > + .ipfix = { > + .vendor = IPFIX_VENDOR_IETF, > + .field_id = IPFIX_flowEndSysUpTime, > + }, > + }, > +}; > + > +static inline uint64_t conv_ntp_us(uint32_t sec, uint32_t usec) > +{ > + /* RFC7011 - 6.1.10. dateTimeMicroseconds */ > + return (((uint64_t) sec << 32) > + + ((uint64_t) usec << 32) / (NSEC_PER_SEC / 1000)) > + & ~0x7ff; > +} > + > +void set_ntp(struct ulogd_key *okeys, uint64_t offset, > + uint32_t start_sec, uint32_t start_usec, > + uint32_t end_sec, uint32_t end_usec) > +{ > + okey_set_u64(&okeys[OKEY_FLOW_START_USEC64], > + conv_ntp_us(start_sec, start_usec)); > + okey_set_u64(&okeys[OKEY_FLOW_END_USEC64], > + conv_ntp_us(end_sec, end_usec)); > + > +} > + > +static inline uint32_t conv_uptime(uint64_t offset, uint32_t sec, uint32_t usec) > +{ > + return (sec - offset / NSEC_PER_SEC) * 1000 > + + usec / 1000 - (offset % NSEC_PER_SEC) / 1000000; > +} > + > +void set_uptime(struct ulogd_key *okeys, uint64_t offset, > + uint32_t start_sec, uint32_t start_usec, > + uint32_t end_sec, uint32_t end_usec) > +{ > + okey_set_u32(&okeys[OKEY_FLOW_START_UPTIME], > + conv_uptime(offset, start_sec, start_usec)); > + okey_set_u32(&okeys[OKEY_FLOW_END_UPTIME], > + conv_uptime(offset, end_sec, end_usec)); > +} Add a line here. > +void set_ntp_uptime(struct ulogd_key *okeys, uint64_t offset, > + uint32_t start_sec, uint32_t start_usec, > + uint32_t end_sec, uint32_t end_usec) > +{ > + set_ntp(okeys, offset, start_sec, start_usec, end_sec, end_usec); > + set_uptime(okeys, offset, start_sec, start_usec, end_sec, end_usec); > +} > + > +static int interp_timeconv(struct ulogd_pluginstance *upi) > +{ > + struct timeconv_priv *priv = > + (struct timeconv_priv *)upi->private; > + struct ulogd_key *inp = upi->input.keys; > + > + if (!pp_is_valid(inp, IKEY_FLOW_START_SEC) > + || !pp_is_valid(inp, IKEY_FLOW_START_USEC) > + || !pp_is_valid(inp, IKEY_FLOW_END_SEC) > + || !pp_is_valid(inp, IKEY_FLOW_END_USEC)) > + return ULOGD_IRET_ERR; > + > + priv->setfunc(upi->output.keys, priv->rtoffset, > + ikey_get_u32(&inp[IKEY_FLOW_START_SEC]), > + ikey_get_u32(&inp[IKEY_FLOW_START_USEC]), > + ikey_get_u32(&inp[IKEY_FLOW_END_SEC]), > + ikey_get_u32(&inp[IKEY_FLOW_END_USEC])); > + > + return ULOGD_IRET_OK; > +} > + > +static int configure_timeconv(struct ulogd_pluginstance *upi, > + struct ulogd_pluginstance_stack *stack) > +{ > + return config_parse_file(upi->id, upi->config_kset); > +} > + > +static int start_timeconv(struct ulogd_pluginstance *upi) > +{ > + struct timeconv_priv *priv = > + (struct timeconv_priv *)upi->private; > + int fd; > + ssize_t nread; > + char buf[4096]; /* XXX: MAGIC NUMBER */ > + char *s = "ktime_get_real\n .offset: "; > + void *p; > + size_t slen = strlen(s); > + > + /* get rt offset */ > + fd = open(PROC_TIMER_LIST, O_RDONLY); > + if (fd == -1) > + return -1; > + nread = read(fd, buf, sizeof(buf)); > + close(fd); > + if (nread == -1) > + return -1; > + p = memmem(buf, nread, s, slen); > + if (p == NULL) > + return -1; > + if (sscanf(p + slen, " %"PRIu64, &priv->rtoffset) == EOF) > + return -1; > + > + /* select set function */ > + if (usec64_ce(upi->config_kset).u.value) > + if (uptime_ce(upi->config_kset).u.value) > + priv->setfunc = &set_ntp_uptime; > + else > + priv->setfunc = &set_ntp; > + else if (uptime_ce(upi->config_kset).u.value) > + priv->setfunc = &set_uptime; > + else > + return -1; > + > + return 0; > +} > + > +static struct ulogd_plugin timeconv_plugin = { > + .name = "TIMECONV", > + .input = { > + .keys = input_keys, > + .num_keys = ARRAY_SIZE(input_keys), > + .type = ULOGD_DTYPE_PACKET | ULOGD_DTYPE_FLOW, > + }, > + .output = { > + .keys = output_keys, > + .num_keys = ARRAY_SIZE(output_keys), > + .type = ULOGD_DTYPE_PACKET | ULOGD_DTYPE_FLOW, > + }, > + .config_kset = &config_keys, > + .interp = &interp_timeconv, > + .configure = &configure_timeconv, > + .start = &start_timeconv, > + .priv_size = sizeof(struct timeconv_priv), > + .version = VERSION, > +}; > + > +void __attribute__ ((constructor)) init(void); > + > +void init(void) > +{ > + ulogd_register_plugin(&timeconv_plugin); > +} > diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c > index fce5273..cb3bf45 100644 > --- a/input/flow/ulogd_inpflow_NFCT.c > +++ b/input/flow/ulogd_inpflow_NFCT.c We will not need the following code in the final version ;) > @@ -442,10 +442,6 @@ static struct ulogd_key nfct_okeys[] = { > .type = ULOGD_RET_UINT32, > .flags = ULOGD_RETF_NONE, > .name = "flow.start.usec", > - .ipfix = { > - .vendor = IPFIX_VENDOR_IETF, > - .field_id = IPFIX_flowStartMicroSeconds, > - }, > }, > { > .type = ULOGD_RET_UINT32, > @@ -460,10 +456,6 @@ static struct ulogd_key nfct_okeys[] = { > .type = ULOGD_RET_UINT32, > .flags = ULOGD_RETF_NONE, > .name = "flow.end.usec", > - .ipfix = { > - .vendor = IPFIX_VENDOR_IETF, > - .field_id = IPFIX_flowEndMicroSeconds, > - }, > }, > { > .type = ULOGD_RET_UINT8, BR, -- Eric Leblond <eric@regit.org> ^ permalink raw reply [flat|nested] 45+ messages in thread
* [ulogd PATCH 13/13] ipfix: add debug symbol for yafscii 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA ` (11 preceding siblings ...) 2014-04-28 11:56 ` [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp Ken-ichirou MATSUZAWA @ 2014-04-28 11:57 ` Ken-ichirou MATSUZAWA 12 siblings, 0 replies; 45+ messages in thread From: Ken-ichirou MATSUZAWA @ 2014-04-28 11:57 UTC (permalink / raw) To: The netfilter developer mailinglist http://tools.netsa.cert.org/yaf/yafscii.html To see flow created by yafscii yafscii --in /tmp/ulogd.yaf and see /tmp/ulogd.yaf.txt Signed-off-by Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp> --- output/ulogd_output_IPFIX.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/output/ulogd_output_IPFIX.c b/output/ulogd_output_IPFIX.c index 2c77264..e0495d2 100644 --- a/output/ulogd_output_IPFIX.c +++ b/output/ulogd_output_IPFIX.c @@ -38,6 +38,12 @@ #include <sys/socket.h> #include <netdb.h> +#define DEBUG_YAFSCII_FILE "/tmp/ulogd.yaf" +#ifdef DEBUG_YAFSCII_FILE +#include <sys/stat.h> +#include <sys/fcntl.h> +#endif + #include <libnetfilter_conntrack/libnetfilter_conntrack.h> #include <ulogd/linuxlist.h> @@ -143,6 +149,10 @@ struct ipfix_instance { struct llist_head template_list; struct nfct_bitmask *valid_bitmask; /* bitmask of valid keys */ u_int32_t seq; + +#ifdef DEBUG_YAFSCII_FILE + int yaf_fd; +#endif }; #define ULOGD_IPFIX_TEMPL_BASE 1024 @@ -486,6 +496,9 @@ static int output_ipfix(struct ulogd_pluginstance *upi) ipfix_fprintf_header(stdout, ipfix_msg); fprintf(stdout, "\n"); +#ifdef DEBUG_YAFSCII_FILE + write(ii->yaf_fd, ipfix_msg, ntohs(ipfix_msg->length)); +#endif return ULOGD_IRET_OK; } @@ -582,6 +595,10 @@ static int start_ipfix(struct ulogd_pluginstance *pi) if (ret < 0) goto out_bm_free; +#ifdef DEBUG_YAFSCII_FILE + ii->yaf_fd = open(DEBUG_YAFSCII_FILE, O_CREAT|O_WRONLY|O_TRUNC, S_IWUSR); +#endif + return 0; out_bm_free: @@ -595,6 +612,9 @@ static int stop_ipfix(struct ulogd_pluginstance *pi) { struct ipfix_instance *ii = (struct ipfix_instance *) &pi->private; +#ifdef DEBUG_YAFSCII_FILE + close(ii->yaf_fd); +#endif close(ii->fd); nfct_bitmask_destroy(ii->valid_bitmask); -- 1.9.1 ^ permalink raw reply related [flat|nested] 45+ messages in thread
end of thread, other threads:[~2014-06-02 18:59 UTC | newest] Thread overview: 45+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-03-08 1:03 [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA 2014-03-08 1:07 ` [PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-03-23 18:55 ` Eric Leblond 2014-03-08 1:09 ` [PATCH 2/8] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA 2014-03-08 1:10 ` [PATCH 3/8] ipfix: some cleanups Ken-ichirou MATSUZAWA 2014-03-08 1:12 ` [PATCH 4/8] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA 2014-03-08 1:13 ` [PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA 2014-03-23 20:06 ` Eric Leblond 2014-03-08 1:15 ` [PATCH 6/8] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA 2014-03-08 1:17 ` [PATCH 7/8] ipfix: print ipfix message Ken-ichirou MATSUZAWA 2014-03-08 1:19 ` [PATCH 8/8] ipfix: build headers with template Ken-ichirou MATSUZAWA 2014-03-08 1:24 ` [libnetfilter_conntrack PATCH] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA 2014-03-08 9:25 ` Florian Westphal 2014-03-23 18:50 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond 2014-03-26 12:11 ` Ken-ichirou MATSUZAWA 2014-03-26 12:16 ` [ulogd PATCH 1/8] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-03-26 12:18 ` [ulogd PATCH 2/8] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA 2014-03-26 12:19 ` [ulogd PATCH 3/8] ipfix: some cleanups Ken-ichirou MATSUZAWA 2014-03-26 12:23 ` [ulogd PATCH 4/8] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA 2014-03-26 12:25 ` [ulogd PATCH 5/8] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA 2014-03-26 12:26 ` [ulogd PATCH 6/8] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA 2014-03-26 12:28 ` [ulogd PATCH 7/8] ipfix: print ipfix message Ken-ichirou MATSUZAWA 2014-03-26 12:30 ` [ulogd PATCH 8/8] ipfix: build headers with template Ken-ichirou MATSUZAWA 2014-04-19 13:36 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Eric Leblond 2014-04-22 11:56 ` [ulogd PATCH 1/8 resend] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-04-22 12:03 ` [ulogd PATCH 0/8] make progress ulogd_output_IPFIX Ken-ichirou MATSUZAWA 2014-04-22 15:20 ` Eric Leblond 2014-04-28 11:39 ` [ulogd PATCH 0/13] " Ken-ichirou MATSUZAWA 2014-04-28 11:42 ` [libnetfilter_conntrack PATCH 1/13] conntrack: introduce clear and equal functions for bitmask object Ken-ichirou MATSUZAWA 2014-04-28 11:44 ` [ulogd PATCH 2/13] ipfix: use nfct_bitmask Ken-ichirou MATSUZAWA 2014-04-28 11:45 ` [ulogd PATCH 3/13] ipfix: fix enterprise bit handling Ken-ichirou MATSUZAWA 2014-04-28 11:46 ` [ulogd PATCH 4/13] ipfix: some cleanups Ken-ichirou MATSUZAWA 2014-04-28 11:48 ` [ulogd PATCH 5/13] ipfix: add functions for ipfix dataset creation Ken-ichirou MATSUZAWA 2014-04-28 11:49 ` [ulogd PATCH 6/13] ipfix: add function for ipfix message creation Ken-ichirou MATSUZAWA 2014-04-28 11:50 ` [ulogd PATCH 7/13] ipfix: decide whether prepending template by send times Ken-ichirou MATSUZAWA 2014-04-28 11:51 ` [ulogd PATCH 8/13] ipfix: print ipfix message Ken-ichirou MATSUZAWA 2014-04-28 11:52 ` [ulogd PATCH 9/13] ipfix: build headers with template Ken-ichirou MATSUZAWA 2014-04-28 11:53 ` [ulogd PATCH 10/13] nfct: fix ipfix field_id of flow.end.usec Ken-ichirou MATSUZAWA 2014-04-28 11:54 ` [ulogd PATCH 11/13] nfct/ipfix: introduce new vendor id Ken-ichirou MATSUZAWA 2014-04-28 11:56 ` [ulogd PATCH 12/13] nfct: introduce new out keys for ipfix timestamp Ken-ichirou MATSUZAWA 2014-06-01 10:28 ` Eric Leblond 2014-06-02 9:52 ` Pablo Neira Ayuso 2014-06-02 12:51 ` Ken-ichirou MATSUZAWA 2014-06-02 18:59 ` Eric Leblond 2014-04-28 11:57 ` [ulogd PATCH 13/13] ipfix: add debug symbol for yafscii Ken-ichirou MATSUZAWA
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).