From patchwork Wed Mar 26 12:28:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken-ichirou MATSUZAWA X-Patchwork-Id: 333852 X-Patchwork-Delegate: regit@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 5ABC714008E for ; Wed, 26 Mar 2014 23:28:39 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752404AbaCZM2i (ORCPT ); Wed, 26 Mar 2014 08:28:38 -0400 Received: from mail-pa0-f46.google.com ([209.85.220.46]:65420 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751130AbaCZM2h (ORCPT ); Wed, 26 Mar 2014 08:28:37 -0400 Received: by mail-pa0-f46.google.com with SMTP id kp14so1853140pab.5 for ; Wed, 26 Mar 2014 05:28:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=NFt7vOmbmzNjpOM6jaWtaBsM+2c6wvY4uUSo/dwwcnc=; b=CzcX62LqVDGALfljHVO6iGySbYZ6W1w+42Na016IDFFXXTPKW1zGWB9RGXC5EDDrsD F6nK2zJmQ+e/pNggziXwGsRSi7FYTBIZ9oWQ1zEh13HiZCp5vrYuExuG9rHXStoyBYhO wbgtLb7rCmU8Oyz1kD9Yym7UUZiBQLhIDIN3ZeXWTKIM73iWawtZ4fvemqlTwDjA64Qg fIiHFc+Y2vtqIwsODBSW512/Lkgy1keBnzVcFIzuCZeQ4P89pf0xeWz/oa6MSeGHHzft dWZIAru813DIj8ROMZtFBXxP+Z7biJTpb+T1Hh4QmUIDsqMkaLw8L1dC/XzmAL70S8cw dLjw== X-Received: by 10.68.201.67 with SMTP id jy3mr86013531pbc.20.1395836917468; Wed, 26 Mar 2014 05:28:37 -0700 (PDT) Received: from gmail.com (softbank220009032017.bbtec.net. [220.9.32.17]) by mx.google.com with ESMTPSA id op3sm57679037pbc.40.2014.03.26.05.28.35 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Wed, 26 Mar 2014 05:28:36 -0700 (PDT) Date: Wed, 26 Mar 2014 21:28:31 +0900 From: Ken-ichirou MATSUZAWA To: Eric Leblond Cc: The netfilter developer mailinglist Subject: [ulogd PATCH 7/8] ipfix: print ipfix message Message-ID: <20140326122830.GH24689@gmail.com> References: <20140308010344.GA4415@gmail.com> <1395600620.23474.18.camel@ice-age2.regit.org> <20140326121122.GA24689@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20140326121122.GA24689@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org by messy ipfix_fprintf_ functions. Signed-off-by Ken-ichirou MATSUZAWA --- 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 #include #include +#include #include #include @@ -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; +}