]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dnsmasq.c
import of dnsmasq-2.9.tar.gz
[people/ms/dnsmasq.git] / src / dnsmasq.c
CommitLineData
9e4abcb5
SK
1/* dnsmasq is Copyright (c) 2000-2003 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.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11*/
12
13/* See RFC1035 for details of the protocol this code talks. */
14
15/* Author's email: simon@thekelleys.org.uk */
16
17#include "dnsmasq.h"
18
44a2a316 19static int sigterm, sighup, sigusr1, sigalarm;
9e4abcb5
SK
20
21static void sig_handler(int sig)
22{
23 if (sig == SIGTERM)
24 sigterm = 1;
25 else if (sig == SIGHUP)
26 sighup = 1;
27 else if (sig == SIGUSR1)
28 sigusr1 = 1;
44a2a316
SK
29 else if (sig == SIGALRM)
30 sigalarm = 1;
9e4abcb5
SK
31}
32
33int main (int argc, char **argv)
34{
9e4abcb5
SK
35 int cachesize = CACHESIZ;
36 int port = NAMESERVER_PORT;
44a2a316 37 int maxleases = MAXLEASES;
9e4abcb5
SK
38 int query_port = 0;
39 int first_loop = 1;
de37951c 40 int bind_fallback = 0;
9e4abcb5 41 unsigned long local_ttl = 0;
44a2a316 42 unsigned int options, min_leasetime;
9e4abcb5
SK
43 char *runfile = RUNFILE;
44 time_t resolv_changed = 0;
45 time_t now, last = 0;
44a2a316 46 struct irec *interfaces = NULL;
de37951c 47 struct listener *listener, *listeners = NULL;
1cff166d 48 struct doctor *doctors = NULL;
de37951c 49 struct mx_record *mxnames = NULL;
9e4abcb5
SK
50 char *mxtarget = NULL;
51 char *lease_file = NULL;
52 char *addn_hosts = NULL;
53 char *domain_suffix = NULL;
54 char *username = CHUSER;
55 char *groupname = CHGRP;
56 struct iname *if_names = NULL;
57 struct iname *if_addrs = NULL;
58 struct iname *if_except = NULL;
9e4abcb5
SK
59 struct server *serv_addrs = NULL;
60 char *dnamebuff, *packet;
44a2a316 61 int uptime_fd = -1;
9e4abcb5
SK
62 struct server *servers, *last_server;
63 struct resolvc default_resolv = { NULL, 1, 0, RESOLVFILE };
64 struct resolvc *resolv = &default_resolv;
65 struct bogus_addr *bogus_addr = NULL;
66 struct serverfd *serverfdp, *sfds = NULL;
67 struct dhcp_context *dhcp_tmp, *dhcp = NULL;
68 struct dhcp_config *dhcp_configs = NULL;
69 struct dhcp_opt *dhcp_options = NULL;
a84fa1d0 70 struct dhcp_vendor *dhcp_vendors = NULL;
9e4abcb5
SK
71 char *dhcp_file = NULL, *dhcp_sname = NULL;
72 struct in_addr dhcp_next_server;
44a2a316 73 int leasefd = -1, dhcpfd = -1, dhcp_raw_fd = -1;
9e4abcb5
SK
74 struct sigaction sigact;
75 sigset_t sigmask;
33820b7e 76
9e4abcb5
SK
77 sighup = 1; /* init cache the first time through */
78 sigusr1 = 0; /* but don't dump */
9e4abcb5 79 sigterm = 0; /* or die */
44a2a316
SK
80#ifdef HAVE_BROKEN_RTC
81 sigalarm = 1; /* need regular lease dumps */
82#else
83 sigalarm = 0; /* or not */
84#endif
9e4abcb5
SK
85
86 sigact.sa_handler = sig_handler;
87 sigact.sa_flags = 0;
88 sigemptyset(&sigact.sa_mask);
89 sigaction(SIGUSR1, &sigact, NULL);
9e4abcb5
SK
90 sigaction(SIGHUP, &sigact, NULL);
91 sigaction(SIGTERM, &sigact, NULL);
44a2a316 92 sigaction(SIGALRM, &sigact, NULL);
9e4abcb5
SK
93
94 /* now block all the signals, they stay that way except
95 during the call to pselect */
96 sigaddset(&sigact.sa_mask, SIGUSR1);
9e4abcb5
SK
97 sigaddset(&sigact.sa_mask, SIGTERM);
98 sigaddset(&sigact.sa_mask, SIGHUP);
44a2a316 99 sigaddset(&sigact.sa_mask, SIGALRM);
9e4abcb5
SK
100 sigprocmask(SIG_BLOCK, &sigact.sa_mask, &sigmask);
101
102 /* These get allocated here to avoid overflowing the small stack
103 on embedded systems. dnamebuff is big enough to hold one
104 maximal sixed domain name and gets passed into all the processing
105 code. We manage to get away with one buffer. */
106 dnamebuff = safe_malloc(MAXDNAME);
44a2a316 107 packet = safe_malloc(DNSMASQ_PACKETSZ);
9e4abcb5
SK
108
109 dhcp_next_server.s_addr = 0;
de37951c 110 options = read_opts(argc, argv, dnamebuff, &resolv, &mxnames, &mxtarget, &lease_file,
9e4abcb5
SK
111 &username, &groupname, &domain_suffix, &runfile,
112 &if_names, &if_addrs, &if_except, &bogus_addr,
113 &serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts,
a84fa1d0 114 &dhcp, &dhcp_configs, &dhcp_options, &dhcp_vendors,
1cff166d
SK
115 &dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime,
116 &doctors);
44a2a316 117
9e4abcb5 118 if (!lease_file)
9e4abcb5 119 {
33820b7e
SK
120 if (dhcp)
121 lease_file = LEASEFILE;
9e4abcb5 122 }
33820b7e
SK
123#ifndef HAVE_ISC_READER
124 else if (!dhcp)
125 die("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h", NULL);
126#endif
9e4abcb5 127
a84fa1d0 128 interfaces = enumerate_interfaces(&if_names, &if_addrs, if_except, port);
de37951c
SK
129
130 if (!(options & OPT_NOWILD) && !(listeners = create_wildcard_listeners(port)))
131 {
132 bind_fallback = 1;
133 options |= OPT_NOWILD;
134 }
9e4abcb5 135
de37951c
SK
136 if (options & OPT_NOWILD)
137 {
138 struct iname *if_tmp;
139 listeners = create_bound_listeners(interfaces);
140
141 for (if_tmp = if_names; if_tmp; if_tmp = if_tmp->next)
142 if (if_tmp->name && !if_tmp->used)
143 die("unknown interface %s", if_tmp->name);
144
145 for (if_tmp = if_addrs; if_tmp; if_tmp = if_tmp->next)
146 if (!if_tmp->used)
147 {
148 char addrbuff[ADDRSTRLEN];
149#ifdef HAVE_IPV6
150 if (if_tmp->addr.sa.sa_family == AF_INET)
151 inet_ntop(AF_INET, &if_tmp->addr.in.sin_addr,
152 addrbuff, ADDRSTRLEN);
153 else
154 inet_ntop(AF_INET6, &if_tmp->addr.in6.sin6_addr,
155 addrbuff, ADDRSTRLEN);
156#else
157 strcpy(addrbuff, inet_ntoa(if_tmp->addr.in.sin_addr));
158#endif
159 die("no interface with address %s", addrbuff);
160 }
161 }
162
9e4abcb5
SK
163 forward_init(1);
164 cache_init(cachesize, options & OPT_LOG);
44a2a316
SK
165
166#ifdef HAVE_BROKEN_RTC
167 if ((uptime_fd = open(UPTIME, O_RDONLY)) == -1)
168 die("cannot open " UPTIME ":%s", NULL);
169#endif
170
171 now = dnsmasq_time(uptime_fd);
9e4abcb5
SK
172
173 if (dhcp)
174 {
de37951c
SK
175#if !defined(IP_PKTINFO) && !defined(IP_RECVIF)
176 int c;
177 struct iname *tmp;
178 for (c = 0, tmp = if_names; tmp; tmp = tmp->next)
179 if (!tmp->isloop)
180 c++;
181 if (c != 1)
182 die("must set exactly one interface on broken systems without IP_RECVIF", NULL);
183#endif
44a2a316
SK
184 dhcp_init(&dhcpfd, &dhcp_raw_fd);
185 leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, now, maxleases);
9e4abcb5
SK
186 }
187
188 setbuf(stdout, NULL);
189
190 if (!(options & OPT_DEBUG))
191 {
192 FILE *pidfile;
193 struct passwd *ent_pw;
194 int i;
195
196 /* The following code "daemonizes" the process.
197 See Stevens section 12.4 */
198
199#ifndef NO_FORK
200 if (fork() != 0 )
201 exit(0);
202
203 setsid();
204
205 if (fork() != 0)
206 exit(0);
207#endif
208
209 chdir("/");
210 umask(022); /* make pidfile 0644 */
211
212 /* write pidfile _after_ forking ! */
213 if (runfile && (pidfile = fopen(runfile, "w")))
214 {
215 fprintf(pidfile, "%d\n", (int) getpid());
216 fclose(pidfile);
217 }
218
219 umask(0);
220
221 for (i=0; i<64; i++)
222 {
44a2a316
SK
223 for (listener = listeners; listener; listener = listener->next)
224 if (listener->fd == i)
9e4abcb5 225 break;
44a2a316 226 if (listener)
9e4abcb5
SK
227 continue;
228
44a2a316
SK
229 if (i == leasefd ||
230 i == uptime_fd ||
231 i == dhcpfd ||
232 i == dhcp_raw_fd)
9e4abcb5
SK
233 continue;
234
235 close(i);
236 }
237
238 /* Change uid and gid for security */
239 if (username && (ent_pw = getpwnam(username)))
240 {
241 gid_t dummy;
242 struct group *gp;
243 /* remove all supplimentary groups */
244 setgroups(0, &dummy);
245 /* change group for /etc/ppp/resolv.conf
246 otherwise get the group for "nobody" */
247 if ((groupname && (gp = getgrnam(groupname))) ||
248 (gp = getgrgid(ent_pw->pw_gid)))
249 setgid(gp->gr_gid);
250 /* finally drop root */
251 setuid(ent_pw->pw_uid);
252 }
253 }
254
255 openlog("dnsmasq",
256 DNSMASQ_LOG_OPT(options & OPT_DEBUG),
257 DNSMASQ_LOG_FAC(options & OPT_DEBUG));
258
259 if (cachesize)
260 syslog(LOG_INFO, "started, version %s cachesize %d", VERSION, cachesize);
261 else
262 syslog(LOG_INFO, "started, version %s cache disabled", VERSION);
263
de37951c
SK
264 if (bind_fallback)
265 syslog(LOG_WARNING, "setting --bind-interfaces option because if OS limitations");
266
9e4abcb5
SK
267 for (dhcp_tmp = dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
268 {
269 strcpy(dnamebuff, inet_ntoa(dhcp_tmp->start));
270 if (dhcp_tmp->lease_time == 0)
271 sprintf(packet, "infinite");
272 else
273 sprintf(packet, "%ds", (int)dhcp_tmp->lease_time);
33820b7e
SK
274 syslog(LOG_INFO,
275 dhcp_tmp->start.s_addr == dhcp_tmp->end.s_addr ?
276 "DHCP, static leases only on %.0s%s, lease time %s" :
277 "DHCP, IP range %s -- %s, lease time %s",
44a2a316 278 dnamebuff, inet_ntoa(dhcp_tmp->end), packet);
9e4abcb5
SK
279 }
280
44a2a316
SK
281#ifdef HAVE_BROKEN_RTC
282 if (dhcp)
283 syslog(LOG_INFO, "DHCP, %s will be written every %ds", lease_file, min_leasetime/3);
284#endif
285
9e4abcb5
SK
286 if (getuid() == 0 || geteuid() == 0)
287 syslog(LOG_WARNING, "failed to drop root privs");
288
de37951c
SK
289 servers = check_servers(serv_addrs, interfaces, &sfds);
290 last_server = NULL;
291
9e4abcb5
SK
292 while (sigterm == 0)
293 {
294 fd_set rset;
295
296 if (sighup)
297 {
298 cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
44a2a316
SK
299 if (dhcp)
300 {
33820b7e
SK
301 if (options & OPT_ETHERS)
302 dhcp_configs = dhcp_read_ethers(dhcp_configs, dnamebuff);
44a2a316
SK
303 dhcp_update_configs(dhcp_configs);
304 lease_update_from_configs(dhcp_configs, domain_suffix);
305 lease_update_file(0, now);
306 lease_update_dns();
307 }
9e4abcb5 308 if (resolv && (options & OPT_NO_POLL))
de37951c
SK
309 {
310 servers = check_servers(reload_servers(resolv->name, dnamebuff, servers, query_port),
311 interfaces, &sfds);
312 last_server = NULL;
313 }
9e4abcb5
SK
314 sighup = 0;
315 }
316
317 if (sigusr1)
318 {
319 dump_cache(options & (OPT_DEBUG | OPT_LOG), cachesize);
320 sigusr1 = 0;
321 }
322
44a2a316 323 if (sigalarm)
9e4abcb5 324 {
44a2a316
SK
325 if (dhcp)
326 {
327 lease_update_file(1, now);
328#ifdef HAVE_BROKEN_RTC
329 alarm(min_leasetime/3);
330#endif
331 }
332 sigalarm = 0;
9e4abcb5
SK
333 }
334
335 FD_ZERO(&rset);
336
337 if (!first_loop)
338 {
339 int maxfd = 0;
340
341 for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
342 {
343 FD_SET(serverfdp->fd, &rset);
344 if (serverfdp->fd > maxfd)
345 maxfd = serverfdp->fd;
346 }
347
44a2a316 348 for (listener = listeners; listener; listener = listener->next)
9e4abcb5 349 {
44a2a316
SK
350 FD_SET(listener->fd, &rset);
351 if (listener->fd > maxfd)
352 maxfd = listener->fd;
9e4abcb5
SK
353 }
354
44a2a316 355 if (dhcp)
9e4abcb5 356 {
44a2a316
SK
357 FD_SET(dhcpfd, &rset);
358 if (dhcpfd > maxfd)
359 maxfd = dhcpfd;
9e4abcb5 360 }
44a2a316 361
9e4abcb5
SK
362#ifdef HAVE_PSELECT
363 if (pselect(maxfd+1, &rset, NULL, NULL, NULL, &sigmask) < 0)
364 FD_ZERO(&rset); /* rset otherwise undefined after error */
365#else
366 {
367 sigset_t save_mask;
368 sigprocmask(SIG_SETMASK, &sigmask, &save_mask);
369 if (select(maxfd+1, &rset, NULL, NULL, NULL) < 0)
370 FD_ZERO(&rset); /* rset otherwise undefined after error */
371 sigprocmask(SIG_SETMASK, &save_mask, NULL);
372 }
373#endif
374
375 }
376
377 first_loop = 0;
44a2a316 378 now = dnsmasq_time(uptime_fd);
9e4abcb5
SK
379
380 /* Check for changes to resolv files once per second max. */
381 if (last == 0 || difftime(now, last) > 1.0)
382 {
383 last = now;
33820b7e
SK
384
385#ifdef HAVE_ISC_READER
386 if (lease_file && !dhcp)
387 load_dhcp(lease_file, domain_suffix, now, dnamebuff);
388#endif
389
9e4abcb5
SK
390 if (!(options & OPT_NO_POLL))
391 {
392 struct resolvc *res = resolv, *latest = NULL;
9e4abcb5 393 struct stat statbuf;
33820b7e 394 time_t last_change = 0;
9e4abcb5
SK
395 /* There may be more than one possible file.
396 Go through and find the one which changed _last_.
397 Warn of any which can't be read. */
398 while (res)
399 {
400 if (stat(res->name, &statbuf) == -1)
401 {
402 if (!res->logged)
403 syslog(LOG_WARNING, "failed to access %s: %m", res->name);
404 res->logged = 1;
405 }
406 else
407 {
408 res->logged = 0;
de37951c 409 if (difftime(statbuf.st_mtime, last_change) > 0.0)
9e4abcb5
SK
410 {
411 last_change = statbuf.st_mtime;
412 latest = res;
413 }
414 }
415 res = res->next;
416 }
417
de37951c 418 if (latest && difftime(last_change, resolv_changed) > 0.0)
9e4abcb5
SK
419 {
420 resolv_changed = last_change;
de37951c
SK
421 servers = check_servers(reload_servers(latest->name, dnamebuff, servers, query_port),
422 interfaces, &sfds);
423 last_server = NULL;
9e4abcb5
SK
424 }
425 }
426 }
427
428 for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
429 if (FD_ISSET(serverfdp->fd, &rset))
de37951c
SK
430 last_server = reply_query(serverfdp, options, packet, now,
431 dnamebuff, servers, last_server, bogus_addr, doctors);
9e4abcb5 432
44a2a316 433 if (dhcp && FD_ISSET(dhcpfd, &rset))
a84fa1d0 434 dhcp_packet(dhcp, packet, dhcp_options, dhcp_configs, dhcp_vendors,
44a2a316
SK
435 now, dnamebuff, domain_suffix, dhcp_file,
436 dhcp_sname, dhcp_next_server, dhcpfd, dhcp_raw_fd,
437 if_names, if_addrs, if_except);
9e4abcb5 438
44a2a316
SK
439 for (listener = listeners; listener; listener = listener->next)
440 if (FD_ISSET(listener->fd, &rset))
441 last_server = receive_query(listener, packet,
de37951c 442 mxnames, mxtarget, options, now, local_ttl, dnamebuff,
44a2a316 443 if_names, if_addrs, if_except, last_server, servers);
9e4abcb5
SK
444 }
445
446 syslog(LOG_INFO, "exiting on receipt of SIGTERM");
44a2a316
SK
447
448#ifdef HAVE_BROKEN_RTC
449 if (dhcp)
450 lease_update_file(1, now);
451#endif
452
453 if (leasefd != -1)
454 close(leasefd);
9e4abcb5
SK
455 return 0;
456}
457
458
459
460
461
462