1 /*
2 pmacct (Promiscuous mode IP Accounting package)
3 pmacct is Copyright (C) 2003-2020 by Paolo Lucente
4 */
5
6 /*
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 /* includes */
23 #include "pmacct.h"
24 #include "addr.h"
25 #ifdef WITH_KAFKA
26 #include "kafka_common.h"
27 #endif
28 #ifdef WITH_MYSQL
29 #include "mysql_plugin.h"
30 #endif
31 #ifdef WITH_PGSQL
32 #include "pgsql_plugin.h"
33 #endif
34 #ifdef WITH_SQLITE3
35 #include "sqlite3_plugin.h"
36 #endif
37 #ifdef WITH_RABBITMQ
38 #include "amqp_plugin.h"
39 #endif
40 #ifdef WITH_KAFKA
41 #include "kafka_plugin.h"
42 #endif
43 #ifdef WITH_REDIS
44 #include "hiredis/hiredis.h"
45 #endif
46 #include "pmacct-data.h"
47 #include "ip_flow.h"
48 #include "classifier.h"
49 #include "plugin_hooks.h"
50 #include <netdb.h>
51 #include <sys/file.h>
52 #include <sys/utsname.h>
53
54 struct _devices_struct _devices[] = {
55 #if defined DLT_LOOP
56 {null_handler, DLT_LOOP},
57 #endif
58 {null_handler, DLT_NULL},
59 {eth_handler, DLT_EN10MB},
60 {ppp_handler, DLT_PPP},
61 #if defined DLT_IEEE802_11
62 {ieee_802_11_handler, DLT_IEEE802_11},
63 #endif
64 #if defined DLT_LINUX_SLL
65 {sll_handler, DLT_LINUX_SLL},
66 #endif
67 #if defined DLT_RAW
68 {raw_handler, DLT_RAW},
69 #endif
70 {NULL, -1},
71 };
72
73 /* Global variables */
74 primptrs_func primptrs_funcs[PRIMPTRS_FUNCS_N];
75
76 /* functions */
setnonblocking(int sock)77 void setnonblocking(int sock)
78 {
79 int opts;
80
81 opts = fcntl(sock, F_GETFL);
82 opts = (opts | O_NONBLOCK);
83 fcntl(sock, F_SETFL, opts);
84 }
85
setblocking(int sock)86 void setblocking(int sock)
87 {
88 int opts;
89
90 opts = fcntl(sock, F_GETFL);
91 opts & O_NONBLOCK ? opts ^= O_NONBLOCK : opts;
92 fcntl(sock, F_SETFL, opts);
93 }
94
daemonize()95 int daemonize()
96 {
97 int fdd;
98 pid_t pid;
99
100 pid = fork();
101
102 switch (pid) {
103 case -1:
104 return -1;
105 case 0:
106 break;
107 default:
108 exit(0);
109 }
110
111 if (setsid() == -1) return -1;
112
113 fdd = open("/dev/null", O_RDWR, 0);
114 if (fdd != -1) {
115 dup2(fdd, 0);
116 dup2(fdd, 1);
117 dup2(fdd, 2);
118 if (fdd > 2) close(fdd);
119 }
120
121 return 0;
122 }
123
extract_token(char ** string,int delim)124 char *extract_token(char **string, int delim)
125 {
126 char *token, *delim_ptr;
127
128 if (!strlen(*string)) return NULL;
129
130 start:
131 if ((delim_ptr = strchr(*string, delim))) {
132 *delim_ptr = '\0';
133 token = *string;
134 *string = delim_ptr+1;
135 if (!strlen(token)) goto start;
136 }
137 else {
138 token = *string;
139 *string += strlen(*string);
140 if (!strlen(token)) return NULL;
141 }
142
143 return token;
144 }
145
extract_plugin_name(char ** string)146 char *extract_plugin_name(char **string)
147 {
148 char *name, *delim_ptr;
149 char name_start = '[';
150 char name_end = ']';
151
152 if ((delim_ptr = strchr(*string, name_start))) {
153 *delim_ptr = '\0';
154 name = delim_ptr+1;
155 if ((delim_ptr = strchr(name, name_end))) *delim_ptr = '\0';
156 else {
157 printf("ERROR: Not weighted parhentesis: '[%s'\n", name);
158 exit(1);
159 }
160 }
161 else return NULL;
162
163 return name;
164 }
165
166
167 /*
168 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
169 * The Regents of the University of California. All rights reserved.
170 *
171 * Redistribution and use in source and binary forms, with or without
172 * modification, are permitted provided that: (1) source code distributions
173 * retain the above copyright notice and this paragraph in its entirety, (2)
174 * distributions including binary code include the above copyright notice and
175 * this paragraph in its entirety in the documentation or other materials
176 * provided with the distribution, and (3) all advertising materials mentioning
177 * features or use of this software display the following acknowledgement:
178 * ``This product includes software developed by the University of California,
179 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
180 * the University nor the names of its contributors may be used to endorse
181 * or promote products derived from this software without specific prior
182 * written permission.
183 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
185 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
186 */
187
copy_argv(register char ** argv)188 char *copy_argv(register char **argv)
189 {
190 register char **p;
191 register unsigned int len = 0;
192 char *buf;
193 char *src, *dst;
194
195 p = argv;
196 if (*p == 0)
197 return NULL;
198
199 while (*p)
200 len += strlen(*p++) + 1;
201
202 buf = (char *)malloc(len);
203 if (buf == NULL) {
204 Log(LOG_ERR, "ERROR ( %s/%s ): copy_argv: malloc()\n", config.name, config.type);
205 return NULL;
206 }
207
208 p = argv;
209 dst = buf;
210 while ((src = *p++) != NULL) {
211 while ((*dst++ = *src++) != '\0');
212 dst[-1] = ' ';
213 }
214
215 dst[-1] = '\0';
216 return buf;
217 }
218
trim_spaces(char * buf)219 void trim_spaces(char *buf)
220 {
221 char *tmp_buf;
222 int i, len;
223
224 len = strlen(buf);
225
226 tmp_buf = (char *)malloc(len + 1);
227 if (tmp_buf == NULL) {
228 Log(LOG_ERR, "ERROR: trim_spaces: malloc() failed.\n");
229 return;
230 }
231
232 /* trimming spaces at beginning of the string */
233 for (i = 0; i <= len; i++) {
234 if (!isspace(buf[i])) {
235 if (i != 0) {
236 strlcpy(tmp_buf, &buf[i], len+1-i);
237 strlcpy(buf, tmp_buf, len+1-i);
238 }
239 break;
240 }
241 }
242
243 /* trimming spaces at the end of the string */
244 for (i = strlen(buf)-1; i >= 0; i--) {
245 if (isspace(buf[i]))
246 buf[i] = '\0';
247 else break;
248 }
249
250 free(tmp_buf);
251 }
252
trim_all_spaces(char * buf)253 void trim_all_spaces(char *buf)
254 {
255 char *tmp_buf;
256 int i = 0, len, quotes = FALSE;
257
258 len = strlen(buf);
259
260 tmp_buf = (char *)malloc(len + 1);
261 if (tmp_buf == NULL) {
262 Log(LOG_ERR, "ERROR: trim_all_spaces: malloc() failed.\n");
263 return;
264 }
265
266 /* trimming all spaces */
267 while (i <= len) {
268 if (buf[i] == '\'') {
269 if (!quotes) quotes = TRUE;
270 else if (quotes) quotes = FALSE;
271 }
272 if (isspace(buf[i]) && !quotes) {
273 strlcpy(tmp_buf, &buf[i+1], len);
274 strlcpy(&buf[i], tmp_buf, len);
275 len--;
276 }
277 else i++;
278 }
279
280 free(tmp_buf);
281 }
282
strip_quotes(char * buf)283 void strip_quotes(char *buf)
284 {
285 char *ptr, *tmp_buf;
286 int i = 0, len;
287
288 len = strlen(buf);
289
290 tmp_buf = (char *) malloc(len + 1);
291 if (tmp_buf == NULL) {
292 Log(LOG_ERR, "ERROR ( %s/%s ): strip_quotes: malloc() failed.\n", config.name, config.type);
293 return;
294 }
295 ptr = buf;
296
297 /* stripping all quote marks using a temporary buffer to avoid string corruption by strcpy() */
298 while (i <= len) {
299 if (ptr[i] == '\'') {
300 strcpy(tmp_buf, &ptr[i+1]);
301 strcpy(&buf[i], tmp_buf);
302 len--;
303 }
304 else i++;
305 }
306
307 free(tmp_buf);
308 }
309
isblankline(char * line)310 int isblankline(char *line)
311 {
312 int len, j, n_spaces = 0;
313
314 if (!line) return FALSE;
315
316 len = strlen(line);
317 for (j = 0; j < len; j++)
318 if (isspace(line[j])) n_spaces++;
319
320 if (n_spaces == len) return TRUE;
321 else return FALSE;
322 }
323
iscomment(char * line)324 int iscomment(char *line)
325 {
326 int len, j, first_char = TRUE;
327
328 if (!line) return FALSE;
329
330 len = strlen(line);
331 for (j = 0; j <= len; j++) {
332 if (!isspace(line[j])) first_char--;
333 if (!first_char) {
334 if (line[j] == '!' || line[j] == '#') return TRUE;
335 else return FALSE;
336 }
337 }
338
339 return FALSE;
340 }
341
string_add_newline(char * buf)342 void string_add_newline(char *buf)
343 {
344 int len = strlen(buf);
345
346 buf[len] = '\n';
347 len++;
348 buf[len] = '\0';
349 }
350
roundoff_time(time_t t,char * value)351 time_t roundoff_time(time_t t, char *value)
352 {
353 struct tm *rounded;
354 int len, j;
355
356 if (!config.timestamps_utc) rounded = localtime(&t);
357 else rounded = gmtime(&t);
358
359 rounded->tm_sec = 0; /* default round off */
360
361 if (value) {
362 len = strlen(value);
363 for (j = 0; j < len; j++) {
364 if (value[j] == 'm') rounded->tm_min = 0;
365 else if (value[j] == 'h') {
366 rounded->tm_min = 0;
367 rounded->tm_hour = 0;
368 }
369 else if (value[j] == 'd') {
370 rounded->tm_min = 0;
371 rounded->tm_hour = 0;
372 rounded->tm_mday = 1;
373 }
374 else if (value[j] == 'w') {
375 rounded->tm_min = 0;
376 rounded->tm_hour = 0;
377 while (rounded->tm_wday > 1) {
378 rounded->tm_mday--;
379 rounded->tm_wday--;
380 }
381 }
382 else if (value[j] == 'M') {
383 rounded->tm_min = 0;
384 rounded->tm_hour = 0;
385 rounded->tm_mday = 1;
386 rounded->tm_mon = 0;
387 }
388 else Log(LOG_WARNING, "WARN ( %s/%s ): ignoring unknown round off value: %c\n", config.name, config.type, value[j]);
389 }
390 }
391
392 t = mktime(rounded);
393 return t;
394 }
395
396 /* op = 0 (add); op = 1 (sub) */
calc_monthly_timeslot(time_t t,int howmany,int op)397 time_t calc_monthly_timeslot(time_t t, int howmany, int op)
398 {
399 time_t base = t, final;
400 struct tm *tmt;
401
402 if (!config.timestamps_utc) tmt = localtime(&t);
403 else tmt = gmtime(&t);
404
405 while (howmany) {
406 tmt->tm_mday = 1;
407 if (op == ADD) tmt->tm_mon++;
408 else if (op == SUB) tmt->tm_mon--;
409 howmany--;
410 }
411
412 final = mktime(tmt);
413
414 return (final-base);
415 }
416
open_output_file(char * filename,char * mode,int lock)417 FILE *open_output_file(char *filename, char *mode, int lock)
418 {
419 FILE *file = NULL;
420 uid_t owner = -1;
421 gid_t group = -1;
422 struct stat st;
423 int ret, fd;
424
425 if (!filename || !mode) return file;
426
427 if (config.files_uid) owner = config.files_uid;
428 if (config.files_gid) group = config.files_gid;
429
430 /* create dir structure to get to file, if needed */
431 ret = mkdir_multilevel(filename, TRUE, owner, group);
432 if (ret) {
433 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): mkdir_multilevel() failed.\n", config.name, config.type, filename);
434 return file;
435 }
436
437 /* handling FIFOs */
438 if (!stat(filename, &st)) {
439 if (st.st_mode & S_IFIFO) {
440 fd = open(filename, (O_RDWR|O_NONBLOCK));
441
442 if (fd == ERR) {
443 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): open() failed (%s).\n", config.name, config.type, filename, strerror(errno));
444 return file;
445 }
446 else {
447 file = fdopen(fd, mode);
448
449 if (!file) {
450 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): fdopen() failed (%s).\n", config.name, config.type, filename, strerror(errno));
451 return file;
452 }
453 }
454 }
455 }
456
457 /* handling regular files */
458 if (!file) file = fopen(filename, mode);
459
460 if (file) {
461 fd = fileno(file);
462
463 if (chown(filename, owner, group) == -1)
464 Log(LOG_WARNING, "WARN ( %s/%s ): [%s] open_output_file(): chown() failed (%s).\n", config.name, config.type, filename, strerror(errno));
465
466 if (lock) {
467 if (file_lock(fd)) {
468 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] open_output_file(): file_lock() failed.\n", config.name, config.type, filename);
469 file = NULL;
470 }
471 }
472 }
473 else {
474 Log(LOG_WARNING, "WARN ( %s/%s ): [%s] open_output_file(): fopen() failed (%s).\n", config.name, config.type, filename, strerror(errno));
475 file = NULL;
476 }
477
478 return file;
479 }
480
link_latest_output_file(char * link_filename,char * filename_to_link)481 void link_latest_output_file(char *link_filename, char *filename_to_link)
482 {
483 int ret, rewrite_latest = FALSE;
484 char buf[SRVBUFLEN];
485 uid_t owner = -1;
486 gid_t group = -1;
487
488 if (!link_filename || !filename_to_link) return;
489
490 if (config.files_uid) owner = config.files_uid;
491 if (config.files_gid) group = config.files_gid;
492
493 /* create dir structure to get to file, if needed */
494 ret = mkdir_multilevel(link_filename, TRUE, owner, group);
495 if (ret) {
496 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] link_latest_output_file(): mkdir_multilevel() failed.\n", config.name, config.type, buf);
497 return;
498 }
499
500 /* if a file with same name exists let's investigate if filename_to_link is newer */
501 ret = access(link_filename, F_OK);
502
503 if (!ret) {
504 struct stat s1, s2;
505
506 memset(&s1, 0, sizeof(struct stat));
507 memset(&s2, 0, sizeof(struct stat));
508 readlink(link_filename, buf, SRVBUFLEN);
509
510 /* filename_to_link is newer than buf or buf is un-existing */
511 stat(buf, &s1);
512 stat(filename_to_link, &s2);
513 if (s2.st_mtime >= s1.st_mtime) rewrite_latest = TRUE;
514 }
515 else rewrite_latest = TRUE;
516
517 if (rewrite_latest) {
518 unlink(link_filename);
519 symlink(filename_to_link, link_filename);
520
521 if (lchown(link_filename, owner, group) == -1)
522 Log(LOG_WARNING, "WARN ( %s/%s ): link_latest_output_file(): unable to chown() '%s'.\n", config.name, config.type, link_filename);
523 }
524 }
525
close_output_file(FILE * f)526 void close_output_file(FILE *f)
527 {
528 if (f) fclose(f);
529 }
530
531 /* Future: tokenization part to be moved away from runtime */
handle_dynname_internal_strings(char * new,int newlen,char * old,struct primitives_ptrs * prim_ptrs,int type)532 int handle_dynname_internal_strings(char *new, int newlen, char *old, struct primitives_ptrs *prim_ptrs, int type)
533 {
534 /* applies only to DYN_STR_PRINT_FILE and DYN_STR_SQL_TABLE */
535 char ref_string[] = "$ref", hst_string[] = "$hst";
536
537 /* applies to all */
538 char psi_string[] = "$peer_src_ip", tag_string[] = "$tag", tag2_string[] = "$tag2";
539 char post_tag_string[] = "$post_tag", post_tag2_string[] = "$post_tag2";
540
541 /* applies only to DYN_STR_KAFKA_PART */
542 char src_host_string[] = "$src_host", dst_host_string[] = "$dst_host";
543 char src_port_string[] = "$src_port", dst_port_string[] = "$dst_port";
544 char proto_string[] = "$proto", in_iface_string[] = "$in_iface";
545
546 char buf[newlen], *ptr_start, *ptr_end, *ptr_var, *ptr_substr, *last_char;
547 int oldlen, var_num, var_len, rem_len, sub_len;
548
549 if (!new || !old || !prim_ptrs) return ERR;
550
551 oldlen = strlen(old);
552 if (oldlen <= newlen) strcpy(new, old);
553 else return ERR;
554
555 for (var_num = 0, ptr_substr = new, ptr_var = strchr(ptr_substr, '$'); ptr_var; var_num++) {
556 rem_len = newlen - (ptr_var - new);
557
558 /* tokenizing: valid charset: a-z, A-Z, 0-9, _ */
559 for (var_len = 1, last_char = NULL; var_len < rem_len; var_len++) {
560 if ((ptr_var[var_len] >= '\x30' && ptr_var[var_len] <= '\x39') ||
561 (ptr_var[var_len] >= '\x41' && ptr_var[var_len] <= '\x5a') ||
562 (ptr_var[var_len] >= '\x61' && ptr_var[var_len] <= '\x7a') ||
563 ptr_var[var_len] == '\x5f') last_char = &ptr_var[var_len];
564 else {
565 if ((*last_char) == '\x5f') var_len--;
566 break;
567 }
568 }
569
570 /* string tests */
571 sub_len = 0;
572 if ((type == DYN_STR_SQL_TABLE || type == DYN_STR_PRINT_FILE) &&
573 !strncmp(ptr_var, ref_string, var_len)) {
574 int len;
575
576 ptr_start = ptr_var;
577 ptr_end = ptr_start;
578 ptr_end += 4;
579 len = strlen(ptr_end);
580
581 snprintf(buf, newlen, "%u", config.sql_refresh_time);
582
583 sub_len = strlen(buf);
584 if ((sub_len + len) >= newlen) return ERR;
585 strncat(buf, ptr_end, len);
586
587 len = strlen(buf);
588 *ptr_start = '\0';
589
590 if (len >= rem_len) return ERR;
591 strncat(new, buf, rem_len);
592 }
593 else if ((type == DYN_STR_SQL_TABLE || type == DYN_STR_PRINT_FILE) &&
594 !strncmp(ptr_var, hst_string, var_len)) {
595 int len, howmany;
596
597 ptr_start = ptr_var;
598 ptr_end = ptr_start;
599 ptr_end += 4;
600 len = strlen(ptr_end);
601
602 howmany = sql_history_to_secs(config.sql_history, config.sql_history_howmany);
603 snprintf(buf, newlen, "%u", howmany);
604
605 sub_len = strlen(buf);
606 if ((sub_len + len) >= newlen) return ERR;
607 strncat(buf, ptr_end, len);
608
609 len = strlen(buf);
610 *ptr_start = '\0';
611
612 if (len >= rem_len) return ERR;
613 strncat(new, buf, rem_len);
614 }
615 else if (!strncmp(ptr_var, psi_string, var_len)) {
616 char empty_peer_src_ip[] = "null";
617 char peer_src_ip[INET6_ADDRSTRLEN];
618 int len;
619
620 ptr_start = ptr_var;
621 ptr_end = ptr_start;
622 ptr_end += strlen(psi_string);
623 len = strlen(ptr_end);
624
625 if (prim_ptrs && prim_ptrs->pbgp) addr_to_str(peer_src_ip, &prim_ptrs->pbgp->peer_src_ip);
626 else strlcpy(peer_src_ip, empty_peer_src_ip, strlen(peer_src_ip));
627
628 escape_ip_uscores(peer_src_ip);
629 snprintf(buf, newlen, "%s", peer_src_ip);
630
631 sub_len = strlen(buf);
632 if ((sub_len + len) >= newlen) return ERR;
633 strncat(buf, ptr_end, len);
634
635 len = strlen(buf);
636 *ptr_start = '\0';
637
638 if (len >= rem_len) return ERR;
639 strncat(new, buf, rem_len);
640 }
641 else if (!strncmp(ptr_var, tag_string, var_len)) {
642 pm_id_t zero_tag = 0;
643 int len;
644
645 ptr_start = ptr_var;
646 ptr_end = ptr_start;
647 ptr_end += strlen(tag_string);
648 len = strlen(ptr_end);
649
650 if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%" PRIu64 "", prim_ptrs->data->primitives.tag);
651 else snprintf(buf, newlen, "%" PRIu64 "", zero_tag);
652
653 sub_len = strlen(buf);
654 if ((sub_len + len) >= newlen) return ERR;
655 strncat(buf, ptr_end, len);
656
657 len = strlen(buf);
658 *ptr_start = '\0';
659
660 if (len >= rem_len) return ERR;
661 strncat(new, buf, rem_len);
662 }
663 else if (!strncmp(ptr_var, tag2_string, var_len)) {
664 pm_id_t zero_tag = 0;
665 int len;
666
667 ptr_start = ptr_var;
668 ptr_end = ptr_start;
669 ptr_end += strlen(tag2_string);
670 len = strlen(ptr_end);
671
672 if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%" PRIu64 "", prim_ptrs->data->primitives.tag2);
673 else snprintf(buf, newlen, "%" PRIu64 "", zero_tag);
674
675 sub_len = strlen(buf);
676 if ((sub_len + len) >= newlen) return ERR;
677 strncat(buf, ptr_end, len);
678
679 len = strlen(buf);
680 *ptr_start = '\0';
681
682 if (len >= rem_len) return ERR;
683 strncat(new, buf, rem_len);
684 }
685 else if (!strncmp(ptr_var, post_tag_string, var_len)) {
686 int len;
687
688 ptr_start = ptr_var;
689 ptr_end = ptr_start;
690 ptr_end += strlen(post_tag_string);
691 len = strlen(ptr_end);
692
693 snprintf(buf, newlen, "%" PRIu64 "", config.post_tag);
694
695 sub_len = strlen(buf);
696 if ((sub_len + len) >= newlen) return ERR;
697 strncat(buf, ptr_end, len);
698
699 len = strlen(buf);
700 *ptr_start = '\0';
701
702 if (len >= rem_len) return ERR;
703 strncat(new, buf, rem_len);
704 }
705 else if (!strncmp(ptr_var, post_tag2_string, var_len)) {
706 int len;
707
708 ptr_start = ptr_var;
709 ptr_end = ptr_start;
710 ptr_end += strlen(post_tag2_string);
711 len = strlen(ptr_end);
712
713 snprintf(buf, newlen, "%" PRIu64 "", config.post_tag2);
714
715 sub_len = strlen(buf);
716 if ((sub_len + len) >= newlen) return ERR;
717 strncat(buf, ptr_end, len);
718
719 len = strlen(buf);
720 *ptr_start = '\0';
721
722 if (len >= rem_len) return ERR;
723 strncat(new, buf, rem_len);
724 }
725 else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, src_host_string, var_len)) {
726 char empty_src_host[] = "null";
727 char src_host[INET6_ADDRSTRLEN];
728 int len;
729
730 ptr_start = ptr_var;
731 ptr_end = ptr_start;
732 ptr_end += strlen(src_host_string);
733 len = strlen(ptr_end);
734
735 if (prim_ptrs && prim_ptrs->data) addr_to_str(src_host, &prim_ptrs->data->primitives.src_ip);
736 else strlcpy(src_host, empty_src_host, strlen(src_host));
737
738 escape_ip_uscores(src_host);
739 snprintf(buf, newlen, "%s", src_host);
740
741 sub_len = strlen(buf);
742 if ((sub_len + len) >= newlen) return ERR;
743 strncat(buf, ptr_end, len);
744
745 len = strlen(buf);
746 *ptr_start = '\0';
747
748 if (len >= rem_len) return ERR;
749 strncat(new, buf, rem_len);
750 }
751 else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, dst_host_string, var_len)) {
752 char empty_dst_host[] = "null";
753 char dst_host[INET6_ADDRSTRLEN];
754 int len;
755
756 ptr_start = ptr_var;
757 ptr_end = ptr_start;
758 ptr_end += strlen(dst_host_string);
759 len = strlen(ptr_end);
760
761 if (prim_ptrs && prim_ptrs->data) addr_to_str(dst_host, &prim_ptrs->data->primitives.dst_ip);
762 else strlcpy(dst_host, empty_dst_host, strlen(dst_host));
763
764 escape_ip_uscores(dst_host);
765 snprintf(buf, newlen, "%s", dst_host);
766
767 sub_len = strlen(buf);
768 if ((sub_len + len) >= newlen) return ERR;
769 strncat(buf, ptr_end, len);
770
771 len = strlen(buf);
772 *ptr_start = '\0';
773
774 if (len >= rem_len) return ERR;
775 strncat(new, buf, rem_len);
776 }
777 else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, src_port_string, var_len)) {
778 u_int16_t zero_port = 0;
779 int len;
780
781 ptr_start = ptr_var;
782 ptr_end = ptr_start;
783 ptr_end += strlen(src_port_string);
784 len = strlen(ptr_end);
785
786 if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%hu", prim_ptrs->data->primitives.src_port);
787 else snprintf(buf, newlen, "%hu", zero_port);
788
789 sub_len = strlen(buf);
790 if ((sub_len + len) >= newlen) return ERR;
791 strncat(buf, ptr_end, len);
792
793 len = strlen(buf);
794 *ptr_start = '\0';
795
796 if (len >= rem_len) return ERR;
797 strncat(new, buf, rem_len);
798 }
799 else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, dst_port_string, var_len)) {
800 u_int16_t zero_port = 0;
801 int len;
802
803 ptr_start = ptr_var;
804 ptr_end = ptr_start;
805 ptr_end += strlen(dst_port_string);
806 len = strlen(ptr_end);
807
808 if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%hu", prim_ptrs->data->primitives.dst_port);
809 else snprintf(buf, newlen, "%hu", zero_port);
810
811 sub_len = strlen(buf);
812 if ((sub_len + len) >= newlen) return ERR;
813 strncat(buf, ptr_end, len);
814
815 len = strlen(buf);
816 *ptr_start = '\0';
817
818 if (len >= rem_len) return ERR;
819 strncat(new, buf, rem_len);
820 }
821 else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, proto_string, var_len)) {
822 int null_proto = -1;
823 int len;
824
825 ptr_start = ptr_var;
826 ptr_end = ptr_start;
827 ptr_end += strlen(proto_string);
828 len = strlen(ptr_end);
829
830 if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%d", prim_ptrs->data->primitives.proto);
831 else snprintf(buf, newlen, "%d", null_proto);
832
833 sub_len = strlen(buf);
834 if ((sub_len + len) >= newlen) return ERR;
835 strncat(buf, ptr_end, len);
836
837 len = strlen(buf);
838 *ptr_start = '\0';
839
840 if (len >= rem_len) return ERR;
841 strncat(new, buf, rem_len);
842 }
843 else if ((type == DYN_STR_KAFKA_PART) && !strncmp(ptr_var, in_iface_string, var_len)) {
844 int null_in_iface = 0;
845 int len;
846
847 ptr_start = ptr_var;
848 ptr_end = ptr_start;
849 ptr_end += strlen(in_iface_string);
850 len = strlen(ptr_end);
851
852 if (prim_ptrs && prim_ptrs->data) snprintf(buf, newlen, "%u", prim_ptrs->data->primitives.ifindex_in);
853 else snprintf(buf, newlen, "%u", null_in_iface);
854
855 sub_len = strlen(buf);
856 if ((sub_len + len) >= newlen) return ERR;
857 strncat(buf, ptr_end, len);
858
859 len = strlen(buf);
860 *ptr_start = '\0';
861
862 if (len >= rem_len) return ERR;
863 strncat(new, buf, rem_len);
864 }
865
866 if (sub_len) ptr_substr = ptr_var + sub_len;
867 else ptr_substr = ptr_var + var_len;
868
869 ptr_var = strchr(ptr_substr, '$');
870 }
871
872 return SUCCESS;
873 }
874
have_dynname_nontime(char * str)875 int have_dynname_nontime(char *str)
876 {
877 char tzone_string[] = "$tzone", *ptr, *newptr;
878 int tzone_strlen = strlen(tzone_string);
879
880 for (newptr = ptr = str; (newptr = strchr(ptr, '$')); ptr = newptr, ptr++) {
881 if (strncmp(newptr, tzone_string, tzone_strlen)) return TRUE;
882 }
883
884 return FALSE;
885 }
886
escape_ip_uscores(char * str)887 void escape_ip_uscores(char *str)
888 {
889 int idx, len = 0;
890
891 if (str) len = strlen(str);
892 for (idx = 0; idx < len; idx++) {
893 if (str[idx] == '.' || str[idx] == ':') str[idx] = '_';
894 }
895 }
896
handle_dynname_internal_strings_same(char * s,int max,char * tmp,struct primitives_ptrs * prim_ptrs,int type)897 int handle_dynname_internal_strings_same(char *s, int max, char *tmp, struct primitives_ptrs *prim_ptrs, int type)
898 {
899 int ret;
900
901 ret = handle_dynname_internal_strings(tmp, max, s, prim_ptrs, type);
902 strlcpy(s, tmp, max);
903
904 return ret;
905 }
906
sql_history_to_secs(int mu,int howmany)907 int sql_history_to_secs(int mu, int howmany)
908 {
909 int ret = 0;
910
911 if (mu == COUNT_SECONDLY) ret = howmany;
912 else if (mu == COUNT_MINUTELY) ret = howmany*60;
913 else if (mu == COUNT_HOURLY) ret = howmany*3600;
914 else if (mu == COUNT_DAILY) ret = howmany*86400;
915 else if (mu == COUNT_WEEKLY) ret = howmany*86400*7;
916 else if (mu == COUNT_MONTHLY) ret = howmany*86400*30; /* XXX: this is an approx! */
917
918 return ret;
919 }
920
write_pid_file(char * filename)921 void write_pid_file(char *filename)
922 {
923 FILE *file;
924 char pid[10];
925 uid_t owner = -1;
926 gid_t group = -1;
927
928 unlink(filename);
929
930 if (config.files_uid) owner = config.files_uid;
931 if (config.files_gid) group = config.files_gid;
932
933 file = fopen(filename,"w");
934 if (file) {
935 if (chown(filename, owner, group) == -1)
936 Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unable to chown(): %s\n", config.name, config.type, filename, strerror(errno));
937
938 if (file_lock(fileno(file))) {
939 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, config.type, filename);
940 return;
941 }
942 sprintf(pid, "%d\n", getpid());
943 fwrite(pid, strlen(pid), 1, file);
944
945 file_unlock(fileno(file));
946 fclose(file);
947 }
948 else {
949 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] fopen() failed.\n", config.name, config.type, filename);
950 return;
951 }
952 }
953
write_pid_file_plugin(char * filename,char * type,char * name)954 void write_pid_file_plugin(char *filename, char *type, char *name)
955 {
956 int len = strlen(filename) + strlen(type) + strlen(name) + 3;
957 FILE *file;
958 char *fname, pid[10], minus[] = "-";
959 uid_t owner = -1;
960 gid_t group = -1;
961
962 fname = malloc(len);
963 if (!fname) {
964 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed.\n", config.name, config.type, filename);
965 return;
966 }
967 memset(fname, 0, len);
968 strcpy(fname, filename);
969 strcat(fname, minus);
970 strcat(fname, type);
971 strcat(fname, minus);
972 strcat(fname, name);
973
974 config.pidfile = fname;
975 unlink(fname);
976
977 if (config.files_uid) owner = config.files_uid;
978 if (config.files_gid) group = config.files_gid;
979
980 file = fopen(fname, "w");
981 if (file) {
982 if (chown(fname, owner, group) == -1)
983 Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unable to chown(): %s\n", config.name, config.type, fname, strerror(errno));
984
985 if (file_lock(fileno(file))) {
986 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, config.type, fname);
987 goto exit_lane;
988 }
989 sprintf(pid, "%d\n", getpid());
990 fwrite(pid, strlen(pid), 1, file);
991
992 file_unlock(fileno(file));
993 fclose(file);
994 }
995 else {
996 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] fopen() failed.\n", config.name, config.type, fname);
997 goto exit_lane;
998 }
999
1000 return;
1001
1002 exit_lane:
1003 config.pidfile = NULL;
1004 free(fname);
1005 }
1006
remove_pid_file(char * filename)1007 void remove_pid_file(char *filename)
1008 {
1009 unlink(filename);
1010 }
1011
file_lock(int fd)1012 int file_lock(int fd)
1013 {
1014 int ret;
1015 #if defined SOLARIS
1016 flock_t lock;
1017
1018 lock.l_type = F_WRLCK;
1019 lock.l_whence = 0;
1020 lock.l_start = 0;
1021 lock.l_len = 0;
1022
1023 ret = fcntl(fd, F_SETLK, &lock);
1024 return((ret == -1) ? -1 : 0);
1025 #else
1026 ret = lockf(fd, F_LOCK, 0);
1027 return ret;
1028 #endif
1029 }
1030
file_unlock(int fd)1031 int file_unlock(int fd)
1032 {
1033 int ret;
1034 #if defined SOLARIS
1035 flock_t lock;
1036
1037 lock.l_type = F_UNLCK;
1038 lock.l_whence = 0;
1039 lock.l_start = 0;
1040 lock.l_len = 0;
1041
1042 ret = fcntl(fd, F_SETLK, &lock);
1043 return((ret == -1) ? -1 : 0);
1044 #else
1045 ret = lockf(fd, F_ULOCK, 0);
1046 return ret;
1047 #endif
1048 }
1049
sanitize_buf_net(char * filename,char * buf,int rows)1050 int sanitize_buf_net(char *filename, char *buf, int rows)
1051 {
1052 if (!sanitize_buf(buf)) {
1053 if (!strchr(buf, '/')) {
1054 Log(LOG_ERR, "ERROR ( %s/%s ): [%s:%u] Missing '/' separator. Ignoring.\n", config.name, config.type, filename, rows);
1055 return TRUE;
1056 }
1057 }
1058 else return TRUE;
1059
1060 return FALSE;
1061 }
1062
sanitize_buf(char * buf)1063 int sanitize_buf(char *buf)
1064 {
1065 int x = 0, valid_char = 0;
1066
1067 trim_all_spaces(buf);
1068 while (x < strlen(buf)) {
1069 if (!isspace(buf[x])) valid_char++;
1070 x++;
1071 }
1072 if (!valid_char) return TRUE;
1073 if (buf[0] == '!') return TRUE;
1074
1075 return FALSE;
1076 }
1077
check_not_valid_char(char * filename,char * buf,int c)1078 int check_not_valid_char(char *filename, char *buf, int c)
1079 {
1080 if (!buf) return FALSE;
1081
1082 if (strchr(buf, c)) {
1083 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Invalid symbol '%c' detected.\n", config.name, config.type, filename, c);
1084 return TRUE;
1085 }
1086 else return FALSE;
1087 }
1088
mark_columns(char * buf)1089 void mark_columns(char *buf)
1090 {
1091 int len, x, word = FALSE, quotes = FALSE;
1092
1093 if (!buf) return;
1094
1095 len = strlen(buf);
1096 for (x = 0; x < len; x++) {
1097 if (buf[x] == '\'') {
1098 if (!quotes) quotes = TRUE;
1099 else if (quotes) quotes = FALSE;
1100 }
1101 if ((isalpha(buf[x])||isdigit(buf[x])||ispunct(buf[x])) && !word) word = TRUE;
1102 if (isspace(buf[x]) && word && !quotes) {
1103 buf[x] = '|';
1104 word = FALSE;
1105 }
1106 }
1107
1108 /* removing trailing '|' if any */
1109 x = strlen(buf);
1110 word = FALSE;
1111
1112 while (x > 0) {
1113 if (buf[x] == '|' && !word) buf[x] = '\0';
1114 if ((isalpha(buf[x])||isdigit(buf[x])||ispunct(buf[x])) && !word) word = TRUE;
1115 x--;
1116 }
1117 }
1118
Setsocksize(int s,int level,int optname,void * optval,socklen_t optlen)1119 int Setsocksize(int s, int level, int optname, void *optval, socklen_t optlen)
1120 {
1121 int ret = 0, saved, value;
1122 socklen_t len = sizeof(int);
1123
1124 memcpy(&value, optval, sizeof(int));
1125
1126 getsockopt(s, level, optname, &saved, &len);
1127 if (value > saved) {
1128 for (; value; value >>= 1) {
1129 ret = setsockopt(s, level, optname, &value, optlen);
1130 if (ret >= 0) break;
1131 }
1132 if (!value) setsockopt(s, level, optname, &saved, len);
1133 }
1134
1135 return ret;
1136 }
1137
map_shared(void * addr,size_t len,int prot,int flags,int fd,off_t off)1138 void *map_shared(void *addr, size_t len, int prot, int flags, int fd, off_t off)
1139 {
1140 #if defined USE_DEVZERO
1141 void *mem;
1142 int devzero;
1143
1144 devzero = open ("/dev/zero", O_RDWR);
1145 if (devzero < 0) return MAP_FAILED;
1146 mem = mmap(addr, len, prot, flags, devzero, off);
1147 close(devzero);
1148
1149 return mem;
1150 #else /* MAP_ANON or MAP_ANONYMOUS */
1151 return (void *)mmap(addr, len, prot, flags, fd, off);
1152 #endif
1153 }
1154
lower_string(char * string)1155 void lower_string(char *string)
1156 {
1157 int i = 0;
1158
1159 if (!string) return;
1160
1161 while (string[i] != '\0') {
1162 string[i] = tolower(string[i]);
1163 i++;
1164 }
1165 }
1166
evaluate_sums(u_int64_t * wtc,u_int64_t * wtc_2,char * name,char * type)1167 void evaluate_sums(u_int64_t *wtc, u_int64_t *wtc_2, char *name, char *type)
1168 {
1169 int tag = FALSE;
1170 int tag2 = FALSE;
1171 int class = FALSE;
1172 int ndpi_class = FALSE;
1173 int flows = FALSE;
1174
1175 if (*wtc & COUNT_TAG) {
1176 *wtc ^= COUNT_TAG;
1177 tag = TRUE;
1178 }
1179
1180 if (*wtc & COUNT_TAG2) {
1181 *wtc ^= COUNT_TAG2;
1182 tag2 = TRUE;
1183 }
1184
1185 if (*wtc & COUNT_CLASS) {
1186 *wtc ^= COUNT_CLASS;
1187 class = TRUE;
1188 }
1189
1190 if (*wtc_2 & COUNT_NDPI_CLASS) {
1191 *wtc_2 ^= COUNT_NDPI_CLASS;
1192 ndpi_class = TRUE;
1193 }
1194
1195 if (*wtc & COUNT_FLOWS) {
1196 *wtc ^= COUNT_FLOWS;
1197 flows = TRUE;
1198 }
1199
1200 if (*wtc & COUNT_SUM_MAC) {
1201 if (*wtc != COUNT_SUM_MAC) {
1202 *wtc = COUNT_SUM_MAC;
1203 Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type);
1204 }
1205 }
1206
1207 if (*wtc & COUNT_SUM_HOST) {
1208 if (*wtc != COUNT_SUM_HOST) {
1209 *wtc = COUNT_SUM_HOST;
1210 Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type);
1211 }
1212 }
1213 else if (*wtc & COUNT_SUM_NET) {
1214 if (*wtc != COUNT_SUM_NET) {
1215 *wtc = COUNT_SUM_NET;
1216 Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type);
1217 }
1218 }
1219 else if (*wtc & COUNT_SUM_AS) {
1220 if (*wtc != COUNT_SUM_AS) {
1221 *wtc = COUNT_SUM_AS;
1222 Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type);
1223 }
1224 }
1225 else if (*wtc & COUNT_SUM_PORT) {
1226 if (*wtc != COUNT_SUM_PORT) {
1227 *wtc = COUNT_SUM_PORT;
1228 Log(LOG_WARNING, "WARN ( %s/%s ): SUM aggregation is to be used alone. Resetting other aggregation methods.\n", name, type);
1229 }
1230 }
1231
1232 if (tag) *wtc |= COUNT_TAG;
1233 if (tag2) *wtc |= COUNT_TAG2;
1234 if (class) *wtc |= COUNT_CLASS;
1235 if (ndpi_class) *wtc_2 |= COUNT_NDPI_CLASS;
1236 if (flows) *wtc |= COUNT_FLOWS;
1237 }
1238
stop_all_childs()1239 void stop_all_childs()
1240 {
1241 PM_sigint_handler(0); /* it does same thing */
1242 }
1243
pm_strftime(char * s,int max,char * format,const time_t * time_ref,int utc)1244 void pm_strftime(char *s, int max, char *format, const time_t *time_ref, int utc)
1245 {
1246 time_t time_loc;
1247 struct tm *tm_loc;
1248
1249 if (time_ref && (*time_ref)) time_loc = (*time_ref);
1250 else time_loc = time(NULL);
1251
1252 if (!utc) tm_loc = localtime(&time_loc);
1253 else tm_loc = gmtime(&time_loc);
1254
1255 strftime(s, max, format, tm_loc);
1256 insert_rfc3339_timezone(s, max, tm_loc);
1257 }
1258
1259 /* format is expected in s; tmp being just a temporary buffer;
1260 both s and tmp are expected to be of at least max space */
pm_strftime_same(char * s,int max,char * tmp,const time_t * time_ref,int utc)1261 void pm_strftime_same(char *s, int max, char *tmp, const time_t *time_ref, int utc)
1262 {
1263 time_t time_loc;
1264 struct tm *tm_loc;
1265
1266 if (time_ref && (*time_ref)) time_loc = (*time_ref);
1267 else time_loc = time(NULL);
1268
1269 if (!utc) tm_loc = localtime(&time_loc);
1270 else tm_loc = gmtime(&time_loc);
1271
1272 strftime(tmp, max, s, tm_loc);
1273 insert_rfc3339_timezone(tmp, max, tm_loc);
1274 strlcpy(s, tmp, max);
1275 }
1276
insert_rfc3339_timezone(char * s,int slen,const struct tm * nowtm)1277 void insert_rfc3339_timezone(char *s, int slen, const struct tm *nowtm)
1278 {
1279 char buf[8], tzone_string[] = "$tzone";
1280 char *ptr_start = strstr(s, tzone_string), *ptr_end;
1281
1282 if (ptr_start) {
1283 ptr_end = ptr_start + 6 /* $tzone */;
1284 strftime(buf, 8, "%z", nowtm);
1285
1286 if (!strcmp(buf, "+0000")) {
1287 ptr_start[0] = 'Z';
1288 ptr_start++;
1289 strcpy(ptr_start, ptr_end);
1290 }
1291 else {
1292 /* ie. '+0200', '-0100', etc. */
1293 if (strlen(buf) == 5) {
1294 ptr_start[0] = buf[0];
1295 ptr_start[1] = buf[1];
1296 ptr_start[2] = buf[2];
1297 ptr_start[3] = ':';
1298 ptr_start[4] = buf[3];
1299 ptr_start[5] = buf[4];
1300 }
1301 }
1302 }
1303 }
1304
append_rfc3339_timezone(char * s,int slen,const struct tm * nowtm)1305 void append_rfc3339_timezone(char *s, int slen, const struct tm *nowtm)
1306 {
1307 int len = strlen(s), max = (slen - len);
1308 char buf[8], zulu[] = "Z";
1309
1310 strftime(buf, 8, "%z", nowtm);
1311
1312 if (!strcmp(buf, "+0000")) {
1313 if (max) strcat(s, zulu);
1314 }
1315 else {
1316 if (max >= 7) {
1317 s[len] = buf[0]; len++;
1318 s[len] = buf[1]; len++;
1319 s[len] = buf[2]; len++;
1320 s[len] = ':'; len++;
1321 s[len] = buf[3]; len++;
1322 s[len] = buf[4]; len++;
1323 s[len] = '\0';
1324 }
1325 }
1326 }
1327
read_SQLquery_from_file(char * path,char * buf,int size)1328 int read_SQLquery_from_file(char *path, char *buf, int size)
1329 {
1330 FILE *f;
1331 char *ptr;
1332 int ret;
1333
1334 memset(buf, 0, size);
1335 f = fopen(path, "r");
1336 if (!f) {
1337 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file does not exist.\n", config.name, config.type, path);
1338 return(0);
1339 }
1340
1341 ret = fread(buf, size, 1, f);
1342
1343 if (ret != 1 && !feof(f)) {
1344 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to read from SQL schema: %s\n", config.name, config.type, path, strerror(errno));
1345 return(0);
1346 }
1347
1348 fclose(f);
1349
1350 ptr = strrchr(buf, ';');
1351 if (!ptr) {
1352 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] missing trailing ';' in SQL query.\n", config.name, config.type, path);
1353 return(0);
1354 }
1355 else *ptr = '\0';
1356
1357 return (int)*ptr-(int)*buf;
1358 }
1359
stick_bosbit(u_char * label)1360 void stick_bosbit(u_char *label)
1361 {
1362 u_char *ptr;
1363
1364 ptr = label+2;
1365 *ptr |= 0x1;
1366 }
1367
check_bosbit(u_char * label)1368 int check_bosbit(u_char *label)
1369 {
1370 u_char *ptr;
1371
1372 ptr = label+2;
1373
1374 if (*ptr & 0x1) return TRUE;
1375 else return FALSE;
1376 }
1377
decode_mpls_label(u_char * label)1378 u_int32_t decode_mpls_label(u_char *label)
1379 {
1380 u_int32_t ret = 0;
1381 u_char label_ttl[4];
1382
1383 memset(label_ttl, 0, 4);
1384 memcpy(label_ttl, label, 3);
1385 ret = ntohl(*(uint32_t *)(label_ttl));
1386 ret = ((ret & 0xfffff000 /* label mask */) >> 12 /* label shift */);
1387
1388 return ret;
1389 }
1390
encode_mpls_label(char * out_label,u_int32_t in_label)1391 void encode_mpls_label(char *out_label, u_int32_t in_label)
1392 {
1393 u_int32_t tmp;
1394 u_char loc_label[4];
1395
1396 memset(out_label, 0, 3);
1397 tmp = in_label;
1398 tmp <<= 4; /* label shift */
1399 memcpy(loc_label, &tmp, 4);
1400 out_label[0] = loc_label[2];
1401 out_label[1] = loc_label[1];
1402 out_label[2] = loc_label[0];
1403 }
1404
1405 /*
1406 * timeval_cmp(): returns > 0 if a > b; < 0 if a < b; 0 if a == b.
1407 */
timeval_cmp(struct timeval * a,struct timeval * b)1408 int timeval_cmp(struct timeval *a, struct timeval *b)
1409 {
1410 if (a->tv_sec > b->tv_sec) return 1;
1411 if (a->tv_sec < b->tv_sec) return -1;
1412 if (a->tv_sec == b->tv_sec) {
1413 if (a->tv_usec > b->tv_usec) return 1;
1414 if (a->tv_usec < b->tv_usec) return -1;
1415 if (a->tv_usec == b->tv_usec) return 0;
1416 }
1417
1418 return INT_MIN; /* silence compiler warning */
1419 }
1420
1421 /*
1422 * exit_all(): Core Process exit lane. Not meant to be a nice shutdown method: it is
1423 * an exit() replacement that sends kill signals to the plugins.
1424 */
exit_all(int status)1425 void exit_all(int status)
1426 {
1427 struct plugins_list_entry *list = plugins_list;
1428
1429 #if defined (SOLARIS)
1430 signal(SIGCHLD, SIG_IGN);
1431 #else
1432 signal(SIGCHLD, ignore_falling_child);
1433 #endif
1434
1435 while (list) {
1436 if (memcmp(list->type.string, "core", sizeof("core"))) kill(list->pid, SIGKILL);
1437 list = list->next;
1438 }
1439
1440 wait(NULL);
1441 if (config.pidfile) remove_pid_file(config.pidfile);
1442
1443 exit(status);
1444 }
1445
1446 /* exit_plugin(): meant to be called on exit by plugins; it is a simple wrapper to
1447 enforce some final operations before shutting down */
exit_plugin(int status)1448 void exit_plugin(int status)
1449 {
1450 if (config.pidfile) remove_pid_file(config.pidfile);
1451
1452 exit(status);
1453 }
1454
exit_gracefully(int status)1455 void exit_gracefully(int status)
1456 {
1457 if (!config.is_forked) {
1458 if (config.type_id == PLUGIN_ID_CORE) exit_all(status);
1459 else exit_plugin(status);
1460 }
1461 else exit(status);
1462 }
1463
reset_tag_label_status(struct packet_ptrs_vector * pptrsv)1464 void reset_tag_label_status(struct packet_ptrs_vector *pptrsv)
1465 {
1466 pptrsv->v4.tag = FALSE;
1467 pptrsv->vlan4.tag = FALSE;
1468 pptrsv->mpls4.tag = FALSE;
1469 pptrsv->vlanmpls4.tag = FALSE;
1470 pptrsv->v4.tag2 = FALSE;
1471 pptrsv->vlan4.tag2 = FALSE;
1472 pptrsv->mpls4.tag2 = FALSE;
1473 pptrsv->vlanmpls4.tag2 = FALSE;
1474 pretag_free_label(&pptrsv->v4.label);
1475 pretag_free_label(&pptrsv->vlan4.label);
1476 pretag_free_label(&pptrsv->mpls4.label);
1477 pretag_free_label(&pptrsv->vlanmpls4.label);
1478
1479 pptrsv->v6.tag = FALSE;
1480 pptrsv->vlan6.tag = FALSE;
1481 pptrsv->mpls6.tag = FALSE;
1482 pptrsv->vlanmpls6.tag = FALSE;
1483 pptrsv->v6.tag2 = FALSE;
1484 pptrsv->vlan6.tag2 = FALSE;
1485 pptrsv->mpls6.tag2 = FALSE;
1486 pptrsv->vlanmpls6.tag2 = FALSE;
1487 pretag_free_label(&pptrsv->v6.label);
1488 pretag_free_label(&pptrsv->vlan6.label);
1489 pretag_free_label(&pptrsv->mpls6.label);
1490 pretag_free_label(&pptrsv->vlanmpls6.label);
1491 }
1492
reset_net_status(struct packet_ptrs * pptrs)1493 void reset_net_status(struct packet_ptrs *pptrs)
1494 {
1495 pptrs->lm_mask_src = FALSE;
1496 pptrs->lm_mask_dst = FALSE;
1497 pptrs->lm_method_src = FALSE;
1498 pptrs->lm_method_dst = FALSE;
1499 }
1500
reset_net_status_v(struct packet_ptrs_vector * pptrsv)1501 void reset_net_status_v(struct packet_ptrs_vector *pptrsv)
1502 {
1503 pptrsv->v4.lm_mask_src = FALSE;
1504 pptrsv->vlan4.lm_mask_src = FALSE;
1505 pptrsv->mpls4.lm_mask_src = FALSE;
1506 pptrsv->vlanmpls4.lm_mask_src = FALSE;
1507 pptrsv->v4.lm_mask_dst = FALSE;
1508 pptrsv->vlan4.lm_mask_dst = FALSE;
1509 pptrsv->mpls4.lm_mask_dst = FALSE;
1510 pptrsv->vlanmpls4.lm_mask_dst = FALSE;
1511 pptrsv->v4.lm_method_src = FALSE;
1512 pptrsv->vlan4.lm_method_src = FALSE;
1513 pptrsv->mpls4.lm_method_src = FALSE;
1514 pptrsv->vlanmpls4.lm_method_src = FALSE;
1515 pptrsv->v4.lm_method_dst = FALSE;
1516 pptrsv->vlan4.lm_method_dst = FALSE;
1517 pptrsv->mpls4.lm_method_dst = FALSE;
1518 pptrsv->vlanmpls4.lm_method_dst = FALSE;
1519
1520 pptrsv->v6.lm_mask_src = FALSE;
1521 pptrsv->vlan6.lm_mask_src = FALSE;
1522 pptrsv->mpls6.lm_mask_src = FALSE;
1523 pptrsv->vlanmpls6.lm_mask_src = FALSE;
1524 pptrsv->v6.lm_mask_dst = FALSE;
1525 pptrsv->vlan6.lm_mask_dst = FALSE;
1526 pptrsv->mpls6.lm_mask_dst = FALSE;
1527 pptrsv->vlanmpls6.lm_mask_dst = FALSE;
1528 pptrsv->v6.lm_method_src = FALSE;
1529 pptrsv->vlan6.lm_method_src = FALSE;
1530 pptrsv->mpls6.lm_method_src = FALSE;
1531 pptrsv->vlanmpls6.lm_method_src = FALSE;
1532 pptrsv->v6.lm_method_dst = FALSE;
1533 pptrsv->vlan6.lm_method_dst = FALSE;
1534 pptrsv->mpls6.lm_method_dst = FALSE;
1535 pptrsv->vlanmpls6.lm_method_dst = FALSE;
1536 }
1537
reset_shadow_status(struct packet_ptrs_vector * pptrsv)1538 void reset_shadow_status(struct packet_ptrs_vector *pptrsv)
1539 {
1540 pptrsv->v4.shadow = FALSE;
1541 pptrsv->vlan4.shadow = FALSE;
1542 pptrsv->mpls4.shadow = FALSE;
1543 pptrsv->vlanmpls4.shadow = FALSE;
1544
1545 pptrsv->v6.shadow = FALSE;
1546 pptrsv->vlan6.shadow = FALSE;
1547 pptrsv->mpls6.shadow = FALSE;
1548 pptrsv->vlanmpls6.shadow = FALSE;
1549 }
1550
reset_fallback_status(struct packet_ptrs * pptrs)1551 void reset_fallback_status(struct packet_ptrs *pptrs)
1552 {
1553 pptrs->renormalized = FALSE;
1554 }
1555
set_default_preferences(struct configuration * cfg)1556 void set_default_preferences(struct configuration *cfg)
1557 {
1558 if (!cfg->proc_name) cfg->proc_name = default_proc_name;
1559 if (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF) {
1560 if (!cfg->nfacctd_net) cfg->nfacctd_net = NF_NET_KEEP;
1561 if (!cfg->nfacctd_as) cfg->nfacctd_as = NF_AS_KEEP;
1562 set_truefalse_nonzero(&cfg->nfacctd_disable_checks);
1563 }
1564 if (!cfg->bgp_daemon_peer_as_src_type) cfg->bgp_daemon_peer_as_src_type = BGP_SRC_PRIMITIVES_KEEP;
1565 if (!cfg->bgp_daemon_src_std_comm_type) cfg->bgp_daemon_src_std_comm_type = BGP_SRC_PRIMITIVES_KEEP;
1566 if (!cfg->bgp_daemon_src_ext_comm_type) cfg->bgp_daemon_src_ext_comm_type = BGP_SRC_PRIMITIVES_KEEP;
1567 if (!cfg->bgp_daemon_src_lrg_comm_type) cfg->bgp_daemon_src_lrg_comm_type = BGP_SRC_PRIMITIVES_KEEP;
1568 if (!cfg->bgp_daemon_src_as_path_type) cfg->bgp_daemon_src_as_path_type = BGP_SRC_PRIMITIVES_KEEP;
1569 if (!cfg->bgp_daemon_src_local_pref_type) cfg->bgp_daemon_src_local_pref_type = BGP_SRC_PRIMITIVES_KEEP;
1570 if (!cfg->bgp_daemon_src_med_type) cfg->bgp_daemon_src_med_type = BGP_SRC_PRIMITIVES_KEEP;
1571 }
1572
set_shadow_status(struct packet_ptrs * pptrs)1573 void set_shadow_status(struct packet_ptrs *pptrs)
1574 {
1575 pptrs->shadow = TRUE;
1576 }
1577
set_sampling_table(struct packet_ptrs_vector * pptrsv,u_char * t)1578 void set_sampling_table(struct packet_ptrs_vector *pptrsv, u_char *t)
1579 {
1580 pptrsv->v4.sampling_table = t;
1581 pptrsv->vlan4.sampling_table = t;
1582 pptrsv->mpls4.sampling_table = t;
1583 pptrsv->vlanmpls4.sampling_table = t;
1584
1585 pptrsv->v6.sampling_table = t;
1586 pptrsv->vlan6.sampling_table = t;
1587 pptrsv->mpls6.sampling_table = t;
1588 pptrsv->vlanmpls6.sampling_table = t;
1589 }
1590
pm_malloc(size_t size)1591 void *pm_malloc(size_t size)
1592 {
1593 unsigned char *obj;
1594
1595 obj = (unsigned char *) malloc(size);
1596 if (!obj) {
1597 Log(LOG_ERR, "ERROR ( %s/%s ): Unable to grab enough memory (requested: %zu bytes). Exiting ...\n",
1598 config.name, config.type, size);
1599 exit_gracefully(1);
1600 }
1601
1602 return obj;
1603 }
1604
pm_tsearch(const void * key,void ** rootp,int (* compar)(const void * key1,const void * key2),size_t alloc_size)1605 void *pm_tsearch(const void *key, void **rootp, int (*compar)(const void *key1, const void *key2), size_t alloc_size)
1606 {
1607 void *alloc_key, *ret_key;
1608
1609 if (alloc_size) {
1610 alloc_key = malloc(alloc_size);
1611 memcpy(alloc_key, key, alloc_size);
1612 ret_key = __pm_tsearch(alloc_key, rootp, compar);
1613
1614 if ((*(void **) ret_key) != alloc_key) free(alloc_key);
1615
1616 return ret_key;
1617 }
1618 else return __pm_tsearch(key, rootp, compar);
1619 }
1620
pm_tdestroy(void ** root,void (* free_node)(void * nodep))1621 void pm_tdestroy(void **root, void (*free_node)(void *nodep))
1622 {
1623 /* in implementations where tdestroy() is not defined, tdelete() against
1624 the root node of the tree would destroy also the last few remaining
1625 bits */
1626 #if (defined HAVE_TDESTROY)
1627 __pm_tdestroy((*root), free_node);
1628 #endif
1629
1630 (*root) = NULL;
1631 }
1632
load_allow_file(char * filename,struct hosts_table * t)1633 void load_allow_file(char *filename, struct hosts_table *t)
1634 {
1635 struct stat st;
1636 FILE *file;
1637 char buf[SRVBUFLEN];
1638 int index = 0;
1639
1640 if (filename) {
1641 if ((file = fopen(filename, "r")) == NULL) {
1642 Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename);
1643 goto handle_error;
1644 }
1645
1646 memset(t->table, 0, sizeof(t->table));
1647 while (!feof(file)) {
1648 if (index >= MAX_MAP_ENTRIES) break; /* XXX: we shouldn't exit silently */
1649 memset(buf, 0, SRVBUFLEN);
1650 if (fgets(buf, SRVBUFLEN, file)) {
1651 if (!sanitize_buf(buf)) {
1652 if (str_to_addr_mask(buf, &t->table[index].addr, &t->table[index].mask)) index++;
1653 else Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Bad IP address '%s'. Ignored.\n", config.name, config.type, filename, buf);
1654 }
1655 }
1656 }
1657 t->num = index;
1658
1659 /* Set to -1 to distinguish between no map and empty map conditions */
1660 if (!t->num) t->num = -1;
1661
1662 fclose(file);
1663
1664 stat(filename, &st);
1665 t->timestamp = st.st_mtime;
1666 }
1667
1668 return;
1669
1670 handle_error:
1671 if (t->timestamp) {
1672 Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back old map.\n", config.name, config.type, filename);
1673
1674 stat(filename, &st);
1675 t->timestamp = st.st_mtime;
1676 }
1677 else exit_gracefully(1);
1678 }
1679
check_allow(struct hosts_table * allow,struct sockaddr * sa)1680 int check_allow(struct hosts_table *allow, struct sockaddr *sa)
1681 {
1682 int index;
1683
1684 if (!allow || !sa) return FALSE;
1685
1686 for (index = 0; index < allow->num; index++) {
1687 if (host_addr_mask_sa_cmp(&allow->table[index].addr, &allow->table[index].mask, sa) == 0)
1688 return TRUE;
1689 }
1690
1691 return FALSE;
1692 }
1693
BTA_find_id(struct id_table * t,struct packet_ptrs * pptrs,pm_id_t * tag,pm_id_t * tag2)1694 int BTA_find_id(struct id_table *t, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2)
1695 {
1696 struct xflow_status_entry *xsentry = (struct xflow_status_entry *) pptrs->f_status;
1697 struct xflow_status_map_cache *xsmc = NULL;
1698 int ret = 0;
1699
1700 pptrs->bta_af = 0;
1701
1702 if (bta_map_caching && xsentry) {
1703 if (pptrs->l3_proto == ETHERTYPE_IP) xsmc = &xsentry->bta_v4;
1704 else if (pptrs->l3_proto == ETHERTYPE_IPV6) xsmc = &xsentry->bta_v6;
1705 }
1706
1707 if (bta_map_caching && xsmc && timeval_cmp(&xsmc->stamp, &reload_map_tstamp) > 0) {
1708 *tag = xsmc->tag;
1709 *tag2 = xsmc->tag2;
1710 ret = xsmc->ret;
1711 memcpy(&pptrs->lookup_bgp_port, &xsmc->port, sizeof(s_uint16_t));
1712 }
1713 else {
1714 if (find_id_func) {
1715 ret = find_id_func(t, pptrs, tag, tag2);
1716 if (xsmc) {
1717 xsmc->tag = *tag;
1718 xsmc->tag2 = *tag2;
1719 xsmc->ret = ret;
1720 memcpy(&xsmc->port, &pptrs->lookup_bgp_port, sizeof(s_uint16_t));
1721 gettimeofday(&xsmc->stamp, NULL);
1722 }
1723 }
1724 }
1725
1726 if (ret & PRETAG_MAP_RCODE_ID) pptrs->bta_af = ETHERTYPE_IP;
1727 else if (ret & BTA_MAP_RCODE_ID_ID2) pptrs->bta_af = ETHERTYPE_IPV6;
1728
1729 return ret;
1730 }
1731
calc_refresh_timeout(time_t deadline,time_t now,int * timeout)1732 void calc_refresh_timeout(time_t deadline, time_t now, int *timeout)
1733 {
1734 if (deadline >= now) *timeout = ((deadline-now)+1)*1000;
1735 else *timeout = 0;
1736 }
1737
1738 /* secs version of calc_refresh_timeout() */
calc_refresh_timeout_sec(time_t deadline,time_t now,int * timeout)1739 void calc_refresh_timeout_sec(time_t deadline, time_t now, int *timeout)
1740 {
1741 if (deadline >= now) *timeout = ((deadline-now)+1);
1742 else *timeout = 0;
1743 }
1744
load_tags(char * filename,struct pretag_filter * filter,char * value_ptr)1745 int load_tags(char *filename, struct pretag_filter *filter, char *value_ptr)
1746 {
1747 char *count_token, *range_ptr;
1748 pm_id_t value = 0, range = 0;
1749 int changes = 0;
1750 char *endptr_v, *endptr_r;
1751 u_int8_t neg;
1752
1753 if (!filter || !value_ptr) return changes;
1754
1755 trim_all_spaces(value_ptr);
1756 filter->num = 0;
1757
1758 while ((count_token = extract_token(&value_ptr, ',')) && changes < MAX_PRETAG_MAP_ENTRIES/4) {
1759 neg = pt_check_neg(&count_token, NULL);
1760 range_ptr = pt_check_range(count_token);
1761 value = strtoull(count_token, &endptr_v, 10);
1762 if (range_ptr) range = strtoull(range_ptr, &endptr_r, 10);
1763 else range = value;
1764
1765 if (range_ptr && range <= value) {
1766 Log(LOG_ERR, "WARN ( %s/%s ): [%s] Range value is expected in format low-high. '%" PRIu64 "-%" PRIu64 "'.\n",
1767 config.name, config.type, filename, value, range);
1768 changes++;
1769 break;
1770 }
1771
1772 filter->table[filter->num].neg = neg;
1773 filter->table[filter->num].n = value;
1774 filter->table[filter->num].r = range;
1775 filter->num++;
1776 changes++;
1777 }
1778
1779 return changes;
1780 }
1781
load_labels(char * filename,struct pretag_label_filter * filter,char * value_ptr)1782 int load_labels(char *filename, struct pretag_label_filter *filter, char *value_ptr)
1783 {
1784 char *count_token, *value;
1785 int changes = 0;
1786 u_int8_t neg = 0;
1787
1788 if (!filter || !value_ptr) return changes;
1789
1790 filter->num = 0;
1791
1792 while ((count_token = extract_token(&value_ptr, ',')) && changes < MAX_PRETAG_MAP_ENTRIES/4) {
1793 neg = pt_check_neg(&count_token, NULL);
1794 value = count_token;
1795
1796 filter->table[filter->num].neg = neg;
1797 filter->table[filter->num].v = value;
1798 filter->table[filter->num].len = strlen(value);
1799 filter->num++;
1800 changes++;
1801 }
1802
1803 return changes;
1804 }
1805
1806 /* return value:
1807 TRUE: We want it!
1808 FALSE: Discard it!
1809 */
1810
evaluate_tags(struct pretag_filter * filter,pm_id_t tag)1811 int evaluate_tags(struct pretag_filter *filter, pm_id_t tag)
1812 {
1813 int index;
1814
1815 if (filter->num == 0) return FALSE; /* no entries in the filter array: tag filtering disabled */
1816
1817 for (index = 0; index < filter->num; index++) {
1818 if (filter->table[index].n <= tag && filter->table[index].r >= tag) return (FALSE | filter->table[index].neg);
1819 else if (filter->table[index].neg) return FALSE;
1820 }
1821
1822 return TRUE;
1823 }
1824
evaluate_labels(struct pretag_label_filter * filter,pt_label_t * label)1825 int evaluate_labels(struct pretag_label_filter *filter, pt_label_t *label)
1826 {
1827 int index;
1828 char *null_label = "null";
1829
1830 if (filter->num == 0) return FALSE; /* no entries in the filter array: tag filtering disabled */
1831 if (!label->val) label->val = strdup(null_label);
1832
1833 for (index = 0; index < filter->num; index++) {
1834 if (!memcmp(filter->table[index].v, label->val, filter->table[index].len)) return (FALSE | filter->table[index].neg);
1835 else {
1836 if (filter->table[index].neg) return FALSE;
1837 }
1838 }
1839
1840 return TRUE;
1841 }
1842
write_sep(char * sep,int * count)1843 char *write_sep(char *sep, int *count)
1844 {
1845 static char empty_sep[] = "";
1846
1847 if (*count) return sep;
1848 else {
1849 (*count)++;
1850 return empty_sep;
1851 }
1852 }
1853
version_daemon(char * header)1854 void version_daemon(char *header)
1855 {
1856 struct utsname utsbuf;
1857
1858 printf("%s %s (%s)\n\n", header, PMACCT_VERSION, PMACCT_BUILD);
1859
1860 printf("Arguments:\n");
1861 printf("%s\n", PMACCT_COMPILE_ARGS);
1862 printf("\n");
1863
1864 printf("Libs:\n");
1865 printf("%s\n", pcap_lib_version());
1866 #ifdef WITH_MYSQL
1867 MY_mysql_get_version();
1868 #endif
1869 #ifdef WITH_PGSQL
1870 PG_postgresql_get_version();
1871 #endif
1872 #ifdef WITH_SQLITE3
1873 SQLI_sqlite3_get_version();
1874 #endif
1875 #ifdef WITH_RABBITMQ
1876 p_amqp_get_version();
1877 #endif
1878 #ifdef WITH_KAFKA
1879 p_kafka_get_version();
1880 #endif
1881 #ifdef WITH_JANSSON
1882 printf("jansson %s\n", JANSSON_VERSION);
1883 #endif
1884 #ifdef WITH_GEOIPV2
1885 printf("MaxmindDB %s\n", MMDB_lib_version());
1886 #endif
1887 #ifdef WITH_ZMQ
1888 printf("ZeroMQ %u.%u.%u\n", ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH);
1889 #endif
1890 #ifdef WITH_REDIS
1891 printf("Redis %u.%u.%u\n", HIREDIS_MAJOR, HIREDIS_MINOR, HIREDIS_PATCH);
1892 #endif
1893 #ifdef WITH_AVRO
1894 printf("avro-c\n");
1895 #endif
1896 #ifdef WITH_SERDES
1897 printf("serdes\n");
1898 #endif
1899 #ifdef WITH_NDPI
1900 printf("nDPI %s\n", ndpi_revision());
1901 #endif
1902 #ifdef WITH_NFLOG
1903 printf("netfilter_log\n");
1904 #endif
1905 printf("\n");
1906
1907 if (!uname(&utsbuf)) {
1908 printf("System:\n");
1909 printf("%s %s %s %s\n", utsbuf.sysname, utsbuf.release, utsbuf.version, utsbuf.machine);
1910 printf("\n");
1911 }
1912
1913 #if defined __clang__
1914 #ifndef PM_COMPILER_NAME
1915 #define PM_COMPILER_NAME "clang"
1916 #endif
1917 #ifndef PM_COMPILER_VERSION
1918 #define PM_COMPILER_VERSION __clang_major__, __clang_minor__, __clang_patchlevel__
1919 #endif
1920 #endif
1921
1922 #if defined __GNUC__
1923 #ifndef PM_COMPILER_NAME
1924 #define PM_COMPILER_NAME "gcc"
1925 #endif
1926 #ifndef PM_COMPILER_VERSION
1927 #define PM_COMPILER_VERSION __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__
1928 #endif
1929 #endif
1930
1931 #if defined PM_COMPILER_NAME && defined PM_COMPILER_VERSION
1932 printf("Compiler:\n");
1933 printf("%s %d.%d.%d\n", PM_COMPILER_NAME, PM_COMPILER_VERSION);
1934 printf("\n");
1935 #endif
1936
1937 printf("For suggestions, critics, bugs, contact me: %s.\n", MANTAINER);
1938 }
1939
1940 #ifdef WITH_JANSSON
compose_json_str(void * obj)1941 char *compose_json_str(void *obj)
1942 {
1943 char *tmpbuf = NULL;
1944
1945 tmpbuf = json_dumps(obj, JSON_PRESERVE_ORDER);
1946 json_decref(obj);
1947
1948 return tmpbuf;
1949 }
1950
write_and_free_json(FILE * f,void * obj)1951 void write_and_free_json(FILE *f, void *obj)
1952 {
1953 char *tmpbuf = NULL;
1954 json_t *json_obj = (json_t *) obj;
1955
1956 if (!f) return;
1957
1958 /* Waiting for jansson issue #256 on GitHub to be solved,
1959 ie. introduction of trailing newline chars, in order to
1960 switch to json_dumpf() */
1961 tmpbuf = json_dumps(json_obj, JSON_PRESERVE_ORDER);
1962 json_decref(json_obj);
1963
1964 if (tmpbuf) {
1965 fprintf(f, "%s\n", tmpbuf);
1966 free(tmpbuf);
1967 }
1968 }
1969
add_writer_name_and_pid_json(void * obj,char * name,pid_t writer_pid)1970 void add_writer_name_and_pid_json(void *obj, char *name, pid_t writer_pid)
1971 {
1972 char wid[SHORTSHORTBUFLEN];
1973 json_t *json_obj = (json_t *) obj;
1974
1975 snprintf(wid, SHORTSHORTBUFLEN, "%s/%u", name, writer_pid);
1976 json_object_set_new_nocheck(json_obj, "writer_id", json_string(wid));
1977 }
1978 #else
compose_json_str(void * obj)1979 char *compose_json_str(void *obj)
1980 {
1981 if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): compose_json_str(): JSON object not created due to missing --enable-jansson\n", config.name, config.type);
1982
1983 return NULL;
1984 }
1985
write_and_free_json(FILE * f,void * obj)1986 void write_and_free_json(FILE *f, void *obj)
1987 {
1988 if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): write_and_free_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type);
1989 }
1990
add_writer_name_and_pid_json(void * obj,char * name,pid_t writer_pid)1991 void add_writer_name_and_pid_json(void *obj, char *name, pid_t writer_pid)
1992 {
1993 if (config.debug) Log(LOG_DEBUG, "DEBUG ( %s/%s ): add_writer_name_and_pid_json(): JSON object not created due to missing --enable-jansson\n", config.name, config.type);
1994 }
1995 #endif
1996
write_file_binary(FILE * f,void * obj,size_t len)1997 void write_file_binary(FILE *f, void *obj, size_t len)
1998 {
1999 if (!f) return;
2000
2001 if (obj && len) fwrite(obj, len, 1, f);
2002 }
2003
compose_timestamp(char * buf,int buflen,struct timeval * tv,int usec,int since_epoch,int rfc3339,int utc)2004 void compose_timestamp(char *buf, int buflen, struct timeval *tv, int usec, int since_epoch, int rfc3339, int utc)
2005 {
2006 int slen;
2007 time_t time1;
2008 struct tm *time2;
2009
2010 if (buflen < VERYSHORTBUFLEN) return;
2011
2012 if (since_epoch) {
2013 if (usec) snprintf(buf, buflen, "%ld.%.6ld", (long)tv->tv_sec, (long)tv->tv_usec);
2014 else snprintf(buf, buflen, "%ld", (long)tv->tv_sec);
2015 }
2016 else {
2017 time1 = tv->tv_sec;
2018 if (!utc) time2 = localtime(&time1);
2019 else time2 = gmtime(&time1);
2020
2021 if (!rfc3339) slen = strftime(buf, buflen, "%Y-%m-%d %H:%M:%S", time2);
2022 else slen = strftime(buf, buflen, "%Y-%m-%dT%H:%M:%S", time2);
2023
2024 if (usec) snprintf((buf + slen), (buflen - slen), ".%.6ld", (long)tv->tv_usec);
2025 if (rfc3339) append_rfc3339_timezone(buf, buflen, time2);
2026 }
2027 }
2028
print_primitives(int acct_type,char * header)2029 void print_primitives(int acct_type, char *header)
2030 {
2031 int idx;
2032
2033 printf("%s %s (%s)\n", header, PMACCT_VERSION, PMACCT_BUILD);
2034
2035 for (idx = 0; strcmp(_primitives_matrix[idx].name, ""); idx++) {
2036 if ((acct_type == ACCT_NF && _primitives_matrix[idx].nfacctd) ||
2037 (acct_type == ACCT_SF && _primitives_matrix[idx].sfacctd) ||
2038 (acct_type == ACCT_PM && _primitives_matrix[idx].pmacctd)) {
2039 if (strcmp(_primitives_matrix[idx].desc, "")) /* entry */
2040 printf("%-32s : %-64s\n", _primitives_matrix[idx].name, _primitives_matrix[idx].desc);
2041 else /* title */
2042 printf("\n%s\n", _primitives_matrix[idx].name);
2043 }
2044 }
2045 }
2046
set_primptrs_funcs(struct extra_primitives * extras)2047 void set_primptrs_funcs(struct extra_primitives *extras)
2048 {
2049 int idx = 0;
2050
2051 memset(primptrs_funcs, 0, sizeof(primptrs_funcs));
2052
2053 if (extras->off_pkt_bgp_primitives) {
2054 primptrs_funcs[idx] = primptrs_set_bgp;
2055 idx++;
2056 }
2057
2058 if (extras->off_pkt_lbgp_primitives) {
2059 primptrs_funcs[idx] = primptrs_set_lbgp;
2060 idx++;
2061 }
2062
2063 if (extras->off_pkt_nat_primitives) {
2064 primptrs_funcs[idx] = primptrs_set_nat;
2065 idx++;
2066 }
2067
2068 if (extras->off_pkt_mpls_primitives) {
2069 primptrs_funcs[idx] = primptrs_set_mpls;
2070 idx++;
2071 }
2072
2073 if (extras->off_pkt_tun_primitives) {
2074 primptrs_funcs[idx] = primptrs_set_tun;
2075 idx++;
2076 }
2077
2078 if (extras->off_custom_primitives) {
2079 primptrs_funcs[idx] = primptrs_set_custom;
2080 idx++;
2081 }
2082
2083 if (extras->off_pkt_extras) {
2084 primptrs_funcs[idx] = primptrs_set_extras;
2085 idx++;
2086 }
2087
2088 if (extras->off_pkt_vlen_hdr_primitives) {
2089 primptrs_funcs[idx] = primptrs_set_vlen_hdr;
2090 idx++;
2091 }
2092 }
2093
primptrs_set_bgp(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2094 void primptrs_set_bgp(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2095 {
2096 prim_ptrs->pbgp = (struct pkt_bgp_primitives *) (base + extras->off_pkt_bgp_primitives);
2097 prim_ptrs->vlen_next_off = 0;
2098 }
2099
primptrs_set_lbgp(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2100 void primptrs_set_lbgp(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2101 {
2102 prim_ptrs->plbgp = (struct pkt_legacy_bgp_primitives *) (base + extras->off_pkt_lbgp_primitives);
2103 prim_ptrs->vlen_next_off = 0;
2104 }
2105
primptrs_set_nat(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2106 void primptrs_set_nat(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2107 {
2108 prim_ptrs->pnat = (struct pkt_nat_primitives *) (base + extras->off_pkt_nat_primitives);
2109 prim_ptrs->vlen_next_off = 0;
2110 }
2111
primptrs_set_mpls(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2112 void primptrs_set_mpls(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2113 {
2114 prim_ptrs->pmpls = (struct pkt_mpls_primitives *) (base + extras->off_pkt_mpls_primitives);
2115 prim_ptrs->vlen_next_off = 0;
2116 }
2117
primptrs_set_tun(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2118 void primptrs_set_tun(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2119 {
2120 prim_ptrs->ptun = (struct pkt_tunnel_primitives *) (base + extras->off_pkt_tun_primitives);
2121 prim_ptrs->vlen_next_off = 0;
2122 }
2123
primptrs_set_custom(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2124 void primptrs_set_custom(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2125 {
2126 prim_ptrs->pcust = (base + extras->off_custom_primitives);
2127 prim_ptrs->vlen_next_off = 0;
2128 }
2129
primptrs_set_extras(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2130 void primptrs_set_extras(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2131 {
2132 prim_ptrs->pextras = (struct pkt_extras *) (base + extras->off_pkt_extras);
2133 prim_ptrs->vlen_next_off = 0;
2134 }
2135
primptrs_set_vlen_hdr(u_char * base,struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs)2136 void primptrs_set_vlen_hdr(u_char *base, struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs)
2137 {
2138 prim_ptrs->pvlen = (struct pkt_vlen_hdr_primitives *) (base + extras->off_pkt_vlen_hdr_primitives);
2139 prim_ptrs->vlen_next_off = extras->off_pkt_vlen_hdr_primitives + PvhdrSz + prim_ptrs->pvlen->tot_len;
2140 }
2141
custom_primitives_vlen(struct custom_primitives_ptrs * cpptrs)2142 int custom_primitives_vlen(struct custom_primitives_ptrs *cpptrs)
2143 {
2144 int cpptrs_idx, vlen_prims = 0;
2145 struct custom_primitive_entry *cpe;
2146
2147 for (cpptrs_idx = 0; cpptrs->primitive[cpptrs_idx].name && cpptrs_idx < cpptrs->num; cpptrs_idx++) {
2148 cpe = cpptrs->primitive[cpptrs_idx].ptr;
2149 if (cpe->len == PM_VARIABLE_LENGTH) vlen_prims++;
2150 }
2151
2152 return vlen_prims;
2153 }
2154
custom_primitives_reconcile(struct custom_primitives_ptrs * cpptrs,struct custom_primitives * registry)2155 void custom_primitives_reconcile(struct custom_primitives_ptrs *cpptrs, struct custom_primitives *registry)
2156 {
2157 int cpptrs_idx, registry_idx;
2158 int pad = 0;
2159
2160 /* first pass: linking */
2161 for (cpptrs_idx = 0; cpptrs->primitive[cpptrs_idx].name && cpptrs_idx < cpptrs->num; cpptrs_idx++) {
2162 for (registry_idx = 0; registry->primitive[registry_idx].len && registry_idx < registry->num; registry_idx++) {
2163 if (!strcmp(cpptrs->primitive[cpptrs_idx].name, registry->primitive[registry_idx].name)) {
2164 if (registry->primitive[registry_idx].len == PM_VARIABLE_LENGTH) {
2165 cpptrs->primitive[cpptrs_idx].ptr = ®istry->primitive[registry_idx];
2166 cpptrs->primitive[cpptrs_idx].off = PM_VARIABLE_LENGTH;
2167 }
2168 else if (cpptrs->len + registry->primitive[registry_idx].len < UINT16_MAX) {
2169 cpptrs->primitive[cpptrs_idx].ptr = ®istry->primitive[registry_idx];
2170 cpptrs->primitive[cpptrs_idx].off = cpptrs->len;
2171 cpptrs->len += registry->primitive[registry_idx].alloc_len;
2172 }
2173 else {
2174 Log(LOG_WARNING, "WARN ( %s/%s ): Max allocatable space for custom primitives finished (%s).\n",
2175 config.name, config.type, cpptrs->primitive[cpptrs_idx].name);
2176 cpptrs->primitive[cpptrs_idx].ptr = NULL;
2177 }
2178
2179 break;
2180 }
2181 }
2182 }
2183
2184 /* second pass: verification and finish-off */
2185 for (cpptrs_idx = 0; cpptrs->primitive[cpptrs_idx].name && cpptrs_idx < cpptrs->num; cpptrs_idx++) {
2186 if (!cpptrs->primitive[cpptrs_idx].ptr) {
2187 Log(LOG_ERR, "ERROR ( %s/%s ): Unknown primitive '%s'\n", config.name, config.type, cpptrs->primitive[cpptrs_idx].name);
2188 exit_gracefully(1);
2189 }
2190 else {
2191 struct custom_primitive_entry *cpe = cpptrs->primitive[cpptrs_idx].ptr;
2192
2193 if (cpptrs->primitive[cpptrs_idx].off != PM_VARIABLE_LENGTH) {
2194 Log(LOG_DEBUG, "DEBUG ( %s/%s ): Custom primitive '%s': type=%" PRIx64 " off=%u len=%u\n", config.name, config.type,
2195 cpptrs->primitive[cpptrs_idx].name, cpe->type, cpptrs->primitive[cpptrs_idx].off, cpe->len);
2196 }
2197 else {
2198 Log(LOG_DEBUG, "DEBUG ( %s/%s ): Custom primitive '%s': type=%" PRIx64 " len=vlen\n", config.name, config.type,
2199 cpptrs->primitive[cpptrs_idx].name, cpe->type);
2200 }
2201 }
2202 }
2203
2204 if (cpptrs->len) pad = 8 - (cpptrs->len % 8);
2205 cpptrs->len += pad; /* padding to a safe 64-bit boundary */
2206 }
2207
custom_primitive_header_print(char * out,int outlen,struct custom_primitive_ptrs * cp_entry,int formatted)2208 void custom_primitive_header_print(char *out, int outlen, struct custom_primitive_ptrs *cp_entry, int formatted)
2209 {
2210 char format[VERYSHORTBUFLEN];
2211
2212 if (out && cp_entry) {
2213 memset(out, 0, outlen);
2214
2215 if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_UINT ||
2216 cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_HEX) {
2217 if (formatted) {
2218 snprintf(format, VERYSHORTBUFLEN, "%%-%d", cps_flen[cp_entry->ptr->len] > strlen(cp_entry->ptr->name) ? cps_flen[cp_entry->ptr->len] : (int)strlen(cp_entry->ptr->name));
2219 strncat(format, "s", VERYSHORTBUFLEN - 1);
2220 }
2221 else snprintf(format, VERYSHORTBUFLEN, "%s", "%s");
2222 }
2223 else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_STRING ||
2224 cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) {
2225 if (formatted) {
2226 snprintf(format, VERYSHORTBUFLEN, "%%-%d", cp_entry->ptr->len > strlen(cp_entry->ptr->name) ? cp_entry->ptr->len : (int)strlen(cp_entry->ptr->name));
2227 strncat(format, "s", VERYSHORTBUFLEN - 1);
2228 }
2229 else snprintf(format, VERYSHORTBUFLEN, "%s", "%s");
2230 }
2231 else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_IP) {
2232 int len = 0;
2233
2234 len = INET6_ADDRSTRLEN;
2235
2236 if (formatted) {
2237 snprintf(format, VERYSHORTBUFLEN, "%%-%d", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name));
2238 strncat(format, "s", VERYSHORTBUFLEN - 1);
2239 }
2240 else snprintf(format, VERYSHORTBUFLEN, "%s", "%s");
2241 }
2242 else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_MAC) {
2243 int len = ETHER_ADDRSTRLEN;
2244
2245 if (formatted) {
2246 snprintf(format, VERYSHORTBUFLEN, "%%-%d", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name));
2247 strncat(format, "s", VERYSHORTBUFLEN - 1);
2248 }
2249 else snprintf(format, VERYSHORTBUFLEN, "%s", "%s");
2250 }
2251
2252 snprintf(out, outlen, format, cp_entry->ptr->name);
2253 }
2254 }
2255
custom_primitive_value_print(char * out,int outlen,u_char * in,struct custom_primitive_ptrs * cp_entry,int formatted)2256 void custom_primitive_value_print(char *out, int outlen, u_char *in, struct custom_primitive_ptrs *cp_entry, int formatted)
2257 {
2258 char format[SHORTBUFLEN];
2259
2260 if (in && out && cp_entry) {
2261 memset(out, 0, outlen);
2262
2263 if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_UINT ||
2264 cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_HEX) {
2265 char double_fmt[] = "ll", semantics[VERYSHORTBUFLEN];
2266
2267 if (cp_entry->ptr->len == 8)
2268 snprintf(semantics, VERYSHORTBUFLEN, "%s%s", double_fmt, cps_type[cp_entry->ptr->semantics]);
2269 else /* XXX: limit to 1, 2 and 4 bytes lengths? */
2270 snprintf(semantics, VERYSHORTBUFLEN, "%s", cps_type[cp_entry->ptr->semantics]);
2271
2272 if (formatted)
2273 snprintf(format, SHORTBUFLEN, "%%-%d%s",
2274 cps_flen[cp_entry->ptr->len] > strlen(cp_entry->ptr->name) ? cps_flen[cp_entry->ptr->len] : (int)strlen(cp_entry->ptr->name),
2275 semantics);
2276 else
2277 snprintf(format, SHORTBUFLEN, "%%%s", semantics);
2278
2279 if (cp_entry->ptr->len == 1) {
2280 u_int8_t t8;
2281
2282 memcpy(&t8, (in+cp_entry->off), 1);
2283 snprintf(out, outlen, format, t8);
2284 }
2285 else if (cp_entry->ptr->len == 2) {
2286 u_int16_t t16, st16;
2287
2288 memcpy(&t16, (in+cp_entry->off), 2);
2289 st16 = ntohs(t16);
2290 snprintf(out, outlen, format, st16);
2291 }
2292 else if (cp_entry->ptr->len == 4) {
2293 u_int32_t t32, st32;
2294
2295 memcpy(&t32, (in+cp_entry->off), 4);
2296 st32 = ntohl(t32);
2297 snprintf(out, outlen, format, st32);
2298 }
2299 else if (cp_entry->ptr->len == 8) {
2300 u_int64_t t64, st64;
2301
2302 memcpy(&t64, (in+cp_entry->off), 8);
2303 st64 = pm_ntohll(t64);
2304 snprintf(out, outlen, format, st64);
2305 }
2306 }
2307 else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_STRING ||
2308 cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_RAW) {
2309 if (formatted)
2310 snprintf(format, VERYSHORTBUFLEN, "%%-%d%s", cp_entry->ptr->len > strlen(cp_entry->ptr->name) ? cp_entry->ptr->len : (int)strlen(cp_entry->ptr->name),
2311 cps_type[cp_entry->ptr->semantics]);
2312 else
2313 snprintf(format, VERYSHORTBUFLEN, "%%%s", cps_type[cp_entry->ptr->semantics]);
2314
2315 snprintf(out, outlen, format, (in+cp_entry->off));
2316 }
2317 else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_IP) {
2318 struct host_addr ip_addr;
2319 char ip_str[INET6_ADDRSTRLEN];
2320 int len = 0;
2321
2322 memset(&ip_addr, 0, sizeof(ip_addr));
2323 memset(ip_str, 0, sizeof(ip_str));
2324
2325 len = INET6_ADDRSTRLEN;
2326
2327 if (cp_entry->ptr->len == 4) {
2328 ip_addr.family = AF_INET;
2329 memcpy(&ip_addr.address.ipv4, in+cp_entry->off, 4);
2330 }
2331 else if (cp_entry->ptr->len == 16) {
2332 ip_addr.family = AF_INET6;
2333 memcpy(&ip_addr.address.ipv6, in+cp_entry->off, 16);
2334 }
2335
2336 addr_to_str(ip_str, &ip_addr);
2337 if (formatted)
2338 snprintf(format, VERYSHORTBUFLEN, "%%-%d%s", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name),
2339 cps_type[cp_entry->ptr->semantics]);
2340 else
2341 snprintf(format, VERYSHORTBUFLEN, "%%%s", cps_type[cp_entry->ptr->semantics]);
2342
2343 snprintf(out, outlen, format, ip_str);
2344 }
2345 else if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_MAC) {
2346 char eth_str[ETHER_ADDRSTRLEN];
2347 int len = ETHER_ADDRSTRLEN;
2348
2349 memset(eth_str, 0, sizeof(eth_str));
2350 etheraddr_string((u_char *)(in + cp_entry->off), eth_str);
2351
2352 if (formatted)
2353 snprintf(format, VERYSHORTBUFLEN, "%%-%d%s", len > strlen(cp_entry->ptr->name) ? len : (int)strlen(cp_entry->ptr->name),
2354 cps_type[cp_entry->ptr->semantics]);
2355 else
2356 snprintf(format, VERYSHORTBUFLEN, "%%%s", cps_type[cp_entry->ptr->semantics]);
2357
2358 snprintf(out, outlen, format, eth_str);
2359 }
2360 }
2361 }
2362
custom_primitives_debug(void * pcust,void * pvlen)2363 void custom_primitives_debug(void *pcust, void *pvlen)
2364 {
2365 char empty_string[] = "";
2366 int cp_idx;
2367
2368 if (!pcust) return;
2369
2370 for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) {
2371 char cph_str[SRVBUFLEN];
2372
2373 custom_primitive_header_print(cph_str, SRVBUFLEN, &config.cpptrs.primitive[cp_idx], TRUE);
2374
2375 if (config.cpptrs.primitive[cp_idx].ptr->len != PM_VARIABLE_LENGTH) {
2376 char cpv_str[SRVBUFLEN];
2377
2378 custom_primitive_value_print(cpv_str, SRVBUFLEN, pcust, &config.cpptrs.primitive[cp_idx], TRUE);
2379
2380 Log(LOG_DEBUG, "DEBUG ( %s/%s ): custom_primitive_value_debug(): PCUST ARRAY: name=%s value=%s\n",
2381 config.name, config.type, cph_str, cpv_str);
2382 }
2383 else {
2384 if (pvlen) {
2385 /* vlen primitives not supported in formatted outputs: we should never get here */
2386 char *label_ptr = NULL;
2387
2388 vlen_prims_get(pvlen, config.cpptrs.primitive[cp_idx].ptr->type, &label_ptr);
2389 if (!label_ptr) label_ptr = empty_string;
2390
2391 Log(LOG_DEBUG, "DEBUG ( %s/%s ): custom_primitive_value_debug(): PCUST ARRAY: name=%s value=%s\n",
2392 config.name, config.type, cph_str, label_ptr);
2393 }
2394 }
2395 }
2396 }
2397
mkdir_multilevel(const char * path,int trailing_filename,uid_t owner,gid_t group)2398 int mkdir_multilevel(const char *path, int trailing_filename, uid_t owner, gid_t group)
2399 {
2400 char opath[SRVBUFLEN];
2401 char *p;
2402 int ret = 0, len = 0;
2403
2404 strlcpy(opath, path, sizeof(opath));
2405
2406 for (p = opath; *p; p++, len++) {
2407 if (*p == '/') {
2408 *p = '\0';
2409 if (len && access(opath, F_OK)) {
2410 ret = mkdir(opath, (S_IRWXU|S_IRWXG|S_IRWXO));
2411 if (ret) return ret;
2412 if (chown(opath, owner, group) == -1) return ret;
2413 }
2414 *p = '/';
2415 }
2416 }
2417
2418 /* do a last mkdir in case the path was not terminated
2419 by a traiing '/' and we do not expect the last part
2420 to be a filename, ie. trailing_filename set to 0 */
2421 if (!trailing_filename && access(opath, F_OK)) {
2422 ret = mkdir(opath, (S_IRWXU|S_IRWXG|S_IRWXO));
2423 if (ret) return ret;
2424 }
2425
2426 return ret;
2427 }
2428
bin_to_hex(int nib)2429 char bin_to_hex(int nib)
2430 {
2431 return (nib < 10) ? ('0' + nib) : ('A' - 10 + nib);
2432 }
2433
hex_to_bin(int a)2434 int hex_to_bin(int a)
2435 {
2436 if (a >= '0' && a <= '9')
2437 return a - '0';
2438 else if (a >= 'a' && a <= 'f')
2439 return a - 'a' + 10;
2440 else if (a >= 'A' && a <= 'F')
2441 return a - 'A' + 10;
2442
2443 return ERR;
2444 }
2445
serialize_hex(const u_char * a,u_char * buf,int len)2446 int serialize_hex(const u_char *a, u_char *buf, int len)
2447 {
2448 int b = 0, i = 0;
2449
2450 for (; i < len; i++) {
2451 u_char byte;
2452
2453 byte = a[i];
2454 buf[b++] = bin_to_hex(byte >> 4);
2455 buf[b++] = bin_to_hex(byte & 0x0f);
2456
2457 // separate the bytes with a dash
2458 if (i < (len - 1)) buf[b++] = '-';
2459 }
2460
2461 if (buf[b-1] == '-') {
2462 buf[b-1] = '\0';
2463 return b;
2464 }
2465 else {
2466 buf[b] = '\0';
2467 return (b+1);
2468 }
2469 }
2470
serialize_bin(const u_char * hex,u_char * bin,int len)2471 int serialize_bin(const u_char *hex, u_char *bin, int len)
2472 {
2473 int i = 0;
2474
2475 for (; i < len; i++) {
2476 if (hex[0] == '-') {
2477 hex++;
2478 continue;
2479 }
2480
2481 *bin++ = hex_to_bin(hex[0]) * 16 + hex_to_bin(hex[1]);
2482 hex += 2;
2483 }
2484
2485 return i;
2486 }
2487
vlen_prims_copy(struct pkt_vlen_hdr_primitives * src)2488 unsigned char *vlen_prims_copy(struct pkt_vlen_hdr_primitives *src)
2489 {
2490 unsigned char *dst = NULL;
2491 int len = 0;
2492
2493 if (!src) return NULL;
2494
2495 len = PvhdrSz + src->tot_len;
2496 dst = malloc(len);
2497
2498 if (dst) {
2499 vlen_prims_init((struct pkt_vlen_hdr_primitives *) dst, src->tot_len);
2500 memcpy(dst, src, len);
2501 }
2502
2503 return dst;
2504 }
2505
vlen_prims_init(struct pkt_vlen_hdr_primitives * hdr,int add_len)2506 void vlen_prims_init(struct pkt_vlen_hdr_primitives *hdr, int add_len)
2507 {
2508 if (!hdr) return;
2509
2510 memset(hdr, 0, PvhdrSz + add_len);
2511 }
2512
vlen_prims_free(struct pkt_vlen_hdr_primitives * hdr)2513 void vlen_prims_free(struct pkt_vlen_hdr_primitives *hdr)
2514 {
2515 if (!hdr) return;
2516
2517 free(hdr);
2518 }
2519
vlen_prims_cmp(struct pkt_vlen_hdr_primitives * src,struct pkt_vlen_hdr_primitives * dst)2520 int vlen_prims_cmp(struct pkt_vlen_hdr_primitives *src, struct pkt_vlen_hdr_primitives *dst)
2521 {
2522 if (!src || !dst) return ERR;
2523
2524 if (src->tot_len != dst->tot_len) return (src->tot_len - dst->tot_len);
2525
2526 return memcmp(src, dst, (src->tot_len + PvhdrSz));
2527 }
2528
vlen_prims_get(struct pkt_vlen_hdr_primitives * hdr,pm_cfgreg_t wtc,char ** res)2529 void vlen_prims_get(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc, char **res)
2530 {
2531 pm_label_t *label_ptr;
2532 char *ptr = (char *) hdr;
2533 int x, rlen;
2534
2535 if (res) *res = NULL;
2536
2537 if (!hdr || !wtc || !res) return;
2538
2539 ptr += PvhdrSz;
2540 label_ptr = (pm_label_t *) ptr;
2541
2542 for (x = 0, rlen = 0; x < hdr->num && rlen < hdr->tot_len; x++) {
2543 if (label_ptr->type == wtc) {
2544 if (label_ptr->len) {
2545 ptr += PmLabelTSz;
2546 *res = ptr;
2547 }
2548
2549 return;
2550 }
2551 else {
2552 ptr += (PmLabelTSz + label_ptr->len);
2553 rlen += (PmLabelTSz + label_ptr->len);
2554 label_ptr = (pm_label_t *) ptr;
2555 }
2556 }
2557 }
2558
vlen_prims_debug(struct pkt_vlen_hdr_primitives * hdr)2559 void vlen_prims_debug(struct pkt_vlen_hdr_primitives *hdr)
2560 {
2561 pm_label_t *label_ptr;
2562 char *ptr = (char *) hdr;
2563 int x = 0;
2564
2565 Log(LOG_DEBUG, "DEBUG ( %s/%s ): vlen_prims_debug(): VLEN ARRAY: num: %u tot_len: %u\n",
2566 config.name, config.type, hdr->num, hdr->tot_len);
2567 ptr += PvhdrSz;
2568
2569 for (x = 0; x < hdr->num; x++) {
2570 label_ptr = (pm_label_t *) ptr;
2571 ptr += PmLabelTSz;
2572
2573 Log(LOG_DEBUG, "DEBUG ( %s/%s ): vlen_prims_debug(): LABEL #%u: type: %" PRIx64 " len: %u val: %s\n",
2574 config.name, config.type, x, label_ptr->type, label_ptr->len, ptr);
2575 }
2576 }
2577
vlen_prims_insert(struct pkt_vlen_hdr_primitives * hdr,pm_cfgreg_t wtc,int len,u_char * val,int copy_type)2578 void vlen_prims_insert(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc, int len, u_char *val, int copy_type /*, optional realloc */)
2579 {
2580 pm_label_t *label_ptr;
2581 char *ptr = (char *) hdr;
2582
2583 ptr += (PvhdrSz + hdr->tot_len);
2584 label_ptr = (pm_label_t *) ptr;
2585 label_ptr->type = wtc;
2586 label_ptr->len = len;
2587
2588 ptr += PmLabelTSz;
2589
2590 if (len) {
2591 switch (copy_type) {
2592 case PM_MSG_BIN_COPY:
2593 memcpy(ptr, val, len);
2594 break;
2595 case PM_MSG_STR_COPY:
2596 strncpy(ptr, (char *)val, len);
2597 break;
2598 case PM_MSG_STR_COPY_ZERO:
2599 label_ptr->len++; /* terminating zero */
2600 strncpy(ptr, (char *)val, len);
2601 ptr[len] = '\0';
2602 break;
2603 default:
2604 break;
2605 }
2606 }
2607
2608 hdr->num++;
2609 hdr->tot_len += (PmLabelTSz + label_ptr->len);
2610 }
2611
vlen_prims_delete(struct pkt_vlen_hdr_primitives * hdr,pm_cfgreg_t wtc)2612 int vlen_prims_delete(struct pkt_vlen_hdr_primitives *hdr, pm_cfgreg_t wtc /*, optional realloc */)
2613 {
2614 pm_label_t *label_ptr;
2615 char *ptr = (char *) hdr;
2616 int x = 0, ret = 0, jump = 0, off = 0;
2617
2618 ptr += PvhdrSz;
2619 off += PvhdrSz;
2620
2621 for (x = 0; x < hdr->num; x++) {
2622 label_ptr = (pm_label_t *) ptr;
2623
2624 if (label_ptr->type == wtc) {
2625 char *new_ptr = ptr;
2626
2627 jump = label_ptr->len;
2628 new_ptr += (PmLabelTSz + jump);
2629 off += (PmLabelTSz + jump);
2630 memset(ptr, 0, PmLabelTSz + jump);
2631
2632 if (x + 1 < hdr->num) memcpy(ptr, new_ptr, hdr->tot_len - off);
2633
2634 hdr->num--;
2635 hdr->tot_len -= (PmLabelTSz + jump);
2636 /* XXX: optional realloc() */
2637
2638 ret = (PmLabelTSz + jump);
2639 break;
2640 }
2641 else {
2642 ptr += (PmLabelTSz + label_ptr->len);
2643 off += (PmLabelTSz + label_ptr->len);
2644 }
2645 }
2646
2647 return ret;
2648 }
2649
delete_line_from_file(int index,char * path)2650 int delete_line_from_file(int index, char *path)
2651 {
2652 int len = strlen(path) + 5;
2653 int line_idx;
2654 char tmpbuf[LARGEBUFLEN];
2655 char *copy_path;
2656 FILE *file = fopen(path, "r+");
2657 FILE *file_copy;
2658
2659 copy_path = malloc(len);
2660 memset(copy_path, 0, len);
2661
2662 strcpy(copy_path, path);
2663 strcat(copy_path, ".copy");
2664 file_copy = fopen(copy_path, "w");
2665
2666 if (file == NULL) {
2667 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] file not found.\n", config.name, config.type, path);
2668 return -1;
2669 }
2670
2671 if (file_lock(fileno(file))) {
2672 Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, config.type, path);
2673 return -1;
2674 }
2675
2676 line_idx = 0;
2677 while (fgets(tmpbuf, LARGEBUFLEN, file)) {
2678 if (line_idx != index)
2679 fwrite(tmpbuf, 1, strlen(tmpbuf), file_copy);
2680
2681 line_idx++;
2682 }
2683
2684 fclose(file);
2685 unlink(path);
2686 fclose(file_copy);
2687 rename(copy_path, path);
2688
2689 file_unlock(fileno(file));
2690 free(copy_path);
2691 return 0;
2692 }
2693
set_truefalse_nonzero(int * value)2694 void set_truefalse_nonzero(int *value)
2695 {
2696 if (!value) return;
2697
2698 if (!(*value)) (*value) = TRUE;
2699 else if ((*value) == FALSE_NONZERO) (*value) = FALSE;
2700 }
2701
hash_init_key(pm_hash_key_t * key)2702 void hash_init_key(pm_hash_key_t *key)
2703 {
2704 if (!key) return;
2705
2706 memset(key->val, 0, key->len);
2707 }
2708
hash_alloc_key(pm_hash_key_t * key,u_int16_t key_len)2709 int hash_alloc_key(pm_hash_key_t *key, u_int16_t key_len)
2710 {
2711 if (!key || !key_len) return ERR;
2712
2713 if (!key->val) {
2714 key->val = malloc(key_len);
2715 if (key->val) {
2716 key->len = key_len;
2717 hash_init_key(key);
2718 }
2719 else return ERR;
2720 }
2721 else {
2722 key->val = realloc(key->val, key_len);
2723 if (key->val) key->len = key_len;
2724 else return ERR;
2725 }
2726
2727 return SUCCESS;
2728 }
2729
hash_dup_key(pm_hash_key_t * dst,pm_hash_key_t * src)2730 int hash_dup_key(pm_hash_key_t *dst, pm_hash_key_t *src)
2731 {
2732 if (!src || !dst) return ERR;
2733
2734 if (hash_alloc_key(dst, src->len) == ERR) return ERR;
2735
2736 memcpy(dst->val, src->val, src->len);
2737
2738 return SUCCESS;
2739 }
2740
hash_destroy_key(pm_hash_key_t * key)2741 void hash_destroy_key(pm_hash_key_t *key)
2742 {
2743 if (!key) return;
2744
2745 free(key->val);
2746 memset(key, 0, sizeof(pm_hash_key_t));
2747 }
2748
hash_init_serial(pm_hash_serial_t * serial,u_int16_t key_len)2749 int hash_init_serial(pm_hash_serial_t *serial, u_int16_t key_len)
2750 {
2751 if (!serial || !key_len) return ERR;
2752
2753 memset(serial, 0, sizeof(pm_hash_serial_t));
2754
2755 return hash_alloc_key(&serial->key, key_len);
2756 }
2757
hash_destroy_serial(pm_hash_serial_t * serial)2758 void hash_destroy_serial(pm_hash_serial_t *serial)
2759 {
2760 if (!serial) return;
2761
2762 hash_destroy_key(&serial->key);
2763 memset(serial, 0, sizeof(pm_hash_serial_t));
2764 }
2765
hash_serial_set_off(pm_hash_serial_t * serial,u_int16_t off)2766 void hash_serial_set_off(pm_hash_serial_t *serial, u_int16_t off)
2767 {
2768 if (!serial) return;
2769
2770 serial->off = off;
2771 }
2772
hash_serial_get_off(pm_hash_serial_t * serial)2773 u_int16_t hash_serial_get_off(pm_hash_serial_t *serial)
2774 {
2775 if (!serial) return ERR;
2776
2777 return serial->off;
2778 }
2779
hash_serial_get_key(pm_hash_serial_t * serial)2780 pm_hash_key_t *hash_serial_get_key(pm_hash_serial_t *serial)
2781 {
2782 if (!serial) return NULL;
2783
2784 return &serial->key;
2785 }
2786
hash_key_get_len(pm_hash_key_t * key)2787 u_int16_t hash_key_get_len(pm_hash_key_t *key)
2788 {
2789 if (!key) return ERR;
2790
2791 return key->len;
2792 }
2793
hash_key_get_val(pm_hash_key_t * key)2794 u_char *hash_key_get_val(pm_hash_key_t *key)
2795 {
2796 if (!key) return NULL;
2797
2798 return key->val;
2799 }
2800
hash_serial_append(pm_hash_serial_t * serial,char * val,u_int16_t len,int realloc)2801 void hash_serial_append(pm_hash_serial_t *serial, char *val, u_int16_t len, int realloc)
2802 {
2803 u_int16_t key_len, key_off, rem_len;
2804 int ret;
2805
2806 if (!serial || !val || !len) return;
2807
2808 key_len = hash_key_get_len(&serial->key);
2809 key_off = hash_serial_get_off(serial);
2810 rem_len = (key_len - key_off);
2811
2812 if (len > rem_len) {
2813 if (!realloc) return;
2814 else {
2815 ret = hash_alloc_key(&serial->key, (hash_key_get_len(&serial->key) + (len - rem_len)));
2816 if (ret == ERR) return;
2817 }
2818 }
2819
2820 memcpy((hash_key_get_val(&serial->key) + key_off), val, len);
2821 hash_serial_set_off(serial, (key_off + len));
2822 }
2823
hash_key_cmp(pm_hash_key_t * a,pm_hash_key_t * b)2824 int hash_key_cmp(pm_hash_key_t *a, pm_hash_key_t *b)
2825 {
2826 if (a->len != b->len) return (a->len - b->len);
2827
2828 return memcmp(a->val, b->val, b->len);
2829 }
2830
dump_writers_init()2831 void dump_writers_init()
2832 {
2833 dump_writers.active = 0;
2834 dump_writers.max = config.dump_max_writers;
2835 if (dump_writers.list) memset(dump_writers.list, 0, (dump_writers.max * sizeof(pid_t)));
2836 dump_writers.flags = FALSE;
2837 }
2838
dump_writers_count()2839 void dump_writers_count()
2840 {
2841 u_int16_t idx, count;
2842
2843 for (idx = 0, count = 0; idx < dump_writers.max; idx++) {
2844 if (dump_writers.list[idx]) {
2845 if (kill(dump_writers.list[idx], 0) != -1) count++;
2846 else dump_writers.list[idx] = 0;
2847 }
2848 }
2849
2850 dump_writers.active = count;
2851 if (dump_writers.active == dump_writers.max) dump_writers.flags = CHLD_ALERT;
2852 else dump_writers.flags = FALSE;
2853 }
2854
dump_writers_get_flags()2855 u_int32_t dump_writers_get_flags()
2856 {
2857 return dump_writers.flags;
2858 }
2859
dump_writers_get_active()2860 u_int16_t dump_writers_get_active()
2861 {
2862 return dump_writers.active;
2863 }
2864
dump_writers_get_max()2865 u_int16_t dump_writers_get_max()
2866 {
2867 return dump_writers.max;
2868 }
2869
dump_writers_add(pid_t pid)2870 int dump_writers_add(pid_t pid)
2871 {
2872 u_int16_t idx;
2873 int ret = FALSE;
2874
2875 if (dump_writers.flags != CHLD_ALERT) {
2876 for (idx = 0; idx < dump_writers.max; idx++) {
2877 if (!dump_writers.list[idx]) {
2878 dump_writers.list[idx] = pid;
2879 break;
2880 }
2881 }
2882
2883 ret = TRUE;
2884 }
2885
2886 return ret;
2887 }
2888
pm_scandir(const char * dir,struct dirent *** namelist,int (* select)(const struct dirent *),int (* compar)(const void *,const void *))2889 int pm_scandir(const char *dir, struct dirent ***namelist,
2890 int (*select)(const struct dirent *),
2891 int (*compar)(const void *, const void *))
2892 {
2893 DIR *d;
2894 struct dirent *entry;
2895 size_t entry_sz;
2896 int idx = 0;
2897
2898 *namelist = NULL;
2899
2900 if ((d = opendir(dir)) == NULL) return ERR;
2901
2902 while ((entry = readdir(d))) {
2903 if (!select || (select && (*select)(entry))) {
2904 *namelist = (struct dirent **) realloc((void *)(*namelist), (size_t)((idx + 1) * sizeof(struct dirent *)));
2905
2906 if (*namelist == NULL) {
2907 closedir(d);
2908 return ERR;
2909 }
2910
2911 entry_sz = sizeof(struct dirent) - sizeof(entry->d_name) + strlen(entry->d_name) + 1;
2912 (*namelist)[idx] = (struct dirent *) malloc(entry_sz);
2913
2914 if ((*namelist)[idx] == NULL) {
2915 closedir(d);
2916 return ERR;
2917 }
2918
2919 memcpy((*namelist)[idx], entry, entry_sz);
2920 idx++;
2921 }
2922 }
2923
2924 if (closedir(d)) return ERR;
2925 if (idx && (compar != NULL))
2926 qsort((void *)(*namelist), (size_t) idx, sizeof(struct dirent *), compar);
2927
2928 return idx;
2929 }
2930
pm_scandir_free(struct dirent *** namelist,int num)2931 void pm_scandir_free(struct dirent ***namelist, int num)
2932 {
2933 int idx;
2934
2935 if (*namelist) {
2936 for (idx = 0; idx < num; idx++) free((*namelist)[idx]);
2937
2938 free((*namelist));
2939 *namelist = NULL;
2940 }
2941 }
2942
pm_alphasort(const void * a,const void * b)2943 int pm_alphasort(const void *a, const void *b)
2944 {
2945 const struct dirent *dira = a;
2946 const struct dirent *dirb = b;
2947
2948 return(strcmp(dira->d_name, dirb->d_name));
2949 }
2950
generate_random_string(char * s,const int len)2951 void generate_random_string(char *s, const int len)
2952 {
2953 static const char alphanum[] =
2954 "0123456789"
2955 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2956 "abcdefghijklmnopqrstuvwxyz";
2957 int i;
2958
2959 for (i = 0; i < len; ++i) {
2960 s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
2961 }
2962
2963 s[len] = '\0';
2964 }
2965
pm_pcap_device_initialize(struct pm_pcap_devices * map)2966 void pm_pcap_device_initialize(struct pm_pcap_devices *map)
2967 {
2968 memset(map, 0, sizeof(struct pm_pcap_devices));
2969 }
2970
open_pcap_savefile(struct pm_pcap_device * dev_ptr,char * file)2971 void open_pcap_savefile(struct pm_pcap_device *dev_ptr, char *file)
2972 {
2973 char errbuf[PCAP_ERRBUF_SIZE];
2974 int idx;
2975
2976 if ((dev_ptr->dev_desc = pcap_open_offline(file, errbuf)) == NULL) {
2977 Log(LOG_ERR, "ERROR ( %s/core ): pcap_open_offline(): %s\n", config.name, errbuf);
2978 exit_gracefully(1);
2979 }
2980
2981 dev_ptr->link_type = pcap_datalink(dev_ptr->dev_desc);
2982 for (idx = 0; _devices[idx].link_type != -1; idx++) {
2983 if (dev_ptr->link_type == _devices[idx].link_type)
2984 dev_ptr->data = &_devices[idx];
2985 }
2986
2987 if (!dev_ptr->data || !dev_ptr->data->handler) {
2988 Log(LOG_ERR, "ERROR ( %s/core ): pcap_savefile: unsupported link layer.\n", config.name);
2989 exit_gracefully(1);
2990 }
2991
2992 dev_ptr->active = TRUE;
2993 }
2994
P_broker_timers_set_last_fail(struct p_broker_timers * btimers,time_t timestamp)2995 void P_broker_timers_set_last_fail(struct p_broker_timers *btimers, time_t timestamp)
2996 {
2997 if (btimers) btimers->last_fail = timestamp;
2998 }
2999
P_broker_timers_get_last_fail(struct p_broker_timers * btimers)3000 time_t P_broker_timers_get_last_fail(struct p_broker_timers *btimers)
3001 {
3002 if (btimers) return btimers->last_fail;
3003
3004 return FALSE;
3005 }
3006
P_broker_timers_unset_last_fail(struct p_broker_timers * btimers)3007 void P_broker_timers_unset_last_fail(struct p_broker_timers *btimers)
3008 {
3009 if (btimers) btimers->last_fail = FALSE;
3010 }
3011
P_broker_timers_set_retry_interval(struct p_broker_timers * btimers,int interval)3012 void P_broker_timers_set_retry_interval(struct p_broker_timers *btimers, int interval)
3013 {
3014 if (btimers) btimers->retry_interval = interval;
3015 }
3016
P_broker_timers_get_retry_interval(struct p_broker_timers * btimers)3017 int P_broker_timers_get_retry_interval(struct p_broker_timers *btimers)
3018 {
3019 if (btimers) return btimers->retry_interval;
3020
3021 return ERR;
3022 }
3023
ip_proto_print(u_int8_t ip_proto_id,char * str,int len)3024 char *ip_proto_print(u_int8_t ip_proto_id, char *str, int len)
3025 {
3026 char *ret = NULL;
3027
3028 if (!config.num_protos && (ip_proto_id < protocols_number)) {
3029 ret = (char *) _protocols[ip_proto_id].name;
3030 }
3031 else {
3032 snprintf(str, len, "%u", ip_proto_id);
3033 ret = str;
3034 }
3035
3036 return ret;
3037 }
3038
parse_hostport(const char * s,struct sockaddr * addr,socklen_t * len)3039 void parse_hostport(const char *s, struct sockaddr *addr, socklen_t *len)
3040 {
3041 char *orig, *host, *port;
3042 struct addrinfo hints, *res;
3043 int herr;
3044
3045 if ((host = orig = strdup(s)) == NULL) {
3046 Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), strdup() out of memory\n", config.name, config.type);
3047 exit_gracefully(1);
3048 }
3049
3050 trim_spaces(host);
3051 trim_spaces(orig);
3052
3053 if ((port = strrchr(host, ':')) == NULL || *(++port) == '\0' || *host == '\0') {
3054 Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), invalid '%s' argument\n", config.name, config.type, orig);
3055 exit_gracefully(1);
3056 }
3057 *(port - 1) = '\0';
3058
3059 /* Accept [host]:port for numeric IPv6 addresses */
3060 if (*host == '[' && *(port - 2) == ']') {
3061 host++;
3062 *(port - 2) = '\0';
3063 }
3064
3065 memset(&hints, '\0', sizeof(hints));
3066 hints.ai_socktype = SOCK_DGRAM;
3067
3068 if ((herr = getaddrinfo(host, port, &hints, &res)) == -1) {
3069 Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), address lookup failed\n", config.name, config.type);
3070 exit_gracefully(1);
3071 }
3072
3073 if (res == NULL || res->ai_addr == NULL) {
3074 Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), no addresses found for [%s]:%s\n", config.name, config.type, host, port);
3075 exit_gracefully(1);
3076 }
3077
3078 if (res->ai_addrlen > *len) {
3079 Log(LOG_ERR, "ERROR ( %s/%s ): parse_hostport(), address too long.\n", config.name, config.type);
3080 exit_gracefully(1);
3081 }
3082
3083 memcpy(addr, res->ai_addr, res->ai_addrlen);
3084 free(orig);
3085 *len = res->ai_addrlen;
3086 }
3087
is_prime(u_int32_t num)3088 bool is_prime(u_int32_t num)
3089 {
3090 int div = 6;
3091
3092 if (num == 2 || num == 3) return TRUE;
3093 if (num % 2 == 0 || num % 3 == 0) return FALSE;
3094
3095 while (div * div - 2 * div + 1 <= num) {
3096 if (num % (div - 1) == 0) return FALSE;
3097 if (num % (div + 1) == 0) return FALSE;
3098
3099 div += 6;
3100 }
3101
3102 return TRUE;
3103 }
3104
next_prime(u_int32_t num)3105 u_int32_t next_prime(u_int32_t num)
3106 {
3107 u_int32_t orig = num;
3108
3109 while (!is_prime(++num));
3110
3111 if (num < orig) return 0; /* it wrapped */
3112 else return num;
3113 }
3114
null_terminate(char * str,int len)3115 char *null_terminate(char *str, int len)
3116 {
3117 char *loc = NULL;
3118
3119 if (str[len - 1] == '\0') loc = strdup(str);
3120 else {
3121 loc = malloc(len + 1);
3122 memcpy(loc, str, len);
3123 loc[len] = '\0';
3124 }
3125
3126 return loc;
3127 }
3128
uint_print(void * value,int len,int flip)3129 char *uint_print(void *value, int len, int flip)
3130 {
3131 char *buf = NULL;
3132 ssize_t buflen = 0;
3133
3134 switch(len) {
3135 case 1:
3136 {
3137 u_int8_t *u8 = (u_int8_t *) value;
3138
3139 buflen = snprintf(NULL, 0, "%u", (*u8));
3140 buf = malloc(buflen + 1);
3141 snprintf(buf, (buflen + 1), "%u", (*u8));
3142 }
3143 break;
3144 case 2:
3145 {
3146 u_int16_t u16h, *u16 = (u_int16_t *) value;
3147
3148 if (flip) u16h = ntohs((*u16));
3149 else u16h = (*u16);
3150
3151 buflen = snprintf(NULL, 0, "%u", u16h);
3152 buf = malloc(buflen + 1);
3153 snprintf(buf, (buflen + 1), "%u", u16h);
3154 }
3155 break;
3156 case 4:
3157 {
3158 u_int32_t u32h, *u32 = (u_int32_t *) value;
3159
3160 if (flip) u32h = ntohl((*u32));
3161 else u32h = (*u32);
3162
3163 buflen = snprintf(NULL, 0, "%u", u32h);
3164 buf = malloc(buflen + 1);
3165 snprintf(buf, (buflen + 1), "%u", u32h);
3166 }
3167 break;
3168 case 8:
3169 {
3170 u_int64_t u64h, *u64 = (u_int64_t *) value;
3171
3172 if (flip) u64h = pm_ntohll((*u64));
3173 else u64h = (*u64);
3174
3175 buflen = snprintf(NULL, 0, "%"PRIu64, u64h);
3176 buf = malloc(buflen + 1);
3177 snprintf(buf, (buflen + 1), "%"PRIu64, u64h);
3178 }
3179 break;
3180 }
3181
3182 return buf;
3183 }
3184
reload_logs()3185 void reload_logs()
3186 {
3187 int logf;
3188
3189 if (config.syslog) {
3190 closelog();
3191 logf = parse_log_facility(config.syslog);
3192 if (logf == ERR) {
3193 config.syslog = NULL;
3194 Log(LOG_WARNING, "WARN ( %s/%s ): specified syslog facility is not supported; logging to console.\n", config.name, config.type);
3195 }
3196 openlog(NULL, LOG_PID, logf);
3197 Log(LOG_INFO, "INFO ( %s/%s ): Start logging ...\n", config.name, config.type);
3198 }
3199
3200 if (config.logfile) {
3201 fclose(config.logfile_fd);
3202 config.logfile_fd = open_output_file(config.logfile, "a", FALSE);
3203 }
3204 }
3205
is_empty_256b(void * area,int len)3206 int is_empty_256b(void *area, int len)
3207 {
3208 if (len <= SRVBUFLEN) {
3209 if (!memcmp(area, empty_mem_area_256b, len)) {
3210 return TRUE;
3211 }
3212 else {
3213 return FALSE;
3214 }
3215 }
3216
3217 return ERR;
3218 }
3219
pm_recv(int sockfd,void * buf,size_t len,int flags,unsigned int seconds)3220 ssize_t pm_recv(int sockfd, void *buf, size_t len, int flags, unsigned int seconds)
3221 {
3222 ssize_t ret;
3223
3224 if (flags == MSG_WAITALL) {
3225 alarm(seconds);
3226 }
3227
3228 ret = recv(sockfd, buf, len, flags);
3229
3230 alarm(0);
3231
3232 return ret;
3233 }
3234