00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042
00048 #ifdef _WIN32
00049 # define WIN32_LEAN_AND_MEAN
00050 # undef UNICODE
00051 # pragma warning(disable: 4201)
00052 # include <windows.h>
00053 # define SQL_Window 0
00054 # define XDMAPI __cdecl
00055 # define XDMEXP __declspec(dllexport)
00056 #else
00057 # define SQL_Window 1
00058 # define XDMAPI
00059 # define XDMEXP
00060 #endif
00061
00062 #include <sql.h>
00063 #include <sqlext.h>
00064
00065 #define ARRAYSZ(x) (sizeof(x)/sizeof(*(x)))
00066
00068 #define XDM_DEF_CONNSTR "DSN=xdas;"
00069
00071 static void (*s_fplogmsg)(int level, const char * msg, ... ) = 0;
00072
00074 static char * (*s_fpgetcnfstr)(const char *, char *, size_t *) = 0;
00075
00077 static SQLHENV hsql = 0;
00078 static SQLHDBC hdbc = 0;
00079 static SQLHSTMT hstmt = 0;
00080
00082 static SQLCHAR * primary_stmt = (SQLCHAR *)
00083 "INSERT INTO xdas (xdasver, timestamp, tmuncert_int, tmuncert_ind, "
00084 "timesrc, tz, event, outcome, org_loc, org_addr, org_type, org_auth, "
00085 "org_pname, org_pid, int_auth, int_dsname, int_dsid, tgt_loc, tgt_addr, "
00086 "tgt_type, tgt_auth, tgt_pname, tgt_pid, esrc, edata) VALUES "
00087 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
00088
00090 static struct xdr_tag
00091 {
00092 char xdasver[16];
00093 char timesrc[256];
00094 char tz[10];
00095 unsigned long timestamp;
00096 unsigned long tm_uncert_int;
00097 unsigned long tm_uncert_ind;
00098 unsigned long event;
00099 unsigned long outcome;
00100 char org_loc[512];
00101 char org_addr[512];
00102 char org_type[512];
00103 char org_auth[512];
00104 char org_pname[512];
00105 char org_pid[512];
00106 char int_auth[512];
00107 char int_dsname[512];
00108 char int_dsid[512];
00109 char tgt_loc[512];
00110 char tgt_addr[512];
00111 char tgt_type[512];
00112 char tgt_auth[512];
00113 char tgt_pname[512];
00114 char tgt_pid[512];
00115 char esrc[1024];
00116 char edata[1024];
00117 } xdr;
00118
00120 static struct pa_tag
00121 {
00122 SQLSMALLINT c_type, s_type;
00123 SQLUINTEGER csize;
00124 SQLPOINTER pvp;
00125 SQLINTEGER blen;
00126 } pa[] =
00127 {
00128
00129
00130 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00131 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00132 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.xdasver), xdr.xdasver, SQL_NTS},
00133 {SQL_C_ULONG, SQL_INTEGER, sizeof(xdr.timestamp), &xdr.timestamp, 0},
00134 {SQL_C_ULONG, SQL_INTEGER, sizeof(xdr.tm_uncert_int), &xdr.tm_uncert_int, 0},
00135 {SQL_C_ULONG, SQL_INTEGER, sizeof(xdr.tm_uncert_ind), &xdr.tm_uncert_ind, 0},
00136 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.timesrc), xdr.timesrc, SQL_NTS},
00137 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tz), xdr.tz, SQL_NTS},
00138 {SQL_C_ULONG, SQL_INTEGER, sizeof(xdr.event), &xdr.event, 0},
00139 {SQL_C_ULONG, SQL_INTEGER, sizeof(xdr.outcome), &xdr.outcome, 0},
00140 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00141 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.org_loc), xdr.org_loc, SQL_NTS},
00142 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.org_addr), xdr.org_addr, SQL_NTS},
00143 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.org_type), xdr.org_type, SQL_NTS},
00144 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.org_auth), xdr.org_auth, SQL_NTS},
00145 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.org_pname), xdr.org_pname, SQL_NTS},
00146 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.org_pid), xdr.org_pid, SQL_NTS},
00147 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00148 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.int_auth), xdr.int_auth, SQL_NTS},
00149 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.int_dsname), xdr.int_dsname, SQL_NTS},
00150 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.int_dsid), xdr.int_dsid, SQL_NTS},
00151 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00152 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tgt_loc), xdr.tgt_loc, SQL_NTS},
00153 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tgt_addr), xdr.tgt_addr, SQL_NTS},
00154 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tgt_type), xdr.tgt_type, SQL_NTS},
00155 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tgt_auth), xdr.tgt_auth, SQL_NTS},
00156 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tgt_pname), xdr.tgt_pname, SQL_NTS},
00157 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.tgt_pid), xdr.tgt_pid, SQL_NTS},
00158 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00159 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.esrc), xdr.esrc, SQL_NTS},
00160 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00161 {SQL_C_CHAR, SQL_VARCHAR, sizeof(xdr.edata), xdr.edata, SQL_NTS},
00162 {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0, 0, 0},
00163 };
00164
00165 static SQLINTEGER ind[ARRAYSZ(pa)];
00166
00171 static void logsqlerr(const char * fn, SQLHANDLE handle,
00172 SQLSMALLINT type, SQLRETURN rc)
00173 {
00174 SQLINTEGER i = 0;
00175 SQLINTEGER native;
00176 SQLCHAR state[32];
00177 SQLCHAR text[512];
00178 SQLSMALLINT len;
00179
00180 (*s_fplogmsg)(0, "xdm_odbc: ODBC reported %d during %s:\n", rc, fn);
00181
00182 do
00183 {
00184 if (SQL_SUCCEEDED(rc = SQLGetDiagRec(type, handle,
00185 (SQLSMALLINT)++i, state, &native, text, sizeof(text), &len)))
00186 (*s_fplogmsg)(0, "xdm_odbc: (cont) %s:%ld:%ld:%s\n", state, i, native, text);
00187 }
00188 while (SQL_SUCCEEDED(rc));
00189 }
00190
00195 static int getmsgparam(const char * cp, const char * ep,
00196 SQLSMALLINT type, SQLPOINTER buf, SQLUINTEGER bufsz)
00197 {
00198 switch(type)
00199 {
00200 case SQL_C_ULONG:
00201 {
00202 char tmp[64];
00203 size_t cnt = ep - cp > sizeof(tmp) - 1? sizeof(tmp) - 1: ep - cp;
00204 memcpy(tmp, cp, cnt);
00205 tmp[cnt] = 0;
00206 *(unsigned long *)buf = strtoul(tmp, 0, 16);
00207 break;
00208 }
00209 case SQL_C_CHAR:
00210 {
00211 unsigned i;
00212 char * op = (char *)buf;
00213 for (i = 0; cp < ep && i < bufsz - 1; i++, cp++)
00214 {
00215 if (*cp == '%') cp++;
00216 op[i] = *cp;
00217 }
00218 op[i] = 0;
00219 break;
00220 }
00221 }
00222 return 0;
00223 }
00224
00231 static int parsemsg(const char ** msgflds)
00232 {
00233 int i;
00234
00235 for (i = 0; i < ARRAYSZ(pa); i++)
00236 {
00237
00238 if (pa[i].pvp && getmsgparam(msgflds[i], msgflds[i+1],
00239 pa[i].c_type, pa[i].pvp, pa[i].csize) != 0)
00240 return -1;
00241 }
00242 return 0;
00243 }
00244
00247 static void sql_disconnect(void)
00248 {
00249 if (hstmt != 0)
00250 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00251 if (hdbc != 0)
00252 {
00253 SQLDisconnect(hdbc);
00254 SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
00255 }
00256 hstmt = hdbc = 0;
00257 }
00258
00261 static int sql_connect(void)
00262 {
00263 int i;
00264 SQLRETURN rc;
00265 SQLUSMALLINT j;
00266 char connstr[512];
00267 size_t connstrsz = sizeof(connstr);
00268
00269 if (!SQL_SUCCEEDED(rc = SQLAllocHandle(SQL_HANDLE_DBC, hsql, &hdbc)))
00270 {
00271 (*s_fplogmsg)(0, "xdm_odbc: SQLAllocHandle(SQL_HANDLE_DBC) failed, %d.\n", rc);
00272 sql_disconnect();
00273 return -1;
00274 }
00275
00276
00277 (*s_fpgetcnfstr)("xdasd.loggers.odbc.connstr", connstr, &connstrsz);
00278 if (connstrsz == 0)
00279 strcpy(connstr, XDM_DEF_CONNSTR);
00280
00281 if (!SQL_SUCCEEDED(rc = SQLDriverConnect(hdbc, (SQLHWND)SQL_Window,
00282 (SQLCHAR*)connstr, SQL_NTS, 0, 0, 0, SQL_DRIVER_COMPLETE)))
00283 {
00284 logsqlerr("SQLDriverConnect", hdbc, SQL_HANDLE_DBC, rc);
00285 sql_disconnect();
00286 return -1;
00287 }
00288
00289 (*s_fplogmsg)(0, "xdm_odbc: Connection established using [%s].\n", connstr);
00290
00291 if (!SQL_SUCCEEDED(rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt)))
00292 {
00293 (*s_fplogmsg)(0, "xdm_odbc: SQLAllocHandle(SQL_HANDLE_STMT) failed, %d.\n", rc);
00294 sql_disconnect();
00295 return -1;
00296 }
00297 if (!SQL_SUCCEEDED(rc = SQLPrepare(hstmt, primary_stmt, SQL_NTS)))
00298 {
00299 (*s_fplogmsg)(0, "xdm_odbc: SQLPrepare failed, %d.\n", rc);
00300 sql_disconnect();
00301 return -1;
00302 }
00303 for (i = 0, j = 1; i < ARRAYSZ(pa); i++)
00304 {
00305 if (pa[i].pvp)
00306 {
00307 ind[i] = pa[i].blen;
00308 if (!SQL_SUCCEEDED(rc = SQLBindParameter(hstmt, j++, SQL_PARAM_INPUT,
00309 pa[i].c_type, pa[i].s_type, pa[i].csize, 0, pa[i].pvp, 0, &ind[i])))
00310 {
00311 logsqlerr("SQLBindParameter", hstmt, SQL_HANDLE_STMT, rc);
00312 sql_disconnect();
00313 return -1;
00314 }
00315 }
00316 }
00317 return 0;
00318 }
00319
00330 XDMEXP int XDMAPI xdm_append(const char ** msgflds)
00331 {
00332 int err;
00333 SQLRETURN rc;
00334
00335 if ((err = parsemsg(msgflds)) != 0)
00336 {
00337 (*s_fplogmsg)(0, "xdm_odbc: Parse failed, error %d, for message:\n[ %s ]\n",
00338 msgflds[0]);
00339 return -1;
00340 }
00341
00342
00343 if (hdbc == 0 && (err = sql_connect()) != 0)
00344 return -1;
00345
00346
00347 if (!SQL_SUCCEEDED(rc = SQLExecute(hstmt)))
00348 {
00349
00350 sql_disconnect();
00351 if ((err = sql_connect()) != 0)
00352 {
00353 (*s_fplogmsg)(0, "xdm_odbc: ODBC Reconnect attempt failed.\n");
00354 return -1;
00355 }
00356 else
00357 {
00358
00359 if (!SQL_SUCCEEDED(rc = SQLExecute(hstmt)))
00360 {
00361 logsqlerr("SQLExecute(SQL_HANDLE_STMT)", hstmt, SQL_HANDLE_STMT, rc);
00362 return -1;
00363 }
00364 }
00365 }
00366 return 0;
00367 }
00368
00373 XDMEXP void XDMAPI xdm_exit(void)
00374 {
00375 sql_disconnect();
00376 SQLFreeHandle(SQL_HANDLE_ENV, hsql);
00377 hsql = 0;
00378 }
00379
00386 XDMEXP int XDMAPI xdm_init(void (*logmsg)(int level, const char * msg, ... ),
00387 char * (*getcnfstr)(const char *, char *, size_t *))
00388 {
00389 SQLRETURN rc;
00390
00391 s_fplogmsg = logmsg;
00392 s_fpgetcnfstr = getcnfstr;
00393
00394
00395 if (!SQL_SUCCEEDED(rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hsql)))
00396 {
00397 (*s_fplogmsg)(0, "xdm_odbc: SQLAllocHandle(SQL_HANDLE_ENV) failed, %d.\n", rc);
00398 return -1;
00399 }
00400 if (!SQL_SUCCEEDED(rc = SQLSetEnvAttr(hsql, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0)))
00401 {
00402 (*s_fplogmsg)(0, "xdm_odbc: SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION) failed, %d.\n", rc);
00403 SQLFreeHandle(SQL_HANDLE_ENV, hsql);
00404 return -1;
00405 }
00406 return 0;
00407 }
00408