/*****************************************************************************/ /* SysLog.c Syslog is a standard for sending and receiving notification messages in a particular format from various network devices. The messages include time stamps, event messages, severity, host IP addresses, diagnostics and more. https://en.wikipedia.org/wiki/Syslog https://www.ietf.org/rfc/rfc5424.html https://www.ietf.org/rfc/rfc3164.html There is not much to be gained (apart from complexity) for doing this via system services so it's implemented using BSD sockets. A maximum of four syslogd servers may be specified via the logical name WASD_SYSLOG, using a string "host[:port][/pri][,host[:port][/pri]]". The code checks the logical name every minute for changes and reinitialises the syslogd services if modified (so no need for a server restart for changes). $ DEFINE /SYSTEM /EXEC WASD_SYSLOG "klaatu.lan" Where |host| is the IP address or host name of the syslogd server. A non-default (514) port may be specified. $ DEFINE /SYSTEM /EXEC WASD_SYSLOG "klaatu.lan:6514" The default is an RFC5424 message. This comprises a place holder PRI, VERSION, TIMESTAMP, HOSTNAME, APP-NAME, PROCID, MSGID and then free-form data. The optional |pri| value, introduced by a slash sign, allows the format of the message to be specified. If a positive integer that value should correspond to a valid PRI and is used in the RFC5424 message. $ DEFINE /SYSTEM /EXEC WASD_SYSLOG "klaatu.lan/123" If specified as a negative zero the message is formatted as RFC3164. $ DEFINE /SYSTEM /EXEC WASD_SYSLOG "klaatu.lan/-0" If specified as a negative integer that value should correspond to a valid PRI. This example sets the PRI to local use 0 plus informational. $ DEFINE /SYSTEM /EXEC WASD_SYSLOG "klaatu.lan/-123" VERSION HISTORY --------------- 01-FEB-2022 MGD initial */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif #include #include #include #include #include #include #include #include #include #include "wasd.h" #include "tcpip.h" #define WASD_MODULE "SYSLOG" #define SYSLOG_MAX 4 #define SYSLOG_PORT 514 /* system daemons plus warning */ #define SYSLOG_PRI ((3 * 8) + 3) /******************/ /* global storage */ /******************/ static int sockfd [SYSLOG_MAX], syspri [SYSLOG_MAX]; static char syslogd [SYSLOG_MAX][64]; static char wasdSysLog [256]; static struct sockaddr_in serv_addr [SYSLOG_MAX]; /********************/ /* external storage */ /********************/ extern int64 HttpdTime64; extern ushort HttpdTime7[]; extern char ServerHostName[], TimeGmtString[]; extern struct dsc$descriptor TcpIpDeviceDsc; extern SYS_INFO SysInfo; extern HTTPD_PROCESS HttpdProcess; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Called at server startup and thereafter every minute to allow changes. */ void SysLogInit () { int idx; ushort port; char ch; char *cptr, *sptr, *zptr; struct in_addr addr; struct hostent *heptr; void *saptr; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "SysLogInit()"); if (!(cptr = SysTrnLnm ("WASD_SYSLOG"))) { /*******************/ /* no logical name */ /*******************/ if (!sockfd[0]) return; for (idx = 0; idx < SYSLOG_MAX && sockfd[idx]; idx++) { if (sockfd[idx]) close (sockfd[idx]); sockfd[idx] = syspri[idx] = 0; syslogd[idx][0] = '\0'; } return; } /* if no change in the logical name value */ if (!strcmp (cptr, wasdSysLog)) return; /************************/ /* changed logical name */ /************************/ /* clear any previous syslogd data */ for (idx = 0; idx < SYSLOG_MAX && sockfd[idx]; idx++) { if (sockfd[idx]) close (sockfd[idx]); sockfd[idx] = syspri[idx] = 0; syslogd[idx][0] = '\0'; } /* store the current configuration */ zptr = (sptr = wasdSysLog) + sizeof(wasdSysLog)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; /*************************************/ /* set up syslogd datagram server(s) */ /*************************************/ /* host[:port][/pri][,host[:port][/pri]] */ idx = -1; cptr = wasdSysLog; while (*cptr) { while (*cptr == ',' || *cptr == ' ') cptr++; if (!*cptr) break; if (++idx >= SYSLOG_MAX) break; memset (&serv_addr[idx], 0, sizeof(serv_addr[0])); zptr = (sptr = syslogd[idx]) + sizeof(syslogd[0])-1; while (*cptr && *cptr != ',' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; for (sptr = syslogd[idx]; *sptr && *sptr != ':' && *sptr != '/'; sptr++); ch = *sptr; *sptr = '\0'; saptr = &serv_addr[idx].sin_addr; addr.s_addr = inet_addr (syslogd[idx]); if (addr.s_addr != INADDR_NONE) memcpy (saptr, &addr, sizeof(struct in_addr)); else { if (heptr = gethostbyname(syslogd[idx])) memcpy (saptr, heptr->h_addr, sizeof(struct in_addr)); else { *sptr = ch; FaoToStdout ("%HTTPD-W-SYSLOG, !AZ !AZ\n", syslogd[idx], strerror(errno)); continue; } } *sptr = ch; while (*sptr && *sptr != ':' && *sptr != '/') sptr++; if (*sptr == ':') { port = atoi (++sptr); while (isdigit(*sptr)) sptr++; } else port = SYSLOG_PORT; if (*sptr == '/') { syspri[idx] = atoi (++sptr); if (!syspri[idx]) if (*sptr == '-') syspri[idx] = -SYSLOG_PRI; else syspri[idx] = SYSLOG_PRI; } else syspri[idx] = SYSLOG_PRI; serv_addr[idx].sin_family = AF_INET; serv_addr[idx].sin_port = htons(port); if ((sockfd[idx] = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "!AZ", sptr); FaoToStdout ("%HTTPD-W-SYSLOG, !AZ !AZ\n", syslogd[idx], strerror(errno)); continue; } FaoToStdout ("%HTTPD-I-SYSLOG, !AZ\n", syslogd[idx]); } } /*****************************************************************************/ /* */ void SysLogOpcom (char* OpcomMsg) { int idx, len, status; ushort slen; char *cptr, *sptr, *zptr; char buf [986+256], dtime [32]; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "SysLogOpcom()"); if (!sockfd[0]) return; FaoToBuffer (dtime, sizeof(dtime), NULL, "!UL-!2ZL-!2ZLT!2ZL:!2ZL:!2ZL.!2ZL!AZ", HttpdTime7[0], HttpdTime7[1], HttpdTime7[2], HttpdTime7[3], HttpdTime7[4], HttpdTime7[5], HttpdTime7[6], TimeGmtString); for (idx = 0; idx < SYSLOG_MAX && sockfd[idx]; idx++) { zptr = (sptr = buf) + sizeof(buf)-5; if (syspri[idx] > 0) FaoToBuffer (buf, sizeof(buf), &slen, "1 !AZ !AZ !AZ !8XL !AZ !%T Message from user !AZ on !AZ | ", syspri[idx], dtime, ServerHostName, "wasd", HttpdProcess.Pid, "OPCOM", &HttpdTime64, HttpdProcess.UserName, SysInfo.NodeName); else FaoToBuffer (buf, sizeof(buf), &slen, "OPCOM message from user !AZ on !AZ | ", -syspri[idx], HttpdProcess.UserName, SysInfo.NodeName); sptr += slen; for (cptr = OpcomMsg; *cptr; cptr++) { if (sptr >= zptr) break; if (*cptr == '\n') { *sptr++ = ' '; *sptr++ = '|'; *sptr++ = ' '; } else if (*cptr == '\r') continue; else if (*cptr < 32 || *cptr > 127) sptr += sprintf (buf, "\\x%02.02x", *cptr); else *sptr++ = *cptr; } *sptr = '\0'; len = sptr - buf; if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "{!UL}!AZ", len, buf); if (sendto (sockfd[idx], buf, len, 0, (struct sockaddr *)&(serv_addr[idx]), sizeof(serv_addr[0])) < 0) FaoToStdout ("%HTTPD-W-SYSLOG, !AZ !AZ\n", syslogd[idx], strerror(errno)); } } /*****************************************************************************/