Big round o changes:

- yp_dblookup.c: Create non-DB specific database access functions.
  Using these allows access to the underlying database functions without
  needing explicit knowledge of Berkeley DB. (These are used only
  when DB_CACHE is #defined. Other programs that use the non-caching
  functions (yp_mkdb, ypxfr, yppush, rpc.yppasswdd) shouldn't notice
  the difference.)

- yp_dnslookup: Implement async DNS lookups. We send our own DNS
  requests using UDP and put the request in a queue. When the response
  arrives, we use the ID in the header to find the corresponsing queue
  entry and then send the response to the client. We can go about our
  business and handle other YP requests in the meantime. This way, we
  can deal with time consuming DNS requests without blocking and without
  forking.

- yp_server.c: Convert to using new non-DB-specific database access
  functions. This simplifies the code a bit and removes the need for
  this module to know anything about Berkeley DB. Also convert the
  ypproc_match_2_svc() function to use the async DNS lookup routines.

- yp_main.c: tweak yp_svc_run() to add the resolver socket to the
  set of descriptors monitored in the select() loop. Also add a
  timeout to select(); we may get stale DNS requests stuck in the
  queue which we want to invalidate after a while. If the timeout
  hits, we decrement the ttl on all pending DNS requests and nuke
  those requests that aren't handled before ttl hits zero.

- yp_extern.h: Add prototypes for new stuff.

- yp_svc_udp.c (new file): The async resolver code needs to be able
  to rummage around inside the RPC UDP transport handle in order to
  work correcty. There's basically one transport handle, and each time
  a request comes in, the transaction ID in the handle is changed.
  This means that if we queue a DNS request, then we handle some other
  unrelated requests, we will be unable to send the DNS response because
  the transaction ID and remote address of the client that made the DNS
  request will have been lost. What we need to do is save the client
  address and transaction ID in the queue entry for the DNS request,
  then put the transaction ID and address back in the transport handle
  when we're ready to reply. (And then we have to undo the change so
  as not to confuse any other part of the server.) The trouble is that
  the transaction ID is hidden in an opaque part of the transport handle,
  and only the code in the svc_udp module in the RPC library knows how
  to handle it. This file contains a couple of functions that let us
  read and set the transaction ID in spite of this. This is really a
  dirty trick and I should be taken out and shot for even thinking about
  it, but there's no other way to get this stuff to work.

- Makefile: add yp_svc_udp.c to SRCS.
This commit is contained in:
Bill Paul 1996-12-22 22:30:58 +00:00
parent ce8bac1e6d
commit 180807d214
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=20818
7 changed files with 627 additions and 161 deletions

View File

@ -1,8 +1,8 @@
# $Id: Makefile,v 1.6 1996/09/15 00:39:19 wpaul Exp $
# $Id: Makefile,v 1.8 1996/12/03 02:37:35 wpaul Exp $
PROG= ypserv
SRCS= yp_svc.c yp_server.c yp_dblookup.c yp_dnslookup.c \
ypxfr_clnt.c yp_main.c yp_error.c yp_access.c
ypxfr_clnt.c yp_main.c yp_error.c yp_access.c yp_svc_udp.c
MAN8= ypserv.8

View File

