OpenBSD-4.6/usr.sbin/ypserv/ypserv/ypserv_proc.c

Compare this file to the similar file:
Show the results in this format:

/*	$OpenBSD: ypserv_proc.c,v 1.26 2006/09/25 05:59:28 otto Exp $ */

/*
 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
 */

#ifndef lint
static const char rcsid[] = "$OpenBSD: ypserv_proc.c,v 1.26 2006/09/25 05:59:28 otto Exp $";
#endif

#include <rpc/rpc.h>
#include <rpcsvc/yp.h>
#include "ypv1.h"
#include <rpcsvc/ypclnt.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "ypdb.h"
#include "acl.h"
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "yplog.h"
#include "ypdef.h"
#include "ypserv.h"

#ifdef DEBUG
#define YPLOG yplog
#else /* DEBUG */
#define YPLOG if (!ok) yplog
#endif /* DEBUG */

static char *True = "true";
static char *False = "FALSE";
#define TORF(N) ((N) ? True : False)

/*ARGSUSED*/
void *
ypproc_null_2_svc(void *argp, struct svc_req *rqstp)
{
	static char *result;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);

	YPLOG("null_2: caller=[%s].%d, auth_ok=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok));

	if (!ok) {
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	result = NULL;
	return ((void *)&result);
}

bool_t *
ypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp)
{
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	static char domain_path[MAXPATHLEN];
	static bool_t result;
	struct stat finfo;

	if (strchr(*argp, '/'))
		goto bail;
	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
	    S_ISDIR(finfo.st_mode));

	YPLOG("domain_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), *argp, TORF(result));

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}
	return (&result);
}

bool_t *
ypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp)
{
	static bool_t result; /* is domain served? */
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	static char domain_path[MAXPATHLEN];
	struct stat finfo;

	if (strchr(*argp, '/'))
		goto bail;
	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
	    S_ISDIR(finfo.st_mode));

	YPLOG("domain_nonack_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
	    *argp, TORF(result));

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (!result)
		return(NULL); /* don't send nack */
	return (&result);
}

ypresp_val *
ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
{
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure = ypdb_secure(argp->domain, argp->map);
	static ypresp_val res;

	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
		goto bail;
	YPLOG("match_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure),
	    argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.stat = YP_YPERR;
	} else {
		res = ypdb_get_record(argp->domain, argp->map, argp->key, TRUE);
	}

#ifdef DEBUG
	yplog("  match2_status: %s", yperr_string(ypprot_err(res.stat)));
#endif
	return (&res);
}

ypresp_key_val *
ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure = ypdb_secure(argp->domain, argp->map);
	static ypresp_key_val res;

	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
		goto bail;
	YPLOG( "first_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure), argp->domain, argp->map);
	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.stat = YP_YPERR;
	} else {
		res = ypdb_get_first(argp->domain, argp->map,FALSE);
	}

#ifdef DEBUG
	yplog("  first2_status: %s", yperr_string(ypprot_err(res.stat)));
#endif
	return (&res);
}

ypresp_key_val *
ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp)
{
	static ypresp_key_val res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure = ypdb_secure(argp->domain, argp->map);

	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
		goto bail;
	YPLOG("next_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure),
	    argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.stat = YP_YPERR;
	} else {
		res = ypdb_get_next(argp->domain, argp->map, argp->key,FALSE);
	}

#ifdef DEBUG
	yplog("  next2_status: %s", yperr_string(ypprot_err(res.stat)));
#endif
	return (&res);
}

