1 #include "output_sqlite.h"
2 #include "util.h"
3 
4 #include <stdlib.h>
5 
6 static const char sqlite_create_template[] = "\
7 CREATE TABLE IF NOT EXISTS %s(\
8 timestamp UNSIGNED BIG INT, \
9 interface varchar(16), \
10 vlan_tag UNSIGNED INT, \
11 mac_address varchar(17), \
12 ip_address varchar(42), \
13 origin TINYINT\
14 );";
15 
16 static const char sqlite_insert_template[] = "INSERT INTO %s VALUES(?, ?, ?, ?, ?, ?);";
17 
output_sqlite_init()18 void output_sqlite_init()
19 {
20 #if HAVE_LIBSQLITE3
21 	int rc;
22 	char create_query[sizeof(sqlite_create_template) + 64];
23 	char insert_query[sizeof(sqlite_insert_template) + 64];
24 
25 	if (!cfg.sqlite_file) {
26 		return;
27 	}
28 
29 	snprintf(create_query, sizeof(create_query), sqlite_create_template, cfg.sqlite_table);
30 	snprintf(insert_query, sizeof(insert_query), sqlite_insert_template, cfg.sqlite_table);
31 
32 	rc = sqlite3_open(cfg.sqlite_file, &cfg.sqlite_conn);
33 	if (rc) {
34 		log_msg(LOG_ERR, "Unable to open sqlite3 database file %s", cfg.sqlite_file);
35 	}
36 
37 	log_msg(LOG_DEBUG, "Using sqlite create query: %s", create_query);
38 	rc = sqlite3_exec(cfg.sqlite_conn, create_query, 0, 0, 0);
39 	if (rc) {
40 		log_msg(LOG_ERR, "Error creating table `addrwatch` in sqlite3 database");
41 	}
42 
43 	log_msg(LOG_DEBUG, "Using sqlite insert query: %s", insert_query);
44 	rc = sqlite3_prepare_v2(cfg.sqlite_conn, insert_query,
45 		sizeof(insert_query), &cfg.sqlite_stmt, NULL);
46 	if (rc) {
47 		log_msg(LOG_ERR, "Error preparing sqlite insert statement");
48 	}
49 
50 	sqlite3_busy_timeout(cfg.sqlite_conn, 100);
51 	log_msg(LOG_DEBUG, "Saving results to %s sqlite database", cfg.sqlite_file);
52 #endif
53 }
54 
output_sqlite_reload()55 void output_sqlite_reload()
56 {
57 	output_sqlite_close();
58 	output_sqlite_init();
59 }
60 
output_sqlite_save(struct pkt * p,char * mac_str,char * ip_str)61 void output_sqlite_save(struct pkt *p, char *mac_str, char *ip_str)
62 {
63 #if HAVE_LIBSQLITE3
64 	int rc;
65 
66 	if (!cfg.sqlite_conn) {
67 		return;
68 	}
69 
70 	rc = sqlite3_bind_int64(cfg.sqlite_stmt, 1, p->pcap_header->ts.tv_sec);
71 	rc += sqlite3_bind_text(cfg.sqlite_stmt, 2, p->ifc->name, -1, NULL);
72 	rc += sqlite3_bind_int(cfg.sqlite_stmt, 3, p->vlan_tag);
73 	rc += sqlite3_bind_text(cfg.sqlite_stmt, 4, mac_str, -1, NULL);
74 	rc += sqlite3_bind_text(cfg.sqlite_stmt, 5, ip_str, -1, NULL);
75 	rc += sqlite3_bind_int(cfg.sqlite_stmt, 6, p->origin);
76 	if (rc) {
77 		log_msg(LOG_ERR, "Unable to bind values to sql statement");
78 	}
79 
80 	rc = sqlite3_step(cfg.sqlite_stmt);
81 	switch (rc) {
82 	case SQLITE_DONE:
83 		break;
84 	case SQLITE_BUSY:
85 		log_msg(LOG_WARNING, "Unable to execute sqlite prepared statement, database is locked (%ld, %s, %s, %s)",
86 			p->pcap_header->ts.tv_sec, p->ifc->name, mac_str, ip_str);
87 		break;
88 	default:
89 		log_msg(LOG_ERR, "Error executing sqlite prepared statement (%d)", rc);
90 		break;
91 	}
92 
93 	rc = sqlite3_reset(cfg.sqlite_stmt);
94 	if (rc && rc != SQLITE_BUSY) {
95 		log_msg(LOG_ERR, "Error reseting sqlite prepared statement (%d)", rc);
96 	}
97 #endif
98 }
99 
output_sqlite_close()100 void output_sqlite_close()
101 {
102 #if HAVE_LIBSQLITE3
103 	if (cfg.sqlite_conn) {
104 		sqlite3_finalize(cfg.sqlite_stmt);
105 		sqlite3_close(cfg.sqlite_conn);
106 	}
107 #endif
108 }
109