|
version 1.1.1.4, 2021/03/17 00:56:46
|
version 1.1.1.5, 2023/09/27 11:02:07
|
|
Line 1
|
Line 1
|
| /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley |
| |
|
| This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
|
Line 17
|
Line 17
|
| /* Declare static char *compiler_opts in config.h */ |
/* Declare static char *compiler_opts in config.h */ |
| #define DNSMASQ_COMPILE_OPTS |
#define DNSMASQ_COMPILE_OPTS |
| |
|
| |
/* dnsmasq.h has to be included first as it sources config.h */ |
| #include "dnsmasq.h" |
#include "dnsmasq.h" |
| |
|
| |
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR) |
| |
#include <locale.h> |
| |
#endif |
| |
|
| struct daemon *daemon; |
struct daemon *daemon; |
| |
|
| static volatile pid_t pid = 0; |
static volatile pid_t pid = 0; |
| static volatile int pipewrite; |
static volatile int pipewrite; |
| |
|
| static int set_dns_listeners(time_t now); | static void set_dns_listeners(void); |
| static void check_dns_listeners(time_t now); |
static void check_dns_listeners(time_t now); |
| static void sig_handler(int sig); |
static void sig_handler(int sig); |
| static void async_event(int pipe, time_t now); |
static void async_event(int pipe, time_t now); |
|
Line 34 static void poll_resolv(int force, int do_reload, time
|
Line 39 static void poll_resolv(int force, int do_reload, time
|
| |
|
| int main (int argc, char **argv) |
int main (int argc, char **argv) |
| { |
{ |
| int bind_fallback = 0; |
|
| time_t now; |
time_t now; |
| struct sigaction sigact; |
struct sigaction sigact; |
| struct iname *if_tmp; |
struct iname *if_tmp; |
|
Line 59 int main (int argc, char **argv)
|
Line 63 int main (int argc, char **argv)
|
| int did_bind = 0; |
int did_bind = 0; |
| struct server *serv; |
struct server *serv; |
| char *netlink_warn; |
char *netlink_warn; |
| |
#else |
| |
int bind_fallback = 0; |
| #endif |
#endif |
| #if defined(HAVE_DHCP) || defined(HAVE_DHCP6) |
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6) |
| struct dhcp_context *context; |
struct dhcp_context *context; |
|
Line 68 int main (int argc, char **argv)
|
Line 74 int main (int argc, char **argv)
|
| int tftp_prefix_missing = 0; |
int tftp_prefix_missing = 0; |
| #endif |
#endif |
| |
|
| #ifdef LOCALEDIR | #if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR) |
| setlocale(LC_ALL, ""); |
setlocale(LC_ALL, ""); |
| |
#endif |
| |
#ifdef LOCALEDIR |
| bindtextdomain("dnsmasq", LOCALEDIR); |
bindtextdomain("dnsmasq", LOCALEDIR); |
| textdomain("dnsmasq"); |
textdomain("dnsmasq"); |
| #endif |
#endif |
|
Line 109 int main (int argc, char **argv)
|
Line 117 int main (int argc, char **argv)
|
| daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ; |
daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ; |
| daemon->packet = safe_malloc(daemon->packet_buff_sz); |
daemon->packet = safe_malloc(daemon->packet_buff_sz); |
| |
|
| daemon->addrbuff = safe_malloc(ADDRSTRLEN); |
|
| if (option_bool(OPT_EXTRALOG)) |
if (option_bool(OPT_EXTRALOG)) |
| daemon->addrbuff2 = safe_malloc(ADDRSTRLEN); |
daemon->addrbuff2 = safe_malloc(ADDRSTRLEN); |
| |
|
|
Line 135 int main (int argc, char **argv)
|
Line 142 int main (int argc, char **argv)
|
| } |
} |
| #endif |
#endif |
| |
|
| |
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) |
| |
/* CONNTRACK UBUS code uses this buffer, so if not allocated above, |
| |
we need to allocate it here. */ |
| |
if (option_bool(OPT_CMARK_ALST_EN) && !daemon->workspacename) |
| |
daemon->workspacename = safe_malloc(MAXDNAME); |
| |
#endif |
| |
|
| #ifdef HAVE_DHCP |
#ifdef HAVE_DHCP |
| if (!daemon->lease_file) |
if (!daemon->lease_file) |
| { |
{ |
|
Line 205 int main (int argc, char **argv)
|
Line 219 int main (int argc, char **argv)
|
| #endif |
#endif |
| |
|
| #ifdef HAVE_CONNTRACK |
#ifdef HAVE_CONNTRACK |
| if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport)) | if (option_bool(OPT_CONNTRACK)) |
| die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF); | { |
| | if (daemon->query_port != 0 || daemon->osport) |
| | die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF); |
| | |
| | need_cap_net_admin = 1; |
| | } |
| #else |
#else |
| if (option_bool(OPT_CONNTRACK)) |
if (option_bool(OPT_CONNTRACK)) |
| die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF); |
die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF); |
|
Line 237 int main (int argc, char **argv)
|
Line 256 int main (int argc, char **argv)
|
| die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF); |
die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF); |
| #endif |
#endif |
| |
|
| |
/* Handle only one of min_port/max_port being set. */ |
| |
if (daemon->min_port != 0 && daemon->max_port == 0) |
| |
daemon->max_port = MAX_PORT; |
| |
|
| |
if (daemon->max_port != 0 && daemon->min_port == 0) |
| |
daemon->min_port = MIN_PORT; |
| |
|
| if (daemon->max_port < daemon->min_port) |
if (daemon->max_port < daemon->min_port) |
| die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF); |
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF); |
| |
|
| |
if (daemon->max_port != 0 && |
| |
daemon->max_port - daemon->min_port + 1 < daemon->randport_limit) |
| |
die(_("port_limit must not be larger than available port range"), NULL, EC_BADCONF); |
| |
|
| now = dnsmasq_time(); |
now = dnsmasq_time(); |
| |
|
| if (daemon->auth_zones) |
if (daemon->auth_zones) |
|
Line 327 int main (int argc, char **argv)
|
Line 357 int main (int argc, char **argv)
|
| } |
} |
| #endif |
#endif |
| |
|
| |
#ifdef HAVE_NFTSET |
| |
if (daemon->nftsets) |
| |
{ |
| |
nftset_init(); |
| |
# ifdef HAVE_LINUX_NETWORK |
| |
need_cap_net_admin = 1; |
| |
# endif |
| |
} |
| |
#endif |
| |
|
| #if defined(HAVE_LINUX_NETWORK) |
#if defined(HAVE_LINUX_NETWORK) |
| netlink_warn = netlink_init(); |
netlink_warn = netlink_init(); |
| #elif defined(HAVE_BSD_NETWORK) |
#elif defined(HAVE_BSD_NETWORK) |
|
Line 351 int main (int argc, char **argv)
|
Line 391 int main (int argc, char **argv)
|
| #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP) |
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP) |
| /* after enumerate_interfaces() */ |
/* after enumerate_interfaces() */ |
| bound_device = whichdevice(); |
bound_device = whichdevice(); |
| |
|
| if (daemon->dhcp) |
|
| { |
|
| if (!daemon->relay4 && bound_device) |
|
| { |
|
| bindtodevice(bound_device, daemon->dhcpfd); |
|
| did_bind = 1; |
|
| } |
|
| if (daemon->enable_pxe && bound_device) |
|
| { |
|
| bindtodevice(bound_device, daemon->pxefd); |
|
| did_bind = 1; |
|
| } |
|
| } |
|
| #endif |
|
| |
|
| #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6) | if ((did_bind = bind_dhcp_devices(bound_device)) & 2) |
| if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device) | die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); |
| { | |
| bindtodevice(bound_device, daemon->dhcp6fd); | |
| did_bind = 1; | |
| } | |
| #endif |
#endif |
| } |
} |
| else |
else |
|
Line 392 int main (int argc, char **argv)
|
Line 413 int main (int argc, char **argv)
|
| cache_init(); |
cache_init(); |
| blockdata_init(); |
blockdata_init(); |
| hash_questions_init(); |
hash_questions_init(); |
| |
|
| |
/* Scale random socket pool by ftabsize, but |
| |
limit it based on available fds. */ |
| |
daemon->numrrand = daemon->ftabsize/2; |
| |
if (daemon->numrrand > max_fd/3) |
| |
daemon->numrrand = max_fd/3; |
| |
/* safe_malloc returns zero'd memory */ |
| |
daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd)); |
| } |
} |
| |
|
| #ifdef HAVE_INOTIFY |
#ifdef HAVE_INOTIFY |
|
Line 415 int main (int argc, char **argv)
|
Line 444 int main (int argc, char **argv)
|
| #ifdef HAVE_DBUS |
#ifdef HAVE_DBUS |
| { |
{ |
| char *err; |
char *err; |
| daemon->dbus = NULL; |
|
| daemon->watches = NULL; |
|
| if ((err = dbus_init())) |
if ((err = dbus_init())) |
| die(_("DBus error: %s"), err, EC_MISC); |
die(_("DBus error: %s"), err, EC_MISC); |
| } |
} |
|
Line 427 int main (int argc, char **argv)
|
Line 454 int main (int argc, char **argv)
|
| if (option_bool(OPT_UBUS)) |
if (option_bool(OPT_UBUS)) |
| #ifdef HAVE_UBUS |
#ifdef HAVE_UBUS |
| { |
{ |
| daemon->ubus = NULL; | char *err; |
| ubus_init(); | if ((err = ubus_init())) |
| | die(_("UBus error: %s"), err, EC_MISC); |
| } |
} |
| #else |
#else |
| die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF); |
die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF); |
|
Line 691 int main (int argc, char **argv)
|
Line 719 int main (int argc, char **argv)
|
| /* if we are to run scripts, we need to fork a helper before dropping root. */ |
/* if we are to run scripts, we need to fork a helper before dropping root. */ |
| daemon->helperfd = -1; |
daemon->helperfd = -1; |
| #ifdef HAVE_SCRIPT |
#ifdef HAVE_SCRIPT |
| if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) && | if ((daemon->dhcp || |
| | daemon->dhcp6 || |
| | daemon->relay6 || |
| | option_bool(OPT_TFTP) || |
| | option_bool(OPT_SCRIPT_ARP)) && |
| (daemon->lease_change_command || daemon->luascript)) |
(daemon->lease_change_command || daemon->luascript)) |
| daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd); |
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd); |
| #endif |
#endif |
|
Line 895 int main (int argc, char **argv)
|
Line 927 int main (int argc, char **argv)
|
| my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), |
my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), |
| daemon->log_file, strerror(log_err)); |
daemon->log_file, strerror(log_err)); |
| |
|
| |
#ifndef HAVE_LINUX_NETWORK |
| if (bind_fallback) |
if (bind_fallback) |
| my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations")); |
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations")); |
| |
#endif |
| |
|
| if (option_bool(OPT_NOWILD)) |
if (option_bool(OPT_NOWILD)) |
| warn_bound_listeners(); |
warn_bound_listeners(); |
|
Line 980 int main (int argc, char **argv)
|
Line 1014 int main (int argc, char **argv)
|
| a single file will be sent to may clients (the file only needs |
a single file will be sent to may clients (the file only needs |
| one fd). */ |
one fd). */ |
| |
|
| max_fd -= 30; /* use other than TFTP */ | max_fd -= 30 + daemon->numrrand; /* use other than TFTP */ |
| |
|
| if (max_fd < 0) |
if (max_fd < 0) |
| max_fd = 5; |
max_fd = 5; |
|
Line 1010 int main (int argc, char **argv)
|
Line 1044 int main (int argc, char **argv)
|
| close(err_pipe[1]); |
close(err_pipe[1]); |
| |
|
| if (daemon->port != 0) |
if (daemon->port != 0) |
| check_servers(); | check_servers(0); |
| |
|
| pid = getpid(); |
pid = getpid(); |
| |
|
|
Line 1025 int main (int argc, char **argv)
|
Line 1059 int main (int argc, char **argv)
|
| |
|
| while (1) |
while (1) |
| { |
{ |
| int t, timeout = -1; | int timeout = fast_retry(now); |
| |
|
| poll_reset(); |
poll_reset(); |
| |
|
| /* if we are out of resources, find how long we have to wait |
|
| for some to come free, we'll loop around then and restart |
|
| listening for queries */ |
|
| if ((t = set_dns_listeners(now)) != 0) |
|
| timeout = t * 1000; |
|
| |
|
| /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */ |
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */ |
| if (daemon->tftp_trans || | if ((daemon->tftp_trans || (option_bool(OPT_DBUS) && !daemon->dbus)) && |
| (option_bool(OPT_DBUS) && !daemon->dbus)) | (timeout == -1 || timeout > 250)) |
| timeout = 250; |
timeout = 250; |
| |
| /* Wake every second whilst waiting for DAD to complete */ |
/* Wake every second whilst waiting for DAD to complete */ |
| else if (is_dad_listeners()) | else if (is_dad_listeners() && |
| | (timeout == -1 || timeout > 1000)) |
| timeout = 1000; |
timeout = 1000; |
| |
|
| |
set_dns_listeners(); |
| |
|
| #ifdef HAVE_DBUS |
#ifdef HAVE_DBUS |
| set_dbus_listeners(); | if (option_bool(OPT_DBUS)) |
| | set_dbus_listeners(); |
| #endif |
#endif |
| |
| #ifdef HAVE_UBUS |
#ifdef HAVE_UBUS |
| if (option_bool(OPT_UBUS)) |
if (option_bool(OPT_UBUS)) |
| set_ubus_listeners(); |
set_ubus_listeners(); |
| #endif |
#endif |
| | |
| #ifdef HAVE_DHCP |
#ifdef HAVE_DHCP |
| |
# if defined(HAVE_LINUX_NETWORK) |
| |
if (bind_dhcp_devices(bound_device) & 2) |
| |
{ |
| |
static int warned = 0; |
| |
if (!warned) |
| |
{ |
| |
my_syslog(LOG_ERR, _("error binding DHCP socket to device %s"), bound_device); |
| |
warned = 1; |
| |
} |
| |
} |
| |
# endif |
| if (daemon->dhcp || daemon->relay4) |
if (daemon->dhcp || daemon->relay4) |
| { |
{ |
| poll_listen(daemon->dhcpfd, POLLIN); |
poll_listen(daemon->dhcpfd, POLLIN); |
|
Line 1097 int main (int argc, char **argv)
|
Line 1140 int main (int argc, char **argv)
|
| while (helper_buf_empty() && do_tftp_script_run()); |
while (helper_buf_empty() && do_tftp_script_run()); |
| # endif |
# endif |
| |
|
| |
# ifdef HAVE_DHCP6 |
| |
while (helper_buf_empty() && do_snoop_script_run()); |
| |
# endif |
| |
|
| if (!helper_buf_empty()) |
if (!helper_buf_empty()) |
| poll_listen(daemon->helperfd, POLLOUT); |
poll_listen(daemon->helperfd, POLLOUT); |
| #else |
#else |
|
Line 1172 int main (int argc, char **argv)
|
Line 1219 int main (int argc, char **argv)
|
| |
|
| #ifdef HAVE_DBUS |
#ifdef HAVE_DBUS |
| /* if we didn't create a DBus connection, retry now. */ |
/* if we didn't create a DBus connection, retry now. */ |
| if (option_bool(OPT_DBUS) && !daemon->dbus) | if (option_bool(OPT_DBUS)) |
| { |
{ |
| char *err; | if (!daemon->dbus) |
| if ((err = dbus_init())) | { |
| my_syslog(LOG_WARNING, _("DBus error: %s"), err); | char *err = dbus_init(); |
| if (daemon->dbus) | |
| my_syslog(LOG_INFO, _("connected to system DBus")); | if (daemon->dbus) |
| | my_syslog(LOG_INFO, _("connected to system DBus")); |
| | else if (err) |
| | { |
| | my_syslog(LOG_ERR, _("DBus error: %s"), err); |
| | reset_option_bool(OPT_DBUS); /* fatal error, stop trying. */ |
| | } |
| | } |
| | |
| | check_dbus_listeners(); |
| } |
} |
| check_dbus_listeners(); |
|
| #endif |
#endif |
| |
|
| #ifdef HAVE_UBUS |
#ifdef HAVE_UBUS |
| |
/* if we didn't create a UBus connection, retry now. */ |
| if (option_bool(OPT_UBUS)) |
if (option_bool(OPT_UBUS)) |
| { | { |
| /* if we didn't create a UBus connection, retry now. */ | if (!daemon->ubus) |
| if (!daemon->ubus) | { |
| { | char *err = ubus_init(); |
| ubus_init(); | |
| } | |
| |
|
| check_ubus_listeners(); | if (daemon->ubus) |
| } | my_syslog(LOG_INFO, _("connected to system UBus")); |
| | else if (err) |
| | { |
| | my_syslog(LOG_ERR, _("UBus error: %s"), err); |
| | reset_option_bool(OPT_UBUS); /* fatal error, stop trying. */ |
| | } |
| | } |
| | |
| | check_ubus_listeners(); |
| | } |
| #endif |
#endif |
| |
|
| check_dns_listeners(now); |
check_dns_listeners(now); |
|
Line 1426 static void async_event(int pipe, time_t now)
|
Line 1489 static void async_event(int pipe, time_t now)
|
| } |
} |
| |
|
| if (check) |
if (check) |
| check_servers(); | check_servers(0); |
| } |
} |
| |
|
| #ifdef HAVE_DHCP |
#ifdef HAVE_DHCP |
|
Line 1537 static void async_event(int pipe, time_t now)
|
Line 1600 static void async_event(int pipe, time_t now)
|
| { |
{ |
| /* block in writes until all done */ |
/* block in writes until all done */ |
| if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1) |
if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1) |
| fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK); | while(retry_send(fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK))); |
| do { |
do { |
| helper_write(); |
helper_write(); |
| } while (!helper_buf_empty() || do_script_run(now)); |
} while (!helper_buf_empty() || do_script_run(now)); |
|
Line 1607 static void poll_resolv(int force, int do_reload, time
|
Line 1670 static void poll_resolv(int force, int do_reload, time
|
| else |
else |
| { |
{ |
| res->logged = 0; |
res->logged = 0; |
| if (force || (statbuf.st_mtime != res->mtime)) | if (force || (statbuf.st_mtime != res->mtime || statbuf.st_ino != res->ino)) |
| { |
{ |
| res->mtime = statbuf.st_mtime; |
res->mtime = statbuf.st_mtime; |
| |
res->ino = statbuf.st_ino; |
| if (difftime(statbuf.st_mtime, last_change) > 0.0) |
if (difftime(statbuf.st_mtime, last_change) > 0.0) |
| { |
{ |
| last_change = statbuf.st_mtime; |
last_change = statbuf.st_mtime; |
|
Line 1625 static void poll_resolv(int force, int do_reload, time
|
Line 1689 static void poll_resolv(int force, int do_reload, time
|
| { |
{ |
| my_syslog(LOG_INFO, _("reading %s"), latest->name); |
my_syslog(LOG_INFO, _("reading %s"), latest->name); |
| warned = 0; |
warned = 0; |
| check_servers(); | check_servers(0); |
| if (option_bool(OPT_RELOAD) && do_reload) |
if (option_bool(OPT_RELOAD) && do_reload) |
| clear_cache_and_reload(now); |
clear_cache_and_reload(now); |
| } |
} |
| else |
else |
| { |
{ |
| |
/* If we're delaying things, we don't call check_servers(), but |
| |
reload_servers() may have deleted some servers, rendering the server_array |
| |
invalid, so just rebuild that here. Once reload_servers() succeeds, |
| |
we call check_servers() above, which calls build_server_array itself. */ |
| |
build_server_array(); |
| latest->mtime = 0; |
latest->mtime = 0; |
| if (!warned) |
if (!warned) |
| { |
{ |
|
Line 1668 void clear_cache_and_reload(time_t now)
|
Line 1737 void clear_cache_and_reload(time_t now)
|
| #endif |
#endif |
| } |
} |
| |
|
| static int set_dns_listeners(time_t now) | static void set_dns_listeners(void) |
| { |
{ |
| struct serverfd *serverfdp; |
struct serverfd *serverfdp; |
| struct listener *listener; |
struct listener *listener; |
| int wait = 0, i; | struct randfd_list *rfl; |
| | int i; |
| |
|
| #ifdef HAVE_TFTP |
#ifdef HAVE_TFTP |
| int tftp = 0; |
int tftp = 0; |
|
Line 1685 static int set_dns_listeners(time_t now)
|
Line 1755 static int set_dns_listeners(time_t now)
|
| } |
} |
| #endif |
#endif |
| |
|
| /* will we be able to get memory? */ |
|
| if (daemon->port != 0) |
|
| get_new_frec(now, &wait, NULL); |
|
| |
|
| for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) |
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) |
| poll_listen(serverfdp->fd, POLLIN); |
poll_listen(serverfdp->fd, POLLIN); |
| |
|
| if (daemon->port != 0 && !daemon->osport) | for (i = 0; i < daemon->numrrand; i++) |
| for (i = 0; i < RANDOM_SOCKS; i++) | if (daemon->randomsocks[i].refcount != 0) |
| if (daemon->randomsocks[i].refcount != 0) | poll_listen(daemon->randomsocks[i].fd, POLLIN); |
| poll_listen(daemon->randomsocks[i].fd, POLLIN); | |
| | /* Check overflow random sockets too. */ |
| | for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next) |
| | poll_listen(rfl->rfd->fd, POLLIN); |
| | |
| | /* check to see if we have free tcp process slots. */ |
| | for (i = MAX_PROCS - 1; i >= 0; i--) |
| | if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) |
| | break; |
| | |
| for (listener = daemon->listeners; listener; listener = listener->next) |
for (listener = daemon->listeners; listener; listener = listener->next) |
| { |
{ |
| /* only listen for queries if we have resources */ | if (listener->fd != -1) |
| if (listener->fd != -1 && wait == 0) | |
| poll_listen(listener->fd, POLLIN); |
poll_listen(listener->fd, POLLIN); |
| | |
| /* death of a child goes through the select loop, so | /* Only listen for TCP connections when a process slot |
| we don't need to explicitly arrange to wake up here */ | is available. Death of a child goes through the select loop, so |
| if (listener->tcpfd != -1) | we don't need to explicitly arrange to wake up here, |
| for (i = 0; i < MAX_PROCS; i++) | we'll be called again when a slot becomes available. */ |
| if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) | if (listener->tcpfd != -1 && i >= 0) |
| { | poll_listen(listener->tcpfd, POLLIN); |
| poll_listen(listener->tcpfd, POLLIN); | |
| break; | |
| } | |
| |
| #ifdef HAVE_TFTP |
#ifdef HAVE_TFTP |
| /* tftp == 0 in single-port mode. */ |
/* tftp == 0 in single-port mode. */ |
| if (tftp <= daemon->tftp_max && listener->tftpfd != -1) |
if (tftp <= daemon->tftp_max && listener->tftpfd != -1) |
| poll_listen(listener->tftpfd, POLLIN); |
poll_listen(listener->tftpfd, POLLIN); |
| #endif |
#endif |
| |
|
| } |
} |
| |
|
| if (!option_bool(OPT_DEBUG)) |
if (!option_bool(OPT_DEBUG)) |
| for (i = 0; i < MAX_PROCS; i++) |
for (i = 0; i < MAX_PROCS; i++) |
| if (daemon->tcp_pipes[i] != -1) |
if (daemon->tcp_pipes[i] != -1) |
| poll_listen(daemon->tcp_pipes[i], POLLIN); |
poll_listen(daemon->tcp_pipes[i], POLLIN); |
| |
|
| return wait; |
|
| } |
} |
| |
|
| static void check_dns_listeners(time_t now) |
static void check_dns_listeners(time_t now) |
| { |
{ |
| struct serverfd *serverfdp; |
struct serverfd *serverfdp; |
| struct listener *listener; |
struct listener *listener; |
| |
struct randfd_list *rfl; |
| int i; |
int i; |
| int pipefd[2]; |
int pipefd[2]; |
| |
|
| for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) |
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) |
| if (poll_check(serverfdp->fd, POLLIN)) |
if (poll_check(serverfdp->fd, POLLIN)) |
| reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now); | reply_query(serverfdp->fd, now); |
| |
|
| if (daemon->port != 0 && !daemon->osport) | for (i = 0; i < daemon->numrrand; i++) |
| for (i = 0; i < RANDOM_SOCKS; i++) | if (daemon->randomsocks[i].refcount != 0 && |
| if (daemon->randomsocks[i].refcount != 0 && | poll_check(daemon->randomsocks[i].fd, POLLIN)) |
| poll_check(daemon->randomsocks[i].fd, POLLIN)) | reply_query(daemon->randomsocks[i].fd, now); |
| reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); | |
| |
|
| |
/* Check overflow random sockets too. */ |
| |
for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next) |
| |
if (poll_check(rfl->rfd->fd, POLLIN)) |
| |
reply_query(rfl->rfd->fd, now); |
| |
|
| /* Races. The child process can die before we read all of the data from the |
/* Races. The child process can die before we read all of the data from the |
| pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the |
pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the |
| process, and tcp_pipes to -1 and close the FD when we read the last |
process, and tcp_pipes to -1 and close the FD when we read the last |
|
Line 1773 static void check_dns_listeners(time_t now)
|
Line 1845 static void check_dns_listeners(time_t now)
|
| tftp_request(listener, now); |
tftp_request(listener, now); |
| #endif |
#endif |
| |
|
| if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN)) | /* check to see if we have a free tcp process slot. |
| | Note that we can't assume that because we had |
| | at least one a poll() time, that we still do. |
| | There may be more waiting connections after |
| | poll() returns then free process slots. */ |
| | for (i = MAX_PROCS - 1; i >= 0; i--) |
| | if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) |
| | break; |
| | |
| | if (listener->tcpfd != -1 && i >= 0 && poll_check(listener->tcpfd, POLLIN)) |
| { |
{ |
| int confd, client_ok = 1; |
int confd, client_ok = 1; |
| struct irec *iface = NULL; |
struct irec *iface = NULL; |
|
Line 1863 static void check_dns_listeners(time_t now)
|
Line 1944 static void check_dns_listeners(time_t now)
|
| close(pipefd[0]); |
close(pipefd[0]); |
| else |
else |
| { |
{ |
| int i; |
|
| #ifdef HAVE_LINUX_NETWORK |
#ifdef HAVE_LINUX_NETWORK |
| /* The child process inherits the netlink socket, |
/* The child process inherits the netlink socket, |
| which it never uses, but when the parent (us) |
which it never uses, but when the parent (us) |
|
Line 1883 static void check_dns_listeners(time_t now)
|
Line 1963 static void check_dns_listeners(time_t now)
|
| read_write(pipefd[0], &a, 1, 1); |
read_write(pipefd[0], &a, 1, 1); |
| #endif |
#endif |
| |
|
| for (i = 0; i < MAX_PROCS; i++) | /* i holds index of free slot */ |
| if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1) | daemon->tcp_pids[i] = p; |
| { | daemon->tcp_pipes[i] = pipefd[0]; |
| daemon->tcp_pids[i] = p; | |
| daemon->tcp_pipes[i] = pipefd[0]; | |
| break; | |
| } | |
| } |
} |
| close(confd); |
close(confd); |
| |
|
|
Line 1939 static void check_dns_listeners(time_t now)
|
Line 2015 static void check_dns_listeners(time_t now)
|
| attribute from the listening socket. |
attribute from the listening socket. |
| Reset that here. */ |
Reset that here. */ |
| if ((flags = fcntl(confd, F_GETFL, 0)) != -1) |
if ((flags = fcntl(confd, F_GETFL, 0)) != -1) |
| fcntl(confd, F_SETFL, flags & ~O_NONBLOCK); | while(retry_send(fcntl(confd, F_SETFL, flags & ~O_NONBLOCK))); |
| |
|
| buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns); |
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns); |
| |
|
| shutdown(confd, SHUT_RDWR); |
|
| close(confd); |
|
| |
|
| if (buff) |
if (buff) |
| free(buff); |
free(buff); |
| |
|
|
Line 2068 int delay_dhcp(time_t start, int sec, int fd, uint32_t
|
Line 2141 int delay_dhcp(time_t start, int sec, int fd, uint32_t
|
| poll_reset(); |
poll_reset(); |
| if (fd != -1) |
if (fd != -1) |
| poll_listen(fd, POLLIN); |
poll_listen(fd, POLLIN); |
| set_dns_listeners(now); | set_dns_listeners(); |
| set_log_writer(); |
set_log_writer(); |
| |
|
| #ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |