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