summaryrefslogtreecommitdiff
path: root/usr/src/lib/libresolv2/common/resolv/res_send.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libresolv2/common/resolv/res_send.c')
-rw-r--r--usr/src/lib/libresolv2/common/resolv/res_send.c255
1 files changed, 142 insertions, 113 deletions
diff --git a/usr/src/lib/libresolv2/common/resolv/res_send.c b/usr/src/lib/libresolv2/common/resolv/res_send.c
index 5891e01e62..8e629a3d96 100644
--- a/usr/src/lib/libresolv2/common/resolv/res_send.c
+++ b/usr/src/lib/libresolv2/common/resolv/res_send.c
@@ -1,12 +1,30 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+
+/*
+ * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1996-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
/*
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -22,7 +40,7 @@
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -38,14 +56,14 @@
/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
+ *
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
@@ -56,31 +74,13 @@
* SOFTWARE.
*/
-/*
- * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Exp $";
+static const char rcsid[] = "$Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp $";
#endif /* LIBC_SCCS and not lint */
-/*
+/*! \file
+ * \brief
* Send query to name server and wait for reply.
*/
@@ -110,14 +110,12 @@ static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Ex
#include "port_after.h"
-#ifdef SUNW_POLL
+#ifdef USE_POLL
+#ifdef HAVE_STROPTS_H
#include <stropts.h>
-#include <poll.h>
-#if defined(pselect)
-#undef pselect
#endif
-#define pselect Pselect
-#endif /* SUNW_POLL */
+#include <poll.h>
+#endif /* USE_POLL */
/* Options. Leave them on. */
#define DEBUG
@@ -126,7 +124,7 @@ static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Ex
#define EXT(res) ((res)->_u._ext)
-#ifdef ORIGINAL_ISC_CODE
+#ifndef USE_POLL
static const int highestFD = FD_SETSIZE - 1;
#else
static int highestFD = 0;
@@ -139,21 +137,20 @@ static struct sockaddr * get_nsaddr __P((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,
- u_char *, int, int *, 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 *);
-#ifdef NEED_PSELECT
+#if defined(NEED_PSELECT) && !defined(USE_POLL)
static int pselect(int, void *, void *, void *,
struct timespec *,
const sigset_t *);
#endif
void res_pquery(const res_state, const u_char *, int, FILE *);
-#ifdef ORIGINAL_ISC_CODE
-#else
+#ifndef ORIGINAL_ISC_CODE
#pragma weak __res_nameinquery = res_nameinquery
#pragma weak __res_queriesmatch = res_queriesmatch
#pragma weak res_nisourserver = res_ourserver_p
@@ -163,14 +160,15 @@ static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
/* Public. */
-/* int
- * res_isourserver(ina)
+/*%
* looks up "ina" in _res.ns_addr_list[]
+ *
* returns:
- * 0 : not found
- * >0 : found
+ *\li 0 : not found
+ *\li >0 : found
+ *
* author:
- * paul vixie, 29may94
+ *\li paul vixie, 29may94
*/
int
res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
@@ -199,8 +197,8 @@ res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
if (srv6->sin6_family == in6p->sin6_family &&
srv6->sin6_port == in6p->sin6_port &&
#ifdef HAVE_SIN6_SCOPE_ID
- (srv6->sin6_scope_id == 0 ||
- srv6->sin6_scope_id == in6p->sin6_scope_id) &&
+ (srv6->sin6_scope_id == 0 ||
+ srv6->sin6_scope_id == in6p->sin6_scope_id) &&
#endif
(IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
@@ -213,17 +211,19 @@ res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
return (0);
}
-/* int
- * res_nameinquery(name, type, class, buf, eom)
+/*%
* look for (name,type,class) in the query section of packet (buf,eom)
+ *
* requires:
- * buf + HFIXEDSZ <= eom
+ *\li buf + HFIXEDSZ <= eom
+ *
* returns:
- * -1 : format error
- * 0 : not found
- * >0 : found
+ *\li -1 : format error
+ *\li 0 : not found
+ *\li >0 : found
+ *
* author:
- * paul vixie, 29may94
+ *\li paul vixie, 29may94
*/
int
res_nameinquery(const char *name, int type, int class,
@@ -251,16 +251,17 @@ res_nameinquery(const char *name, int type, int class,
return (0);
}
-/* int
- * res_queriesmatch(buf1, eom1, buf2, eom2)
+/*%
* is there a 1:1 mapping of (name,type,class)
* in (buf1,eom1) and (buf2,eom2)?
+ *
* returns:
- * -1 : format error
- * 0 : not a 1:1 mapping
- * >0 : is a 1:1 mapping
+ *\li -1 : format error
+ *\li 0 : not a 1:1 mapping
+ *\li >0 : is a 1:1 mapping
+ *
* author:
- * paul vixie, 29may94
+ *\li paul vixie, 29may94
*/
int
res_queriesmatch(const u_char *buf1, const u_char *eom1,
@@ -304,14 +305,14 @@ int
res_nsend(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
- int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+ int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
char abuf[NI_MAXHOST];
-#ifdef SUNW_POLL
+#ifdef USE_POLL
highestFD = sysconf(_SC_OPEN_MAX) - 1;
#endif
- /* No name servers or previous res_ninit() failure */
+ /* No name servers or res_init() failure */
if (statp->nscount == 0 || EXT(statp).ext == NULL) {
errno = ESRCH;
return (-1);
@@ -349,7 +350,7 @@ res_nsend(res_state statp,
if (EXT(statp).nssocks[ns] == -1)
continue;
peerlen = sizeof(peer);
- if (getsockname(EXT(statp).nssocks[ns],
+ if (getpeername(EXT(statp).nssocks[ns],
(struct sockaddr *)&peer, &peerlen) < 0) {
needclose++;
break;
@@ -385,8 +386,8 @@ res_nsend(res_state statp,
* Some resolvers want to even out the load on their nameservers.
* Note that RES_BLAST overrides RES_ROTATE.
*/
- if ((statp->options & RES_ROTATE) != 0 &&
- (statp->options & RES_BLAST) == 0) {
+ if ((statp->options & RES_ROTATE) != 0U &&
+ (statp->options & RES_BLAST) == 0U) {
union res_sockaddr_union inu;
struct sockaddr_in ina;
int lastns = statp->nscount - 1;
@@ -400,7 +401,7 @@ res_nsend(res_state statp,
nstime = EXT(statp).nstimes[0];
for (ns = 0; ns < lastns; ns++) {
if (EXT(statp).ext != NULL)
- EXT(statp).ext->nsaddrs[ns] =
+ EXT(statp).ext->nsaddrs[ns] =
EXT(statp).ext->nsaddrs[ns + 1];
statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
@@ -416,7 +417,7 @@ res_nsend(res_state statp,
/*
* Send request, RETRY times, or until successful.
*/
- for (try = 0; try < statp->retry; try++) {
+ for (tries = 0; tries < statp->retry; tries++) {
for (ns = 0; ns < statp->nscount; ns++) {
struct sockaddr *nsap;
int nsaplen;
@@ -464,7 +465,7 @@ res_nsend(res_state statp,
if (v_circuit) {
/* Use VC; at most one attempt per server. */
- try = statp->retry;
+ tries = statp->retry;
n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
ns);
if (n < 0)
@@ -475,7 +476,7 @@ res_nsend(res_state statp,
} else {
/* Use datagrams. */
n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
- ns, &v_circuit, &gotsomewhere);
+ ns, tries, &v_circuit, &gotsomewhere);
if (n < 0)
goto fail;
if (n == 0)
@@ -500,8 +501,8 @@ res_nsend(res_state statp,
* or if we haven't been asked to keep a socket open,
* close the socket.
*/
- if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
- (statp->options & RES_STAYOPEN) == 0) {
+ if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
+ (statp->options & RES_STAYOPEN) == 0U) {
res_nclose(statp);
}
if (statp->rhook) {
@@ -540,9 +541,9 @@ res_nsend(res_state statp,
res_nclose(statp);
if (!v_circuit) {
if (!gotsomewhere)
- errno = ECONNREFUSED; /* no nameservers found */
+ errno = ECONNREFUSED; /*%< no nameservers found */
else
- errno = ETIMEDOUT; /* no answer obtained */
+ errno = ETIMEDOUT; /*%< no answer obtained */
} else
errno = terrno;
return (-1);
@@ -569,10 +570,10 @@ get_salen(sa)
else if (sa->sa_family == AF_INET6)
return (sizeof(struct sockaddr_in6));
else
- return (0); /* unknown, die on connect */
+ return (0); /*%< unknown, die on connect */
}
-/*
+/*%
* pick appropriate nsaddr_list for use. see res_init() for initialization.
*/
static struct sockaddr *
@@ -612,6 +613,9 @@ send_vc(res_state statp,
u_short len;
u_char *cp;
void *tmp;
+#ifdef SO_NOSIGPIPE
+ int on = 1;
+#endif
nsap = get_nsaddr(statp, ns);
nsaplen = get_salen(nsap);
@@ -643,10 +647,31 @@ send_vc(res_state statp,
errno = ENOTSOCK;
}
if (statp->_vcsock < 0) {
- *terrno = errno;
- Perror(statp, stderr, "socket(vc)", errno);
- return (-1);
+ switch (errno) {
+ case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+#endif
+ case EAFNOSUPPORT:
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (0);
+ default:
+ *terrno = errno;
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (-1);
+ }
}
+#ifdef SO_NOSIGPIPE
+ /*
+ * Disable generation of SIGPIPE when writing to a closed
+ * socket. Write should return -1 and set errno to EPIPE
+ * instead.
+ *
+ * Push on even if setsockopt(SO_NOSIGPIPE) fails.
+ */
+ (void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
+ sizeof(on));
+#endif
errno = 0;
if (connect(statp->_vcsock, nsap, nsaplen) < 0) {
*terrno = errno;
@@ -679,7 +704,7 @@ send_vc(res_state statp,
len = INT16SZ;
while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
cp += n;
- if ((len -= n) <= 0)
+ if ((len -= n) == 0)
break;
}
if (n <= 0) {
@@ -739,14 +764,6 @@ send_vc(res_state statp,
*/
anhp->tc = 1;
len = resplen - anssiz;
- /*
- * Reset the value of resplen to anssiz,
- * this is done because the caller assumes
- * resplen contains the size of message read
- * into the "ans" buffer passed in.
- */
- resplen = anssiz;
-
while (len != 0) {
char junk[PACKETSZ];
@@ -781,22 +798,23 @@ send_vc(res_state statp,
}
static int
-send_dg(res_state statp,
- const u_char *buf, int buflen, u_char *ans, int anssiz,
- int *terrno, int ns, int *v_circuit, int *gotsomewhere)
+send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
+ int anssiz, int *terrno, int ns, int tries, int *v_circuit,
+ int *gotsomewhere)
{
const HEADER *hp = (const HEADER *) buf;
HEADER *anhp = (HEADER *) ans;
const struct sockaddr *nsap;
int nsaplen;
struct timespec now, timeout, finish;
- fd_set dsmask;
struct sockaddr_storage from;
ISC_SOCKLEN_T fromlen;
int resplen, seconds, n, s;
-#ifdef SUNW_POLL
- int polltimeout;
+#ifdef USE_POLL
+ int polltimeout;
struct pollfd pollfd;
+#else
+ fd_set dsmask;
#endif
nsap = get_nsaddr(statp, ns);
@@ -808,9 +826,19 @@ send_dg(res_state statp,
errno = ENOTSOCK;
}
if (EXT(statp).nssocks[ns] < 0) {
- *terrno = errno;
- Perror(statp, stderr, "socket(dg)", errno);
- return (-1);
+ switch (errno) {
+ case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+#endif
+ case EAFNOSUPPORT:
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (0);
+ default:
+ *terrno = errno;
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (-1);
+ }
}
#ifndef CANNOT_CONNECT_DGRAM
/*
@@ -853,7 +881,7 @@ send_dg(res_state statp,
/*
* Wait for reply.
*/
- seconds = (statp->retrans << ns);
+ seconds = (statp->retrans << tries);
if (ns > 0)
seconds /= statp->nscount;
if (seconds <= 0)
@@ -865,7 +893,15 @@ send_dg(res_state statp,
wait:
now = evNowTime();
nonow:
-#ifdef SUNW_POLL
+#ifndef USE_POLL
+ FD_ZERO(&dsmask);
+ FD_SET(s, &dsmask);
+ if (evCmpTime(finish, now) > 0)
+ timeout = evSubTime(finish, now);
+ else
+ timeout = evConsTime(0, 0);
+ n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+#else
timeout = evSubTime(finish, now);
if (timeout.tv_sec < 0)
timeout = evConsTime(0, 0);
@@ -874,15 +910,8 @@ send_dg(res_state statp,
pollfd.fd = s;
pollfd.events = POLLRDNORM;
n = poll(&pollfd, 1, polltimeout);
-#else
- FD_ZERO(&dsmask);
- FD_SET(s, &dsmask);
- if (evCmpTime(finish, now) > 0)
- timeout = evSubTime(finish, now);
- else
- timeout = evConsTime(0, 0);
- n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
-#endif
+#endif /* USE_POLL */
+
if (n == 0) {
Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
*gotsomewhere = 1;
@@ -891,11 +920,11 @@ send_dg(res_state statp,
if (n < 0) {
if (errno == EINTR)
goto wait;
-#ifdef SUNW_POLL
- Perror(statp, stderr, "poll", errno);
-#else
+#ifndef USE_POLL
Perror(statp, stderr, "select", errno);
-#endif
+#else
+ Perror(statp, stderr, "poll", errno);
+#endif /* USE_POLL */
res_nclose(statp);
return (0);
}
@@ -946,7 +975,7 @@ send_dg(res_state statp,
goto wait;
}
#ifdef RES_USE_EDNS0
- if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) {
+ if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
/*
* Do not retry if the server do not understand EDNS0.
* The case has to be captured here, as FORMERR packet do not
@@ -1014,7 +1043,7 @@ Aerror(const res_state statp, FILE *file, const char *string, int error,
alen = alen;
- if ((statp->options & RES_DEBUG) != 0) {
+ if ((statp->options & RES_DEBUG) != 0U) {
if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
sbuf, sizeof(sbuf), niflags)) {
strncpy(hbuf, "?", sizeof(hbuf) - 1);
@@ -1032,7 +1061,7 @@ static void
Perror(const res_state statp, FILE *file, const char *string, int error) {
int save = errno;
- if ((statp->options & RES_DEBUG) != 0)
+ if ((statp->options & RES_DEBUG) != 0U)
fprintf(file, "res_send: %s: %s\n",
string, strerror(error));
errno = save;
@@ -1064,7 +1093,7 @@ sock_eq(struct sockaddr *a, struct sockaddr *b) {
}
}
-#ifdef NEED_PSELECT
+#if defined(NEED_PSELECT) && !defined(USE_POLL)
/* XXX needs to move to the porting library. */
static int
pselect(int nfds, void *rfds, void *wfds, void *efds,