@@ -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;
}