@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: yp_dblookup.c,v 1.4 1996/07/07 19:04:33 wpaul Exp wpaul $
* $Id: yp_dblookup.c,v 1.2 1996/12/22 15:54:15 wpaul Exp $
*
*/
#include <stdio.h>
@ -47,11 +47,11 @@
#include "yp_extern.h"
#ifndef lint
static const char rcsid[] = "$Id: yp_dblookup.c,v 1.4 1996/07/07 19:04:33 wpaul Exp wpaul $";
static const char rcsid[] = "$Id: yp_dblookup.c,v 1.2 1996/12/22 15:54:15 wpaul Exp $";
#endif
int ypdb_debug = 0;
int yp_errno = YP_TRUE;
enum ypstat yp_errno = YP_TRUE;
#define PERM_SECURE (S_IRUSR|S_IWUSR)
HASHINFO openinfo = {
@ -459,22 +459,29 @@ DB *yp_open_db(domain, map)
* the supplied key value in the database.
*/
#ifdef DB_CACHE
int yp_get_record(dbp,key,data,allow)
DB *dbp;
#else
int yp_get_record(domain,map,key,data,allow)
const char *domain;
const char *map;
#endif
const DBT *key;
DBT *data;
int allow;
{
#ifndef DB_CACHE
DB *dbp;
#endif
int rval = 0;
#ifndef DB_CACHE
static unsigned char buf[YPMAXRECORD];
#endif
if (ypdb_debug)
yp_error("Looking up key [%.*s] in map [%s]",
key->size, key->data, map);
yp_error("Looking up key [%.*s]",
key->size, key->data);
/*
* Avoid passing back magic "YP_*" entries unless
@ -484,13 +491,11 @@ int yp_get_record(domain,map,key,data,allow)
if (!allow && !strncmp(key->data, "YP_", 3))
return(YP_NOKEY);
#ifdef DB_CACHE
if ((dbp = yp_open_db_cache(domain, map, NULL, 0)) == NULL) {
#else
#ifndef DB_CACHE
if ((dbp = yp_open_db(domain, map)) == NULL) {
#endif
return(yp_errno);
}
#endif
if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) {
#ifdef DB_CACHE
@ -591,7 +596,7 @@ int yp_next_record(dbp,key,data,all,allow)
static unsigned char datbuf[YPMAXRECORD];
#endif
if (key == NULL || key->data == NULL) {
if (key == NULL || !key->size || key->data == NULL) {
rval = yp_first_record(dbp,key,data,allow);
if (rval == YP_NOKEY)
return(YP_NOMORE);
@ -657,3 +662,87 @@ int yp_next_record(dbp,key,data,all,allow)
return(YP_TRUE);
}
#ifdef DB_CACHE
/*
* Database glue functions.
*/
static DB *yp_currmap_db = NULL;
static int yp_allow_db = 0;
ypstat yp_select_map(map, domain, key, allow)
char *map;
char *domain;
keydat *key;
int allow;
{
yp_currmap_db = yp_open_db_cache(domain, map, key->keydat_val,
key->keydat_len);
yp_allow_db = allow;
return(yp_errno);
}
ypstat yp_getbykey(key, val)
keydat *key;
valdat *val;
{
DBT db_key = { NULL, 0 }, db_val = { NULL, 0 };
ypstat rval;
db_key.data = key->keydat_val;
db_key.size = key->keydat_len;
rval = yp_get_record(yp_currmap_db,
&db_key, &db_val, yp_allow_db);
if (rval == YP_TRUE) {
val->valdat_val = db_val.data;
val->valdat_len = db_val.size;
}
return(rval);
}
ypstat yp_firstbykey(key, val)
keydat *key;
valdat *val;
{
DBT db_key = { NULL, 0 }, db_val = { NULL, 0 };
ypstat rval;
rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db);
if (rval == YP_TRUE) {
key->keydat_val = db_key.data;
key->keydat_len = db_key.size;
val->valdat_val = db_val.data;
val->valdat_len = db_val.size;
}
return(rval);
}
ypstat yp_nextbykey(key, val)
keydat *key;
valdat *val;
{
DBT db_key = { NULL, 0 }, db_val = { NULL, 0 };
ypstat rval;
db_key.data = key->keydat_val;
db_key.size = key->keydat_len;
rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db);
if (rval == YP_TRUE) {
key->keydat_val = db_key.data;
key->keydat_len = db_key.size;
val->valdat_val = db_val.data;
val->valdat_len = db_val.size;
}
return(rval);
}
#endif

View File

