1 /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 # include <android/log.h>
23 /* Implement logging to /dev/log asynchronously. If syslogd is
24 making DNS lookups through dnsmasq, and dnsmasq blocks awaiting
25 syslogd, then the two daemons can deadlock. We get around this
26 by not blocking when talking to syslog, instead we queue up to
27 MAX_LOGS messages. If more are queued, they will be dropped,
28 and the drop event itself logged. */
30 /* The "wire" protocol for logging is defined in RFC 3164 */
33 #define MAX_MESSAGE 1024
35 /* defaults in case we die() before we log_start() */
36 static int log_fac = LOG_DAEMON;
37 static int log_stderr = 0;
38 static int echo_stderr = 0;
39 static int log_fd = -1;
40 static int log_to_file = 0;
41 static int entries_alloced = 0;
42 static int entries_lost = 0;
43 static int connection_good = 1;
44 static int max_logs = 0;
45 static int connection_type = SOCK_DGRAM;
49 pid_t pid; /* to avoid duplicates over a fork */
50 struct log_entry *next;
51 char payload[MAX_MESSAGE];
54 static struct log_entry *entries = NULL;
55 static struct log_entry *free_entries = NULL;
58 int log_start(struct passwd *ent_pw, int errfd)
62 echo_stderr = option_bool(OPT_DEBUG);
64 if (daemon->log_fac != -1)
65 log_fac = daemon->log_fac;
67 else if (option_bool(OPT_DEBUG))
75 if (strcmp(daemon->log_file, "-") == 0)
79 log_fd = dup(STDERR_FILENO);
83 max_logs = daemon->max_logs;
85 if (!log_reopen(daemon->log_file))
87 send_event(errfd, EVENT_LOG_ERR, errno, daemon->log_file ? daemon->log_file : "");
91 /* if queuing is inhibited, make sure we allocate
92 the one required buffer now. */
95 free_entries = safe_malloc(sizeof(struct log_entry));
96 free_entries->next = NULL;
100 /* If we're running as root and going to change uid later,
101 change the ownership here so that the file is always owned by
102 the dnsmasq user. Then logrotate can just copy the owner.
103 Failure of the chown call is OK, (for instance when started as non-root).
105 If we've created a file with group-id root, we also make
106 the file group-writable. This gives processes in the root group
107 write access to the file and avoids the problem that on some systems,
108 once the file is owned by the dnsmasq user, it can't be written
109 whilst dnsmasq is running as root during startup.
111 if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0)
114 if (getgid() == 0 && fstat(log_fd, &ls) == 0 && ls.st_gid == 0 &&
115 (ls.st_mode & S_IWGRP) == 0)
116 (void)fchmod(log_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
117 if (fchown(log_fd, ent_pw->pw_uid, -1) != 0)
124 int log_reopen(char *log_file)
131 /* NOTE: umask is set to 022 by the time this gets called */
134 log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
137 #if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__)
138 /* Solaris logging is "different", /dev/log is not unix-domain socket.
139 Just leave log_fd == -1 and use the vsyslog call for everything.... */
140 # define _PATH_LOG "" /* dummy */
144 log_fd = socket(AF_UNIX, connection_type, 0);
146 /* if max_logs is zero, leave the socket blocking */
147 if (log_fd != -1 && max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
148 fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
156 static void free_entry(void)
158 struct log_entry *tmp = entries;
160 tmp->next = free_entries;
164 static void log_write(void)
170 /* The data in the payload is written with a terminating zero character
171 and the length reflects this. For a stream connection we need to
172 send the zero as a record terminator, but this isn't done for a
173 datagram connection, so treat the length as one less than reality
174 to elide the zero. If we're logging to a file, turn the zero into
175 a newline, and leave the length alone. */
179 entries->payload[entries->offset + entries->length - 1] = '\n';
180 else if (connection_type == SOCK_DGRAM)
183 /* Avoid duplicates over a fork() */
184 if (entries->pid != getpid())
192 if ((rc = write(log_fd, entries->payload + entries->offset, entries->length - len_adjust)) != -1)
194 entries->length -= rc;
195 entries->offset += rc;
196 if (entries->length == len_adjust)
199 if (entries_lost != 0)
201 int e = entries_lost;
202 entries_lost = 0; /* avoid wild recursion */
203 my_syslog(LOG_WARNING, _("overflow: %d log entries lost"), e);
212 if (errno == EAGAIN || errno == EWOULDBLOCK)
213 return; /* syslogd busy, go again when select() or poll() says so */
215 if (errno == ENOBUFS)
221 /* errors handling after this assumes sockets */
224 /* Once a stream socket hits EPIPE, we have to close and re-open
225 (we ignore SIGPIPE) */
228 if (log_reopen(NULL))
231 else if (errno == ECONNREFUSED ||
233 errno == EDESTADDRREQ ||
236 /* socket went (syslogd down?), try and reconnect. If we fail,
237 stop trying until the next call to my_syslog()
238 ECONNREFUSED -> connection went down
239 ENOTCONN -> nobody listening
240 (ECONNRESET, EDESTADDRREQ are *BSD equivalents) */
242 struct sockaddr_un logaddr;
244 #ifdef HAVE_SOCKADDR_SA_LEN
245 logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1;
247 logaddr.sun_family = AF_UNIX;
248 safe_strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
250 /* Got connection back? try again. */
251 if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1)
254 /* errors from connect which mean we should keep trying */
255 if (errno == ENOENT ||
257 errno == ECONNREFUSED ||
261 errno == EWOULDBLOCK)
263 /* try again on next syslog() call */
268 /* try the other sort of socket... */
269 if (errno == EPROTOTYPE)
271 connection_type = connection_type == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM;
272 if (log_reopen(NULL))
278 /* give up - fall back to syslog() - this handles out-of-space
279 when logging to a file, for instance. */
281 my_syslog(LOG_CRIT, _("log failed: %s"), strerror(errno));
286 /* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h.
287 OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between
288 DNS, DHCP and TFTP services.
289 If OR'd with MS_DEBUG, the messages are suppressed unless --log-debug is set. */
290 void my_syslog(int priority, const char *format, ...)
293 struct log_entry *entry;
297 pid_t pid = getpid();
300 if ((LOG_FACMASK & priority) == MS_TFTP)
302 else if ((LOG_FACMASK & priority) == MS_DHCP)
304 else if ((LOG_FACMASK & priority) == MS_SCRIPT)
306 else if ((LOG_FACMASK & priority) == MS_DEBUG)
308 if (!option_bool(OPT_LOG_DEBUG))
314 priority = LOG_PRI(priority);
316 /* Solaris doesn't have LOG_PRI */
317 priority &= LOG_PRIMASK;
322 fprintf(stderr, "dnsmasq%s: ", func);
323 va_start(ap, format);
324 vfprintf(stderr, format, ap);
332 /* do android-specific logging.
333 log_fd is always -1 on Android except when logging to a file. */
336 if (priority <= LOG_ERR)
337 alog_lvl = ANDROID_LOG_ERROR;
338 else if (priority == LOG_WARNING)
339 alog_lvl = ANDROID_LOG_WARN;
340 else if (priority <= LOG_INFO)
341 alog_lvl = ANDROID_LOG_INFO;
343 alog_lvl = ANDROID_LOG_DEBUG;
345 va_start(ap, format);
346 __android_log_vprint(alog_lvl, "dnsmasq", format, ap);
349 /* fall-back to syslog if we die during startup or
350 fail during running (always on Solaris). */
351 static int isopen = 0;
355 openlog("dnsmasq", LOG_PID, log_fac);
358 va_start(ap, format);
359 vsyslog(priority, format, ap);
366 if ((entry = free_entries))
367 free_entries = entry->next;
368 else if (entries_alloced < max_logs && (entry = malloc(sizeof(struct log_entry))))
375 /* add to end of list, consumed from the start */
381 struct log_entry *tmp;
382 for (tmp = entries; tmp->next; tmp = tmp->next);
389 p += sprintf(p, "<%d>", priority | log_fac);
391 /* Omit timestamp for default daemontools situation */
392 if (!log_stderr || !option_bool(OPT_NO_FORK))
393 p += sprintf(p, "%.15s ", ctime(&time_now) + 4);
395 p += sprintf(p, "dnsmasq%s[%d]: ", func, (int)pid);
397 len = p - entry->payload;
398 va_start(ap, format);
399 len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */
401 entry->length = len > MAX_MESSAGE ? MAX_MESSAGE : len;
406 /* almost always, logging won't block, so try and write this now,
407 to save collecting too many log messages during a select loop. */
410 /* Since we're doing things asynchronously, a cache-dump, for instance,
411 can now generate log lines very fast. With a small buffer (desirable),
412 that means it can overflow the log-buffer very quickly,
413 so that the cache dump becomes mainly a count of how many lines
414 overflowed. To avoid this, we delay here, the delay is controlled
415 by queue-occupancy, and grows exponentially. The delay is limited to (2^8)ms.
416 The scaling stuff ensures that when the queue is bigger than 8, the delay
417 only occurs for the last 8 entries. Once the queue is full, we stop delaying
418 to preserve performance.
421 if (entries && max_logs != 0)
425 for (d = 0,entry = entries; entry; entry = entry->next, d++);
429 else if (max_logs > 8)
434 struct timespec waiter;
436 waiter.tv_nsec = 1000000 << (d - 1); /* 1 ms */
437 nanosleep(&waiter, NULL);
439 /* Have another go now */
445 void set_log_writer(void)
447 if (entries && log_fd != -1 && connection_good)
448 poll_listen(log_fd, POLLOUT);
451 void check_log_writer(int force)
453 if (log_fd != -1 && (force || poll_check(log_fd, POLLOUT)))
459 /* write until queue empty, but don't loop forever if there's
460 no connection to the syslog in existence */
463 struct timespec waiter;
465 if (!entries || !connection_good)
471 waiter.tv_nsec = 1000000; /* 1 ms */
472 nanosleep(&waiter, NULL);
476 void die(char *message, char *arg1, int exit_code)
478 char *errmess = strerror(errno);
485 echo_stderr = 1; /* print as well as log when we die.... */
486 fputc('\n', stderr); /* prettyfy startup-script message */
488 my_syslog(LOG_CRIT, message, arg1, errmess);
490 my_syslog(LOG_CRIT, _("FAILED to start up"));