ypresp_xfr *
ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp)
{
	static ypresp_xfr res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	pid_t	pid;
	char	tid[11], prog[11], port[11];
	char	ypxfr_proc[] = YPXFR_PROC, *ipadd;

	bzero(&res, sizeof(res));

	YPLOG("xfr_2: caller=[%s].%d, auth_ok=%s, domain=%s, tid=%d, prog=%d",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
	    argp->map_parms.domain, argp->transid, argp->prog);
	YPLOG("       ipadd=%s, port=%d, map=%s", inet_ntoa(caller->sin_addr),
	    argp->port, argp->map_parms.map);

	if (strchr(argp->map_parms.domain, '/') ||
	    strchr(argp->map_parms.map, '/') ||
	    ntohs(caller->sin_port) >= IPPORT_RESERVED) {
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	snprintf(tid, sizeof(tid), "%d", argp->transid);
	snprintf(prog, sizeof(prog), "%d", argp->prog);
	snprintf(port, sizeof(port), "%d", argp->port);
	ipadd = inet_ntoa(caller->sin_addr);

	pid = vfork();
	if (pid == -1) {
		svcerr_systemerr(rqstp->rq_xprt);
		return(NULL);
	}
	if (pid == 0) {
		execl(ypxfr_proc, "ypxfr", "-d", argp->map_parms.domain,
		    "-C", tid, prog, ipadd, port, argp->map_parms.map, (char *)NULL);
		_exit(1);
	}
	/*
	 * XXX: fill in res
	 */
	return (&res);
}

/*ARGSUSED*/
void *
ypproc_clear_2_svc(void *argp, struct svc_req *rqstp)
{
	static char *res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);

	YPLOG( "clear_2: caller=[%s].%d, auth_ok=%s, opt=%s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
#ifdef OPTDB
		True
#else
		False
#endif
	);

	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
		ok = FALSE;

	if (!ok) {
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	res = NULL;

#ifdef OPTDB
	ypdb_close_all();
#endif
	return ((void *)&res);
}

ypresp_all *
ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
	static ypresp_all res;
	pid_t pid;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure = ypdb_secure(argp->domain, argp->map);

	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
		goto bail;
	YPLOG( "all_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure), argp->domain, argp->map);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}
	bzero(&res, sizeof(res));

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.ypresp_all_u.val.stat = YP_YPERR;
		return(&res);
	}

	pid = fork();
	if (pid) {
		if (pid == -1) {
			/* XXXCDC An error has occurred */
		}
		return(NULL); /* PARENT: continue */
	}
	/* CHILD: send result, then exit */

	if (!svc_sendreply(rqstp->rq_xprt, ypdb_xdr_get_all, (char *)argp)) {
		svcerr_systemerr(rqstp->rq_xprt);
	}
	exit(0);
}

ypresp_master *
ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
	static ypresp_master res;
	static peername nopeer = "";
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure = ypdb_secure(argp->domain, argp->map);

	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
		goto bail;
	YPLOG( "master_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure), argp->domain, argp->map);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.stat = YP_YPERR;
	} else {
		res = ypdb_get_master(argp->domain, argp->map);
	}

#ifdef DEBUG
	yplog("  master2_status: %s", yperr_string(ypprot_err(res.stat)));
#endif

	/*
	 * This code was added because a yppoll <unknown-domain>
	 * from a sun crashed the server in xdr_string, trying
	 * to access the peer through a NULL-pointer. yppoll in
	 * this server start asking for order. If order is ok
	 * then it will ask for master. SunOS 4 asks for both
	 * always. I'm not sure this is the best place for the
	 * fix, but for now it will do. xdr_peername or
	 * xdr_string in ypserv_xdr.c may be a better place?
	 */
	if (res.peer == NULL)
		res.peer = nopeer;
	return (&res);
}


ypresp_order *
ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
{
	static ypresp_order res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure = ypdb_secure(argp->domain, argp->map);

	if (strchr(argp->domain, '/'))
		goto bail;
	YPLOG( "order_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure), argp->domain, argp->map);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.stat = YP_YPERR;
	} else if (strchr(argp->map, '/')) {
		res.stat = YP_NOMAP;
	} else {
		res = ypdb_get_order(argp->domain, argp->map);
	}

#ifdef DEBUG
	yplog("  order2_status: %s", yperr_string(ypprot_err(res.stat)));
#endif
	return (&res);
}


ypresp_maplist *
ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp)
{
	static ypresp_maplist res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	static char domain_path[MAXPATHLEN];
	struct stat finfo;
	DIR   *dirp = NULL;
	struct dirent *dp;
	char  *suffix;
	ypstat status;
	struct ypmaplist *m;
	char  *map_name;

	if (strchr(*argp, '/'))
		goto bail;
	YPLOG("maplist_2: caller=[%s].%d, auth_ok=%s, domain=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
	    *argp);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	bzero(&res, sizeof(res));
	snprintf(domain_path, sizeof domain_path, "%s/%s", YP_DB_PATH, *argp);

	status = YP_TRUE;
	res.maps = NULL;

	if (!((stat(domain_path, &finfo) == 0) && S_ISDIR(finfo.st_mode)))
		status = YP_NODOM;

	if (status >= 0) {
		if ((dirp = opendir(domain_path)) == NULL)
			status = YP_NODOM;
	}

	if (status >= 0) {
		for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
			if ((!strcmp(dp->d_name, ".")) ||
			    ((!strcmp(dp->d_name, ".."))) ||
			    (dp->d_namlen < 4))
				continue;
			suffix = (char *) &dp->d_name[dp->d_namlen-3];
			if (strcmp(suffix, ".db") == 0) {
				if ((m = malloc(sizeof(struct ypmaplist))) == NULL) {
					status = YP_YPERR;
					break;
				}

				if ((map_name = malloc(dp->d_namlen - 2)) == NULL) {
					status = YP_YPERR;
					break;
				}

				m->next = res.maps;
				m->map = map_name;
				res.maps = m;
				strncpy(map_name, dp->d_name, dp->d_namlen - 3);
				m->map[dp->d_namlen - 3] = '\0';
			}
		}
	}
	if (dirp != NULL)
		closedir(dirp);

	res.stat = status;
