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:
parent
5db7774e00
commit
24c42ee823
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 * ));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
90
usr.sbin/ypserv/yp_svc_udp.c
Normal file
90
usr.sbin/ypserv/yp_svc_udp.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user