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 #include "nfacctd.h"
26 #include "pretag_handlers.h"
27 #include "pretag-data.h"
28 #include "plugin_hooks.h"
29 #include "tee_plugin/tee_recvs.h"
30 #include "tee_plugin/tee_recvs-data.h"
31 #include "isis/isis.h"
32 #include "isis/isis-data.h"
33 #include "bgp/bgp_xcs.h"
34 #include "bgp/bgp_xcs-data.h"
35 #include "crc32.h"
36 #include "pmacct-data.h"
37 
38 //Global variables
39 int bpas_map_allocated;
40 int blp_map_allocated;
41 int bmed_map_allocated;
42 int biss_map_allocated;
43 int bta_map_allocated;
44 int bitr_map_allocated;
45 int sampling_map_allocated;
46 int custom_primitives_allocated;
47 
48 int bta_map_caching;
49 int sampling_map_caching;
50 
51 int (*find_id_func)(struct id_table *, struct packet_ptrs *, pm_id_t *, pm_id_t *);
52 
53 /*
54    XXX: load_id_file() interface cleanup pending:
55    - if a table is tag-related then it is passed as argument t
56    - else it is passed as argument req->key_value_table
57 */
load_id_file(int acct_type,char * filename,struct id_table * t,struct plugin_requests * req,int * map_allocated)58 void load_id_file(int acct_type, char *filename, struct id_table *t, struct plugin_requests *req, int *map_allocated)
59 {
60   struct id_table tmp;
61   struct id_entry *ptr, *ptr2;
62   FILE *file;
63   char *buf = NULL;
64   int v4_num = 0, x, tot_lines = 0, err, index, label_solved, sz;
65   int ignoring, map_entries, map_row_len;
66   struct stat st;
67   int v6_num = 0;
68 
69   if (!filename || !map_allocated) return;
70 
71   if (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM ||
72       acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_TO_XFLOW_AGENT ||
73       acct_type == MAP_BGP_SRC_LOCAL_PREF || acct_type == MAP_BGP_SRC_MED ||
74       acct_type == MAP_FLOW_TO_RD || acct_type == MAP_SAMPLING) {
75     req->key_value_table = (void *) &tmp;
76   }
77 
78   /* parsing engine vars */
79   char *start, *key = NULL, *value = NULL;
80   int len;
81 
82   Log(LOG_INFO, "INFO ( %s/%s ): [%s] (re)loading map.\n", config.name, config.type, filename);
83 
84   memset(&st, 0, sizeof(st));
85   memset(&tmp, 0, sizeof(struct id_table));
86 
87   if (req->map_entries) map_entries = req->map_entries;
88   else if (config.maps_entries) map_entries = config.maps_entries;
89   else map_entries = MAX_PRETAG_MAP_ENTRIES;
90 
91   if (req->map_row_len) map_row_len = req->map_row_len;
92   else if (config.maps_row_len) map_row_len = config.maps_row_len;
93   else {
94     if (acct_type == MAP_IGP) map_row_len = LARGEBUFLEN;
95     else map_row_len = SRVBUFLEN;
96   }
97 
98   buf = (char *) malloc(map_row_len);
99   if (!buf) {
100     Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed (readbuf: %u chars).\n", config.name, config.type, filename, map_row_len);
101     goto handle_error;
102   }
103   memset(buf, 0, map_row_len);
104 
105   if (filename) {
106     if ((file = fopen(filename, "r")) == NULL) {
107       Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file not found.\n", config.name, config.type, filename);
108       goto handle_error;
109     }
110 
111     sz = sizeof(struct id_entry)*map_entries;
112 
113     if (t) {
114       if (*map_allocated == 0) {
115         memset(t, 0, sizeof(struct id_table));
116         t->e = (struct id_entry *) malloc(sz);
117 	if (!t->e) {
118 	  Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed.\n", config.name, config.type, filename);
119 	  goto handle_error;
120 	}
121         *map_allocated = TRUE;
122       }
123       else {
124         ptr = t->e ;
125 
126 	/* freeing up resources before memset() */
127         if (config.maps_index && pretag_index_have_one(t)) {
128 	  pretag_index_destroy(t);
129 	}
130 	for (index = 0; index < t->num; index++) {
131 	  pcap_freecode(&t->e[index].key.filter);
132 	  pretag_free_label(&t->e[index].label);
133 	  if (t->e[index].jeq.label) free(t->e[index].jeq.label);
134 	}
135 
136         memset(t, 0, sizeof(struct id_table));
137         t->e = ptr ;
138       }
139     }
140     else {
141       *map_allocated = TRUE;
142     }
143 
144     tmp.e = (struct id_entry *) malloc(sz);
145     if (!tmp.e) {
146       Log(LOG_ERR, "ERROR ( %s/%s ): [%s] malloc() failed.\n", config.name, config.type, filename);
147       goto handle_error;
148     }
149 
150     memset(tmp.e, 0, sz);
151     if (t) memset(t->e, 0, sz);
152 
153     if (acct_type == MAP_IGP) igp_daemon_map_initialize(filename, req);
154     if (acct_type == MAP_CUSTOM_PRIMITIVES) custom_primitives_map_initialize();
155 
156     /* first stage: reading Agent ID file and arranging it in a temporary memory table */
157     while (!feof(file)) {
158       ignoring = FALSE;
159       req->line_num = ++tot_lines;
160 
161       if (tmp.num >= map_entries) {
162 	Log(LOG_WARNING, "WARN ( %s/%s ): [%s] file cut to the first %u entries. Number of entries can be configured via 'maps_entries'.\n",
163 		config.name, config.type, filename, map_entries);
164 	break;
165       }
166       memset(buf, 0, map_row_len);
167       if (fgets(buf, map_row_len, file)) {
168         if (!iscomment(buf) && !isblankline(buf)) {
169 	  if (strlen(buf) == (map_row_len-1) && !strchr(buf, '\n')) {
170 	    Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] line too long (max %u chars). Ignored.\n",
171 			config.name, config.type, filename, tot_lines, map_row_len);
172 	    continue;
173 	  }
174           if (!check_not_valid_char(filename, buf, '|')) {
175             mark_columns(buf);
176             trim_all_spaces(buf);
177 	    strip_quotes(buf);
178 
179 	    /* resetting the entry and enforcing defaults */
180 	    if (acct_type == MAP_IGP) memset(&ime, 0, sizeof(ime));
181             memset(&tmp.e[tmp.num], 0, sizeof(struct id_entry));
182 	    tmp.e[tmp.num].ret = FALSE;
183 
184             err = FALSE; key = NULL; value = NULL;
185             start = buf;
186             len = strlen(buf);
187 
188             for (x = 0; x <= len; x++) {
189               if (buf[x] == '=') {
190                 if (start == &buf[x]) continue;
191                 if (!key) {
192                   buf[x] = '\0';
193 		  key = start;
194                   x++;
195                   start = &buf[x];
196 		}
197               }
198               if ((buf[x] == '|') || (buf[x] == '\0')) {
199                 if (start == &buf[x]) continue;
200                 buf[x] = '\0';
201                 if (value || !key) {
202                   Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] malformed line. Ignored.\n", config.name, config.type, filename, tot_lines);
203                   err = TRUE;
204                   break;
205                 }
206                 else value = start;
207                 x++;
208                 start = &buf[x];
209               }
210 
211               if (key && value) {
212                 int dindex; /* dictionary index */
213 
214 		/* Processing of source BGP-related primitives kept consistent;
215 		   This can indeed be split as required in future */
216 		if (acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_SRC_LOCAL_PREF ||
217 		    acct_type == MAP_BGP_SRC_MED) {
218                   for (dindex = 0; strcmp(bpas_map_dictionary[dindex].key, ""); dindex++) {
219                     if (!strcmp(bpas_map_dictionary[dindex].key, key)) {
220                       err = (*bpas_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
221                       break;
222                     }
223                     else err = E_NOTFOUND; /* key not found */
224                   }
225                   if (err) {
226                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
227 						config.name, config.type, filename, tot_lines, key);
228                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
229                     break;
230                   }
231                   key = NULL; value = NULL;
232 		}
233 		else if (acct_type == MAP_BGP_TO_XFLOW_AGENT) {
234                   for (dindex = 0; strcmp(bta_map_dictionary[dindex].key, ""); dindex++) {
235                     if (!strcmp(bta_map_dictionary[dindex].key, key)) {
236                       err = (*bta_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
237                       break;
238                     }
239                     else err = E_NOTFOUND; /* key not found */
240                   }
241                   if (err) {
242                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
243 						config.name, config.type, filename, tot_lines, key);
244                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
245                     break;
246                   }
247                   key = NULL; value = NULL;
248 		}
249                 else if (acct_type == MAP_FLOW_TO_RD) {
250                   for (dindex = 0; strcmp(bitr_map_dictionary[dindex].key, ""); dindex++) {
251                     if (!strcmp(bitr_map_dictionary[dindex].key, key)) {
252                       err = (*bitr_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
253                       break;
254                     }
255                     else err = E_NOTFOUND; /* key not found */
256                   }
257                   if (err) {
258                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
259 						config.name, config.type, filename, tot_lines, key);
260                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
261                     break;
262                   }
263                   key = NULL; value = NULL;
264                 }
265 		else if (acct_type == MAP_SAMPLING) {
266                   for (dindex = 0; strcmp(sampling_map_dictionary[dindex].key, ""); dindex++) {
267                     if (!strcmp(sampling_map_dictionary[dindex].key, key)) {
268                       err = (*sampling_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
269                       break;
270                     }
271                     else err = E_NOTFOUND; /* key not found */
272                   }
273                   if (err) {
274                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
275 						config.name, config.type, filename, tot_lines, key);
276                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
277                     break;
278                   }
279                   key = NULL; value = NULL;
280 		}
281 		else if (acct_type == MAP_TEE_RECVS) {
282                   for (dindex = 0; strcmp(tee_recvs_map_dictionary[dindex].key, ""); dindex++) {
283                     if (!strcmp(tee_recvs_map_dictionary[dindex].key, key)) {
284                       err = (*tee_recvs_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type);
285                       break;
286                     }
287                     else err = E_NOTFOUND; /* key not found */
288                   }
289                   if (err) {
290                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
291 						config.name, config.type, filename, tot_lines, key);
292                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
293                     break;
294                   }
295                   key = NULL; value = NULL;
296 		}
297 		else if (acct_type == MAP_BGP_XCS) {
298                   for (dindex = 0; strcmp(bgp_xcs_map_dictionary[dindex].key, ""); dindex++) {
299                     if (!strcmp(bgp_xcs_map_dictionary[dindex].key, key)) {
300                       err = (*bgp_xcs_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type);
301                       break;
302                     }
303                     else err = E_NOTFOUND; /* key not found */
304                   }
305                   if (err) {
306                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
307 						config.name, config.type, filename, tot_lines, key);
308                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
309                     break;
310                   }
311                   key = NULL; value = NULL;
312 		}
313                 else if (acct_type == MAP_IGP) {
314                   for (dindex = 0; strcmp(igp_daemon_map_dictionary[dindex].key, ""); dindex++) {
315                     if (!strcmp(igp_daemon_map_dictionary[dindex].key, key)) {
316                       err = (*igp_daemon_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type);
317                       break;
318                     }
319                     else err = E_NOTFOUND; /* key not found */
320                   }
321                   if (err) {
322                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
323                                                 config.name, config.type, filename, tot_lines, key);
324                     else {
325 		      Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
326 		      ignoring = TRUE;
327 		    }
328                   }
329                   key = NULL; value = NULL;
330                 }
331                 else if (acct_type == MAP_CUSTOM_PRIMITIVES) {
332                   for (dindex = 0; strcmp(custom_primitives_map_dictionary[dindex].key, ""); dindex++) {
333                     if (!strcmp(custom_primitives_map_dictionary[dindex].key, key)) {
334                       err = (*custom_primitives_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
335                       break;
336                     }
337                     else err = E_NOTFOUND; /* key not found */
338                   }
339                   if (err) {
340                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
341                                                 config.name, config.type, filename, tot_lines, key);
342                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
343 		    ignoring = TRUE;
344                     break;
345                   }
346                   key = NULL; value = NULL;
347 		}
348                 else if (acct_type == MAP_PCAP_INTERFACES) {
349                   for (dindex = 0; strcmp(pm_pcap_interfaces_map_dictionary[dindex].key, ""); dindex++) {
350                     if (!strcmp(pm_pcap_interfaces_map_dictionary[dindex].key, key)) {
351                       err = (*pm_pcap_interfaces_map_dictionary[dindex].func)(filename, NULL, value, req, acct_type);
352                       break;
353                     }
354                     else err = E_NOTFOUND; /* key not found */
355                   }
356                   if (err) {
357                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
358                                                 config.name, config.type, filename, tot_lines, key);
359                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
360                     break;
361                   }
362                   key = NULL; value = NULL;
363                 }
364 		else {
365 		  if (tee_plugins) {
366                     for (dindex = 0; strcmp(tag_map_tee_dictionary[dindex].key, ""); dindex++) {
367                       if (!strcmp(tag_map_tee_dictionary[dindex].key, key)) {
368                         err = (*tag_map_tee_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
369                         break;
370                       }
371                       else err = E_NOTFOUND; /* key not found */
372                     }
373 		  }
374 		  else {
375                     for (dindex = 0; strcmp(tag_map_dictionary[dindex].key, ""); dindex++) {
376                       if (!strcmp(tag_map_dictionary[dindex].key, key)) {
377                         err = (*tag_map_dictionary[dindex].func)(filename, &tmp.e[tmp.num], value, req, acct_type);
378                         break;
379                       }
380                       else err = E_NOTFOUND; /* key not found */
381 		    }
382 		  }
383                   if (err) {
384                     if (err == E_NOTFOUND) Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] unknown key '%s'. Ignored.\n",
385 						config.name, config.type, filename, tot_lines, key);
386                     else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] Line ignored.\n", config.name, config.type, filename, tot_lines);
387                     break;
388                   }
389                   key = NULL; value = NULL;
390 		}
391               }
392             }
393 	    if (!ignoring) {
394               /* verifying errors and required fields */
395 	      if (acct_type == ACCT_NF || acct_type == ACCT_SF) {
396 	        if (tmp.e[tmp.num].id && tmp.e[tmp.num].id2 && tmp.e[tmp.num].label.len)
397 		   Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] set_tag (id), set_tag2 (id2) and set_label are mutual exclusive. Line ignored.\n",
398 			config.name, config.type, filename, tot_lines);
399                 else if (!err) {
400                   int j, z, recirculate;
401 		  struct id_entry recirc_e;
402 
403 		  recirculate = FALSE;
404 		  recirculate_ipv6:
405 
406 		  if (!tmp.e[tmp.num].key.agent_ip.a.family) {
407 		    if (!recirculate) {
408 		      memset(&tmp.e[tmp.num].key.agent_ip, 0, sizeof(pt_hostaddr_t));
409 		      memset(&tmp.e[tmp.num].key.agent_mask, 0, sizeof(pt_hostmask_t));
410 		      tmp.e[tmp.num].key.agent_ip.a.family = AF_INET;
411 		      tmp.e[tmp.num].key.agent_mask.family = AF_INET;
412 
413 		      memcpy(&recirc_e, &tmp.e[tmp.num], sizeof(struct id_entry));
414 		      recirculate = TRUE;
415 		    }
416 		    else {
417 		      memcpy(&tmp.e[tmp.num], &recirc_e, sizeof(struct id_entry));
418                       tmp.e[tmp.num].key.agent_ip.a.family = AF_INET6;
419                       tmp.e[tmp.num].key.agent_mask.family = AF_INET6;
420 
421 		      if (recirc_e.label.val) {
422 			memset(&tmp.e[tmp.num].label, 0, sizeof(pt_label_t));
423 			pretag_copy_label(&tmp.e[tmp.num].label, &recirc_e.label);
424 		      }
425 
426 		      recirculate = FALSE;
427 		    }
428 		  }
429 
430                   for (j = 0; tmp.e[tmp.num].func[j]; j++);
431 		  for (z = 0; tmp.e[tmp.num].set_func[z]; z++, j++) {
432 		    tmp.e[tmp.num].func[j] = tmp.e[tmp.num].set_func[z];
433 		    tmp.e[tmp.num].func_type[j] = tmp.e[tmp.num].set_func_type[z];
434 		  }
435 
436 	          if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++;
437 	          else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++;
438                   tmp.num++;
439 
440 		  if (recirculate) {
441 		    if (tmp.num < map_entries) goto recirculate_ipv6;
442 		  }
443                 }
444 	        /* if any required field is missing and other errors have been signalled
445 	           before we will trap an error message */
446 	      }
447 	      else if (acct_type == ACCT_PM) {
448 	        if (tmp.e[tmp.num].id && tmp.e[tmp.num].id2 && tmp.e[tmp.num].label.len)
449                    Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] set_tag (id), set_tag2 (id2) and set_label are mutual exclusive. Line ignored.\n",
450 			config.name, config.type, filename, tot_lines);
451 	        else if (tmp.e[tmp.num].key.agent_ip.a.family)
452 		  Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] key 'ip' not applicable. Line ignored.\n",
453 			config.name, config.type, filename, tot_lines);
454 	        else if (!err) {
455                   int j, z;
456 
457 		  for (j = 0; tmp.e[tmp.num].func[j]; j++);
458 		  for (z = 0; tmp.e[tmp.num].set_func[z]; z++, j++) {
459 		    tmp.e[tmp.num].func[j] = tmp.e[tmp.num].set_func[z];
460 		    tmp.e[tmp.num].func_type[j] = tmp.e[tmp.num].set_func_type[z];
461 		  }
462 		  tmp.e[tmp.num].key.agent_ip.a.family = AF_INET; /* we emulate a dummy '0.0.0.0' IPv4 address */
463 		  v4_num++; tmp.num++;
464 	        }
465 	      }
466 	      else if (acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_BGP_SRC_LOCAL_PREF ||
467 	  	       acct_type == MAP_BGP_SRC_MED) {
468                 if (!err && (tmp.e[tmp.num].id || tmp.e[tmp.num].flags) && tmp.e[tmp.num].key.agent_ip.a.family) {
469                   int j;
470 
471                   for (j = 0; tmp.e[tmp.num].func[j]; j++);
472                   tmp.e[tmp.num].func[j] = pretag_id_handler;
473                   if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++;
474                   else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++;
475                   tmp.num++;
476                 }
477                 else if ((!tmp.e[tmp.num].id || !tmp.e[tmp.num].key.agent_ip.a.family) && !err)
478                   Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] required key missing. Required keys are: 'id', 'ip'. Line ignored.\n",
479 			config.name, config.type, filename, tot_lines);
480 	      }
481               else if (acct_type == MAP_BGP_TO_XFLOW_AGENT) {
482                 if (!err && (tmp.e[tmp.num].id || tmp.e[tmp.num].id2) && tmp.e[tmp.num].key.agent_ip.a.family) {
483                   int j, z;
484 
485                   for (j = 0; tmp.e[tmp.num].func[j]; j++);
486 		  for (z = 0; tmp.e[tmp.num].set_func[z]; z++, j++) {
487                     tmp.e[tmp.num].func[j] = tmp.e[tmp.num].set_func[z];
488                     tmp.e[tmp.num].func_type[j] = tmp.e[tmp.num].set_func_type[z];
489                   }
490 		  /* imposing pretag_id_handler to be the last one */
491 		  tmp.e[tmp.num].func[j] = pretag_id_handler;
492 
493                   if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++;
494                   else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++;
495                   tmp.num++;
496                 }
497                 else if (((!tmp.e[tmp.num].id && !tmp.e[tmp.num].id2) || !tmp.e[tmp.num].key.agent_ip.a.family) && !err)
498                   Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] required key missing. Required keys are: 'id', 'ip'. Line ignored.\n",
499                         config.name, config.type, filename, tot_lines);
500               }
501               else if (acct_type == MAP_FLOW_TO_RD) {
502                 if (!err && tmp.e[tmp.num].id && tmp.e[tmp.num].key.agent_ip.a.family) {
503                   int j;
504 
505                   for (j = 0; tmp.e[tmp.num].func[j]; j++);
506                   tmp.e[tmp.num].func[j] = pretag_id_handler;
507                   if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++;
508                   else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++;
509                   tmp.num++;
510                 }
511 	      }
512               else if (acct_type == MAP_SAMPLING) {
513                 if (!err && tmp.e[tmp.num].id && tmp.e[tmp.num].key.agent_ip.a.family) {
514                   int j;
515 
516                   for (j = 0; tmp.e[tmp.num].func[j]; j++);
517                   tmp.e[tmp.num].func[j] = pretag_id_handler;
518                   if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET) v4_num++;
519                   else if (tmp.e[tmp.num].key.agent_ip.a.family == AF_INET6) v6_num++;
520                   tmp.num++;
521                 }
522                 else if ((!tmp.e[tmp.num].id || !tmp.e[tmp.num].key.agent_ip.a.family) && !err)
523                   Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] required key missing. Required keys are: 'id', 'ip'. Line ignored.\n",
524 			config.name, config.type, filename, tot_lines);
525               }
526 	      else if (acct_type == MAP_TEE_RECVS) tee_recvs_map_validate(filename, tot_lines, req);
527 	      else if (acct_type == MAP_BGP_XCS) bgp_xcs_map_validate(filename, req);
528 	      else if (acct_type == MAP_IGP) igp_daemon_map_validate(filename, req);
529 	      else if (acct_type == MAP_CUSTOM_PRIMITIVES) custom_primitives_map_validate(filename, req);
530 	      else if (acct_type == MAP_PCAP_INTERFACES) pm_pcap_interfaces_map_validate(filename, req);
531 	    }
532           }
533           else Log(LOG_WARNING, "WARN ( %s/%s ): [%s:%u] malformed line. Ignored.\n",
534 			config.name, config.type, filename, tot_lines);
535         }
536       }
537     }
538     fclose(file);
539 
540     if (acct_type == MAP_IGP) igp_daemon_map_finalize(filename, req);
541 
542     if (t) {
543       stat(filename, &st);
544       t->timestamp = st.st_mtime;
545 
546       /* second stage: segregating IPv4, IPv6. No further reordering
547          in order to deal smoothly with jumps (ie. JEQs) */
548 
549       x = 0;
550       t->type = acct_type;
551       t->num = tmp.num;
552       t->ipv4_num = v4_num;
553       t->ipv4_base = &t->e[x];
554       t->flags = tmp.flags;
555       for (index = 0; index < tmp.num; index++) {
556         if (tmp.e[index].key.agent_ip.a.family == AF_INET) {
557           memcpy(&t->e[x], &tmp.e[index], sizeof(struct id_entry));
558 	  t->e[x].pos = x;
559 	  x++;
560         }
561       }
562 
563       t->ipv6_num = v6_num;
564       t->ipv6_base = &t->e[x];
565       for (index = 0; index < tmp.num; index++) {
566         if (tmp.e[index].key.agent_ip.a.family == AF_INET6) {
567           memcpy(&t->e[x], &tmp.e[index], sizeof(struct id_entry));
568 	  t->e[x].pos = x;
569           x++;
570         }
571       }
572 
573       /* third stage: building short circuits basing on jumps and labels. Only
574          forward references are solved. Backward and unsolved references will
575          generate errors. */
576       for (ptr = t->ipv4_base, x = 0; x < t->ipv4_num; ptr++, x++) {
577         if (ptr->jeq.label) {
578 	  label_solved = FALSE;
579 
580 	  /* honouring reserved labels (ie. "next"). Then resolving unknown labels */
581 	  if (!strcmp(ptr->jeq.label, "next")) {
582 	    ptr->jeq.ptr = ptr+1;
583 	    label_solved = TRUE;
584 	  }
585 	  else {
586 	    for (ptr2 = ptr+1, index = x+1; index < t->ipv4_num; ptr2++, index++) {
587 	      if (!strcmp(ptr->jeq.label, ptr2->entry_label)) {
588 	        ptr->jeq.ptr = ptr2;
589 	        label_solved = TRUE;
590 		break;
591 	      }
592 	    }
593 	  }
594 	  if (!label_solved) {
595 	    ptr->jeq.ptr = NULL;
596 	    Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unresolved label '%s'. Ignoring it.\n",
597 			config.name, config.type, filename, ptr->jeq.label);
598 	  }
599         }
600       }
601 
602       for (ptr = t->ipv6_base, x = 0; x < t->ipv6_num; ptr++, x++) {
603         if (ptr->jeq.label) {
604           label_solved = FALSE;
605           for (ptr2 = ptr+1, index = x+1; index < t->ipv6_num; ptr2++, index++) {
606             if (!strcmp(ptr->jeq.label, ptr2->entry_label)) {
607               ptr->jeq.ptr = ptr2;
608               label_solved = TRUE;
609 	      break;
610             }
611           }
612           if (!label_solved) {
613             ptr->jeq.ptr = NULL;
614             Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unresolved label '%s'. Ignoring it.\n",
615 			config.name, config.type, filename, ptr->jeq.label);
616           }
617         }
618       }
619 
620       t->filename = filename;
621 
622       /* pre_tag_map indexing here */
623       if (config.maps_index &&
624 	  (acct_type == ACCT_NF || acct_type == ACCT_SF || acct_type == ACCT_PM ||
625 	   acct_type == MAP_BGP_PEER_AS_SRC || acct_type == MAP_FLOW_TO_RD)) {
626 	pt_bitmap_t idx_bmap;
627 
628 	t->index_num = MAX_ID_TABLE_INDEXES;
629 
630         for (ptr = t->ipv4_base, x = 0; x < (t->ipv4_num + t->ipv6_num); ptr++, x++) {
631 	  idx_bmap = pretag_index_build_bitmap(ptr, acct_type);
632 
633 	  /* insert bitmap to index list and determine entries per index */
634 	  if (pretag_index_insert_bitmap(t, idx_bmap)) {
635 	    Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Out of indexes. Indexing disabled.\n",
636 		config.name, config.type, filename);
637 	    pretag_index_destroy(t);
638 	    break;
639 	  }
640 	}
641 
642 	/* set handlers */
643 	pretag_index_set_handlers(t);
644 
645 	/* allocate indexes */
646         pretag_index_allocate(t);
647 
648         for (ptr = t->ipv4_base, x = 0; x < (t->ipv4_num + t->ipv6_num); ptr++, x++) {
649           idx_bmap = pretag_index_build_bitmap(ptr, acct_type);
650 
651 	  /* fill indexes */
652 	  pretag_index_fill(t, idx_bmap, ptr);
653 	}
654       }
655 
656       if (t->flags & PRETAG_FLAG_NEG) {
657         Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Negations not supported. Indexing disabled.\n",
658                 config.name, config.type, filename);
659         pretag_index_destroy(t);
660       }
661       else pretag_index_report(t);
662     }
663   }
664 
665   if (tmp.e) free(tmp.e) ;
666   if (buf) free(buf) ;
667 
668   Log(LOG_INFO, "INFO ( %s/%s ): [%s] map successfully (re)loaded.\n", config.name, config.type, filename);
669 
670   return;
671 
672   handle_error:
673   if (*map_allocated && tmp.e) free(tmp.e) ;
674   if (buf) free(buf);
675 
676   if (t && t->timestamp) {
677     Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Rolling back old map.\n", config.name, config.type, filename);
678 
679     /* we update the timestamp to avoid loops */
680     stat(filename, &st);
681     t->timestamp = st.st_mtime;
682   }
683   else exit_gracefully(1);
684 }
685 
pt_check_neg(char ** value,u_int32_t * flags)686 u_int8_t pt_check_neg(char **value, u_int32_t *flags)
687 {
688   if (**value == '-') {
689     (*value)++;
690 
691     if (flags) *flags |= PRETAG_FLAG_NEG;
692 
693     return TRUE;
694   }
695   else return FALSE;
696 }
697 
pt_check_range(char * str)698 char *pt_check_range(char *str)
699 {
700   char *ptr;
701 
702   if ((ptr = strchr(str, '-'))) {
703     *ptr = '\0';
704     ptr++;
705     return ptr;
706   }
707   else return NULL;
708 }
709 
load_pre_tag_map(int acct_type,char * filename,struct id_table * t,struct plugin_requests * req,int * map_allocated,int map_entries,int map_row_len)710 void load_pre_tag_map(int acct_type, char *filename, struct id_table *t, struct plugin_requests *req,
711 		      int *map_allocated, int map_entries, int map_row_len)
712 {
713   if (req) {
714     req->map_entries = map_entries;
715     req->map_row_len = map_row_len;
716   }
717 
718   load_id_file(acct_type, filename, t, req, map_allocated);
719 
720   if (req) {
721     req->map_entries = FALSE;
722     req->map_row_len = FALSE;
723   }
724 }
725 
pretag_init_vars(struct packet_ptrs * pptrs,struct id_table * t)726 void pretag_init_vars(struct packet_ptrs *pptrs, struct id_table *t)
727 {
728   if (!pptrs) return;
729 
730   if (t->type == ACCT_NF) memset(&pptrs->set_tos, 0, sizeof(s_uint8_t));
731   if (t->type == MAP_BGP_TO_XFLOW_AGENT) memset(&pptrs->lookup_bgp_port, 0, sizeof(s_uint16_t));
732 
733   if (pptrs->label.val) {
734     pretag_free_label(&pptrs->label);
735     pptrs->have_label = FALSE;
736   }
737 }
738 
pretag_init_label(pt_label_t * label)739 void pretag_init_label(pt_label_t *label)
740 {
741   if (!label) return;
742 
743   memset(label, 0, sizeof(pt_label_t));
744 }
745 
pretag_malloc_label(pt_label_t * label,int len)746 int pretag_malloc_label(pt_label_t *label, int len)
747 {
748   if (!label) return ERR;
749 
750   label->val = malloc(len);
751   if (!label->val) {
752     Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_malloc_label).\n", config.name, config.type);
753     return ERR;
754   }
755   label->len = len;
756 
757   return SUCCESS;
758 }
759 
pretag_realloc_label(pt_label_t * label,int len)760 int pretag_realloc_label(pt_label_t *label, int len)
761 {
762   if (!label) return ERR;
763 
764   label->val = realloc(label->val, len);
765   if (!label->val) {
766     Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_realloc_label).\n", config.name, config.type);
767     return ERR;
768   }
769   label->len = len;
770 
771   return SUCCESS;
772 }
773 
pretag_copy_label(pt_label_t * dst,pt_label_t * src)774 int pretag_copy_label(pt_label_t *dst, pt_label_t *src)
775 {
776   if (!src || !dst) return ERR;
777 
778   if (dst->val) {
779     Log(LOG_WARNING, "WARN ( %s/%s ): pretag_copy_label failed: dst->val not null\n", config.name, config.type);
780     return ERR;
781   }
782   else {
783     if (src->len) {
784       pretag_malloc_label(dst, src->len + 1);
785       if (!dst->val) {
786         Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_copy_label).\n", config.name, config.type);
787         return ERR;
788       }
789 
790       strncpy(dst->val, src->val, src->len);
791       dst->val[dst->len] = '\0';
792     }
793   }
794 
795   return SUCCESS;
796 }
797 
pretag_move_label(pt_label_t * dst,pt_label_t * src)798 int pretag_move_label(pt_label_t *dst, pt_label_t *src)
799 {
800   if (!src || !dst) return ERR;
801 
802   if (dst->val) {
803     Log(LOG_WARNING, "WARN ( %s/%s ): pretag_move_label failed: dst->val not null\n", config.name, config.type);
804     return ERR;
805   }
806   else {
807     if (src->len) {
808       dst->val = src->val;
809       dst->len = src->len;
810 
811       src->val = NULL;
812       src->len = 0;
813     }
814   }
815 
816   return SUCCESS;
817 }
818 
pretag_append_label(pt_label_t * dst,pt_label_t * src)819 int pretag_append_label(pt_label_t *dst, pt_label_t *src)
820 {
821   char default_sep[] = ",";
822 
823   if (!src || !dst) return ERR;
824 
825   if (!dst->val) {
826     Log(LOG_WARNING, "WARN ( %s/%s ): pretag_append_label failed: dst->val null\n", config.name, config.type);
827     return ERR;
828   }
829   else {
830     if (src->len) {
831       pretag_realloc_label(dst, (dst->len + src->len + 1 /* sep */ + 1 /* null */));
832       if (!dst->val) {
833         Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (pretag_append_label).\n", config.name, config.type);
834         return ERR;
835       }
836 
837       strncat(dst->val, default_sep, 1);
838       strncat(dst->val, src->val, src->len);
839       dst->val[dst->len] = '\0';
840     }
841   }
842 
843   return SUCCESS;
844 }
845 
pretag_free_label(pt_label_t * label)846 void pretag_free_label(pt_label_t *label)
847 {
848   if (label && label->val) {
849     free(label->val);
850     label->val = NULL;
851     label->len = 0;
852   }
853 }
854 
pretag_entry_process(struct id_entry * e,struct packet_ptrs * pptrs,pm_id_t * tag,pm_id_t * tag2)855 int pretag_entry_process(struct id_entry *e, struct packet_ptrs *pptrs, pm_id_t *tag, pm_id_t *tag2)
856 {
857   int j = 0;
858   pm_id_t id = 0, stop = 0, ret = 0;
859   pt_label_t *label_local = malloc(sizeof(pt_label_t));
860 
861   pretag_init_label(label_local);
862 
863   e->last_matched = FALSE;
864 
865   for (j = 0, stop = 0, ret = 0; ((!ret || ret > TRUE) && (*e->func[j])); j++) {
866     if (e->func_type[j] == PRETAG_SET_LABEL) {
867       ret = (*e->func[j])(pptrs, label_local, e);
868     }
869     else {
870       ret = (*e->func[j])(pptrs, &id, e);
871     }
872 
873     if (ret > TRUE) stop |= ret;
874     else stop = ret;
875   }
876 
877   if (!stop || stop > TRUE) {
878     if (stop & PRETAG_MAP_RCODE_ID) {
879       if (e->stack.func) id = (*e->stack.func)(id, *tag);
880       *tag = id;
881       pptrs->have_tag = TRUE;
882     }
883     else if (stop & PRETAG_MAP_RCODE_ID2) {
884       if (e->stack.func) id = (*e->stack.func)(id, *tag2);
885       *tag2 = id;
886       pptrs->have_tag2 = TRUE;
887     }
888     else if (stop & PRETAG_MAP_RCODE_LABEL) {
889       if (pptrs->label.len) {
890 	pretag_append_label(&pptrs->label, label_local);
891       }
892       else {
893 	pretag_copy_label(&pptrs->label, label_local);
894       }
895 
896       pptrs->have_label = TRUE;
897     }
898     else if (stop == BTA_MAP_RCODE_ID_ID2) {
899       // stack not applicable here
900       *tag = id;
901       *tag2 = e->id2;
902       pptrs->have_tag = TRUE;
903       pptrs->have_tag2 = TRUE;
904     }
905 
906     if (e->jeq.ptr) {
907       if (e->ret) {
908 	exec_plugins(pptrs, NULL);
909 	set_shadow_status(pptrs);
910 	*tag = 0;
911 	*tag2 = 0;
912 	if (pptrs->label.val) pretag_free_label(&pptrs->label);
913 
914 	pptrs->have_tag = FALSE;
915 	pptrs->have_tag2 = FALSE;
916 	pptrs->have_label = FALSE;
917       }
918       stop |= PRETAG_MAP_RCODE_JEQ;
919     }
920   }
921 
922   pretag_free_label(label_local);
923   if (label_local) free(label_local);
924 
925   return stop;
926 }
927 
pretag_index_build_bitmap(struct id_entry * ptr,int acct_type)928 pt_bitmap_t pretag_index_build_bitmap(struct id_entry *ptr, int acct_type)
929 {
930   pt_bitmap_t idx_bmap = 0;
931   u_int32_t iterator = 0;
932 
933   for (; ptr->func[iterator]; iterator++) idx_bmap |= ptr->func_type[iterator];
934 
935   /* 1) invalidate bitmap if we have fields incompatible with indexing */
936   if (idx_bmap & PRETAG_FILTER) return 0;
937 
938   /* 2) scrub bitmap: remove PRETAG_SET_* fields from the bitmap */
939   if (idx_bmap & PRETAG_SET_TOS) idx_bmap ^= PRETAG_SET_TOS;
940   if (idx_bmap & PRETAG_SET_TAG) idx_bmap ^= PRETAG_SET_TAG;
941   if (idx_bmap & PRETAG_SET_TAG2) idx_bmap ^= PRETAG_SET_TAG2;
942   if (idx_bmap & PRETAG_SET_LABEL) idx_bmap ^= PRETAG_SET_LABEL;
943 
944   return idx_bmap;
945 }
946 
pretag_index_insert_bitmap(struct id_table * t,pt_bitmap_t idx_bmap)947 int pretag_index_insert_bitmap(struct id_table *t, pt_bitmap_t idx_bmap)
948 {
949   u_int32_t iterator = 0;
950 
951   if (!t) return TRUE;
952 
953   for (iterator = 0; iterator < t->index_num; iterator++) {
954     if (!t->index[iterator].entries || t->index[iterator].bitmap == idx_bmap) {
955       t->index[iterator].bitmap = idx_bmap;
956       t->index[iterator].entries++;
957       return FALSE;
958     }
959   }
960 
961   return TRUE;
962 }
963 
pretag_index_set_handlers(struct id_table * t)964 int pretag_index_set_handlers(struct id_table *t)
965 {
966   pt_bitmap_t residual_idx_bmap = 0;
967   u_int32_t index = 0, iterator = 0, handler_index = 0;
968 
969   if (!t) return TRUE;
970 
971   for (iterator = 0; iterator < t->index_num; iterator++) {
972     residual_idx_bmap = t->index[iterator].bitmap;
973 
974     handler_index = 0;
975     memset(t->index[iterator].idt_handler, 0, sizeof(t->index[iterator].idt_handler));
976     memset(t->index[iterator].fdata_handler, 0, sizeof(t->index[iterator].fdata_handler));
977 
978     for (index = 0; tag_map_index_entries_dictionary[index].key; index++) {
979       if (t->index[iterator].bitmap & tag_map_index_entries_dictionary[index].key) {
980         t->index[iterator].idt_handler[handler_index] = (*tag_map_index_entries_dictionary[index].func);
981 	handler_index++;
982 
983         residual_idx_bmap ^= tag_map_index_entries_dictionary[index].key;
984       }
985     }
986 
987     handler_index = 0;
988 
989     /* we set foreign data handlers here but skip on the residual_idx_bmap */
990     for (index = 0; tag_map_index_fdata_dictionary[index].key; index++) {
991       if (t->index[iterator].bitmap & tag_map_index_fdata_dictionary[index].key) {
992         t->index[iterator].fdata_handler[handler_index] = (*tag_map_index_fdata_dictionary[index].func);
993         handler_index++;
994       }
995     }
996 
997     if (residual_idx_bmap) {
998       Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: not supported for field(s) %llx. Indexing disabled.\n",
999 		config.name, config.type, t->filename, (unsigned long long)residual_idx_bmap);
1000       pretag_index_destroy(t);
1001     }
1002   }
1003 
1004   return FALSE;
1005 }
1006 
pretag_index_allocate(struct id_table * t)1007 int pretag_index_allocate(struct id_table *t)
1008 {
1009   pt_bitmap_t idx_t_size = 0;
1010   u_int32_t iterator = 0, j = 0;
1011   int ret, destroy = FALSE;
1012 
1013   if (!t) return TRUE;
1014 
1015   for (iterator = 0; iterator < t->index_num; iterator++) {
1016     if (t->index[iterator].entries) {
1017       Log(LOG_INFO, "INFO ( %s/%s ): [%s] maps_index: created index %llx (%u entries).\n", config.name,
1018     		config.type, t->filename, (unsigned long long)t->index[iterator].bitmap, t->index[iterator].entries);
1019 
1020       assert(!t->index[iterator].idx_t);
1021 
1022       t->index[iterator].modulo = next_prime(t->index[iterator].entries * 2);
1023       if (!t->index[iterator].modulo) t->index[iterator].modulo = (t->index[iterator].entries * 2);
1024 
1025       idx_t_size = t->index[iterator].modulo * sizeof(struct id_index_entry);
1026       t->index[iterator].idx_t = malloc(idx_t_size);
1027 
1028       if (!t->index[iterator].idx_t) {
1029         Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: unable to allocate index %llx.\n", config.name,
1030 		config.type, t->filename, (unsigned long long)t->index[iterator].bitmap);
1031 	t->index[iterator].bitmap = 0;
1032 	t->index[iterator].entries = 0;
1033 	destroy = TRUE;
1034 	break;
1035       }
1036       else {
1037 	memset(t->index[iterator].idx_t, 0, idx_t_size);
1038 
1039 	for (j = 0; j < t->index[iterator].modulo; j++) {
1040 	  t->index[iterator].idx_t[j].depth = ID_TABLE_INDEX_DEPTH;
1041 	}
1042 
1043 	ret = hash_init_serial(&t->index[iterator].hash_serializer, 16 /* dummy len for init sake */);
1044 	if (ret == ERR) {
1045 	  Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: unable to allocate hash serializer for index %llx.\n", config.name,
1046 		config.type, t->filename, (unsigned long long)t->index[iterator].bitmap);
1047 	  destroy = TRUE;
1048 	  break;
1049 	}
1050       }
1051     }
1052   }
1053 
1054   if (destroy) {
1055     pretag_index_destroy(t);
1056     return ERR;
1057   }
1058 
1059   return SUCCESS;
1060 }
1061 
pretag_index_fill(struct id_table * t,pt_bitmap_t idx_bmap,struct id_entry * ptr)1062 int pretag_index_fill(struct id_table *t, pt_bitmap_t idx_bmap, struct id_entry *ptr)
1063 {
1064   u_int32_t index = 0, iterator = 0, handler_index = 0;
1065 
1066   if (!t) return ERR;
1067 
1068   for (iterator = 0; iterator < t->index_num; iterator++) {
1069     if (t->index[iterator].entries && t->index[iterator].bitmap == idx_bmap) {
1070       struct id_entry e;
1071       struct id_index_entry *idie;
1072       pm_hash_serial_t *hash_serializer;
1073       pm_hash_key_t *hash_key;
1074       int modulo, buckets;
1075 
1076       /* fill serializer in and compute modulo */
1077       memset(&e, 0, sizeof(struct id_entry));
1078       hash_serializer = &t->index[iterator].hash_serializer;
1079       hash_serial_set_off(hash_serializer, 0);
1080       hash_key = hash_serial_get_key(hash_serializer);
1081       buckets = t->index[iterator].modulo;
1082 
1083       if (!hash_key) return ERR;
1084 
1085       for (handler_index = 0; t->index[iterator].idt_handler[handler_index]; handler_index++) {
1086 	(*t->index[iterator].idt_handler[handler_index])(&e, hash_serializer, ptr);
1087       }
1088       modulo = cache_crc32(hash_key_get_val(hash_key), hash_key_get_len(hash_key)) % buckets;
1089       idie = &t->index[iterator].idx_t[modulo];
1090 
1091       for (index = 0; index < idie->depth; index++) {
1092         if (!idie->result[index]) {
1093 	  hash_dup_key(&idie->hash_key[index], hash_key);
1094           idie->result[index] = ptr;
1095           break;
1096         }
1097         /* removing duplicates */
1098         else {
1099 	  pm_id_t saved_pos_idie, saved_pos_ptr;
1100 	  int match = FALSE;
1101 
1102 	  saved_pos_idie = idie->result[index]->pos; idie->result[index]->pos = 0;
1103 	  saved_pos_ptr = ptr->pos; ptr->pos = 0;
1104 
1105           if (!memcmp(idie->result[index], ptr, sizeof(struct id_entry))) match = TRUE;
1106 
1107           idie->result[index]->pos = saved_pos_idie;
1108           ptr->pos = saved_pos_ptr;
1109 
1110 	  if (match) {
1111 	    hash_destroy_key(hash_key);
1112 	    break;
1113 	  }
1114         }
1115       }
1116 
1117       if (index == idie->depth) {
1118         Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: out of index space %llx. Indexing disabled.\n",
1119 		config.name, config.type, t->filename, (unsigned long long)idx_bmap);
1120 	pretag_index_report(t);
1121 	pretag_index_destroy(t);
1122 	break;
1123       }
1124     }
1125   }
1126 
1127   return SUCCESS;
1128 }
1129 
pretag_index_report(struct id_table * t)1130 void pretag_index_report(struct id_table *t)
1131 {
1132   u_int32_t iterator = 0, buckets = 0, index = 0;
1133 
1134   if (!t) return;
1135 
1136   for (iterator = 0; iterator < t->index_num; iterator++) {
1137     if (t->index[iterator].entries) {
1138       u_int32_t bucket_depths[ID_TABLE_INDEX_DEPTH];
1139 
1140       buckets = t->index[iterator].modulo;
1141       memset(&bucket_depths, 0, sizeof(bucket_depths));
1142 
1143       for (index = 0; index < buckets; index++) {
1144 	struct id_index_entry *idie = &t->index[iterator].idx_t[index];
1145 	u_int32_t depth = 0;
1146 
1147 	for (depth = 0; idie->result[depth] && depth < idie->depth; depth++) bucket_depths[depth]++;
1148       }
1149 
1150       Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] pretag_index_report(): index=%llx buckets=%u depths=[0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u] size=%lu\n",
1151 	  config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap,
1152 	  buckets, bucket_depths[0], bucket_depths[1], bucket_depths[2], bucket_depths[3],
1153 	  bucket_depths[4], bucket_depths[5], bucket_depths[6], bucket_depths[7],
1154 	  (unsigned long)(buckets * sizeof(struct id_index_entry)));
1155     }
1156   }
1157 }
1158 
pretag_index_destroy(struct id_table * t)1159 void pretag_index_destroy(struct id_table *t)
1160 {
1161   pm_hash_serial_t *hash_serializer;
1162   pm_hash_key_t *hash_key;
1163   u_int32_t iterator = 0, buckets = 0, bucket_idx = 0, depth_idx = 0;
1164 
1165   if (!t) return;
1166 
1167   for (iterator = 0; iterator < t->index_num; iterator++) {
1168     if (t->index[iterator].idx_t) {
1169       buckets = t->index[iterator].modulo;
1170 
1171       for (bucket_idx = 0; bucket_idx < buckets; bucket_idx++) {
1172         for (depth_idx = 0; depth_idx < ID_TABLE_INDEX_DEPTH; depth_idx++) {
1173           hash_destroy_key(&t->index[iterator].idx_t[bucket_idx].hash_key[depth_idx]);
1174         }
1175       }
1176 
1177       free(t->index[iterator].idx_t);
1178       Log(LOG_INFO, "INFO ( %s/%s ): [%s] maps_index: destroyed index %llx.\n",
1179                 config.name, config.type, t->filename, (unsigned long long)t->index[iterator].bitmap);
1180     }
1181 
1182     hash_serializer = &t->index[iterator].hash_serializer;
1183     hash_key = hash_serial_get_key(hash_serializer);
1184     hash_destroy_key(hash_key);
1185     memset(&t->index[iterator], 0, sizeof(struct id_table_index));
1186   }
1187 
1188   t->index_num = 0;
1189 }
1190 
pretag_index_lookup(struct id_table * t,struct packet_ptrs * pptrs,struct id_entry ** index_results,int ir_entries)1191 u_int32_t pretag_index_lookup(struct id_table *t, struct packet_ptrs *pptrs, struct id_entry **index_results, int ir_entries)
1192 {
1193   struct id_entry res_fdata;
1194   struct id_index_entry *idie;
1195   pm_hash_serial_t *hash_serializer;
1196   pm_hash_key_t *hash_key;
1197   u_int32_t iterator, index_cc, index_hdlr;
1198   int modulo, buckets, iterator_ir;
1199 
1200   if (!t || !pptrs || !index_results) return 0;
1201 
1202   memset(&res_fdata, 0, sizeof(res_fdata));
1203   memset(index_results, 0, (sizeof(struct id_entry *) * ir_entries));
1204   iterator_ir = 0;
1205 
1206   for (iterator = 0; iterator < t->index_num; iterator++) {
1207     if (t->index[iterator].entries) {
1208       hash_serializer = &t->index[iterator].hash_serializer;
1209       hash_serial_set_off(hash_serializer, 0);
1210       hash_key = hash_serial_get_key(hash_serializer);
1211       buckets = t->index[iterator].modulo;
1212 
1213       for (index_hdlr = 0; (*t->index[iterator].fdata_handler[index_hdlr]); index_hdlr++) {
1214         (*t->index[iterator].fdata_handler[index_hdlr])(&res_fdata, &t->index[iterator].hash_serializer, pptrs);
1215       }
1216 
1217       modulo = cache_crc32(hash_key_get_val(hash_key), hash_key_get_len(hash_key)) % buckets;
1218       idie = &t->index[iterator].idx_t[modulo];
1219 
1220       for (index_cc = 0; idie->result[index_cc] && index_cc < idie->depth; index_cc++) {
1221 	if (!hash_key_cmp(&idie->hash_key[index_cc], hash_key)) {
1222           index_results[iterator_ir] = idie->result[index_cc];
1223 	  if (iterator_ir < ir_entries) iterator_ir++;
1224 	  else {
1225 	    Log(LOG_WARNING, "WARN ( %s/%s ): [%s] maps_index: out of index results space. Indexing disabled.\n",
1226                 config.name, config.type, t->filename);
1227 	    pretag_index_destroy(t);
1228 	    memset(index_results, 0, (sizeof(struct id_entry *) * ir_entries));
1229 	    return 0;
1230 	  }
1231 	}
1232       }
1233     }
1234     else break;
1235   }
1236 
1237   // pretag_index_results_compress(index_results, iterator_ir);
1238   pretag_index_results_sort(index_results, iterator_ir);
1239   pretag_index_results_compress_jeqs(index_results, iterator_ir);
1240 
1241   return iterator_ir;
1242 }
1243 
pretag_index_results_sort(struct id_entry ** index_results,int ir_entries)1244 void pretag_index_results_sort(struct id_entry **index_results, int ir_entries)
1245 {
1246   struct id_entry *ptr = NULL;
1247   u_int32_t i, j;
1248 
1249   if (!index_results) return;
1250 
1251   for (i = 0, j = 1; index_results[i] && i < ir_entries; i++, j++) {
1252     if (index_results[j] && j < ir_entries) {
1253       if (index_results[i]->pos > index_results[j]->pos) {
1254 	ptr = index_results[j];
1255 	index_results[j] = index_results[i];
1256 	index_results[i] = ptr;
1257       }
1258     }
1259   }
1260 }
1261 
pretag_index_results_compress(struct id_entry ** index_results,int ir_entries)1262 void pretag_index_results_compress(struct id_entry **index_results, int ir_entries)
1263 {
1264   u_int32_t j, valid;
1265   int i;
1266 
1267   if (!index_results) return;
1268 
1269   for (i = 0; i < ir_entries; i++) {
1270     valid = 0;
1271     if (!index_results[i]) {
1272       for (j = i + 1; j < ir_entries; j++) {
1273 	if (index_results[j]) valid++;
1274         index_results[j-1] = index_results[j];
1275       }
1276       index_results[ir_entries-1] = NULL;
1277       if (!index_results[i] && valid) i--;
1278     }
1279   }
1280 }
1281 
pretag_index_results_compress_jeqs(struct id_entry ** index_results,int ir_entries)1282 void pretag_index_results_compress_jeqs(struct id_entry **index_results, int ir_entries)
1283 {
1284   u_int32_t i, j, x;
1285 
1286   if (!index_results) return;
1287 
1288   for (i = 0; index_results[i] && i < ir_entries; i++) {
1289     if (index_results[i]->jeq.ptr) {
1290       for (j = i + 1; index_results[j] && j < ir_entries; j++) {
1291         if (index_results[i]->jeq.ptr->pos > index_results[j]->pos) {
1292 	  for (x = j + 1; x < ir_entries; x++) {
1293 	    index_results[x-1] = index_results[x];
1294 	  }
1295 
1296 	  index_results[ir_entries-1] = NULL;
1297 	}
1298       }
1299     }
1300   }
1301 }
1302 
pretag_index_have_one(struct id_table * t)1303 int pretag_index_have_one(struct id_table *t)
1304 {
1305   return t->index[0].entries;
1306 }
1307