113007Swpaul/*
213007Swpaul * Copyright (c) 1995
313007Swpaul *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
413007Swpaul *
513007Swpaul * Redistribution and use in source and binary forms, with or without
613007Swpaul * modification, are permitted provided that the following conditions
713007Swpaul * are met:
813007Swpaul * 1. Redistributions of source code must retain the above copyright
913007Swpaul *    notice, this list of conditions and the following disclaimer.
1013007Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1113007Swpaul *    notice, this list of conditions and the following disclaimer in the
1213007Swpaul *    documentation and/or other materials provided with the distribution.
1313007Swpaul * 3. All advertising materials mentioning features or use of this software
1413007Swpaul *    must display the following acknowledgement:
1513007Swpaul *	This product includes software developed by Bill Paul.
1613007Swpaul * 4. Neither the name of the author nor the names of any co-contributors
1713007Swpaul *    may be used to endorse or promote products derived from this software
1813007Swpaul *    without specific prior written permission.
1913007Swpaul *
2013007Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2113007Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2213007Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2313007Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2413007Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2513007Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2613007Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2713007Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2813007Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2913007Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3013007Swpaul * SUCH DAMAGE.
3113007Swpaul */
3231626Scharnier
33114626Sobrien#include <sys/cdefs.h>
34114626Sobrien__FBSDID("$FreeBSD$");
3531626Scharnier
3619181Swpaul#include <stdio.h>
3719181Swpaul#include <string.h>
3813895Swpaul#include <stdlib.h>
3913895Swpaul#include <unistd.h>
4013895Swpaul#include <sys/param.h>
4113007Swpaul#include <rpc/rpc.h>
4213007Swpaul#include <rpcsvc/yp.h>
4313007Swpaul#include <rpcsvc/ypclnt.h>
4413007Swpaul#include "ypxfr_extern.h"
4513007Swpaul
4693979Sdesconst char *
4790298Sdesypxfrerr_string(ypxfrstat code)
4813007Swpaul{
4990297Sdes	switch (code) {
5013007Swpaul	case YPXFR_SUCC:
5161187Sjlemon		return ("Map successfully transferred");
5213007Swpaul		break;
5313007Swpaul	case YPXFR_AGE:
5413007Swpaul		return ("Master's version not newer");
5513007Swpaul		break;
5613007Swpaul	case YPXFR_NOMAP:
5713007Swpaul		return ("No such map in server's domain");
5813007Swpaul		break;
5913007Swpaul	case YPXFR_NODOM:
6013007Swpaul		return ("Domain not supported by server");
6113007Swpaul		break;
6213007Swpaul	case YPXFR_RSRC:
6313007Swpaul		return ("Local resource allocation failure");
6413007Swpaul		break;
6513007Swpaul	case YPXFR_RPC:
6613007Swpaul		return ("RPC failure talking to server");
6713007Swpaul		break;
6813007Swpaul	case YPXFR_MADDR:
6913007Swpaul		return ("Could not get master server address");
7013007Swpaul		break;
7113007Swpaul	case YPXFR_YPERR:
7213007Swpaul		return ("NIS server/map database error");
7313007Swpaul		break;
7413007Swpaul	case YPXFR_BADARGS:
7513007Swpaul		return ("Request arguments bad");
7613007Swpaul		break;
7713007Swpaul	case YPXFR_DBM:
7813007Swpaul		return ("Local database operation failed");
7913007Swpaul		break;
8013007Swpaul	case YPXFR_FILE:
8113007Swpaul		return ("Local file I/O operation failed");
8213007Swpaul		break;
8313007Swpaul	case YPXFR_SKEW:
8413007Swpaul		return ("Map version skew during transfer");
8513007Swpaul		break;
8613007Swpaul	case YPXFR_CLEAR:
8713007Swpaul		return ("Couldn't send \"clear\" request to local ypserv");
8813007Swpaul		break;
8913007Swpaul	case YPXFR_FORCE:
9013007Swpaul		return ("No local order number in map -- use -f flag");
9113007Swpaul		break;
9213007Swpaul	case YPXFR_XFRERR:
9313007Swpaul		return ("General ypxfr error");
9413007Swpaul		break;
9513007Swpaul	case YPXFR_REFUSED:
9613007Swpaul		return ("Transfer request refused by ypserv");
9713007Swpaul		break;
9813007Swpaul	default:
9913007Swpaul		return ("Unknown error code");
10013007Swpaul		break;
10113007Swpaul	}
10213007Swpaul}
10313007Swpaul
10413007Swpaul/*
10513007Swpaul * These are wrappers for the usual yp_master() and yp_order() functions.
10613007Swpaul * They can use either local yplib functions (the real yp_master() and
10713007Swpaul * yp_order()) or do direct RPCs to a specified server. The latter is
10813007Swpaul * necessary if ypxfr is run on a machine that isn't configured as an
10913007Swpaul * NIS client (this can happen very easily: a given machine need not be
11013007Swpaul * an NIS client in order to be an NIS server).
11113007Swpaul */
11213007Swpaul
11313895Swpaul/*
11413895Swpaul * Careful: yp_master() returns a pointer to a dynamically allocated
11513895Swpaul * buffer. Calling ypproc_master_2() ourselves also returns a pointer
11613895Swpaul * to dynamically allocated memory, though this time it's memory
11713895Swpaul * allocated by the XDR routines. We have to rememver to free() or
11813895Swpaul * xdr_free() the memory as required to avoid leaking memory.
11913895Swpaul */
12090298Sdeschar *
12190298Sdesypxfr_get_master(char *domain, char *map, char *source, const int yplib)
12213007Swpaul{
12313895Swpaul	static char mastername[MAXPATHLEN + 2];
12413895Swpaul
12513895Swpaul	bzero((char *)&mastername, sizeof(mastername));
12613895Swpaul
12713007Swpaul	if (yplib) {
12813007Swpaul		int res;
12913007Swpaul		char *master;
13013007Swpaul		if ((res = yp_master(domain, map, &master))) {
13113007Swpaul			switch (res) {
13213007Swpaul			case YPERR_DOMAIN:
133229142Sdim				yp_errno = (enum ypstat)YPXFR_NODOM;
13413007Swpaul				break;
13513007Swpaul			case YPERR_MAP:
136229142Sdim				yp_errno = (enum ypstat)YPXFR_NOMAP;
13713007Swpaul				break;
13813007Swpaul			case YPERR_YPERR:
13913007Swpaul			default:
140229142Sdim				yp_errno = (enum ypstat)YPXFR_YPERR;
14113007Swpaul				break;
14213007Swpaul			}
14313007Swpaul			return(NULL);
14413895Swpaul		} else {
14513895Swpaul			snprintf(mastername, sizeof(mastername), "%s", master);
14613895Swpaul			free(master);
14713895Swpaul			return((char *)&mastername);
14813895Swpaul		}
14913007Swpaul	} else {
15013007Swpaul		CLIENT *clnt;
15113007Swpaul		ypresp_master *resp;
15213007Swpaul		ypreq_nokey req;
15313007Swpaul
15413007Swpaul		if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) {
15513007Swpaul			yp_error("%s",clnt_spcreateerror("failed to \
15613007Swpaulcreate udp handle to ypserv"));
157229142Sdim			yp_errno = (enum ypstat)YPXFR_RPC;
15813007Swpaul			return(NULL);
15913007Swpaul		}
16013007Swpaul
16113007Swpaul		req.map = map;
16213007Swpaul		req.domain = domain;
16313007Swpaul		if ((resp = ypproc_master_2(&req, clnt)) == NULL) {
16413007Swpaul			yp_error("%s",clnt_sperror(clnt,"YPPROC_MASTER \
16513007Swpaulfailed"));
16613007Swpaul			clnt_destroy(clnt);
167229142Sdim			yp_errno = (enum ypstat)YPXFR_RPC;
16813007Swpaul			return(NULL);
16913007Swpaul		}
17013007Swpaul		clnt_destroy(clnt);
17113007Swpaul		if (resp->stat != YP_TRUE) {
17213007Swpaul			switch (resp->stat) {
17313007Swpaul			case YP_NODOM:
174229142Sdim				yp_errno = (enum ypstat)YPXFR_NODOM;
17513007Swpaul				break;
17613007Swpaul			case YP_NOMAP:
177229142Sdim				yp_errno = (enum ypstat)YPXFR_NOMAP;
17813007Swpaul				break;
17913007Swpaul			case YP_YPERR:
18013007Swpaul			default:
181229142Sdim				yp_errno = (enum ypstat)YPXFR_YPERR;
18213007Swpaul				break;
18313007Swpaul			}
18413007Swpaul			return(NULL);
18513007Swpaul		}
18613895Swpaul		snprintf(mastername, sizeof(mastername), "%s", resp->peer);
18716132Swpaul/*		xdr_free(xdr_ypresp_master, (char *)&resp); */
18813895Swpaul		return((char *)&mastername);
18913007Swpaul	}
19013007Swpaul}
19190297Sdes
19290298Sdesunsigned long
19390298Sdesypxfr_get_order(char *domain, char *map, char *source, const int yplib)
19413007Swpaul{
19513007Swpaul	if (yplib) {
196125868Sdas		unsigned int order;
19713007Swpaul		int res;
198125868Sdas		if ((res = yp_order(domain, map, &order))) {
19913007Swpaul			switch (res) {
20013895Swpaul			case YPERR_DOMAIN:
201229142Sdim				yp_errno = (enum ypstat)YPXFR_NODOM;
20213007Swpaul				break;
20313895Swpaul			case YPERR_MAP:
204229142Sdim				yp_errno = (enum ypstat)YPXFR_NOMAP;
20513007Swpaul				break;
20613895Swpaul			case YPERR_YPERR:
20713007Swpaul			default:
208229142Sdim				yp_errno = (enum ypstat)YPXFR_YPERR;
20913007Swpaul				break;
21013007Swpaul			}
21113007Swpaul			return(0);
21213007Swpaul		} else
21313007Swpaul			return(order);
21413007Swpaul	} else {
21513007Swpaul		CLIENT *clnt;
21613007Swpaul		ypresp_order *resp;
21713007Swpaul		ypreq_nokey req;
21813007Swpaul
21913007Swpaul		if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) {
22013007Swpaul			yp_error("%s",clnt_spcreateerror("couldn't create \
22113007Swpauludp handle to ypserv"));
222229142Sdim			yp_errno = (enum ypstat)YPXFR_RPC;
22313007Swpaul			return(0);
22413007Swpaul		}
22513007Swpaul		req.map = map;
22613007Swpaul		req.domain = domain;
22713007Swpaul		if ((resp = ypproc_order_2(&req, clnt)) == NULL) {
22813007Swpaul			yp_error("%s", clnt_sperror(clnt, "YPPROC_ORDER \
22913007Swpaulfailed"));
23013007Swpaul			clnt_destroy(clnt);
231229142Sdim			yp_errno = (enum ypstat)YPXFR_RPC;
23213007Swpaul			return(0);
23313007Swpaul		}
23413007Swpaul		clnt_destroy(clnt);
23513007Swpaul		if (resp->stat != YP_TRUE) {
23613007Swpaul			switch (resp->stat) {
23713895Swpaul			case YP_NODOM:
238229142Sdim				yp_errno = (enum ypstat)YPXFR_NODOM;
23913007Swpaul				break;
24013895Swpaul			case YP_NOMAP:
241229142Sdim				yp_errno = (enum ypstat)YPXFR_NOMAP;
24213007Swpaul				break;
24313895Swpaul			case YP_YPERR:
24413007Swpaul			default:
245229142Sdim				yp_errno = (enum ypstat)YPXFR_YPERR;
24613007Swpaul				break;
24713007Swpaul			}
24813007Swpaul			return(0);
24913007Swpaul		}
25013007Swpaul		return(resp->ordernum);
25113007Swpaul	}
25213007Swpaul}
25319181Swpaul
25490298Sdesint
25590298Sdesypxfr_match(char *server, char *domain, char *map, char *key,
25690298Sdes    unsigned long keylen)
25719181Swpaul{
25819181Swpaul	ypreq_key ypkey;
25919181Swpaul	ypresp_val *ypval;
26019181Swpaul	CLIENT *clnt;
26119181Swpaul	static char buf[YPMAXRECORD + 2];
26219181Swpaul
26395658Sdes	bzero(buf, sizeof(buf));
26419181Swpaul
26519181Swpaul	if ((clnt = clnt_create(server, YPPROG,YPVERS,"udp")) == NULL) {
26619181Swpaul		yp_error("failed to create UDP handle: %s",
26719181Swpaul					clnt_spcreateerror(server));
26819181Swpaul		return(0);
26919181Swpaul	}
27019181Swpaul
27119181Swpaul	ypkey.domain = domain;
27219181Swpaul	ypkey.map = map;
27319181Swpaul	ypkey.key.keydat_len = keylen;
27419181Swpaul	ypkey.key.keydat_val = key;
27519181Swpaul
27619181Swpaul	if ((ypval = ypproc_match_2(&ypkey, clnt)) == NULL) {
27719181Swpaul		clnt_destroy(clnt);
27819181Swpaul		yp_error("%s: %s", server,
27919181Swpaul				clnt_sperror(clnt,"YPPROC_MATCH failed"));
28019181Swpaul		return(0);
28119181Swpaul	}
28219181Swpaul
28319181Swpaul	clnt_destroy(clnt);
28419181Swpaul
28519181Swpaul	if (ypval->stat != YP_TRUE) {
28695658Sdes		xdr_free((xdrproc_t)xdr_ypresp_val, ypval);
28719181Swpaul		return(0);
28819181Swpaul	}
28919181Swpaul
29095658Sdes	xdr_free((xdrproc_t)xdr_ypresp_val, ypval);
29119181Swpaul
29219181Swpaul	return(1);
29319181Swpaul}
294