OSSP CVS Repository

ossp - Difference in ossp-pkg/l2/l2_ch_syslog.c versions 1.20 and 1.21
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/l2/l2_ch_syslog.c 1.20 -> 1.21

--- l2_ch_syslog.c       2001/09/12 09:42:34     1.20
+++ l2_ch_syslog.c       2001/09/14 19:11:00     1.21
@@ -28,33 +28,123 @@
 */
 
 #include "l2.h"
+#include "l2_p.h"
 
 #include <syslog.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <unistd.h>
 
 /* declare private channel configuration */
 typedef struct {
-    char *pszIdent; /* String to prepend to each syslog message */
-    int iLogopt;    /* Manipulates how kernel interacts with syslogd */
-    int iFacility;  /* Which part of the system generates this message */
-    int iPriority;  /* EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO... */
-    int iMaskpri;   /* Controls which priorities are or are not logged */
+    char      *szTarget;
+    char      *szRemoteHost;
+    int        nRemotePort;
+    char      *szLocalHost;
+    char      *szFacility;
+    int        nFacility;
+    char      *szIdent;
+    int        bLogPid;
+    sa_t      *saRemoteSock;
+    sa_addr_t *saaRemoteAddr;
 } l2_ch_syslog_t;
 
+/* mapping from L2 log levels to syslog(3) log levels */
+static struct {
+    int levelL2;
+    int levelSL;
+} l2_ch_syslog_L2toSL[] = {
+    { L2_LEVEL_PANIC,    LOG_EMERG   },
+    { L2_LEVEL_CRITICAL, LOG_CRIT    },
+    { L2_LEVEL_ERROR,    LOG_ERR         },
+    { L2_LEVEL_WARNING,  LOG_WARNING },
+    { L2_LEVEL_NOTICE,   LOG_NOTICE  },
+    { L2_LEVEL_INFO,     LOG_INFO        },
+    { L2_LEVEL_TRACE,    LOG_INFO    },
+    { L2_LEVEL_DEBUG,    LOG_DEBUG   },
+    { -1,                -1          }
+};
+
+/* Syslog Facility Table */
+static struct {
+    char *name;      /* the common name */
+    int   numREMOTE; /* number according to RFC3164 */
+    int   numLOCAL;  /* local encoding */
+} l2_ch_syslog_SLfac[] = {
+    { "kern",      0,      LOG_KERN     },
+    { "user",      1,      LOG_USER     },
+    { "mail",      2,      LOG_MAIL     },
+    { "daemon",    3,      LOG_DAEMON   },
+    { "auth",      4,      LOG_AUTH     },
+#ifndef LOG_SYSLOG
+#define LOG_SYSLOG   (5 << 3)
+#endif
+    { "syslog",    5,      LOG_SYSLOG   },
+    { "lpr",       6,      LOG_LPR      },
+    { "news",      7,      LOG_NEWS     },
+    { "uucp",      8,      LOG_UUCP     },
+    { "cron",      9,      LOG_CRON     },
+#ifndef LOG_AUTHPRIV
+#define LOG_AUTHPRIV (10 << 3)
+#endif
+    { "authpriv", 10,      LOG_AUTHPRIV },
+    { "ftp",      11,      LOG_FTP      },
+#ifndef LOG_NTP
+#define LOG_NTP      (12 << 3)
+#endif
+    { "ntp",      12,      LOG_NTP      },
+#ifndef LOG_SECURITY
+#define LOG_SECURITY (13 << 3)
+#endif
+    { "security", 13,      LOG_SECURITY },
+#ifndef LOG_CONSOLE
+#define LOG_CONSOLE  (14 << 3)
+#endif
+    { "console",  14,      LOG_CONSOLE  },
+#ifndef LOG_CLOCK
+#define LOG_CLOCK    (15 << 3)
+#endif
+    { "clock",    15,      LOG_CLOCK    },
+    { "local0",   16,      LOG_LOCAL0   },
+    { "local1",   17,      LOG_LOCAL1   },
+    { "local2",   18,      LOG_LOCAL2   },
+    { "local3",   19,      LOG_LOCAL3   },
+    { "local4",   20,      LOG_LOCAL4   },
+    { "local5",   21,      LOG_LOCAL5   },
+    { "local6",   22,      LOG_LOCAL6   },
+    { "local7",   23,      LOG_LOCAL7   },
+    { NULL,       0,       0            }
+};
+
 /* create channel */
 static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch)
 {
     l2_ch_syslog_t *cfg;
+    struct utsname uts;
+    char *cp;
 
     /* allocate private channel configuration */
     if ((cfg = (l2_ch_syslog_t *)malloc(sizeof(l2_ch_syslog_t))) == NULL)
         return L2_ERR_MEM;
 
     /* initialize configuration with reasonable defaults */
-    cfg->pszIdent  = NULL;
-    cfg->iLogopt   = 0;
-    cfg->iFacility = LOG_USER;
-    cfg->iPriority = (LOG_DEBUG|LOG_ERR);
-    cfg->iMaskpri  = (0xFFFFFFFF); /* Allow all priorities to pass through */
+    cfg->szTarget      = strdup("local");
+    cfg->szRemoteHost  = NULL;
+    cfg->nRemotePort   = 514;
+    if (uname(&uts) == 0) {
+        cfg->szLocalHost = strdup(uts.nodename);
+        if ((cp = strchr(cfg->szLocalHost, '.')) != NULL)
+            *cp = '\0';
+    }
+    else
+        cfg->szLocalHost = strdup("localhost");
+    cfg->szFacility    = strdup("user");
+    cfg->nFacility     = LOG_USER;
+    cfg->szIdent       = NULL;
+    cfg->bLogPid       = FALSE;
+    cfg->saRemoteSock  = NULL;
+    cfg->saaRemoteAddr = NULL;
 
     /* link private channel configuration into channel context */
     ctx->vp = cfg;
@@ -66,18 +156,45 @@
 static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap)
 {
     l2_ch_syslog_t *cfg = (l2_ch_syslog_t *)ctx->vp;
-    l2_param_t pa[6];
+    l2_param_t pa[8];
     l2_result_t rv;
+    int i;
 
     /* feed and call generic parameter parsing engine */
-    L2_PARAM_SET(pa[0], ident,   CHARPTR,  &cfg->pszIdent);
-    L2_PARAM_SET(pa[1], logopts, INT,      &cfg->iLogopt);
-    L2_PARAM_SET(pa[2], facility, INT,     &cfg->iFacility);
-    L2_PARAM_SET(pa[3], priority, INT,     &cfg->iPriority);
-    L2_PARAM_SET(pa[4], maskpriority, INT, &cfg->iMaskpri);
-    L2_PARAM_END(pa[5]);
-    rv = l2_util_setparams(pa, fmt, ap);
+    L2_PARAM_SET(pa[0], target,     STRING, &cfg->szTarget);
+    L2_PARAM_SET(pa[1], remotehost, STRING, &cfg->szRemoteHost);
+    L2_PARAM_SET(pa[2], remoteport, INT,    &cfg->nRemotePort);
+    L2_PARAM_SET(pa[3], localhost,  STRING, &cfg->szLocalHost);
+    L2_PARAM_SET(pa[4], facility,   STRING, &cfg->szFacility);
+    L2_PARAM_SET(pa[5], ident,      STRING, &cfg->szIdent);
+    L2_PARAM_SET(pa[6], logpid,     INT,    &cfg->bLogPid);
+    L2_PARAM_END(pa[7]);
 
+    /* sanity checking & post-processing */
+    rv = l2_util_setparams(pa, fmt, ap);
+    if (cfg->szTarget == NULL || cfg->szFacility == NULL)
+        return L2_ERR_USE;
+    if (!(   strcmp(cfg->szTarget, "local") == 0
+          || strcmp(cfg->szTarget, "remote") == 0))
+        return L2_ERR_USE;
+    for (i = 0; l2_ch_syslog_SLfac[i].name != NULL; i++)
+        if (strcmp(l2_ch_syslog_SLfac[i].name, cfg->szFacility) == 0)
+            break;
+    if (l2_ch_syslog_SLfac[i].name == NULL)
+        return L2_ERR_USE;
+    if (strcmp(cfg->szTarget, "local") == 0)
+        cfg->nFacility = l2_ch_syslog_SLfac[i].numLOCAL;
+    else
+        cfg->nFacility = (l2_ch_syslog_SLfac[i].numREMOTE << 3);
+    if (   strcmp(cfg->szTarget, "remote") == 0 
+        && (cfg->szRemoteHost == NULL
+            || (cfg->nRemotePort <= 0 || cfg->nRemotePort >= 65536)))
+        return L2_ERR_USE;
+    if (   cfg->szLocalHost == NULL
+        || strchr(cfg->szLocalHost, '.') != NULL)
+        return L2_ERR_USE;
+    if (cfg->szIdent != NULL && strlen(cfg->szIdent) > (32-(1+5+1)))
+        return L2_ERR_USE;
     return rv;
 }
 
