Skip to content

Commit 2eaad5a

Browse files
committed
Viewer: Added module from old repository. Minor changes in output, mostly spaces and indentation has been fixed.
1 parent fefd6a1 commit 2eaad5a

File tree

9 files changed

+894
-1
lines changed

9 files changed

+894
-1
lines changed

src/plugins/output/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# List of output plugin to build and install
22
add_subdirectory(dummy)
3-
add_subdirectory(json)
3+
add_subdirectory(json)
4+
add_subdirectory(viewer)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Create a linkable module
2+
3+
add_library(viewer-output MODULE
4+
viewer.c
5+
config.c
6+
config.h
7+
Reader.h
8+
Reader.c
9+
)
10+
11+
install(
12+
TARGETS viewer-output
13+
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/ipfixcol2/"
14+
)
15+
16+
if (ENABLE_DOC_MANPAGE)
17+
# Build a manual page
18+
set(SRC_FILE "${CMAKE_CURRENT_SOURCE_DIR}/doc/ipfixcol2-viewer-output.7.rst")
19+
set(DST_FILE "${CMAKE_CURRENT_BINARY_DIR}/ipfixcol2-viewer-output.7")
20+
21+
add_custom_command(TARGET viewer-output PRE_BUILD
22+
COMMAND ${RST2MAN_EXECUTABLE} --syntax-highlight=none ${SRC_FILE} ${DST_FILE}
23+
DEPENDS ${SRC_FILE}
24+
VERBATIM
25+
)
26+
27+
install(
28+
FILES "${DST_FILE}"
29+
DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man7"
30+
)
31+
endif()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Viewer (output plugin)
2+
=====================
3+
4+
The plugin provides a way how to observe functionality of collector.
5+
Viewer module prints information about incoming IPFIX packets and data inside of them.
6+
7+
Example configuration
8+
---------------------
9+
10+
.. code-block:: xml
11+
12+
<output>
13+
<name>Viewer output</name>
14+
<plugin>viewer</plugin>
15+
<params>
16+
</params>
17+
</output>
18+
19+
Parameters
20+
----------
21+

