xdm_odbc.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002  * Copyright (c) 2006, Novell, Inc.
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions are 
00007  * met:
00008  * 
00009  *     * Redistributions of source code must retain the above copyright 
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright 
00012  *       notice, this list of conditions and the following disclaimer in the 
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the Novell nor the names of its contributors 
00015  *       may be used to endorse or promote products derived from this 
00016  *       software without specific prior written permission.
00017  * 
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00019  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00020  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00021  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
00022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
00025  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
00026  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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) /* non-standard extension used : nameless structure/union */
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 /*  C data type       SQL data type     Column Size                Buffer Addr         Buf Len
00129     ----------------- ----------------- -------------------------- ------------------- -------- */
00130    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 0  HDR:     */
00131    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 1  hex4len: */
00132    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.xdasver),       xdr.xdasver,        SQL_NTS}, /* 2  xdasver: */
00133    {SQL_C_ULONG,      SQL_INTEGER,      sizeof(xdr.timestamp),     &xdr.timestamp,     0},       /* 3  tstamp:  */
00134    {SQL_C_ULONG,      SQL_INTEGER,      sizeof(xdr.tm_uncert_int), &xdr.tm_uncert_int, 0},       /* 4  tuinter: */
00135    {SQL_C_ULONG,      SQL_INTEGER,      sizeof(xdr.tm_uncert_ind), &xdr.tm_uncert_ind, 0},       /* 5  tuindic: */
00136    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.timesrc),       xdr.timesrc,        SQL_NTS}, /* 6  tsrc:    */
00137    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tz),            xdr.tz,             SQL_NTS}, /* 7  tzone:   */
00138    {SQL_C_ULONG,      SQL_INTEGER,      sizeof(xdr.event),         &xdr.event,         0},       /* 8  event:   */
00139    {SQL_C_ULONG,      SQL_INTEGER,      sizeof(xdr.outcome),       &xdr.outcome,       0},       /* 9  outcome: */
00140    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 10 ORG:     */
00141    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.org_loc),       xdr.org_loc,        SQL_NTS}, /* 11 orgloc:  */
00142    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.org_addr),      xdr.org_addr,       SQL_NTS}, /* 12 orgaddr: */
00143    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.org_type),      xdr.org_type,       SQL_NTS}, /* 13 orgtype: */
00144    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.org_auth),      xdr.org_auth,       SQL_NTS}, /* 14 orgauth: */
00145    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.org_pname),     xdr.org_pname,      SQL_NTS}, /* 15 orgpname:*/
00146    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.org_pid),       xdr.org_pid,        SQL_NTS}, /* 16 orgpid:  */
00147    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 17 INT:     */
00148    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.int_auth),      xdr.int_auth,       SQL_NTS}, /* 18 intauth: */
00149    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.int_dsname),    xdr.int_dsname,     SQL_NTS}, /* 19 intdsnam:*/
00150    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.int_dsid),      xdr.int_dsid,       SQL_NTS}, /* 20 intdsid: */
00151    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 21 TGT:     */
00152    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tgt_loc),       xdr.tgt_loc,        SQL_NTS}, /* 22 tgtloc:  */
00153    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tgt_addr),      xdr.tgt_addr,       SQL_NTS}, /* 23 tgtaddr: */
00154    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tgt_type),      xdr.tgt_type,       SQL_NTS}, /* 24 tgttype: */
00155    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tgt_auth),      xdr.tgt_auth,       SQL_NTS}, /* 25 tgtauth: */
00156    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tgt_pname),     xdr.tgt_pname,      SQL_NTS}, /* 26 tgtpname:*/
00157    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.tgt_pid),       xdr.tgt_pid,        SQL_NTS}, /* 27 tgtpid:  */
00158    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 28 SRC:     */
00159    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.esrc),          xdr.esrc,           SQL_NTS}, /* 29 src:     */
00160    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 30 EVT:     */
00161    {SQL_C_CHAR,       SQL_VARCHAR,      sizeof(xdr.edata),         xdr.edata,          SQL_NTS}, /* 31 edata:   */
00162    {SQL_UNKNOWN_TYPE, SQL_UNKNOWN_TYPE, 0,                         0,                  0},       /* 32 END      */
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++;   /* skip escape characters */
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       /* extract only fields we care about */
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    /* Read connection string from the configuration file. */
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    /* first time? - establish initial connection and prepare statement */
00343    if (hdbc == 0 && (err = sql_connect()) != 0)
00344       return -1;     /* sql_connect logs its own errors */
00345 
00346    /* attempt one: execute the statement */
00347    if (!SQL_SUCCEEDED(rc = SQLExecute(hstmt)))
00348    {
00349       /* statement execution failed - disconnect and attempt to reconnect */
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          /* now try statement execution again */
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;       /* save logmsg function pointer */
00392    s_fpgetcnfstr = getcnfstr; /* save get conf str function pointer */
00393 
00394    /* establish environment handle and set ODBC version */
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 

Generated on Thu Aug 20 22:33:05 2009 for OpenXDAS by  doxygen 1.5.6