00001
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <unistd.h>
00042 #include <string.h>
00043 #include <time.h>
00044 #include <arpa/inet.h>
00045 #include <flowmonexp/plugin_export.h>
00046
00065 #define VERSION "1.0"
00066
00070 unsigned int __attribute__((used))plugin_type = (PLUGIN_TYPE_EXPORT);
00071
00075
00076 #define PRINT(format,args...)
00077
00081 #define PRINTERR(format,args...) fprintf(stderr,format,##args)
00082
00086 #define PRINTWARN(format,args...) fprintf(stderr,format,##args)
00087
00091 #define PRINT_SQL_INIT char obuf[16384],dummy[1024];obuf[0]='\0'
00092
00096 #define PRINT_SQL(format,args...) sprintf(dummy,format,##args);strcat(obuf, dummy)
00097
00101 #define PRINT_SQL_FLUSH printf("%s", obuf);fflush(stdout)
00102
00103
00107 #define ADDR_BUF_SIZE 128
00108
00112 enum TIME_UNITS {
00113 TU_NO,
00114 TU_YEAR,
00115 TU_MONTH,
00116 TU_DAY,
00117 TU_HOUR,
00118 TU_MINUTE
00119 };
00120
00125 typedef struct{
00126 int counter;
00127 enum TIME_UNITS partition;
00128 flow_record_getter_t *getters;
00129 } bacnet_export_csv_private_t;
00130
00134 static plugin_desc_t pcap_desc = {
00135 "export-bacnet-csv",
00136 "Version " VERSION
00137 "\nPlugin which outputs all records to stdout in csv format. A time unit can be set as parameter for output partitioning - allowed values include year, month, day, hour and minute.",
00138 0,
00139 0
00140 };
00141
00148 enum GETTER_ID {
00149 FLOW_START_USEC,
00150 FLOW_END_USEC,
00151 L2_VLAN_0,
00152 L2_VLAN_1,
00153 L2_VLAN_2,
00154 L2_VLAN_3,
00155 L2_SRC_MAC,
00156 L2_DST_MAC,
00157 ETHERTYPE,
00158 L3_PROTO,
00159 L3_IPV4_ADDR_SRC,
00160 L3_IPV4_ADDR_DST,
00161 L3_IPV4_TOS,
00162 L3_IPV6_ADDR_SRC,
00163 L3_IPV6_ADDR_DST,
00164 L4_PROTO,
00165 L4_TCP_FLAGS,
00166 L4_PORT_SRC,
00167 L4_PORT_DST,
00168 L4_ICMP_TYPE_CODE,
00169 BACNET_CONTROL,
00170 BACNET_HOP_COUNT,
00171 BACNET_MESSAGE_TYPE,
00172 BACNET_VENDOR_ID,
00173 BACNET_SNET,
00174 BACNET_DNET,
00175 BACNET_SADR,
00176 BACNET_DADR,
00177 PACKETS,
00178 BYTES,
00179
00180 GETTER_MAX
00181 };
00182
00187 struct getter_pair {
00188 char *name;
00189 enum GETTER_ID id;
00190 };
00191
00200 struct getter_pair selected_getters[] = {
00201 {"FLOW_START_USEC", FLOW_START_USEC},
00202 {"FLOW_END_USEC", FLOW_END_USEC},
00203 {"L2_VLAN_0", L2_VLAN_0},
00204 {"L2_SRC_MAC", L2_SRC_MAC},
00205 {"L2_DST_MAC", L2_DST_MAC},
00206 {"ETHERTYPE", ETHERTYPE},
00207 {"L3_PROTO", L3_PROTO},
00208 {"L3_IPV4_ADDR_SRC", L3_IPV4_ADDR_SRC},
00209 {"L3_IPV4_ADDR_DST", L3_IPV4_ADDR_DST},
00210 {"L3_IPV6_ADDR_SRC", L3_IPV6_ADDR_SRC},
00211 {"L3_IPV6_ADDR_DST", L3_IPV6_ADDR_DST},
00212 {"L4_PROTO", L4_PROTO},
00213 {"L4_TCP_FLAGS", L4_TCP_FLAGS},
00214 {"L4_PORT_SRC", L4_PORT_SRC},
00215 {"L4_PORT_DST", L4_PORT_DST},
00216 {"L4_ICMP_TYPE_CODE", L4_ICMP_TYPE_CODE},
00217 {"BACNET_CONTROL", BACNET_CONTROL},
00218 {"BACNET_HOP_COUNT", BACNET_HOP_COUNT},
00219 {"BACNET_MESSAGE_TYPE", BACNET_MESSAGE_TYPE},
00220 {"BACNET_SNET", BACNET_SNET},
00221 {"BACNET_DNET", BACNET_DNET},
00222 {"BACNET_SADR", BACNET_SADR},
00223 {"BACNET_DADR", BACNET_DADR},
00224 {"PACKETS", PACKETS},
00225 {"BYTES", BYTES},
00226
00227 {NULL, GETTER_MAX}
00228 };
00229
00230
00231
00232
00233
00238 plugin_desc_t *plugin_export_desc()
00239 {
00240 return(&pcap_desc);
00241 }
00242
00252 void *plugin_export_init(char *params, flow_record_getter_t *getter_list)
00253 {
00254 bacnet_export_csv_private_t *retval;
00255 flow_record_getter_t *tmp = getter_list;
00256 int i;
00257
00258 PRINT("CSV Output plugin init start\n");
00259 retval = malloc(sizeof(bacnet_export_csv_private_t));
00260 if(!retval){
00261 return(NULL);
00262 }
00263
00264
00265 retval->counter = 0;
00266 retval->partition = TU_NO;
00267 retval->getters = NULL;
00268
00269
00270 if (params != NULL) {
00271 if (strlen (params) == 0) {
00272 PRINTERR ( "Invalid parameters\n");
00273 exit (-1);
00274 } else if (!strcmp ("year", params)) {
00275 retval->partition = TU_YEAR;
00276 } else if (!strcmp ("month", params)) {
00277 retval->partition = TU_MONTH;
00278 } else if (!strcmp ("day", params)) {
00279 retval->partition = TU_DAY;
00280 } else if (!strcmp ("hour", params)) {
00281 retval->partition = TU_HOUR;
00282 } else if (!strcmp ("minute", params)) {
00283 retval->partition = TU_MINUTE;
00284 } else {
00285 PRINTWARN ( "Unknown partitioning parameter (%s) - no partitioning used\n", params);
00286 }
00287 }
00288
00289
00290 i = 0;
00291 while (selected_getters[i].id != GETTER_MAX) {
00292 tmp = getter_by_name (getter_list, selected_getters[i].name);
00293 if (tmp != NULL) {
00294 PRINT("getter: %s - %i\n",tmp->name, tmp->length);
00295 getter_copy_to(&(retval->getters),tmp);
00296 }
00297 i++;
00298 }
00299
00300 PRINT("CSV Output plugin init end\n");
00301
00302
00303 setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00304
00305 return(retval);
00306 }
00307
00314 void print_headers(flow_record_getter_t *getters)
00315 {
00316 while(getters && getters->name){
00317 printf ("%s,", getters->name);
00318 getters++;
00319 }
00320 printf ("\n");
00321 }
00322
00332 int plugin_export_export(void *plugin_private, flow_record_t *record)
00333 {
00334 bacnet_export_csv_private_t *p = (bacnet_export_csv_private_t*)plugin_private;
00335 flow_record_getter_t *tmp = p->getters;
00336 unsigned char block[1024];
00337 int i, j, len, to_network_byte_order;
00338 char addr[ADDR_BUF_SIZE];
00339
00340 char datestr[64];
00341 time_t t = time(NULL);
00342 struct tm *now;
00343
00344 PRINT_SQL_INIT;
00345
00346 datestr[0] = '\0';
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 p->counter++;
00357 for (i = 0; selected_getters[i].id != GETTER_MAX; i++) {
00358 if ((tmp = getter_by_name (p->getters, selected_getters[i].name)) == NULL) {
00359 continue;
00360 }
00361 len = tmp->current_length(tmp->self,record);
00362 if ((selected_getters[i].id == L3_IPV6_ADDR_SRC) ||
00363 (selected_getters[i].id == L3_IPV6_ADDR_DST) ||
00364 (selected_getters[i].id == L3_IPV4_ADDR_SRC) ||
00365 (selected_getters[i].id == L3_IPV4_ADDR_DST)) {
00366 to_network_byte_order = 1;
00367 } else {
00368 to_network_byte_order = 0;
00369 }
00370 if(!tmp->valid(tmp->self,record)){
00371 PRINT_SQL(",NULL");
00372 continue;
00373 }
00374 tmp->filler (tmp->self, record, block, len, to_network_byte_order);
00375
00376
00377 switch (selected_getters[i].id) {
00378 case FLOW_START_USEC:
00379
00380 if (p->partition != TU_NO) {
00381 t = (time_t) (*(uint64_t*)&(block[0]))/1000000;
00382 now = localtime (&t);
00383 switch (p->partition) {
00384 case TU_YEAR:
00385 snprintf (datestr, 63, "_%i", now->tm_year + 1900);
00386 break;
00387 case TU_MONTH:
00388 snprintf (datestr, 63, "_%i%02i", now->tm_year + 1900, now->tm_mon + 1);
00389 break;
00390 case TU_DAY:
00391 snprintf (datestr, 63, "_%i%02i%02i", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
00392 break;
00393 case TU_HOUR:
00394 snprintf (datestr, 63, "_%i%02i%02i%02i", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour);
00395 break;
00396 case TU_MINUTE:
00397 snprintf (datestr, 63, "_%i%02i%02i%02i%02i", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min);
00398 break;
00399 default:
00400
00401 break;
00402 }
00403 }
00404 PRINT_SQL("INSERT INTO bacnet%s VALUES (to_timestamp('%lu.%06lu'),", datestr, (*(uint64_t*)&(block[0]))/1000000, (*(uint64_t*)&(block[0]))%1000000);
00405
00406 break;
00407 case FLOW_END_USEC:
00408 PRINT_SQL("to_timestamp('%lu.%06lu')", (*(uint64_t*)&(block[0]))/1000000, (*(uint64_t*)&(block[0]))%1000000);
00409
00410 break;
00411 case L2_SRC_MAC:
00412 case L2_DST_MAC:
00413 case BACNET_SADR:
00414 case BACNET_DADR:
00415 PRINT_SQL(",'");
00416
00417 if (len==1) {
00418 PRINT_SQL("00:00:00:00:00:%02x", block[0]);
00419 }
00420 else {
00421 PRINT_SQL("%02x", block[0]);
00422 for (j = 1; j < len; j++) {
00423 PRINT_SQL(":%02x", block[j]);
00424 }
00425 }
00426 PRINT_SQL("'");
00427 break;
00428 case BACNET_CONTROL:
00429 PRINT_SQL(",'%u'", block[0]);
00430 break;
00431 case BACNET_HOP_COUNT:
00432 case BACNET_MESSAGE_TYPE:
00433 case L3_PROTO:
00434 case L4_PROTO:
00435 case L4_TCP_FLAGS:
00436 case L3_IPV4_TOS:
00437
00438 PRINT_SQL(",'%u'", block[0]);
00439 break;
00440 case L2_VLAN_0:
00441 case L2_VLAN_1:
00442 case L2_VLAN_2:
00443 case L2_VLAN_3:
00444 case BACNET_VENDOR_ID:
00445 case ETHERTYPE:
00446 case BACNET_SNET:
00447 case BACNET_DNET:
00448 case L4_PORT_SRC:
00449 case L4_PORT_DST:
00450 case L4_ICMP_TYPE_CODE:
00451
00452 PRINT_SQL(",'%u'", (*(uint16_t*)block));
00453 break;
00454 case PACKETS:
00455 case BYTES:
00456
00457 PRINT_SQL(",'%u'", (*(uint32_t*)block));
00458 break;
00459 case L3_IPV6_ADDR_SRC:
00460 case L3_IPV6_ADDR_DST:
00461 PRINT_SQL(",'");
00462 inet_ntop (AF_INET6, block, addr, ADDR_BUF_SIZE);
00463 PRINT_SQL("%s/128'", addr);
00464 break;
00465 case L3_IPV4_ADDR_SRC:
00466 case L3_IPV4_ADDR_DST:
00467 PRINT_SQL(",'");
00468 inet_ntop (AF_INET, block, addr, ADDR_BUF_SIZE);
00469 PRINT_SQL("%s/32'", addr);
00470 break;
00471 default:
00472 break;
00473 }
00474 }
00475
00476 PRINT_SQL(");\n");
00477 PRINT_SQL_FLUSH;
00478 return(0);
00479 }
00480
00489 int plugin_export_flush(void *plugin_private)
00490 {
00491 PRINT("Output plugin flush\n");
00492 fflush(stdout);
00493 return(0);
00494 }
00495