xref: /freebsd/libexec/ypxfr/ypxfr_misc.c (revision f5147e312f43a9050468de539aeafa072caa1a60)
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 
48 const char *
49 ypxfrerr_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  */
122 char *
123 ypxfr_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 \
158 create 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 \
167 failed"));
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 
194 unsigned long
195 ypxfr_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 \
223 udp 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 \
231 failed"));
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 
256 int
257 ypxfr_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