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.
This commit is contained in:
parent
d13912467f
commit
adc4fa336b
@ -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));
|
||||
/*
|
||||
* 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.stat = YP_NOKEY;
|
||||
else {
|
||||
result.val.valdat_len = strlen(buf);
|
||||
result.val.valdat_val = buf;
|
||||
result.stat = YP_TRUE;
|
||||
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) {
|
||||
|
@ -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 * ));
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user