10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
21132Srobinson */
22132Srobinson
23132Srobinson /*
24*1219Sraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
250Sstevel@tonic-gate * Use is subject to license terms.
260Sstevel@tonic-gate */
270Sstevel@tonic-gate
280Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
290Sstevel@tonic-gate /* All Rights Reserved */
300Sstevel@tonic-gate
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate * Portions of this source code were derived from Berkeley
330Sstevel@tonic-gate * under license from the Regents of the University of
340Sstevel@tonic-gate * California.
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
370Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
380Sstevel@tonic-gate
39*1219Sraf #include "mt.h"
40132Srobinson #include <stdlib.h>
41132Srobinson #include <unistd.h>
420Sstevel@tonic-gate #include <rpc/rpc.h>
430Sstevel@tonic-gate #include <syslog.h>
440Sstevel@tonic-gate #include "yp_b.h"
450Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
460Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
470Sstevel@tonic-gate #include <netdir.h>
480Sstevel@tonic-gate #include <string.h>
490Sstevel@tonic-gate
500Sstevel@tonic-gate extern int __yp_dobind_cflookup(char *, struct dom_binding **, int);
510Sstevel@tonic-gate
520Sstevel@tonic-gate static struct timeval tp_timout = { 120, 0};
530Sstevel@tonic-gate static char nullstring[] = "\000";
540Sstevel@tonic-gate
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * __yp_all_cflookup() is a variant of the yp_all() code,
570Sstevel@tonic-gate * which adds a 'hardlookup' parameter. This parameter is passed
580Sstevel@tonic-gate * to __yp_dobind_cflookup(), and determines whether the server
590Sstevel@tonic-gate * binding attempt is hard (try forever) of soft (retry a compiled-
600Sstevel@tonic-gate * in number of times).
610Sstevel@tonic-gate */
620Sstevel@tonic-gate int
__yp_all_cflookup(char * domain,char * map,struct ypall_callback * callback,int hardlookup)63132Srobinson __yp_all_cflookup(char *domain, char *map, struct ypall_callback *callback,
64132Srobinson int hardlookup)
650Sstevel@tonic-gate {
660Sstevel@tonic-gate size_t domlen;
670Sstevel@tonic-gate size_t maplen;
680Sstevel@tonic-gate struct ypreq_nokey req;
690Sstevel@tonic-gate int reason;
700Sstevel@tonic-gate struct dom_binding *pdomb;
710Sstevel@tonic-gate enum clnt_stat s;
720Sstevel@tonic-gate CLIENT *allc;
730Sstevel@tonic-gate char server_name[MAXHOSTNAMELEN];
740Sstevel@tonic-gate char errbuf[BUFSIZ];
750Sstevel@tonic-gate
76132Srobinson if ((map == NULL) || (domain == NULL))
770Sstevel@tonic-gate return (YPERR_BADARGS);
780Sstevel@tonic-gate
790Sstevel@tonic-gate domlen = strlen(domain);
800Sstevel@tonic-gate maplen = strlen(map);
810Sstevel@tonic-gate
820Sstevel@tonic-gate if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
830Sstevel@tonic-gate (maplen == 0) || (maplen > YPMAXMAP) ||
84132Srobinson (callback == NULL))
850Sstevel@tonic-gate return (YPERR_BADARGS);
860Sstevel@tonic-gate
87132Srobinson if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
880Sstevel@tonic-gate return (reason);
890Sstevel@tonic-gate
900Sstevel@tonic-gate if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) {
910Sstevel@tonic-gate __yp_rel_binding(pdomb);
920Sstevel@tonic-gate return (YPERR_VERS);
930Sstevel@tonic-gate }
94132Srobinson (void) mutex_lock(&pdomb->server_name_lock);
950Sstevel@tonic-gate if (!pdomb->dom_binding->ypbind_servername) {
96132Srobinson (void) mutex_unlock(&pdomb->server_name_lock);
970Sstevel@tonic-gate __yp_rel_binding(pdomb);
980Sstevel@tonic-gate syslog(LOG_ERR, "yp_all: failed to get server's name\n");
990Sstevel@tonic-gate return (YPERR_RPC);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate (void) strcpy(server_name, pdomb->dom_binding->ypbind_servername);
102132Srobinson (void) mutex_unlock(&pdomb->server_name_lock);
1030Sstevel@tonic-gate if (strcmp(server_name, nullstring) == 0) {
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate * This is the case where ypbind is running in broadcast mode,
1060Sstevel@tonic-gate * we have to do the jugglery to get the
1070Sstevel@tonic-gate * ypserv's address on COTS transport based
1080Sstevel@tonic-gate * on the CLTS address ypbind gave us !
1090Sstevel@tonic-gate */
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate struct nd_hostservlist *nhs;
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate if (netdir_getbyaddr(pdomb->dom_binding->ypbind_nconf,
1140Sstevel@tonic-gate &nhs, pdomb->dom_binding->ypbind_svcaddr) != ND_OK) {
1150Sstevel@tonic-gate syslog(LOG_ERR,
1160Sstevel@tonic-gate "yp_all: failed to get server's name\n");
1170Sstevel@tonic-gate __yp_rel_binding(pdomb);
1180Sstevel@tonic-gate return (YPERR_RPC);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate /* check server name again, some other thread may have set it */
121132Srobinson (void) mutex_lock(&pdomb->server_name_lock);
1220Sstevel@tonic-gate if (strcmp(pdomb->dom_binding->ypbind_servername,
1230Sstevel@tonic-gate nullstring) == 0) {
1240Sstevel@tonic-gate pdomb->dom_binding->ypbind_servername =
1250Sstevel@tonic-gate (char *)strdup(nhs->h_hostservs->h_host);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate (void) strcpy(server_name,
1280Sstevel@tonic-gate pdomb->dom_binding->ypbind_servername);
129132Srobinson (void) mutex_unlock(&pdomb->server_name_lock);
1300Sstevel@tonic-gate netdir_free((char *)nhs, ND_HOSTSERVLIST);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate __yp_rel_binding(pdomb);
1330Sstevel@tonic-gate if ((allc = clnt_create(server_name, YPPROG,
134132Srobinson YPVERS, "circuit_n")) == NULL) {
135132Srobinson (void) snprintf(errbuf, BUFSIZ, "yp_all \
1360Sstevel@tonic-gate - transport level create failure for domain %s / map %s", domain, map);
137132Srobinson syslog(LOG_ERR, "%s", clnt_spcreateerror(errbuf));
1380Sstevel@tonic-gate return (YPERR_RPC);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate req.domain = domain;
1420Sstevel@tonic-gate req.map = map;
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate s = clnt_call(allc, YPPROC_ALL,
1460Sstevel@tonic-gate (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
1470Sstevel@tonic-gate (xdrproc_t)xdr_ypall, (char *)callback, tp_timout);
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate if (s != RPC_SUCCESS && s != RPC_TIMEDOUT) {
150132Srobinson syslog(LOG_ERR, "%s", clnt_sperror(allc,
1510Sstevel@tonic-gate "yp_all - RPC clnt_call (transport level) failure"));
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate clnt_destroy(allc);
1550Sstevel@tonic-gate switch (s) {
1560Sstevel@tonic-gate case RPC_SUCCESS:
1570Sstevel@tonic-gate return (0);
1580Sstevel@tonic-gate case RPC_TIMEDOUT:
1590Sstevel@tonic-gate return (YPERR_YPSERV);
1600Sstevel@tonic-gate default:
1610Sstevel@tonic-gate return (YPERR_RPC);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate /*
1670Sstevel@tonic-gate * This does the "glommed enumeration" stuff. callback->foreach is the name
1680Sstevel@tonic-gate * of a function which gets called per decoded key-value pair:
1690Sstevel@tonic-gate *
1700Sstevel@tonic-gate * (*callback->foreach)(status, key, keylen, val, vallen, callback->data);
1710Sstevel@tonic-gate *
1720Sstevel@tonic-gate * If the server we get back from __yp_dobind speaks the old protocol, this
1730Sstevel@tonic-gate * returns YPERR_VERS, and does not attempt to emulate the new functionality
1740Sstevel@tonic-gate * by using the old protocol.
1750Sstevel@tonic-gate */
1760Sstevel@tonic-gate int
yp_all(char * domain,char * map,struct ypall_callback * callback)177132Srobinson yp_all(char *domain, char *map, struct ypall_callback *callback)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate return (__yp_all_cflookup(domain, map, callback, 1));
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate /*
1840Sstevel@tonic-gate * This function is identical to 'yp_all' with the exception that it
1850Sstevel@tonic-gate * attempts to use reserve ports.
1860Sstevel@tonic-gate */
1870Sstevel@tonic-gate int
__yp_all_rsvdport(char * domain,char * map,struct ypall_callback * callback)188132Srobinson __yp_all_rsvdport(char *domain, char *map, struct ypall_callback *callback)
1890Sstevel@tonic-gate {
1900Sstevel@tonic-gate size_t domlen;
1910Sstevel@tonic-gate size_t maplen;
1920Sstevel@tonic-gate struct ypreq_nokey req;
1930Sstevel@tonic-gate int reason;
1940Sstevel@tonic-gate struct dom_binding *pdomb;
1950Sstevel@tonic-gate enum clnt_stat s;
1960Sstevel@tonic-gate CLIENT *allc;
1970Sstevel@tonic-gate char server_name[MAXHOSTNAMELEN];
1980Sstevel@tonic-gate char errbuf[BUFSIZ];
1990Sstevel@tonic-gate
200132Srobinson if ((map == NULL) || (domain == NULL))
2010Sstevel@tonic-gate return (YPERR_BADARGS);
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate domlen = strlen(domain);
2040Sstevel@tonic-gate maplen = strlen(map);
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
2070Sstevel@tonic-gate (maplen == 0) || (maplen > YPMAXMAP) ||
208132Srobinson (callback == NULL))
2090Sstevel@tonic-gate return (YPERR_BADARGS);
2100Sstevel@tonic-gate
211132Srobinson if (reason = __yp_dobind_rsvdport(domain, &pdomb))
2120Sstevel@tonic-gate return (reason);
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) {
2150Sstevel@tonic-gate /*
2160Sstevel@tonic-gate * Have to free the binding since the reserved
2170Sstevel@tonic-gate * port bindings are not cached.
2180Sstevel@tonic-gate */
2190Sstevel@tonic-gate __yp_rel_binding(pdomb);
2200Sstevel@tonic-gate free_dom_binding(pdomb);
2210Sstevel@tonic-gate return (YPERR_VERS);
2220Sstevel@tonic-gate }
223132Srobinson (void) mutex_lock(&pdomb->server_name_lock);
2240Sstevel@tonic-gate if (!pdomb->dom_binding->ypbind_servername) {
225132Srobinson (void) mutex_unlock(&pdomb->server_name_lock);
2260Sstevel@tonic-gate syslog(LOG_ERR, "yp_all: failed to get server's name\n");
2270Sstevel@tonic-gate __yp_rel_binding(pdomb);
2280Sstevel@tonic-gate free_dom_binding(pdomb);
2290Sstevel@tonic-gate return (YPERR_RPC);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate (void) strcpy(server_name, pdomb->dom_binding->ypbind_servername);
232132Srobinson (void) mutex_unlock(&pdomb->server_name_lock);
2330Sstevel@tonic-gate if (strcmp(server_name, nullstring) == 0) {
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * This is the case where ypbind is running in broadcast mode,
2360Sstevel@tonic-gate * we have to do the jugglery to get the
2370Sstevel@tonic-gate * ypserv's address on COTS transport based
2380Sstevel@tonic-gate * on the CLTS address ypbind gave us !
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate struct nd_hostservlist *nhs;
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate if (netdir_getbyaddr(pdomb->dom_binding->ypbind_nconf,
2440Sstevel@tonic-gate &nhs, pdomb->dom_binding->ypbind_svcaddr) != ND_OK) {
2450Sstevel@tonic-gate syslog(LOG_ERR,
2460Sstevel@tonic-gate "yp_all: failed to get server's name\n");
2470Sstevel@tonic-gate __yp_rel_binding(pdomb);
2480Sstevel@tonic-gate free_dom_binding(pdomb);
2490Sstevel@tonic-gate return (YPERR_RPC);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate /* check server name again, some other thread may have set it */
252132Srobinson (void) mutex_lock(&pdomb->server_name_lock);
2530Sstevel@tonic-gate if (strcmp(pdomb->dom_binding->ypbind_servername,
2540Sstevel@tonic-gate nullstring) == 0) {
2550Sstevel@tonic-gate pdomb->dom_binding->ypbind_servername =
2560Sstevel@tonic-gate (char *)strdup(nhs->h_hostservs->h_host);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate (void) strcpy(server_name,
2590Sstevel@tonic-gate pdomb->dom_binding->ypbind_servername);
260132Srobinson (void) mutex_unlock(&pdomb->server_name_lock);
2610Sstevel@tonic-gate netdir_free((char *)nhs, ND_HOSTSERVLIST);
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate __yp_rel_binding(pdomb);
2650Sstevel@tonic-gate if ((allc = __yp_clnt_create_rsvdport(server_name, YPPROG, YPVERS,
266132Srobinson "tcp6", 0, 0)) == NULL &&
2670Sstevel@tonic-gate (allc = __yp_clnt_create_rsvdport(server_name, YPPROG, YPVERS,
268132Srobinson "tcp", 0, 0)) == NULL) {
269132Srobinson (void) snprintf(errbuf, BUFSIZ, "yp_all \
2700Sstevel@tonic-gate - transport level create failure for domain %s / map %s", domain, map);
271132Srobinson syslog(LOG_ERR, "%s", clnt_spcreateerror(errbuf));
2720Sstevel@tonic-gate free_dom_binding(pdomb);
2730Sstevel@tonic-gate return (YPERR_RPC);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate req.domain = domain;
2770Sstevel@tonic-gate req.map = map;
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate s = clnt_call(allc, YPPROC_ALL,
2800Sstevel@tonic-gate (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
2810Sstevel@tonic-gate (xdrproc_t)xdr_ypall, (char *)callback, tp_timout);
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate if (s != RPC_SUCCESS && s != RPC_TIMEDOUT) {
284132Srobinson syslog(LOG_ERR, "%s", clnt_sperror(allc,
2850Sstevel@tonic-gate "yp_all - RPC clnt_call (transport level) failure"));
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate clnt_destroy(allc);
2890Sstevel@tonic-gate free_dom_binding(pdomb);
2900Sstevel@tonic-gate switch (s) {
2910Sstevel@tonic-gate case RPC_SUCCESS:
2920Sstevel@tonic-gate return (0);
2930Sstevel@tonic-gate case RPC_TIMEDOUT:
2940Sstevel@tonic-gate return (YPERR_YPSERV);
2950Sstevel@tonic-gate default:
2960Sstevel@tonic-gate return (YPERR_RPC);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate }
299