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
11723d6d5c524cd8bb0dcba45ffa9dd546b507e7e30Elliott Hughes#if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__)
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