Search
j0ke.net Open Build Service
>
Projects
>
ha
:
firewall
>
ulogd
> ulogd-1.24-fixes-pgsql.dif
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File ulogd-1.24-fixes-pgsql.dif of Package ulogd
--- pgsql/ulogd_PGSQL.c +++ pgsql/ulogd_PGSQL.c 2007/05/30 15:27:23 @@ -16,7 +16,7 @@ #include <ulogd/ulogd.h> #include <ulogd/conffile.h> #include <libpq-fe.h> - +#include <inttypes.h> #ifdef DEBUG_PGSQL #define DEBUGP(x, args...) fprintf(stderr, x, ## args) @@ -27,6 +27,7 @@ struct _field { char name[ULOGD_MAX_KEYLEN]; unsigned int id; + unsigned int str; struct _field *next; }; @@ -39,6 +40,9 @@ static struct _field *fields; /* 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; @@ -97,6 +101,12 @@ static config_entry_t port_ce = { static unsigned char pgsql_have_schemas; +#define STMT_ADD(pos,beg,siz,fmt...) \ + do { \ + if((pos) >= (beg) && (siz) > (pos) - (beg)) \ + snprintf((pos), (siz)-((pos)-(beg)), ##fmt); \ + } while(0) + /* our main output function, called by ulogd */ static int pgsql_output(ulog_iret_t *result) { @@ -108,6 +118,9 @@ static int pgsql_output(ulog_iret_t *res struct in_addr addr; #endif + if( stmt_val == NULL) + return 1; + stmt_ins = stmt_val; for (f = fields; f; f = f->next) { @@ -120,62 +133,80 @@ static int pgsql_output(ulog_iret_t *res if (!res || !IS_VALID((*res))) { /* no result, we have to fake something */ - sprintf(stmt_ins, "NULL,"); + STMT_ADD(stmt_ins,stmt,stmt_siz, "NULL,"); stmt_ins = stmt + strlen(stmt); continue; } switch (res->type) { case ULOGD_RET_INT8: - sprintf(stmt_ins, "%d,", res->value.i8); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%d,", res->value.i8); break; case ULOGD_RET_INT16: - sprintf(stmt_ins, "%d,", res->value.i16); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%d,", res->value.i16); break; case ULOGD_RET_INT32: - sprintf(stmt_ins, "%d,", res->value.i32); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%d,", res->value.i32); break; case ULOGD_RET_INT64: - sprintf(stmt_ins, "%lld,", res->value.i64); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%"PRId64",", res->value.i64); break; case ULOGD_RET_UINT8: - sprintf(stmt_ins, "%u,", res->value.ui8); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%u,", res->value.ui8); break; case ULOGD_RET_UINT16: - sprintf(stmt_ins, "%u,", res->value.ui16); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%u,", res->value.ui16); break; case ULOGD_RET_IPADDR: #ifdef IP_AS_STRING - *stmt_ins++ = '\''; - memset(&addr, 0, sizeof(addr)); - addr.s_addr = ntohl(res->value.ui32); - tmpstr = (char *)inet_ntoa(addr); - PQescapeString(stmt_ins,tmpstr,strlen(tmpstr)); - stmt_ins = stmt + strlen(stmt); - sprintf(stmt_ins, "',"); - break; + if(f->str) + { + memset(&addr, 0, sizeof(addr)); + addr.s_addr = ntohl(res->value.ui32); + tmpstr = (char *)inet_ntoa(addr); + + if(stmt_siz > (stmt_ins-stmt)+(strlen(tmpstr)*2)+4) + { + *stmt_ins++ = '\''; + PQescapeString(stmt_ins,tmpstr,strlen(tmpstr)); + stmt_ins = stmt + strlen(stmt); + STMT_ADD(stmt_ins,stmt,stmt_siz, "',"); + } + else + { + STMT_ADD(stmt_ins,stmt,stmt_siz, "'',"); + } + 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(stmt_ins,stmt,stmt_siz, "%u,", res->value.ui32); break; case ULOGD_RET_UINT64: - sprintf(stmt_ins, "%llu,", res->value.ui64); + STMT_ADD(stmt_ins,stmt,stmt_siz, "%"PRIu64",", res->value.ui64); break; case ULOGD_RET_BOOL: - sprintf(stmt_ins, "'%d',", res->value.b); + STMT_ADD(stmt_ins,stmt,stmt_siz, "'%d',", res->value.b); break; case ULOGD_RET_STRING: - *stmt_ins++ = '\''; - PQescapeString(stmt_ins,res->value.ptr,strlen(res->value.ptr)); - stmt_ins = stmt + strlen(stmt); - sprintf(stmt_ins, "',"); + if(stmt_siz > (stmt_ins-stmt)+(strlen(res->value.ptr)*2)+4) + { + *stmt_ins++ = '\''; + PQescapeString(stmt_ins,res->value.ptr,strlen(res->value.ptr)); + stmt_ins = stmt + strlen(stmt); + STMT_ADD(stmt_ins,stmt,stmt_siz, "',"); + } + else + { + STMT_ADD(stmt_ins,stmt,stmt_siz, "'',"); + } break; case ULOGD_RET_RAW: ulogd_log(ULOGD_NOTICE,"%s: pgsql doesn't support type RAW\n",res->key); - sprintf(stmt_ins, "NULL,"); + STMT_ADD(stmt_ins,stmt,stmt_siz, "NULL,"); break; default: ulogd_log(ULOGD_NOTICE, @@ -186,6 +217,7 @@ static int pgsql_output(ulog_iret_t *res stmt_ins = stmt + strlen(stmt); } *(stmt_ins - 1) = ')'; + DEBUGP("stmt=#%s#\n", stmt); /* now we have created our statement, insert it */ @@ -212,7 +244,7 @@ static int pgsql_namespace(void) { if (!dbh) return 1; - sprintf(pgbuf, PGSQL_HAVE_NAMESPACE_TEMPLATE, schema_ce.u.string); + snprintf(pgbuf, sizeof(pgbuf), PGSQL_HAVE_NAMESPACE_TEMPLATE, schema_ce.u.string); ulogd_log(ULOGD_DEBUG, "%s\n", pgbuf); result = PQexec(dbh, pgbuf); @@ -240,7 +272,6 @@ static int pgsql_namespace(void) { static int pgsql_createstmt(void) { struct _field *f; - unsigned int size; char buf[ULOGD_MAX_KEYLEN]; char *underscore; @@ -251,41 +282,43 @@ static int pgsql_createstmt(void) } /* caclulate the size for the insert statement */ - size = strlen(PGSQL_INSERTTEMPL) + strlen(table_ce.u.string) + strlen(schema_ce.u.string) + 1; + stmt_siz = strlen(PGSQL_INSERTTEMPL) + strlen(table_ce.u.string) + strlen(schema_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 + PGSQL_VALSIZE; + stmt_siz += strlen(f->name) + 1 + PGSQL_VALSIZE; } - ulogd_log(ULOGD_DEBUG, "allocating %u bytes for statement\n", size); + ulogd_log(ULOGD_DEBUG, "allocating %u bytes for statement\n", stmt_siz); - stmt = (char *) malloc(size); + stmt = (char *) malloc(stmt_siz); if (!stmt) { + stmt_siz = 0; ulogd_log(ULOGD_ERROR, "OOM!\n"); return 1; } if (pgsql_have_schemas) { - sprintf(stmt, "insert into %s.%s (", schema_ce.u.string, table_ce.u.string); + snprintf(stmt, stmt_siz, "insert into %s.%s (", schema_ce.u.string, table_ce.u.string); } else { - 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); @@ -293,9 +326,9 @@ static int pgsql_createstmt(void) return 0; } -#define PGSQL_GETCOLUMN_TEMPLATE "SELECT a.attname FROM pg_class c, pg_attribute a WHERE c.relname ='%s' AND a.attnum>0 AND a.attrelid=c.oid ORDER BY a.attnum" +#define PGSQL_GETCOLUMN_TEMPLATE "SELECT a.attname,t.typname FROM pg_class c, pg_attribute a, pg_type t WHERE c.relname ='%s' AND a.attnum>0 AND a.attrelid=c.oid AND a.atttypid=t.oid ORDER BY a.attnum" -#define PGSQL_GETCOLUMN_TEMPLATE_SCHEMA "SELECT a.attname FROM pg_attribute a, pg_class c LEFT JOIN pg_namespace n ON c.relnamespace=n.oid WHERE c.relname ='%s' AND n.nspname='%s' AND a.attnum>0 AND a.attrelid=c.oid AND a.attisdropped=FALSE ORDER BY a.attnum" +#define PGSQL_GETCOLUMN_TEMPLATE_SCHEMA "SELECT a.attname,t.typname FROM pg_attribute a, pg_type t, pg_class c LEFT JOIN pg_namespace n ON c.relnamespace=n.oid WHERE c.relname ='%s' AND n.nspname='%s' AND a.attnum>0 AND a.attrelid=c.oid AND a.atttypid=t.oid AND a.attisdropped=FALSE ORDER BY a.attnum" /* find out which columns the table has */ static int pgsql_get_columns(const char *table) @@ -307,6 +340,7 @@ static int pgsql_get_columns(const char struct _field *f; int id; int intaux; + char *typename; if (!dbh) return 1; @@ -333,7 +367,8 @@ static int pgsql_get_columns(const char for (intaux=0; intaux<PQntuples(result); intaux++) { /* replace all underscores with dots */ - strncpy(buf, PQgetvalue(result, intaux, 0), ULOGD_MAX_KEYLEN); + strncpy(buf, PQgetvalue(result, intaux, 0), ULOGD_MAX_KEYLEN-1); + buf[ULOGD_MAX_KEYLEN-1] = '\0'; while ((underscore = strchr(buf, '_'))) *underscore = '.'; @@ -352,8 +387,16 @@ static int pgsql_get_columns(const char 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 = 0; + if( (typename = PQgetvalue(result, intaux, 1)) != NULL) + { + if(strcmp(typename, "inet") == 0 || + strstr(typename, "char") != NULL) + f->str = 1; + } f->next = fields; fields = f; } @@ -386,34 +429,37 @@ static int pgsql_open_db(char *server, i if (port) len += 20; - connstr = (char *) malloc(len); + connstr = (char *) malloc(len+1); if (!connstr) return 1; + *connstr = '\0'; if (server) { - strcpy(connstr, " host="); - strcat(connstr, server); + strncat(connstr, " host=", len-strlen(connstr)); + strncat(connstr, server, len-strlen(connstr)); } if (port) { char portbuf[20]; snprintf(portbuf, sizeof(portbuf), " port=%u", port); - strcat(connstr, portbuf); + strncat(connstr, portbuf, len-strlen(connstr)); } - strcat(connstr, " dbname="); - strcat(connstr, db); - strcat(connstr, " user="); - strcat(connstr, user); + strncat(connstr, " dbname=", len-strlen(connstr)); + strncat(connstr, db, len-strlen(connstr)); + strncat(connstr, " user=", len-strlen(connstr)); + strncat(connstr, user, len-strlen(connstr)); if (pass) { - strcat(connstr, " password="); - strcat(connstr, pass); + strncat(connstr, " password=", len-strlen(connstr)); + strncat(connstr, pass, len-strlen(connstr)); } dbh = PQconnectdb(connstr); + free(connstr); if (PQstatus(dbh)!=CONNECTION_OK) { exit_nicely(dbh); + dbh = NULL; return 1; } @@ -432,23 +478,39 @@ static int pgsql_init(void) } if (pgsql_namespace()) { - return 1; + PQfinish(dbh); + dbh = NULL; ulogd_log(ULOGD_ERROR, "unable to test for pgsql schemas\n"); + return 1; } /* read the fieldnames to know which values to insert */ if (pgsql_get_columns(table_ce.u.string)) { + PQfinish(dbh); + dbh = NULL; ulogd_log(ULOGD_ERROR, "unable to get pgsql columns\n"); return 1; } - pgsql_createstmt(); + + if(pgsql_createstmt()) { + PQfinish(dbh); + dbh = NULL; + return 1; + } return 0; } static void pgsql_fini(void) { - PQfinish(dbh); + if(dbh) + PQfinish(dbh); + if(stmt) + { + free(stmt); + stmt = NULL; + stmt_val = NULL; + } } static ulog_output_t pgsql_plugin = {