]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/dnsmasq.c
1 /* dnsmasq is Copyright (c) 2000-2003 Simon Kelley
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.
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.
13 /* See RFC1035 for details of the protocol this code talks. */
15 /* Author's email: simon@thekelleys.org.uk */
19 static int sigterm
, sighup
, sigusr1
, sigalarm
;
21 static void sig_handler(int sig
)
25 else if (sig
== SIGHUP
)
27 else if (sig
== SIGUSR1
)
29 else if (sig
== SIGALRM
)
33 int main (int argc
, char **argv
)
35 int cachesize
= CACHESIZ
;
36 int port
= NAMESERVER_PORT
;
37 int maxleases
= MAXLEASES
;
40 unsigned long local_ttl
= 0;
41 unsigned int options
, min_leasetime
;
42 char *runfile
= RUNFILE
;
43 time_t resolv_changed
= 0;
45 struct irec
*interfaces
= NULL
;
46 struct listener
*listener
, *listeners
;
48 char *mxtarget
= NULL
;
49 char *lease_file
= NULL
;
50 char *addn_hosts
= NULL
;
51 char *domain_suffix
= NULL
;
52 char *username
= CHUSER
;
53 char *groupname
= CHGRP
;
54 struct iname
*if_names
= NULL
;
55 struct iname
*if_addrs
= NULL
;
56 struct iname
*if_except
= NULL
;
57 struct server
*serv_addrs
= NULL
;
58 char *dnamebuff
, *packet
;
60 struct server
*servers
, *last_server
;
61 struct resolvc default_resolv
= { NULL
, 1, 0, RESOLVFILE
};
62 struct resolvc
*resolv
= &default_resolv
;
63 struct bogus_addr
*bogus_addr
= NULL
;
64 struct serverfd
*serverfdp
, *sfds
= NULL
;
65 struct dhcp_context
*dhcp_tmp
, *dhcp
= NULL
;
66 struct dhcp_config
*dhcp_configs
= NULL
;
67 struct dhcp_opt
*dhcp_options
= NULL
;
68 char *dhcp_file
= NULL
, *dhcp_sname
= NULL
;
69 struct in_addr dhcp_next_server
;
70 int leasefd
= -1, dhcpfd
= -1, dhcp_raw_fd
= -1;
71 struct sigaction sigact
;
74 sighup
= 1; /* init cache the first time through */
75 sigusr1
= 0; /* but don't dump */
76 sigterm
= 0; /* or die */
77 #ifdef HAVE_BROKEN_RTC
78 sigalarm
= 1; /* need regular lease dumps */
80 sigalarm
= 0; /* or not */
83 sigact
.sa_handler
= sig_handler
;
85 sigemptyset(&sigact
.sa_mask
);
86 sigaction(SIGUSR1
, &sigact
, NULL
);
87 sigaction(SIGHUP
, &sigact
, NULL
);
88 sigaction(SIGTERM
, &sigact
, NULL
);
89 sigaction(SIGALRM
, &sigact
, NULL
);
91 /* now block all the signals, they stay that way except
92 during the call to pselect */
93 sigaddset(&sigact
.sa_mask
, SIGUSR1
);
94 sigaddset(&sigact
.sa_mask
, SIGTERM
);
95 sigaddset(&sigact
.sa_mask
, SIGHUP
);
96 sigaddset(&sigact
.sa_mask
, SIGALRM
);
97 sigprocmask(SIG_BLOCK
, &sigact
.sa_mask
, &sigmask
);
99 /* These get allocated here to avoid overflowing the small stack
100 on embedded systems. dnamebuff is big enough to hold one
101 maximal sixed domain name and gets passed into all the processing
102 code. We manage to get away with one buffer. */
103 dnamebuff
= safe_malloc(MAXDNAME
);
104 packet
= safe_malloc(DNSMASQ_PACKETSZ
);
106 dhcp_next_server
.s_addr
= 0;
107 options
= read_opts(argc
, argv
, dnamebuff
, &resolv
, &mxname
, &mxtarget
, &lease_file
,
108 &username
, &groupname
, &domain_suffix
, &runfile
,
109 &if_names
, &if_addrs
, &if_except
, &bogus_addr
,
110 &serv_addrs
, &cachesize
, &port
, &query_port
, &local_ttl
, &addn_hosts
,
111 &dhcp
, &dhcp_configs
, &dhcp_options
,
112 &dhcp_file
, &dhcp_sname
, &dhcp_next_server
, &maxleases
, &min_leasetime
);
114 /* if we cannot support binding the wildcard address, set the "bind only
115 interfaces in use" option */
116 #ifndef HAVE_UDP_SRC_DST
117 options
|= OPT_NOWILD
;
121 lease_file
= LEASEFILE
;
126 complain("********* dhcp-lease option set, but not dhcp-range.", NULL
);
127 complain("********* Are you trying to use the obsolete ISC dhcpd integration?", NULL
);
128 complain("********* Please configure the dnsmasq integrated DHCP server by using", NULL
);
129 complain("********* the \"dhcp-range\" option, and remove any other DHCP server.", NULL
);
133 interfaces
= enumerate_interfaces(if_names
, if_addrs
, if_except
, port
);
134 if (options
& OPT_NOWILD
)
135 listeners
= create_bound_listeners(interfaces
);
137 listeners
= create_wildcard_listeners(port
);
140 cache_init(cachesize
, options
& OPT_LOG
);
142 #ifdef HAVE_BROKEN_RTC
143 if ((uptime_fd
= open(UPTIME
, O_RDONLY
)) == -1)
144 die("cannot open " UPTIME
":%s", NULL
);
147 now
= dnsmasq_time(uptime_fd
);
151 dhcp_init(&dhcpfd
, &dhcp_raw_fd
);
152 leasefd
= lease_init(lease_file
, domain_suffix
, dnamebuff
, packet
, now
, maxleases
);
153 if (options
& OPT_ETHERS
)
154 dhcp_configs
= dhcp_read_ethers(dhcp_configs
, dnamebuff
);
155 dhcp_update_configs(dhcp_configs
);
156 lease_update_from_configs(dhcp_configs
, domain_suffix
); /* must follow cache_init and lease_init */
157 lease_update_file(0, now
);
161 setbuf(stdout
, NULL
);
163 if (!(options
& OPT_DEBUG
))
166 struct passwd
*ent_pw
;
169 /* The following code "daemonizes" the process.
170 See Stevens section 12.4 */
183 umask(022); /* make pidfile 0644 */
185 /* write pidfile _after_ forking ! */
186 if (runfile
&& (pidfile
= fopen(runfile
, "w")))
188 fprintf(pidfile
, "%d\n", (int) getpid());
196 for (listener
= listeners
; listener
; listener
= listener
->next
)
197 if (listener
->fd
== i
)
211 /* Change uid and gid for security */
212 if (username
&& (ent_pw
= getpwnam(username
)))
216 /* remove all supplimentary groups */
217 setgroups(0, &dummy
);
218 /* change group for /etc/ppp/resolv.conf
219 otherwise get the group for "nobody" */
220 if ((groupname
&& (gp
= getgrnam(groupname
))) ||
221 (gp
= getgrgid(ent_pw
->pw_gid
)))
223 /* finally drop root */
224 setuid(ent_pw
->pw_uid
);
229 DNSMASQ_LOG_OPT(options
& OPT_DEBUG
),
230 DNSMASQ_LOG_FAC(options
& OPT_DEBUG
));
233 syslog(LOG_INFO
, "started, version %s cachesize %d", VERSION
, cachesize
);
235 syslog(LOG_INFO
, "started, version %s cache disabled", VERSION
);
237 if (options
& OPT_LOCALMX
)
238 syslog(LOG_INFO
, "serving MX record for local hosts target %s", mxtarget
);
240 syslog(LOG_INFO
, "serving MX record for mailhost %s target %s",
243 for (dhcp_tmp
= dhcp
; dhcp_tmp
; dhcp_tmp
= dhcp_tmp
->next
)
245 strcpy(dnamebuff
, inet_ntoa(dhcp_tmp
->start
));
246 if (dhcp_tmp
->lease_time
== 0)
247 sprintf(packet
, "infinite");
249 sprintf(packet
, "%ds", (int)dhcp_tmp
->lease_time
);
250 syslog(LOG_INFO
, "DHCP, IP range %s -- %s, lease time %s",
251 dnamebuff
, inet_ntoa(dhcp_tmp
->end
), packet
);
254 #ifdef HAVE_BROKEN_RTC
256 syslog(LOG_INFO
, "DHCP, %s will be written every %ds", lease_file
, min_leasetime
/3);
259 if (getuid() == 0 || geteuid() == 0)
260 syslog(LOG_WARNING
, "failed to drop root privs");
262 servers
= last_server
= check_servers(serv_addrs
, interfaces
, &sfds
);
270 cache_reload(options
, dnamebuff
, domain_suffix
, addn_hosts
);
273 dhcp_update_configs(dhcp_configs
);
274 lease_update_from_configs(dhcp_configs
, domain_suffix
);
275 lease_update_file(0, now
);
278 if (resolv
&& (options
& OPT_NO_POLL
))
279 servers
= last_server
=
280 check_servers(reload_servers(resolv
->name
, dnamebuff
, servers
, query_port
),
287 dump_cache(options
& (OPT_DEBUG
| OPT_LOG
), cachesize
);
295 lease_update_file(1, now
);
296 #ifdef HAVE_BROKEN_RTC
297 alarm(min_leasetime
/3);
309 for (serverfdp
= sfds
; serverfdp
; serverfdp
= serverfdp
->next
)
311 FD_SET(serverfdp
->fd
, &rset
);
312 if (serverfdp
->fd
> maxfd
)
313 maxfd
= serverfdp
->fd
;
316 for (listener
= listeners
; listener
; listener
= listener
->next
)
318 FD_SET(listener
->fd
, &rset
);
319 if (listener
->fd
> maxfd
)
320 maxfd
= listener
->fd
;
325 FD_SET(dhcpfd
, &rset
);
331 if (pselect(maxfd
+1, &rset
, NULL
, NULL
, NULL
, &sigmask
) < 0)
332 FD_ZERO(&rset
); /* rset otherwise undefined after error */
336 sigprocmask(SIG_SETMASK
, &sigmask
, &save_mask
);
337 if (select(maxfd
+1, &rset
, NULL
, NULL
, NULL
) < 0)
338 FD_ZERO(&rset
); /* rset otherwise undefined after error */
339 sigprocmask(SIG_SETMASK
, &save_mask
, NULL
);
346 now
= dnsmasq_time(uptime_fd
);
348 /* Check for changes to resolv files once per second max. */
349 if (last
== 0 || difftime(now
, last
) > 1.0)
352 if (!(options
& OPT_NO_POLL
))
354 struct resolvc
*res
= resolv
, *latest
= NULL
;
355 time_t last_change
= 0;
357 /* There may be more than one possible file.
358 Go through and find the one which changed _last_.
359 Warn of any which can't be read. */
362 if (stat(res
->name
, &statbuf
) == -1)
365 syslog(LOG_WARNING
, "failed to access %s: %m", res
->name
);
371 if (statbuf
.st_mtime
> last_change
)
373 last_change
= statbuf
.st_mtime
;
380 if (latest
&& last_change
> resolv_changed
)
382 resolv_changed
= last_change
;
383 servers
= last_server
=
384 check_servers(reload_servers(latest
->name
, dnamebuff
, servers
, query_port
),
390 for (serverfdp
= sfds
; serverfdp
; serverfdp
= serverfdp
->next
)
391 if (FD_ISSET(serverfdp
->fd
, &rset
))
392 last_server
= reply_query(serverfdp
->fd
, options
, packet
, now
,
393 dnamebuff
, last_server
, bogus_addr
);
395 if (dhcp
&& FD_ISSET(dhcpfd
, &rset
))
396 dhcp_packet(dhcp
, packet
, dhcp_options
, dhcp_configs
,
397 now
, dnamebuff
, domain_suffix
, dhcp_file
,
398 dhcp_sname
, dhcp_next_server
, dhcpfd
, dhcp_raw_fd
,
399 if_names
, if_addrs
, if_except
);
401 for (listener
= listeners
; listener
; listener
= listener
->next
)
402 if (FD_ISSET(listener
->fd
, &rset
))
403 last_server
= receive_query(listener
, packet
,
404 mxname
, mxtarget
, options
, now
, local_ttl
, dnamebuff
,
405 if_names
, if_addrs
, if_except
, last_server
, servers
);
408 syslog(LOG_INFO
, "exiting on receipt of SIGTERM");
410 #ifdef HAVE_BROKEN_RTC
412 lease_update_file(1, now
);