1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
10 /* Common lib for dealing with databases */
15 void *(*osdb_connect)(const char *host, const char *user, const char *pass, const char *db, unsigned int port, const char *sock);
16 int (* osdb_query_insert)(void *db_conn, const char *query);
17 int (* osdb_query_select)(void *db_conn, const char *query);
18 void *(*osdb_close)(void *db_conn);
19 const unsigned char insert_map[256] = {
20 0, 0, 0, 0, 0, 0, 0, 0,
21 0, 0, 1, 0, 0, 0, 0, 0,
22 0, 0, 0, 0, 0, 0, 0, 0,
23 0, 0, 0, 0, 0, 0, 0, 0,
24 1, 1, 1, 1, 1, 1, 1, 0,
25 1, 1, 1, 1, 1, 1, 1, 1,
26 1, 1, 1, 1, 1, 1, 1, 1,
27 1, 1, 1, 1, 1, 1, 1, 1,
28 1, 1, 1, 1, 1, 1, 1, 1,
29 1, 1, 1, 1, 1, 1, 1, 1,
30 1, 1, 1, 1, 1, 1, 1, 1,
31 1, 1, 1, 1, 1, 1, 1, 1,
32 1, 1, 1, 1, 1, 1, 1, 1,
33 1, 1, 1, 1, 1, 1, 1, 1,
34 1, 1, 1, 1, 1, 1, 1, 1,
35 1, 1, 1, 1, 1, 1, 1, 0,
36 0, 0, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0,
38 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0,
42 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0,
54 #ifdef MYSQL_DATABASE_ENABLED
58 #ifdef PGSQL_DATABASE_ENABLED
62 #if defined(MYSQL_DATABASE_ENABLED) || defined(PGSQL_DATABASE_ENABLED)
63 static void osdb_checkerror(void);
64 static void osdb_seterror(void);
68 static DBConfig *db_config_pt = NULL;
71 /* Escapes a null terminated string before inserting into the database
72 * We built a allow list of allowed characters at insert_map. Everything
73 * not allowed will become a space.
75 void osdb_escapestr(char *str)
84 } else if (*str == '\\') {
86 } else if (insert_map[(unsigned char)*str] != '\001') {
92 /* It can not end with \\ */
93 if (*(str - 1) == '\\') {
98 #if defined(MYSQL_DATABASE_ENABLED) || defined(PGSQL_DATABASE_ENABLED)
100 /* Check for errors and handle them appropriately */
101 static void osdb_checkerror()
103 if (!db_config_pt || db_config_pt->error_count > 20) {
104 ErrorExit(DB_MAINERROR, ARGV0);
107 /* If error count is too large, we try to reconnect */
108 if (db_config_pt->error_count > 0) {
109 unsigned int i = 0, sleep_time = 2;
111 if (db_config_pt->conn) {
112 osdb_close(db_config_pt->conn);
113 db_config_pt->conn = NULL;
116 while (i <= db_config_pt->maxreconnect) {
117 merror(DB_ATTEMPT, ARGV0);
118 db_config_pt->conn = osdb_connect(db_config_pt->host,
125 /* If we were able to reconnect, keep going */
126 if (db_config_pt->conn) {
134 /* If we weren't able to connect, exit */
135 if (!db_config_pt->conn) {
136 ErrorExit(DB_MAINERROR, ARGV0);
139 verbose("%s: Connected to database '%s' at '%s'.",
140 ARGV0, db_config_pt->db, db_config_pt->host);
144 /* Set the error counter */
145 static void osdb_seterror()
147 db_config_pt->error_count++;
154 /* Create an internal pointer to the db configuration */
155 void osdb_setconfig(DBConfig *db_config)
157 db_config_pt = db_config;
161 #ifdef MYSQL_DATABASE_ENABLED
163 /* Create the database connection
164 * Returns NULL on error
166 void *mysql_osdb_connect(const char *host, const char *user, const char *pass, const char *db,
167 unsigned int port, const char *sock)
170 conn = mysql_init(NULL);
172 merror(DBINIT_ERROR, ARGV0);
176 /* If host is 127.0.0.1 or localhost, use TCP socket */
177 if ((strcmp(host, "127.0.0.1") == 0) ||
178 (strcmp(host, "::1") == 0) ||
179 (strcmp(host, "localhost") == 0)) {
181 mysql_options(conn, MYSQL_OPT_NAMED_PIPE, NULL);
183 unsigned int p_type = MYSQL_PROTOCOL_TCP;
184 mysql_options(conn, MYSQL_OPT_PROTOCOL, (char *)&p_type);
187 if (mysql_real_connect(conn, host, user, pass, db,
188 port, sock, 0) == NULL) {
189 merror(DBCONN_ERROR, ARGV0, host, db, mysql_error(conn));
197 /* Close the database connection */
198 void *mysql_osdb_close(void *db_conn)
200 merror(DB_CLOSING, ARGV0);
201 mysql_close(db_conn);
205 /* Sends insert query to database */
206 int mysql_osdb_query_insert(void *db_conn, const char *query)
208 if (mysql_query(db_conn, query) != 0) {
209 /* failure; report error */
210 merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn));
218 /* Sends a select query to database. Returns the value of it.
219 * Returns 0 on error (not found).
221 int mysql_osdb_query_select(void *db_conn, const char *query)
224 MYSQL_RES *result_data;
225 MYSQL_ROW result_row;
227 /* Send the query. It can not fail. */
228 if (mysql_query(db_conn, query) != 0) {
229 /* Failure: report error */
230 merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn));
236 result_data = mysql_use_result(db_conn);
237 if (result_data == NULL) {
238 /* Failure: report error */
239 merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn));
244 /* Get row. We only care about the first result. */
245 result_row = mysql_fetch_row(result_data);
246 if (result_row && (result_row[0] != NULL)) {
247 result_int = atoi(result_row[0]);
250 mysql_free_result(result_data);
255 /** End of MySQL calls **/
257 /** PostgreSQL Calls **/
258 #ifdef PGSQL_DATABASE_ENABLED
260 /* Create the PostgreSQL database connection
261 * Returns NULL on error
263 void *postgresql_osdb_connect(const char *host, const char *user, const char *pass, const char *db,
264 unsigned int port, __attribute__((unused)) const char *sock)
267 char portAsString[6];
270 snprintf(portAsString, 6, "%u", port);
272 snprintf(portAsString, 6, "");
275 conn = PQsetdbLogin(host, portAsString, NULL, NULL, db, user, pass);
277 if (PQstatus(conn) == CONNECTION_BAD) {
278 merror(DBCONN_ERROR, ARGV0, host, db, PQerrorMessage(conn));
286 /* Terminates db connection */
287 void *postgresql_osdb_close(void *db_conn)
289 merror(DB_CLOSING, ARGV0);
294 /* Send insert query to database */
295 int postgresql_osdb_query_insert(void *db_conn, const char *query)
299 result = PQexec(db_conn, query);
301 merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
306 if (PQresultStatus(result) != PGRES_COMMAND_OK) {
307 merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
318 /* Send a select query to database. Returns the value of it.
319 * Returns 0 on error (not found).
321 int postgresql_osdb_query_select(void *db_conn, const char *query)
326 result = PQexec(db_conn, query);
328 merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
333 if ((PQresultStatus(result) == PGRES_TUPLES_OK)) {
334 if (PQntuples(result) == 1) {
335 result_int = atoi(PQgetvalue(result, 0, 0));
338 merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
348 /** End of PostgreSQL calls **/
351 /* Everything else when db is not defined */
352 #if !defined(PGSQL_DATABASE_ENABLED) && !defined(MYSQL_DATABASE_ENABLED)
354 void *none_osdb_connect(__attribute__((unused)) const char *host, __attribute__((unused)) const char *user,
355 __attribute__((unused)) const char *pass, __attribute__((unused)) const char *db,
356 __attribute__((unused)) unsigned int port, __attribute__((unused)) const char *sock)
358 merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
361 void *none_osdb_close(__attribute__((unused)) void *db_conn)
363 merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
366 int none_osdb_query_insert(__attribute__((unused)) void *db_conn, __attribute__((unused)) const char *query)
368 merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
371 int none_osdb_query_select(__attribute__((unused)) void *db_conn, __attribute__((unused)) const char *query)
373 merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);