summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ypserv
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1996-12-25 18:10:35 +0000
committerwpaul <wpaul@FreeBSD.org>1996-12-25 18:10:35 +0000
commit9595ea6d1eb97fa3074c2f7c8e7b86d793ca6f8b (patch)
tree6077b7732802a3647746e612ca585a0ce843b915 /usr.sbin/ypserv
parent59eadfda914b1a76f8105d01e61675cc806a5646 (diff)
downloadFreeBSD-src-9595ea6d1eb97fa3074c2f7c8e7b86d793ca6f8b.zip
FreeBSD-src-9595ea6d1eb97fa3074c2f7c8e7b86d793ca6f8b.tar.gz
More async resolver refinements:
- yp_main.c: Always add the resolver socket to the set of fds monitored by select(). It can happen that pending == 0 but we still have some data in the socket buffer from an old query. This way, the data will be flushed in a timely manner. - yp_extern.h: remove proto for yp_dns_pending() since we don't need it anynmore. - yp_server.c: call yp_async_lookup_name()/yp_async_lookup_addr() functions with the svc_req pointer as an arg instead of the xprt. (The svc_req struct includes a pointer to the transport handle, and it also has the service version number which the async DNS code will need. (see below)) - yp_dnslookup.c: o Nuke yp_dns_pending() since we don't need it anymore. o In yp_run_dnsq(), swallow up and ignore replies if no requests are pending or the ID doesn't match any of the IDs in the queue. o In yp_send_dns_reply(), we assume that we will always be replying to an NIS v2 client. While this will probably always be the case, we do support the v1 'match' procedure, and it has a different result struct than v2. For completeness, support replying to both NIS v1 and v2 clients. o Update the queue entry structure to include a member to keep track of the NIS version number. o Have yp_async_lookup_name/addr() extract the version number from the svc_req structure and save it with the queue entry for yp_send_dns_reply() to inspect later. o Add some comments.
Diffstat (limited to 'usr.sbin/ypserv')
-rw-r--r--usr.sbin/ypserv/yp_dnslookup.c149
-rw-r--r--usr.sbin/ypserv/yp_extern.h7
-rw-r--r--usr.sbin/ypserv/yp_main.c7
-rw-r--r--usr.sbin/ypserv/yp_server.c6
4 files changed, 115 insertions, 54 deletions
diff --git a/usr.sbin/ypserv/yp_dnslookup.c b/usr.sbin/ypserv/yp_dnslookup.c
index 7e350a2..91eebc3 100644
--- a/usr.sbin/ypserv/yp_dnslookup.c
+++ b/usr.sbin/ypserv/yp_dnslookup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995
+ * Copyright (c) 1995, 1996
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -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.4 1996/12/22 22:30:54 wpaul Exp $
+ * $Id: yp_dnslookup.c,v 1.9 1996/12/25 17:52:35 wpaul Exp $
*/
/*
@@ -65,7 +65,7 @@
#include "yp_extern.h"
#ifndef lint
-static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.4 1996/12/22 22:30:54 wpaul Exp $";
+static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.9 1996/12/25 17:52:35 wpaul Exp $";
#endif
static char *parse(hp)
@@ -106,9 +106,9 @@ struct circleq_dnsentry {
SVCXPRT *xprt;
unsigned long xid;
struct sockaddr_in client_addr;
+ unsigned long ypvers;
unsigned long id;
unsigned long ttl;
- unsigned long sent;
unsigned long type;
unsigned short prot_type;
char **domain;
@@ -137,11 +137,6 @@ int yp_init_resolver()
return(0);
}
-int yp_dnsq_pending()
-{
- return(pending);
-}
-
static struct circleq_dnsentry *yp_malloc_dnsent()
{
register struct circleq_dnsentry *q;
@@ -202,7 +197,7 @@ static struct circleq_dnsentry *yp_find_dnsqent(id)
register struct circleq_dnsentry *q;
for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) {
- if (q->id == id)
+ if (id == q->id)
return(q);
}
return (NULL);
@@ -212,25 +207,60 @@ static void yp_send_dns_reply(q, buf)
struct circleq_dnsentry *q;
char *buf;
{
- ypresp_val result;
+ ypresponse result_v1;
+ ypresp_val result_v2;
unsigned long xid;
struct sockaddr_in client_addr;
+ xdrproc_t xdrfunc;
+ char *result;
- bzero((char *)&result, sizeof(result));
-
- if (buf == NULL)
- result.stat = YP_NOKEY;
- else {
- result.val.valdat_len = strlen(buf);
- result.val.valdat_val = buf;
- result.stat = YP_TRUE;
+ /*
+ * Set up correct reply struct and
+ * XDR filter depending on ypvers.
+ */
+ switch(q->ypvers) {
+ case YPVERS:
+ bzero((char *)&result_v2, sizeof(result_v2));
+
+ if (buf == NULL)
+ result_v2.stat = YP_NOKEY;
+ else {
+ result_v2.val.valdat_len = strlen(buf);
+ result_v2.val.valdat_val = buf;
+ result_v2.stat = YP_TRUE;
+ }
+ result = (char *)&result_v2;
+ xdrfunc = (xdrproc_t)xdr_ypresp_val;
+ break;
+ case YPOLDVERS:
+ /*
+ * The odds are we will _never_ execute this
+ * particular code, but we include it anyway
+ * for the sake of completeness.
+ */
+ bzero((char *)&result_v1, sizeof(result_v1));
+ result_v1.yp_resptype = YPRESP_VAL;
+# define YPVAL ypresponse_u.yp_resp_valtype
+
+ if (buf == NULL)
+ result_v1.YPVAL.stat = YP_NOKEY;
+ else {
+ result_v1.YPVAL.val.valdat_len = strlen(buf);
+ result_v1.YPVAL.val.valdat_val = buf;
+ result_v1.YPVAL.stat = YP_TRUE;
+ }
+ result = (char *)&result_v1;
+ xdrfunc = (xdrproc_t)xdr_ypresponse;
+ break;
+ default:
+ yp_error("Bad YP program version (%lu)!",q->ypvers);
+ return;
+ break;
}
if (debug)
yp_error("Sending dns reply to %s (%lu)",
- inet_ntoa(q->client_addr.sin_addr),
- q->id);
-
+ inet_ntoa(q->client_addr.sin_addr), q->id);
/*
* XXX This is disgusting. There's basically one transport
* handle for UDP, but we're holding off on replying to a
@@ -245,20 +275,31 @@ static void yp_send_dns_reply(q, buf)
* not even supported by the RPC library.
*/
/*
- * XXX Don't from the transaction ID for TCP handles.
+ * XXX Don't frob 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))
+
+ if (!svc_sendreply(q->xprt, xdrfunc, result))
yp_error("svc_sendreply failed");
+
+ /*
+ * Now that we sent the reply,
+ * put the handle back the way it was.
+ */
if (q->prot_type == SOCK_DGRAM)
svcudp_set_xid(q->xprt, xid);
q->xprt->xp_raddr = client_addr;
+
return;
}
+/*
+ * Decrement TTL on all queue entries, possibly nuking
+ * any that have been around too long without being serviced.
+ */
void yp_prune_dnsq()
{
register struct circleq_dnsentry *q;
@@ -279,10 +320,15 @@ void yp_prune_dnsq()
return;
}
+/*
+ * Data is pending on the DNS socket; check for valid replies
+ * to our queries and dispatch them to waiting clients.
+ */
void yp_run_dnsq()
{
register struct circleq_dnsentry *q;
char buf[sizeof(HEADER) + MAXPACKET];
+ char retrybuf[MAXHOSTNAMELEN];
struct sockaddr_in sin;
int rval;
int len;
@@ -303,9 +349,16 @@ void yp_run_dnsq()
return;
}
+ /*
+ * We may have data left in the socket that represents
+ * replies to earlier queries that we don't care about
+ * anymore. If there are no lookups pending or the packet
+ * ID doesn't match any of the queue IDs, just drop it
+ * on the floor.
+ */
hptr = (HEADER *)&buf;
- if ((q = yp_find_dnsqent(ntohs(hptr->id))) == NULL) {
- /* bogus id -- ignore */
+ if (!pending || (q = yp_find_dnsqent(ntohs(hptr->id))) == NULL) {
+ /* ignore */
return;
}
@@ -314,9 +367,12 @@ void yp_run_dnsq()
hent = __dns_getanswer(buf, rval, q->name, q->type);
+ /*
+ * If the lookup failed, try appending one of the domains
+ * from resolv.conf. If we have no domains to test, the
+ * query has failed.
+ */
if (hent == NULL) {
- char retrybuf[MAXHOSTNAMELEN];
-
if (h_errno == TRY_AGAIN && q->domain && *q->domain) {
snprintf(retrybuf, sizeof(retrybuf), "%s.%s",
q->name, *q->domain);
@@ -334,20 +390,24 @@ void yp_run_dnsq()
}
}
+ /* Got an answer ready for a client -- send it off. */
yp_send_dns_reply(q, parse(hent));
-
pending--;
CIRCLEQ_REMOVE(&qhead, q, links);
free(q->name);
free(q);
+ /* Decrement TTLs on other entries while we're here. */
yp_prune_dnsq();
return;
}
-ypstat yp_async_lookup_name(xprt, name)
- SVCXPRT *xprt;
+/*
+ * Queue and transmit an asynchronous DNS hostname lookup.
+ */
+ypstat yp_async_lookup_name(rqstp, name)
+ struct svc_req *rqstp;
char *name;
{
register struct circleq_dnsentry *q;
@@ -358,17 +418,17 @@ ypstat yp_async_lookup_name(xprt, name)
q->type = T_A;
q->ttl = DEF_TTL;
- q->sent = 1;
- q->xprt = xprt;
+ q->xprt = rqstp->rq_xprt;
+ q->ypvers = rqstp->rq_vers;
type = -1; len = sizeof(type);
- if (getsockopt(xprt->xp_sock,SOL_SOCKET,SO_TYPE,&type,&len) == -1) {
+ if (getsockopt(q->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->xid = svcudp_get_xid(q->xprt);
+ q->client_addr = q->xprt->xp_raddr;
if (!strchr(name, '.'))
q->domain = _res.dnsrch;
else
@@ -391,8 +451,11 @@ ypstat yp_async_lookup_name(xprt, name)
return(YP_TRUE);
}
-ypstat yp_async_lookup_addr(xprt, addr)
- SVCXPRT *xprt;
+/*
+ * Queue and transmit an asynchronous DNS IP address lookup.
+ */
+ypstat yp_async_lookup_addr(rqstp, addr)
+ struct svc_req *rqstp;
char *addr;
{
register struct circleq_dnsentry *q;
@@ -414,18 +477,18 @@ ypstat yp_async_lookup_addr(xprt, addr)
q->type = T_PTR;
q->ttl = DEF_TTL;
- q->sent = 1;
- q->xprt = xprt;
+ q->xprt = rqstp->rq_xprt;
+ q->ypvers = rqstp->rq_vers;
q->domain = NULL;
type = -1; len = sizeof(type);
- if (getsockopt(xprt->xp_sock,SOL_SOCKET,SO_TYPE,&type,&len) == -1) {
+ if (getsockopt(q->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->xid = svcudp_get_xid(q->xprt);
+ q->client_addr = q->xprt->xp_raddr;
q->id = yp_send_dns_query(buf, q->type);
if (q->id == 0) {
diff --git a/usr.sbin/ypserv/yp_extern.h b/usr.sbin/ypserv/yp_extern.h
index fc3e6dd..0fb7ab2 100644
--- a/usr.sbin/ypserv/yp_extern.h
+++ b/usr.sbin/ypserv/yp_extern.h
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: yp_extern.h,v 1.3 1996/12/22 15:53:55 wpaul Exp $
+ * $Id: yp_extern.h,v 1.4 1996/12/24 07:52:52 wpaul Exp $
*/
#include <stdio.h>
#include <string.h>
@@ -106,8 +106,7 @@ extern unsigned long svcudp_get_xid __P(( SVCXPRT * ));
#endif
extern int yp_init_resolver __P(( void ));
-extern int yp_dnsq_pending __P(( void ));
extern void yp_run_dnsq __P(( void ));
extern void yp_prune_dnsq __P(( void ));
-extern ypstat yp_async_lookup_name __P(( SVCXPRT *, char * ));
-extern ypstat yp_async_lookup_addr __P(( SVCXPRT *, char * ));
+extern ypstat yp_async_lookup_name __P(( struct svc_req *, char * ));
+extern ypstat yp_async_lookup_addr __P(( struct svc_req *, char * ));
diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c
index db40ac6..b172180 100644
--- a/usr.sbin/ypserv/yp_main.c
+++ b/usr.sbin/ypserv/yp_main.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: yp_main.c,v 1.4 1996/12/22 15:54:03 wpaul Exp $
+ * $Id: yp_main.c,v 1.5 1996/12/24 07:52:52 wpaul Exp $
*/
/*
@@ -66,7 +66,7 @@
#define _RPCSVC_CLOSEDOWN 120
#ifndef lint
-static const char rcsid[] = "$Id: yp_main.c,v 1.4 1996/12/22 15:54:03 wpaul Exp $";
+static const char rcsid[] = "$Id: yp_main.c,v 1.5 1996/12/24 07:52:52 wpaul Exp $";
#endif /* not lint */
int _rpcpmstart; /* Started by a port monitor ? */
static int _rpcfdtype;
@@ -122,8 +122,7 @@ yp_svc_run()
readfds = svc_fds;
#endif /* def FD_SETSIZE */
- if (yp_dnsq_pending())
- FD_SET(resfd, &readfds);
+ FD_SET(resfd, &readfds);
switch (select(fd_setsize, &readfds, NULL, NULL,
&timeout)) {
diff --git a/usr.sbin/ypserv/yp_server.c b/usr.sbin/ypserv/yp_server.c
index 32a8a2c..da1a73b 100644
--- a/usr.sbin/ypserv/yp_server.c
+++ b/usr.sbin/ypserv/yp_server.c
@@ -45,7 +45,7 @@
#include <rpc/rpc.h>
#ifndef lint
-static const char rcsid[] = "$Id: yp_server.c,v 1.2 1996/12/22 06:57:55 wpaul Exp $";
+static const char rcsid[] = "$Id: yp_server.c,v 1.3 1996/12/24 18:43:53 wpaul Exp $";
#endif /* not lint */
int forked = 0;
@@ -169,10 +169,10 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
argp->key.keydat_val);
if (!strcmp(argp->map, "hosts.byname"))
- result.stat = yp_async_lookup_name(rqstp->rq_xprt,
+ result.stat = yp_async_lookup_name(rqstp,
(char *)argp->key.keydat_val);
else if (!strcmp(argp->map, "hosts.byaddr"))
- result.stat = yp_async_lookup_addr(rqstp->rq_xprt,
+ result.stat = yp_async_lookup_addr(rqstp,
(char *)argp->key.keydat_val);
if (result.stat == YP_TRUE)
OpenPOWER on IntegriCloud