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 "pmacct-data.h"
25 #include "plugin_hooks.h"
26 #include "sql_common.h"
27 #include "sql_common_m.h"
28 #include "crc32.h"
29 
30 /* Global variables */
31 char sql_data[LARGEBUFLEN];
32 char lock_clause[LONGSRVBUFLEN];
33 char unlock_clause[LONGSRVBUFLEN];
34 char update_clause[LONGSRVBUFLEN];
35 char set_clause[LONGSRVBUFLEN];
36 char copy_clause[LONGSRVBUFLEN];
37 char insert_clause[LONGSRVBUFLEN];
38 char insert_counters_clause[LONGSRVBUFLEN];
39 char insert_nocounters_clause[LONGSRVBUFLEN];
40 char insert_full_clause[LONGSRVBUFLEN];
41 char values_clause[LONGLONGSRVBUFLEN];
42 char *multi_values_buffer;
43 char where_clause[LONGLONGSRVBUFLEN];
44 unsigned char *pipebuf;
45 struct db_cache *sql_cache;
46 struct db_cache **sql_queries_queue, **sql_pending_queries_queue;
47 struct db_cache *collision_queue;
48 int cq_ptr, qq_size;
49 int cq_size;
50 struct db_cache lru_head, *lru_tail;
51 struct frags where[N_PRIMITIVES+2];
52 struct frags values[N_PRIMITIVES+2];
53 struct frags copy_values[N_PRIMITIVES+2];
54 struct frags set[N_PRIMITIVES+2];
55 struct frags set_event[N_PRIMITIVES+2];
56 int glob_num_primitives; /* last resort for signal handling */
57 int glob_basetime; /* last resort for signal handling */
58 time_t glob_new_basetime; /* last resort for signal handling */
59 time_t glob_committed_basetime; /* last resort for signal handling */
60 int glob_dyn_table, glob_dyn_table_time_only; /* last resort for signal handling */
61 int glob_timeslot; /* last resort for sql handlers */
62 
63 struct sqlfunc_cb_registry sqlfunc_cbr;
64 struct DBdesc p;
65 struct DBdesc b;
66 struct BE_descs bed;
67 struct largebuf_s envbuf;
68 time_t now; /* PostgreSQL */
69 
70 /* Functions */
sql_set_signals()71 void sql_set_signals()
72 {
73   signal(SIGINT, sql_exit_gracefully);
74   signal(SIGHUP, reload); /* handles reopening of syslog channel */
75   signal(SIGUSR1, SIG_IGN);
76   signal(SIGUSR2, reload_maps);
77   signal(SIGPIPE, SIG_IGN);
78   signal(SIGCHLD, ignore_falling_child);
79 }
80 
sql_set_insert_func()81 void sql_set_insert_func()
82 {
83   if (config.what_to_count & (COUNT_SUM_HOST|COUNT_SUM_NET))
84     insert_func = sql_sum_host_insert;
85   else if (config.what_to_count & COUNT_SUM_PORT) insert_func = sql_sum_port_insert;
86   else if (config.what_to_count & COUNT_SUM_AS) insert_func = sql_sum_as_insert;
87 #if defined (HAVE_L2)
88   else if (config.what_to_count & COUNT_SUM_MAC) insert_func = sql_sum_mac_insert;
89 #endif
90   else insert_func = sql_cache_insert;
91 }
92 
sql_init_maps(struct extra_primitives * extras,struct primitives_ptrs * prim_ptrs,struct networks_table * nt,struct networks_cache * nc,struct ports_table * pt)93 void sql_init_maps(struct extra_primitives *extras, struct primitives_ptrs *prim_ptrs,
94 		   struct networks_table *nt, struct networks_cache *nc, struct ports_table *pt)
95 {
96   memset(prim_ptrs, 0, sizeof(struct primitives_ptrs));
97   set_primptrs_funcs(extras);
98 
99   memset(nt, 0, sizeof(struct networks_table));
100   memset(nc, 0, sizeof(struct networks_cache));
101   memset(pt, 0, sizeof(struct ports_table));
102 
103   load_networks(config.networks_file, nt, nc);
104   set_net_funcs(nt);
105 
106   if (config.ports_file) load_ports(config.ports_file, pt);
107 }
108 
sql_init_global_buffers()109 void sql_init_global_buffers()
110 {
111   memset(sql_data, 0, sizeof(sql_data));
112   memset(lock_clause, 0, sizeof(lock_clause));
113   memset(unlock_clause, 0, sizeof(unlock_clause));
114   memset(update_clause, 0, sizeof(update_clause));
115   memset(set_clause, 0, sizeof(set_clause));
116   memset(copy_clause, 0, sizeof(copy_clause));
117   memset(insert_clause, 0, sizeof(insert_clause));
118   memset(insert_counters_clause, 0, sizeof(insert_counters_clause));
119   memset(insert_nocounters_clause, 0, sizeof(insert_nocounters_clause));
120   memset(where, 0, sizeof(where));
121   memset(values, 0, sizeof(values));
122   memset(set, 0, sizeof(set));
123   memset(set_event, 0, sizeof(set_event));
124   memset(&lru_head, 0, sizeof(lru_head));
125   lru_tail = &lru_head;
126 
127   Log(LOG_INFO, "INFO ( %s/%s ): cache entries=%d base cache memory=%luu bytes\n", config.name, config.type,
128         config.sql_cache_entries, (unsigned long) ((config.sql_cache_entries * sizeof(struct db_cache)) +
129 	(2 * (qq_size * sizeof(struct db_cache *)))) );
130 
131   pipebuf = (unsigned char *) malloc(config.buffer_size);
132   sql_cache = (struct db_cache *) malloc(config.sql_cache_entries*sizeof(struct db_cache));
133   sql_queries_queue = (struct db_cache **) malloc(qq_size*sizeof(struct db_cache *));
134   sql_pending_queries_queue = (struct db_cache **) malloc(qq_size*sizeof(struct db_cache *));
135 
136   if (!pipebuf || !sql_cache || !sql_queries_queue || !sql_pending_queries_queue) {
137     Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (sql_init_global_buffers). Exiting ..\n", config.name, config.type);
138     exit_gracefully(1);
139   }
140 
141   memset(pipebuf, 0, config.buffer_size);
142   memset(sql_cache, 0, config.sql_cache_entries*sizeof(struct db_cache));
143   memset(sql_queries_queue, 0, qq_size*sizeof(struct db_cache *));
144   memset(sql_pending_queries_queue, 0, qq_size*sizeof(struct db_cache *));
145 }
146 
147 /* being the first routine to be called by each SQL plugin, this is
148    also the place for some initial common configuration consistency
149    check */
sql_init_default_values(struct extra_primitives * extras)150 void sql_init_default_values(struct extra_primitives *extras)
151 {
152   memset(empty_mem_area_256b, 0, sizeof(empty_mem_area_256b));
153 
154   if (config.proc_priority) {
155     int ret;
156 
157     ret = setpriority(PRIO_PROCESS, 0, config.proc_priority);
158     if (ret) Log(LOG_WARNING, "WARN ( %s/%s ): proc_priority failed (errno: %d)\n", config.name, config.type, errno);
159     else Log(LOG_INFO, "INFO ( %s/%s ): proc_priority set to %d\n", config.name, config.type, getpriority(PRIO_PROCESS, 0));
160   }
161 
162   if (!config.sql_refresh_time) config.sql_refresh_time = DEFAULT_DB_REFRESH_TIME;
163   if (!config.sql_table_version) config.sql_table_version = DEFAULT_SQL_TABLE_VERSION;
164   if (!config.sql_cache_entries) config.sql_cache_entries = CACHE_ENTRIES;
165   if (!config.dump_max_writers) config.dump_max_writers = DEFAULT_SQL_WRITERS_NO;
166 
167   dump_writers.list = malloc(config.dump_max_writers * sizeof(pid_t));
168   dump_writers_init();
169 
170   /* SQL table type parsing; basically mapping everything down to a SQL table version */
171   /* ie. BGP == 1000 */
172   if (config.sql_table_type) {
173     if (!strcmp(config.sql_table_type, "bgp")) config.sql_table_version += SQL_TABLE_VERSION_BGP;
174     else {
175       Log(LOG_ERR, "ERROR ( %s/%s ): Unknown sql_table_type value: '%s'.\n", config.name, config.type, config.sql_table_type);
176       exit_gracefully(1);
177     }
178   }
179   else {
180     if (extras->off_pkt_bgp_primitives) {
181       config.sql_table_version += SQL_TABLE_VERSION_BGP;
182       Log(LOG_INFO, "INFO ( %s/%s ): sql_table_type set to 'bgp' (aggregate includes one or more BGP primitives).\n", config.name, config.type);
183     }
184   }
185 
186   if (config.nfacctd_stitching) {
187     if (config.nfacctd_pro_rating) {
188       Log(LOG_ERR, "ERROR ( %s/%s ): Pro-rating (ie. nfacctd_pro_rating) and stitching (ie. nfacctd_stitching) are mutual exclusive. Exiting.\n", config.name, config.type);
189       exit_gracefully(1);
190     }
191 
192     if (!config.sql_dont_try_update) {
193       Log(LOG_WARNING, "WARN ( %s/%s ): stitching (ie. nfacctd_stitching) behaviour is undefined when sql_dont_try_update is set to false.\n", config.name, config.type);
194     }
195   }
196 
197   qq_ptr = 0;
198   pqq_ptr = 0;
199   qq_size = config.sql_cache_entries+(config.sql_refresh_time*REASONABLE_NUMBER);
200   pp_size = sizeof(struct pkt_primitives);
201   pb_size = sizeof(struct pkt_bgp_primitives);
202   pn_size = sizeof(struct pkt_nat_primitives);
203   pm_size = sizeof(struct pkt_mpls_primitives);
204   pt_size = sizeof(struct pkt_tunnel_primitives);
205   pc_size = config.cpptrs.len;
206   dbc_size = sizeof(struct db_cache);
207 
208   /* handling purge preprocessor */
209   set_preprocess_funcs(config.sql_preprocess, &prep, PREP_DICT_SQL);
210 }
211 
sql_init_historical_acct(time_t now,struct insert_data * idata)212 void sql_init_historical_acct(time_t now, struct insert_data *idata)
213 {
214   time_t t;
215 
216   if (config.sql_history) {
217     idata->basetime = now;
218     if (config.sql_history == COUNT_SECONDLY) idata->timeslot = config.sql_history_howmany;
219     else if (config.sql_history == COUNT_MINUTELY) idata->timeslot = config.sql_history_howmany*60;
220     else if (config.sql_history == COUNT_HOURLY) idata->timeslot = config.sql_history_howmany*3600;
221     else if (config.sql_history == COUNT_DAILY) idata->timeslot = config.sql_history_howmany*86400;
222     else if (config.sql_history == COUNT_WEEKLY) idata->timeslot = config.sql_history_howmany*86400*7;
223     else if (config.sql_history == COUNT_MONTHLY) {
224       idata->basetime = roundoff_time(idata->basetime, "d"); /* resetting day of month */
225       idata->timeslot = calc_monthly_timeslot(idata->basetime, config.sql_history_howmany, ADD);
226     }
227 
228     /* round off stuff */
229     t = roundoff_time(idata->basetime, config.sql_history_roundoff);
230 
231     while ((t+idata->timeslot) < idata->basetime) {
232       t += idata->timeslot;
233       if (config.sql_history == COUNT_MONTHLY) idata->timeslot = calc_monthly_timeslot(t, config.sql_history_howmany, ADD);
234     }
235 
236     if (config.sql_history_offset) {
237       if (config.sql_history_offset >= idata->timeslot) {
238 	Log(LOG_ERR, "ERROR ( %s/%s ): History offset (ie. sql_history_offset) must be < history (ie. sql_history).\n", config.name, config.type);
239 	exit_gracefully(1);
240       }
241 
242       t = t - (idata->timeslot + config.sql_history_offset);
243     }
244 
245     idata->basetime = t;
246     glob_basetime = idata->basetime;
247     idata->new_basetime = idata->basetime;
248     glob_new_basetime = idata->basetime;
249     glob_timeslot = idata->timeslot;
250     idata->committed_basetime = 0;
251     glob_committed_basetime = 0;
252   }
253 }
254 
255 /* NOTE: sql triggers time init: deadline; if a trigger exec is specified but
256    no time is supplied, use 'sql_refresh_time' as interval; this will result
257    in a trigger being executed each time data is purged into the DB */
sql_init_triggers(time_t now,struct insert_data * idata)258 void sql_init_triggers(time_t now, struct insert_data *idata)
259 {
260   time_t t, deadline;
261 
262   if (config.sql_trigger_exec) {
263     deadline = now;
264 
265     if (config.sql_trigger_time == COUNT_MINUTELY) idata->t_timeslot = config.sql_trigger_time_howmany*60;
266     else if (config.sql_trigger_time == COUNT_HOURLY) idata->t_timeslot = config.sql_trigger_time_howmany*3600;
267     else if (config.sql_trigger_time == COUNT_DAILY) idata->t_timeslot = config.sql_trigger_time_howmany*86400;
268     else if (config.sql_trigger_time == COUNT_WEEKLY) idata->t_timeslot = config.sql_trigger_time_howmany*86400*7;
269     else if (config.sql_trigger_time == COUNT_MONTHLY) {
270       deadline = roundoff_time(deadline, "d"); /* resetting day of month */
271       idata->t_timeslot = calc_monthly_timeslot(deadline, config.sql_trigger_time_howmany, ADD);
272     }
273     else idata->t_timeslot = config.sql_refresh_time;
274 
275     /* round off stuff */
276     t = roundoff_time(deadline, config.sql_history_roundoff);
277     while ((t+idata->t_timeslot) < deadline) {
278       t += idata->t_timeslot;
279       if (config.sql_trigger_time == COUNT_MONTHLY)
280 	idata->t_timeslot = calc_monthly_timeslot(t, config.sql_trigger_time_howmany, ADD);
281     }
282     idata->triggertime = (t + config.sql_startup_delay);
283 
284     /* adding a trailer timeslot: it's a deadline not a basetime */
285     idata->triggertime += idata->t_timeslot;
286     if (config.sql_trigger_time == COUNT_MONTHLY)
287       idata->t_timeslot = calc_monthly_timeslot(t, config.sql_trigger_time_howmany, ADD);
288   }
289 }
290 
sql_init_refresh_deadline(time_t * rd)291 void sql_init_refresh_deadline(time_t *rd)
292 {
293   time_t t;
294 
295   t = roundoff_time(*rd, config.sql_history_roundoff);
296   while ((t+config.sql_refresh_time) < *rd) t += config.sql_refresh_time;
297   *rd = t;
298   *rd += (config.sql_refresh_time+config.sql_startup_delay); /* it's a deadline not a basetime */
299 }
300 
sql_link_backend_descriptors(struct BE_descs * registry,struct DBdesc * p,struct DBdesc * b)301 void sql_link_backend_descriptors(struct BE_descs *registry, struct DBdesc *p, struct DBdesc *b)
302 {
303   memset(registry, 0, sizeof(struct BE_descs));
304   memset(p, 0, sizeof(struct DBdesc));
305   memset(b, 0, sizeof(struct DBdesc));
306 
307   registry->p = p;
308   registry->b = b;
309   registry->p->type = BE_TYPE_PRIMARY;
310   registry->b->type = BE_TYPE_BACKUP;
311 
312   if (*sqlfunc_cbr.create_backend) {
313     (*sqlfunc_cbr.create_backend)(registry->p);
314     (*sqlfunc_cbr.create_backend)(registry->b);
315   }
316 }
317 
sql_cache_modulo(struct primitives_ptrs * prim_ptrs,struct insert_data * idata)318 void sql_cache_modulo(struct primitives_ptrs *prim_ptrs, struct insert_data *idata)
319 {
320   struct pkt_data *pdata = prim_ptrs->data;
321   struct pkt_primitives *srcdst = &pdata->primitives;
322   struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp;
323   struct pkt_nat_primitives *pnat = prim_ptrs->pnat;
324   struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls;
325   struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun;
326   u_char *pcust = prim_ptrs->pcust;
327   struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen;
328 
329   idata->hash = cache_crc32((unsigned char *)srcdst, pp_size);
330   if (pbgp) idata->hash ^= cache_crc32((unsigned char *)pbgp, pb_size);
331   if (pnat) idata->hash ^= cache_crc32((unsigned char *)pnat, pn_size);
332   if (pmpls) idata->hash ^= cache_crc32((unsigned char *)pmpls, pm_size);
333   if (ptun) idata->hash ^= cache_crc32((unsigned char *)ptun, pt_size);
334   if (pcust) idata->hash ^= cache_crc32((unsigned char *)pcust, pc_size);
335   if (pvlen) idata->hash ^= cache_crc32((unsigned char *)pvlen, (PvhdrSz + pvlen->tot_len));
336 
337   idata->modulo = idata->hash % config.sql_cache_entries;
338 }
339 
sql_cache_flush(struct db_cache * queue[],int index,struct insert_data * idata,int exiting)340 int sql_cache_flush(struct db_cache *queue[], int index, struct insert_data *idata, int exiting)
341 {
342   int j, delay = 0, new_basetime = FALSE;
343 
344   /* We are seeking how many time-bins data has to be delayed by; residual
345      time is taken into account by scanner deadlines (sql_refresh_time) */
346   if (config.sql_startup_delay) {
347     if (idata->timeslot) delay = config.sql_startup_delay/idata->timeslot;
348     delay = delay*idata->timeslot;
349   }
350 
351   /* check-pointing: we record last committed time-bin; part of this is
352      checking whether basetime was moved forward yet (as this is not for
353      sure). */
354   if (idata->new_basetime && idata->new_basetime < idata->basetime &&
355       idata->new_basetime > idata->committed_basetime) {
356     new_basetime = TRUE;
357     idata->committed_basetime = idata->new_basetime;
358   }
359   else idata->committed_basetime = idata->basetime;
360 
361   if (!exiting) {
362     for (j = 0, pqq_ptr = 0; j < index; j++) {
363       if (new_basetime && queue[j]->basetime+delay >= idata->basetime) {
364         sql_pending_queries_queue[pqq_ptr] = queue[j];
365         pqq_ptr++;
366       }
367       else if (!new_basetime && queue[j]->basetime+delay > idata->basetime) {
368         sql_pending_queries_queue[pqq_ptr] = queue[j];
369         pqq_ptr++;
370       }
371       else queue[j]->valid = SQL_CACHE_COMMITTED;
372     }
373   }
374   /* If exiting instead .. */
375   else {
376     for (j = 0; j < index; j++) queue[j]->valid = SQL_CACHE_COMMITTED;
377   }
378 
379   return index;
380 }
381 
sql_cache_flush_pending(struct db_cache * queue[],int index,struct insert_data * idata)382 void sql_cache_flush_pending(struct db_cache *queue[], int index, struct insert_data *idata)
383 {
384   struct db_cache *Cursor, *auxCursor, *PendingElem, SavedCursor;
385   int j;
386 
387   /* Not everything was purged, let's sort out the SQL cache buckets involved into that */
388   if (index) {
389     for (j = 0; j < index; j++) {
390       /* Select next element on the pending queue */
391       PendingElem = queue[j];
392 
393       /* Go to the first element in the bucket */
394       for (Cursor = PendingElem, auxCursor = NULL; Cursor; auxCursor = Cursor, Cursor = Cursor->prev);
395 
396       /* Check whether we are already first in the bucket */
397       if (auxCursor != PendingElem) {
398 	Cursor = auxCursor;
399 
400         for (; Cursor && Cursor != PendingElem && Cursor->valid == SQL_CACHE_INUSE; Cursor = Cursor->next);
401         /* Check whether a) the whole bucket chain is currently in use
402 	   or b) we came across the current pending element: meaning no
403 	   free positions are available in the chain, ahead of it */
404         if (Cursor && Cursor != PendingElem) {
405           /* Check whether we have to replace the first element in the bucket */
406           if (!Cursor->prev) {
407             memcpy(&SavedCursor, Cursor, sizeof(struct db_cache));
408             memcpy(Cursor, PendingElem, sizeof(struct db_cache));
409             Cursor->prev = NULL;
410             Cursor->next = SavedCursor.next;
411             Cursor->chained = FALSE;
412             Cursor->lru_prev = NULL;
413             Cursor->lru_next = NULL;
414 
415 	    /* unlinking pointers from PendingElem to prevent free-up (linked by Cursor) */
416 	    PendingElem->pbgp = NULL;
417 	    PendingElem->pnat = NULL;
418 	    PendingElem->pmpls = NULL;
419 	    PendingElem->ptun = NULL;
420 	    PendingElem->pcust = NULL;
421 	    PendingElem->pvlen = NULL;
422 	    PendingElem->stitch = NULL;
423             RetireElem(PendingElem);
424 
425             queue[j] = Cursor;
426 
427 	    /* freeing stale allocations */
428 	    if (SavedCursor.pbgp) free(SavedCursor.pbgp);
429 	    if (SavedCursor.pnat) free(SavedCursor.pnat);
430 	    if (SavedCursor.pmpls) free(SavedCursor.pmpls);
431 	    if (SavedCursor.ptun) free(SavedCursor.ptun);
432 	    if (SavedCursor.pcust) free(SavedCursor.pcust);
433 	    if (SavedCursor.pvlen) free(SavedCursor.pvlen);
434 	    if (SavedCursor.stitch) free(SavedCursor.stitch);
435           }
436           /* We found at least one Cursor->valid == SQL_CACHE_INUSE */
437           else SwapChainedElems(PendingElem, Cursor);
438         }
439       }
440     }
441   }
442 }
443 
sql_cache_handle_flush_event(struct insert_data * idata,time_t * refresh_deadline,struct ports_table * pt)444 void sql_cache_handle_flush_event(struct insert_data *idata, time_t *refresh_deadline, struct ports_table *pt)
445 {
446   int ret;
447 
448   dump_writers_count();
449   if (dump_writers_get_flags() != CHLD_ALERT) {
450     switch (ret = fork()) {
451     case 0: /* Child */
452       /* we have to ignore signals to avoid loops: because we are already forked */
453       signal(SIGINT, SIG_IGN);
454       signal(SIGHUP, SIG_IGN);
455       pm_setproctitle("%s %s [%s]", config.type, "Plugin -- DB Writer", config.name);
456       config.is_forked = TRUE;
457 
458       if (qq_ptr) {
459         if (dump_writers_get_flags() == CHLD_WARNING) sql_db_fail(&p);
460         if (!strcmp(config.type, "mysql"))
461           (*sqlfunc_cbr.connect)(&p, config.sql_host);
462         else
463           (*sqlfunc_cbr.connect)(&p, NULL);
464       }
465 
466       /* qq_ptr check inside purge function along with a Log() call */
467       (*sqlfunc_cbr.purge)(sql_queries_queue, qq_ptr, idata);
468 
469       if (qq_ptr) (*sqlfunc_cbr.close)(&bed);
470 
471       if (config.sql_trigger_exec) {
472         if (idata->now > idata->triggertime) sql_trigger_exec(config.sql_trigger_exec);
473       }
474 
475       exit_gracefully(0);
476     default: /* Parent */
477       if (ret == -1) Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork DB writer: %s\n", config.name, config.type, strerror(errno));
478       else dump_writers_add(ret);
479 
480       break;
481     }
482   }
483   else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active());
484 
485   if (pqq_ptr) sql_cache_flush_pending(sql_pending_queries_queue, pqq_ptr, idata);
486   gettimeofday(&idata->flushtime, NULL);
487   while (idata->now > *refresh_deadline)
488     *refresh_deadline += config.sql_refresh_time;
489   while (idata->now > idata->triggertime && idata->t_timeslot > 0) {
490     idata->triggertime  += idata->t_timeslot;
491     if (config.sql_trigger_time == COUNT_MONTHLY)
492       idata->t_timeslot = calc_monthly_timeslot(idata->triggertime, config.sql_trigger_time_howmany, ADD);
493   }
494 
495   idata->new_basetime = FALSE;
496   glob_new_basetime = FALSE;
497   qq_ptr = pqq_ptr;
498   memcpy(sql_queries_queue, sql_pending_queries_queue, qq_ptr*sizeof(struct db_cache *));
499 
500   if (reload_map) {
501     load_networks(config.networks_file, &nt, &nc);
502     load_ports(config.ports_file, pt);
503     reload_map = FALSE;
504   }
505 
506   if (reload_log) {
507     reload_logs();
508     reload_log = FALSE;
509   }
510 }
511 
sql_cache_search(struct primitives_ptrs * prim_ptrs,time_t basetime)512 struct db_cache *sql_cache_search(struct primitives_ptrs *prim_ptrs, time_t basetime)
513 {
514   struct pkt_data *pdata = prim_ptrs->data;
515   struct pkt_primitives *data = &pdata->primitives;
516   struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp;
517   struct pkt_nat_primitives *pnat = prim_ptrs->pnat;
518   struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls;
519   struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun;
520   u_char *pcust = prim_ptrs->pcust;
521   struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen;
522   struct db_cache *Cursor;
523   struct insert_data idata;
524   int res_data = TRUE, res_bgp = TRUE, res_nat = TRUE, res_mpls = TRUE, res_tun = TRUE;
525   int res_cust = TRUE, res_vlen = TRUE;
526 
527   sql_cache_modulo(prim_ptrs, &idata);
528 
529   Cursor = &sql_cache[idata.modulo];
530 
531   start:
532   if (idata.hash != Cursor->signature) {
533     if (Cursor->valid == SQL_CACHE_INUSE) {
534       follow_chain:
535       if (Cursor->next) {
536         Cursor = Cursor->next;
537         goto start;
538       }
539     }
540   }
541   else {
542     if (Cursor->valid == SQL_CACHE_INUSE) {
543       /* checks: pkt_primitives and pkt_bgp_primitives */
544       res_data = memcmp(&Cursor->primitives, data, sizeof(struct pkt_primitives));
545 
546       if (pbgp && Cursor->pbgp) {
547         res_bgp = memcmp(Cursor->pbgp, pbgp, sizeof(struct pkt_bgp_primitives));
548       }
549       else res_bgp = FALSE;
550 
551       if (pnat && Cursor->pnat) {
552         res_nat = memcmp(Cursor->pnat, pnat, sizeof(struct pkt_nat_primitives));
553       }
554       else res_nat = FALSE;
555 
556       if (pmpls && Cursor->pmpls) {
557         res_mpls = memcmp(Cursor->pmpls, pmpls, sizeof(struct pkt_mpls_primitives));
558       }
559       else res_mpls = FALSE;
560 
561       if (ptun && Cursor->ptun) {
562         res_tun = memcmp(Cursor->ptun, ptun, sizeof(struct pkt_tunnel_primitives));
563       }
564       else res_tun = FALSE;
565 
566       if (pcust && Cursor->pcust) {
567         res_cust = memcmp(Cursor->pcust, pcust, config.cpptrs.len);
568       }
569       else res_cust = FALSE;
570 
571       if (pvlen && Cursor->pvlen) {
572         res_vlen = vlen_prims_cmp(Cursor->pvlen, pvlen);
573       }
574       else res_vlen = FALSE;
575 
576       if (!res_data && !res_bgp && !res_nat && !res_mpls && !res_tun && !res_cust && !res_vlen) {
577         /* additional check: time */
578         if ((Cursor->basetime < basetime) && config.sql_history)
579           goto follow_chain;
580         else return Cursor;
581       }
582       else goto follow_chain;
583     }
584   }
585 
586   return NULL;
587 }
588 
sql_cache_insert(struct primitives_ptrs * prim_ptrs,struct insert_data * idata)589 void sql_cache_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata)
590 {
591   struct pkt_data *data = prim_ptrs->data;
592   struct pkt_bgp_primitives *pbgp = prim_ptrs->pbgp;
593   struct pkt_nat_primitives *pnat = prim_ptrs->pnat;
594   struct pkt_mpls_primitives *pmpls = prim_ptrs->pmpls;
595   struct pkt_tunnel_primitives *ptun = prim_ptrs->ptun;
596   u_char *pcust = prim_ptrs->pcust;
597   struct pkt_vlen_hdr_primitives *pvlen = prim_ptrs->pvlen;
598   time_t basetime = idata->basetime, timeslot = idata->timeslot;
599   struct pkt_primitives *srcdst = &data->primitives;
600   struct db_cache *Cursor, *newElem, *SafePtr = NULL, *staleElem = NULL;
601   int ret, insert_status;
602 
603   /* pro_rating vars */
604   int time_delta = 0, time_total = 0;
605   pm_counter_t tot_bytes = 0, tot_packets = 0, tot_flows = 0;
606 
607   /* housekeeping to start */
608   if (lru_head.lru_next && ((idata->now-lru_head.lru_next->lru_tag) > RETIRE_M*config.sql_refresh_time)) {
609     /* if element status is SQL_CACHE_INUSE it can't be retired because sits on the queue */
610     if (lru_head.lru_next->valid != SQL_CACHE_INUSE) RetireElem(lru_head.lru_next);
611   }
612 
613   tot_bytes = data->pkt_len;
614   tot_packets = data->pkt_num;
615   tot_flows = data->flo_num;
616 
617   if (data->time_start.tv_sec && config.sql_history) {
618     if (config.sql_history != COUNT_MONTHLY) {
619       int residual;
620 
621       if (basetime > data->time_start.tv_sec) {
622 	residual = timeslot - ((basetime - data->time_start.tv_sec) % timeslot);
623       }
624       else {
625 	residual = ((data->time_start.tv_sec - basetime) % timeslot);
626       }
627 
628       basetime = data->time_start.tv_sec - residual;
629     }
630     else {
631       while (basetime > data->time_start.tv_sec) {
632         timeslot = calc_monthly_timeslot(basetime, config.sql_history_howmany, SUB);
633         basetime -= timeslot;
634       }
635       while ((basetime + timeslot) < data->time_start.tv_sec) {
636         basetime += timeslot;
637         timeslot = calc_monthly_timeslot(basetime, config.sql_history_howmany, ADD);
638       }
639     }
640   }
641 
642   new_timeslot:
643   /* pro_rating, if needed */
644   if (config.acct_type == ACCT_NF && config.nfacctd_pro_rating && config.sql_history) {
645     if (data->time_end.tv_sec > data->time_start.tv_sec) {
646       time_total = data->time_end.tv_sec - data->time_start.tv_sec;
647       time_delta = MIN(data->time_end.tv_sec, basetime + timeslot) - MAX(data->time_start.tv_sec, basetime);
648 
649       if (time_delta > 0 && time_total > 0 && time_delta < time_total) {
650         float ratio = (float) time_total / (float) time_delta;
651 
652         if (tot_bytes) data->pkt_len = MAX((float)tot_bytes / ratio, 1);
653         if (tot_packets) data->pkt_num = MAX((float)tot_packets / ratio, 1);
654         if (tot_flows) data->flo_num = MAX((float)tot_flows / ratio, 1);
655       }
656     }
657   }
658 
659   /* We are classifing packets. We have a non-zero bytes accumulator (ba)
660      and a non-zero class. Before accounting ba to this class, we have to
661      remove ba from class zero. */
662   if (config.what_to_count & COUNT_CLASS && data->cst.ba && data->primitives.class) {
663     pm_class_t lclass = data->primitives.class;
664 
665     data->primitives.class = 0;
666     Cursor = sql_cache_search(prim_ptrs, basetime);
667     data->primitives.class = lclass;
668 
669     /* We can assign the flow to a new class only if we are able to subtract
670        the accumulator from the zero-class. If this is not the case, we will
671        discard the accumulators. The assumption is that accumulators are not
672        retroactive */
673 
674     if (Cursor) {
675       if (timeval_cmp(&data->cst.stamp, &idata->flushtime) >= 0) {
676         Cursor->bytes_counter -= MIN(Cursor->bytes_counter, data->cst.ba);
677         Cursor->packet_counter -= MIN(Cursor->packet_counter, data->cst.pa);
678         Cursor->flows_counter -= MIN(Cursor->flows_counter, data->cst.fa);
679       }
680       else memset(&data->cst, 0, CSSz);
681     }
682     else memset(&data->cst, 0, CSSz);
683   }
684 
685   sql_cache_modulo(prim_ptrs, idata);
686   Cursor = &sql_cache[idata->modulo];
687 
688   start:
689   insert_status = SQL_INSERT_INSERT;
690 
691   if (idata->hash != Cursor->signature) {
692     if (Cursor->valid == SQL_CACHE_INUSE) {
693       follow_chain:
694       if (Cursor->next) {
695         Cursor = Cursor->next;
696         goto start;
697       }
698       else {
699         if (lru_head.lru_next && lru_head.lru_next->valid != SQL_CACHE_INUSE &&
700 	    ((idata->now-lru_head.lru_next->lru_tag) > STALE_M*config.sql_refresh_time)) {
701           newElem = lru_head.lru_next;
702 	  /* if (newElem != Cursor) */
703 	  /* check removed: Cursor must be SQL_CACHE_INUSE; newElem must be not SQL_CACHE_INUSE */
704           ReBuildChain(Cursor, newElem);
705           Cursor = newElem;
706           /* we have successfully reused a stale element */
707         }
708         else {
709           newElem = (struct db_cache *) malloc(sizeof(struct db_cache));
710           if (newElem) {
711             memset(newElem, 0, sizeof(struct db_cache));
712             BuildChain(Cursor, newElem);
713             Cursor = newElem;
714             /* creating a new element */
715           }
716           else insert_status = SQL_INSERT_SAFE_ACTION; /* we should have finished memory */
717         }
718       }
719     }
720     /* we found a no more valid entry; let's insert here our data */
721   }
722   else {
723     if (Cursor->valid == SQL_CACHE_INUSE) {
724       int res_data = TRUE, res_bgp = TRUE, res_nat = TRUE, res_mpls = TRUE, res_tun = TRUE;
725       int res_cust = TRUE, res_vlen = TRUE;
726 
727       /* checks: pkt_primitives and pkt_bgp_primitives */
728       res_data = memcmp(&Cursor->primitives, srcdst, sizeof(struct pkt_primitives));
729 
730       if (pbgp && Cursor->pbgp) {
731         res_bgp = memcmp(Cursor->pbgp, pbgp, sizeof(struct pkt_bgp_primitives));
732       }
733       else res_bgp = FALSE;
734 
735       if (pnat && Cursor->pnat) {
736         res_nat = memcmp(Cursor->pnat, pnat, sizeof(struct pkt_nat_primitives));
737       }
738       else res_nat = FALSE;
739 
740       if (pmpls && Cursor->pmpls) {
741         res_mpls = memcmp(Cursor->pmpls, pmpls, sizeof(struct pkt_mpls_primitives));
742       }
743       else res_mpls = FALSE;
744 
745       if (ptun && Cursor->ptun) {
746         res_tun = memcmp(Cursor->ptun, ptun, sizeof(struct pkt_tunnel_primitives));
747       }
748       else res_tun = FALSE;
749 
750       if (pcust && Cursor->pcust) {
751         res_cust = memcmp(Cursor->pcust, pcust, config.cpptrs.len);
752       }
753       else res_cust = FALSE;
754 
755       if (pvlen && Cursor->pvlen) {
756         res_vlen = vlen_prims_cmp(Cursor->pvlen, pvlen);
757       }
758       else res_vlen = FALSE;
759 
760       if (!res_data && !res_bgp && !res_nat && !res_mpls && !res_tun && !res_cust && !res_vlen) {
761         /* additional check: time */
762         if ((Cursor->basetime != basetime) && config.sql_history) goto follow_chain;
763 
764         /* additional check: bytes counter overflow */
765         if (Cursor->bytes_counter > CACHE_THRESHOLD) goto follow_chain;
766 
767 	/* All is good: let's update the matching entry */
768         insert_status = SQL_INSERT_UPDATE;
769       }
770       else goto follow_chain;
771     }
772   }
773 
774   if (insert_status == SQL_INSERT_INSERT) {
775     if (qq_ptr < qq_size) {
776       sql_queries_queue[qq_ptr] = Cursor;
777       qq_ptr++;
778     }
779     else SafePtr = Cursor;
780 
781     /* we add the new entry in the cache */
782     memcpy(&Cursor->primitives, srcdst, sizeof(struct pkt_primitives));
783 
784     if (pbgp) {
785       if (!Cursor->pbgp) {
786         Cursor->pbgp = (struct pkt_bgp_primitives *) malloc(pb_size);
787         if (!Cursor->pbgp) goto safe_action;
788       }
789       memcpy(Cursor->pbgp, pbgp, pb_size);
790     }
791     else {
792       if (Cursor->pbgp) free(Cursor->pbgp);
793       Cursor->pbgp = NULL;
794     }
795 
796     if (pnat) {
797       if (!Cursor->pnat) {
798         Cursor->pnat = (struct pkt_nat_primitives *) malloc(pn_size);
799         if (!Cursor->pnat) goto safe_action;
800       }
801       memcpy(Cursor->pnat, pnat, pn_size);
802     }
803     else {
804       if (Cursor->pnat) free(Cursor->pnat);
805       Cursor->pnat = NULL;
806     }
807 
808     if (pmpls) {
809       if (!Cursor->pmpls) {
810         Cursor->pmpls = (struct pkt_mpls_primitives *) malloc(pm_size);
811         if (!Cursor->pmpls) goto safe_action;
812       }
813       memcpy(Cursor->pmpls, pmpls, pm_size);
814     }
815     else {
816       if (Cursor->pmpls) free(Cursor->pmpls);
817       Cursor->pmpls = NULL;
818     }
819 
820     if (ptun) {
821       if (!Cursor->ptun) {
822         Cursor->ptun = (struct pkt_tunnel_primitives *) malloc(pt_size);
823         if (!Cursor->ptun) goto safe_action;
824       }
825       memcpy(Cursor->ptun, ptun, pt_size);
826     }
827     else {
828       if (Cursor->ptun) free(Cursor->ptun);
829       Cursor->ptun = NULL;
830     }
831 
832     if (pcust) {
833       if (!Cursor->pcust) {
834         Cursor->pcust = malloc(pc_size);
835         if (!Cursor->pcust) goto safe_action;
836       }
837       memcpy(Cursor->pcust, pcust, pc_size);
838     }
839     else {
840       if (Cursor->pcust) free(Cursor->pcust);
841       Cursor->pcust = NULL;
842     }
843 
844     /* if we have a pvlen from before let's free it
845        up due to the vlen nature of the memory area */
846     if (Cursor->pvlen) {
847       vlen_prims_free(Cursor->pvlen);
848       Cursor->pvlen = NULL;
849     }
850 
851     if (pvlen) {
852       Cursor->pvlen = (struct pkt_vlen_hdr_primitives *) vlen_prims_copy(pvlen);
853       if (!Cursor->pvlen) goto safe_action;
854     }
855 
856     Cursor->packet_counter = data->pkt_num;
857     Cursor->flows_counter = data->flo_num;
858     Cursor->bytes_counter = data->pkt_len;
859     Cursor->flow_type = data->flow_type;
860     Cursor->tcp_flags = data->tcp_flags;
861 
862     if (config.what_to_count & COUNT_CLASS) {
863       Cursor->bytes_counter += data->cst.ba;
864       Cursor->packet_counter += data->cst.pa;
865       Cursor->flows_counter += data->cst.fa;
866       Cursor->tentatives = data->cst.tentatives;
867     }
868 
869     if (config.nfacctd_stitching) {
870       if (!Cursor->stitch) Cursor->stitch = (struct pkt_stitching *) malloc(sizeof(struct pkt_stitching));
871       if (Cursor->stitch) {
872         if (data->time_start.tv_sec) {
873           memcpy(&Cursor->stitch->timestamp_min, &data->time_start, sizeof(struct timeval));
874         }
875         else {
876           Cursor->stitch->timestamp_min.tv_sec = idata->now;
877           Cursor->stitch->timestamp_min.tv_usec = 0;
878         }
879 
880         if (data->time_end.tv_sec) {
881           memcpy(&Cursor->stitch->timestamp_max, &data->time_end, sizeof(struct timeval));
882         }
883         else {
884           Cursor->stitch->timestamp_max.tv_sec = idata->now;
885           Cursor->stitch->timestamp_max.tv_usec = 0;
886         }
887       }
888       else Log(LOG_WARNING, "WARN ( %s/%s ): Finished memory for flow stitching.\n", config.name, config.type);
889     }
890     else assert(!Cursor->stitch);
891 
892     Cursor->valid = SQL_CACHE_INUSE;
893     Cursor->basetime = basetime;
894     Cursor->start_tag = idata->now;
895     Cursor->lru_tag = idata->now;
896     Cursor->signature = idata->hash;
897     /* We are not so fancy to reuse elements which have
898        not been malloc()'d before */
899     if (Cursor->chained) AddToLRUTail(Cursor);
900     if (SafePtr) goto safe_action;
901     if (staleElem) SwapChainedElems(Cursor, staleElem);
902     insert_status = SQL_INSERT_PRO_RATING;
903   }
904 
905   if (insert_status == SQL_INSERT_UPDATE) {
906     Cursor->packet_counter += data->pkt_num;
907     Cursor->flows_counter += data->flo_num;
908     Cursor->bytes_counter += data->pkt_len;
909     Cursor->flow_type = data->flow_type;
910     Cursor->tcp_flags |= data->tcp_flags;
911 
912     if (config.what_to_count & COUNT_CLASS) {
913       Cursor->bytes_counter += data->cst.ba;
914       Cursor->packet_counter += data->cst.pa;
915       Cursor->flows_counter += data->cst.fa;
916       Cursor->tentatives = data->cst.tentatives;
917     }
918 
919     if (config.nfacctd_stitching) {
920       if (Cursor->stitch) {
921         if (data->time_end.tv_sec) {
922           if (data->time_end.tv_sec > Cursor->stitch->timestamp_max.tv_sec &&
923               data->time_end.tv_usec > Cursor->stitch->timestamp_max.tv_usec)
924             memcpy(&Cursor->stitch->timestamp_max, &data->time_end, sizeof(struct timeval));
925         }
926         else {
927           Cursor->stitch->timestamp_max.tv_sec = idata->now;
928           Cursor->stitch->timestamp_max.tv_usec = 0;
929         }
930       }
931     }
932 
933     insert_status = SQL_INSERT_PRO_RATING;
934   }
935 
936   if (insert_status == SQL_INSERT_PRO_RATING) {
937     if (config.acct_type == ACCT_NF && config.nfacctd_pro_rating && config.sql_history) {
938       if ((basetime + timeslot) < data->time_end.tv_sec) {
939         basetime += timeslot;
940         goto new_timeslot;
941       }
942     }
943   }
944 
945   if (insert_status == SQL_INSERT_SAFE_ACTION) {
946     safe_action:
947 
948     Log(LOG_INFO, "INFO ( %s/%s ): Finished cache entries (ie. sql_cache_entries). Purging.\n", config.name, config.type);
949 
950     if (qq_ptr) sql_cache_flush(sql_queries_queue, qq_ptr, idata, FALSE);
951 
952     dump_writers_count();
953     if (dump_writers_get_flags() != CHLD_ALERT) {
954       switch (ret = fork()) {
955       case 0: /* Child */
956         signal(SIGINT, SIG_IGN);
957         signal(SIGHUP, SIG_IGN);
958         pm_setproctitle("%s [%s]", "SQL Plugin -- DB Writer (urgent)", config.name);
959 	config.is_forked = TRUE;
960 
961         if (qq_ptr) {
962           if (dump_writers_get_flags() == CHLD_WARNING) sql_db_fail(&p);
963           (*sqlfunc_cbr.connect)(&p, config.sql_host);
964           (*sqlfunc_cbr.purge)(sql_queries_queue, qq_ptr, idata);
965           (*sqlfunc_cbr.close)(&bed);
966         }
967 
968         exit_gracefully(0);
969       default: /* Parent */
970         if (ret == -1) Log(LOG_WARNING, "WARN ( %s/%s ): Unable to fork DB writer (urgent): %s\n", config.name, config.type, strerror(errno));
971 	else dump_writers_add(ret);
972 
973         break;
974       }
975     }
976     else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active());
977 
978     qq_ptr = pqq_ptr;
979     memcpy(sql_queries_queue, sql_pending_queries_queue, sizeof(*sql_queries_queue));
980 
981     if (SafePtr) {
982       sql_queries_queue[qq_ptr] = Cursor;
983       qq_ptr++;
984     }
985     else {
986       Cursor = &sql_cache[idata->modulo];
987       goto start;
988     }
989   }
990 }
991 
sql_sum_host_insert(struct primitives_ptrs * prim_ptrs,struct insert_data * idata)992 void sql_sum_host_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata)
993 {
994   struct pkt_data *data = prim_ptrs->data;
995   struct host_addr tmp;
996 
997   memcpy(&tmp, &data->primitives.dst_ip, HostAddrSz);
998   memset(&data->primitives.dst_ip, 0, HostAddrSz);
999   sql_cache_insert(prim_ptrs, idata);
1000   memcpy(&data->primitives.src_ip, &tmp, HostAddrSz);
1001   sql_cache_insert(prim_ptrs, idata);
1002 }
1003 
sql_sum_port_insert(struct primitives_ptrs * prim_ptrs,struct insert_data * idata)1004 void sql_sum_port_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata)
1005 {
1006   struct pkt_data *data = prim_ptrs->data;
1007   u_int16_t port;
1008 
1009   port = data->primitives.dst_port;
1010   data->primitives.dst_port = 0;
1011   sql_cache_insert(prim_ptrs, idata);
1012   data->primitives.src_port = port;
1013   sql_cache_insert(prim_ptrs, idata);
1014 }
1015 
sql_sum_as_insert(struct primitives_ptrs * prim_ptrs,struct insert_data * idata)1016 void sql_sum_as_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata)
1017 {
1018   struct pkt_data *data = prim_ptrs->data;
1019   as_t asn;
1020 
1021   asn = data->primitives.dst_as;
1022   data->primitives.dst_as = 0;
1023   sql_cache_insert(prim_ptrs, idata);
1024   data->primitives.src_as = asn;
1025   sql_cache_insert(prim_ptrs, idata);
1026 }
1027 
1028 #if defined (HAVE_L2)
sql_sum_mac_insert(struct primitives_ptrs * prim_ptrs,struct insert_data * idata)1029 void sql_sum_mac_insert(struct primitives_ptrs *prim_ptrs, struct insert_data *idata)
1030 {
1031   struct pkt_data *data = prim_ptrs->data;
1032   u_char macaddr[ETH_ADDR_LEN];
1033 
1034   memcpy(macaddr, &data->primitives.eth_dhost, ETH_ADDR_LEN);
1035   memset(data->primitives.eth_dhost, 0, ETH_ADDR_LEN);
1036   sql_cache_insert(prim_ptrs, idata);
1037   memcpy(&data->primitives.eth_shost, macaddr, ETH_ADDR_LEN);
1038   sql_cache_insert(prim_ptrs, idata);
1039 }
1040 #endif
1041 
sql_trigger_exec(char * filename)1042 int sql_trigger_exec(char *filename)
1043 {
1044   char *args[2] = { filename, NULL };
1045   int pid;
1046 
1047   switch (pid = vfork()) {
1048   case -1:
1049     return -1;
1050   case 0:
1051     execv(filename, args);
1052     _exit(0);
1053   }
1054 
1055   return 0;
1056 }
1057 
sql_db_ok(struct DBdesc * db)1058 void sql_db_ok(struct DBdesc *db)
1059 {
1060   db->fail = FALSE;
1061   db->connected = TRUE;
1062 }
1063 
sql_db_fail(struct DBdesc * db)1064 void sql_db_fail(struct DBdesc *db)
1065 {
1066   db->fail = TRUE;
1067   db->connected = FALSE;
1068 }
1069 
sql_db_errmsg(struct DBdesc * db)1070 void sql_db_errmsg(struct DBdesc *db)
1071 {
1072   if (db->type == BE_TYPE_PRIMARY)
1073     Log(LOG_ERR, "ERROR ( %s/%s ): PRIMARY '%s' backend trouble.\n", config.name, config.type, config.type);
1074   else if (db->type == BE_TYPE_BACKUP)
1075     Log(LOG_ERR, "ERROR ( %s/%s ): BACKUP '%s' backend trouble.\n", config.name, config.type, config.type);
1076 
1077   if (db->errmsg) Log(LOG_ERR, "ERROR ( %s/%s ): The SQL server says: %s\n", config.name, config.type, db->errmsg);
1078 }
1079 
sql_db_warnmsg(struct DBdesc * db)1080 void sql_db_warnmsg(struct DBdesc *db)
1081 {
1082   if (db->errmsg) Log(LOG_WARNING, "WARN ( %s/%s ): The SQL server says: %s\n", config.name, config.type, db->errmsg);
1083 }
1084 
sql_exit_gracefully(int signum)1085 void sql_exit_gracefully(int signum)
1086 {
1087   struct insert_data idata;
1088 
1089   signal(SIGINT, SIG_IGN);
1090   signal(SIGHUP, SIG_IGN);
1091 
1092   Log(LOG_DEBUG, "( %s/%s ) *** Purging queries queue ***\n", config.name, config.type);
1093   if (config.syslog) closelog();
1094 
1095   memset(&idata, 0, sizeof(idata));
1096   idata.num_primitives = glob_num_primitives;
1097   idata.now = time(NULL);
1098   idata.basetime = glob_basetime;
1099   idata.dyn_table = glob_dyn_table;
1100   idata.dyn_table_time_only = glob_dyn_table_time_only;
1101   idata.new_basetime = glob_new_basetime;
1102   idata.timeslot = glob_timeslot;
1103   idata.committed_basetime = glob_committed_basetime;
1104   if (config.sql_backup_host) idata.recover = TRUE;
1105   if (config.sql_locking_style) idata.locks = sql_select_locking_style(config.sql_locking_style);
1106 
1107   sql_cache_flush(sql_queries_queue, qq_ptr, &idata, TRUE);
1108 
1109   dump_writers_count();
1110   if (dump_writers_get_flags() != CHLD_ALERT) {
1111     if (dump_writers_get_flags() == CHLD_WARNING) sql_db_fail(&p);
1112     (*sqlfunc_cbr.connect)(&p, config.sql_host);
1113     (*sqlfunc_cbr.purge)(sql_queries_queue, qq_ptr, &idata);
1114     (*sqlfunc_cbr.close)(&bed);
1115   }
1116   else Log(LOG_WARNING, "WARN ( %s/%s ): Maximum number of writer processes reached (%d).\n", config.name, config.type, dump_writers_get_active());
1117 
1118   if (config.pidfile) remove_pid_file(config.pidfile);
1119 
1120   exit_gracefully(0);
1121 }
1122 
sql_evaluate_primitives(int primitive)1123 int sql_evaluate_primitives(int primitive)
1124 {
1125   pm_cfgreg_t what_to_count = 0, what_to_count_2 = 0, fakes = 0;
1126   short int assume_custom_table = FALSE;
1127   char *insert_clause_start_ptr = insert_clause + strlen(insert_clause);
1128   char default_delim[] = ",", delim_buf[SRVBUFLEN];
1129 
1130   /* SQL tables < v6 multiplex IP addresses and AS numbers on the same field, thus are
1131      unable to use both them for a same direction (ie. src, dst). Tables v6 break such
1132      assumption */
1133   if (((config.what_to_count & (COUNT_SRC_HOST|COUNT_SRC_NET|COUNT_SUM_HOST|COUNT_SUM_NET) &&
1134      config.what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) || (config.what_to_count & COUNT_DST_AS
1135      && config.what_to_count & (COUNT_DST_HOST|COUNT_DST_NET))) && config.sql_table_version < 6) {
1136     Log(LOG_ERR, "ERROR ( %s/%s ): SQL tables < v6 are unable to mix IP addresses and AS numbers (ie. src_ip, src_as).\n", config.name, config.type);
1137     exit_gracefully(1);
1138   }
1139 
1140   if (config.sql_optimize_clauses) {
1141     what_to_count = config.what_to_count;
1142     what_to_count_2 = config.what_to_count_2;
1143     assume_custom_table = TRUE;
1144   }
1145   else {
1146     /* It is being requested to avoid SQL query optmization;
1147        then we will build an all-true bitmap */
1148     if (config.what_to_count & COUNT_SRC_MAC) what_to_count |= COUNT_SRC_MAC;
1149     else if (config.what_to_count & COUNT_SUM_MAC) what_to_count |= COUNT_SUM_MAC;
1150     else fakes |= FAKE_SRC_MAC;
1151 
1152     if (config.what_to_count & COUNT_DST_MAC) what_to_count |= COUNT_DST_MAC;
1153     else fakes |= FAKE_DST_MAC;
1154 
1155     if (config.what_to_count & COUNT_SUM_PORT) what_to_count |= COUNT_SUM_PORT;
1156 
1157     what_to_count |= COUNT_SRC_PORT|COUNT_DST_PORT|COUNT_TCPFLAGS|COUNT_IP_PROTO|COUNT_CLASS|COUNT_VLAN|COUNT_IP_TOS;
1158 
1159     if (config.what_to_count & COUNT_SRC_HOST) what_to_count |= COUNT_SRC_HOST;
1160     else if (config.what_to_count & COUNT_SUM_HOST) what_to_count |= COUNT_SUM_HOST;
1161     else if (config.what_to_count & COUNT_SUM_NET) what_to_count |= COUNT_SUM_NET;
1162     else fakes |= FAKE_SRC_HOST;
1163 
1164     if (config.what_to_count & COUNT_SRC_NET) what_to_count |= COUNT_SRC_NET;
1165 
1166     if (config.what_to_count & COUNT_DST_HOST) what_to_count |= COUNT_DST_HOST;
1167     else fakes |= FAKE_DST_HOST;
1168 
1169     if (config.what_to_count & COUNT_DST_NET) what_to_count |= COUNT_DST_NET;
1170 
1171     if (config.what_to_count & COUNT_AS_PATH) what_to_count |= COUNT_AS_PATH;
1172     else fakes |= FAKE_AS_PATH;
1173 
1174     if (config.what_to_count & COUNT_SRC_AS_PATH) what_to_count |= COUNT_SRC_AS_PATH;
1175 
1176     if (config.what_to_count & COUNT_STD_COMM) what_to_count |= COUNT_STD_COMM;
1177     else if (config.what_to_count & COUNT_EXT_COMM) what_to_count |= COUNT_EXT_COMM;
1178     else fakes |= FAKE_COMMS;
1179 
1180     if (config.what_to_count & COUNT_SRC_STD_COMM) what_to_count |= COUNT_SRC_STD_COMM;
1181     else if (config.what_to_count & COUNT_SRC_EXT_COMM) what_to_count |= COUNT_SRC_EXT_COMM;
1182 
1183     if (config.what_to_count & COUNT_PEER_SRC_AS) what_to_count |= COUNT_PEER_SRC_AS;
1184     else fakes |= FAKE_PEER_SRC_AS;
1185 
1186     if (config.what_to_count & COUNT_PEER_DST_AS) what_to_count |= COUNT_PEER_DST_AS;
1187     else fakes |= FAKE_PEER_DST_AS;
1188 
1189     if (config.what_to_count & COUNT_PEER_SRC_IP) what_to_count |= COUNT_PEER_SRC_IP;
1190     else fakes |= FAKE_PEER_SRC_IP;
1191 
1192     if (config.what_to_count & COUNT_PEER_DST_IP) what_to_count |= COUNT_PEER_DST_IP;
1193     else fakes |= FAKE_PEER_DST_IP;
1194 
1195     what_to_count |= COUNT_LOCAL_PREF|COUNT_MED;
1196 
1197     if (config.what_to_count & COUNT_SRC_LOCAL_PREF) what_to_count |= COUNT_SRC_LOCAL_PREF;
1198     if (config.what_to_count & COUNT_SRC_MED) what_to_count |= COUNT_SRC_MED;
1199 
1200     if (config.what_to_count_2 & COUNT_SRC_ROA) what_to_count_2 |= COUNT_SRC_ROA;
1201     if (config.what_to_count_2 & COUNT_DST_ROA) what_to_count_2 |= COUNT_DST_ROA;
1202 
1203     if (config.sql_table_version < 6) {
1204       if (config.what_to_count & COUNT_SRC_AS) what_to_count |= COUNT_SRC_AS;
1205       else if (config.what_to_count & COUNT_SUM_AS) what_to_count |= COUNT_SUM_AS;
1206       else fakes |= FAKE_SRC_AS;
1207     }
1208     else {
1209       what_to_count |= COUNT_SRC_AS;
1210       if (config.what_to_count & COUNT_SUM_AS) what_to_count |= COUNT_SUM_AS;
1211     }
1212 
1213     if (config.sql_table_version < 6) {
1214       if (config.what_to_count & COUNT_DST_AS) what_to_count |= COUNT_DST_AS;
1215       else fakes |= FAKE_DST_AS;
1216     }
1217     else what_to_count |= COUNT_DST_AS;
1218 
1219     if (config.sql_table_version < 6) {
1220       if (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) {
1221         if (fakes & FAKE_SRC_HOST) fakes ^= FAKE_SRC_HOST;
1222       }
1223       else {
1224         if (fakes & FAKE_SRC_AS) fakes ^= FAKE_SRC_AS;
1225       }
1226       if (what_to_count & COUNT_DST_AS) {
1227         if (fakes & FAKE_DST_HOST) fakes ^= FAKE_DST_HOST;
1228       }
1229       else {
1230         if (fakes & FAKE_DST_AS) fakes ^= FAKE_DST_AS;
1231       }
1232     }
1233 
1234     what_to_count |= COUNT_TAG;
1235 
1236     /* aggregation primitives listed below are not part of any default SQL schema; hence
1237        no matter if SQL statements optimization is enabled or not, they have to be passed
1238        on blindly */
1239     if (config.what_to_count & COUNT_TAG2) what_to_count |= COUNT_TAG2;
1240     if (config.what_to_count & COUNT_COS) what_to_count |= COUNT_COS;
1241     if (config.what_to_count & COUNT_ETHERTYPE) what_to_count |= COUNT_ETHERTYPE;
1242     if (config.what_to_count & COUNT_MPLS_VPN_RD) what_to_count |= COUNT_MPLS_VPN_RD;
1243     if (config.what_to_count & COUNT_IN_IFACE) what_to_count |= COUNT_IN_IFACE;
1244     if (config.what_to_count & COUNT_OUT_IFACE) what_to_count |= COUNT_OUT_IFACE;
1245     if (config.what_to_count & COUNT_SRC_NMASK) what_to_count |= COUNT_SRC_NMASK;
1246     if (config.what_to_count & COUNT_DST_NMASK) what_to_count |= COUNT_DST_NMASK;
1247 
1248 #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2)
1249     if (config.what_to_count_2 & COUNT_SRC_HOST_COUNTRY) what_to_count_2 |= COUNT_SRC_HOST_COUNTRY;
1250     if (config.what_to_count_2 & COUNT_DST_HOST_COUNTRY) what_to_count_2 |= COUNT_DST_HOST_COUNTRY;
1251 #endif
1252 #if defined (WITH_GEOIPV2)
1253     if (config.what_to_count_2 & COUNT_SRC_HOST_POCODE) what_to_count_2 |= COUNT_SRC_HOST_POCODE;
1254     if (config.what_to_count_2 & COUNT_DST_HOST_POCODE) what_to_count_2 |= COUNT_DST_HOST_POCODE;
1255     if (config.what_to_count_2 & COUNT_SRC_HOST_COORDS) what_to_count_2 |= COUNT_SRC_HOST_COORDS;
1256     if (config.what_to_count_2 & COUNT_DST_HOST_COORDS) what_to_count_2 |= COUNT_DST_HOST_COORDS;
1257 #endif
1258 
1259     if (config.what_to_count_2 & COUNT_SAMPLING_RATE) what_to_count_2 |= COUNT_SAMPLING_RATE;
1260 
1261     if (config.what_to_count_2 & COUNT_POST_NAT_SRC_HOST) what_to_count_2 |= COUNT_POST_NAT_SRC_HOST;
1262     if (config.what_to_count_2 & COUNT_POST_NAT_DST_HOST) what_to_count_2 |= COUNT_POST_NAT_DST_HOST;
1263     if (config.what_to_count_2 & COUNT_POST_NAT_SRC_PORT) what_to_count_2 |= COUNT_POST_NAT_SRC_PORT;
1264     if (config.what_to_count_2 & COUNT_POST_NAT_DST_PORT) what_to_count_2 |= COUNT_POST_NAT_DST_PORT;
1265     if (config.what_to_count_2 & COUNT_NAT_EVENT) what_to_count_2 |= COUNT_NAT_EVENT;
1266 
1267     if (config.what_to_count_2 & COUNT_MPLS_LABEL_TOP) what_to_count_2 |= COUNT_MPLS_LABEL_TOP;
1268     if (config.what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) what_to_count_2 |= COUNT_MPLS_LABEL_BOTTOM;
1269     if (config.what_to_count_2 & COUNT_MPLS_STACK_DEPTH) what_to_count_2 |= COUNT_MPLS_STACK_DEPTH;
1270 
1271     if (config.what_to_count_2 & COUNT_TUNNEL_SRC_MAC) what_to_count_2 |= COUNT_TUNNEL_SRC_MAC;
1272     if (config.what_to_count_2 & COUNT_TUNNEL_DST_MAC) what_to_count_2 |= COUNT_TUNNEL_DST_MAC;
1273     if (config.what_to_count_2 & COUNT_TUNNEL_SRC_HOST) what_to_count_2 |= COUNT_TUNNEL_SRC_HOST;
1274     if (config.what_to_count_2 & COUNT_TUNNEL_DST_HOST) what_to_count_2 |= COUNT_TUNNEL_DST_HOST;
1275     if (config.what_to_count_2 & COUNT_TUNNEL_IP_PROTO) what_to_count_2 |= COUNT_TUNNEL_IP_PROTO;
1276     if (config.what_to_count_2 & COUNT_TUNNEL_IP_TOS) what_to_count_2 |= COUNT_TUNNEL_IP_TOS;
1277     if (config.what_to_count_2 & COUNT_TUNNEL_SRC_PORT) what_to_count_2 |= COUNT_TUNNEL_SRC_PORT;
1278     if (config.what_to_count_2 & COUNT_TUNNEL_DST_PORT) what_to_count_2 |= COUNT_TUNNEL_DST_PORT;
1279 
1280     if (config.what_to_count_2 & COUNT_TIMESTAMP_START) what_to_count_2 |= COUNT_TIMESTAMP_START;
1281     if (config.what_to_count_2 & COUNT_TIMESTAMP_END) what_to_count_2 |= COUNT_TIMESTAMP_END;
1282     if (config.what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) what_to_count_2 |= COUNT_TIMESTAMP_ARRIVAL;
1283 
1284     if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) what_to_count_2 |= COUNT_EXPORT_PROTO_SEQNO;
1285     if (config.what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) what_to_count_2 |= COUNT_EXPORT_PROTO_VERSION;
1286     if (config.what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) what_to_count_2 |= COUNT_EXPORT_PROTO_SYSID;
1287     if (config.what_to_count_2 & COUNT_LABEL) what_to_count_2 |= COUNT_LABEL;
1288 
1289 #if defined (WITH_NDPI)
1290     if (config.what_to_count_2 & COUNT_NDPI_CLASS) what_to_count_2 |= COUNT_NDPI_CLASS;
1291 #endif
1292   }
1293 
1294   /* sorting out delimiter */
1295   if (!config.sql_delimiter || !config.sql_use_copy)
1296     snprintf(delim_buf, SRVBUFLEN, "%s ", default_delim);
1297   else
1298     snprintf(delim_buf, SRVBUFLEN, "%s ", config.sql_delimiter);
1299 
1300   /* 1st part: arranging pointers to an opaque structure and
1301      composing the static selection (WHERE) string */
1302 
1303 #if defined (HAVE_L2)
1304   if (what_to_count & (COUNT_SRC_MAC|COUNT_SUM_MAC)) {
1305     int count_it = FALSE;
1306 
1307     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1308       Log(LOG_ERR, "ERROR ( %s/%s ): MAC accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1309       exit_gracefully(1);
1310     }
1311     else count_it = TRUE;
1312 
1313     if (count_it) {
1314       if (primitive) {
1315         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1316         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1317         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1318       }
1319       strncat(insert_clause, "mac_src", SPACELEFT(insert_clause));
1320       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1321       strncat(where[primitive].string, "mac_src=\'%s\'", SPACELEFT(where[primitive].string));
1322       values[primitive].type = where[primitive].type = COUNT_INT_SRC_MAC;
1323       values[primitive].handler = where[primitive].handler = count_src_mac_handler;
1324       primitive++;
1325     }
1326   }
1327 
1328   if (what_to_count & COUNT_DST_MAC) {
1329     int count_it = FALSE;
1330 
1331     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1332       Log(LOG_ERR, "ERROR ( %s/%s ): MAC accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1333       exit_gracefully(1);
1334     }
1335     else count_it = TRUE;
1336 
1337     if (count_it) {
1338       if (primitive) {
1339         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1340         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1341         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1342       }
1343       strncat(insert_clause, "mac_dst", SPACELEFT(insert_clause));
1344       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1345       strncat(where[primitive].string, "mac_dst=\'%s\'", SPACELEFT(where[primitive].string));
1346       values[primitive].type = where[primitive].type = COUNT_INT_DST_MAC;
1347       values[primitive].handler = where[primitive].handler = count_dst_mac_handler;
1348       primitive++;
1349     }
1350   }
1351 
1352   if (what_to_count & COUNT_VLAN) {
1353     int count_it = FALSE;
1354 
1355     if ((config.sql_table_version < 2 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1356       if (config.what_to_count & COUNT_VLAN) {
1357         Log(LOG_ERR, "ERROR ( %s/%s ): VLAN accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1358         exit_gracefully(1);
1359       }
1360       else what_to_count ^= COUNT_VLAN;
1361     }
1362     else count_it = TRUE;
1363 
1364     if (count_it) {
1365       if (primitive) {
1366         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1367         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1368         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1369       }
1370       strncat(insert_clause, "vlan", SPACELEFT(insert_clause));
1371       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1372       strncat(where[primitive].string, "vlan=%u", SPACELEFT(where[primitive].string));
1373       values[primitive].type = where[primitive].type = COUNT_INT_VLAN;
1374       values[primitive].handler = where[primitive].handler = count_vlan_handler;
1375       primitive++;
1376     }
1377   }
1378 
1379   if (what_to_count & COUNT_COS) {
1380     if (primitive) {
1381       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1382       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1383       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1384     }
1385     strncat(insert_clause, "cos", SPACELEFT(insert_clause));
1386     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1387     strncat(where[primitive].string, "cos=%u", SPACELEFT(where[primitive].string));
1388     values[primitive].type = where[primitive].type = COUNT_INT_COS;
1389     values[primitive].handler = where[primitive].handler = count_cos_handler;
1390     primitive++;
1391   }
1392 
1393   if (what_to_count & COUNT_ETHERTYPE) {
1394     if (primitive) {
1395       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1396       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1397       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1398     }
1399     strncat(insert_clause, "etype", SPACELEFT(insert_clause));
1400     strncat(values[primitive].string, "\'%x\'", SPACELEFT(values[primitive].string));
1401     strncat(where[primitive].string, "etype=\'%x\'", SPACELEFT(where[primitive].string));
1402     values[primitive].type = where[primitive].type = COUNT_INT_ETHERTYPE;
1403     values[primitive].handler = where[primitive].handler = count_etype_handler;
1404     primitive++;
1405   }
1406 #endif
1407 
1408   if (what_to_count & (COUNT_SRC_HOST|COUNT_SUM_HOST)) {
1409     int count_it = FALSE;
1410 
1411     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1412       Log(LOG_ERR, "ERROR ( %s/%s ): IP host accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1413       exit_gracefully(1);
1414     }
1415     else count_it = TRUE;
1416 
1417     if (count_it) {
1418       if (primitive) {
1419         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1420         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1421         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1422       }
1423       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
1424         strncat(insert_clause, "ip_src", SPACELEFT(insert_clause));
1425         strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
1426         strncat(where[primitive].string, "ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
1427         values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST;
1428         values[primitive].handler = where[primitive].handler = count_src_host_aton_handler;
1429         primitive++;
1430       }
1431       else {
1432 	strncat(insert_clause, "ip_src", SPACELEFT(insert_clause));
1433 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1434 	strncat(where[primitive].string, "ip_src=\'%s\'", SPACELEFT(where[primitive].string));
1435 	values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST;
1436 	values[primitive].handler = where[primitive].handler = count_src_host_handler;
1437 	primitive++;
1438       }
1439     }
1440   }
1441 
1442   if (what_to_count & (COUNT_SRC_NET|COUNT_SUM_NET)) {
1443     if (primitive) {
1444       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1445       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1446       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1447     }
1448     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
1449       strncat(insert_clause, "net_src", SPACELEFT(insert_clause));
1450       strncat(where[primitive].string, "net_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
1451       strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
1452       values[primitive].type = where[primitive].type = COUNT_INT_SRC_NET;
1453       values[primitive].handler = where[primitive].handler = count_src_net_aton_handler;
1454       primitive++;
1455     }
1456     else {
1457       strncat(insert_clause, "net_src", SPACELEFT(insert_clause));
1458       strncat(where[primitive].string, "net_src=\'%s\'", SPACELEFT(where[primitive].string));
1459       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1460       values[primitive].type = where[primitive].type = COUNT_INT_SRC_NET;
1461       values[primitive].handler = where[primitive].handler = count_src_net_handler;
1462       primitive++;
1463     }
1464   }
1465 
1466   if (what_to_count & COUNT_DST_HOST) {
1467     int count_it = FALSE;
1468 
1469     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1470       Log(LOG_ERR, "ERROR ( %s/%s ): IP host accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1471       exit_gracefully(1);
1472     }
1473     else count_it = TRUE;
1474 
1475     if (count_it) {
1476       if (primitive) {
1477         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1478         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1479         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1480       }
1481       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
1482         strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause));
1483         strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
1484         strncat(where[primitive].string, "ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
1485         values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST;
1486         values[primitive].handler = where[primitive].handler = count_dst_host_aton_handler;
1487         primitive++;
1488       }
1489       else {
1490 	strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause));
1491 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1492 	strncat(where[primitive].string, "ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
1493 	values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST;
1494 	values[primitive].handler = where[primitive].handler = count_dst_host_handler;
1495 	primitive++;
1496       }
1497     }
1498   }
1499 
1500   if (what_to_count & COUNT_DST_NET) {
1501     if (primitive) {
1502       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1503       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1504       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1505     }
1506     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
1507       strncat(insert_clause, "net_dst", SPACELEFT(insert_clause));
1508       strncat(where[primitive].string, "net_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
1509       strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
1510       values[primitive].type = where[primitive].type = COUNT_INT_DST_NET;
1511       values[primitive].handler = where[primitive].handler = count_dst_net_aton_handler;
1512       primitive++;
1513     }
1514     else {
1515       strncat(insert_clause, "net_dst", SPACELEFT(insert_clause));
1516       strncat(where[primitive].string, "net_dst=\'%s\'", SPACELEFT(where[primitive].string));
1517       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1518       values[primitive].type = where[primitive].type = COUNT_INT_DST_NET;
1519       values[primitive].handler = where[primitive].handler = count_dst_net_handler;
1520       primitive++;
1521     }
1522   }
1523 
1524   if (what_to_count & (COUNT_SRC_AS|COUNT_SUM_AS)) {
1525     if (primitive) {
1526       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1527       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1528       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1529     }
1530 
1531     if (config.sql_table_version >= 6) {
1532       strncat(insert_clause, "as_src", SPACELEFT(insert_clause));
1533       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1534       strncat(where[primitive].string, "as_src=%u", SPACELEFT(where[primitive].string));
1535     }
1536     else {
1537       strncat(insert_clause, "ip_src", SPACELEFT(insert_clause));
1538       if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") ||
1539 	 (!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) {
1540 	strncat(values[primitive].string, "\'%u\'", SPACELEFT(values[primitive].string));
1541 	strncat(where[primitive].string, "ip_src=\'%u\'", SPACELEFT(where[primitive].string));
1542       }
1543       else {
1544 	strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1545 	strncat(where[primitive].string, "ip_src=%u", SPACELEFT(where[primitive].string));
1546       }
1547     }
1548     values[primitive].type = where[primitive].type = COUNT_INT_SRC_AS;
1549     values[primitive].handler = where[primitive].handler = count_src_as_handler;
1550     primitive++;
1551   }
1552 
1553   if (what_to_count & COUNT_IN_IFACE) {
1554     if (primitive) {
1555       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1556       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1557       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1558     }
1559     strncat(insert_clause, "iface_in", SPACELEFT(insert_clause));
1560     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1561     strncat(where[primitive].string, "iface_in=%u", SPACELEFT(where[primitive].string));
1562     values[primitive].type = where[primitive].type = COUNT_INT_IN_IFACE;
1563     values[primitive].handler = where[primitive].handler = count_in_iface_handler;
1564     primitive++;
1565   }
1566 
1567   if (what_to_count & COUNT_OUT_IFACE) {
1568     if (primitive) {
1569       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1570       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1571       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1572     }
1573     strncat(insert_clause, "iface_out", SPACELEFT(insert_clause));
1574     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1575     strncat(where[primitive].string, "iface_out=%u", SPACELEFT(where[primitive].string));
1576     values[primitive].type = where[primitive].type = COUNT_INT_OUT_IFACE;
1577     values[primitive].handler = where[primitive].handler = count_out_iface_handler;
1578     primitive++;
1579   }
1580 
1581   if (what_to_count & COUNT_SRC_NMASK) {
1582     if (primitive) {
1583       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1584       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1585       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1586     }
1587     strncat(insert_clause, "mask_src", SPACELEFT(insert_clause));
1588     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1589     strncat(where[primitive].string, "mask_src=%u", SPACELEFT(where[primitive].string));
1590     values[primitive].type = where[primitive].type = COUNT_INT_SRC_NMASK;
1591     values[primitive].handler = where[primitive].handler = count_src_nmask_handler;
1592     primitive++;
1593   }
1594 
1595   if (what_to_count & COUNT_DST_NMASK) {
1596     if (primitive) {
1597       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1598       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1599       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1600     }
1601     strncat(insert_clause, "mask_dst", SPACELEFT(insert_clause));
1602     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1603     strncat(where[primitive].string, "mask_dst=%u", SPACELEFT(where[primitive].string));
1604     values[primitive].type = where[primitive].type = COUNT_INT_DST_NMASK;
1605     values[primitive].handler = where[primitive].handler = count_dst_nmask_handler;
1606     primitive++;
1607   }
1608 
1609   if (what_to_count & COUNT_DST_AS) {
1610     if (primitive) {
1611       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1612       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1613       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1614     }
1615 
1616     if (config.sql_table_version >= 6) {
1617       strncat(insert_clause, "as_dst", SPACELEFT(insert_clause));
1618       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1619       strncat(where[primitive].string, "as_dst=%u", SPACELEFT(where[primitive].string));
1620     }
1621     else {
1622       strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause));
1623       if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") ||
1624 	 (!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) {
1625 	strncat(values[primitive].string, "\'%u\'", SPACELEFT(values[primitive].string));
1626 	strncat(where[primitive].string, "ip_dst=\'%u\'", SPACELEFT(where[primitive].string));
1627       }
1628       else {
1629 	strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1630 	strncat(where[primitive].string, "ip_dst=%u", SPACELEFT(where[primitive].string));
1631       }
1632     }
1633     values[primitive].type = where[primitive].type = COUNT_INT_DST_AS;
1634     values[primitive].handler = where[primitive].handler = count_dst_as_handler;
1635     primitive++;
1636   }
1637 
1638   if (what_to_count & COUNT_STD_COMM) {
1639     int count_it = FALSE;
1640 
1641     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1642       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1643       exit_gracefully(1);
1644     }
1645     else count_it = TRUE;
1646 
1647     if (count_it) {
1648       if (primitive) {
1649         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1650         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1651         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1652       }
1653       strncat(insert_clause, "comms", SPACELEFT(insert_clause));
1654       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1655       strncat(where[primitive].string, "comms=\'%s\'", SPACELEFT(where[primitive].string));
1656       values[primitive].type = where[primitive].type = COUNT_INT_STD_COMM;
1657       values[primitive].handler = where[primitive].handler = count_std_comm_handler;
1658       primitive++;
1659     }
1660   }
1661 
1662   if (what_to_count & COUNT_EXT_COMM) {
1663     int count_it = FALSE;
1664 
1665     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1666       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1667       exit_gracefully(1);
1668     }
1669     else count_it = TRUE;
1670 
1671     if (count_it) {
1672       if (primitive) {
1673         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1674         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1675         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1676       }
1677 
1678       strncat(insert_clause, "ecomms", SPACELEFT(insert_clause));
1679       strncat(where[primitive].string, "ecomms=\'%s\'", SPACELEFT(where[primitive].string));
1680 
1681       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1682       values[primitive].type = where[primitive].type = COUNT_INT_EXT_COMM;
1683       values[primitive].handler = where[primitive].handler = count_ext_comm_handler;
1684       primitive++;
1685     }
1686   }
1687 
1688   if (what_to_count_2 & COUNT_LRG_COMM) {
1689     if (primitive) {
1690       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1691       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1692       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1693     }
1694 
1695     strncat(insert_clause, "lcomms", SPACELEFT(insert_clause));
1696     strncat(where[primitive].string, "lcomms=\'%s\'", SPACELEFT(where[primitive].string));
1697 
1698     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1699     values[primitive].type = where[primitive].type = COUNT_INT_LRG_COMM;
1700     values[primitive].handler = where[primitive].handler = count_lrg_comm_handler;
1701     primitive++;
1702   }
1703 
1704   if (what_to_count & COUNT_SRC_STD_COMM) {
1705     if (primitive) {
1706       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1707       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1708       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1709     }
1710     strncat(insert_clause, "comms_src", SPACELEFT(insert_clause));
1711     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1712     strncat(where[primitive].string, "comms_src=\'%s\'", SPACELEFT(where[primitive].string));
1713     values[primitive].type = where[primitive].type = COUNT_INT_SRC_STD_COMM;
1714     values[primitive].handler = where[primitive].handler = count_src_std_comm_handler;
1715     primitive++;
1716   }
1717 
1718   if (what_to_count & COUNT_SRC_EXT_COMM) {
1719     if (primitive) {
1720       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1721       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1722       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1723     }
1724     strncat(insert_clause, "ecomms_src", SPACELEFT(insert_clause));
1725     strncat(where[primitive].string, "ecomms_src=\'%s\'", SPACELEFT(where[primitive].string));
1726     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1727     values[primitive].type = where[primitive].type = COUNT_INT_SRC_EXT_COMM;
1728     values[primitive].handler = where[primitive].handler = count_src_ext_comm_handler;
1729     primitive++;
1730   }
1731 
1732   if (what_to_count_2 & COUNT_SRC_LRG_COMM) {
1733     if (primitive) {
1734       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1735       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1736       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1737     }
1738 
1739     strncat(insert_clause, "lcomms_src", SPACELEFT(insert_clause));
1740     strncat(where[primitive].string, "lcomms_src=\'%s\'", SPACELEFT(where[primitive].string));
1741 
1742     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1743     values[primitive].type = where[primitive].type = COUNT_INT_SRC_LRG_COMM;
1744     values[primitive].handler = where[primitive].handler = count_src_lrg_comm_handler;
1745     primitive++;
1746   }
1747 
1748   if (what_to_count & COUNT_AS_PATH) {
1749     int count_it = FALSE;
1750 
1751     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1752       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1753       exit_gracefully(1);
1754     }
1755     else count_it = TRUE;
1756 
1757     if (count_it) {
1758       if (primitive) {
1759         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1760         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1761         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1762       }
1763       strncat(insert_clause, "as_path", SPACELEFT(insert_clause));
1764       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1765       strncat(where[primitive].string, "as_path=\'%s\'", SPACELEFT(where[primitive].string));
1766       values[primitive].type = where[primitive].type = COUNT_INT_AS_PATH;
1767       values[primitive].handler = where[primitive].handler = count_as_path_handler;
1768       primitive++;
1769     }
1770   }
1771 
1772   if (what_to_count & COUNT_SRC_AS_PATH) {
1773     if (primitive) {
1774       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1775       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1776       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1777     }
1778     strncat(insert_clause, "as_path_src", SPACELEFT(insert_clause));
1779     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1780     strncat(where[primitive].string, "as_path_src=\'%s\'", SPACELEFT(where[primitive].string));
1781     values[primitive].type = where[primitive].type = COUNT_INT_SRC_AS_PATH;
1782     values[primitive].handler = where[primitive].handler = count_src_as_path_handler;
1783     primitive++;
1784   }
1785 
1786   if (what_to_count & COUNT_LOCAL_PREF) {
1787     int count_it = FALSE;
1788 
1789     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1790       if (config.what_to_count & COUNT_LOCAL_PREF) {
1791         Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1792         exit_gracefully(1);
1793       }
1794       else what_to_count ^= COUNT_LOCAL_PREF;
1795     }
1796     else count_it = TRUE;
1797 
1798     if (count_it) {
1799       if (primitive) {
1800         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1801         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1802         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1803       }
1804       strncat(insert_clause, "local_pref", SPACELEFT(insert_clause));
1805       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1806       strncat(where[primitive].string, "local_pref=%u", SPACELEFT(where[primitive].string));
1807       values[primitive].type = where[primitive].type = COUNT_INT_LOCAL_PREF;
1808       values[primitive].handler = where[primitive].handler = count_local_pref_handler;
1809       primitive++;
1810     }
1811   }
1812 
1813   if (what_to_count & COUNT_SRC_LOCAL_PREF) {
1814     if (primitive) {
1815       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1816       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1817       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1818     }
1819     strncat(insert_clause, "local_pref_src", SPACELEFT(insert_clause));
1820     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1821     strncat(where[primitive].string, "local_pref_src=%u", SPACELEFT(where[primitive].string));
1822     values[primitive].type = where[primitive].type = COUNT_INT_SRC_LOCAL_PREF;
1823     values[primitive].handler = where[primitive].handler = count_src_local_pref_handler;
1824     primitive++;
1825   }
1826 
1827   if (what_to_count & COUNT_MED) {
1828     int count_it = FALSE;
1829 
1830     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1831       if (config.what_to_count & COUNT_MED) {
1832         Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1833         exit_gracefully(1);
1834       }
1835       else what_to_count ^= COUNT_MED;
1836     }
1837     else count_it = TRUE;
1838 
1839     if (count_it) {
1840       if (primitive) {
1841         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1842         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1843         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1844       }
1845       strncat(insert_clause, "med", SPACELEFT(insert_clause));
1846       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1847       strncat(where[primitive].string, "med=%u", SPACELEFT(where[primitive].string));
1848       values[primitive].type = where[primitive].type = COUNT_INT_MED;
1849       values[primitive].handler = where[primitive].handler = count_med_handler;
1850       primitive++;
1851     }
1852   }
1853 
1854   if (what_to_count & COUNT_SRC_MED) {
1855     if (primitive) {
1856       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1857       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1858       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1859     }
1860     strncat(insert_clause, "med_src", SPACELEFT(insert_clause));
1861     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1862     strncat(where[primitive].string, "med_src=%u", SPACELEFT(where[primitive].string));
1863     values[primitive].type = where[primitive].type = COUNT_INT_SRC_MED;
1864     values[primitive].handler = where[primitive].handler = count_src_med_handler;
1865     primitive++;
1866   }
1867 
1868   if (what_to_count_2 & COUNT_SRC_ROA) {
1869     if (primitive) {
1870       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1871       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1872       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1873     }
1874     strncat(insert_clause, "roa_src", SPACELEFT(insert_clause));
1875     strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
1876     strncat(where[primitive].string, "roa_src=%s", SPACELEFT(where[primitive].string));
1877     values[primitive].type = where[primitive].type = COUNT_INT_SRC_ROA;
1878     values[primitive].handler = where[primitive].handler = count_src_roa_handler;
1879     primitive++;
1880   }
1881 
1882   if (what_to_count_2 & COUNT_DST_ROA) {
1883     if (primitive) {
1884       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1885       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1886       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1887     }
1888     strncat(insert_clause, "roa_dst", SPACELEFT(insert_clause));
1889     strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
1890     strncat(where[primitive].string, "roa_dst=%s", SPACELEFT(where[primitive].string));
1891     values[primitive].type = where[primitive].type = COUNT_INT_DST_ROA;
1892     values[primitive].handler = where[primitive].handler = count_dst_roa_handler;
1893     primitive++;
1894   }
1895 
1896   if (what_to_count & COUNT_MPLS_VPN_RD) {
1897     if (primitive) {
1898       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1899       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1900       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1901     }
1902     strncat(insert_clause, "mpls_vpn_rd", SPACELEFT(insert_clause));
1903     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
1904     strncat(where[primitive].string, "mpls_vpn_rd=\'%s\'", SPACELEFT(where[primitive].string));
1905     values[primitive].type = where[primitive].type = COUNT_INT_MPLS_VPN_RD;
1906     values[primitive].handler = where[primitive].handler = count_mpls_vpn_rd_handler;
1907     primitive++;
1908   }
1909 
1910   if (what_to_count_2 & COUNT_MPLS_PW_ID) {
1911     if (primitive) {
1912       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1913       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1914       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1915     }
1916     strncat(insert_clause, "mpls_pw_id", SPACELEFT(insert_clause));
1917     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1918     strncat(where[primitive].string, "mpls_pw_id=%u", SPACELEFT(where[primitive].string));
1919     values[primitive].type = where[primitive].type = COUNT_INT_MPLS_PW_ID;
1920     values[primitive].handler = where[primitive].handler = count_mpls_pw_id_handler;
1921     primitive++;
1922   }
1923 
1924   if (what_to_count & COUNT_PEER_SRC_AS) {
1925     int count_it = FALSE;
1926 
1927     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1928       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1929       exit_gracefully(1);
1930     }
1931     else count_it = TRUE;
1932 
1933     if (count_it) {
1934       if (primitive) {
1935         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1936         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1937         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1938       }
1939 
1940       strncat(insert_clause, "peer_as_src", SPACELEFT(insert_clause));
1941       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1942       strncat(where[primitive].string, "peer_as_src=%u", SPACELEFT(where[primitive].string));
1943       values[primitive].type = where[primitive].type = COUNT_INT_PEER_SRC_AS;
1944       values[primitive].handler = where[primitive].handler = count_peer_src_as_handler;
1945       primitive++;
1946     }
1947   }
1948 
1949   if (what_to_count & COUNT_PEER_DST_AS) {
1950     int count_it = FALSE;
1951 
1952     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1953       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1954       exit_gracefully(1);
1955     }
1956     else count_it = TRUE;
1957 
1958     if (count_it) {
1959       if (primitive) {
1960         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1961         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1962         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1963       }
1964 
1965       strncat(insert_clause, "peer_as_dst", SPACELEFT(insert_clause));
1966       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
1967       strncat(where[primitive].string, "peer_as_dst=%u", SPACELEFT(where[primitive].string));
1968       values[primitive].type = where[primitive].type = COUNT_INT_PEER_DST_AS;
1969       values[primitive].handler = where[primitive].handler = count_peer_dst_as_handler;
1970       primitive++;
1971     }
1972   }
1973 
1974   if (what_to_count & COUNT_PEER_SRC_IP) {
1975     int count_it = FALSE;
1976 
1977     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
1978       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
1979       exit_gracefully(1);
1980     }
1981     else count_it = TRUE;
1982 
1983     if (count_it) {
1984       if (primitive) {
1985         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
1986         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
1987         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
1988       }
1989       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
1990         strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause));
1991         strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
1992         strncat(where[primitive].string, "peer_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
1993         values[primitive].type = where[primitive].type = COUNT_INT_PEER_SRC_IP;
1994         values[primitive].handler = where[primitive].handler = count_peer_src_ip_aton_handler;
1995         primitive++;
1996       }
1997       else {
1998 	strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause));
1999 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2000 	strncat(where[primitive].string, "peer_ip_src=\'%s\'", SPACELEFT(where[primitive].string));
2001 	values[primitive].type = where[primitive].type = COUNT_INT_PEER_SRC_IP;
2002 	values[primitive].handler = where[primitive].handler = count_peer_src_ip_handler;
2003 	primitive++;
2004       }
2005     }
2006   }
2007 
2008   if (what_to_count & COUNT_PEER_DST_IP) {
2009     int count_it = FALSE;
2010 
2011     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
2012       Log(LOG_ERR, "ERROR ( %s/%s ): BGP accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2013       exit_gracefully(1);
2014     }
2015     else count_it = TRUE;
2016 
2017     if (count_it) {
2018       if (primitive) {
2019         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2020         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2021         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2022       }
2023       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
2024         strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause));
2025         strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
2026         strncat(where[primitive].string, "peer_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
2027         values[primitive].type = where[primitive].type = COUNT_INT_PEER_DST_IP;
2028         values[primitive].handler = where[primitive].handler = count_peer_dst_ip_aton_handler;
2029         primitive++;
2030       }
2031       else {
2032 	strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause));
2033 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2034 	strncat(where[primitive].string, "peer_ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
2035 	values[primitive].type = where[primitive].type = COUNT_INT_PEER_DST_IP;
2036 	values[primitive].handler = where[primitive].handler = count_peer_dst_ip_handler;
2037 	primitive++;
2038       }
2039     }
2040   }
2041 
2042   if (what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) {
2043     int count_it = FALSE;
2044 
2045     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
2046       if (config.what_to_count & (COUNT_SRC_PORT|COUNT_SUM_PORT)) {
2047         Log(LOG_ERR, "ERROR ( %s/%s ): TCP/UDP port accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2048         exit_gracefully(1);
2049       }
2050       else {
2051         if (what_to_count & COUNT_SRC_PORT) what_to_count ^= COUNT_SRC_PORT;
2052         if (what_to_count & COUNT_SUM_PORT) what_to_count ^= COUNT_SUM_PORT;
2053       }
2054     }
2055     else count_it = TRUE;
2056 
2057     if (count_it) {
2058       if (primitive) {
2059         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2060         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2061         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2062       }
2063       if ((!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3")) && (config.sql_table_version < 8 ||
2064 	  (config.sql_table_version >= SQL_TABLE_VERSION_BGP && config.sql_table_version < SQL_TABLE_VERSION_BGP+8))) {
2065         strncat(insert_clause, "src_port", SPACELEFT(insert_clause));
2066         strncat(where[primitive].string, "src_port=%u", SPACELEFT(where[primitive].string));
2067       }
2068       else {
2069         strncat(insert_clause, "port_src", SPACELEFT(insert_clause));
2070         strncat(where[primitive].string, "port_src=%u", SPACELEFT(where[primitive].string));
2071       }
2072       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2073       values[primitive].type = where[primitive].type = COUNT_INT_SRC_PORT;
2074       values[primitive].handler = where[primitive].handler = count_src_port_handler;
2075       primitive++;
2076     }
2077   }
2078 
2079   if (what_to_count & COUNT_DST_PORT) {
2080     int count_it = FALSE;
2081 
2082     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
2083       if (config.what_to_count & COUNT_DST_PORT) {
2084         Log(LOG_ERR, "ERROR ( %s/%s ): TCP/UDP port accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2085         exit_gracefully(1);
2086       }
2087       else what_to_count ^= COUNT_DST_PORT;
2088     }
2089     else count_it = TRUE;
2090 
2091     if (count_it) {
2092       if (primitive) {
2093         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2094         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2095         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2096       }
2097       if ((!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3")) && (config.sql_table_version < 8 ||
2098           (config.sql_table_version >= SQL_TABLE_VERSION_BGP && config.sql_table_version < SQL_TABLE_VERSION_BGP+8))) {
2099         strncat(insert_clause, "dst_port", SPACELEFT(insert_clause));
2100         strncat(where[primitive].string, "dst_port=%u", SPACELEFT(where[primitive].string));
2101       }
2102       else {
2103         strncat(insert_clause, "port_dst", SPACELEFT(insert_clause));
2104         strncat(where[primitive].string, "port_dst=%u", SPACELEFT(where[primitive].string));
2105       }
2106       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2107       values[primitive].type = where[primitive].type = COUNT_INT_DST_PORT;
2108       values[primitive].handler = where[primitive].handler = count_dst_port_handler;
2109       primitive++;
2110     }
2111   }
2112 
2113   if (what_to_count & COUNT_TCPFLAGS) {
2114     int count_it = FALSE;
2115 
2116     if ((config.sql_table_version < 7 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
2117       if (config.what_to_count & COUNT_TCPFLAGS) {
2118         Log(LOG_ERR, "ERROR ( %s/%s ): TCP flags accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2119 	exit_gracefully(1);
2120       }
2121       else what_to_count ^= COUNT_TCPFLAGS;
2122     }
2123     else count_it = TRUE;
2124 
2125     if (count_it) {
2126       if (primitive) {
2127 	strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2128 	strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2129       }
2130       strncat(insert_clause, "tcp_flags", SPACELEFT(insert_clause));
2131       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2132       values[primitive].type = where[primitive].type = COUNT_INT_TCPFLAGS;
2133       values[primitive].handler = where[primitive].handler = count_tcpflags_handler;
2134       primitive++;
2135     }
2136   }
2137 
2138   if (what_to_count & COUNT_IP_TOS) {
2139     int count_it = FALSE;
2140 
2141     if ((config.sql_table_version < 3 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
2142       if (config.what_to_count & COUNT_IP_TOS) {
2143         Log(LOG_ERR, "ERROR ( %s/%s ): IP ToS accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2144         exit_gracefully(1);
2145       }
2146       else what_to_count ^= COUNT_IP_TOS;
2147     }
2148     else count_it = TRUE;
2149 
2150     if (count_it) {
2151       if (primitive) {
2152         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2153         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2154         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2155       }
2156       strncat(insert_clause, "tos", SPACELEFT(insert_clause));
2157       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2158       strncat(where[primitive].string, "tos=%u", SPACELEFT(where[primitive].string));
2159       values[primitive].type = where[primitive].type = COUNT_INT_IP_TOS;
2160       values[primitive].handler = where[primitive].handler = count_ip_tos_handler;
2161       primitive++;
2162     }
2163   }
2164 
2165   if (what_to_count & COUNT_IP_PROTO) {
2166     int count_it = FALSE;
2167 
2168     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
2169       if (config.what_to_count & COUNT_IP_PROTO) {
2170         Log(LOG_ERR, "ERROR ( %s/%s ): IP proto accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2171         exit_gracefully(1);
2172       }
2173       else what_to_count ^= COUNT_IP_PROTO;
2174     }
2175     else count_it = TRUE;
2176 
2177     if (count_it) {
2178       if (primitive) {
2179         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2180         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2181         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2182       }
2183       strncat(insert_clause, "ip_proto", SPACELEFT(insert_clause));
2184       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && !config.num_protos) {
2185         strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2186         strncat(where[primitive].string, "ip_proto=\'%s\'", SPACELEFT(where[primitive].string));
2187         values[primitive].handler = where[primitive].handler = MY_count_ip_proto_handler;
2188       }
2189       else {
2190         strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2191         strncat(where[primitive].string, "ip_proto=%u", SPACELEFT(where[primitive].string));
2192         values[primitive].handler = where[primitive].handler = PG_count_ip_proto_handler;
2193       }
2194       values[primitive].type = where[primitive].type = COUNT_INT_IP_PROTO;
2195       primitive++;
2196     }
2197   }
2198 
2199 #if defined (WITH_GEOIP) || defined (WITH_GEOIPV2)
2200   if (what_to_count_2 & COUNT_SRC_HOST_COUNTRY) {
2201     if (primitive) {
2202       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2203       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2204       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2205     }
2206     strncat(insert_clause, "country_ip_src", SPACELEFT(insert_clause));
2207     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2208     strncat(where[primitive].string, "country_ip_src=\'%s\'", SPACELEFT(where[primitive].string));
2209     values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST_COUNTRY;
2210     values[primitive].handler = where[primitive].handler = count_src_host_country_handler;
2211     primitive++;
2212   }
2213 
2214   if (what_to_count_2 & COUNT_DST_HOST_COUNTRY) {
2215     if (primitive) {
2216       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2217       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2218       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2219     }
2220     strncat(insert_clause, "country_ip_dst", SPACELEFT(insert_clause));
2221     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2222     strncat(where[primitive].string, "country_ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
2223     values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST_COUNTRY;
2224     values[primitive].handler = where[primitive].handler = count_dst_host_country_handler;
2225     primitive++;
2226   }
2227 #endif
2228 
2229 #if defined (WITH_GEOIPV2)
2230   if (what_to_count_2 & COUNT_SRC_HOST_POCODE) {
2231     if (primitive) {
2232       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2233       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2234       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2235     }
2236     strncat(insert_clause, "pocode_ip_src", SPACELEFT(insert_clause));
2237     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2238     strncat(where[primitive].string, "pocode_ip_src=\'%s\'", SPACELEFT(where[primitive].string));
2239     values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST_POCODE;
2240     values[primitive].handler = where[primitive].handler = count_src_host_pocode_handler;
2241     primitive++;
2242   }
2243 
2244   if (what_to_count_2 & COUNT_DST_HOST_POCODE) {
2245     if (primitive) {
2246       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2247       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2248       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2249     }
2250     strncat(insert_clause, "pocode_ip_dst", SPACELEFT(insert_clause));
2251     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2252     strncat(where[primitive].string, "pocode_ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
2253     values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST_POCODE;
2254     values[primitive].handler = where[primitive].handler = count_dst_host_pocode_handler;
2255     primitive++;
2256   }
2257 
2258   if (what_to_count_2 & COUNT_SRC_HOST_COORDS) {
2259     if (primitive) {
2260       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2261       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2262       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2263     }
2264     strncat(insert_clause, "lat_ip_src", SPACELEFT(insert_clause));
2265     strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string));
2266     strncat(where[primitive].string, "lat_ip_src=\'%f\'", SPACELEFT(where[primitive].string));
2267 
2268     strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2269     strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2270     strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2271 
2272     strncat(insert_clause, "lon_ip_src", SPACELEFT(insert_clause));
2273     strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string));
2274     strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2275     strncat(where[primitive].string, "lon_ip_src=\'%f\'", SPACELEFT(where[primitive].string));
2276     values[primitive].type = where[primitive].type = COUNT_INT_SRC_HOST_COORDS;
2277     values[primitive].handler = where[primitive].handler = count_src_host_coords_handler;
2278     primitive++;
2279   }
2280 
2281   if (what_to_count_2 & COUNT_DST_HOST_COORDS) {
2282     if (primitive) {
2283       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2284       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2285       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2286     }
2287     strncat(insert_clause, "lat_ip_dst", SPACELEFT(insert_clause));
2288     strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string));
2289     strncat(where[primitive].string, "lat_ip_dst=\'%f\'", SPACELEFT(where[primitive].string));
2290 
2291     strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2292     strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2293     strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2294 
2295     strncat(insert_clause, "lon_ip_dst", SPACELEFT(insert_clause));
2296     strncat(values[primitive].string, "\'%f\'", SPACELEFT(values[primitive].string));
2297     strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2298     strncat(where[primitive].string, "lon_ip_dst=\'%f\'", SPACELEFT(where[primitive].string));
2299     values[primitive].type = where[primitive].type = COUNT_INT_DST_HOST_COORDS;
2300     values[primitive].handler = where[primitive].handler = count_dst_host_coords_handler;
2301     primitive++;
2302   }
2303 #endif
2304 
2305   if (what_to_count_2 & COUNT_SAMPLING_RATE) {
2306     if (primitive) {
2307       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2308       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2309       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2310     }
2311     strncat(insert_clause, "sampling_rate", SPACELEFT(insert_clause));
2312     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2313     strncat(where[primitive].string, "sampling_rate=%u", SPACELEFT(where[primitive].string));
2314     values[primitive].type = where[primitive].type = COUNT_INT_SAMPLING_RATE;
2315     values[primitive].handler = where[primitive].handler = count_sampling_rate_handler;
2316     primitive++;
2317   }
2318 
2319   if (what_to_count_2 & COUNT_SAMPLING_DIRECTION) {
2320     if (primitive) {
2321       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2322       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2323       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2324     }
2325     strncat(insert_clause, "sampling_direction", SPACELEFT(insert_clause));
2326     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2327     strncat(where[primitive].string, "sampling_direction=\'%s\'", SPACELEFT(where[primitive].string));
2328     values[primitive].type = where[primitive].type = COUNT_INT_SAMPLING_DIRECTION;
2329     values[primitive].handler = where[primitive].handler = count_sampling_direction_handler;
2330     primitive++;
2331   }
2332 
2333   if (what_to_count_2 & COUNT_POST_NAT_SRC_HOST) {
2334     if (primitive) {
2335       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2336       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2337       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2338     }
2339     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
2340       strncat(insert_clause, "post_nat_ip_src", SPACELEFT(insert_clause));
2341       strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
2342       strncat(where[primitive].string, "post_nat_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
2343       values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_SRC_HOST;
2344       values[primitive].handler = where[primitive].handler = count_post_nat_src_ip_aton_handler;
2345       primitive++;
2346     }
2347     else {
2348       strncat(insert_clause, "post_nat_ip_src", SPACELEFT(insert_clause));
2349       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2350       strncat(where[primitive].string, "post_nat_ip_src=\'%s\'", SPACELEFT(where[primitive].string));
2351       values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_SRC_HOST;
2352       values[primitive].handler = where[primitive].handler = count_post_nat_src_ip_handler;
2353       primitive++;
2354     }
2355   }
2356 
2357   if (what_to_count_2 & COUNT_POST_NAT_DST_HOST) {
2358     if (primitive) {
2359       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2360       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2361       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2362     }
2363     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
2364       strncat(insert_clause, "post_nat_ip_dst", SPACELEFT(insert_clause));
2365       strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
2366       strncat(where[primitive].string, "post_nat_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
2367       values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_DST_HOST;
2368       values[primitive].handler = where[primitive].handler = count_post_nat_dst_ip_aton_handler;
2369       primitive++;
2370     }
2371     else {
2372       strncat(insert_clause, "post_nat_ip_dst", SPACELEFT(insert_clause));
2373       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2374       strncat(where[primitive].string, "post_nat_ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
2375       values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_DST_HOST;
2376       values[primitive].handler = where[primitive].handler = count_post_nat_dst_ip_handler;
2377       primitive++;
2378     }
2379   }
2380 
2381   if (what_to_count_2 & COUNT_POST_NAT_SRC_PORT) {
2382     if (primitive) {
2383       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2384       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2385       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2386     }
2387     strncat(insert_clause, "post_nat_port_src", SPACELEFT(insert_clause));
2388     strncat(where[primitive].string, "post_nat_port_src=%u", SPACELEFT(where[primitive].string));
2389     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2390     values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_SRC_PORT;
2391     values[primitive].handler = where[primitive].handler = count_post_nat_src_port_handler;
2392     primitive++;
2393   }
2394 
2395   if (what_to_count_2 & COUNT_POST_NAT_DST_PORT) {
2396     if (primitive) {
2397       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2398       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2399       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2400     }
2401     strncat(insert_clause, "post_nat_port_dst", SPACELEFT(insert_clause));
2402     strncat(where[primitive].string, "post_nat_port_dst=%u", SPACELEFT(where[primitive].string));
2403     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2404     values[primitive].type = where[primitive].type = COUNT_INT_POST_NAT_DST_PORT;
2405     values[primitive].handler = where[primitive].handler = count_post_nat_dst_port_handler;
2406     primitive++;
2407   }
2408 
2409   if (what_to_count_2 & COUNT_NAT_EVENT) {
2410     if (primitive) {
2411       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2412       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2413       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2414     }
2415     strncat(insert_clause, "nat_event", SPACELEFT(insert_clause));
2416     strncat(where[primitive].string, "nat_event=%u", SPACELEFT(where[primitive].string));
2417     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2418     values[primitive].type = where[primitive].type = COUNT_INT_NAT_EVENT;
2419     values[primitive].handler = where[primitive].handler = count_nat_event_handler;
2420     primitive++;
2421   }
2422 
2423   if (what_to_count_2 & COUNT_MPLS_LABEL_TOP) {
2424     if (primitive) {
2425       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2426       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2427       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2428     }
2429     strncat(insert_clause, "mpls_label_top", SPACELEFT(insert_clause));
2430     strncat(where[primitive].string, "mpls_label_top=%u", SPACELEFT(where[primitive].string));
2431     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2432     values[primitive].type = where[primitive].type = COUNT_INT_MPLS_LABEL_TOP;
2433     values[primitive].handler = where[primitive].handler = count_mpls_label_top_handler;
2434     primitive++;
2435   }
2436 
2437   if (what_to_count_2 & COUNT_MPLS_LABEL_BOTTOM) {
2438     if (primitive) {
2439       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2440       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2441       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2442     }
2443     strncat(insert_clause, "mpls_label_bottom", SPACELEFT(insert_clause));
2444     strncat(where[primitive].string, "mpls_label_bottom=%u", SPACELEFT(where[primitive].string));
2445     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2446     values[primitive].type = where[primitive].type = COUNT_INT_MPLS_LABEL_BOTTOM;
2447     values[primitive].handler = where[primitive].handler = count_mpls_label_bottom_handler;
2448     primitive++;
2449   }
2450 
2451   if (what_to_count_2 & COUNT_MPLS_STACK_DEPTH) {
2452     if (primitive) {
2453       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2454       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2455       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2456     }
2457     strncat(insert_clause, "mpls_stack_depth", SPACELEFT(insert_clause));
2458     strncat(where[primitive].string, "mpls_stack_depth=%u", SPACELEFT(where[primitive].string));
2459     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2460     values[primitive].type = where[primitive].type = COUNT_INT_MPLS_STACK_DEPTH;
2461     values[primitive].handler = where[primitive].handler = count_mpls_stack_depth_handler;
2462     primitive++;
2463   }
2464 
2465   if (what_to_count_2 & COUNT_TUNNEL_SRC_MAC) {
2466     if (primitive) {
2467       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2468       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2469       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2470     }
2471     strncat(insert_clause, "tunnel_mac_src", SPACELEFT(insert_clause));
2472     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2473     strncat(where[primitive].string, "tunnel_mac_src=\'%s\'", SPACELEFT(where[primitive].string));
2474     values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_MAC;
2475     values[primitive].handler = where[primitive].handler = count_tunnel_src_mac_handler;
2476     primitive++;
2477   }
2478 
2479   if (what_to_count_2 & COUNT_TUNNEL_DST_MAC) {
2480     if (primitive) {
2481       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2482       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2483       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2484     }
2485     strncat(insert_clause, "tunnel_mac_dst", SPACELEFT(insert_clause));
2486     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2487     strncat(where[primitive].string, "tunnel_mac_dst=\'%s\'", SPACELEFT(where[primitive].string));
2488     values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_MAC;
2489     values[primitive].handler = where[primitive].handler = count_tunnel_dst_mac_handler;
2490     primitive++;
2491   }
2492 
2493   if (what_to_count_2 & COUNT_TUNNEL_SRC_HOST) {
2494     if (primitive) {
2495       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2496       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2497       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2498     }
2499     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
2500       strncat(insert_clause, "tunnel_ip_src", SPACELEFT(insert_clause));
2501       strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
2502       strncat(where[primitive].string, "tunnel_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
2503       values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_HOST;
2504       values[primitive].handler = where[primitive].handler = count_tunnel_src_ip_aton_handler;
2505       primitive++;
2506     }
2507     else {
2508       strncat(insert_clause, "tunnel_ip_src", SPACELEFT(insert_clause));
2509       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2510       strncat(where[primitive].string, "tunnel_ip_src=\'%s\'", SPACELEFT(where[primitive].string));
2511       values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_HOST;
2512       values[primitive].handler = where[primitive].handler = count_tunnel_src_ip_handler;
2513       primitive++;
2514     }
2515   }
2516 
2517   if (what_to_count_2 & COUNT_TUNNEL_DST_HOST) {
2518     if (primitive) {
2519       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2520       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2521       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2522     }
2523     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
2524       strncat(insert_clause, "tunnel_ip_dst", SPACELEFT(insert_clause));
2525       strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
2526       strncat(where[primitive].string, "tunnel_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
2527       values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_HOST;
2528       values[primitive].handler = where[primitive].handler = count_tunnel_dst_ip_aton_handler;
2529       primitive++;
2530     }
2531     else {
2532       strncat(insert_clause, "tunnel_ip_dst", SPACELEFT(insert_clause));
2533       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2534       strncat(where[primitive].string, "tunnel_ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
2535       values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_HOST;
2536       values[primitive].handler = where[primitive].handler = count_tunnel_dst_ip_handler;
2537       primitive++;
2538     }
2539   }
2540 
2541   if (what_to_count_2 & COUNT_TUNNEL_IP_PROTO) {
2542     if (primitive) {
2543       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2544       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2545       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2546     }
2547     strncat(insert_clause, "tunnel_ip_proto", SPACELEFT(insert_clause));
2548     if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && !config.num_protos) {
2549       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2550       strncat(where[primitive].string, "tunnel_ip_proto=\'%s\'", SPACELEFT(where[primitive].string));
2551       values[primitive].handler = where[primitive].handler = MY_count_tunnel_ip_proto_handler;
2552     }
2553     else {
2554       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2555       strncat(where[primitive].string, "tunnel_ip_proto=%u", SPACELEFT(where[primitive].string));
2556       values[primitive].handler = where[primitive].handler = PG_count_tunnel_ip_proto_handler;
2557     }
2558     values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_IP_PROTO;
2559     primitive++;
2560   }
2561 
2562   if (what_to_count_2 & COUNT_TUNNEL_IP_TOS) {
2563     if (primitive) {
2564       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2565       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2566       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2567     }
2568     strncat(insert_clause, "tunnel_tos", SPACELEFT(insert_clause));
2569     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2570     strncat(where[primitive].string, "tunnel_tos=%u", SPACELEFT(where[primitive].string));
2571     values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_IP_TOS;
2572     values[primitive].handler = where[primitive].handler = count_tunnel_ip_tos_handler;
2573     primitive++;
2574   }
2575 
2576   if (what_to_count_2 & COUNT_TUNNEL_SRC_PORT) {
2577     if (primitive) {
2578       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2579       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2580       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2581     }
2582     strncat(insert_clause, "tunnel_port_src", SPACELEFT(insert_clause));
2583     strncat(where[primitive].string, "tunnel_port_src=%u", SPACELEFT(where[primitive].string));
2584     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2585     values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_SRC_PORT;
2586     values[primitive].handler = where[primitive].handler = count_tunnel_src_port_handler;
2587     primitive++;
2588   }
2589 
2590   if (what_to_count_2 & COUNT_TUNNEL_DST_PORT) {
2591     if (primitive) {
2592       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2593       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2594       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2595     }
2596     strncat(insert_clause, "tunnel_port_dst", SPACELEFT(insert_clause));
2597     strncat(where[primitive].string, "tunnel_port_dst=%u", SPACELEFT(where[primitive].string));
2598     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2599     values[primitive].type = where[primitive].type = COUNT_INT_TUNNEL_DST_PORT;
2600     values[primitive].handler = where[primitive].handler = count_tunnel_dst_port_handler;
2601     primitive++;
2602   }
2603 
2604   if (what_to_count_2 & COUNT_VXLAN) {
2605     if (primitive) {
2606       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2607       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2608       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2609     }
2610     strncat(insert_clause, "vxlan", SPACELEFT(insert_clause));
2611     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2612     strncat(where[primitive].string, "vxlan=%u", SPACELEFT(where[primitive].string));
2613     values[primitive].type = where[primitive].type = COUNT_INT_VXLAN;
2614     values[primitive].handler = where[primitive].handler = count_vxlan_handler;
2615     primitive++;
2616   }
2617 
2618   if (what_to_count_2 & COUNT_TIMESTAMP_START) {
2619     int use_copy=0;
2620 
2621     if (primitive) {
2622       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2623       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2624       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2625     }
2626     strncat(insert_clause, "timestamp_start", SPACELEFT(insert_clause));
2627     if (config.timestamps_since_epoch) {
2628       strncat(where[primitive].string, "timestamp_start=%u", SPACELEFT(where[primitive].string));
2629       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2630     }
2631     else {
2632       if (!strcmp(config.type, "mysql")) {
2633         strncat(where[primitive].string, "timestamp_start=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string));
2634         strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string));
2635       }
2636       else if (!strcmp(config.type, "pgsql")) {
2637 	if (config.sql_use_copy) {
2638           strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
2639 	  use_copy = TRUE;
2640 	}
2641 	else {
2642           strncat(where[primitive].string, "timestamp_start=to_timestamp(%u)", SPACELEFT(where[primitive].string));
2643           strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string));
2644 	}
2645       }
2646       else if (!strcmp(config.type, "sqlite3")) {
2647 	if (!config.timestamps_utc) {
2648           strncat(where[primitive].string, "timestamp_start=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string));
2649           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string));
2650 	}
2651 	else {
2652           strncat(where[primitive].string, "timestamp_start=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string));
2653           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string));
2654 	}
2655       }
2656     }
2657     if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_start_handler;
2658     else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_start_handler;
2659     values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_START;
2660     primitive++;
2661 
2662     if (!config.timestamps_secs) {
2663       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2664       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2665       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2666 
2667       strncat(insert_clause, "timestamp_start_residual", SPACELEFT(insert_clause));
2668       strncat(where[primitive].string, "timestamp_start_residual=%u", SPACELEFT(where[primitive].string));
2669       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2670       values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_START;
2671       values[primitive].handler = where[primitive].handler = count_timestamp_start_residual_handler;
2672       primitive++;
2673     }
2674   }
2675 
2676   if (what_to_count_2 & COUNT_TIMESTAMP_END) {
2677     int use_copy=0;
2678 
2679     if (primitive) {
2680       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2681       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2682       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2683     }
2684     strncat(insert_clause, "timestamp_end", SPACELEFT(insert_clause));
2685     if (config.timestamps_since_epoch) {
2686       strncat(where[primitive].string, "timestamp_end=%u", SPACELEFT(where[primitive].string));
2687       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2688     }
2689     else {
2690       if (!strcmp(config.type, "mysql")) {
2691         strncat(where[primitive].string, "timestamp_end=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string));
2692         strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string));
2693       }
2694       else if (!strcmp(config.type, "pgsql")) {
2695         if (config.sql_use_copy) {
2696           strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
2697           use_copy = TRUE;
2698         }
2699         else {
2700           strncat(where[primitive].string, "timestamp_end=to_timestamp(%u)", SPACELEFT(where[primitive].string));
2701           strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string));
2702         }
2703       }
2704       else if (!strcmp(config.type, "sqlite3")) {
2705 	if (!config.timestamps_utc) {
2706           strncat(where[primitive].string, "timestamp_end=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string));
2707           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string));
2708 	}
2709 	else {
2710           strncat(where[primitive].string, "timestamp_end=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string));
2711           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string));
2712 	}
2713       }
2714     }
2715     if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_end_handler;
2716     else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_end_handler;
2717     values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_END;
2718     primitive++;
2719 
2720     if (!config.timestamps_secs) {
2721       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2722       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2723       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2724 
2725       strncat(insert_clause, "timestamp_end_residual", SPACELEFT(insert_clause));
2726       strncat(where[primitive].string, "timestamp_end_residual=%u", SPACELEFT(where[primitive].string));
2727       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2728       values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_END;
2729       values[primitive].handler = where[primitive].handler = count_timestamp_end_residual_handler;
2730       primitive++;
2731     }
2732   }
2733 
2734   if (what_to_count_2 & COUNT_TIMESTAMP_ARRIVAL) {
2735     int use_copy=0;
2736 
2737     if (primitive) {
2738       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2739       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2740       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2741     }
2742     strncat(insert_clause, "timestamp_arrival", SPACELEFT(insert_clause));
2743     if (config.timestamps_since_epoch) {
2744       strncat(where[primitive].string, "timestamp_arrival=%u", SPACELEFT(where[primitive].string));
2745       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2746     }
2747     else {
2748       if (!strcmp(config.type, "mysql")) {
2749         strncat(where[primitive].string, "timestamp_arrival=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string));
2750         strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string));
2751       }
2752       else if (!strcmp(config.type, "pgsql")) {
2753         if (config.sql_use_copy) {
2754           strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
2755           use_copy = TRUE;
2756         }
2757         else {
2758           strncat(where[primitive].string, "timestamp_arrival=to_timestamp(%u)", SPACELEFT(where[primitive].string));
2759           strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string));
2760         }
2761       }
2762       else if (!strcmp(config.type, "sqlite3")) {
2763 	if (!config.timestamps_utc) {
2764           strncat(where[primitive].string, "timestamp_arrival=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string));
2765           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string));
2766 	}
2767 	else {
2768           strncat(where[primitive].string, "timestamp_arrival=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string));
2769           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string));
2770 	}
2771       }
2772     }
2773     if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_arrival_handler;
2774     else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_arrival_handler;
2775     values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_ARRIVAL;
2776     primitive++;
2777 
2778     if (!config.timestamps_secs) {
2779       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2780       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2781       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2782 
2783       strncat(insert_clause, "timestamp_arrival_residual", SPACELEFT(insert_clause));
2784       strncat(where[primitive].string, "timestamp_arrival_residual=%u", SPACELEFT(where[primitive].string));
2785       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2786       values[primitive].type = where[primitive].type = COUNT_INT_TIMESTAMP_ARRIVAL;
2787       values[primitive].handler = where[primitive].handler = count_timestamp_arrival_residual_handler;
2788       primitive++;
2789     }
2790   }
2791 
2792   if (config.nfacctd_stitching) {
2793     int use_copy=0;
2794 
2795     /* timestamp_min */
2796     if (primitive) {
2797       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2798       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2799       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2800     }
2801     strncat(insert_clause, "timestamp_min", SPACELEFT(insert_clause));
2802     if (config.timestamps_since_epoch) {
2803       strncat(where[primitive].string, "timestamp_min=%u", SPACELEFT(where[primitive].string));
2804       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2805     }
2806     else {
2807       if (!strcmp(config.type, "mysql")) {
2808         strncat(where[primitive].string, "timestamp_min=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string));
2809         strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string));
2810       }
2811       else if (!strcmp(config.type, "pgsql")) {
2812         if (config.sql_use_copy) {
2813           strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
2814           use_copy = TRUE;
2815         }
2816         else {
2817           strncat(where[primitive].string, "timestamp_min=to_timestamp(%u)", SPACELEFT(where[primitive].string));
2818           strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string));
2819         }
2820       }
2821       else if (!strcmp(config.type, "sqlite3")) {
2822 	if (!config.timestamps_utc) {
2823           strncat(where[primitive].string, "timestamp_min=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string));
2824           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string));
2825 	}
2826 	else {
2827           strncat(where[primitive].string, "timestamp_min=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string));
2828           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string));
2829 	}
2830       }
2831     }
2832     if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_min_handler;
2833     else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_min_handler;
2834     values[primitive].type = where[primitive].type = FALSE;
2835     primitive++;
2836 
2837     if (!config.timestamps_secs) {
2838       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2839       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2840       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2841 
2842       strncat(insert_clause, "timestamp_min_residual", SPACELEFT(insert_clause));
2843       strncat(where[primitive].string, "timestamp_min_residual=%u", SPACELEFT(where[primitive].string));
2844       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2845       values[primitive].type = where[primitive].type = FALSE;
2846       values[primitive].handler = where[primitive].handler = count_timestamp_min_residual_handler;
2847       primitive++;
2848     }
2849 
2850     /* timestamp_max */
2851     if (primitive) {
2852       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2853       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2854       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2855     }
2856     strncat(insert_clause, "timestamp_max", SPACELEFT(insert_clause));
2857     if (config.timestamps_since_epoch) {
2858       strncat(where[primitive].string, "timestamp_max=%u", SPACELEFT(where[primitive].string));
2859       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2860     }
2861     else {
2862       if (!strcmp(config.type, "mysql")) {
2863         strncat(where[primitive].string, "timestamp_max=FROM_UNIXTIME(%u)", SPACELEFT(where[primitive].string));
2864         strncat(values[primitive].string, "FROM_UNIXTIME(%u)", SPACELEFT(values[primitive].string));
2865       }
2866       else if (!strcmp(config.type, "pgsql")) {
2867         if (config.sql_use_copy) {
2868           strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
2869           use_copy = TRUE;
2870         }
2871         else {
2872           strncat(where[primitive].string, "timestamp_max=to_timestamp(%u)", SPACELEFT(where[primitive].string));
2873           strncat(values[primitive].string, "to_timestamp(%u)", SPACELEFT(values[primitive].string));
2874         }
2875       }
2876       else if (!strcmp(config.type, "sqlite3")) {
2877 	if (!config.timestamps_utc) {
2878           strncat(where[primitive].string, "timestamp_max=DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(where[primitive].string));
2879           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch', 'localtime')", SPACELEFT(values[primitive].string));
2880 	}
2881 	else {
2882           strncat(where[primitive].string, "timestamp_max=DATETIME(%u, 'unixepoch')", SPACELEFT(where[primitive].string));
2883           strncat(values[primitive].string, "DATETIME(%u, 'unixepoch')", SPACELEFT(values[primitive].string));
2884 	}
2885       }
2886     }
2887 
2888     if (!use_copy) values[primitive].handler = where[primitive].handler = count_timestamp_max_handler;
2889     else values[primitive].handler = where[primitive].handler = PG_copy_count_timestamp_max_handler;
2890     values[primitive].type = where[primitive].type = FALSE;
2891     primitive++;
2892 
2893     if (!config.timestamps_secs) {
2894       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2895       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2896       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2897 
2898       strncat(insert_clause, "timestamp_max_residual", SPACELEFT(insert_clause));
2899       strncat(where[primitive].string, "timestamp_max_residual=%u", SPACELEFT(where[primitive].string));
2900       strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2901       values[primitive].type = where[primitive].type = FALSE;
2902       values[primitive].handler = where[primitive].handler = count_timestamp_max_residual_handler;
2903       primitive++;
2904     }
2905   }
2906 
2907   if (what_to_count_2 & COUNT_EXPORT_PROTO_SEQNO) {
2908     if (primitive) {
2909       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2910       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2911       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2912     }
2913     strncat(insert_clause, "export_proto_seqno", SPACELEFT(insert_clause));
2914     strncat(where[primitive].string, "export_proto_seqno=%u", SPACELEFT(where[primitive].string));
2915     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2916     values[primitive].handler = where[primitive].handler = count_export_proto_seqno_handler;
2917     values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_SEQNO;
2918     primitive++;
2919   }
2920 
2921   if (what_to_count_2 & COUNT_EXPORT_PROTO_VERSION) {
2922     if (primitive) {
2923       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2924       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2925       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2926     }
2927     strncat(insert_clause, "export_proto_version", SPACELEFT(insert_clause));
2928     strncat(where[primitive].string, "export_proto_version=%u", SPACELEFT(where[primitive].string));
2929     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2930     values[primitive].handler = where[primitive].handler = count_export_proto_version_handler;
2931     values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_VERSION;
2932     primitive++;
2933   }
2934 
2935   if (what_to_count_2 & COUNT_EXPORT_PROTO_SYSID) {
2936     if (primitive) {
2937       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2938       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2939       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2940     }
2941     strncat(insert_clause, "export_proto_sysid", SPACELEFT(insert_clause));
2942     strncat(where[primitive].string, "export_proto_sysid=%u", SPACELEFT(where[primitive].string));
2943     strncat(values[primitive].string, "%u", SPACELEFT(values[primitive].string));
2944     values[primitive].handler = where[primitive].handler = count_export_proto_sysid_handler;
2945     values[primitive].type = where[primitive].type = COUNT_INT_EXPORT_PROTO_SYSID;
2946     primitive++;
2947   }
2948 
2949   /* all custom primitives printed here */
2950   {
2951     struct custom_primitive_ptrs *cp_entry;
2952     int cp_idx;
2953 
2954     for (cp_idx = 0; cp_idx < config.cpptrs.num; cp_idx++) {
2955       if (primitive) {
2956 	strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2957 	strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2958 	strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2959       }
2960 
2961       cp_entry = &config.cpptrs.primitive[cp_idx];
2962       strncat(insert_clause, cp_entry->name, SPACELEFT(insert_clause));
2963       strncat(where[primitive].string, cp_entry->name, SPACELEFT(where[primitive].string));
2964       if (cp_entry->ptr->semantics == CUSTOM_PRIMITIVE_TYPE_UINT) {
2965 	strncat(where[primitive].string, "=%s", SPACELEFT(where[primitive].string));
2966         strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
2967       }
2968       else {
2969 	strncat(where[primitive].string, "=\'%s\'", SPACELEFT(where[primitive].string));
2970         strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
2971       }
2972       values[primitive].type = where[primitive].type = COUNT_INT_CUSTOM_PRIMITIVES;
2973       values[primitive].handler = where[primitive].handler = count_custom_primitives_handler;
2974       primitive++;
2975     }
2976   }
2977 
2978   if (what_to_count & COUNT_TAG) {
2979     int count_it = FALSE;
2980 
2981     if ((config.sql_table_version < 2) && !assume_custom_table) {
2982       if (config.what_to_count & COUNT_TAG) {
2983 	Log(LOG_ERR, "ERROR ( %s/%s ): Tag/ID accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
2984         exit_gracefully(1);
2985       }
2986       else what_to_count ^= COUNT_TAG;
2987     }
2988     else count_it = TRUE;
2989 
2990     if (count_it) {
2991       if (primitive) {
2992         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
2993         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
2994         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
2995       }
2996       if (config.sql_table_version < 9 || (config.sql_table_version >= SQL_TABLE_VERSION_BGP
2997 	  && config.sql_table_version < SQL_TABLE_VERSION_BGP+9)) {
2998         strncat(insert_clause, "agent_id", SPACELEFT(insert_clause));
2999         strncat(where[primitive].string, "agent_id=%llu", SPACELEFT(where[primitive].string));
3000       }
3001       else {
3002         strncat(insert_clause, "tag", SPACELEFT(insert_clause));
3003         strncat(where[primitive].string, "tag=%llu", SPACELEFT(where[primitive].string));
3004       }
3005       strncat(values[primitive].string, "%llu", SPACELEFT(values[primitive].string));
3006       values[primitive].type = where[primitive].type = COUNT_INT_TAG;
3007       values[primitive].handler = where[primitive].handler = count_tag_handler;
3008       primitive++;
3009     }
3010   }
3011 
3012   if (what_to_count & COUNT_TAG2) {
3013     if (primitive) {
3014       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3015       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3016       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3017     }
3018     strncat(insert_clause, "tag2", SPACELEFT(insert_clause));
3019     strncat(values[primitive].string, "%llu", SPACELEFT(values[primitive].string));
3020     strncat(where[primitive].string, "tag2=%llu", SPACELEFT(where[primitive].string));
3021     values[primitive].type = where[primitive].type = COUNT_INT_TAG2;
3022     values[primitive].handler = where[primitive].handler = count_tag2_handler;
3023     primitive++;
3024   }
3025 
3026   if (what_to_count_2 & COUNT_LABEL) {
3027     if (primitive) {
3028       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3029       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3030       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3031     }
3032     strncat(insert_clause, "label", SPACELEFT(insert_clause));
3033     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3034     strncat(where[primitive].string, "label=%\'%s\'", SPACELEFT(where[primitive].string));
3035     values[primitive].type = where[primitive].type = COUNT_INT_LABEL;
3036     values[primitive].handler = where[primitive].handler = count_label_handler;
3037     primitive++;
3038   }
3039 
3040   if (what_to_count & COUNT_CLASS) {
3041     int count_it = FALSE;
3042 
3043     if ((config.sql_table_version < 5 || config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3044       if (config.what_to_count & COUNT_CLASS) {
3045         Log(LOG_ERR, "ERROR ( %s/%s ): L7 classification accounting not supported for selected sql_table_version/_type. Read about SQL table versioning or consider using sql_optimize_clauses.\n", config.name, config.type);
3046         exit_gracefully(1);
3047       }
3048       else what_to_count ^= COUNT_CLASS;
3049     }
3050     else count_it = TRUE;
3051 
3052     if (count_it) {
3053       if (primitive) {
3054         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3055         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3056         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3057       }
3058       strncat(insert_clause, "class_id", SPACELEFT(insert_clause));
3059       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3060       strncat(where[primitive].string, "class_id=\'%s\'", SPACELEFT(where[primitive].string));
3061       values[primitive].type = where[primitive].type = COUNT_INT_CLASS;
3062       values[primitive].handler = where[primitive].handler = count_class_id_handler;
3063       primitive++;
3064     }
3065   }
3066 
3067 #if defined (WITH_NDPI)
3068   if (what_to_count_2 & COUNT_NDPI_CLASS) {
3069     if (primitive) {
3070       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3071       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3072       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3073     }
3074     strncat(insert_clause, "class", SPACELEFT(insert_clause));
3075     strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3076     strncat(where[primitive].string, "class=\'%s\'", SPACELEFT(where[primitive].string));
3077     values[primitive].type = where[primitive].type = COUNT_INT_CLASS;
3078     values[primitive].handler = where[primitive].handler = count_ndpi_class_handler;
3079     primitive++;
3080   }
3081 #endif
3082 
3083 #if defined (HAVE_L2)
3084   if (fakes & FAKE_SRC_MAC) {
3085     int count_it = FALSE;
3086 
3087     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3088       fakes ^= FAKE_SRC_MAC;
3089     }
3090     else count_it = TRUE;
3091 
3092     if (count_it) {
3093       if (primitive) {
3094         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3095         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3096         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3097       }
3098       strncat(insert_clause, "mac_src", SPACELEFT(insert_clause));
3099       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3100       strncat(where[primitive].string, "mac_src=\'%s\'", SPACELEFT(where[primitive].string));
3101       values[primitive].type = where[primitive].type = FAKE_SRC_MAC;
3102       values[primitive].handler = where[primitive].handler = fake_mac_handler;
3103       primitive++;
3104     }
3105   }
3106 
3107   if (fakes & FAKE_DST_MAC) {
3108     int count_it = FALSE;
3109 
3110     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3111       fakes ^= FAKE_DST_MAC;
3112     }
3113     else count_it = TRUE;
3114 
3115     if (count_it) {
3116       if (primitive) {
3117         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3118         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3119         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3120       }
3121       strncat(insert_clause, "mac_dst", SPACELEFT(insert_clause));
3122       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3123       strncat(where[primitive].string, "mac_dst=\'%s\'", SPACELEFT(where[primitive].string));
3124       values[primitive].type = where[primitive].type = FAKE_DST_MAC;
3125       values[primitive].handler = where[primitive].handler = fake_mac_handler;
3126       primitive++;
3127     }
3128   }
3129 #endif
3130 
3131   if (fakes & FAKE_SRC_HOST) {
3132     int count_it = FALSE;
3133 
3134     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3135       fakes ^= FAKE_SRC_HOST;
3136     }
3137     else count_it = TRUE;
3138 
3139     if (count_it) {
3140       if (primitive) {
3141         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3142         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3143         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3144       }
3145       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
3146 	strncat(insert_clause, "ip_src", SPACELEFT(insert_clause));
3147 	strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
3148 	strncat(where[primitive].string, "ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
3149 	values[primitive].type = where[primitive].type = FAKE_SRC_HOST;
3150 	values[primitive].handler = where[primitive].handler = fake_host_aton_handler;
3151 	primitive++;
3152       }
3153       else {
3154 	strncat(insert_clause, "ip_src", SPACELEFT(insert_clause));
3155 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3156 	strncat(where[primitive].string, "ip_src=\'%s\'", SPACELEFT(where[primitive].string));
3157 	values[primitive].type = where[primitive].type = FAKE_SRC_HOST;
3158 	values[primitive].handler = where[primitive].handler = fake_host_handler;
3159 	primitive++;
3160       }
3161     }
3162   }
3163 
3164   if (fakes & FAKE_DST_HOST) {
3165     int count_it = FALSE;
3166 
3167     if ((config.sql_table_version >= SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3168       fakes ^= FAKE_DST_HOST;
3169     }
3170     else count_it = TRUE;
3171 
3172     if (count_it) {
3173       if (primitive) {
3174         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3175         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3176         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3177       }
3178       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
3179 	strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause));
3180 	strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
3181 	strncat(where[primitive].string, "ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
3182 	values[primitive].type = where[primitive].type = FAKE_DST_HOST;
3183 	values[primitive].handler = where[primitive].handler = fake_host_aton_handler;
3184 	primitive++;
3185       }
3186       else {
3187 	strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause));
3188 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3189 	strncat(where[primitive].string, "ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
3190 	values[primitive].type = where[primitive].type = FAKE_DST_HOST;
3191 	values[primitive].handler = where[primitive].handler = fake_host_handler;
3192 	primitive++;
3193       }
3194     }
3195   }
3196 
3197   if (fakes & FAKE_SRC_AS) {
3198     if (primitive) {
3199       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3200       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3201       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3202     }
3203     strncat(insert_clause, "ip_src", SPACELEFT(insert_clause));
3204     if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") ||
3205 	(!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) {
3206       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3207       strncat(where[primitive].string, "ip_src=\'%s\'", SPACELEFT(where[primitive].string));
3208     }
3209     else {
3210       strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
3211       strncat(where[primitive].string, "ip_src=%s", SPACELEFT(where[primitive].string));
3212     }
3213     values[primitive].type = where[primitive].type = FAKE_SRC_AS;
3214     values[primitive].handler = where[primitive].handler = fake_as_handler;
3215     primitive++;
3216   }
3217 
3218   if (fakes & FAKE_DST_AS) {
3219     if (primitive) {
3220       strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3221       strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3222       strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3223     }
3224     strncat(insert_clause, "ip_dst", SPACELEFT(insert_clause));
3225     if (!strcmp(config.type, "mysql") || !strcmp(config.type, "sqlite3") ||
3226 	(!strcmp(config.type, "pgsql") && !strcmp(config.sql_data, "unified"))) {
3227       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3228       strncat(where[primitive].string, "ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
3229     }
3230     else {
3231       strncat(values[primitive].string, "%s", SPACELEFT(values[primitive].string));
3232       strncat(where[primitive].string, "ip_dst=%s", SPACELEFT(where[primitive].string));
3233     }
3234     values[primitive].type = where[primitive].type = FAKE_DST_AS;
3235     values[primitive].handler = where[primitive].handler = fake_as_handler;
3236     primitive++;
3237   }
3238 
3239   if (fakes & FAKE_COMMS) {
3240     int count_it = FALSE;
3241 
3242     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3243       fakes ^= FAKE_COMMS;
3244     }
3245     else count_it = TRUE;
3246 
3247     if (count_it) {
3248       if (primitive) {
3249         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3250         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3251         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3252       }
3253       strncat(insert_clause, "comms", SPACELEFT(insert_clause));
3254       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3255       strncat(where[primitive].string, "comms=\'%s\'", SPACELEFT(where[primitive].string));
3256       values[primitive].type = where[primitive].type = FAKE_COMMS;
3257       values[primitive].handler = where[primitive].handler = fake_comms_handler;
3258       primitive++;
3259     }
3260   }
3261 
3262   if (fakes & FAKE_AS_PATH) {
3263     int count_it = FALSE;
3264 
3265     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3266       fakes ^= FAKE_AS_PATH;
3267     }
3268     else count_it = TRUE;
3269 
3270     if (count_it) {
3271       if (primitive) {
3272         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3273         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3274         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3275       }
3276       strncat(insert_clause, "as_path", SPACELEFT(insert_clause));
3277       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3278       strncat(where[primitive].string, "as_path=\'%s\'", SPACELEFT(where[primitive].string));
3279       values[primitive].type = where[primitive].type = FAKE_AS_PATH;
3280       values[primitive].handler = where[primitive].handler = fake_as_path_handler;
3281       primitive++;
3282     }
3283   }
3284 
3285   if (fakes & FAKE_PEER_SRC_AS) {
3286     int count_it = FALSE;
3287 
3288     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3289       fakes ^= FAKE_PEER_SRC_AS;
3290     }
3291     else count_it = TRUE;
3292 
3293     if (count_it) {
3294       if (primitive) {
3295         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3296         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3297         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3298       }
3299       strncat(insert_clause, "peer_as_src", SPACELEFT(insert_clause));
3300       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3301       strncat(where[primitive].string, "peer_as_src=\'%s\'", SPACELEFT(where[primitive].string));
3302       values[primitive].type = where[primitive].type = FAKE_PEER_SRC_AS;
3303       values[primitive].handler = where[primitive].handler = fake_as_handler;
3304       primitive++;
3305     }
3306   }
3307 
3308   if (fakes & FAKE_PEER_DST_AS) {
3309     int count_it = FALSE;
3310 
3311     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3312       fakes ^= FAKE_PEER_DST_AS;
3313     }
3314     else count_it = TRUE;
3315 
3316     if (count_it) {
3317       if (primitive) {
3318         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3319         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3320         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3321       }
3322       strncat(insert_clause, "peer_as_dst", SPACELEFT(insert_clause));
3323       strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3324       strncat(where[primitive].string, "peer_as_dst=\'%s\'", SPACELEFT(where[primitive].string));
3325       values[primitive].type = where[primitive].type = FAKE_PEER_DST_AS;
3326       values[primitive].handler = where[primitive].handler = fake_as_handler;
3327       primitive++;
3328     }
3329   }
3330 
3331   if (fakes & FAKE_PEER_SRC_IP) {
3332     int count_it = FALSE;
3333 
3334     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3335       fakes ^= FAKE_PEER_SRC_IP;
3336     }
3337     else count_it = TRUE;
3338 
3339     if (count_it) {
3340       if (primitive) {
3341         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3342         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3343         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3344       }
3345       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
3346 	strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause));
3347 	strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
3348 	strncat(where[primitive].string, "peer_ip_src=%s(\'%s\')", SPACELEFT(where[primitive].string));
3349 	values[primitive].type = where[primitive].type = FAKE_PEER_SRC_IP;
3350 	values[primitive].handler = where[primitive].handler = fake_host_aton_handler;
3351 	primitive++;
3352       }
3353       else {
3354 	strncat(insert_clause, "peer_ip_src", SPACELEFT(insert_clause));
3355 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3356 	strncat(where[primitive].string, "peer_ip_src=\'%s\'", SPACELEFT(where[primitive].string));
3357 	values[primitive].type = where[primitive].type = FAKE_PEER_SRC_IP;
3358 	values[primitive].handler = where[primitive].handler = fake_host_handler;
3359 	primitive++;
3360       }
3361     }
3362   }
3363 
3364   if (fakes & FAKE_PEER_DST_IP) {
3365     int count_it = FALSE;
3366 
3367     if ((config.sql_table_version < SQL_TABLE_VERSION_BGP) && !assume_custom_table) {
3368       fakes ^= FAKE_PEER_DST_IP;
3369     }
3370     else count_it = TRUE;
3371 
3372     if (count_it) {
3373       if (primitive) {
3374         strncat(insert_clause, ", ", SPACELEFT(insert_clause));
3375         strncat(values[primitive].string, delim_buf, SPACELEFT(values[primitive].string));
3376         strncat(where[primitive].string, " AND ", SPACELEFT(where[primitive].string));
3377       }
3378       if ((!strcmp(config.type, "sqlite3") || !strcmp(config.type, "mysql")) && config.num_hosts) {
3379 	strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause));
3380 	strncat(values[primitive].string, "%s(\'%s\')", SPACELEFT(values[primitive].string));
3381 	strncat(where[primitive].string, "peer_ip_dst=%s(\'%s\')", SPACELEFT(where[primitive].string));
3382 	values[primitive].type = where[primitive].type = FAKE_PEER_DST_IP;
3383 	values[primitive].handler = where[primitive].handler = fake_host_aton_handler;
3384 	primitive++;
3385       }
3386       else {
3387 	strncat(insert_clause, "peer_ip_dst", SPACELEFT(insert_clause));
3388 	strncat(values[primitive].string, "\'%s\'", SPACELEFT(values[primitive].string));
3389 	strncat(where[primitive].string, "peer_ip_dst=\'%s\'", SPACELEFT(where[primitive].string));
3390 	values[primitive].type = where[primitive].type = FAKE_PEER_DST_IP;
3391 	values[primitive].handler = where[primitive].handler = fake_host_handler;
3392 	primitive++;
3393       }
3394     }
3395   }
3396 
3397   strncat(copy_clause, insert_clause_start_ptr, SPACELEFT(copy_clause));
3398 
3399   return primitive;
3400 }
3401 
sql_query(struct BE_descs * bed,struct db_cache * elem,struct insert_data * idata)3402 int sql_query(struct BE_descs *bed, struct db_cache *elem, struct insert_data *idata)
3403 {
3404   if (!bed->p->fail && elem->valid == SQL_CACHE_COMMITTED) {
3405     if ((*sqlfunc_cbr.op)(bed->p, elem, idata)); /* failed */
3406     else {
3407       idata->qn++;
3408       return FALSE;
3409     }
3410   }
3411 
3412   if ( elem->valid == SQL_CACHE_ERROR || (bed->p->fail && !(elem->valid == SQL_CACHE_INUSE)) ) {
3413     if (config.sql_backup_host) {
3414       if (!bed->b->fail) {
3415         if (!bed->b->connected) {
3416           (*sqlfunc_cbr.connect)(bed->b, config.sql_backup_host);
3417           if (config.sql_table_schema) {
3418 	    time_t stamp = idata->new_basetime ? idata->new_basetime : idata->basetime;
3419 
3420 	    sql_create_table(bed->b, &stamp, NULL); // XXX: should not be null
3421 	  }
3422           (*sqlfunc_cbr.lock)(bed->b);
3423         }
3424         if (!bed->b->fail) {
3425           if ((*sqlfunc_cbr.op)(bed->b, elem, idata)) sql_db_fail(bed->b);
3426         }
3427       }
3428     }
3429   }
3430 
3431   return TRUE;
3432 }
3433 
sql_create_table(struct DBdesc * db,time_t * basetime,struct primitives_ptrs * prim_ptrs)3434 void sql_create_table(struct DBdesc *db, time_t *basetime, struct primitives_ptrs *prim_ptrs)
3435 {
3436   char buf[LARGEBUFLEN], tmpbuf[LARGEBUFLEN];
3437   int ret;
3438 
3439   ret = read_SQLquery_from_file(config.sql_table_schema, buf, LARGEBUFLEN);
3440   if (ret) {
3441     handle_dynname_internal_strings_same(buf, LARGEBUFLEN, tmpbuf, prim_ptrs, DYN_STR_SQL_TABLE);
3442     pm_strftime_same(buf, LARGEBUFLEN, tmpbuf, basetime, config.timestamps_utc);
3443     (*sqlfunc_cbr.create_table)(db, buf);
3444   }
3445 }
3446 
sql_invalidate_shadow_entries(struct db_cache * queue[],int * num)3447 void sql_invalidate_shadow_entries(struct db_cache *queue[], int *num)
3448 {
3449   int x;
3450 
3451   for (x = 0; x < *num; x++) {
3452     if (!queue[x]->bytes_counter && !queue[x]->packet_counter && !queue[x]->flows_counter)
3453       queue[x]->valid = SQL_CACHE_FREE;
3454   }
3455 }
3456 
sql_select_locking_style(char * lock)3457 int sql_select_locking_style(char *lock)
3458 {
3459   int i = 0, len = strlen(lock);
3460 
3461   while (i < len) {
3462     lock[i] = tolower(lock[i]);
3463     i++;
3464   }
3465 
3466   if (!strcmp(lock, "table")) return PM_LOCK_EXCLUSIVE;
3467   else if (!strcmp(lock, "row")) return PM_LOCK_ROW_EXCLUSIVE;
3468   else if (!strcmp(lock, "none")) return PM_LOCK_NONE;
3469 
3470   Log(LOG_WARNING, "WARN ( %s/%s ): sql_locking_style value '%s' is unknown. Ignored.\n", config.name, config.type, lock);
3471 
3472   return PM_LOCK_EXCLUSIVE;
3473 }
3474 
sql_compose_static_set_event()3475 int sql_compose_static_set_event()
3476 {
3477   int set_primitives=0;
3478 
3479   if (config.what_to_count & COUNT_TCPFLAGS) {
3480     strncat(set_event[set_primitives].string, "SET tcp_flags=tcp_flags|%u", SPACELEFT(set_event[set_primitives].string));
3481     set_event[set_primitives].type = COUNT_INT_TCPFLAGS;
3482     set_event[set_primitives].handler = count_tcpflags_setclause_handler;
3483     set_primitives++;
3484   }
3485 
3486   return set_primitives;
3487 }
3488 
sql_compose_static_set(int have_flows)3489 int sql_compose_static_set(int have_flows)
3490 {
3491   int set_primitives=0;
3492 
3493   strncpy(set[set_primitives].string, "SET packets=packets+%llu, bytes=bytes+%llu", SPACELEFT(set[set_primitives].string));
3494   set[set_primitives].type = COUNT_INT_COUNTERS;
3495   set[set_primitives].handler = count_counters_setclause_handler;
3496   set_primitives++;
3497 
3498   if (have_flows) {
3499     strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string));
3500     strncat(set[set_primitives].string, "flows=flows+%llu", SPACELEFT(set[set_primitives].string));
3501     set[set_primitives].type = COUNT_INT_FLOWS;
3502     set[set_primitives].handler = count_flows_setclause_handler;
3503     set_primitives++;
3504   }
3505 
3506   if (config.what_to_count & COUNT_TCPFLAGS) {
3507     strncpy(set[set_primitives].string, ", ", SPACELEFT(set[set_primitives].string));
3508     strncat(set[set_primitives].string, "tcp_flags=tcp_flags|%u", SPACELEFT(set[set_primitives].string));
3509     set[set_primitives].type = COUNT_INT_TCPFLAGS;
3510     set[set_primitives].handler = count_tcpflags_setclause_handler;
3511     set_primitives++;
3512   }
3513 
3514   return set_primitives;
3515 }
3516 
primptrs_set_all_from_db_cache(struct primitives_ptrs * prim_ptrs,struct db_cache * entry)3517 void primptrs_set_all_from_db_cache(struct primitives_ptrs *prim_ptrs, struct db_cache *entry)
3518 {
3519   struct pkt_data *data = prim_ptrs->data;
3520 
3521   if (prim_ptrs && data && entry) {
3522     memset(data, 0, PdataSz);
3523     data->primitives = entry->primitives;
3524     prim_ptrs->pbgp = entry->pbgp;
3525     prim_ptrs->pnat = entry->pnat;
3526     prim_ptrs->pmpls = entry->pmpls;
3527     prim_ptrs->ptun = entry->ptun;
3528     prim_ptrs->pcust = entry->pcust;
3529     prim_ptrs->pvlen = entry->pvlen;
3530   }
3531 }
3532