@@ -85,11 +202,36 @@
 static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch)
 {
     l2_ch_syslog_t *cfg = (l2_ch_syslog_t *)ctx->vp;
-
-    /* open channel syslog */
-    openlog(cfg->pszIdent, cfg->iLogopt, cfg->iFacility);
-    setlogmask(cfg->iMaskpri);
-
+    int opt;
+    sa_rc_t rc;
+    sa_addr_t *la;
+
+    if (cfg->szIdent == NULL)
+        return L2_ERR_USE;
+    if (strcmp(cfg->szTarget, "local") == 0) {
+        /* open local syslog connection via syslog(3) */
+        opt = 0;
+        if (cfg->bLogPid)
+            opt |= LOG_PID;
+        openlog(cfg->szIdent, opt, cfg->nFacility);
+        /* setlogmask(0); */
+    }
+    else {
+        /* open remote syslog connection via UDP socket */
+        if (cfg->szRemoteHost == NULL)
+            return L2_ERR_USE;
+        if ((rc = sa_u2a(&cfg->saaRemoteAddr, "udp://%s:%d", 
+                         cfg->szRemoteHost, cfg->nRemotePort)) != SA_OK)
+            return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+        if ((rc = sa_create(&cfg->saRemoteSock)) != SA_OK)
+            return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+        sa_timeout(cfg->saRemoteSock, 10, 0);
+        /* FIXME: if uid == 0 -> use port 514 */
+        if ((rc = sa_u2a(&la, "udp://0.0.0.0:0")) != SA_OK)
+            return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+        if ((rc = sa_bind(cfg->saRemoteSock, la)) != SA_OK)
+            return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+    }
     return L2_OK;
 }
 
