Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/resolv - make all filedescriptors close-on-exec
details: https://anonhg.NetBSD.org/src/rev/cc145f031fd9
branches: trunk
changeset: 784956:cc145f031fd9
user: christos <christos%NetBSD.org@localhost>
date: Fri Feb 15 14:08:25 2013 +0000
description:
- make all filedescriptors close-on-exec
- use SOCK_NOSIGPIPE.
- add kqueue handling (not enabled by default, from FreeBSD)
- add RES_INSECURE1 handling (from FreeBSD)
diffstat:
lib/libc/resolv/res_send.c | 138 ++++++++++++++++++++++++++++++++++++--------
1 files changed, 111 insertions(+), 27 deletions(-)
diffs (truncated from 349 to 300 lines):
diff -r f38943f81475 -r cc145f031fd9 lib/libc/resolv/res_send.c
--- a/lib/libc/resolv/res_send.c Fri Feb 15 09:25:03 2013 +0000
+++ b/lib/libc/resolv/res_send.c Fri Feb 15 14:08:25 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: res_send.c,v 1.25 2012/03/21 00:34:54 christos Exp $ */
+/* $NetBSD: res_send.c,v 1.26 2013/02/15 14:08:25 christos Exp $ */
/*
* Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
@@ -93,7 +93,7 @@
static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp";
#else
-__RCSID("$NetBSD: res_send.c,v 1.25 2012/03/21 00:34:54 christos Exp $");
+__RCSID("$NetBSD: res_send.c,v 1.26 2013/02/15 14:08:25 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -104,13 +104,18 @@
#include "namespace.h"
#include "port_before.h"
+#ifndef USE_KQUEUE
#include "fd_setsize.h"
+#endif /* USE_KQUEUE */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#ifdef USE_KQUEUE
+#include <sys/event.h>
+#endif /* USE_KQUEUE */
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -122,6 +127,7 @@
#include <resolv.h>
#include <signal.h>
#include <stdio.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -139,6 +145,12 @@
#endif
#endif
+#ifndef SOCK_NOSIGPIPE
+#define SOCK_NOSIGPIPE 0
+#endif
+#ifndef SOCK_NOCLOEXEC
+#define SOCK_NOCLOEXEC 0
+#endif
#ifdef USE_POLL
#ifdef HAVE_STROPTS_H
@@ -156,7 +168,7 @@
#define EXT(res) ((res)->_u._ext)
-#ifndef USE_POLL
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
static const int highestFD = FD_SETSIZE - 1;
#endif
@@ -166,14 +178,18 @@
static struct sockaddr * get_nsaddr(res_state, size_t);
static int send_vc(res_state, const u_char *, int,
u_char *, int, int *, int);
-static int send_dg(res_state, const u_char *, int,
+static int send_dg(res_state,
+#ifdef USE_KQUEUE
+ int,
+#endif
+ const u_char *, int,
u_char *, int, int *, int, int,
int *, int *);
static void Aerror(const res_state, FILE *, const char *, int,
const struct sockaddr *, int);
static void Perror(const res_state, FILE *, const char *, int);
static int sock_eq(struct sockaddr *, struct sockaddr *);
-#if defined(NEED_PSELECT) && !defined(USE_POLL)
+#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
static int pselect(int, void *, void *, void *,
struct timespec *,
const sigset_t *);
@@ -330,6 +346,9 @@
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
+#ifdef USE_KQUEUE
+ int kq;
+#endif
char abuf[NI_MAXHOST];
(void)res_check(statp, NULL);
@@ -349,6 +368,12 @@
gotsomewhere = 0;
terrno = ETIMEDOUT;
+#ifdef USE_KQUEUE
+ if ((kq = kqueue1(O_CLOEXEC)) == -1) {
+ return (-1);
+ }
+#endif
+
/*
* If the ns_addr_list in the resolver context has changed, then
* invalidate our cached copy and the associated timing data.
@@ -464,6 +489,9 @@
res_nclose(statp);
goto next_ns;
case res_done:
+#ifdef USE_KQUEUE
+ close(kq);
+#endif
return (resplen);
case res_modified:
/* give the hook another try */
@@ -497,8 +525,12 @@
resplen = n;
} else {
/* Use datagrams. */
- n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
- ns, tries, &v_circuit, &gotsomewhere);
+ n = send_dg(statp,
+#ifdef USE_KQUEUE
+ kq,
+#endif
+ buf, buflen, ans, anssiz, &terrno,
+ ns, tries, &v_circuit, &gotsomewhere);
if (n < 0)
goto fail;
if (n == 0)
@@ -556,11 +588,17 @@
} while (!done);
}
+#ifdef USE_KQUEUE
+ close(kq);
+#endif
return (resplen);
next_ns: ;
} /*foreach ns*/
} /*foreach retry*/
res_nclose(statp);
+#ifdef USE_KQUEUE
+ close(kq);
+#endif
if (!v_circuit) {
if (!gotsomewhere)
errno = ECONNREFUSED; /*%< no nameservers found */
@@ -571,6 +609,9 @@
return (-1);
fail:
res_nclose(statp);
+#ifdef USE_KQUEUE
+ close(kq);
+#endif
return (-1);
}
@@ -633,7 +674,7 @@
u_short len;
u_char *cp;
void *tmp;
-#ifdef SO_NOSIGPIPE
+#if defined(SO_NOSIGPIPE) && SOCK_NOSIGPIPE == 0
int on = 1;
#endif
@@ -661,8 +702,12 @@
if (statp->_vcsock >= 0)
res_nclose(statp);
- statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
-#ifndef USE_POLL
+ statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM
+ | SOCK_NOSIGPIPE | SOCK_CLOEXEC, 0);
+#if SOCK_CLOEXEC == 0
+ fcntl(statp->_vcsock, F_SETFD, FD_CLOEXEC);
+#endif
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
if (statp->_vcsock > highestFD) {
res_nclose(statp);
errno = ENOTSOCK;
@@ -683,7 +728,7 @@
return (-1);
}
}
-#ifdef SO_NOSIGPIPE
+#if defined(SO_NOSIGPIPE) && SOCK_NOSIGPIPE == 0
/*
* Disable generation of SIGPIPE when writing to a closed
* socket. Write should return -1 and set errno to EPIPE
@@ -692,7 +737,7 @@
* Push on even if setsockopt(SO_NOSIGPIPE) fails.
*/
(void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
- (unsigned int)sizeof(on));
+ (socklen_t)sizeof(on));
#endif
errno = 0;
if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
@@ -820,7 +865,11 @@
}
static int
-send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
+send_dg(res_state statp,
+#ifdef USE_KQUEUE
+ int kq,
+#endif
+ const u_char *buf, int buflen, u_char *ans,
int anssiz, int *terrno, int ns, int tries, int *v_circuit,
int *gotsomewhere)
{
@@ -833,18 +882,26 @@
ISC_SOCKLEN_T fromlen;
ssize_t resplen;
int seconds, n, s;
+#ifdef USE_KQUEUE
+ struct kevent kv;
+#else
#ifdef USE_POLL
int polltimeout;
struct pollfd pollfd;
#else
fd_set dsmask;
#endif
+#endif
nsap = get_nsaddr(statp, (size_t)ns);
nsaplen = get_salen(nsap);
if (EXT(statp).nssocks[ns] == -1) {
- EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
-#ifndef USE_POLL
+ EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM
+ | SOCK_CLOEXEC, 0);
+#if SOCK_CLOEXEC == 0
+ fcntl(EXT(statp)nssocks[ns], F_SETFD, FD_CLOEXEC);
+#endif
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
if (EXT(statp).nssocks[ns] > highestFD) {
res_nclose(statp);
errno = ENOTSOCK;
@@ -876,8 +933,16 @@
* socket operation, and select returns if the
* error message is received. We can thus detect
* the absence of a nameserver without timing out.
- */
- if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
+ *
+ * When the option "insecure1" is specified, we'd
+ * rather expect to see responses from an "unknown"
+ * address. In order to let the kernel accept such
+ * responses, do not connect the socket here.
+ * XXX: or do we need an explicit option to disable
+ * connecting?
+ */
+ if (!(statp->options & RES_INSECURE1) &&
+ connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
Aerror(statp, stderr, "connect(dg)", errno, nsap,
nsaplen);
res_nclose(statp);
@@ -889,13 +954,20 @@
}
s = EXT(statp).nssocks[ns];
#ifndef CANNOT_CONNECT_DGRAM
- if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
+ if (statp->options & RES_INSECURE1) {
+ if (sendto(s,
+ (const char*)buf, buflen, 0, nsap, (socklen_t)nsaplen) != buflen) {
+ Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+ } else if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
Perror(statp, stderr, "send", errno);
res_nclose(statp);
return (0);
}
#else /* !CANNOT_CONNECT_DGRAM */
- if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
+ if (sendto(s, (const char*)buf, buflen, 0, nsap, (socklen_t)nsaplen) != buflen)
{
Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
res_nclose(statp);
@@ -919,13 +991,18 @@
now = evNowTime();
nonow:
#ifndef USE_POLL
- FD_ZERO(&dsmask);
- FD_SET(s, &dsmask);
if (evCmpTime(finish, now) > 0)
timeout = evSubTime(finish, now);
else
timeout = evConsTime(0L, 0L);
Home |
Main Index |
Thread Index |
Old Index