1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is free software; you can redistribute it and/or modify 4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it under the terms of the GNU General Public License as published by 5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the Free Software Foundation; version 2 dated June, 1991, or 6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (at your option) version 3 dated 29 June, 2007. 7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is distributed in the hope that it will be useful, 9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat but WITHOUT ANY WARRANTY; without even the implied warranty of 10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GNU General Public License for more details. 12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat You should have received a copy of the GNU General Public License 14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat along with this program. If not, see <http://www.gnu.org/licenses/>. 15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/ 16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h" 18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__ 2033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#include <android/log.h> 2133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 2233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Implement logging to /dev/log asynchronously. If syslogd is 24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat making DNS lookups through dnsmasq, and dnsmasq blocks awaiting 25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat syslogd, then the two daemons can deadlock. We get around this 26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat by not blocking when talking to syslog, instead we queue up to 27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat MAX_LOGS messages. If more are queued, they will be dropped, 28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat and the drop event itself logged. */ 29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* The "wire" protocol for logging is defined in RFC 3164 */ 31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* From RFC 3164 */ 33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#define MAX_MESSAGE 1024 34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* defaults in case we die() before we log_start() */ 36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int log_fac = LOG_DAEMON; 37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int log_stderr = 0; 38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int log_fd = -1; 39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int log_to_file = 0; 40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int entries_alloced = 0; 41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int entries_lost = 0; 42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int connection_good = 1; 43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int max_logs = 0; 44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int connection_type = SOCK_DGRAM; 45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct log_entry { 47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int offset, length; 48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat pid_t pid; /* to avoid duplicates over a fork */ 49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct log_entry *next; 50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char payload[MAX_MESSAGE]; 51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}; 52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct log_entry *entries = NULL; 54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct log_entry *free_entries = NULL; 55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint log_start(struct passwd *ent_pw, int errfd) 58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int ret = 0; 60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_stderr = !!(daemon->options & OPT_DEBUG); 62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->log_fac != -1) 64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_fac = daemon->log_fac; 65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef LOG_LOCAL0 66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (daemon->options & OPT_DEBUG) 67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_fac = LOG_LOCAL0; 68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->log_file) 71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_to_file = 1; 73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->max_logs = 0; 74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat max_logs = daemon->max_logs; 77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!log_reopen(daemon->log_file)) 79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat send_event(errfd, EVENT_LOG_ERR, errno); 81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat _exit(0); 82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* if queuing is inhibited, make sure we allocate 85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the one required buffer now. */ 86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (max_logs == 0) 87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free_entries = safe_malloc(sizeof(struct log_entry)); 89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free_entries->next = NULL; 90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries_alloced = 1; 91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If we're running as root and going to change uid later, 94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat change the ownership here so that the file is always owned by 95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the dnsmasq user. Then logrotate can just copy the owner. 96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Failure of the chown call is OK, (for instance when started as non-root) */ 97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_to_file && ent_pw && ent_pw->pw_uid != 0 && 98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fchown(log_fd, ent_pw->pw_uid, -1) != 0) 99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = errno; 100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ret; 102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint log_reopen(char *log_file) 105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_fd != -1) 107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(log_fd); 108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* NOTE: umask is set to 022 by the time this gets called */ 110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_file) 112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP); 114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return log_fd != -1; 115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOLARIS_NETWORK 118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Solaris logging is "different", /dev/log is not unix-domain socket. 119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Just leave log_fd == -1 and use the vsyslog call for everything.... */ 120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# define _PATH_LOG "" /* dummy */ 121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_fd = -1; 122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int flags; 125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_fd = socket(AF_UNIX, connection_type, 0); 126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_fd == -1) 128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* if max_logs is zero, leave the socket blocking */ 131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1) 132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fcntl(log_fd, F_SETFL, flags | O_NONBLOCK); 133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void free_entry(void) 140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct log_entry *tmp = entries; 142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries = tmp->next; 143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp->next = free_entries; 144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free_entries = tmp; 145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void log_write(void) 148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ssize_t rc; 150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (entries) 152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Avoid duplicates over a fork() */ 154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (entries->pid != getpid()) 155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free_entry(); 157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat connection_good = 1; 161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((rc = write(log_fd, entries->payload + entries->offset, entries->length)) != -1) 163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries->length -= rc; 165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries->offset += rc; 166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (entries->length == 0) 167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free_entry(); 169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (entries_lost != 0) 170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int e = entries_lost; 172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries_lost = 0; /* avoid wild recursion */ 173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_WARNING, _("overflow: %d log entries lost"), e); 174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno == EINTR) 180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno == EAGAIN) 183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; /* syslogd busy, go again when select() or poll() says so */ 184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno == ENOBUFS) 186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat connection_good = 0; 188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* errors handling after this assumes sockets */ 192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!log_to_file) 193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Once a stream socket hits EPIPE, we have to close and re-open 195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (we ignore SIGPIPE) */ 196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno == EPIPE) 197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_reopen(NULL)) 199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (errno == ECONNREFUSED || 202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == ENOTCONN || 203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EDESTADDRREQ || 204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == ECONNRESET) 205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* socket went (syslogd down?), try and reconnect. If we fail, 207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat stop trying until the next call to my_syslog() 208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ECONNREFUSED -> connection went down 209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ENOTCONN -> nobody listening 210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (ECONNRESET, EDESTADDRREQ are *BSD equivalents) */ 211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct sockaddr_un logaddr; 213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1; 216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat logaddr.sun_family = AF_UNIX; 218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path)); 219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Got connection back? try again. */ 221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1) 222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* errors from connect which mean we should keep trying */ 225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno == ENOENT || 226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EALREADY || 227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == ECONNREFUSED || 228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EISCONN || 229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EINTR || 230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EAGAIN) 231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* try again on next syslog() call */ 233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat connection_good = 0; 234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* try the other sort of socket... */ 238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno == EPROTOTYPE) 239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat connection_type = connection_type == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM; 241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_reopen(NULL)) 242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* give up - fall back to syslog() - this handles out-of-space 248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat when logging to a file, for instance. */ 249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_fd = -1; 250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_CRIT, _("log failed: %s"), strerror(errno)); 251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h. 256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between 257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat DNS, DHCP and TFTP services. 258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/ 259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid my_syslog(int priority, const char *format, ...) 260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_list ap; 262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct log_entry *entry; 263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat time_t time_now; 264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *p; 265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat size_t len; 266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat pid_t pid = getpid(); 267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *func = ""; 26833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__ 26933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat int alog_lvl; 27033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((LOG_FACMASK & priority) == MS_TFTP) 273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat func = "-tftp"; 274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if ((LOG_FACMASK & priority) == MS_DHCP) 275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat func = "-dhcp"; 276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat priority = LOG_PRI(priority); 278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_stderr) 280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fprintf(stderr, "dnsmasq%s: ", func); 282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_start(ap, format); 283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat vfprintf(stderr, format, ap); 284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_end(ap); 285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fputc('\n', stderr); 286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 28833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__ 28933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if (priority <= LOG_ERR) 29033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat alog_lvl = ANDROID_LOG_ERROR; 29133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else if (priority == LOG_WARNING) 29233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat alog_lvl = ANDROID_LOG_WARN; 29333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else if (priority <= LOG_INFO) 29433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat alog_lvl = ANDROID_LOG_INFO; 29533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else 29633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat alog_lvl = ANDROID_LOG_DEBUG; 29733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat va_start(ap, format); 29833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat __android_log_vprint(alog_lvl, "dnsmasq", format, ap); 29933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat va_end(ap); 30033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#else 30133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_fd == -1) 303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* fall-back to syslog if we die during startup or fail during running. */ 305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat static int isopen = 0; 306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!isopen) 307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat openlog("dnsmasq", LOG_PID, log_fac); 309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat isopen = 1; 310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_start(ap, format); 312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat vsyslog(priority, format, ap); 313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_end(ap); 314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((entry = free_entries)) 318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free_entries = entry->next; 319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (entries_alloced < max_logs && (entry = malloc(sizeof(struct log_entry)))) 320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries_alloced++; 321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!entry) 323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries_lost++; 324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* add to end of list, consumed from the start */ 327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entry->next = NULL; 328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!entries) 329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entries = entry; 330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct log_entry *tmp; 333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (tmp = entries; tmp->next; tmp = tmp->next); 334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp->next = entry; 335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat time(&time_now); 338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p = entry->payload; 339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!log_to_file) 340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += sprintf(p, "<%d>", priority | log_fac); 341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat p += sprintf(p, "%.15s dnsmasq%s[%d]: ", ctime(&time_now) + 4, func, (int)pid); 343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len = p - entry->payload; 345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_start(ap, format); 346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */ 347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat va_end(ap); 348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entry->length = len > MAX_MESSAGE ? MAX_MESSAGE : len; 349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entry->offset = 0; 350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entry->pid = pid; 351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* replace terminator with \n */ 353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_to_file) 354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat entry->payload[entry->length - 1] = '\n'; 355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* almost always, logging won't block, so try and write this now, 358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat to save collecting too many log messages during a select loop. */ 359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_write(); 360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Since we're doing things asynchronously, a cache-dump, for instance, 362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat can now generate log lines very fast. With a small buffer (desirable), 363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat that means it can overflow the log-buffer very quickly, 364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat so that the cache dump becomes mainly a count of how many lines 365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat overflowed. To avoid this, we delay here, the delay is controlled 366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat by queue-occupancy, and grows exponentially. The delay is limited to (2^8)ms. 367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat The scaling stuff ensures that when the queue is bigger than 8, the delay 368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat only occurs for the last 8 entries. Once the queue is full, we stop delaying 369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat to preserve performance. 370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat */ 371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (entries && max_logs != 0) 373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int d; 375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (d = 0,entry = entries; entry; entry = entry->next, d++); 377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (d == max_logs) 379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat d = 0; 380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (max_logs > 8) 381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat d -= max_logs - 8; 382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (d > 0) 384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct timespec waiter; 386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat waiter.tv_sec = 0; 387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat waiter.tv_nsec = 1000000 << (d - 1); /* 1 ms */ 388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat nanosleep(&waiter, NULL); 389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Have another go now */ 391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_write(); 392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 39333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 39433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid set_log_writer(fd_set *set, int *maxfdp) 398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (entries && log_fd != -1 && connection_good) 400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat FD_SET(log_fd, set); 402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bump_maxfd(log_fd, maxfdp); 403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid check_log_writer(fd_set *set) 407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_fd != -1 && (!set || FD_ISSET(log_fd, set))) 409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_write(); 410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid flush_log(void) 413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* block until queue empty */ 415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (log_fd != -1) 416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int flags; 418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((flags = fcntl(log_fd, F_GETFL)) != -1) 419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fcntl(log_fd, F_SETFL, flags & ~O_NONBLOCK); 420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_write(); 421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(log_fd); 422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid die(char *message, char *arg1, int exit_code) 426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *errmess = strerror(errno); 428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!arg1) 430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat arg1 = errmess; 431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_stderr = 1; /* print as well as log when we die.... */ 433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fputc('\n', stderr); /* prettyfy startup-script message */ 434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_CRIT, message, arg1, errmess); 435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat log_stderr = 0; 437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_CRIT, _("FAILED to start up")); 438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat flush_log(); 439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat exit(exit_code); 441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 442