1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2 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. 7 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. 12 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/>. 15 */ 16 17 #include "dnsmasq.h" 18 19 #ifdef __ANDROID__ 20 #include <android/log.h> 21 #endif 22 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. */ 29 30 /* The "wire" protocol for logging is defined in RFC 3164 */ 31 32 /* From RFC 3164 */ 33 #define MAX_MESSAGE 1024 34 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 log_fd = -1; 39 static int log_to_file = 0; 40 static int entries_alloced = 0; 41 static int entries_lost = 0; 42 static int connection_good = 1; 43 static int max_logs = 0; 44 static int connection_type = SOCK_DGRAM; 45 46 struct log_entry { 47 int offset, length; 48 pid_t pid; /* to avoid duplicates over a fork */ 49 struct log_entry* next; 50 char payload[MAX_MESSAGE]; 51 }; 52 53 static struct log_entry* entries = NULL; 54 static struct log_entry* free_entries = NULL; 55 56 int log_start(struct passwd* ent_pw, int errfd) { 57 int ret = 0; 58 59 log_stderr = !!(daemon->options & OPT_DEBUG); 60 61 if (daemon->log_fac != -1) log_fac = daemon->log_fac; 62 #ifdef LOG_LOCAL0 63 else if (daemon->options & OPT_DEBUG) 64 log_fac = LOG_LOCAL0; 65 #endif 66 67 if (daemon->log_file) { 68 log_to_file = 1; 69 daemon->max_logs = 0; 70 } 71 72 max_logs = daemon->max_logs; 73 74 if (!log_reopen(daemon->log_file)) { 75 send_event(errfd, EVENT_LOG_ERR, errno); 76 _exit(0); 77 } 78 79 /* if queuing is inhibited, make sure we allocate 80 the one required buffer now. */ 81 if (max_logs == 0) { 82 free_entries = safe_malloc(sizeof(struct log_entry)); 83 free_entries->next = NULL; 84 entries_alloced = 1; 85 } 86 87 /* If we're running as root and going to change uid later, 88 change the ownership here so that the file is always owned by 89 the dnsmasq user. Then logrotate can just copy the owner. 90 Failure of the chown call is OK, (for instance when started as non-root) */ 91 if (log_to_file && ent_pw && ent_pw->pw_uid != 0 && fchown(log_fd, ent_pw->pw_uid, -1) != 0) 92 ret = errno; 93 94 return ret; 95 } 96 97 int log_reopen(char* log_file) { 98 if (log_fd != -1) close(log_fd); 99 100 /* NOTE: umask is set to 022 by the time this gets called */ 101 102 if (log_file) { 103 log_fd = open(log_file, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); 104 return log_fd != -1; 105 } else 106 #if defined(__ANDROID__) 107 #define _PATH_LOG "" /* dummy */ 108 log_fd = -1; 109 #else 110 { 111 int flags; 112 log_fd = socket(AF_UNIX, connection_type, 0); 113 114 if (log_fd == -1) return 0; 115 116 /* if max_logs is zero, leave the socket blocking */ 117 if (max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1) 118 fcntl(log_fd, F_SETFL, flags | O_NONBLOCK); 119 } 120 #endif 121 122 return 1; 123 } 124 125 static void free_entry(void) { 126 struct log_entry* tmp = entries; 127 entries = tmp->next; 128 tmp->next = free_entries; 129 free_entries = tmp; 130 } 131 132 static void log_write(void) { 133 ssize_t rc; 134 135 while (entries) { 136 /* Avoid duplicates over a fork() */ 137 if (entries->pid != getpid()) { 138 free_entry(); 139 continue; 140 } 141 142 connection_good = 1; 143 144 if ((rc = write(log_fd, entries->payload + entries->offset, entries->length)) != -1) { 145 entries->length -= rc; 146 entries->offset += rc; 147 if (entries->length == 0) { 148 free_entry(); 149 if (entries_lost != 0) { 150 int e = entries_lost; 151 entries_lost = 0; /* avoid wild recursion */ 152 my_syslog(LOG_WARNING, _("overflow: %d log entries lost"), e); 153 } 154 } 155 continue; 156 } 157 158 if (errno == EINTR) continue; 159 160 if (errno == EAGAIN) return; /* syslogd busy, go again when select() or poll() says so */ 161 162 if (errno == ENOBUFS) { 163 connection_good = 0; 164 return; 165 } 166 167 /* errors handling after this assumes sockets */ 168 if (!log_to_file) { 169 /* Once a stream socket hits EPIPE, we have to close and re-open 170 (we ignore SIGPIPE) */ 171 if (errno == EPIPE) { 172 if (log_reopen(NULL)) continue; 173 } else if (errno == ECONNREFUSED || errno == ENOTCONN || errno == EDESTADDRREQ || 174 errno == ECONNRESET) { 175 /* socket went (syslogd down?), try and reconnect. If we fail, 176 stop trying until the next call to my_syslog() 177 ECONNREFUSED -> connection went down 178 ENOTCONN -> nobody listening 179 (ECONNRESET, EDESTADDRREQ are *BSD equivalents) */ 180 181 struct sockaddr_un logaddr; 182 183 logaddr.sun_family = AF_UNIX; 184 strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path)); 185 186 /* Got connection back? try again. */ 187 if (connect(log_fd, (struct sockaddr*) &logaddr, sizeof(logaddr)) != -1) continue; 188 189 /* errors from connect which mean we should keep trying */ 190 if (errno == ENOENT || errno == EALREADY || errno == ECONNREFUSED || 191 errno == EISCONN || errno == EINTR || errno == EAGAIN) { 192 /* try again on next syslog() call */ 193 connection_good = 0; 194 return; 195 } 196 197 /* try the other sort of socket... */ 198 if (errno == EPROTOTYPE) { 199 connection_type = connection_type == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM; 200 if (log_reopen(NULL)) continue; 201 } 202 } 203 } 204 205 /* give up - fall back to syslog() - this handles out-of-space 206 when logging to a file, for instance. */ 207 log_fd = -1; 208 my_syslog(LOG_CRIT, _("log failed: %s"), strerror(errno)); 209 return; 210 } 211 } 212 213 /* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h. 214 OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between 215 DNS, DHCP and TFTP services. 216 */ 217 void my_syslog(int priority, const char* format, ...) { 218 va_list ap; 219 struct log_entry* entry; 220 time_t time_now; 221 char* p; 222 size_t len; 223 pid_t pid = getpid(); 224 char* func = ""; 225 #ifdef __ANDROID__ 226 int alog_lvl; 227 #endif 228 229 if ((LOG_FACMASK & priority) == MS_TFTP) 230 func = "-tftp"; 231 else if ((LOG_FACMASK & priority) == MS_DHCP) 232 func = "-dhcp"; 233 234 priority = LOG_PRI(priority); 235 236 if (log_stderr) { 237 fprintf(stderr, "dnsmasq%s: ", func); 238 va_start(ap, format); 239 vfprintf(stderr, format, ap); 240 va_end(ap); 241 fputc('\n', stderr); 242 } 243 244 #ifdef __ANDROID__ 245 if (priority <= LOG_ERR) 246 alog_lvl = ANDROID_LOG_ERROR; 247 else if (priority == LOG_WARNING) 248 alog_lvl = ANDROID_LOG_WARN; 249 else if (priority <= LOG_INFO) 250 alog_lvl = ANDROID_LOG_INFO; 251 else 252 alog_lvl = ANDROID_LOG_DEBUG; 253 va_start(ap, format); 254 __android_log_vprint(alog_lvl, "dnsmasq", format, ap); 255 va_end(ap); 256 #else 257 258 if (log_fd == -1) { 259 /* fall-back to syslog if we die during startup or fail during running. */ 260 static int isopen = 0; 261 if (!isopen) { 262 openlog("dnsmasq", LOG_PID, log_fac); 263 isopen = 1; 264 } 265 va_start(ap, format); 266 vsyslog(priority, format, ap); 267 va_end(ap); 268 return; 269 } 270 271 if ((entry = free_entries)) 272 free_entries = entry->next; 273 else if (entries_alloced < max_logs && (entry = malloc(sizeof(struct log_entry)))) 274 entries_alloced++; 275 276 if (!entry) 277 entries_lost++; 278 else { 279 /* add to end of list, consumed from the start */ 280 entry->next = NULL; 281 if (!entries) 282 entries = entry; 283 else { 284 struct log_entry* tmp; 285 for (tmp = entries; tmp->next; tmp = tmp->next) 286 ; 287 tmp->next = entry; 288 } 289 290 time(&time_now); 291 p = entry->payload; 292 if (!log_to_file) p += sprintf(p, "<%d>", priority | log_fac); 293 294 p += sprintf(p, "%.15s dnsmasq%s[%d]: ", ctime(&time_now) + 4, func, (int) pid); 295 296 len = p - entry->payload; 297 va_start(ap, format); 298 len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */ 299 va_end(ap); 300 entry->length = len > MAX_MESSAGE ? MAX_MESSAGE : len; 301 entry->offset = 0; 302 entry->pid = pid; 303 304 /* replace terminator with \n */ 305 if (log_to_file) entry->payload[entry->length - 1] = '\n'; 306 } 307 308 /* almost always, logging won't block, so try and write this now, 309 to save collecting too many log messages during a select loop. */ 310 log_write(); 311 312 /* Since we're doing things asynchronously, a cache-dump, for instance, 313 can now generate log lines very fast. With a small buffer (desirable), 314 that means it can overflow the log-buffer very quickly, 315 so that the cache dump becomes mainly a count of how many lines 316 overflowed. To avoid this, we delay here, the delay is controlled 317 by queue-occupancy, and grows exponentially. The delay is limited to (2^8)ms. 318 The scaling stuff ensures that when the queue is bigger than 8, the delay 319 only occurs for the last 8 entries. Once the queue is full, we stop delaying 320 to preserve performance. 321 */ 322 323 if (entries && max_logs != 0) { 324 int d; 325 326 for (d = 0, entry = entries; entry; entry = entry->next, d++) 327 ; 328 329 if (d == max_logs) 330 d = 0; 331 else if (max_logs > 8) 332 d -= max_logs - 8; 333 334 if (d > 0) { 335 struct timespec waiter; 336 waiter.tv_sec = 0; 337 waiter.tv_nsec = 1000000 << (d - 1); /* 1 ms */ 338 nanosleep(&waiter, NULL); 339 340 /* Have another go now */ 341 log_write(); 342 } 343 } 344 #endif 345 } 346 347 void set_log_writer(fd_set* set, int* maxfdp) { 348 if (entries && log_fd != -1 && connection_good) { 349 FD_SET(log_fd, set); 350 bump_maxfd(log_fd, maxfdp); 351 } 352 } 353 354 void check_log_writer(fd_set* set) { 355 if (log_fd != -1 && (!set || FD_ISSET(log_fd, set))) log_write(); 356 } 357 358 void flush_log(void) { 359 /* block until queue empty */ 360 if (log_fd != -1) { 361 int flags; 362 if ((flags = fcntl(log_fd, F_GETFL)) != -1) fcntl(log_fd, F_SETFL, flags & ~O_NONBLOCK); 363 log_write(); 364 close(log_fd); 365 } 366 } 367 368 void die(char* message, char* arg1, int exit_code) { 369 char* errmess = strerror(errno); 370 371 if (!arg1) arg1 = errmess; 372 373 log_stderr = 1; /* print as well as log when we die.... */ 374 fputc('\n', stderr); /* prettyfy startup-script message */ 375 my_syslog(LOG_CRIT, message, arg1, errmess); 376 377 log_stderr = 0; 378 my_syslog(LOG_CRIT, _("FAILED to start up")); 379 flush_log(); 380 381 exit(exit_code); 382 } 383