@@ -98,9 +240,56 @@
                               l2_level_t level, const char *buf, size_t buf_size)
 {
     l2_ch_syslog_t *cfg = (l2_ch_syslog_t *)ctx->vp;
-
-    /* write message to channel syslog */
-    syslog(cfg->iPriority, buf);
+    int prio;
+    int i;
+    char caTime[15+1];
+    char caBuf[2048];
+    time_t t;
+    struct tm *tm;
+    size_t n;
+    sa_rc_t rc;
+
+    /* determine syslog priority */
+    prio = 0;
+    for (i = 0; l2_ch_syslog_L2toSL[i].levelL2 != -1; i++) {
+        if (l2_ch_syslog_L2toSL[i].levelL2 == level) {
+            prio = l2_ch_syslog_L2toSL[i].levelSL;
+            break;
+        }
+    }
+    if (l2_ch_syslog_L2toSL[i].levelL2 == -1)
+        return L2_ERR_USE;
+
+    /* FIXME: nul-terminate buf? */
+
+    if (strcmp(cfg->szTarget, "local") == 0) {
+        /* send to local syslogd via syslog(3) */
+        syslog(prio, buf);
+    }
+    else {
+        /* send to remote syslogd via UDP */
+        if (strlen(buf) > 1024)
+            return L2_ERR_MEM;
+        prio += cfg->nFacility;
+        t = time(NULL);
+        tm = localtime(&t);
+        strftime(caTime, sizeof(caTime), "%b %d %H:%M:%S", tm);
+        if (caTime[4] == '0')
+            caTime[4] = ' ';
+        if (cfg->bLogPid) 
+            sprintf(caBuf, "<%d>%s %s %s[%lu]: %s", 
+                    prio, caTime, cfg->szLocalHost, 
+                    cfg->szIdent, (unsigned long)getpid(), buf);
+        else
+            sprintf(caBuf, "<%d>%s %s %s: %s", 
+                    prio, caTime, cfg->szLocalHost, 
+                    cfg->szIdent, buf);
+        if ((n = strlen(caBuf)) > 1024)
+            return L2_ERR_IO;
+        if ((rc = sa_writeto(cfg->saRemoteSock, caBuf, n, 
+                             NULL, cfg->saaRemoteAddr)) != SA_OK)
+            return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_IO);
+    }
 
     return L2_OK;
 }
@@ -108,9 +297,21 @@
 /* close channel */
 static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch)
 {
-    /* close channel syslog */
-    closelog();
+    l2_ch_syslog_t *cfg = (l2_ch_syslog_t *)ctx->vp;
 
+    if (strcmp(cfg->szTarget, "local") == 0) {
+        closelog();
+    }
+    else {
+        if (cfg->saRemoteSock != NULL) {
+            sa_destroy(cfg->saRemoteSock);
+            cfg->saRemoteSock = NULL;
+        }
+        if (cfg->saaRemoteAddr != NULL) {
+            free(cfg->saaRemoteAddr);
+            cfg->saaRemoteAddr = NULL;
+        }
+    }
     return L2_OK;
 }
 
@@ -120,6 +321,20 @@
     l2_ch_syslog_t *cfg = (l2_ch_syslog_t *)ctx->vp;
 
     /* destroy channel configuration */
+    if (cfg->szTarget != NULL)
+        free(cfg->szTarget);
+    if (cfg->szRemoteHost != NULL)
+        free(cfg->szRemoteHost);
+    if (cfg->szLocalHost != NULL)
+        free(cfg->szLocalHost);
+    if (cfg->szFacility != NULL)
+        free(cfg->szFacility);
+    if (cfg->szIdent != NULL)
+        free(cfg->szIdent);
+    if (cfg->saRemoteSock != NULL)
+        sa_destroy(cfg->saRemoteSock);
+    if (cfg->saaRemoteAddr != NULL)
+        free(cfg->saaRemoteAddr);
     free(cfg);
 
     return L2_OK;

CVSTrac 2.0.1