#ifdef DEBUG
	yplog("  maplist_status: %s", yperr_string(ypprot_err(res.stat)));
#endif
	return (&res);
}

/*ARGSUSED*/
void *
ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp)
{
	static char *result;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);

	YPLOG("null_1: caller=[%s].%d, auth_ok=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok));

	if (!ok) {
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	result = NULL;

	return ((void *)&result);
}

bool_t *
ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp)
{
	static bool_t result; /* is domain_served? */
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	static char domain_path[MAXPATHLEN];
	struct stat finfo;

	if (strchr(*argp, '/'))
		goto bail;
	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
				    S_ISDIR(finfo.st_mode));

	YPLOG("domain_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), *argp, TORF(result));

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	return (&result);
}

bool_t *
ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp)
{
	static bool_t result; /* is domain served? */
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	static char domain_path[MAXPATHLEN];
	struct stat finfo;

	if (strchr(*argp, '/'))
		goto bail;
	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
				    S_ISDIR(finfo.st_mode));

	YPLOG(
	  "domain_nonack_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
	  *argp, TORF(result));

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (!result) {
		return(NULL); /* don't send nack */
	}

	return (&result);
}

ypresponse *
ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	static ypresponse res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;

	if (strchr(argp->ypmatch_req_domain, '/') ||
	    strchr(argp->ypmatch_req_map, '/'))
		goto bail;
	res.yp_resptype = YPMATCH_RESPTYPE;
	res.ypmatch_resp_valptr = "";
	res.ypmatch_resp_valsize = 0;

	if (argp->yp_reqtype != YPMATCH_REQTYPE) {
		res.ypmatch_resp_status = YP_BADARGS;
		return(&res);
	}

	secure = ypdb_secure(argp->ypmatch_req_domain, argp->ypmatch_req_map);

	YPLOG(
	  "match_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	  TORF(ok), TORF(secure),
	  argp->ypmatch_req_domain,  argp->ypmatch_req_map,
	  argp->ypmatch_req_keysize, argp->ypmatch_req_keyptr);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.ypmatch_resp_status = YP_YPERR;
	} else {
		res.ypmatch_resp_val = ypdb_get_record(
		    argp->ypmatch_req_domain, argp->ypmatch_req_map,
		    argp->ypmatch_req_keydat, TRUE);
	}

#ifdef DEBUG
	yplog("  match1_status: %s",
	    yperr_string(ypprot_err(res.ypmatch_resp_status)));
#endif

	return (&res);
}

ypresponse *
ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	static ypresponse res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;

	if (strchr(argp->ypfirst_req_domain, '/') ||
	    strchr(argp->ypfirst_req_map, '/'))
		goto bail;
	res.yp_resptype = YPFIRST_RESPTYPE;
	res.ypfirst_resp_valptr = res.ypfirst_resp_keyptr = "";
	res.ypfirst_resp_valsize = res.ypfirst_resp_keysize = 0;

	if (argp->yp_reqtype != YPREQ_NOKEY) {
		res.ypfirst_resp_status = YP_BADARGS;
		return(&res);
	}

	secure = ypdb_secure(argp->ypfirst_req_domain, argp->ypfirst_req_map);

	YPLOG( "first_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	  TORF(ok), TORF(secure),
	  argp->ypfirst_req_domain, argp->ypfirst_req_map);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.ypfirst_resp_status = YP_YPERR;
	} else {
		res.ypfirst_resp_val = ypdb_get_first(
		    argp->ypfirst_req_domain, argp->ypfirst_req_map, FALSE);
	}

#ifdef DEBUG
	yplog("  first1_status: %s",
	    yperr_string(ypprot_err(res.ypfirst_resp_status)));
#endif

	return (&res);
}

ypresponse *
ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	static ypresponse res;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;

	if (strchr(argp->ypnext_req_domain, '/') ||
	    strchr(argp->ypnext_req_map, '/'))
		goto bail;
	res.yp_resptype = YPNEXT_RESPTYPE;
	res.ypnext_resp_valptr = res.ypnext_resp_keyptr = "";
	res.ypnext_resp_valsize = res.ypnext_resp_keysize = 0;

	if (argp->yp_reqtype != YPNEXT_REQTYPE) {
		res.ypnext_resp_status = YP_BADARGS;
		return(&res);
	}

	secure = ypdb_secure(argp->ypnext_req_domain, argp->ypnext_req_map);

	YPLOG(
	  "next_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	  TORF(ok), TORF(secure),
	  argp->ypnext_req_domain,  argp->ypnext_req_map,
	  argp->ypnext_req_keysize, argp->ypnext_req_keyptr);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
		res.ypnext_resp_status = YP_YPERR;
	} else {
		res.ypnext_resp_val = ypdb_get_next(
		    argp->ypnext_req_domain, argp->ypnext_req_map,
		    argp->ypnext_req_keydat, FALSE);
	}