src/plugins/output/viewer/Reader.c

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/**
2+
* \file src/plugins/output/viewer/Reader.c
3+
* \author Jan Kala <[email protected]>
4+
* \brief Viewer - output module for printing information about incoming packets on stdout (source file)
5+
* \date 2018
6+
*/
7+
/* Copyright (C) 2018 CESNET, z.s.p.o.
8+
*
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions
11+
* are met:
12+
* 1. Redistributions of source code must retain the above copyright
13+
* notice, this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in
16+
* the documentation and/or other materials provided with the
17+
* distribution.
18+
* 3. Neither the name of the Company nor the names of its contributors
19+
* may be used to endorse or promote products derived from this
20+
* software without specific prior written permission.
21+
*
22+
* ALTERNATIVELY, provided that this notice is retained in full, this
23+
* product may be distributed under the terms of the GNU General Public
24+
* License (GPL) version 2 or later, in which case the provisions
25+
* of the GPL apply INSTEAD OF those given above.
26+
*
27+
* This software is provided ``as is'', and any express or implied
28+
* warranties, including, but not limited to, the implied warranties of
29+
* merchantability and fitness for a particular purpose are disclaimed.
30+
* In no event shall the company or contributors be liable for any
31+
* direct, indirect, incidental, special, exemplary, or consequential
32+
* damages (including, but not limited to, procurement of substitute
33+
* goods or services; loss of use, data, or profits; or business
34+
* interruption) however caused and on any theory of liability, whether
35+
* in contract, strict liability, or tort (including negligence or
36+
* otherwise) arising in any way out of the use of this software, even
37+
* if advised of the possibility of such damage.
38+
*
39+
*/
40+
41+
#include <inttypes.h>
42+
#include <libfds.h>
43+
#include "Reader.h"
44+
#include <ipfixcol2.h>
45+
46+
void read_packet(ipx_msg_ipfix_t *msg, const fds_iemgr_t *iemgr) {
47+
48+
const struct fds_ipfix_msg_hdr *ipfix_msg_hdr;
49+
ipfix_msg_hdr = (const struct fds_ipfix_msg_hdr*)ipx_msg_ipfix_get_packet(msg);
50+
51+
if (ipfix_msg_hdr->length < FDS_IPFIX_MSG_HDR_LEN){
52+
return;
53+
}
54+
55+
// Print packet header
56+
printf("## Message header\n");
57+
printf("\tversion:\t%"PRIu16"\n",ntohs(ipfix_msg_hdr->version));
58+
printf("\tlength:\t\t%"PRIu16"\n",ntohs(ipfix_msg_hdr->length));
59+
printf("\texport time:\t%"PRIu32"\n",ntohl(ipfix_msg_hdr->export_time));
60+
printf("\tsequence no.:\t%"PRIu32"\n",ntohl(ipfix_msg_hdr->seq_num));
61+
printf("\tODID:\t\t%"PRIu32"\n", ntohl(ipfix_msg_hdr->odid));
62+
63+
// Get number of sets
64+
struct ipx_ipfix_set *sets;
65+
size_t set_cnt;
66+
ipx_msg_ipfix_get_sets(msg, &sets, &set_cnt);
67+
68+
// Record counter of total records in IPFIX message
69+
uint32_t rec_i = 0;
70+
71+
// Iteration through all the sets
72+
for (uint32_t i = 0; i < set_cnt; ++i){
73+
read_set(&sets[i], msg, iemgr, &rec_i);
74+
}
75+
}
76+
77+
void read_set(struct ipx_ipfix_set *set, ipx_msg_ipfix_t *msg, const fds_iemgr_t *iemgr, uint32_t *rec_i) {
78+
uint8_t *set_end = (uint8_t *)set->ptr + ntohs(set->ptr->length);
79+
uint16_t set_id = ntohs(set->ptr->flowset_id);
80+
81+
const uint32_t rec_cnt = ipx_msg_ipfix_get_drec_cnt(msg);
82+
83+
printf("** Set header\n");
84+
printf("\tset ID: %"PRIu16"\n",set_id);
85+
printf("\tlength: %"PRIu16"\n",ntohs(set->ptr->length));
86+
87+
// Template set
88+
if (set_id == FDS_IPFIX_SET_TMPLT || set_id ==FDS_IPFIX_SET_OPTS_TMPLT){
89+
90+
struct fds_tset_iter tset_iter;
91+
fds_tset_iter_init(&tset_iter, set->ptr);
92+
93+
// Iteration through all templates in the set
94+
while (fds_tset_iter_next(&tset_iter) == FDS_OK){
95+
// Read and print single template
96+
read_template_set(&tset_iter, set_id,iemgr);
97+
putchar('\n');
98+
}
99+
return;
100+
}
101+
// Data set
102+
if (set_id >= FDS_IPFIX_SET_MIN_DSET){
103+
struct ipx_ipfix_record *ipfix_rec = ipx_msg_ipfix_get_drec(msg,*rec_i);
104+
105+
//All the records in the set has same template id, so we extract it from the first record and print it
106+
printf("\ttemplate id: %"PRIu16"\n", ipfix_rec->rec.tmplt->id);
107+
108+
// Iteration through the records which belongs to the current set
109+
while ((ipfix_rec != NULL) && (ipfix_rec->rec.data < set_end) && (*rec_i < rec_cnt)){
110+
// Print record header
111+
printf("-- Record [n.%"PRIu32" of %"PRIu32"]\n", *rec_i+1, rec_cnt);
112+
113+
// Get the specific record and read all the fields
114+
read_record(&ipfix_rec->rec, 1, iemgr); //add iemgr
115+
putchar('\n');
116+
// Get the next record
117+
(*rec_i)++;
118+
ipfix_rec = ipx_msg_ipfix_get_drec(msg, *rec_i);
119+
}
120+
return;
121+
}
122+
123+
//Unknown set ID
124+
printf("\t<Unknown set ID>\n");
125+
}
126+
127+
void read_template_set(struct fds_tset_iter *tset_iter, uint16_t set_id, const fds_iemgr_t *iemgr) {
128+
enum fds_template_type type;
129+
void *ptr;
130+
switch (set_id){
131+
case FDS_IPFIX_SET_TMPLT:
132+
type = FDS_TYPE_TEMPLATE;
133+
ptr = tset_iter->ptr.trec;
134+
break;
135+
case FDS_IPFIX_SET_OPTS_TMPLT:
136+
type = FDS_TYPE_TEMPLATE_OPTS;
137+
ptr = tset_iter->ptr.opts_trec;
138+
break;
139+
default:
140+
printf("\t<Undefined template>\n");
141+
return;
142+
}
143+
// Filling the template structure with data from raw packet
144+
uint16_t tmplt_size = tset_iter->size;
145+
struct fds_template *tmplt;
146+
if (fds_template_parse(type, ptr, &tmplt_size, &tmplt) != FDS_OK){
147+
printf("*Template parsing error*\n");
148+
fds_template_destroy(tmplt);
149+
return;
150+
}
151+
152+
// Printing out the header
153+
printf("-- Template header\n");
154+
printf("\ttemplate id: %"PRIu16"\n", tmplt->id);
155+
printf("\tfield count: %"PRIu16"\n", tmplt->fields_cnt_total);
156+
157+
// Using IEManager to fill the definitions of the fields in the template
158+
if(fds_template_ies_define(tmplt, iemgr , false) != FDS_OK){
159+
printf("*Error while assigning element definitions in template*\n");
160+
fds_template_destroy(tmplt);
161+
return;
162+
}
163+
164+
printf("\tfields:\n");
165+
// Iteration through the fields and printing them out
166+
for (uint16_t i = 0; i < tmplt->fields_cnt_total ; ++i) {
167+
struct fds_tfield current = tmplt->fields[i];
168+
printf("\t");
169+
printf("en:%*"PRIu32" ",WRITER_EN_SPACE, current.en);
170+
printf("id:%*"PRIu16" ",WRITER_ID_SPACE, current.id);
171+
printf("size:");
172+
// In case of variable length print keyword "var"
173+
current.length == FDS_IPFIX_VAR_IE_LEN ? printf("%*s ", WRITER_SIZE_SPACE, "var") : printf("%*"PRIu16" ", WRITER_SIZE_SPACE,current.length);
174+
175+
// Unknown field definition
176+
if (current.def == NULL){
177+
printf("<Unknown field name>\n");
178+
}
179+
// Known field definition
180+
else {
181+
printf("%*s ", WRITER_ORG_NAME_SPACE, current.def->scope->name);
182+
printf("%s", current.def->name);
183+
}
184+
putchar('\n');
185+
}
186+
fds_template_destroy(tmplt);
187+
}
188+
189+
void print_indent(unsigned int n){
190+
for (unsigned int i = 0; i < n; i++){
191+
putchar('\t');
192+
}
193+
}
194+
195+
void read_record(struct fds_drec *rec, unsigned int indent, const fds_iemgr_t *iemgr) {
196+
// Write info from header about the record template
197+
print_indent(indent);
198+
printf("field count: %"PRIu16"\n", rec->tmplt->fields_cnt_total);
199+
print_indent(indent);
200+
printf("data length: %"PRIu16"\n", rec->tmplt->data_length);
201+
print_indent(indent);
202+
printf("size : %"PRIu16"\n", rec->size);
203+
204+
// Iterate through all the fields in record
205+
struct fds_drec_iter iter;
206+
fds_drec_iter_init(&iter, rec, 0);
207+
208+
print_indent(indent);
209+
printf("fields:\n");
210+
while (fds_drec_iter_next(&iter) != FDS_EOC) {
211+
struct fds_drec_field field = iter.field;
212+
read_field(&field,indent, iemgr, rec->snap, false); // add iemgr
213+
}
214+
}
215+
216+
const char * fds_semantic2str(enum fds_ipfix_list_semantics semantic){
217+
switch (semantic){
218+
case (FDS_IPFIX_LIST_ALL_OF):
219+
return "All of";
220+
case (FDS_IPFIX_LIST_EXACTLY_ONE_OF):
221+
return "Exactly one of";
222+
case (FDS_IPFIX_LIST_ORDERED):
223+
return "Ordered";
224+
case (FDS_IPFIX_LIST_NONE_OF):
225+
return "None of";
226+
case (FDS_IPFIX_LIST_ONE_OR_MORE_OF):
227+
return "One or more of";
228+
default:
229+
return "Undefined";
230+
}
231+
}
232+
233+
void read_field(struct fds_drec_field *field, unsigned int indent, const fds_iemgr_t *iemgr, const fds_tsnapshot_t *snap, bool in_basicList) {
234+
// Write info from header about field
235+
print_indent(indent);
236+
if (!in_basicList) {
237+
printf("en:%*" PRIu32 " id:%*" PRIu16" ", WRITER_EN_SPACE, field->info->en, WRITER_ID_SPACE, field->info->id);
238+
}
239+
240+
enum fds_iemgr_element_type type;
241+
char *org;
242+
char *field_name;
243+
const char *unit;
244+
245+
// Get the organisation name, field name and unit of the data.
246+
if (field->info->def == NULL){
247+
type = FDS_ET_OCTET_ARRAY;
248+
org = "<unknown>";
249+
field_name = "<unknown>";
250+
unit = "";
251+
}
252+
else {
253+
type = field->info->def->data_type;
254+
org = field->info->def->scope->name;
255+
field_name = field->info->def->name;
256+
if (field->info->def->data_unit != FDS_EU_NONE){
257+
unit = fds_iemgr_unit2str(field->info->def->data_unit);
258+
}
259+
else{
260+
unit = "";
261+
}
262+
}
263+
264+
switch(type){
265+
case FDS_ET_BASIC_LIST: {
266+
// Iteration through the basic list
267+
bool did_read = false;
268+
struct fds_blist_iter blist_it;
269+
270+
printf("%*s %s", WRITER_ORG_NAME_SPACE, org, field_name);
271+
fds_blist_iter_init(&blist_it,field, iemgr);
272+
printf("%4s[semantic: %s]"," ",fds_semantic2str(blist_it.semantic)); // Semantic is known after initialization
273+
274+
while (fds_blist_iter_next(&blist_it) == FDS_OK){
275+
if (!did_read){
276+
putchar('\n');
277+
did_read = true;
278+
}
279+
read_field(&blist_it.field,indent+1, iemgr, snap, true);
280+
}
281+
if (!did_read){ // if we didn't read a single field
282+
printf("%4s : empty\n"," ");
283+
}
284+
return;
285+
}
286+
case FDS_ET_SUB_TEMPLATE_LIST:
287+
case FDS_ET_SUB_TEMPLATE_MULTILIST: {
288+
// Iteration through the subTemplate and subTemplateMulti lists
289+
printf("%*s %s\n", WRITER_ORG_NAME_SPACE, org, field_name);
290+
struct fds_stlist_iter stlist_iter;
291+
print_indent(indent);
292+
fds_stlist_iter_init(&stlist_iter, field, snap, 0);
293+
printf("- semantic: %d\n",stlist_iter.semantic);
294+
while (fds_stlist_iter_next(&stlist_iter) == FDS_OK){
295+
read_record(&stlist_iter.rec, indent+1, iemgr);
296+
putchar('\n');
297+
}
298+
putchar('\b');
299+
return;
300+
}
301+
default:
302+
printf("%*s %-*s : ", WRITER_ORG_NAME_SPACE,org, WRITER_FIELD_NAME_SPACE, field_name);
303+
}
304+
305+
// Read and write the data from the field
306+
char buffer[1024];
307+
int res = fds_field2str_be(field->data, field->size, type, buffer, sizeof(buffer));
308+
309+
if(res >= 0){
310+
// Conversion was successful
311+
if (type == FDS_ET_STRING){
312+
printf("\"%s\"", buffer);
313+
}
314+
else {
315+
printf("%s", buffer);
316+
}
317+
318+
if (*unit != 0)
319+
printf(" %s", unit);
320+
putchar('\n');
321+
322+
return;
323+
}
324+
else if (res == FDS_ERR_BUFFER){
325+
// Buffer too small
326+
printf("<Data is too long to show>\n");
327+
return;
328+
}
329+
else {
330+
// Any other error
331+
printf("*Invalid value*\n");
332+
return;
333+
}
334+
}
335+

0 commit comments

Comments
 (0)