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