xref: /illumos-gate/usr/src/lib/libnsl/yp/yp_master.c (revision 1a2d662a91cee3bf82f41cd47c7ae6f3825d9db2)
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 
23 /*
24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  * Copyright (c) 2016 by Delphix. All rights reserved.
27  */
28 
29 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /*	  All Rights Reserved   */
31 
32 /*
33  * Portions of this source code were derived from Berkeley
34  * under license from the Regents of the University of
35  * California.
36  */
37 
38 #include "mt.h"
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <rpc/rpc.h>
42 #include <sys/types.h>
43 #include "yp_b.h"
44 #include <rpcsvc/yp_prot.h>
45 #include <rpcsvc/ypclnt.h>
46 #include <string.h>
47 
48 static int domaster(char *, char *, struct dom_binding *, struct timeval,
49     char **);
50 extern int __yp_master_rsvdport(char *, char *, char **);
51 
52 /*
53  * This checks parameters, and implements the outer "until binding success"
54  * loop.
55  */
56 int
57 yp_master(char *domain, char *map, char **master)
58 {
59 	size_t domlen;
60 	size_t maplen;
61 	int reason;
62 	struct dom_binding *pdomb;
63 
64 	if ((map == NULL) || (domain == NULL))
65 		return (YPERR_BADARGS);
66 
67 	domlen = strlen(domain);
68 	maplen = strlen(map);
69 
70 	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
71 	    (maplen == 0) || (maplen > YPMAXMAP) ||
72 	    (master == NULL))
73 		return (YPERR_BADARGS);
74 
75 	for (;;) {
76 
77 		if (reason = __yp_dobind(domain, &pdomb))
78 			return (reason);
79 
80 		if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) {
81 
82 			reason = domaster(domain, map, pdomb, _ypserv_timeout,
83 			    master);
84 
85 			__yp_rel_binding(pdomb);
86 			if (reason == YPERR_RPC) {
87 				yp_unbind(domain);
88 				(void) sleep(_ypsleeptime);
89 			} else {
90 				break;
91 			}
92 		} else {
93 			__yp_rel_binding(pdomb);
94 			return (YPERR_VERS);
95 		}
96 	}
97 
98 	if (reason == YPERR_MAP && geteuid() == 0) {
99 		/*
100 		 * Lookup could be for a secure map; fail over to retry
101 		 * from a reserved port. Only useful to try this if we're
102 		 * the super user.
103 		 */
104 		int rsvdreason;
105 		rsvdreason = __yp_master_rsvdport(domain, map, master);
106 		if (rsvdreason == 0)
107 			reason = rsvdreason;
108 	}
109 
110 	return (reason);
111 }
112 
113 
114 /*
115  * This function is identical to 'yp_master' with the exception that it calls
116  * '__yp_dobind_rsvdport' rather than '__yp_dobind'
117  */
118 int
119 __yp_master_rsvdport(char *domain, char *map, char **master)
120 {
121 	size_t domlen;
122 	size_t maplen;
123 	int reason;
124 	struct dom_binding *pdomb;
125 
126 	if ((map == NULL) || (domain == NULL))
127 		return (YPERR_BADARGS);
128 
129 	domlen = strlen(domain);
130 	maplen = strlen(map);
131 
132 	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
133 	    (maplen == 0) || (maplen > YPMAXMAP) ||
134 	    (master == NULL))
135 		return (YPERR_BADARGS);
136 
137 	for (;;) {
138 
139 		if (reason = __yp_dobind_rsvdport(domain, &pdomb))
140 			return (reason);
141 
142 		if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) {
143 
144 			reason = domaster(domain, map, pdomb, _ypserv_timeout,
145 			    master);
146 
147 			/*
148 			 * Have to free the binding since the reserved
149 			 * port bindings are not cached.
150 			 */
151 			__yp_rel_binding(pdomb);
152 			free_dom_binding(pdomb);
153 			if (reason == YPERR_RPC) {
154 				yp_unbind(domain);
155 				(void) sleep(_ypsleeptime);
156 			} else {
157 				break;
158 			}
159 		} else {
160 			/*
161 			 * Have to free the binding since the reserved
162 			 * port bindings are not cached.
163 			 */
164 			__yp_rel_binding(pdomb);
165 			free_dom_binding(pdomb);
166 			return (YPERR_VERS);
167 		}
168 	}
169 	return (reason);
170 }
171 
172 /*
173  * This talks v2 to ypserv
174  */
175 static int
176 domaster(char *domain, char *map, struct dom_binding *pdomb,
177 					struct timeval timeout, char **master)
178 {
179 	struct ypreq_nokey req;
180 	struct ypresp_master resp;
181 	unsigned int retval = 0;
182 
183 	req.domain = domain;
184 	req.map = map;
185 	(void) memset(&resp, 0, sizeof (struct ypresp_master));
186 
187 	/*
188 	 * Do the get_master request.  If the rpc call failed, return with
189 	 * status from this point.
190 	 */
191 
192 	if (clnt_call(pdomb->dom_client,
193 			YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey,
194 		    (char *)&req, (xdrproc_t)xdr_ypresp_master, (char *)&resp,
195 		    timeout) != RPC_SUCCESS)
196 		return (YPERR_RPC);
197 
198 	/* See if the request succeeded */
199 
200 	if (resp.status != YP_TRUE)
201 		retval = ypprot_err(resp.status);
202 
203 	/* Get some memory which the user can get rid of as they like */
204 
205 	if (!retval && ((*master = malloc(strlen(resp.master) + 1)) == NULL))
206 		retval = YPERR_RESRC;
207 
208 	if (!retval)
209 		(void) strcpy(*master, resp.master);
210 
211 	CLNT_FREERES(pdomb->dom_client,
212 		(xdrproc_t)xdr_ypresp_master, (char *)&resp);
213 	return (retval);
214 }
215