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