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 |