RemoteSyslogAppender.cpp
Go to the documentation of this file.
1 /*
2  * RemoteSyslogAppender.cpp
3  *
4  * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
5  * Copyright 2001, Walter Stroebel. All rights reserved.
6  *
7  * See the COPYING file for the terms of usage and distribution.
8  */
9 
10 #include "PortabilityImpl.hh"
11 
12 #ifdef LOG4CPP_HAVE_UNISTD_H
13 # include <unistd.h>
14 #endif
15 #include <cstdlib>
16 #include <stdio.h>
17 #include <cstring>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
22 #include <log4cpp/FactoryParams.hh>
23 #include <memory>
24 
25 #ifdef WIN32
26 #include <winsock2.h>
27 #else
28 #include <netdb.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #endif
33 
34 namespace log4cpp {
35 
37  static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
39  LOG_DEBUG };
40  int result;
41 
42  priority++;
43  priority /= 100;
44 
45  if (priority < 0) {
46  result = LOG_EMERG;
47  } else if (priority > 7) {
48  result = LOG_DEBUG;
49  } else {
50  result = priorities[priority];
51  }
52 
53  return result;
54  }
55 
56 
58  const std::string& syslogName,
59  const std::string& relayer,
60  int facility,
61  int portNumber) :
62  LayoutAppender(name),
63  _syslogName(syslogName),
64  _relayer(relayer),
65  _facility((facility == -1) ? LOG_USER : facility),
66  _portNumber((portNumber == -1) ? 514 : portNumber),
67  _socket (0),
68  _ipAddr (0),
69  _cludge (0)
70  {
71  open();
72  }
73 
75  close();
76 #ifdef WIN32
77  if (_cludge) {
78  // we started it, we end it.
79  WSACleanup ();
80  }
81 #endif
82  }
83 
85  if (!_ipAddr) {
86  struct hostent *pent = gethostbyname (_relayer.c_str ());
87 #ifdef WIN32
88  if (pent == NULL) {
89  if (WSAGetLastError () == WSANOTINITIALISED) {
90  WSADATA wsaData;
91  int err;
92 
93  err = WSAStartup (0x101, &wsaData );
94  if (err) {
95  // loglog("RemoteSyslogAppender: WSAStartup returned %d", err);
96  return; // fail silently
97  }
98  pent = gethostbyname (_relayer.c_str ());
99  _cludge = 1;
100  } else {
101  // loglog("RemoteSyslogAppender: gethostbyname returned error");
102  return; // fail silently
103  }
104  }
105 #endif
106  if (pent == NULL) {
107  in_addr_t ip = inet_addr (_relayer.c_str ());
108  pent = gethostbyaddr ((const char *) &ip, sizeof(in_addr_t), AF_INET);
109  if (pent == NULL) {
110  // loglog("RemoteSyslogAppender: failed to resolve host %s", _relayer.c_str());
111  return; // fail silently
112  }
113  }
114  _ipAddr = *(in_addr_t*)(pent->h_addr); // fixed bug #1579890
115  }
116  // Get a datagram socket.
117 
118  if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
119  // loglog("RemoteSyslogAppender: failed to open socket");
120  return; // fail silently
121  }
122  }
123 
125  if (_socket) {
126 #ifdef WIN32
127  closesocket (_socket);
128 #else
129  ::close (_socket);
130 #endif
131  _socket = 0;
132  }
133  }
134 
136  const std::string message(_getLayout().format(event));
137  size_t messageLength = message.length();
138  char *buf = new char [messageLength + 16];
139  int priority = _facility + toSyslogPriority(event.priority);
140  int preambleLength = sprintf (buf, "<%d>", priority);
141  memcpy (buf + preambleLength, message.data(), messageLength);
142 
143  sockaddr_in sain;
144  sain.sin_family = AF_INET;
145  sain.sin_port = htons (_portNumber);
146  // NO, do NOT use htonl on _ipAddr. Is already in network order.
147  sain.sin_addr.s_addr = _ipAddr;
148 
149  while (messageLength > 0) {
150  /* if packet larger than maximum (900 bytes), split
151  into two or more syslog packets. */
152  if (preambleLength + messageLength > 900) {
153  sendto (_socket, buf, 900, 0, (struct sockaddr *) &sain, sizeof (sain));
154  messageLength -= (900 - preambleLength);
155  std::memmove (buf + preambleLength, buf + 900, messageLength);
156  // note: we might need to sleep a bit here
157  } else {
158  sendto (_socket, buf, preambleLength + messageLength, 0, (struct sockaddr *) &sain, sizeof (sain));
159  break;
160  }
161  }
162 
163  delete[] buf;
164  }
165 
167  close();
168  open();
169  return true;
170  }
171 
172  std::auto_ptr<Appender> create_remote_syslog_appender(const FactoryParams& params)
173  {
174  std::string name, syslog_name, relayer;
175  int facility = -1, port_number = -1;
176  params.get_for("remote syslog appender").required("name", name)("syslog_name", syslog_name)("relayer", relayer)
177  .optional("facility", facility)("port", port_number);
178  return std::auto_ptr<Appender>(new RemoteSyslogAppender(name, syslog_name, relayer, facility, port_number));
179  }
180 }
system is unusable
error conditions
informational
debug-level messages
u_long in_addr_t
warning conditions
normal but significant condition
std::auto_ptr< Appender > create_remote_syslog_appender(const FactoryParams &)
critical conditions
virtual void _append(const LoggingEvent &event)
action must be taken immediately
required_params_validator required(const char *param, T &value) const
Priority::Value priority
Definition: LoggingEvent.hh:67
RemoteSyslogAppender(const std::string &name, const std::string &syslogName, const std::string &relayer, int facility=LOG_USER, int portNumber=514)
details::parameter_validator get_for(const char *tag) const
static int toSyslogPriority(Priority::Value priority)
optional_params_validator optional(const char *param, T &value) const
random user-level messages


log4cpp
Author(s): Stephen Roderick, Bastiaan Bakker, Cedric Le Goater, Steve Ostlind, Marcel Harkema, Walter Stroebel, Glenn Scott and Tony Cheung
autogenerated on Sun Jun 23 2019 19:10:00