1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 1995
5 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#include <stdio.h>
39#include <string.h>
40#include <stdlib.h>
41#include <unistd.h>
42#include <sys/param.h>
43#include <rpc/rpc.h>
44#include <rpcsvc/yp.h>
45#include <rpcsvc/ypclnt.h>
46#include "ypxfr_extern.h"
47
48const char *
49ypxfrerr_string(ypxfrstat code)
50{
51	switch (code) {
52	case YPXFR_SUCC:
53		return ("Map successfully transferred");
54		break;
55	case YPXFR_AGE:
56		return ("Master's version not newer");
57		break;
58	case YPXFR_NOMAP:
59		return ("No such map in server's domain");
60		break;
61	case YPXFR_NODOM:
62		return ("Domain not supported by server");
63		break;
64	case YPXFR_RSRC:
65		return ("Local resource allocation failure");
66		break;
67	case YPXFR_RPC:
68		return ("RPC failure talking to server");
69		break;
70	case YPXFR_MADDR:
71		return ("Could not get master server address");
72		break;
73	case YPXFR_YPERR:
74		return ("NIS server/map database error");
75		break;
76	case YPXFR_BADARGS:
77		return ("Request arguments bad");
78		break;
79	case YPXFR_DBM:
80		return ("Local database operation failed");
81		break;
82	case YPXFR_FILE:
83		return ("Local file I/O operation failed");
84		break;
85	case YPXFR_SKEW:
86		return ("Map version skew during transfer");
87		break;
88	case YPXFR_CLEAR:
89		return ("Couldn't send \"clear\" request to local ypserv");
90		break;
91	case YPXFR_FORCE:
92		return ("No local order number in map -- use -f flag");
93		break;
94	case YPXFR_XFRERR:
95		return ("General ypxfr error");
96		break;
97	case YPXFR_REFUSED:
98		return ("Transfer request refused by ypserv");
99		break;
100	default:
101		return ("Unknown error code");
102		break;
103	}
104}
105
106/*
107 * These are wrappers for the usual yp_master() and yp_order() functions.
108 * They can use either local yplib functions (the real yp_master() and
109 * yp_order()) or do direct RPCs to a specified server. The latter is
110 * necessary if ypxfr is run on a machine that isn't configured as an
111 * NIS client (this can happen very easily: a given machine need not be
112 * an NIS client in order to be an NIS server).
113 */
114
115/*
116 * Careful: yp_master() returns a pointer to a dynamically allocated
117 * buffer. Calling ypproc_master_2() ourselves also returns a pointer
118 * to dynamically allocated memory, though this time it's memory
119 * allocated by the XDR routines. We have to rememver to free() or
120 * xdr_free() the memory as required to avoid leaking memory.
121 */
122char *
123ypxfr_get_master(char *domain, char *map, char *source, const int yplib)
124{
125	static char mastername[MAXPATHLEN + 2];
126
127	bzero((char *)&mastername, sizeof(mastername));
128
129	if (yplib) {
130		int res;
131		char *master;
132		if ((res = yp_master(domain, map, &master))) {
133			switch (res) {
134			case YPERR_DOMAIN:
135				yp_errno = (enum ypstat)YPXFR_NODOM;
136				break;
137			case YPERR_MAP:
138				yp_errno = (enum ypstat)YPXFR_NOMAP;
139				break;
140			case YPERR_YPERR:
141			default:
142				yp_errno = (enum ypstat)YPXFR_YPERR;
143				break;
144			}
145			return(NULL);
146		} else {
147			snprintf(mastername, sizeof(mastername), "%s", master);
148			free(master);
149			return((char *)&mastername);
150		}
151	} else {
152		CLIENT *clnt;
153		ypresp_master *resp;
154		ypreq_nokey req;
155
156		if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) {
157			yp_error("%s",clnt_spcreateerror("failed to \
158create udp handle to ypserv"));
159			yp_errno = (enum ypstat)YPXFR_RPC;
160			return(NULL);
161		}
162
163		req.map = map;
164		req.domain = domain;
165		if ((resp = ypproc_master_2(&req, clnt)) == NULL) {
166			yp_error("%s",clnt_sperror(clnt,"YPPROC_MASTER \
167failed"));
168			clnt_destroy(clnt);
169			yp_errno = (enum ypstat)YPXFR_RPC;
170			return(NULL);
171		}
172		clnt_destroy(clnt);
173		if (resp->stat != YP_TRUE) {
174			switch (resp->stat) {
175			case YP_NODOM:
176				yp_errno = (enum ypstat)YPXFR_NODOM;
177				break;
178			case YP_NOMAP:
179				yp_errno = (enum ypstat)YPXFR_NOMAP;
180				break;
181			case YP_YPERR:
182			default:
183				yp_errno = (enum ypstat)YPXFR_YPERR;
184				break;
185			}
186			return(NULL);
187		}
188		snprintf(mastername, sizeof(mastername), "%s", resp->peer);
189/*		xdr_free(xdr_ypresp_master, (char *)&resp); */
190		return((char *)&mastername);
191	}
192}
193
194unsigned long
195ypxfr_get_order(char *domain, char *map, char *source, const int yplib)
196{
197	if (yplib) {
198		unsigned int order;
199		int res;
200		if ((res = yp_order(domain, map, &order))) {
201			switch (res) {
202			case YPERR_DOMAIN:
203				yp_errno = (enum ypstat)YPXFR_NODOM;
204				break;
205			case YPERR_MAP:
206				yp_errno = (enum ypstat)YPXFR_NOMAP;
207				break;
208			case YPERR_YPERR:
209			default:
210				yp_errno = (enum ypstat)YPXFR_YPERR;
211				break;
212			}
213			return(0);
214		} else
215			return(order);
216	} else {
217		CLIENT *clnt;
218		ypresp_order *resp;
219		ypreq_nokey req;
220
221		if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) {
222			yp_error("%s",clnt_spcreateerror("couldn't create \
223udp handle to ypserv"));
224			yp_errno = (enum ypstat)YPXFR_RPC;
225			return(0);
226		}
227		req.map = map;
228		req.domain = domain;
229		if ((resp = ypproc_order_2(&req, clnt)) == NULL) {
230			yp_error("%s", clnt_sperror(clnt, "YPPROC_ORDER \
231failed"));
232			clnt_destroy(clnt);
233			yp_errno = (enum ypstat)YPXFR_RPC;
234			return(0);
235		}
236		clnt_destroy(clnt);
237		if (resp->stat != YP_TRUE) {
238			switch (resp->stat) {
239			case YP_NODOM:
240				yp_errno = (enum ypstat)YPXFR_NODOM;
241				break;
242			case YP_NOMAP:
243				yp_errno = (enum ypstat)YPXFR_NOMAP;
244				break;
245			case YP_YPERR:
246			default:
247				yp_errno = (enum ypstat)YPXFR_YPERR;
248				break;
249			}
250			return(0);
251		}
252		return(resp->ordernum);
253	}
254}
255
256int
257ypxfr_match(char *server, char *domain, char *map, char *key,
258    unsigned long keylen)
259{
260	ypreq_key ypkey;
261	ypresp_val *ypval;
262	CLIENT *clnt;
263	static char buf[YPMAXRECORD + 2];
264
265	bzero(buf, sizeof(buf));
266
267	if ((clnt = clnt_create(server, YPPROG,YPVERS,"udp")) == NULL) {
268		yp_error("failed to create UDP handle: %s",
269					clnt_spcreateerror(server));
270		return(0);
271	}
272
273	ypkey.domain = domain;
274	ypkey.map = map;
275	ypkey.key.keydat_len = keylen;
276	ypkey.key.keydat_val = key;
277
278	if ((ypval = ypproc_match_2(&ypkey, clnt)) == NULL) {
279		clnt_destroy(clnt);
280		yp_error("%s: %s", server,
281				clnt_sperror(clnt,"YPPROC_MATCH failed"));
282		return(0);
283	}
284
285	clnt_destroy(clnt);
286
287	if (ypval->stat != YP_TRUE) {
288		xdr_free((xdrproc_t)xdr_ypresp_val, ypval);
289		return(0);
290	}
291
292	xdr_free((xdrproc_t)xdr_ypresp_val, ypval);
293
294	return(1);
295}
296