[netfilter-cvslog] r6878 - trunk/ulog/ulogd/mysql
pablo at netfilter.org
pablo at netfilter.org
Tue Jun 19 13:33:56 CEST 2007
Author: pablo at netfilter.org
Date: 2007-06-19 13:33:55 +0200 (Tue, 19 Jun 2007)
New Revision: 6878
Modified:
trunk/ulog/ulogd/mysql/ulogd_MYSQL.c
Log:
Marius Tomaschewski <mt at suse.de>
- included inttypes.h and changed to use PRId64/PRIu64 format definitions
to use correct number of l's on all platforms (WORDSIZE depending).
- added str flag to the struct _field - it is set in the mysql_get_columns
function when the IP-Addr columns in the database are non-numeric/string
and used to insert proper converted value.
See also the --with-mysql-log-ip-as-string configure option and doc dir.
- changed to use snprintf instead of sprintf to take care about the
allocated buffer length: STMT_ADD macro
- added global stmt_siz variable for the allocated size of the stmt buffer
(set in mysql_createstmt, used in mysql_output; obsoletes local size
variable in mysql_createstmt).
- Added guard at the beginning of mysql_output() triggering reconnect
if stmt_val == NULL.
- Fixed to check in mysql_output() if the buffer contains enough place for
mysql_*escape_string calls -- see mysql documentation.
- Fixed to close the old db handle before reconnect is initiated on failure
of mysql_real_query() in mysql_output.
- Increased size of allocated stmt buffer in mysql_createstmt() to +1.
- Fixed strncpy calls in mysql_createstmt and mysql_get_columns;
use ULOGD_MAX_KEYLEN-1, not ULOGD_MAX_KEYLEN and terminate the buffer
explicitelly after (in case the source string was longer / not term.).
- Fixed mysql_open_db() to close db handle after connect failure.
- Fixed _mysql_init_db() to close db handle after mysql_get_columns failure.
- Fixed _mysql_fini to call mysql_close(dbh) only if dbh not NULL and reset
it to NULL after.
Modified: trunk/ulog/ulogd/mysql/ulogd_MYSQL.c
===================================================================
--- trunk/ulog/ulogd/mysql/ulogd_MYSQL.c 2007-06-15 00:07:36 UTC (rev 6877)
+++ trunk/ulog/ulogd/mysql/ulogd_MYSQL.c 2007-06-19 11:33:55 UTC (rev 6878)
@@ -43,6 +43,7 @@
#include <ulogd/ulogd.h>
#include <ulogd/conffile.h>
#include <mysql/mysql.h>
+#include <inttypes.h>
#ifdef DEBUG_MYSQL
#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
@@ -53,6 +54,7 @@
struct _field {
char name[ULOGD_MAX_KEYLEN];
unsigned int id;
+ unsigned int str;
struct _field *next;
};
@@ -68,12 +70,21 @@
/* buffer for our insert statement */
static char *stmt;
+/* size of our insert statement buffer */
+static size_t stmt_siz;
+
/* pointer to the beginning of the "VALUES" part */
static char *stmt_val;
/* pointer to current inser position in statement */
static char *stmt_ins;
+#define STMT_ADD(fmt...) \
+ do { \
+ if (stmt_ins >= stmt && stmt_siz > stmt_ins - stmt) \
+ snprintf(stmt_ins, stmt_siz-(stmt_ins-stmt), ##fmt); \
+ } while(0)
+
/* Attempt to reconnect if connection is lost */
time_t reconnect = 0;
#define TIME_ERR ((time_t)-1) /* Be paranoid */
@@ -132,6 +143,7 @@
};
static int _mysql_init_db(ulog_iret_t *result);
+static void _mysql_fini(void);
/* our main output function, called by ulogd */
static int mysql_output(ulog_iret_t *result)
@@ -142,7 +154,13 @@
char *tmpstr; /* need this for --log-ip-as-string */
struct in_addr addr;
#endif
+ size_t esclen;
+ if (stmt_val == NULL) {
+ _mysql_fini();
+ return _mysql_init_db(result);
+ }
+
stmt_ins = stmt_val;
for (f = fields; f; f = f->next) {
@@ -155,60 +173,74 @@
if (!res || !IS_VALID((*res))) {
/* no result, we have to fake something */
- sprintf(stmt_ins, "NULL,");
+ STMT_ADD("NULL,");
stmt_ins = stmt + strlen(stmt);
continue;
}
switch (res->type) {
case ULOGD_RET_INT8:
- sprintf(stmt_ins, "%d,", res->value.i8);
+ STMT_ADD("%d,", res->value.i8);
break;
case ULOGD_RET_INT16:
- sprintf(stmt_ins, "%d,", res->value.i16);
+ STMT_ADD("%d,", res->value.i16);
break;
case ULOGD_RET_INT32:
- sprintf(stmt_ins, "%d,", res->value.i32);
+ STMT_ADD("%d,", res->value.i32);
break;
case ULOGD_RET_INT64:
- sprintf(stmt_ins, "%lld,", res->value.i64);
+ STMT_ADD("%"PRId64",", res->value.i64);
break;
case ULOGD_RET_UINT8:
- sprintf(stmt_ins, "%u,", res->value.ui8);
+ STMT_ADD("%u,", res->value.ui8);
break;
case ULOGD_RET_UINT16:
- sprintf(stmt_ins, "%u,", res->value.ui16);
+ STMT_ADD("%u,", res->value.ui16);
break;
case ULOGD_RET_IPADDR:
#ifdef IP_AS_STRING
- memset(&addr, 0, sizeof(addr));
- addr.s_addr = ntohl(res->value.ui32);
- *stmt_ins++ = '\'';
- tmpstr = inet_ntoa(addr);
+ if (f->str) {
+ addr.s_addr = ntohl(res->value.ui32);
+ tmpstr = inet_ntoa(addr);
+ esclen = (strlen(tmpstr)*2) + 4;
+ if (stmt_siz <= (stmt_ins-stmt)+esclen){
+ STMT_ADD("'',");
+ break;
+ }
+
+ *stmt_ins++ = '\'';
#ifdef OLD_MYSQL
- mysql_escape_string(stmt_ins, tmpstr,
- strlen(tmpstr));
+ mysql_escape_string(stmt_ins,
+ tmpstr,
+ strlen(tmpstr));
#else
- mysql_real_escape_string(dbh, stmt_ins,
- tmpstr,
- strlen(tmpstr));
+ mysql_real_escape_string(dbh,
+ stmt_ins,
+ tmpstr,
+ strlen(tmpstr));
#endif /* OLD_MYSQL */
- stmt_ins = stmt + strlen(stmt);
- sprintf(stmt_ins, "',");
- break;
+ stmt_ins = stmt + strlen(stmt);
+ STMT_ADD("',");
+ break;
+ }
#endif /* IP_AS_STRING */
/* EVIL: fallthrough when logging IP as
* u_int32_t */
case ULOGD_RET_UINT32:
- sprintf(stmt_ins, "%u,", res->value.ui32);
+ STMT_ADD("%u,", res->value.ui32);
break;
case ULOGD_RET_UINT64:
- sprintf(stmt_ins, "%llu,", res->value.ui64);
+ STMT_ADD("%"PRIu64",", res->value.ui64);
break;
case ULOGD_RET_BOOL:
- sprintf(stmt_ins, "'%d',", res->value.b);
+ STMT_ADD("'%d',", res->value.b);
break;
case ULOGD_RET_STRING:
+ esclen = (strlen(res->value.ptr)*2) + 4;
+ if (stmt_siz <= (stmt_ins-stmt) + esclen) {
+ STMT_ADD("'',");
+ break;
+ }
*stmt_ins++ = '\'';
#ifdef OLD_MYSQL
mysql_escape_string(stmt_ins, res->value.ptr,
@@ -218,8 +250,7 @@
res->value.ptr, strlen(res->value.ptr));
#endif
stmt_ins = stmt + strlen(stmt);
- sprintf(stmt_ins, "',");
- /* sprintf(stmt_ins, "'%s',", res->value.ptr); */
+ STMT_ADD("',");
break;
case ULOGD_RET_RAW:
ulogd_log(ULOGD_NOTICE,
@@ -235,6 +266,8 @@
stmt_ins = stmt + strlen(stmt);
}
*(stmt_ins - 1) = ')';
+ *stmt_ins = '\0';
+
DEBUGP("stmt=#%s#\n", stmt);
/* now we have created our statement, insert it */
@@ -242,6 +275,7 @@
if (mysql_real_query(dbh, stmt, strlen(stmt))) {
ulogd_log(ULOGD_ERROR, "sql error during insert: %s\n",
mysql_error(dbh));
+ _mysql_fini();
return _mysql_init_db(result);
}
@@ -261,7 +295,6 @@
static int mysql_createstmt(void)
{
struct _field *f;
- unsigned int size;
char buf[ULOGD_MAX_KEYLEN];
char *underscore;
@@ -269,36 +302,40 @@
free(stmt);
/* caclulate the size for the insert statement */
- size = strlen(MYSQL_INSERTTEMPL) + strlen(table_ce.u.string);
+ stmt_siz = strlen(MYSQL_INSERTTEMPL) + strlen(table_ce.u.string) + 1;
for (f = fields; f; f = f->next) {
/* we need space for the key and a comma, as well as
* enough space for the values */
- size += strlen(f->name) + 1 + MYSQL_VALSIZE;
+ stmt_siz += strlen(f->name) + 1 + MYSQL_VALSIZE;
}
- ulogd_log(ULOGD_DEBUG, "allocating %u bytes for statement\n", size);
+ ulogd_log(ULOGD_DEBUG, "allocating %zu bytes for statement\n",
+ stmt_siz);
- stmt = (char *) malloc(size);
+ stmt = (char *) malloc(stmt_siz);
if (!stmt) {
+ stmt_val = NULL;
+ stmt_siz = 0;
ulogd_log(ULOGD_ERROR, "OOM!\n");
return -1;
}
- sprintf(stmt, "insert into %s (", table_ce.u.string);
+ snprintf(stmt, stmt_siz, "insert into %s (", table_ce.u.string);
stmt_val = stmt + strlen(stmt);
for (f = fields; f; f = f->next) {
- strncpy(buf, f->name, ULOGD_MAX_KEYLEN);
+ strncpy(buf, f->name, ULOGD_MAX_KEYLEN-1);
+ buf[ULOGD_MAX_KEYLEN-1] = '\0';
while ((underscore = strchr(buf, '.')))
*underscore = '_';
- sprintf(stmt_val, "%s,", buf);
+ STMT_ADD(stmt_val,stmt,stmt_siz, "%s,", buf);
stmt_val = stmt + strlen(stmt);
}
*(stmt_val - 1) = ')';
- sprintf(stmt_val, " values (");
+ STMT_ADD(stmt_val,stmt,stmt_siz, " values (");
stmt_val = stmt + strlen(stmt);
ulogd_log(ULOGD_DEBUG, "stmt='%s'\n", stmt);
@@ -333,7 +370,9 @@
while ((field = mysql_fetch_field(result))) {
/* replace all underscores with dots */
- strncpy(buf, field->name, ULOGD_MAX_KEYLEN);
+ strncpy(buf, field->name, ULOGD_MAX_KEYLEN-1);
+ buf[ULOGD_MAX_KEYLEN-1] = '\0';
+
while ((underscore = strchr(buf, '_')))
*underscore = '.';
@@ -352,8 +391,10 @@
ulogd_log(ULOGD_ERROR, "OOM!\n");
return -1;
}
- strncpy(f->name, buf, ULOGD_MAX_KEYLEN);
+ strncpy(f->name, buf, ULOGD_MAX_KEYLEN-1);
+ f->name[ULOGD_MAX_KEYLEN-1] = '\0';
f->id = id;
+ f->str = !IS_NUM(field->type);
f->next = fields;
fields = f;
}
@@ -371,10 +412,14 @@
return -1;
if (connect_timeout_ce.u.value)
- mysql_options(dbh, MYSQL_OPT_CONNECT_TIMEOUT, (const char *) &connect_timeout_ce.u.value);
+ mysql_options(dbh, MYSQL_OPT_CONNECT_TIMEOUT,
+ (const char *) &connect_timeout_ce.u.value);
if (!mysql_real_connect(dbh, server, user, pass, db, port, NULL, 0))
+ {
+ _mysql_fini();
return -1;
+ }
return 0;
}
@@ -413,10 +458,17 @@
/* read the fieldnames to know which values to insert */
if (mysql_get_columns(table_ce.u.string)) {
ulogd_log(ULOGD_ERROR, "unable to get mysql columns\n");
+ _mysql_fini();
return init_reconnect();
}
- mysql_createstmt();
-
+
+ if (mysql_createstmt())
+ {
+ ulogd_log(ULOGD_ERROR, "unable to create mysql statement\n");
+ _mysql_fini();
+ return init_reconnect();
+ }
+
/* enable plugin */
mysql_plugin.output = &mysql_output;
@@ -438,7 +490,10 @@
static void _mysql_fini(void)
{
- mysql_close(dbh);
+ if (dbh) {
+ mysql_close(dbh);
+ dbh = NULL;
+ }
}
static ulog_output_t mysql_plugin = {
More information about the netfilter-cvslog
mailing list