#ifdef DEBUG
	yplog("  next1_status: %s",
	    yperr_string(ypprot_err(res.ypnext_resp_status)));
#endif

	return (&res);
}

ypresponse *
ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	static ypresponse res;
	ypresp_order order;
	ypresp_master master;
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;

	if (strchr(argp->yppoll_req_domain, '/') ||
	    strchr(argp->yppoll_req_map, '/'))
		goto bail;
	res.yp_resptype = YPPOLL_RESPTYPE;
	res.yppoll_resp_domain = argp->yppoll_req_domain;
	res.yppoll_resp_map = argp->yppoll_req_map;
	res.yppoll_resp_ordernum = 0;
	res.yppoll_resp_owner = "";

	if (argp->yp_reqtype != YPPOLL_REQTYPE) {
		return(&res);
	}

	secure = ypdb_secure(argp->yppoll_req_domain, argp->yppoll_req_map);

	YPLOG( "poll_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	  TORF(ok), TORF(secure),
	  argp->yppoll_req_domain, argp->yppoll_req_map);

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	if (!(secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED))) {
		order = ypdb_get_order(argp->yppoll_req_domain,
		    argp->yppoll_req_map);
		master = ypdb_get_master(argp->yppoll_req_domain,
		    argp->yppoll_req_map);
		res.yppoll_resp_ordernum = order.ordernum;
		res.yppoll_resp_owner = master.peer;
	}

#ifdef DEBUG
	yplog("  poll1_status: %s", "none");
#endif
	return (&res);
}

void *
ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;
	pid_t	pid;
	char	yppush_proc[] = YPPUSH_PROC;

	if (strchr(argp->yppush_req_domain, '/') ||
	    strchr(argp->yppush_req_map, '/'))
		goto bail;
	if (argp->yp_reqtype != YPPUSH_REQTYPE) {
		return(NULL);
	}

	secure = ypdb_secure(argp->yppush_req_domain, argp->yppush_req_map);

	YPLOG( "push_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	  TORF(ok), TORF(secure),
	  argp->yppush_req_domain, argp->yppush_req_map);

	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
		ok = FALSE;

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	pid = vfork();
	if (pid == -1) {
		svcerr_systemerr(rqstp->rq_xprt);
		return(NULL);
	}
	if (pid == 0) {
		execl(yppush_proc, "yppush", "-d", argp->yppush_req_domain,
		    argp->yppush_req_map, (char *)NULL);
		_exit(1);
	}
	return (NULL);
}

void *
ypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;
	pid_t	pid;
	char	ypxfr_proc[] = YPXFR_PROC;

	if (strchr(argp->yppull_req_domain, '/') ||
	    strchr(argp->yppull_req_map, '/'))
		goto bail;
	if (argp->yp_reqtype != YPPULL_REQTYPE) {
		return(NULL);
	}

	secure = ypdb_secure(argp->yppull_req_domain, argp->yppull_req_map);

	YPLOG( "pull_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	  TORF(ok), TORF(secure),
	  argp->yppull_req_domain, argp->yppull_req_map);

	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
		ok = FALSE;

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	pid = vfork();
	if (pid == -1) {
		svcerr_systemerr(rqstp->rq_xprt);
		return(NULL);
	}
	if (pid == 0) {
		execl(ypxfr_proc, "ypxfr", "-d", argp->yppull_req_domain,
		    argp->yppull_req_map, (char *)NULL);
		_exit(1);
	}
	return (NULL);
}

void *
ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp)
{
	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
	int ok = acl_check_host(&caller->sin_addr);
	int secure;
	pid_t	pid;
	char	ypxfr_proc[] = YPXFR_PROC;

	if (strchr(argp->ypget_req_domain, '/') ||
	    strchr(argp->ypget_req_map, '/'))
		goto bail;
	if (argp->yp_reqtype != YPGET_REQTYPE)
		return(NULL);

	secure = ypdb_secure(argp->ypget_req_domain, argp->ypget_req_map);

	YPLOG( "get_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, owner=%s",
	    inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
	    TORF(ok), TORF(secure),
	    argp->ypget_req_domain, argp->ypget_req_map,
	    argp->ypget_req_owner);

	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
		ok = FALSE;

	if (!ok) {
bail:
		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
		return(NULL);
	}

	pid = vfork();
	if (pid == -1) {
		svcerr_systemerr(rqstp->rq_xprt);
		return(NULL);
	}
	if (pid == 0) {
		execl(ypxfr_proc, "ypxfr", "-d", argp->ypget_req_domain, "-h",
		    argp->ypget_req_owner, argp->yppush_req_map, (char *)NULL);
		_exit(1);
	}
	return (NULL);
}