yp_all.c revision 1219:f89f56c2d9ac
149594Simp/* 249593Simp * CDDL HEADER START 3139815Simp * 449593Simp * The contents of this file are subject to the terms of the 549593Simp * Common Development and Distribution License, Version 1.0 only 649593Simp * (the "License"). You may not use this file except in compliance 749593Simp * with the License. 849593Simp * 949593Simp * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1049593Simp * or http://www.opensolaris.org/os/licensing. 1149593Simp * See the License for the specific language governing permissions 1249593Simp * and limitations under the License. 1349593Simp * 1449593Simp * When distributing Covered Code, include this CDDL HEADER in each 1549593Simp * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1649593Simp * If applicable, add the following below this CDDL HEADER, with the 1749593Simp * fields enclosed by brackets "[]" replaced with your own identifying 1849593Simp * information: Portions Copyright [yyyy] [name of copyright owner] 1949593Simp * 2049593Simp * CDDL HEADER END 2149593Simp */ 2249593Simp 2349593Simp/* 2449593Simp * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2549593Simp * Use is subject to license terms. 2649593Simp */ 2749593Simp 2849593Simp/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 2949593Simp/* All Rights Reserved */ 3049593Simp 31141209Sru/* 3249593Simp * Portions of this source code were derived from Berkeley 3386170Sobrien * under license from the Regents of the University of 3486170Sobrien * California. 3549593Simp */ 3649593Simp 37103000Speter#pragma ident "%Z%%M% %I% %E% SMI" 3849593Simp 3949593Simp#include "mt.h" 4049593Simp#include <stdlib.h> 4149593Simp#include <unistd.h> 4271191Sjedgar#include <rpc/rpc.h> 4380274Skris#include <syslog.h> 4480274Skris#include "yp_b.h" 4549593Simp#include <rpcsvc/yp_prot.h> 4680274Skris#include <rpcsvc/ypclnt.h> 4780274Skris#include <netdir.h> 4849593Simp#include <string.h> 4949593Simp 5049593Simpextern int __yp_dobind_cflookup(char *, struct dom_binding **, int); 5149593Simp 5292889Sobrienstatic struct timeval tp_timout = { 120, 0}; 5392889Sobrienstatic char nullstring[] = "\000"; 5492889Sobrien 5549593Simp/* 5649593Simp * __yp_all_cflookup() is a variant of the yp_all() code, 5749594Simp * which adds a 'hardlookup' parameter. This parameter is passed 5871191Sjedgar * to __yp_dobind_cflookup(), and determines whether the server 5949593Simp * binding attempt is hard (try forever) of soft (retry a compiled- 6049593Simp * in number of times). 6149594Simp */ 6249593Simpint 6349593Simp__yp_all_cflookup(char *domain, char *map, struct ypall_callback *callback, 6449593Simp int hardlookup) 6549593Simp{ 6649593Simp size_t domlen; 6749593Simp size_t maplen; 6849593Simp struct ypreq_nokey req; 6949593Simp int reason; 7049593Simp struct dom_binding *pdomb; 7149593Simp enum clnt_stat s; 7249593Simp CLIENT *allc; 7349593Simp char server_name[MAXHOSTNAMELEN]; 7449593Simp char errbuf[BUFSIZ]; 7549593Simp 76 if ((map == NULL) || (domain == NULL)) 77 return (YPERR_BADARGS); 78 79 domlen = strlen(domain); 80 maplen = strlen(map); 81 82 if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 83 (maplen == 0) || (maplen > YPMAXMAP) || 84 (callback == NULL)) 85 return (YPERR_BADARGS); 86 87 if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup)) 88 return (reason); 89 90 if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) { 91 __yp_rel_binding(pdomb); 92 return (YPERR_VERS); 93 } 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); 100 } 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) { 104 /* 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 ! 109 */ 110 111 struct nd_hostservlist *nhs; 112 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); 119 } 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); 126 } 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); 131 } 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); 139 } 140 141 req.domain = domain; 142 req.map = map; 143 144 145 s = clnt_call(allc, YPPROC_ALL, 146 (xdrproc_t)xdr_ypreq_nokey, (char *)&req, 147 (xdrproc_t)xdr_ypall, (char *)callback, tp_timout); 148 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")); 152 } 153 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); 162 } 163} 164 165 166/* 167 * This does the "glommed enumeration" stuff. callback->foreach is the name 168 * of a function which gets called per decoded key-value pair: 169 * 170 * (*callback->foreach)(status, key, keylen, val, vallen, callback->data); 171 * 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. 175 */ 176int 177yp_all(char *domain, char *map, struct ypall_callback *callback) 178{ 179 return (__yp_all_cflookup(domain, map, callback, 1)); 180} 181 182 183/* 184 * This function is identical to 'yp_all' with the exception that it 185 * attempts to use reserve ports. 186 */ 187int 188__yp_all_rsvdport(char *domain, char *map, struct ypall_callback *callback) 189{ 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]; 199 200 if ((map == NULL) || (domain == NULL)) 201 return (YPERR_BADARGS); 202 203 domlen = strlen(domain); 204 maplen = strlen(map); 205 206 if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 207 (maplen == 0) || (maplen > YPMAXMAP) || 208 (callback == NULL)) 209 return (YPERR_BADARGS); 210 211 if (reason = __yp_dobind_rsvdport(domain, &pdomb)) 212 return (reason); 213 214 if (pdomb->dom_binding->ypbind_hi_vers < YPVERS) { 215 /* 216 * Have to free the binding since the reserved 217 * port bindings are not cached. 218 */ 219 __yp_rel_binding(pdomb); 220 free_dom_binding(pdomb); 221 return (YPERR_VERS); 222 } 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); 230 } 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) { 234 /* 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 ! 239 */ 240 241 struct nd_hostservlist *nhs; 242 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); 250 } 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); 257 } 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); 262 263 } 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); 274 } 275 276 req.domain = domain; 277 req.map = map; 278 279 s = clnt_call(allc, YPPROC_ALL, 280 (xdrproc_t)xdr_ypreq_nokey, (char *)&req, 281 (xdrproc_t)xdr_ypall, (char *)callback, tp_timout); 282 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")); 286 } 287 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); 297 } 298} 299