mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f74b74e521 | ||
|
|
c9342cb556 | ||
|
|
2b844b8c83 | ||
|
|
65e9a8957c | ||
|
|
da868a2fbe | ||
|
|
bceb5287b9 | ||
|
|
84445dec26 | ||
|
|
c70b92b2a4 | ||
|
|
57e582492b | ||
|
|
ec8f3e65c1 | ||
|
|
15841f187d | ||
|
|
ade97495e6 | ||
|
|
2b19285724 | ||
|
|
a444715bf0 | ||
|
|
14e81b6976 | ||
|
|
6ce7f2d55a |
No files matched your search
+1
-1
@@ -673,7 +673,7 @@ machine on which dnsmasq is running) for each
|
||||
local machine. Local machines are those in /etc/hosts or with DHCP
|
||||
leases.
|
||||
.TP
|
||||
.B \-W, --srv-host=<_service>.<_prot>.[<domain>],[<target>[,<port>[,<priority>[,<weight>]]]]
|
||||
.B \-W, --srv-host=<_service>.<_prot>[.<domain>],[<target>[,<port>[,<priority>[,<weight>]]]]
|
||||
Return a SRV DNS record. See RFC2782 for details. If not supplied, the
|
||||
domain defaults to that given by
|
||||
.B --domain.
|
||||
|
||||
+4
-2
@@ -2360,6 +2360,8 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
||||
source = "reply";
|
||||
else if (flags & F_AUTH)
|
||||
source = "auth";
|
||||
else if (flags & F_QUERY)
|
||||
source = "query";
|
||||
else if (flags & F_SECSTAT)
|
||||
{
|
||||
if (addr && addr->log.ede != EDE_UNSET && option_bool(OPT_EXTRALOG))
|
||||
@@ -2400,8 +2402,8 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
||||
source = "non-query opcode";
|
||||
name = opcodestring;
|
||||
}
|
||||
else if (!(flags & F_AUTH))
|
||||
source = "query";
|
||||
else if (type > 0)
|
||||
source = querystr(source, type);
|
||||
|
||||
verb = "from";
|
||||
}
|
||||
|
||||
+11
-1
@@ -290,6 +290,7 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_BSD_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#define NO_IPSET
|
||||
/* Define before sys/socket.h is included so we get socklen_t */
|
||||
#define _BSD_SOCKLEN_T_
|
||||
/* Select the RFC_3542 version of the IPv6 socket API.
|
||||
@@ -349,7 +350,6 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LINUX_NETWORK)
|
||||
#undef HAVE_IPSET
|
||||
#undef HAVE_NFTSET
|
||||
#endif
|
||||
|
||||
@@ -357,6 +357,16 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#undef HAVE_IPSET
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_IPSET)
|
||||
# if defined(HAVE_LINUX_NETWORK)
|
||||
# define HAVE_LINUX_IPSET
|
||||
# elif defined(HAVE_BSD_NETWORK)
|
||||
# define HAVE_BSD_IPSET
|
||||
# else
|
||||
# undef HAVE_IPSET
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NO_LOOP
|
||||
#undef HAVE_LOOP
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -1777,9 +1777,9 @@ void clear_cache_and_reload(time_t now)
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
{
|
||||
reread_dhcp();
|
||||
if (option_bool(OPT_ETHERS))
|
||||
dhcp_read_ethers();
|
||||
reread_dhcp();
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
lease_update_from_configs();
|
||||
lease_update_file(now);
|
||||
|
||||
+1
-1
@@ -1938,7 +1938,7 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
char *name, char *limit, int first, int last, int ede);
|
||||
int server_samegroup(struct server *a, struct server *b);
|
||||
#ifdef HAVE_DNSSEC
|
||||
int dnssec_server(struct server *server, char *keyname, int *firstp, int *lastp);
|
||||
int dnssec_server(struct server *server, char *keyname, int is_ds, int *firstp, int *lastp);
|
||||
#endif
|
||||
void mark_servers(int flag);
|
||||
void cleanup_servers(void);
|
||||
|
||||
+24
-8
@@ -95,6 +95,7 @@ void build_server_array(void)
|
||||
|
||||
A flag of F_SERVER returns an upstream server only.
|
||||
A flag of F_DNSSECOK disables NODOTS servers from consideration.
|
||||
A flag of F_DS returns parent domain server.
|
||||
A flag of F_DOMAINSRV returns a domain-specific server only.
|
||||
A flag of F_CONFIG returns anything that generates a local
|
||||
reply of IPv4 or IPV6.
|
||||
@@ -106,12 +107,23 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
||||
ssize_t qlen;
|
||||
int try, high, low = 0;
|
||||
int nlow = 0, nhigh = 0;
|
||||
char *cp, *qdomain = domain;
|
||||
|
||||
char *cp, *qdomain;
|
||||
|
||||
/* may be no configured servers. */
|
||||
if (daemon->serverarraysz == 0)
|
||||
return 0;
|
||||
|
||||
/* DS records should come from the parent domain. */
|
||||
if (flags & F_DS)
|
||||
{
|
||||
if ((cp = strchr(domain, '.')))
|
||||
domain = cp+1;
|
||||
else
|
||||
domain = "";
|
||||
}
|
||||
|
||||
qdomain = domain;
|
||||
|
||||
/* find query length and presence of '.' */
|
||||
for (cp = qdomain, nodots = 1, qlen = 0; *cp; qlen++, cp++)
|
||||
if (*cp == '.')
|
||||
@@ -244,7 +256,10 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
||||
if (nodots &&
|
||||
(daemon->serverarray[daemon->serverarraysz-1]->flags & SERV_FOR_NODOTS) &&
|
||||
(nlow == nhigh || daemon->serverarray[nlow]->domain_len == 0))
|
||||
filter_servers(daemon->serverarraysz-1, flags, &nlow, &nhigh);
|
||||
{
|
||||
filter_servers(daemon->serverarraysz-1, flags, &nlow, &nhigh);
|
||||
qlen = 0;
|
||||
}
|
||||
|
||||
if (lowout)
|
||||
*lowout = nlow;
|
||||
@@ -343,7 +358,8 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
else
|
||||
{
|
||||
/* If we want a server for a particular domain, and this one isn't, return nothing. */
|
||||
if (nlow != nhigh && (flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0)
|
||||
if (nlow < daemon->serverarraysz && nlow != nhigh && (flags & F_DOMAINSRV) &&
|
||||
daemon->serverarray[nlow]->domain_len == 0 && !(daemon->serverarray[nlow]->flags & SERV_FOR_NODOTS))
|
||||
nlow = nhigh;
|
||||
}
|
||||
}
|
||||
@@ -399,7 +415,7 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
|
||||
setup_reply(header, flags, ede);
|
||||
|
||||
gotname &= ~F_QUERY;
|
||||
gotname &= ~(F_QUERY | F_DS);
|
||||
|
||||
if (flags & (F_NXDOMAIN | F_NOERR))
|
||||
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL, 0);
|
||||
@@ -459,14 +475,14 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
int dnssec_server(struct server *server, char *keyname, int *firstp, int *lastp)
|
||||
int dnssec_server(struct server *server, char *keyname, int is_ds, int *firstp, int *lastp)
|
||||
{
|
||||
int first, last, index;
|
||||
|
||||
|
||||
/* Find server to send DNSSEC query to. This will normally be the
|
||||
same as for the original query, but may be another if
|
||||
servers for domains are involved. */
|
||||
if (!lookup_domain(keyname, F_SERVER | F_DNSSECOK, &first, &last))
|
||||
if (!lookup_domain(keyname, F_SERVER | F_DNSSECOK | (is_ds ? F_DS : 0), &first, &last))
|
||||
return -1;
|
||||
|
||||
for (index = first; index != last; index++)
|
||||
|
||||
+13
-13
@@ -763,6 +763,16 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
|
||||
header->hb4 &= ~HB4_AD;
|
||||
|
||||
/* Complain loudly if the upstream server is non-recursive. */
|
||||
if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
|
||||
server && !(server->flags & SERV_WARNED_RECURSIVE))
|
||||
{
|
||||
(void)prettyprint_addr(&server->addr, daemon->namebuff);
|
||||
my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
|
||||
if (!option_bool(OPT_LOG))
|
||||
server->flags |= SERV_WARNED_RECURSIVE;
|
||||
}
|
||||
|
||||
header->hb4 |= HB4_RA; /* recursion if available */
|
||||
|
||||
if (OPCODE(header) != QUERY)
|
||||
@@ -778,16 +788,6 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
return resize_packet(header, n, pheader, plen);
|
||||
}
|
||||
|
||||
/* Complain loudly if the upstream server is non-recursive. */
|
||||
if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
|
||||
server && !(server->flags & SERV_WARNED_RECURSIVE))
|
||||
{
|
||||
(void)prettyprint_addr(&server->addr, daemon->namebuff);
|
||||
my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
|
||||
if (!option_bool(OPT_LOG))
|
||||
server->flags |= SERV_WARNED_RECURSIVE;
|
||||
}
|
||||
|
||||
if (header->hb3 & HB3_TC)
|
||||
log_query(F_UPSTREAM, NULL, NULL, "truncated", 0);
|
||||
else if (!bogusanswer || (header->hb4 & HB4_CD))
|
||||
@@ -1024,7 +1024,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
||||
|
||||
/* Make sure we don't expire and free the orig frec during the
|
||||
allocation of a new one: third arg of get_new_frec() does that. */
|
||||
if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 &&
|
||||
if ((serverind = dnssec_server(forward->sentto, daemon->keyname, STAT_ISEQUAL(status, STAT_NEED_DS), NULL, NULL)) != -1 &&
|
||||
(server = daemon->serverarray[serverind]) &&
|
||||
(nn = dnssec_generate_query(header, ((unsigned char *) header) + daemon->edns_pktsz,
|
||||
daemon->keyname, forward->class, get_id(),
|
||||
@@ -2199,7 +2199,7 @@ int tcp_from_udp(time_t now, int status, struct dns_header *header, ssize_t *ple
|
||||
first = start = server->arrayposn;
|
||||
last = first + 1;
|
||||
|
||||
if (!STAT_ISEQUAL(status, STAT_OK) && (start = dnssec_server(server, name, &first, &last)) == -1)
|
||||
if (!STAT_ISEQUAL(status, STAT_OK) && (start = dnssec_server(server, name, STAT_ISEQUAL(status, STAT_NEED_DS), &first, &last)) == -1)
|
||||
new_status = STAT_ABANDONED;
|
||||
else
|
||||
{
|
||||
@@ -2307,7 +2307,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class, 0,
|
||||
STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? T_DNSKEY : T_DS);
|
||||
|
||||
if ((start = dnssec_server(server, keyname, &first, &last)) == -1)
|
||||
if ((start = dnssec_server(server, keyname, STAT_ISEQUAL(new_status, STAT_NEED_DS), &first, &last)) == -1)
|
||||
{
|
||||
new_status = STAT_ABANDONED;
|
||||
break;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#if defined(HAVE_IPSET)
|
||||
#if defined(HAVE_LINUX_IPSET)
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
+9
-3
@@ -2917,13 +2917,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
break;
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
# endif
|
||||
case LOPT_LEASEQUERY:
|
||||
set_option_bool(OPT_LEASEQUERY);
|
||||
if (!arg)
|
||||
break;
|
||||
#pragma GCC diagnostic pop
|
||||
# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
#endif
|
||||
case 'B': /* --bogus-nxdomain */
|
||||
case LOPT_IGNORE_ADDR: /* --ignore-address */
|
||||
@@ -6258,6 +6262,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
strchr(srv->name, '.') &&
|
||||
strchr(srv->name, '.') == strrchr(srv->name, '.'))
|
||||
{
|
||||
if (strlen(srv->name) + 1 + strlen(daemon->domain_suffix) > MAXDNAME)
|
||||
die(_("srv-host name %s too long after domain appended"), srv->name, EC_MISC);
|
||||
strcpy(buff, srv->name);
|
||||
strcat(buff, ".");
|
||||
strcat(buff, daemon->domain_suffix);
|
||||
|
||||
+3
-4
@@ -415,6 +415,7 @@ int private_net(struct in_addr addr, int ban_localhost)
|
||||
(((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ ||
|
||||
(((ip_addr & 0xFF000000) == 0x00000000) && ban_localhost) /* RFC 5735 section 3. "here" network */ ||
|
||||
((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
|
||||
((ip_addr & 0xFFC00000) == 0x64400000) /* 100.64.0.0/10 (CG-NAT) RFC6598/RFC7793*/ ||
|
||||
((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
|
||||
((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
|
||||
((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ||
|
||||
@@ -1244,12 +1245,10 @@ unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
|
||||
return F_IPV4 | F_IPV6;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* Make the behaviour for DS and DNSKEY queries we forward the same
|
||||
as for DS and DNSKEY queries we originate. */
|
||||
if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DS || qtype == T_DNSKEY))
|
||||
return F_DNSSECOK;
|
||||
#endif
|
||||
if (qtype == T_DS || qtype == T_DNSKEY)
|
||||
return F_DNSSECOK | (qtype == T_DS ? F_DS : 0);
|
||||
|
||||
return F_QUERY;
|
||||
}
|
||||
|
||||
+50
-53
@@ -2276,64 +2276,61 @@ int relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface)
|
||||
{
|
||||
void *opt, *opts = inbuff + 34;
|
||||
void *end = inbuff + sz;
|
||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||
if (opt6_type(opt) == OPTION6_RELAY_MSG && opt6_len(opt) > 0)
|
||||
{
|
||||
int encap_type = *((unsigned char *)opt6_ptr(opt, 0));
|
||||
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||
memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ);
|
||||
peer->sin6_scope_id = relay->iface_index;
|
||||
|
||||
if (encap_type == DHCP6RELAYREPL)
|
||||
{
|
||||
peer->sin6_port = ntohs(DHCPV6_SERVER_PORT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
peer->sin6_port = ntohs(DHCPV6_CLIENT_PORT);
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command && encap_type == DHCP6REPLY)
|
||||
{
|
||||
/* decapsulate relayed message */
|
||||
opts = opt6_ptr(opt, 4);
|
||||
end = opt6_ptr(opt, opt6_len(opt));
|
||||
|
||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||
if (opt6_type(opt) == OPTION6_IA_PD && opt6_len(opt) > 12)
|
||||
{
|
||||
void *ia_opts = opt6_ptr(opt, 12);
|
||||
void *ia_end = opt6_ptr(opt, opt6_len(opt));
|
||||
void *ia_opt;
|
||||
|
||||
for (ia_opt = ia_opts; ia_opt; ia_opt = opt6_next(ia_opt, ia_end))
|
||||
/* valid lifetime must not be zero. */
|
||||
if (opt6_type(ia_opt) == OPTION6_IAPREFIX && opt6_len(ia_opt) >= 25 && opt6_uint(ia_opt, 4, 4) != 0)
|
||||
{
|
||||
if (daemon->free_snoops ||
|
||||
(daemon->free_snoops = whine_malloc(sizeof(struct snoop_record))))
|
||||
{
|
||||
struct snoop_record *snoop = daemon->free_snoops;
|
||||
|
||||
daemon->free_snoops = snoop->next;
|
||||
snoop->client = peer->sin6_addr;
|
||||
snoop->prefix_len = opt6_uint(ia_opt, 8, 1);
|
||||
memcpy(&snoop->prefix, opt6_ptr(ia_opt, 9), IN6ADDRSZ);
|
||||
snoop->next = relay->snoop_records;
|
||||
relay->snoop_records = snoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((opt = opt6_find(opts, end, OPTION6_RELAY_MSG, 4)))
|
||||
{
|
||||
int encap_type = opt6_uint(opt, 0, 1);
|
||||
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||
memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ);
|
||||
peer->sin6_scope_id = relay->iface_index;
|
||||
|
||||
if (encap_type == DHCP6RELAYREPL)
|
||||
{
|
||||
peer->sin6_port = ntohs(DHCPV6_SERVER_PORT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
peer->sin6_port = ntohs(DHCPV6_CLIENT_PORT);
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command && encap_type == DHCP6REPLY)
|
||||
{
|
||||
/* skip over message type and transaction-id. to get to options. */
|
||||
opts = opt6_ptr(opt, 4);
|
||||
end = opt6_ptr(opt, opt6_len(opt));
|
||||
|
||||
if ((opt = opt6_find(opts, end, OPTION6_IA_PD, 12)))
|
||||
{
|
||||
opts = opt6_ptr(opt, 12);
|
||||
end = opt6_ptr(opt, opt6_len(opt));
|
||||
|
||||
for (opt = opt6_find(opts, end, OPTION6_IAPREFIX, 25); opt; opt = opt6_find(opt6_next(opt, end), end, OPTION6_IAPREFIX, 25))
|
||||
/* valid lifetime must not be zero. */
|
||||
if (opt6_uint(opt, 4, 4) != 0)
|
||||
{
|
||||
if (daemon->free_snoops ||
|
||||
(daemon->free_snoops = whine_malloc(sizeof(struct snoop_record))))
|
||||
{
|
||||
struct snoop_record *snoop = daemon->free_snoops;
|
||||
|
||||
daemon->free_snoops = snoop->next;
|
||||
snoop->client = peer->sin6_addr;
|
||||
snoop->prefix_len = opt6_uint(opt, 8, 1);
|
||||
memcpy(&snoop->prefix, opt6_ptr(opt, 9), IN6ADDRSZ);
|
||||
snoop->next = relay->snoop_records;
|
||||
relay->snoop_records = snoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
int do_snoop_script_run(void)
|
||||
{
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
|
||||
#if defined(HAVE_BSD_IPSET)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
+33
-4
@@ -34,6 +34,10 @@
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BSD_NETWORK
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
/* SURF random number generator */
|
||||
|
||||
static u32 seed[32];
|
||||
@@ -831,9 +835,34 @@ void close_fds(long max_fd, int spare1, int spare2, int spare3)
|
||||
#endif
|
||||
|
||||
#ifdef FDESCFS
|
||||
DIR *d;
|
||||
DIR *d = NULL;
|
||||
|
||||
if ((d = opendir(FDESCFS)))
|
||||
# ifdef HAVE_BSD_NETWORK
|
||||
dev_t dirdev = 0;
|
||||
char fdescfs[] = FDESCFS; /* string must be writable */
|
||||
struct stat statbuf;
|
||||
|
||||
/* On BSD, fdescfs is normally mounted at /dev/fd. However
|
||||
if it is NOT mounted, devfs creates a directory at /dev/fd
|
||||
which contains (only) the file descriptors 0,1 and 2.
|
||||
|
||||
Under these conditions, opendir() will succeed, and
|
||||
if we proceed we will fail to close extant
|
||||
file descriptors which should be closed.
|
||||
|
||||
Check that there is a filesystem mounted at /dev/fd
|
||||
by checking that the device changes between /dev/fd
|
||||
and /dev. If if doesn't, fall back to the dumb path. */
|
||||
|
||||
if (stat(fdescfs, &statbuf) != -1)
|
||||
dirdev = statbuf.st_dev;
|
||||
|
||||
if (stat(dirname(fdescfs), &statbuf) != -1 &&
|
||||
dirdev != statbuf.st_dev)
|
||||
# endif
|
||||
d = opendir(FDESCFS);
|
||||
|
||||
if (d)
|
||||
{
|
||||
struct dirent *de;
|
||||
|
||||
@@ -855,9 +884,9 @@ void close_fds(long max_fd, int spare1, int spare2, int spare3)
|
||||
|
||||
closedir(d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* fallback, dumb code. */
|
||||
for (max_fd--; max_fd >= 0; max_fd--)
|
||||
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && max_fd != STDIN_FILENO &&
|
||||
|
||||
Reference in new issue
Block a user