xref: /illumos-gate/usr/src/lib/libnsl/yp/yp_master.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /*	  All Rights Reserved   */
28 
29 /*
30  * Portions of this source code were derived from Berkeley
31  * under license from the Regents of the University of
32  * California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #define	NULL 0
38 #include <rpc/rpc.h>
39 #include <sys/types.h>
40 #include <rpc/trace.h>
41 #include "yp_b.h"
42 #include <rpcsvc/yp_prot.h>
43 #include <rpcsvc/ypclnt.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 
48 static int domaster(char *, char *, struct dom_binding *, struct timeval,
49     char **);
50 int __yp_master_rsvdport();
51 
52 /*
53  * This checks parameters, and implements the outer "until binding success"
54  * loop.
55  */
56 int
57 yp_master (domain, map, master)
58 	char *domain;
59 	char *map;
60 	char **master;
61 {
62 	size_t domlen;
63 	size_t maplen;
64 	int reason;
65 	struct dom_binding *pdomb;
66 
67 	trace1(TR_yp_master, 0);
68 	if ((map == NULL) || (domain == NULL)) {
69 		trace1(TR_yp_master, 1);
70 		return (YPERR_BADARGS);
71 	}
72 
73 	domlen = strlen(domain);
74 	maplen = strlen(map);
75 
76 	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
77 	    (maplen == 0) || (maplen > YPMAXMAP) ||
78 	    (master == NULL)) {
79 		trace1(TR_yp_master, 1);
80 		return (YPERR_BADARGS);
81 	}
82 
83 	for (;;) {
84 
85 		if (reason = __yp_dobind(domain, &pdomb)) {
86 			trace1(TR_yp_master, 1);
87 			return (reason);
88 		}
89 
90 		if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) {
91 
92 			reason = domaster(domain, map, pdomb, _ypserv_timeout,
93 			    master);
94 
95 			__yp_rel_binding(pdomb);
96 			if (reason == YPERR_RPC) {
97 				yp_unbind(domain);
98 				(void) _sleep(_ypsleeptime);
99 			} else {
100 				break;
101 			}
102 		} else {
103 			__yp_rel_binding(pdomb);
104 			trace1(TR_yp_master, 1);
105 			return (YPERR_VERS);
106 		}
107 	}
108 
109 	if (reason == YPERR_MAP && geteuid() == 0) {
110 		/*
111 		 * Lookup could be for a secure map; fail over to retry
112 		 * from a reserved port. Only useful to try this if we're
113 		 * the super user.
114 		 */
115 		int rsvdreason;
116 		rsvdreason = __yp_master_rsvdport(domain, map, master);
117 		if (rsvdreason == 0)
118 			reason = rsvdreason;
119 	}
120 
121 	trace1(TR_yp_master, 1);
122 	return (reason);
123 }
124 
125 
126 /*
127  * This function is identical to 'yp_master' with the exception that it calls
128  * '__yp_dobind_rsvdport' rather than '__yp_dobind'
129  */
130 int
131 __yp_master_rsvdport (domain, map, master)
132 	char *domain;
133 	char *map;
134 	char **master;
135 {
136 	size_t domlen;
137 	size_t maplen;
138 	int reason;
139 	struct dom_binding *pdomb;
140 
141 	trace1(TR_yp_master, 0);
142 	if ((map == NULL) || (domain == NULL)) {
143 		trace1(TR_yp_master, 1);
144 		return (YPERR_BADARGS);
145 	}
146 
147 	domlen = strlen(domain);
148 	maplen = strlen(map);
149 
150 	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
151 	    (maplen == 0) || (maplen > YPMAXMAP) ||
152 	    (master == NULL)) {
153 		trace1(TR_yp_master, 1);
154 		return (YPERR_BADARGS);
155 	}
156 
157 	for (;;) {
158 
159 		if (reason = __yp_dobind_rsvdport(domain, &pdomb)) {
160 			trace1(TR_yp_master, 1);
161 			return (reason);
162 		}
163 
164 		if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) {
165 
166 			reason = domaster(domain, map, pdomb, _ypserv_timeout,
167 			    master);
168 
169 			/*
170 			 * Have to free the binding since the reserved
171 			 * port bindings are not cached.
172 			 */
173 			__yp_rel_binding(pdomb);
174 			free_dom_binding(pdomb);
175 			if (reason == YPERR_RPC) {
176 				yp_unbind(domain);
177 				(void) _sleep(_ypsleeptime);
178 			} else {
179 				break;
180 			}
181 		} else {
182 			/*
183 			 * Have to free the binding since the reserved
184 			 * port bindings are not cached.
185 			 */
186 			__yp_rel_binding(pdomb);
187 			free_dom_binding(pdomb);
188 			trace1(TR_yp_master, 1);
189 			return (YPERR_VERS);
190 		}
191 	}
192 
193 	trace1(TR_yp_master, 1);
194 	return (reason);
195 }
196 
197 /*
198  * This talks v2 to ypserv
199  */
200 static int
201 domaster (domain, map, pdomb, timeout, master)
202 	char *domain;
203 	char *map;
204 	struct dom_binding *pdomb;
205 	struct timeval timeout;
206 	char **master;
207 {
208 	struct ypreq_nokey req;
209 	struct ypresp_master resp;
210 	unsigned int retval = 0;
211 
212 	trace1(TR_domaster, 0);
213 	req.domain = domain;
214 	req.map = map;
215 	(void) memset((char *) &resp, 0, sizeof (struct ypresp_master));
216 
217 	/*
218 	 * Do the get_master request.  If the rpc call failed, return with
219 	 * status from this point.
220 	 */
221 
222 	if (clnt_call(pdomb->dom_client,
223 			YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey,
224 		    (char *)&req, (xdrproc_t)xdr_ypresp_master, (char *)&resp,
225 		    timeout) != RPC_SUCCESS) {
226 		trace1(TR_domaster, 1);
227 		return (YPERR_RPC);
228 	}
229 
230 	/* See if the request succeeded */
231 
232 	if (resp.status != YP_TRUE) {
233 		retval = ypprot_err(resp.status);
234 	}
235 
236 	/* Get some memory which the user can get rid of as he likes */
237 
238 	if (!retval && ((*master = malloc(strlen(resp.master) + 1))
239 	    == NULL)) {
240 		retval = YPERR_RESRC;
241 
242 	}
243 
244 	if (!retval) {
245 		(void) strcpy(*master, resp.master);
246 	}
247 
248 	CLNT_FREERES(pdomb->dom_client,
249 		(xdrproc_t)xdr_ypresp_master, (char *)&resp);
250 	trace1(TR_domaster, 1);
251 	return (retval);
252 }
253