@ -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.2 1996/05/31 16:01:49 wpaul Exp $
* $Id: yp_dnslookup.c,v 1.5 1996/12/22 15:45:33 wpaul Exp $
*/
/*
@ -42,19 +42,30 @@
* it disappeared up its own belly button.
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/fcntl.h>
#include <sys/queue.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <stdio.h>
#include <ctype.h>
#include <resolv.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#include <rpcsvc/yp.h>
#include "yp_extern.h"
#ifndef lint
static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.2 1996/05/31 16:01:49 wpaul Exp $";
static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.5 1996/12/22 15:45:33 wpaul Exp $";
#endif
static char *parse(hp)
@ -64,6 +75,9 @@ static char *parse(hp)
int len,i;
struct in_addr addr;
if (hp == NULL)
return(NULL);
len = 16 + strlen(hp->h_name);
for (i = 0; hp->h_aliases[i]; i++)
len += strlen(hp->h_aliases[i]) + 1;
@ -81,32 +95,329 @@ static char *parse(hp)
return ((char *)&result);
}
char *yp_dnsname(address)
char *address;
{
struct hostent *hp;
#define MAXPACKET 1024
#define DEF_TTL 50
if (strchr(address, '@'))
return (NULL);
if ((hp = (struct hostent *)_gethostbydnsname(address, AF_INET)) == NULL)
return (NULL);
extern struct hostent *__dns_getanswer __P((char *, int, char *, int));
return(parse(hp));
}
static CIRCLEQ_HEAD(dns_qhead, circleq_dnsentry) qhead;
char *yp_dnsaddr(address)
const char *address;
{
struct hostent *hp;
struct circleq_dnsentry {
SVCXPRT *xprt;
unsigned long xid;
struct sockaddr_in client_addr;
unsigned long id;
unsigned long ttl;
unsigned long sent;
unsigned long type;
char **domain;
char *name;
struct in_addr addr;
CIRCLEQ_ENTRY(circleq_dnsentry) links;
};
if (strchr(address, '@'))
return (NULL);
if (!inet_aton(address, &addr))
return (NULL);
if ((hp = (struct hostent *)_gethostbydnsaddr((const char *)&addr,
sizeof(unsigned long), AF_INET)) == NULL)
return (NULL);
static int pending = 0;
return(parse(hp));
int yp_init_resolver()
{
CIRCLEQ_INIT(&qhead);
if (!(_res.options & RES_INIT) && res_init() == -1) {
yp_error("res_init failed");
return(1);
}
if ((resfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
yp_error("couldn't create socket");
return(1);
}
if (fcntl(resfd, F_SETFL, O_NONBLOCK) == -1) {
yp_error("couldn't make resolver socket non-blocking");
return(1);
}
return(0);
}
int yp_dnsq_pending()
{
return(pending);
}
static struct circleq_dnsentry *yp_malloc_dnsent()
{
register struct circleq_dnsentry *q;
q = (struct circleq_dnsentry *)malloc(sizeof(struct circleq_dnsentry));
if (q == NULL) {
yp_error("failed to malloc() circleq dns entry: %s",
strerror(errno));
return(NULL);
}
return(q);
}
/*
* Transmit a query.
*/
static unsigned long yp_send_dns_query(name, type)
char *name;
int type;
{
char buf[MAXPACKET];
int n;
HEADER *hptr;
int ns;
int rval;
unsigned long id;
bzero(buf, sizeof(buf));
n = res_mkquery(QUERY,name,C_IN,type,NULL,0,NULL,buf,sizeof(buf));
if (n <= 0) {
yp_error("res_mkquery failed");
return(0);
}
hptr = (HEADER *)&buf;
id = ntohs(hptr->id);
for (ns = 0; ns < _res.nscount; ns++) {
rval = sendto(resfd, buf, n, 0,
(struct sockaddr *)&_res.nsaddr_list[ns],
sizeof(struct sockaddr));
if (rval == -1) {
yp_error("sendto failed");
return(0);
}
}
return(id);
}
static struct circleq_dnsentry *yp_find_dnsqent(id)
unsigned long id;
{
register struct circleq_dnsentry *q;
for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) {
if (q->id == id)
return(q);
}
return (NULL);
}
static void yp_send_dns_reply(q, buf)
struct circleq_dnsentry *q;
char *buf;
{
ypresp_val result;
unsigned long xid;
struct sockaddr_in client_addr;
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;
}
if (debug)
yp_error("Sending dns reply to %s (%lu)",
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
* client until we're ready, by which time we may have received
* several other queries from other clients with different
* transaction IDs. So to make the delayed response thing work,
* we have to save the transaction ID and client address of
* each request, then jam them into the transport handle when
* we're ready to send a reply. Then after we've send the reply,
* we put the old transaction ID and remote address back the
* 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);
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);
q->xprt->xp_raddr = client_addr;
return;
}
void yp_prune_dnsq()
{
register struct circleq_dnsentry *q;
for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) {
q->ttl--;
if (!q->ttl) {
CIRCLEQ_REMOVE(&qhead, q, links);
free(q->name);
free(q);
pending--;
}
}
if (pending < 0)
pending = 0;
return;
}
void yp_run_dnsq()
{
register struct circleq_dnsentry *q;
char buf[sizeof(HEADER) + MAXPACKET];
struct sockaddr_in sin;
int rval;
int len;
HEADER *hptr;
struct hostent *hent;
if (debug)
yp_error("Running dns queue");
bzero(buf, sizeof(buf));
len = sizeof(struct sockaddr_in);
rval = recvfrom(resfd, buf, sizeof(buf), 0,
(struct sockaddr *)&sin, &len);
if (rval == -1) {
yp_error("recvfrom failed: %s", strerror(errno));
return;
}
hptr = (HEADER *)&buf;
if ((q = yp_find_dnsqent(ntohs(hptr->id))) == NULL) {
/* bogus id -- ignore */
return;
}
if (debug)
yp_error("Got dns reply from %s", inet_ntoa(sin.sin_addr));
hent = __dns_getanswer(buf, rval, q->name, q->type);
if (hent == NULL) {
char retrybuf[MAXHOSTNAMELEN];
if (q->domain && *q->domain) {
snprintf(retrybuf, sizeof(retrybuf), "%s.%s",
q->name, *q->domain);
if (debug)
yp_error("Retrying with: %s", retrybuf);
q->id = yp_send_dns_query(retrybuf, q->type);
q->ttl = DEF_TTL;
q->domain++;
return;
}
}
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--;
CIRCLEQ_REMOVE(&qhead, q, links);
free(q->name);
free(q);
yp_prune_dnsq();
return;
}
ypstat yp_async_lookup_name(xprt, name)
SVCXPRT *xprt;
char *name;
{
register struct circleq_dnsentry *q;
if ((q = yp_malloc_dnsent()) == NULL)
return(YP_YPERR);
q->type = T_A;
q->ttl = DEF_TTL;
q->sent = 1;
q->xprt = xprt;
q->xid = svcudp_get_xid(xprt);
q->client_addr = xprt->xp_raddr;
if (!strchr(name, '.'))
q->domain = _res.dnsrch;
else
q->domain = NULL;
q->id = yp_send_dns_query(name, q->type);
if (q->id == 0) {
yp_error("DNS query failed");
free(q);
return(YP_YPERR);
}
q->name = strdup(name);
CIRCLEQ_INSERT_HEAD(&qhead, q, links);
pending++;
if (debug)
yp_error("Queueing async DNS name lookup (%d)", q->id);
return(YP_TRUE);
}
ypstat yp_async_lookup_addr(xprt, addr)
SVCXPRT *xprt;
char *addr;
{
register struct circleq_dnsentry *q;
char buf[MAXHOSTNAMELEN];
int a, b, c, d;
if ((q = yp_malloc_dnsent()) == NULL)
return(YP_YPERR);
if (sscanf(addr, "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
return(YP_NOKEY);
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa",
d, c, b, a, addr);
if (debug)
yp_error("DNS address is: %s", buf);
q->type = T_PTR;
q->ttl = DEF_TTL;
q->sent = 1;
q->xprt = xprt;
q->domain = NULL;
q->xid = svcudp_get_xid(xprt);
q->client_addr = xprt->xp_raddr;
q->id = yp_send_dns_query(buf, q->type);
if (q->id == 0) {
yp_error("DNS query failed");
free(q);
return(YP_YPERR);
}
inet_aton(addr, &q->addr);
q->name = strdup(buf);
CIRCLEQ_INSERT_HEAD(&qhead, q, links);
pending++;
if (debug)
yp_error("Queueing async DNS address lookup (%d)", q->id);
return(YP_TRUE);
}

View File

@ -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.5 1996/10/24 18:58:24 wpaul Exp $
* $Id: yp_extern.h,v 1.3 1996/12/22 15:53:55 wpaul Exp $
*/
#include <stdio.h>
#include <string.h>
@ -39,7 +39,7 @@
#include <limits.h>
#include <db.h>
#include <rpc/rpc.h>
#include <rpcsvc/yp.h>
#ifndef _PATH_YP
#define _PATH_YP "/var/yp/"
@ -64,11 +64,16 @@ extern int debug;
extern int ypdb_debug;
extern int do_dns;
extern int children;
extern int resfd;
extern char *progname;
extern char *yp_dir;
extern int yp_errno;
extern enum ypstat yp_errno;
extern void yp_error __P((const char *, ...));
#ifdef DB_CACHE
extern int yp_get_record __P(( DB *, const DBT *, DBT *, int));
#else
extern int yp_get_record __P(( const char *, const char *, const DBT *, DBT *, int));
#endif
extern int yp_first_record __P((const DB *, DBT *, DBT *, int));
extern int yp_next_record __P((const DB *, DBT *, DBT *, int, int));
extern char *yp_dnsname __P(( char * ));
@ -85,3 +90,24 @@ extern void yp_flush_all __P(( void ));
extern void yp_init_dbs __P(( void ));
extern int yp_testflag __P(( char *, char *, int ));
extern void load_securenets __P(( void ));
#ifdef DB_CACHE
extern ypstat yp_select_map __P(( char *, char *, keydat *, int ));
extern ypstat yp_getbykey __P(( keydat *, valdat * ));
extern ypstat yp_firstbykey __P(( keydat *, valdat * ));
extern ypstat yp_nextbykey __P(( keydat *, valdat * ));
#endif
extern unsigned long svcudp_set_xid __P(( SVCXPRT *, unsigned long ));
extern unsigned long svcudp_get_xid __P(( SVCXPRT * ));
#ifndef RESOLVER_TIMEOUT
#define RESOLVER_TIMEOUT 3600
#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 * ));

View File

@ -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.6 1996/05/31 16:01:50 wpaul Exp $
* $Id: yp_main.c,v 1.4 1996/12/22 15:54:03 wpaul Exp $
*/
/*
@ -66,7 +66,7 @@
#define _RPCSVC_CLOSEDOWN 120
#ifndef lint
static const char rcsid[] = "$Id: yp_main.c,v 1.6 1996/05/31 16:01:50 wpaul Exp $";
static const char rcsid[] = "$Id: yp_main.c,v 1.4 1996/12/22 15:54:03 wpaul Exp $";
#endif /* not lint */
int _rpcpmstart; /* Started by a port monitor ? */
static int _rpcfdtype;
@ -85,6 +85,7 @@ char *progname = "ypserv";
char *yp_dir = _PATH_YP;
int debug = 0;
int do_dns = 0;
int resfd;
static
void _msgout(char* msg)
@ -109,6 +110,7 @@ yp_svc_run()
extern int forked;
int pid;
int fd_setsize = _rpc_dtablesize();
struct timeval timeout = { RESOLVER_TIMEOUT, 0 };
/* Establish the identity of the parent ypserv process. */
pid = getpid();
@ -119,8 +121,12 @@ yp_svc_run()
#else
readfds = svc_fds;
#endif /* def FD_SETSIZE */
if (yp_dnsq_pending())
FD_SET(resfd, &readfds);
switch (select(fd_setsize, &readfds, NULL, NULL,
(struct timeval *)0)) {
&timeout)) {
case -1:
if (errno == EINTR) {
continue;
@ -128,8 +134,13 @@ yp_svc_run()
perror("svc_run: - select failed");
return;
case 0:
continue;
yp_prune_dnsq();
break;
default:
if (FD_ISSET(resfd, &readfds)) {
yp_run_dnsq();
FD_CLR(resfd, &readfds);
}
svc_getreqset(&readfds);
if (forked && pid != getpid())
exit(0);
@ -230,6 +241,7 @@ main(argc, argv)
}
load_securenets();
yp_init_resolver();
#ifdef DB_CACHE
yp_init_dbs();
#endif

View File

@ -31,8 +31,8 @@
*
*/
#include "yp_extern.h"
#include "yp.h"
#include "yp_extern.h"
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
@ -45,12 +45,11 @@
#include <rpc/rpc.h>
#ifndef lint
static const char rcsid[] = "$Id: yp_server.c,v 1.12 1996/10/24 18:58:26 wpaul Exp $";
static const char rcsid[] = "$Id: yp_server.c,v 1.2 1996/12/22 06:57:55 wpaul Exp $";
#endif /* not lint */
int forked = 0;
int children = 0;
static DB *spec_dbp = NULL; /* Special global DB handle for ypproc_all. */
static char *master_string = "YP_MASTER_NAME";
static char *order_string = "YP_LAST_MODIFIED";
static int master_sz = sizeof("YP_MASTER_NAME") - 1;
@ -124,7 +123,6 @@ ypresp_val *
ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
{
static ypresp_val result;
DBT key, data;
result.val.valdat_val = "";
result.val.valdat_len = 0;
@ -143,15 +141,13 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
return (&result);
}
key.size = argp->key.keydat_len;
key.data = argp->key.keydat_val;
if ((result.stat = yp_get_record(argp->domain, argp->map,
&key, &data, 1)) == YP_TRUE) {
result.val.valdat_len = data.size;
result.val.valdat_val = data.data;
if (yp_select_map(argp->map, argp->domain, &argp->key, 1) != YP_TRUE) {
result.stat = yp_errno;
return(&result);
}
result.stat = yp_getbykey(&argp->key, &result.val);
/*
* Do DNS lookups for hosts maps if database lookup failed.
*/
@ -163,50 +159,24 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
#else
if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) {
#endif
char *rval = NULL;
/* DNS lookups can take time -- do them in a subprocess */
if (!debug && children < MAX_CHILDREN && fork()) {
children++;
forked = 0;
/*
* Returning NULL here prevents svc_sendreply()
* from being called by the parent. This is vital
* since having both the parent and the child process
* call it would confuse the client.
*/
return (NULL);
} else {
forked++;
}
/* NUL terminate! NUL terminate!! NUL TERMINATE!!! */
argp->key.keydat_val[argp->key.keydat_len] = '\0';
if (debug)
yp_error("Doing DNS lookup of %.*s",
argp->key.keydat_len,
argp->key.keydat_val);
/* NUL terminate! NUL terminate!! NUL TERMINATE!!! */
argp->key.keydat_val[argp->key.keydat_len] = '\0';
if (!strcmp(argp->map, "hosts.byname"))
rval = yp_dnsname((char *)argp->key.keydat_val);
result.stat = yp_async_lookup_name(rqstp->rq_xprt,
(char *)argp->key.keydat_val);
else if (!strcmp(argp->map, "hosts.byaddr"))
rval = yp_dnsaddr((const char *)argp->key.keydat_val);
result.stat = yp_async_lookup_addr(rqstp->rq_xprt,
(char *)argp->key.keydat_val);
if (rval) {
if (debug)
yp_error("DNS lookup successful. Result: %s",
rval);
result.val.valdat_len = strlen(rval);
result.val.valdat_val = rval;
result.stat = YP_TRUE;
} else {
if (debug)
yp_error("DNS lookup failed.");
result.stat = YP_NOKEY;
}
if (result.stat == YP_TRUE)
return(NULL);
}
return (&result);
@ -216,8 +186,6 @@ ypresp_key_val *
ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
static ypresp_key_val result;
DBT key, data;
DB *dbp;
result.val.valdat_val = result.key.keydat_val = "";
result.val.valdat_len = result.key.keydat_len = 0;
@ -236,27 +204,13 @@ ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
return (&result);
}
#ifdef DB_CACHE
if ((dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) {
#else
if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
#endif
if (yp_select_map(argp->map, argp->domain, &result.key, 0) != YP_TRUE) {
result.stat = yp_errno;
return(&result);
}
key.data = NULL;
key.size = 0;
result.stat = yp_firstbykey(&result.key, &result.val);
if ((result.stat = yp_first_record(dbp, &key, &data, 0)) == YP_TRUE) {
result.key.keydat_len = key.size;
result.key.keydat_val = key.data;
result.val.valdat_len = data.size;
result.val.valdat_val = data.data;
}
#ifndef DB_CACHE
(void)(dbp->close)(dbp);
#endif
return (&result);
}
@ -264,8 +218,6 @@ ypresp_key_val *
ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp)
{
static ypresp_key_val result;
DBT key, data;
DB *dbp;
result.val.valdat_val = result.key.keydat_val = "";
result.val.valdat_len = result.key.keydat_len = 0;
@ -284,29 +236,16 @@ ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp)
return (&result);
}
#ifdef DB_CACHE
if ((dbp = yp_open_db_cache(argp->domain, argp->map,
argp->key.keydat_val,
argp->key.keydat_len)) == NULL) {
#else
if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
#endif
if (yp_select_map(argp->map, argp->domain, &argp->key, 0) != YP_TRUE) {
result.stat = yp_errno;
return(&result);
}
key.size = argp->key.keydat_len;
key.data = argp->key.keydat_val;
result.key.keydat_len = argp->key.keydat_len;
result.key.keydat_val = argp->key.keydat_val;
result.stat = yp_nextbykey(&result.key, &result.val);
if ((result.stat = yp_next_record(dbp, &key, &data,0,0)) == YP_TRUE) {
result.key.keydat_len = key.size;
result.key.keydat_val = key.data;
result.val.valdat_len = data.size;
result.val.valdat_val = data.data;
}
#ifndef DB_CACHE
(void)(dbp->close)(dbp);
#endif
return (&result);
}
@ -480,16 +419,11 @@ ypproc_clear_2_svc(void *argp, struct svc_req *rqstp)
static bool_t
xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp)
{
DBT key = { NULL, 0 } , data = { NULL, 0 };
while (1) {
/* Get a record. */
if ((objp->ypresp_all_u.val.stat =
yp_next_record(spec_dbp,&key,&data,1,0)) == YP_TRUE) {
objp->ypresp_all_u.val.val.valdat_len = data.size;
objp->ypresp_all_u.val.val.valdat_val = data.data;
objp->ypresp_all_u.val.key.keydat_len = key.size;
objp->ypresp_all_u.val.key.keydat_val = key.data;
yp_nextbykey(&objp->ypresp_all_u.val.key,
&objp->ypresp_all_u.val.val)) == YP_TRUE) {
objp->more = TRUE;
} else {
objp->more = FALSE;
@ -545,24 +479,15 @@ ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
forked++;
}
#ifndef DB_CACHE
if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
if (yp_select_map(argp->map, argp->domain,
&result.ypresp_all_u.val.key, 0) != YP_TRUE) {
result.ypresp_all_u.val.stat = yp_errno;
return(&result);
}
#else
if ((spec_dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) {
result.ypresp_all_u.val.stat = yp_errno;
return(&result);
}
#endif
/* Kick off the actual data transfer. */
svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result);
#ifndef DB_CACHE
(void)(spec_dbp->close)(spec_dbp);
#endif
/*
* Returning NULL prevents the dispatcher from calling
* svc_sendreply() since we already did it.
@ -575,7 +500,8 @@ ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
static ypresp_master result;
static char ypvalbuf[YPMAXRECORD];
DBT key = { master_string, master_sz }, data;
keydat key = { master_sz, master_string };
valdat val;
result.peer = "";
@ -593,6 +519,11 @@ ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
return (&result);
}
if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) {
result.stat = yp_errno;
return(&result);
}
/*
* Note that we copy the data retrieved from the database to
* a private buffer and NUL terminate the buffer rather than
@ -601,10 +532,11 @@ ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
* allocated by the DB package. This is a bad thing now that we
* cache DB handles rather than closing the database immediately.
*/
if ((result.stat = yp_get_record(argp->domain, argp->map,
&key, &data, 1)) == YP_TRUE) {
bcopy((char *)data.data, (char *)&ypvalbuf, data.size);
ypvalbuf[data.size] = '\0';
result.stat = yp_getbykey(&key, &val);
if (result.stat == YP_TRUE) {
bcopy((char *)val.valdat_val, (char *)&ypvalbuf,
val.valdat_len);
ypvalbuf[val.valdat_len] = '\0';
result.peer = (char *)&ypvalbuf;
} else
result.peer = "";
@ -616,7 +548,8 @@ ypresp_order *
ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
static ypresp_order result;
DBT key = { order_string, order_sz }, data;
keydat key = { order_sz, order_string };
valdat val;
result.ordernum = 0;
@ -641,13 +574,18 @@ ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
* updated.
*/
if ((result.stat = yp_get_record(argp->domain, argp->map,
&key, &data, 1)) == YP_TRUE)
result.ordernum = atoi((char *)data.data);
if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) {
result.stat = yp_errno;
return(&result);
}
result.stat = yp_getbykey(&key, &val);
if (result.stat == YP_TRUE)
result.ordernum = atoi((char *)val.valdat_val);
else
result.ordernum = 0;
return (&result);
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 1996
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul 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
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: yp_svc_udp.c,v 1.1 1996/12/22 15:44:09 wpaul Exp $
*/
#include <rpc/rpc.h>
#include "yp_extern.h"
#ifndef lint
static const char rcsid[] = "$Id: yp_svc_udp.c,v 1.1 1996/12/22 15:44:09 wpaul Exp $";
#endif
/*
* XXX Must not diverge from what's in src/lib/libc/rpc/svc_udp.c
*/
/*
* kept in xprt->xp_p2
*/
struct svcudp_data {
u_int su_iosz; /* byte size of send.recv buffer */
u_long su_xid; /* transaction id */
XDR su_xdrs; /* XDR handle */
char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
char * su_cache; /* cached data, NULL if no cache */
};
#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
/*
* We need to be able to manually set the transaction ID in the
* UDP transport handle, but the standard library offers us no way
* to do that. Hence we need this garbage.
*/
unsigned long
svcudp_get_xid(xprt)
SVCXPRT *xprt;
{
struct svcudp_data *su;
if (xprt == NULL)
return(0);
su = su_data(xprt);
return(su->su_xid);
}
unsigned long
svcudp_set_xid(xprt, xid)
SVCXPRT *xprt;
unsigned long xid;
{
struct svcudp_data *su;
unsigned long old_xid;
if (xprt == NULL)
return(0);
su = su_data(xprt);
old_xid = su->su_xid;
su->su_xid = xid;
return(old_xid);
}