/***************************************************************************/ /* */ /* Project: OpenSLP - OpenSource implementation of Service Location */ /* Protocol Version 2 */ /* */ /* File: slpd_log.c */ /* */ /* Abstract: slpd logging functions */ /* */ /* WARNING: NOT thread safe! */ /* */ /*-------------------------------------------------------------------------*/ /* */ /* Please submit patches to http://www.openslp.org */ /* */ /*-------------------------------------------------------------------------*/ /* */ /* Copyright (C) 2000 Caldera Systems, Inc */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in */ /* the documentation and/or other materials provided with the */ /* distribution. */ /* */ /* Neither the name of Caldera Systems nor the names of its */ /* contributors may be used to endorse or promote products derived */ /* from this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */ /* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* */ /***************************************************************************/ /*=========================================================================*/ /* slpd includes */ /*=========================================================================*/ #include "slpd_log.h" #include "slpd_property.h" #include /********************************************/ /* TODO: Make these functions thread safe!! */ /********************************************/ /*=========================================================================*/ static FILE* G_SlpdLogFile = 0; /*=========================================================================*/ /*=========================================================================*/ int SLPDLogFileOpen(const char* path, int append) /* Prepares the file at the specified path as the log file. */ /* */ /* path - (IN) the path to the log file. If path is the empty string */ /* (""), then we log to stdout. */ /* */ /* append - (IN) if zero log file will be truncated. */ /* */ /* Returns - zero on success. errno on failure. */ /*=========================================================================*/ { if (G_SlpdLogFile) { /* logfile was already open close it */ fclose(G_SlpdLogFile); } if (*path == 0) { /* Log to console. */ G_SlpdLogFile = stdout; } else { /* Log to file. */ #ifndef _WIN32 /* only owner can read/write */ umask(0077); #endif if (append) { G_SlpdLogFile = fopen(path,"a"); } else { G_SlpdLogFile = fopen(path,"w"); } if (G_SlpdLogFile == 0) { /* could not open the log file */ return -1; } } return 0; } #ifdef DEBUG /*=========================================================================*/ int SLPDLogFileClose() /* Releases resources associated with the log file */ /*=========================================================================*/ { fclose(G_SlpdLogFile); return 0; } #endif /*=========================================================================*/ void SLPDLog(const char* msg, ...) /* Logs a message */ /*=========================================================================*/ { va_list ap; if (G_SlpdLogFile) { va_start(ap,msg); vfprintf(G_SlpdLogFile,msg,ap); va_end(ap); fflush(G_SlpdLogFile); } } /*=========================================================================*/ void SLPDFatal(const char* msg, ...) /* Logs a message and halts the process */ /*=========================================================================*/ { va_list ap; if (G_SlpdLogFile) { fprintf(G_SlpdLogFile,"A FATAL Error has occured:\n"); va_start(ap,msg); vfprintf(G_SlpdLogFile,msg,ap); va_end(ap); fflush(G_SlpdLogFile); } else { fprintf(stderr,"A FATAL Error has occured:\n"); va_start(ap,msg); vprintf(msg,ap); va_end(ap); } exit(1); } /*=========================================================================*/ void SLPDLogBuffer(const char* prefix, int bufsize, const char* buf) /* Writes a buffer to the logfile */ /*=========================================================================*/ { if (G_SlpdLogFile) { fprintf(G_SlpdLogFile,"%s",prefix); fwrite(buf,bufsize,1,G_SlpdLogFile); fprintf(G_SlpdLogFile,"\n"); fflush(G_SlpdLogFile); } } /*=========================================================================*/ void SLPDLogTime() /* Logs a timestamp */ /*=========================================================================*/ { time_t curtime = time(NULL); SLPDLog("%s",ctime(&curtime)); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvRqstMessage(SLPSrvRqst* srvrqst) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVRQST:\n"); SLPDLogBuffer(" srvtype = ", srvrqst->srvtypelen, srvrqst->srvtype); SLPDLogBuffer(" scopelist = ", srvrqst->scopelistlen, srvrqst->scopelist); SLPDLogBuffer(" predicate = ", srvrqst->predicatelen, srvrqst->predicate); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvRplyMessage(SLPSrvRply* srvrply) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVRPLY:\n"); SLPDLog(" errorcode = %i\n",srvrply->errorcode); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvRegMessage(SLPSrvReg* srvreg) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVREG:\n"); SLPDLogBuffer(" srvtype = ", srvreg->srvtypelen, srvreg->srvtype); SLPDLogBuffer(" scope = ", srvreg->scopelistlen, srvreg->scopelist); SLPDLogBuffer(" url = ", srvreg->urlentry.urllen, srvreg->urlentry.url); SLPDLogBuffer(" attributes = ", srvreg->attrlistlen, srvreg->attrlist); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvDeRegMessage(SLPSrvDeReg* srvdereg) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVDEREG:\n"); SLPDLogBuffer(" scope = ", srvdereg->scopelistlen, srvdereg->scopelist); SLPDLogBuffer(" url = ", srvdereg->urlentry.urllen, srvdereg->urlentry.url); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvAckMessage(SLPSrvAck* srvack) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVACK:\n"); SLPDLog(" errorcode = %i\n",srvack->errorcode); } /*-------------------------------------------------------------------------*/ void SLPDLogAttrRqstMessage(SLPAttrRqst* attrrqst) /*-------------------------------------------------------------------------*/ { SLPDLog("Message ATTRRQST:\n"); SLPDLogBuffer(" scope = ", attrrqst->scopelistlen, attrrqst->scopelist); SLPDLogBuffer(" url = ", attrrqst->urllen, attrrqst->url); } /*-------------------------------------------------------------------------*/ void SLPDLogAttrRplyMessage(SLPAttrRply* attrrply) /*-------------------------------------------------------------------------*/ { SLPDLog("Message ATTRRPLY:\n"); SLPDLog(" errorcode = %i\n",attrrply->errorcode); } /*-------------------------------------------------------------------------*/ void SLPDLogDAAdvertMessage(SLPDAAdvert* daadvert) /*-------------------------------------------------------------------------*/ { SLPDLog("Message DAADVERT:\n"); SLPDLogBuffer(" scope = ", daadvert->scopelistlen, daadvert->scopelist); SLPDLogBuffer(" url = ", daadvert->urllen, daadvert->url); SLPDLogBuffer(" attributes = ", daadvert->attrlistlen, daadvert->attrlist); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvTypeRqstMessage(SLPSrvTypeRqst* srvtyperqst) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVTYPERQST:\n"); SLPDLogBuffer(" namingauth = ", srvtyperqst->namingauthlen, srvtyperqst->namingauth); SLPDLogBuffer(" scope = ", srvtyperqst->scopelistlen, srvtyperqst->scopelist); } /*-------------------------------------------------------------------------*/ void SLPDLogSrvTypeRplyMessage(SLPSrvTypeRply* srvtyperply) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SRVTYPERPLY:\n"); SLPDLog(" errorcode = %i\n",srvtyperply->errorcode); } /*-------------------------------------------------------------------------*/ void SLPDLogSAAdvertMessage(SLPSAAdvert* saadvert) /*-------------------------------------------------------------------------*/ { SLPDLog("Message SAADVERT:\n"); SLPDLogBuffer(" scope = ", saadvert->scopelistlen, saadvert->scopelist); SLPDLogBuffer(" url = ", saadvert->urllen, saadvert->url); SLPDLogBuffer(" attributes = ", saadvert->attrlistlen, saadvert->attrlist); } /*-------------------------------------------------------------------------*/ void SLPDLogPeerAddr(struct sockaddr_in* peeraddr) /*-------------------------------------------------------------------------*/ { SLPDLog("Peer IP address: %s\n", inet_ntoa(peeraddr->sin_addr)); } /*=========================================================================*/ void SLPDLogMessageInternals(SLPMessage message) /*=========================================================================*/ { SLPDLog("Peer: \n"); SLPDLog(" IP address: %s\n", inet_ntoa(message->peer.sin_addr)); SLPDLog("Header:\n"); SLPDLog(" version = %i\n",message->header.version); SLPDLog(" functionid = %i\n",message->header.functionid); SLPDLog(" length = %i\n",message->header.length); SLPDLog(" flags = %i\n",message->header.flags); SLPDLog(" extoffset = %i\n",message->header.extoffset); SLPDLog(" xid = %i\n",message->header.xid); SLPDLogBuffer(" langtag = ", message->header.langtaglen, message->header.langtag); switch (message->header.functionid) { case SLP_FUNCT_SRVRQST: SLPDLogSrvRqstMessage(&(message->body.srvrqst)); break; case SLP_FUNCT_SRVRPLY: SLPDLogSrvRplyMessage(&(message->body.srvrply)); break; case SLP_FUNCT_SRVREG: SLPDLogSrvRegMessage(&(message->body.srvreg)); break; case SLP_FUNCT_SRVDEREG: SLPDLogSrvDeRegMessage(&(message->body.srvdereg)); break; case SLP_FUNCT_SRVACK: SLPDLogSrvAckMessage(&(message->body.srvack)); break; case SLP_FUNCT_ATTRRQST: SLPDLogAttrRqstMessage(&(message->body.attrrqst)); break; case SLP_FUNCT_ATTRRPLY: SLPDLogAttrRplyMessage(&(message->body.attrrply)); break; case SLP_FUNCT_DAADVERT: SLPDLogDAAdvertMessage(&(message->body.daadvert)); break; case SLP_FUNCT_SRVTYPERQST: SLPDLogSrvTypeRqstMessage(&(message->body.srvtyperqst)); break; case SLP_FUNCT_SRVTYPERPLY: SLPDLogSrvTypeRplyMessage(&(message->body.srvtyperply)); break; case SLP_FUNCT_SAADVERT: SLPDLogSAAdvertMessage(&(message->body.saadvert)); break; default: SLPDLog("Message %i UNKNOWN:\n",message->header.functionid); SLPDLog(" This is really bad\n"); break; } } /*=========================================================================*/ void SLPDLogMessage(int msglogflags, struct sockaddr_in* peerinfo, SLPBuffer buf) /* Log record of receiving or sending an SLP Message. Logging will only */ /* occur if message logging is enabled G_SlpProperty.traceMsg != 0 */ /* */ /* msglogflags (IN) What type of message to log */ /* */ /* peerinfo (IN) the source or destination peer */ /* */ /* msg (IN) the message to log */ /* */ /* Returns: none */ /*=========================================================================*/ { SLPMessage msg; if (peerinfo == NULL || buf == NULL) { return; } if ((G_SlpdProperty.traceMsg && (msglogflags & SLPDLOG_TRACEMSG)) || (G_SlpdProperty.traceDrop && (msglogflags & SLPDLOG_TRACEDROP)) ) { /* Don't log localhost traffic since it is probably IPC */ /* and don't log empty messages */ if (!ISLOCAL(peerinfo->sin_addr) && buf->end != buf->start) { msg = SLPMessageAlloc(); if (msg) { SLPDLog("\n"); SLPDLogTime(); SLPDLog("MESSAGE - "); if (msglogflags == SLPDLOG_TRACEMSG_OUT) { SLPDLog("Trace message (OUT)\n"); } else if (msglogflags == SLPDLOG_TRACEMSG_IN) { SLPDLog("Trace message (IN)\n"); } else if (msglogflags == SLPDLOG_TRACEDROP) { SLPDLog("Dropped message (following message silently ignored)\n"); } else { SLPDLog("\n"); } if (SLPMessageParseBuffer(peerinfo,buf,msg) == 0) { SLPDLogMessageInternals(msg); } else { SLPDLog("Message parsing failed\n"); SLPDLog("Peer: \n"); SLPDLog(" IP address: %s\n", inet_ntoa(msg->peer.sin_addr)); } SLPMessageFree(msg); } } } } /*=========================================================================*/ void SLPDLogRegistration(const char* prefix, SLPDatabaseEntry* entry) /* Log record of having added a registration to the database. Logging of */ /* registraions will only occur if registration trace is enabled */ /* G_SlpProperty.traceReg != 0 */ /* */ /* prefix (IN) an informative prefix for the log entry */ /* */ /* entry (IN) the database entry that was affected */ /* */ /* Returns: none */ /*=========================================================================*/ { if (prefix == NULL || entry == NULL) { return; } if (G_SlpdProperty.traceReg) { SLPDLog("\n"); SLPDLogTime(); SLPDLog("DATABASE - %s:\n",prefix); SLPDLog(" SA address = "); switch (entry->msg->body.srvreg.source) { case SLP_REG_SOURCE_UNKNOWN: SLPDLog("\n"); break; case SLP_REG_SOURCE_REMOTE: SLPDLog("remote (%s)\n", inet_ntoa(entry->msg->peer.sin_addr)); break; case SLP_REG_SOURCE_LOCAL: SLPDLog("IPC (libslp)\n"); break; case SLP_REG_SOURCE_STATIC: SLPDLog("static (slp.reg)\n"); break; } SLPDLogBuffer(" service-url = ", entry->msg->body.srvreg.urlentry.urllen, entry->msg->body.srvreg.urlentry.url); SLPDLogBuffer(" scope = ", entry->msg->body.srvreg.scopelistlen, entry->msg->body.srvreg.scopelist); SLPDLogBuffer(" attributes = ", entry->msg->body.srvreg.attrlistlen, entry->msg->body.srvreg.attrlist); } } /*=========================================================================*/ void SLPDLogDAAdvertisement(const char* prefix, SLPDatabaseEntry* entry) /* Log record of addition or removal of a DA to the store of known DAs. */ /* Will only occur if DA Advertisment message logging is enabled */ /* G_SlpProperty.traceDATraffic != 0 */ /* */ /* prefix (IN) an informative prefix for the log entry */ /* */ /* entry (IN) the database entry that was affected */ /* */ /* Returns: none */ /*=========================================================================*/ { if (prefix == NULL || entry == NULL) { return; } if (G_SlpdProperty.traceDATraffic) { SLPDLog("\n"); SLPDLogTime(); SLPDLog("KNOWNDA - %s:\n",prefix); SLPDLog(" DA address = %s\n",inet_ntoa(entry->msg->peer.sin_addr)); SLPDLogBuffer(" directory-agent-url = ", entry->msg->body.daadvert.urllen, entry->msg->body.daadvert.url); SLPDLog(" bootstamp = %x\n",entry->msg->body.daadvert.bootstamp); SLPDLogBuffer(" scope = ", entry->msg->body.daadvert.scopelistlen, entry->msg->body.daadvert.scopelist); SLPDLogBuffer(" attributes = ", entry->msg->body.daadvert.attrlistlen, entry->msg->body.daadvert.attrlist); #ifdef ENABLE_SLPV2_SECURITY SLPDLogBuffer(" SPI list = ", entry->msg->body.daadvert.spilistlen, entry->msg->body.daadvert.spilist); #endif /*ENABLE_SLPV2_SECURITY*/ } } /*=========================================================================*/ void SLPDLogParseWarning(struct sockaddr_in* peeraddr, SLPBuffer buf) /* Log a parsing error warning and dumps the invalid message. */ /*=========================================================================*/ { unsigned char* curpos; int i = 0; if (peeraddr == NULL || buf == NULL) { return; } SLPDLog("\n"); SLPDLogTime(); SLPDLog("*** WARNING Parse Error ***\n"); SLPDLogPeerAddr(peeraddr); SLPDLog("message size = %i\n",buf->end - buf->start); SLPDLog("message dump follows:\n"); for (curpos = buf->start; curpos < buf->end; curpos++) { SLPDLog("0x%02x",*curpos); if (*curpos < 0x20 || *curpos > 0x7f) { SLPDLog("(' ') "); } else { SLPDLog("('%c') ",*curpos); } /* newline every 70 columns */ i++; if (i==10) { i=0; SLPDLog("\n"); } } SLPDLog("\n"); }