$search
00001 /* 00002 * RemoteSyslogAppender.cpp 00003 * 00004 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved. 00005 * Copyright 2001, Walter Stroebel. All rights reserved. 00006 * 00007 * See the COPYING file for the terms of usage and distribution. 00008 */ 00009 00010 #include "PortabilityImpl.hh" 00011 00012 #ifdef LOG4CPP_HAVE_UNISTD_H 00013 # include <unistd.h> 00014 #endif 00015 #include <cstdlib> 00016 #include <cstdio> 00017 #include <cstring> 00018 #include <sys/types.h> 00019 #include <sys/stat.h> 00020 #include <fcntl.h> 00021 #include <log4cpp/RemoteSyslogAppender.hh> 00022 #include <log4cpp/FactoryParams.hh> 00023 #include <memory> 00024 00025 #ifdef WIN32 00026 #include <winsock2.h> 00027 #else 00028 #include <netdb.h> 00029 #include <sys/socket.h> 00030 #include <netinet/in.h> 00031 #include <arpa/inet.h> 00032 #endif 00033 00034 namespace log4cpp { 00035 00036 int RemoteSyslogAppender::toSyslogPriority(Priority::Value priority) { 00037 static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, 00038 LOG_WARNING, LOG_NOTICE, LOG_INFO, 00039 LOG_DEBUG }; 00040 int result; 00041 00042 priority++; 00043 priority /= 100; 00044 00045 if (priority < 0) { 00046 result = LOG_EMERG; 00047 } else if (priority > 7) { 00048 result = LOG_DEBUG; 00049 } else { 00050 result = priorities[priority]; 00051 } 00052 00053 return result; 00054 } 00055 00056 00057 RemoteSyslogAppender::RemoteSyslogAppender(const std::string& name, 00058 const std::string& syslogName, 00059 const std::string& relayer, 00060 int facility, 00061 int portNumber) : 00062 LayoutAppender(name), 00063 _syslogName(syslogName), 00064 _relayer(relayer), 00065 _facility((facility == -1) ? LOG_USER : facility), 00066 _portNumber((portNumber == -1) ? 514 : portNumber), 00067 _socket (0), 00068 _ipAddr (0), 00069 _cludge (0) 00070 { 00071 open(); 00072 } 00073 00074 RemoteSyslogAppender::~RemoteSyslogAppender() { 00075 close(); 00076 #ifdef WIN32 00077 if (_cludge) { 00078 // we started it, we end it. 00079 WSACleanup (); 00080 } 00081 #endif 00082 } 00083 00084 void RemoteSyslogAppender::open() { 00085 if (!_ipAddr) { 00086 struct hostent *pent = gethostbyname (_relayer.c_str ()); 00087 #ifdef WIN32 00088 if (pent == NULL) { 00089 if (WSAGetLastError () == WSANOTINITIALISED) { 00090 WSADATA wsaData; 00091 int err; 00092 00093 err = WSAStartup (0x101, &wsaData ); 00094 if (err) { 00095 // loglog("RemoteSyslogAppender: WSAStartup returned %d", err); 00096 return; // fail silently 00097 } 00098 pent = gethostbyname (_relayer.c_str ()); 00099 _cludge = 1; 00100 } else { 00101 // loglog("RemoteSyslogAppender: gethostbyname returned error"); 00102 return; // fail silently 00103 } 00104 } 00105 #endif 00106 if (pent == NULL) { 00107 in_addr_t ip = inet_addr (_relayer.c_str ()); 00108 pent = gethostbyaddr ((const char *) &ip, sizeof(in_addr_t), AF_INET); 00109 if (pent == NULL) { 00110 // loglog("RemoteSyslogAppender: failed to resolve host %s", _relayer.c_str()); 00111 return; // fail silently 00112 } 00113 } 00114 _ipAddr = *(pent->h_addr); 00115 } 00116 // Get a datagram socket. 00117 00118 if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00119 // loglog("RemoteSyslogAppender: failed to open socket"); 00120 return; // fail silently 00121 } 00122 } 00123 00124 void RemoteSyslogAppender::close() { 00125 if (_socket) { 00126 #ifdef WIN32 00127 closesocket (_socket); 00128 #else 00129 ::close (_socket); 00130 #endif 00131 _socket = 0; 00132 } 00133 } 00134 00135 void RemoteSyslogAppender::_append(const LoggingEvent& event) { 00136 const std::string message(_getLayout().format(event)); 00137 size_t messageLength = message.length(); 00138 char *buf = new char [messageLength + 16]; 00139 int priority = _facility + toSyslogPriority(event.priority); 00140 int preambleLength = std::sprintf (buf, "<%d>", priority); 00141 memcpy (buf + preambleLength, message.data(), messageLength); 00142 00143 sockaddr_in sain; 00144 sain.sin_family = AF_INET; 00145 sain.sin_port = htons (_portNumber); 00146 // NO, do NOT use htonl on _ipAddr. Is already in network order. 00147 sain.sin_addr.s_addr = _ipAddr; 00148 00149 while (messageLength > 0) { 00150 /* if packet larger than maximum (900 bytes), split 00151 into two or more syslog packets. */ 00152 if (preambleLength + messageLength > 900) { 00153 sendto (_socket, buf, 900, 0, (struct sockaddr *) &sain, sizeof (sain)); 00154 messageLength -= (900 - preambleLength); 00155 std::memmove (buf + preambleLength, buf + 900, messageLength); 00156 // note: we might need to sleep a bit here 00157 } else { 00158 sendto (_socket, buf, preambleLength + messageLength, 0, (struct sockaddr *) &sain, sizeof (sain)); 00159 break; 00160 } 00161 } 00162 00163 delete[] buf; 00164 } 00165 00166 bool RemoteSyslogAppender::reopen() { 00167 close(); 00168 open(); 00169 return true; 00170 } 00171 00172 std::auto_ptr<Appender> create_remote_syslog_appender(const FactoryParams& params) 00173 { 00174 std::string name, syslog_name, relayer; 00175 int facility = -1, port_number = -1; 00176 params.get_for("remote syslog appender").required("name", name)("syslog_name", syslog_name)("relayer", relayer) 00177 .optional("facility", facility)("port", port_number); 00178 return std::auto_ptr<Appender>(new RemoteSyslogAppender(name, syslog_name, relayer, facility, port_number)); 00179 } 00180 }