diff options
author | wpaul <wpaul@FreeBSD.org> | 1996-12-24 02:44:52 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1996-12-24 02:44:52 +0000 |
commit | d99939c736aca9e71967d283a2ca32bb8ba0c564 (patch) | |
tree | e2cd5added12483e83950c4fdd1088c6a9f1d241 /usr.sbin | |
parent | 4ab0d63c8aed49b7d37e4c8f3557febdad48a701 (diff) | |
download | FreeBSD-src-d99939c736aca9e71967d283a2ca32bb8ba0c564.zip FreeBSD-src-d99939c736aca9e71967d283a2ca32bb8ba0c564.tar.gz |
Fix some bugs:
- Don't dereference a NULL hostent pointer (if T_PTR lookup fails).
- Today I asked myself: "Self, you wrote this nifty async resolver
that does a great job handling delayed replies to clients using
the UDP transport, and the yplib code in libc always uses UDP
(except for yp_all()). But what if some dork makes a DNS lookup using
TCP?" Being the only dork on hand at the time, I tried it and was
enlightened. As I suspected, my transaction ID frobbing hacks cause
fireworks if called on a TCP transport handle (duh: the structures
are different). Fix: check the type of socket in xprt->xp_sock using
getsockopt() and don't use svcudp_get_xid() and svcudp_set_xid() for
anything except SOCK_DGRAM sockets. (Since accept() gives you a
new socket for each connection, the transaction ID munging isn't
needed for TCP anyway.)
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ypserv/yp_dnslookup.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/usr.sbin/ypserv/yp_dnslookup.c b/usr.sbin/ypserv/yp_dnslookup.c index 7b0acbb..7e350a2 100644 --- a/usr.sbin/ypserv/yp_dnslookup.c +++ b/usr.sbin/ypserv/yp_dnslookup.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: yp_dnslookup.c,v 1.5 1996/12/22 15:45:33 wpaul Exp $ + * $Id: yp_dnslookup.c,v 1.4 1996/12/22 22:30:54 wpaul Exp $ */ /* @@ -65,7 +65,7 @@ #include "yp_extern.h" #ifndef lint -static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.5 1996/12/22 15:45:33 wpaul Exp $"; +static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.4 1996/12/22 22:30:54 wpaul Exp $"; #endif static char *parse(hp) @@ -110,6 +110,7 @@ struct circleq_dnsentry { unsigned long ttl; unsigned long sent; unsigned long type; + unsigned short prot_type; char **domain; char *name; struct in_addr addr; @@ -243,12 +244,17 @@ static void yp_send_dns_reply(q, buf) * way we found 'em. This is _INCREDIBLY_ non-portable; it's * not even supported by the RPC library. */ - xid = svcudp_set_xid(q->xprt, q->xid); + /* + * XXX Don't from the transaction ID for TCP handles. + */ + if (q->prot_type == SOCK_DGRAM) + xid = svcudp_set_xid(q->xprt, q->xid); client_addr = q->xprt->xp_raddr; q->xprt->xp_raddr = q->client_addr; if (!svc_sendreply(q->xprt, xdr_ypresp_val, (char *)&result)) yp_error("svc_sendreply failed"); - svcudp_set_xid(q->xprt, xid); + if (q->prot_type == SOCK_DGRAM) + svcudp_set_xid(q->xprt, xid); q->xprt->xp_raddr = client_addr; return; } @@ -311,7 +317,7 @@ void yp_run_dnsq() if (hent == NULL) { char retrybuf[MAXHOSTNAMELEN]; - if (q->domain && *q->domain) { + if (h_errno == TRY_AGAIN && q->domain && *q->domain) { snprintf(retrybuf, sizeof(retrybuf), "%s.%s", q->name, *q->domain); if (debug) @@ -321,12 +327,13 @@ void yp_run_dnsq() q->domain++; return; } + } else { + if (q->type == T_PTR) { + hent->h_addr = (char *)&q->addr.s_addr; + hent->h_length = sizeof(struct in_addr); + } } - if (q->type == T_PTR) { - hent->h_addr = (char *)&q->addr.s_addr; - hent->h_length = sizeof(struct in_addr); - } yp_send_dns_reply(q, parse(hent)); pending--; @@ -344,6 +351,7 @@ ypstat yp_async_lookup_name(xprt, name) char *name; { register struct circleq_dnsentry *q; + int type, len; if ((q = yp_malloc_dnsent()) == NULL) return(YP_YPERR); @@ -352,7 +360,14 @@ ypstat yp_async_lookup_name(xprt, name) q->ttl = DEF_TTL; q->sent = 1; q->xprt = xprt; - q->xid = svcudp_get_xid(xprt); + type = -1; len = sizeof(type); + if (getsockopt(xprt->xp_sock,SOL_SOCKET,SO_TYPE,&type,&len) == -1) { + yp_error("getsockopt failed: %s", strerror(errno)); + return(YP_YPERR); + } + q->prot_type = type; + if (q->prot_type == SOCK_DGRAM) + q->xid = svcudp_get_xid(xprt); q->client_addr = xprt->xp_raddr; if (!strchr(name, '.')) q->domain = _res.dnsrch; @@ -383,6 +398,7 @@ ypstat yp_async_lookup_addr(xprt, addr) register struct circleq_dnsentry *q; char buf[MAXHOSTNAMELEN]; int a, b, c, d; + int type, len; if ((q = yp_malloc_dnsent()) == NULL) return(YP_YPERR); @@ -401,7 +417,14 @@ ypstat yp_async_lookup_addr(xprt, addr) q->sent = 1; q->xprt = xprt; q->domain = NULL; - q->xid = svcudp_get_xid(xprt); + type = -1; len = sizeof(type); + if (getsockopt(xprt->xp_sock,SOL_SOCKET,SO_TYPE,&type,&len) == -1) { + yp_error("getsockopt failed: %s", strerror(errno)); + return(YP_YPERR); + } + q->prot_type = type; + if (q->prot_type == SOCK_DGRAM) + q->xid = svcudp_get_xid(xprt); q->client_addr = xprt->xp_raddr; q->id = yp_send_dns_query(buf, q->type); |