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 = &registry->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 = &registry->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