import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / nsl / yp_all.c
blobdda70b58fe2f12db486e8e0aeb88c419e76785aa
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * Portions of this source code were derived from Berkeley
33 * under license from the Regents of the University of
34 * California.
37 #pragma ident "%Z%%M% %I% %E% SMI"
39 #include "mt.h"
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <rpc/rpc.h>
43 #include <syslog.h>
44 #include "yp_b.h"
45 #include <rpcsvc/yp_prot.h>
46 #include <rpcsvc/ypclnt.h>
47 #include <netdir.h>
48 #include <string.h>
50 extern int __yp_dobind_cflookup(char *, struct dom_binding **, int);
52 static struct timeval tp_timout = { 120, 0};
53 static char nullstring[] = "\000";
56 * __yp_all_cflookup() is a variant of the yp_all() code,
57 * which adds a 'hardlookup' parameter. This parameter is passed
58 * to __yp_dobind_cflookup(), and determines whether the server
59 * binding attempt is hard (try forever) of soft (retry a compiled-
60 * in number of times).
62 int
63 __yp_all_cflookup(char *domain, char *map, struct ypall_callback *callback,
64 int hardlookup)
66 size_t domlen;
67 size_t maplen;
68 struct ypreq_nokey req;
69 int reason;
70 struct dom_binding *pdomb;
71 enum clnt_stat s;
72 CLIENT *allc;
73 char server_name[MAXHOSTNAMELEN];
74 char errbuf[BUFSIZ];
76 if ((map == NULL) || (domain == NULL))
77 return (YPERR_BADARGS);
79 domlen = strlen(domain);
80 maplen = strlen(map);
82 if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
83 (maplen == 0) || (maplen > YPMAXMAP) ||
84 (callback == NULL))
85 return (YPERR_BADARGS);
87 if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
88 return (reason);
90 if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) {
91 __yp_rel_binding(pdomb);
92 return (YPERR_VERS);
94 (void) mutex_lock(&pdomb->server_name_lock);
95 if (!pdomb->dom_binding->ypbind_servername) {
96 (void) mutex_unlock(&pdomb->server_name_lock);
97 __yp_rel_binding(pdomb);
98 syslog(LOG_ERR, "yp_all: failed to get server's name\n");
99 return (YPERR_RPC);
101 (void) strcpy(server_name, pdomb->dom_binding->ypbind_servername);
102 (void) mutex_unlock(&pdomb->server_name_lock);
103 if (strcmp(server_name, nullstring) == 0) {
105 * This is the case where ypbind is running in broadcast mode,
106 * we have to do the jugglery to get the
107 * ypserv's address on COTS transport based
108 * on the CLTS address ypbind gave us !
111 struct nd_hostservlist *nhs;
113 if (netdir_getbyaddr(pdomb->dom_binding->ypbind_nconf,
114 &nhs, pdomb->dom_binding->ypbind_svcaddr) != ND_OK) {
115 syslog(LOG_ERR,
116 "yp_all: failed to get server's name\n");
117 __yp_rel_binding(pdomb);
118 return (YPERR_RPC);
120 /* check server name again, some other thread may have set it */
121 (void) mutex_lock(&pdomb->server_name_lock);
122 if (strcmp(pdomb->dom_binding->ypbind_servername,
123 nullstring) == 0) {
124 pdomb->dom_binding->ypbind_servername =
125 (char *)strdup(nhs->h_hostservs->h_host);
127 (void) strcpy(server_name,
128 pdomb->dom_binding->ypbind_servername);
129 (void) mutex_unlock(&pdomb->server_name_lock);
130 netdir_free((char *)nhs, ND_HOSTSERVLIST);
132 __yp_rel_binding(pdomb);
133 if ((allc = clnt_create(server_name, YPPROG,
134 YPVERS, "circuit_n")) == NULL) {
135 (void) snprintf(errbuf, BUFSIZ, "yp_all \
136 - transport level create failure for domain %s / map %s", domain, map);
137 syslog(LOG_ERR, "%s", clnt_spcreateerror(errbuf));
138 return (YPERR_RPC);
141 req.domain = domain;
142 req.map = map;
145 s = clnt_call(allc, YPPROC_ALL,
146 (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
147 (xdrproc_t)xdr_ypall, (char *)callback, tp_timout);
149 if (s != RPC_SUCCESS && s != RPC_TIMEDOUT) {
150 syslog(LOG_ERR, "%s", clnt_sperror(allc,
151 "yp_all - RPC clnt_call (transport level) failure"));
154 clnt_destroy(allc);
155 switch (s) {
156 case RPC_SUCCESS:
157 return (0);
158 case RPC_TIMEDOUT:
159 return (YPERR_YPSERV);
160 default:
161 return (YPERR_RPC);
167 * This does the "glommed enumeration" stuff. callback->foreach is the name
168 * of a function which gets called per decoded key-value pair:
170 * (*callback->foreach)(status, key, keylen, val, vallen, callback->data);
172 * If the server we get back from __yp_dobind speaks the old protocol, this
173 * returns YPERR_VERS, and does not attempt to emulate the new functionality
174 * by using the old protocol.
177 yp_all(char *domain, char *map, struct ypall_callback *callback)
179 return (__yp_all_cflookup(domain, map, callback, 1));
184 * This function is identical to 'yp_all' with the exception that it
185 * attempts to use reserve ports.
188 __yp_all_rsvdport(char *domain, char *map, struct ypall_callback *callback)
190 size_t domlen;
191 size_t maplen;
192 struct ypreq_nokey req;
193 int reason;
194 struct dom_binding *pdomb;
195 enum clnt_stat s;
196 CLIENT *allc;
197 char server_name[MAXHOSTNAMELEN];
198 char errbuf[BUFSIZ];
200 if ((map == NULL) || (domain == NULL))
201 return (YPERR_BADARGS);
203 domlen = strlen(domain);
204 maplen = strlen(map);
206 if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
207 (maplen == 0) || (maplen > YPMAXMAP) ||
208 (callback == NULL))
209 return (YPERR_BADARGS);
211 if (reason = __yp_dobind_rsvdport(domain, &pdomb))
212 return (reason);
214 if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) {
216 * Have to free the binding since the reserved
217 * port bindings are not cached.
219 __yp_rel_binding(pdomb);
220 free_dom_binding(pdomb);
221 return (YPERR_VERS);
223 (void) mutex_lock(&pdomb->server_name_lock);
224 if (!pdomb->dom_binding->ypbind_servername) {
225 (void) mutex_unlock(&pdomb->server_name_lock);
226 syslog(LOG_ERR, "yp_all: failed to get server's name\n");
227 __yp_rel_binding(pdomb);
228 free_dom_binding(pdomb);
229 return (YPERR_RPC);
231 (void) strcpy(server_name, pdomb->dom_binding->ypbind_servername);
232 (void) mutex_unlock(&pdomb->server_name_lock);
233 if (strcmp(server_name, nullstring) == 0) {
235 * This is the case where ypbind is running in broadcast mode,
236 * we have to do the jugglery to get the
237 * ypserv's address on COTS transport based
238 * on the CLTS address ypbind gave us !
241 struct nd_hostservlist *nhs;
243 if (netdir_getbyaddr(pdomb->dom_binding->ypbind_nconf,
244 &nhs, pdomb->dom_binding->ypbind_svcaddr) != ND_OK) {
245 syslog(LOG_ERR,
246 "yp_all: failed to get server's name\n");
247 __yp_rel_binding(pdomb);
248 free_dom_binding(pdomb);
249 return (YPERR_RPC);
251 /* check server name again, some other thread may have set it */
252 (void) mutex_lock(&pdomb->server_name_lock);
253 if (strcmp(pdomb->dom_binding->ypbind_servername,
254 nullstring) == 0) {
255 pdomb->dom_binding->ypbind_servername =
256 (char *)strdup(nhs->h_hostservs->h_host);
258 (void) strcpy(server_name,
259 pdomb->dom_binding->ypbind_servername);
260 (void) mutex_unlock(&pdomb->server_name_lock);
261 netdir_free((char *)nhs, ND_HOSTSERVLIST);
264 __yp_rel_binding(pdomb);
265 if ((allc = __yp_clnt_create_rsvdport(server_name, YPPROG, YPVERS,
266 "tcp6", 0, 0)) == NULL &&
267 (allc = __yp_clnt_create_rsvdport(server_name, YPPROG, YPVERS,
268 "tcp", 0, 0)) == NULL) {
269 (void) snprintf(errbuf, BUFSIZ, "yp_all \
270 - transport level create failure for domain %s / map %s", domain, map);
271 syslog(LOG_ERR, "%s", clnt_spcreateerror(errbuf));
272 free_dom_binding(pdomb);
273 return (YPERR_RPC);
276 req.domain = domain;
277 req.map = map;
279 s = clnt_call(allc, YPPROC_ALL,
280 (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
281 (xdrproc_t)xdr_ypall, (char *)callback, tp_timout);
283 if (s != RPC_SUCCESS && s != RPC_TIMEDOUT) {
284 syslog(LOG_ERR, "%s", clnt_sperror(allc,
285 "yp_all - RPC clnt_call (transport level) failure"));
288 clnt_destroy(allc);
289 free_dom_binding(pdomb);
290 switch (s) {
291 case RPC_SUCCESS:
292 return (0);
293 case RPC_TIMEDOUT:
294 return (YPERR_YPSERV);
295 default:
296 return (YPERR_RPC);