mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq
This commit is contained in:
@@ -2254,6 +2254,10 @@ example command to query this, using the
|
||||
utility would be
|
||||
|
||||
dig +short chaos txt cachesize.bind
|
||||
.TP
|
||||
.B --max-tcp-connections=<number>
|
||||
The maximum number of concurrent TCP connections. The application forks to
|
||||
handle each TCP request. The default maximum is 20.
|
||||
|
||||
.SH CONFIG FILE
|
||||
At startup, dnsmasq reads
|
||||
|
||||
28
src/cache.c
28
src/cache.c
@@ -124,6 +124,7 @@ static const struct {
|
||||
{ 258, "AVC" }, /* Application Visibility and Control [Wolfgang_Riedel] AVC/avc-completed-template 2016-02-26*/
|
||||
{ 259, "DOA" }, /* Digital Object Architecture [draft-durand-doa-over-dns] DOA/doa-completed-template 2017-08-30*/
|
||||
{ 260, "AMTRELAY" }, /* Automatic Multicast Tunneling Relay [RFC8777] AMTRELAY/amtrelay-completed-template 2019-02-06*/
|
||||
{ 261, "RESINFO" }, /* Resolver Information as Key/Value Pairs https://datatracker.ietf.org/doc/draft-ietf-add-resolver-info/06/ */
|
||||
{ 32768, "TA" }, /* DNSSEC Trust Authorities [Sam_Weiler][http://cameo.library.cmu.edu/][ Deploying DNSSEC Without a Signed Root. Technical Report 1999-19, Information Networking Institute, Carnegie Mellon University, April 2004.] 2005-12-13*/
|
||||
{ 32769, "DLV" }, /* DNSSEC Lookaside Validation (OBSOLETE) [RFC8749][RFC4431] */
|
||||
};
|
||||
@@ -424,18 +425,21 @@ unsigned int cache_remove_uid(const unsigned int uid)
|
||||
{
|
||||
int i;
|
||||
unsigned int removed = 0;
|
||||
struct crec *crecp, **up;
|
||||
struct crec *crecp, *tmp, **up;
|
||||
|
||||
for (i = 0; i < hash_size; i++)
|
||||
for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = crecp->hash_next)
|
||||
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && crecp->uid == uid)
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
free(crecp);
|
||||
removed++;
|
||||
}
|
||||
else
|
||||
up = &crecp->hash_next;
|
||||
for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = tmp)
|
||||
{
|
||||
tmp = crecp->hash_next;
|
||||
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && crecp->uid == uid)
|
||||
{
|
||||
*up = tmp;
|
||||
free(crecp);
|
||||
removed++;
|
||||
}
|
||||
else
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
@@ -629,8 +633,8 @@ static struct crec *really_insert(char *name, union all_addr *addr, unsigned sho
|
||||
if (insert_error)
|
||||
return NULL;
|
||||
|
||||
/* we don't cache zero-TTL records. */
|
||||
if (ttl == 0)
|
||||
/* we don't cache zero-TTL records unless we're doing stale-caching. */
|
||||
if (daemon->cache_max_expiry == 0 && ttl == 0)
|
||||
{
|
||||
insert_error = 1;
|
||||
return NULL;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
#define MAX_PROCS 20 /* default max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
|
||||
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
|
||||
|
||||
35
src/dhcp6.c
35
src/dhcp6.c
@@ -92,7 +92,7 @@ void dhcp6_packet(time_t now)
|
||||
struct iface_param parm;
|
||||
struct cmsghdr *cmptr;
|
||||
struct msghdr msg;
|
||||
int if_index = 0;
|
||||
uint32_t if_index = 0;
|
||||
union {
|
||||
struct cmsghdr align; /* this ensures alignment */
|
||||
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
@@ -118,11 +118,6 @@ void dhcp6_packet(time_t now)
|
||||
if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
|
||||
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
@@ -138,6 +133,34 @@ void dhcp6_packet(time_t now)
|
||||
|
||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* This works around a possible Linux kernel bug when using interfaces
|
||||
enslaved to a VRF. The scope_id in the source address gets set
|
||||
to the index of the VRF interface, not the slave. Fortunately,
|
||||
the interface index returned by packetinfo is correct so we use
|
||||
that instead. Log this once, so if it triggers in other circumstances
|
||||
we've not anticipated and breaks things, we get some clues. */
|
||||
if (from.sin6_scope_id != if_index)
|
||||
{
|
||||
static int logged = 0;
|
||||
|
||||
if (!logged)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("Working around kernel bug: faulty source address scope for VRF slave %s"),
|
||||
ifr.ifr_name);
|
||||
logged = 1;
|
||||
}
|
||||
|
||||
from.sin6_scope_id = if_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
|
||||
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
if (relay_reply6(&from, sz, ifr.ifr_name))
|
||||
{
|
||||
|
||||
@@ -30,12 +30,14 @@ static volatile pid_t pid = 0;
|
||||
static volatile int pipewrite;
|
||||
|
||||
static void set_dns_listeners(void);
|
||||
static void set_tftp_listeners(void);
|
||||
static void check_dns_listeners(time_t now);
|
||||
static void sig_handler(int sig);
|
||||
static void async_event(int pipe, time_t now);
|
||||
static void fatal_event(struct event_desc *ev, char *msg);
|
||||
static int read_event(int fd, struct event_desc *evp, char **msg);
|
||||
static void poll_resolv(int force, int do_reload, time_t now);
|
||||
static void tcp_init(void);
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
@@ -415,6 +417,8 @@ int main (int argc, char **argv)
|
||||
daemon->numrrand = max_fd/3;
|
||||
/* safe_malloc returns zero'd memory */
|
||||
daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd));
|
||||
|
||||
tcp_init();
|
||||
}
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
@@ -1043,8 +1047,10 @@ int main (int argc, char **argv)
|
||||
pid = getpid();
|
||||
|
||||
daemon->pipe_to_parent = -1;
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
daemon->tcp_pipes[i] = -1;
|
||||
|
||||
if (daemon->port != 0)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
daemon->tcp_pipes[i] = -1;
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
/* Using inotify, have to select a resolv file at startup */
|
||||
@@ -1067,7 +1073,12 @@ int main (int argc, char **argv)
|
||||
(timeout == -1 || timeout > 1000))
|
||||
timeout = 1000;
|
||||
|
||||
set_dns_listeners();
|
||||
if (daemon->port != 0)
|
||||
set_dns_listeners();
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
set_tftp_listeners();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
if (option_bool(OPT_DBUS))
|
||||
@@ -1252,8 +1263,9 @@ int main (int argc, char **argv)
|
||||
check_ubus_listeners();
|
||||
}
|
||||
#endif
|
||||
|
||||
check_dns_listeners(now);
|
||||
|
||||
if (daemon->port != 0)
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
check_tftp_listeners(now);
|
||||
@@ -1519,8 +1531,8 @@ static void async_event(int pipe, time_t now)
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
}
|
||||
else
|
||||
for (i = 0 ; i < MAX_PROCS; i++)
|
||||
else if (daemon->port != 0)
|
||||
for (i = 0 ; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pids[i] == p)
|
||||
daemon->tcp_pids[i] = 0;
|
||||
break;
|
||||
@@ -1584,9 +1596,10 @@ static void async_event(int pipe, time_t now)
|
||||
|
||||
case EVENT_TERM:
|
||||
/* Knock all our children on the head. */
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
if (daemon->port != 0)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
|
||||
#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
|
||||
/* handle pending lease transitions */
|
||||
@@ -1731,23 +1744,33 @@ void clear_cache_and_reload(time_t now)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_dns_listeners(void)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
struct randfd_list *rfl;
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
static void set_tftp_listeners(void)
|
||||
{
|
||||
int tftp = 0;
|
||||
struct tftp_transfer *transfer;
|
||||
struct listener *listener;
|
||||
|
||||
if (!option_bool(OPT_SINGLE_PORT))
|
||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||
{
|
||||
tftp++;
|
||||
poll_listen(transfer->sockfd, POLLIN);
|
||||
}
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
/* tftp == 0 in single-port mode. */
|
||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||
poll_listen(listener->tftpfd, POLLIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_dns_listeners(void)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
struct randfd_list *rfl;
|
||||
int i;
|
||||
|
||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||
poll_listen(serverfdp->fd, POLLIN);
|
||||
@@ -1761,7 +1784,7 @@ static void set_dns_listeners(void)
|
||||
poll_listen(rfl->rfd->fd, POLLIN);
|
||||
|
||||
/* check to see if we have free tcp process slots. */
|
||||
for (i = MAX_PROCS - 1; i >= 0; i--)
|
||||
for (i = daemon->max_procs - 1; i >= 0; i--)
|
||||
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
|
||||
break;
|
||||
|
||||
@@ -1776,16 +1799,10 @@ static void set_dns_listeners(void)
|
||||
we'll be called again when a slot becomes available. */
|
||||
if (listener->tcpfd != -1 && i >= 0)
|
||||
poll_listen(listener->tcpfd, POLLIN);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
/* tftp == 0 in single-port mode. */
|
||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||
poll_listen(listener->tftpfd, POLLIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pipes[i] != -1)
|
||||
poll_listen(daemon->tcp_pipes[i], POLLIN);
|
||||
}
|
||||
@@ -1820,7 +1837,7 @@ static void check_dns_listeners(time_t now)
|
||||
to free the process slot. Once the child process has gone, poll()
|
||||
returns POLLHUP, not POLLIN, so have to check for both here. */
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pipes[i] != -1 &&
|
||||
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
|
||||
!cache_recv_insert(now, daemon->tcp_pipes[i]))
|
||||
@@ -1834,17 +1851,12 @@ static void check_dns_listeners(time_t now)
|
||||
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
||||
receive_query(listener, now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
|
||||
tftp_request(listener, now);
|
||||
#endif
|
||||
|
||||
/* 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--)
|
||||
for (i = daemon->max_procs - 1; i >= 0; i--)
|
||||
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
|
||||
break;
|
||||
|
||||
@@ -2135,7 +2147,11 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
||||
poll_reset();
|
||||
if (fd != -1)
|
||||
poll_listen(fd, POLLIN);
|
||||
set_dns_listeners();
|
||||
if (daemon->port != 0)
|
||||
set_dns_listeners();
|
||||
#ifdef HAVE_TFTP
|
||||
set_tftp_listeners();
|
||||
#endif
|
||||
set_log_writer();
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
@@ -2153,7 +2169,8 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
||||
now = dnsmasq_time();
|
||||
|
||||
check_log_writer(0);
|
||||
check_dns_listeners(now);
|
||||
if (daemon->port != 0)
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
|
||||
@@ -2186,3 +2203,9 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_DHCP */
|
||||
|
||||
void tcp_init(void)
|
||||
{
|
||||
daemon->tcp_pids = safe_malloc(daemon->max_procs*sizeof(pid_t));
|
||||
daemon->tcp_pipes = safe_malloc(daemon->max_procs*sizeof(int));
|
||||
}
|
||||
|
||||
@@ -1252,8 +1252,8 @@ extern struct daemon {
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
int fd_save; /* " " */
|
||||
pid_t tcp_pids[MAX_PROCS];
|
||||
int tcp_pipes[MAX_PROCS];
|
||||
pid_t *tcp_pids;
|
||||
int *tcp_pipes;
|
||||
int pipe_to_parent;
|
||||
int numrrand;
|
||||
struct randfd *randomsocks;
|
||||
@@ -1313,6 +1313,7 @@ extern struct daemon {
|
||||
/* file for packet dumps. */
|
||||
int dumpfd;
|
||||
#endif
|
||||
int max_procs;
|
||||
} *daemon;
|
||||
|
||||
struct server_details {
|
||||
|
||||
16
src/option.c
16
src/option.c
@@ -190,6 +190,7 @@ struct myoption {
|
||||
#define LOPT_FILTER_RR 381
|
||||
#define LOPT_NO_DHCP6 382
|
||||
#define LOPT_NO_DHCP4 383
|
||||
#define LOPT_MAX_PROCS 384
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -384,6 +385,7 @@ static const struct myoption opts[] =
|
||||
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
|
||||
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
|
||||
{ "no-ident", 0, 0, LOPT_NO_IDENT },
|
||||
{ "max-tcp-connections", 1, 0, LOPT_MAX_PROCS },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -585,6 +587,7 @@ static struct {
|
||||
{ LOPT_NORR, OPT_NORR, NULL, gettext_noop("Suppress round-robin ordering of DNS records."), NULL },
|
||||
{ LOPT_NO_IDENT, OPT_NO_IDENT, NULL, gettext_noop("Do not add CHAOS TXT records."), NULL },
|
||||
{ LOPT_CACHE_RR, ARG_DUP, "<RR-type>", gettext_noop("Cache this DNS resource record type."), NULL },
|
||||
{ LOPT_MAX_PROCS, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent tcp connections."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -5313,7 +5316,17 @@ err:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
case LOPT_MAX_PROCS: /* --max-tcp-connections */
|
||||
{
|
||||
int max_procs;
|
||||
/* Don't accept numbers less than 1. */
|
||||
if (!atoi_check(arg, &max_procs) || max_procs < 1)
|
||||
ret_err(gen_err);
|
||||
daemon->max_procs = max_procs;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
|
||||
|
||||
@@ -5841,6 +5854,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
daemon->soa_expiry = SOA_EXPIRY;
|
||||
daemon->randport_limit = 1;
|
||||
daemon->host_index = SRC_AH;
|
||||
daemon->max_procs = MAX_PROCS;
|
||||
|
||||
/* See comment above make_servers(). Optimises server-read code. */
|
||||
mark_servers(0);
|
||||
|
||||
@@ -847,11 +847,18 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
int len;
|
||||
|
||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||
return 2;
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 2;
|
||||
}
|
||||
|
||||
len = to_wire(name);
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, name, len))
|
||||
return 0;
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr.rrblock.datalen += len;
|
||||
}
|
||||
else
|
||||
@@ -859,8 +866,13 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
/* desc is length of a block of data to be used as-is */
|
||||
if (desc > endrr - p1)
|
||||
desc = endrr - p1;
|
||||
|
||||
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p1, desc))
|
||||
return 0;
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr.rrblock.datalen += desc;
|
||||
p1 += desc;
|
||||
}
|
||||
@@ -868,7 +880,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
|
||||
/* we overwrote the original name, so get it back here. */
|
||||
if (!extract_name(header, qlen, &tmp, name, 1, 0))
|
||||
return 2;
|
||||
{
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (flags & (F_IPV4 | F_IPV6))
|
||||
@@ -914,6 +929,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
cpp = NULL;
|
||||
|
||||
/* cache insert failed, don't leak blockdata. */
|
||||
if (!newc && (flags & F_RR) && (flags & F_KEYTAG))
|
||||
blockdata_free(addr.rrblock.rrdata);
|
||||
}
|
||||
|
||||
if (aqtype == T_TXT)
|
||||
|
||||
@@ -1074,7 +1074,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
||||
|
||||
case DHCP6CONFIRM:
|
||||
{
|
||||
int good_addr = 0;
|
||||
int good_addr = 0, bad_addr = 0;
|
||||
|
||||
/* set reply message type */
|
||||
outmsgtype = DHCP6REPLY;
|
||||
@@ -1096,26 +1096,24 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
||||
|
||||
if (!address6_valid(state->context, &req_addr, tagif, 1))
|
||||
{
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6NOTONLINK);
|
||||
put_opt6_string(_("confirm failed"));
|
||||
end_opt6(o1);
|
||||
bad_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
good_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
|
||||
else
|
||||
{
|
||||
good_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No addresses, no reply: RFC 3315 18.2.2 */
|
||||
if (!good_addr)
|
||||
if (!good_addr && !bad_addr)
|
||||
return 0;
|
||||
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6SUCCESS );
|
||||
put_opt6_string(_("all addresses still on link"));
|
||||
put_opt6_short(bad_addr ? DHCP6NOTONLINK : DHCP6SUCCESS);
|
||||
put_opt6_string(bad_addr ? (_("confirm failed")) : (_("all addresses still on link")));
|
||||
end_opt6(o1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -585,8 +585,13 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, char *c
|
||||
|
||||
void check_tftp_listeners(time_t now)
|
||||
{
|
||||
struct listener *listener;
|
||||
struct tftp_transfer *transfer, *tmp, **up;
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
|
||||
tftp_request(listener, now);
|
||||
|
||||
/* In single port mode, all packets come via port 69 and tftp_request() */
|
||||
if (!option_bool(OPT_SINGLE_PORT))
|
||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||
|
||||
Reference in New Issue
Block a user