1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 32*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of 33*7c478bd9Sstevel@tonic-gate * California. 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include "ypsym.h" 39*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 40*7c478bd9Sstevel@tonic-gate #include "yp_b.h" 41*7c478bd9Sstevel@tonic-gate #include <string.h> 42*7c478bd9Sstevel@tonic-gate #include <limits.h> 43*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 44*7c478bd9Sstevel@tonic-gate #include <netdir.h> 45*7c478bd9Sstevel@tonic-gate #include <rpc/clnt.h> 46*7c478bd9Sstevel@tonic-gate #include <syslog.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 48*7c478bd9Sstevel@tonic-gate #include <unistd.h> 49*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 51*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #ifndef NULL 55*7c478bd9Sstevel@tonic-gate #define NULL 0 56*7c478bd9Sstevel@tonic-gate #endif 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #define YPSERVERS "ypservers" 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate void ypbind_init_default(); 61*7c478bd9Sstevel@tonic-gate static int ypbind_pipe_setdom(); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate static bool firsttime = TRUE; 64*7c478bd9Sstevel@tonic-gate static struct domain *known_domains; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate extern struct netconfig *__rpc_getconf(); 67*7c478bd9Sstevel@tonic-gate extern void *__rpc_setconf(), *__rpc_endconf(); 68*7c478bd9Sstevel@tonic-gate extern CLIENT *__clnt_tp_create_bootstrap(); 69*7c478bd9Sstevel@tonic-gate extern char *inet_ntoa(); 70*7c478bd9Sstevel@tonic-gate extern int __rpc_get_local_uid(); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate extern listofnames *names(); 73*7c478bd9Sstevel@tonic-gate extern void free_listofnames(); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #define PINGTIME 10 /* Timeout for the ypservers list */ 76*7c478bd9Sstevel@tonic-gate #define PINGTOTTIM 5 /* Total seconds for ping timeout */ 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate static void broadcast_setup(); 79*7c478bd9Sstevel@tonic-gate static void sigcld_handler(); 80*7c478bd9Sstevel@tonic-gate static struct ypbind_binding *dup_ypbind_binding(); 81*7c478bd9Sstevel@tonic-gate static struct netbuf *dup_netbuf(); 82*7c478bd9Sstevel@tonic-gate static void free_ypbind_binding(); 83*7c478bd9Sstevel@tonic-gate static void enable_exit(); 84*7c478bd9Sstevel@tonic-gate static void ypbind_ping(); 85*7c478bd9Sstevel@tonic-gate static struct domain *ypbind_point_to_domain(); 86*7c478bd9Sstevel@tonic-gate static bool ypbind_broadcast_ack(); 87*7c478bd9Sstevel@tonic-gate static int pong_servers(); 88*7c478bd9Sstevel@tonic-gate void cache_binding(); 89*7c478bd9Sstevel@tonic-gate void uncache_binding(); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate extern int setok; 92*7c478bd9Sstevel@tonic-gate extern int broadcast; 93*7c478bd9Sstevel@tonic-gate extern int cache_okay; 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * Need to differentiate between RPC_UNKNOWNHOST returned by the RPC 97*7c478bd9Sstevel@tonic-gate * library, and the same error caused by a local lookup failure in 98*7c478bd9Sstevel@tonic-gate * /etc/hosts and/or /etc/inet/ipnodes. 99*7c478bd9Sstevel@tonic-gate */ 100*7c478bd9Sstevel@tonic-gate int hostNotKnownLocally; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 103*7c478bd9Sstevel@tonic-gate void * 104*7c478bd9Sstevel@tonic-gate ypbindproc_null_3(argp, clnt) 105*7c478bd9Sstevel@tonic-gate void *argp; 106*7c478bd9Sstevel@tonic-gate CLIENT *clnt; 107*7c478bd9Sstevel@tonic-gate { 108*7c478bd9Sstevel@tonic-gate static char res; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate return ((void *) & res); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate static void 114*7c478bd9Sstevel@tonic-gate enable_exit() 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate static bool done = FALSE; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (!done) { 119*7c478bd9Sstevel@tonic-gate done = TRUE; 120*7c478bd9Sstevel@tonic-gate sigset(SIGCHLD, (void (*)())sigcld_handler); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate int sigcld_event = 0; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate static void 127*7c478bd9Sstevel@tonic-gate sigcld_handler() 128*7c478bd9Sstevel@tonic-gate { 129*7c478bd9Sstevel@tonic-gate sigcld_event++; 130*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 131*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind sighandler: got SIGCLD signal (event=%d)\n", 132*7c478bd9Sstevel@tonic-gate sigcld_event); 133*7c478bd9Sstevel@tonic-gate #endif 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* 138*7c478bd9Sstevel@tonic-gate * This is a Unix SIGCHILD handler that notices when a broadcaster child 139*7c478bd9Sstevel@tonic-gate * process has exited, and retrieves the exit status. The broadcaster pid 140*7c478bd9Sstevel@tonic-gate * is set to 0. If the broadcaster succeeded, dom_report_success will be 141*7c478bd9Sstevel@tonic-gate * be set to -1. 142*7c478bd9Sstevel@tonic-gate */ 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate void 145*7c478bd9Sstevel@tonic-gate broadcast_proc_exit() 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate int pid, ret; 148*7c478bd9Sstevel@tonic-gate siginfo_t infop; 149*7c478bd9Sstevel@tonic-gate register struct domain *pdom; 150*7c478bd9Sstevel@tonic-gate bool succeeded = FALSE; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate sigcld_event = 0; 153*7c478bd9Sstevel@tonic-gate /* ==== Why WEXITED? */ 154*7c478bd9Sstevel@tonic-gate while ((ret = waitid(P_ALL, 0, &infop, WNOHANG | WEXITED)) != -1) { 155*7c478bd9Sstevel@tonic-gate switch (infop.si_code) { 156*7c478bd9Sstevel@tonic-gate case CLD_EXITED: 157*7c478bd9Sstevel@tonic-gate succeeded = infop.si_status == 0; 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate case CLD_KILLED: 160*7c478bd9Sstevel@tonic-gate case CLD_DUMPED: 161*7c478bd9Sstevel@tonic-gate succeeded = FALSE; 162*7c478bd9Sstevel@tonic-gate break; 163*7c478bd9Sstevel@tonic-gate case CLD_TRAPPED: 164*7c478bd9Sstevel@tonic-gate case CLD_STOPPED: 165*7c478bd9Sstevel@tonic-gate case CLD_CONTINUED: 166*7c478bd9Sstevel@tonic-gate enable_exit(); 167*7c478bd9Sstevel@tonic-gate return; 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate pid = infop.si_pid; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 172*7c478bd9Sstevel@tonic-gate fprintf(stderr, 173*7c478bd9Sstevel@tonic-gate "ypbind event_handler: got wait from %d status = %d\n", 174*7c478bd9Sstevel@tonic-gate pid, infop.si_status); 175*7c478bd9Sstevel@tonic-gate #endif 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate /* to aid the progeny print the infamous "not responding" message */ 178*7c478bd9Sstevel@tonic-gate firsttime = FALSE; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate for (pdom = known_domains; pdom != (struct domain *)NULL; 181*7c478bd9Sstevel@tonic-gate pdom = pdom->dom_pnext) { 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if (pdom->dom_broadcaster_pid == pid) { 184*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 185*7c478bd9Sstevel@tonic-gate fprintf(stderr, 186*7c478bd9Sstevel@tonic-gate "ypbind event_handler: got match %s\n", pdom->dom_name); 187*7c478bd9Sstevel@tonic-gate #endif 188*7c478bd9Sstevel@tonic-gate if (succeeded) { 189*7c478bd9Sstevel@tonic-gate broadcast_setup(pdom); 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate if (pdom->broadcaster_pipe != 0) { 192*7c478bd9Sstevel@tonic-gate xdr_destroy(&(pdom->broadcaster_xdr)); 193*7c478bd9Sstevel@tonic-gate fclose(pdom->broadcaster_pipe); 194*7c478bd9Sstevel@tonic-gate pdom->broadcaster_pipe = 0; 195*7c478bd9Sstevel@tonic-gate pdom->broadcaster_fd = -1; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate pdom->dom_broadcaster_pid = 0; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate break; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate } /* while loop */ 203*7c478bd9Sstevel@tonic-gate enable_exit(); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate static void 207*7c478bd9Sstevel@tonic-gate broadcast_setup(pdom) 208*7c478bd9Sstevel@tonic-gate struct domain *pdom; 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate ypbind_setdom req; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate memset(&req, 0, sizeof (req)); 213*7c478bd9Sstevel@tonic-gate if (pdom->broadcaster_pipe) { 214*7c478bd9Sstevel@tonic-gate pdom->dom_report_success = -1; 215*7c478bd9Sstevel@tonic-gate if (xdr_ypbind_setdom(&(pdom->broadcaster_xdr), &req)) { 216*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 217*7c478bd9Sstevel@tonic-gate fprintf(stderr, "parent: broadcast_setup: got xdr ok \n"); 218*7c478bd9Sstevel@tonic-gate #endif 219*7c478bd9Sstevel@tonic-gate ypbindproc_setdom_3(&req, (struct svc_req *)NULL, 220*7c478bd9Sstevel@tonic-gate (SVCXPRT *)NULL); 221*7c478bd9Sstevel@tonic-gate xdr_free(xdr_ypbind_setdom, (char *)&req); 222*7c478bd9Sstevel@tonic-gate gettimeofday(&(pdom->lastping), NULL); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 225*7c478bd9Sstevel@tonic-gate else { 226*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind parent: xdr_ypbind_setdom failed\n"); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate #endif 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 231*7c478bd9Sstevel@tonic-gate else { 232*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind: internal error -- no broadcaster pipe\n"); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate #endif 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate #define YPBIND_PINGHOLD_DOWN 5 238*7c478bd9Sstevel@tonic-gate /* Same as the ypbind_get_binding() routine in SunOS */ 239*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 240*7c478bd9Sstevel@tonic-gate ypbind_resp * 241*7c478bd9Sstevel@tonic-gate ypbindproc_domain_3(argp, clnt) 242*7c478bd9Sstevel@tonic-gate ypbind_domain *argp; 243*7c478bd9Sstevel@tonic-gate CLIENT *clnt; 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate static ypbind_resp resp; 246*7c478bd9Sstevel@tonic-gate struct domain *cur_domain; 247*7c478bd9Sstevel@tonic-gate int bpid; 248*7c478bd9Sstevel@tonic-gate int fildes[2]; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate memset((char *)&resp, 0, sizeof (resp)); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 253*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\nypbindproc_domain_3: domain: %s\n", 254*7c478bd9Sstevel@tonic-gate argp->ypbind_domainname); 255*7c478bd9Sstevel@tonic-gate #endif 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate if ((int)strlen(argp->ypbind_domainname) > YPMAXDOMAIN) { 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate resp.ypbind_status = YPBIND_FAIL_VAL; 260*7c478bd9Sstevel@tonic-gate resp.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; 261*7c478bd9Sstevel@tonic-gate return (&resp); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if ((cur_domain = ypbind_point_to_domain(argp->ypbind_domainname)) != 265*7c478bd9Sstevel@tonic-gate (struct domain *)NULL) { 266*7c478bd9Sstevel@tonic-gate if (cur_domain->dom_boundp) { 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate struct timeval tp; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&tp, NULL); 271*7c478bd9Sstevel@tonic-gate if ((tp.tv_sec - cur_domain->lastping.tv_sec) > 272*7c478bd9Sstevel@tonic-gate YPBIND_PINGHOLD_DOWN) { 273*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 274*7c478bd9Sstevel@tonic-gate fprintf(stderr, "domain is bound pinging: %s\n", 275*7c478bd9Sstevel@tonic-gate argp->ypbind_domainname); 276*7c478bd9Sstevel@tonic-gate #endif 277*7c478bd9Sstevel@tonic-gate (void) ypbind_ping(cur_domain); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Bound or not, return the current state of the binding. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate if (cur_domain->dom_boundp) { 286*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 287*7c478bd9Sstevel@tonic-gate fprintf(stderr, "server is up for domain: %s\n", 288*7c478bd9Sstevel@tonic-gate argp->ypbind_domainname); 289*7c478bd9Sstevel@tonic-gate #endif 290*7c478bd9Sstevel@tonic-gate resp.ypbind_status = YPBIND_SUCC_VAL; 291*7c478bd9Sstevel@tonic-gate resp.ypbind_resp_u.ypbind_bindinfo = 292*7c478bd9Sstevel@tonic-gate cur_domain->dom_binding; 293*7c478bd9Sstevel@tonic-gate } else { 294*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 295*7c478bd9Sstevel@tonic-gate fprintf(stderr, "domain is NOT bound returning: %s %d\n", 296*7c478bd9Sstevel@tonic-gate argp->ypbind_domainname, cur_domain->dom_error); 297*7c478bd9Sstevel@tonic-gate #endif 298*7c478bd9Sstevel@tonic-gate resp.ypbind_status = YPBIND_FAIL_VAL; 299*7c478bd9Sstevel@tonic-gate resp.ypbind_resp_u.ypbind_error = 300*7c478bd9Sstevel@tonic-gate cur_domain->dom_error; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate } else { 304*7c478bd9Sstevel@tonic-gate resp.ypbind_status = YPBIND_FAIL_VAL; 305*7c478bd9Sstevel@tonic-gate resp.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * RETURN NOW: if successful, otherwise 309*7c478bd9Sstevel@tonic-gate * RETURN LATER: after spawning off a child to do the "broadcast" work. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate if (resp.ypbind_status == YPBIND_SUCC_VAL) { 312*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 313*7c478bd9Sstevel@tonic-gate fprintf(stderr, "yp_b_subr: returning success to yp_b_svc %d\n", 314*7c478bd9Sstevel@tonic-gate resp.ypbind_status); 315*7c478bd9Sstevel@tonic-gate #endif 316*7c478bd9Sstevel@tonic-gate return (&resp); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* Go about the broadcast (really, pinging here) business */ 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if ((cur_domain) && (!cur_domain->dom_boundp) && 322*7c478bd9Sstevel@tonic-gate (!cur_domain->dom_broadcaster_pid)) { 323*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 324*7c478bd9Sstevel@tonic-gate fprintf(stderr, "yp_b_subr: fork: boundp=%d broadcast_pid=%d\n", 325*7c478bd9Sstevel@tonic-gate cur_domain->dom_boundp, cur_domain->dom_broadcaster_pid); 326*7c478bd9Sstevel@tonic-gate #endif 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * The current domain is unbound, and there is no child 329*7c478bd9Sstevel@tonic-gate * process active now. Fork off a child who will beg to the 330*7c478bd9Sstevel@tonic-gate * ypservers list one by one or broadcast and accept whoever 331*7c478bd9Sstevel@tonic-gate * commands the right domain. 332*7c478bd9Sstevel@tonic-gate */ 333*7c478bd9Sstevel@tonic-gate if (pipe(fildes) < 0) { 334*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 335*7c478bd9Sstevel@tonic-gate fprintf(stderr, "yp_b_subr: returning pipe failure to yp_b_svc %d\n", 336*7c478bd9Sstevel@tonic-gate resp.ypbind_status); 337*7c478bd9Sstevel@tonic-gate #endif 338*7c478bd9Sstevel@tonic-gate return (&resp); 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate enable_exit(); 342*7c478bd9Sstevel@tonic-gate sighold(SIGCLD); /* add it to ypbind's signal mask */ 343*7c478bd9Sstevel@tonic-gate cur_domain->dom_report_success++; 344*7c478bd9Sstevel@tonic-gate bpid = fork(); 345*7c478bd9Sstevel@tonic-gate if (bpid != 0) { /* parent */ 346*7c478bd9Sstevel@tonic-gate if (bpid > 0) { /* parent started */ 347*7c478bd9Sstevel@tonic-gate close(fildes[1]); 348*7c478bd9Sstevel@tonic-gate cur_domain->dom_broadcaster_pid = bpid; 349*7c478bd9Sstevel@tonic-gate cur_domain->broadcaster_fd = fildes[0]; 350*7c478bd9Sstevel@tonic-gate cur_domain->broadcaster_pipe = 351*7c478bd9Sstevel@tonic-gate fdopen(fildes[0], "r"); 352*7c478bd9Sstevel@tonic-gate if (cur_domain->broadcaster_pipe) 353*7c478bd9Sstevel@tonic-gate xdrstdio_create(&(cur_domain->broadcaster_xdr), 354*7c478bd9Sstevel@tonic-gate (cur_domain->broadcaster_pipe), XDR_DECODE); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 357*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbindproc_domain_3: %s starting pid = %d try = %d\n", 358*7c478bd9Sstevel@tonic-gate cur_domain->dom_name, bpid, 359*7c478bd9Sstevel@tonic-gate cur_domain->dom_report_success); 360*7c478bd9Sstevel@tonic-gate fprintf(stderr, "yp_b_subr: returning after spawning, to yp_b_svc %d\n", 361*7c478bd9Sstevel@tonic-gate resp.ypbind_status); 362*7c478bd9Sstevel@tonic-gate #endif 363*7c478bd9Sstevel@tonic-gate sigrelse(SIGCLD); 364*7c478bd9Sstevel@tonic-gate /* remove it from ypbind's signal mask */ 365*7c478bd9Sstevel@tonic-gate return (&resp); 366*7c478bd9Sstevel@tonic-gate } else { /* fork failed */ 367*7c478bd9Sstevel@tonic-gate perror("fork"); 368*7c478bd9Sstevel@tonic-gate close(fildes[0]); 369*7c478bd9Sstevel@tonic-gate close(fildes[1]); 370*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 371*7c478bd9Sstevel@tonic-gate fprintf(stderr, "yp_b_subr: returning fork failure to yp_b_svc %d\n", 372*7c478bd9Sstevel@tonic-gate resp.ypbind_status); 373*7c478bd9Sstevel@tonic-gate #endif 374*7c478bd9Sstevel@tonic-gate sigrelse(SIGCLD); 375*7c478bd9Sstevel@tonic-gate return (&resp); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate } /* end parent */ 378*7c478bd9Sstevel@tonic-gate /* child only code */ 379*7c478bd9Sstevel@tonic-gate sigrelse(SIGCLD); 380*7c478bd9Sstevel@tonic-gate close(fildes[0]); 381*7c478bd9Sstevel@tonic-gate cur_domain->broadcaster_fd = fildes[1]; 382*7c478bd9Sstevel@tonic-gate cur_domain->broadcaster_pipe = fdopen(fildes[1], "w"); 383*7c478bd9Sstevel@tonic-gate if (cur_domain->broadcaster_pipe) 384*7c478bd9Sstevel@tonic-gate xdrstdio_create(&(cur_domain->broadcaster_xdr), 385*7c478bd9Sstevel@tonic-gate (cur_domain->broadcaster_pipe), XDR_ENCODE); 386*7c478bd9Sstevel@tonic-gate else { 387*7c478bd9Sstevel@tonic-gate perror("fdopen-pipe"); 388*7c478bd9Sstevel@tonic-gate exit(-1); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate exit(pong_servers(cur_domain)); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 393*7c478bd9Sstevel@tonic-gate fprintf(stderr, "yp_b_subr: lazy returns failure status yp_b_svc %d\n", 394*7c478bd9Sstevel@tonic-gate resp.ypbind_status); 395*7c478bd9Sstevel@tonic-gate #endif 396*7c478bd9Sstevel@tonic-gate return (&resp); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* 401*7c478bd9Sstevel@tonic-gate * call ypbindproc_domain_3 and convert results 402*7c478bd9Sstevel@tonic-gate * 403*7c478bd9Sstevel@tonic-gate * This adds support for YP clients that send requests on 404*7c478bd9Sstevel@tonic-gate * ypbind version 1 & 2 (i.e. clients before we started 405*7c478bd9Sstevel@tonic-gate * using universal addresses and netbufs). This is supported 406*7c478bd9Sstevel@tonic-gate * for binary compatibility for static 4.x programs. The 407*7c478bd9Sstevel@tonic-gate * assumption used to be that clients coming in with ypbind vers 1 408*7c478bd9Sstevel@tonic-gate * should be given the address of a server serving ypserv version 1. 409*7c478bd9Sstevel@tonic-gate * However, since yp_bind routines in 4.x YP library try 410*7c478bd9Sstevel@tonic-gate * to connect with ypserv version 2, even if they requested 411*7c478bd9Sstevel@tonic-gate * binding using ypbind version 1, the ypbind process will 412*7c478bd9Sstevel@tonic-gate * "always" look for only ypserv version 2 servers for all 413*7c478bd9Sstevel@tonic-gate * (ypbind vers 1, 2, & 3) clients. 414*7c478bd9Sstevel@tonic-gate */ 415*7c478bd9Sstevel@tonic-gate ypbind_resp_2 * 416*7c478bd9Sstevel@tonic-gate ypbindproc_domain_2(argp, clnt) 417*7c478bd9Sstevel@tonic-gate domainname_2 *argp; 418*7c478bd9Sstevel@tonic-gate CLIENT *clnt; 419*7c478bd9Sstevel@tonic-gate { 420*7c478bd9Sstevel@tonic-gate ypbind_domain arg_3; 421*7c478bd9Sstevel@tonic-gate ypbind_resp *resp_3; 422*7c478bd9Sstevel@tonic-gate static ypbind_resp_2 resp; 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate arg_3.ypbind_domainname = *argp; 425*7c478bd9Sstevel@tonic-gate resp_3 = ypbindproc_domain_3(&arg_3, clnt); 426*7c478bd9Sstevel@tonic-gate if (resp_3 == NULL) 427*7c478bd9Sstevel@tonic-gate return (NULL); 428*7c478bd9Sstevel@tonic-gate resp.ypbind_status = resp_3->ypbind_status; 429*7c478bd9Sstevel@tonic-gate if (resp_3->ypbind_status == YPBIND_SUCC_VAL) { 430*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 431*7c478bd9Sstevel@tonic-gate struct ypbind_binding_2 *bi; 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *) 434*7c478bd9Sstevel@tonic-gate resp_3->ypbind_resp_u.ypbind_bindinfo->ypbind_svcaddr->buf; 435*7c478bd9Sstevel@tonic-gate if (sin->sin_family == AF_INET) { 436*7c478bd9Sstevel@tonic-gate bi = &resp.ypbind_respbody_2.ypbind_bindinfo; 437*7c478bd9Sstevel@tonic-gate memcpy(&(bi->ypbind_binding_port), &sin->sin_port, 2); 438*7c478bd9Sstevel@tonic-gate memcpy(&(bi->ypbind_binding_addr), &sin->sin_addr, 4); 439*7c478bd9Sstevel@tonic-gate } else { 440*7c478bd9Sstevel@tonic-gate resp.ypbind_respbody_2.ypbind_error = YPBIND_ERR_NOSERV; 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate } else { 443*7c478bd9Sstevel@tonic-gate resp.ypbind_respbody_2.ypbind_error = 444*7c478bd9Sstevel@tonic-gate resp_3->ypbind_resp_u.ypbind_error; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate return (&resp); 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* used to exchange information between pong_servers and ypbind_broadcast_ack */ 450*7c478bd9Sstevel@tonic-gate struct domain *process_current_domain; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate int 453*7c478bd9Sstevel@tonic-gate pong_servers(domain_struct) 454*7c478bd9Sstevel@tonic-gate struct domain *domain_struct; /* to pass back */ 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate char *domain = domain_struct->dom_name; 457*7c478bd9Sstevel@tonic-gate CLIENT *clnt2; 458*7c478bd9Sstevel@tonic-gate char *servername; 459*7c478bd9Sstevel@tonic-gate listofnames *list, *lin; 460*7c478bd9Sstevel@tonic-gate char serverfile[MAXNAMLEN]; 461*7c478bd9Sstevel@tonic-gate struct timeval timeout; 462*7c478bd9Sstevel@tonic-gate int isok = 0, res = -1; 463*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 464*7c478bd9Sstevel@tonic-gate void *handle; 465*7c478bd9Sstevel@tonic-gate int nconf_count; 466*7c478bd9Sstevel@tonic-gate char rpcdomain[YPMAXDOMAIN+1]; 467*7c478bd9Sstevel@tonic-gate long inforet; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* 470*7c478bd9Sstevel@tonic-gate * If the ``domain'' name passed in is not the same as the RPC 471*7c478bd9Sstevel@tonic-gate * domain set from /etc/defaultdomain. Then we set ``firsttime'' 472*7c478bd9Sstevel@tonic-gate * to TRUE so no error messages are ever syslog()-ed this 473*7c478bd9Sstevel@tonic-gate * prevents a possible Denial of Service attack. 474*7c478bd9Sstevel@tonic-gate */ 475*7c478bd9Sstevel@tonic-gate inforet = sysinfo(SI_SRPC_DOMAIN, &(rpcdomain[0]), YPMAXDOMAIN); 476*7c478bd9Sstevel@tonic-gate if ((inforet > 0) && (strcmp(domain, rpcdomain) != 0)) 477*7c478bd9Sstevel@tonic-gate firsttime = TRUE; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if (broadcast) { 480*7c478bd9Sstevel@tonic-gate enum clnt_stat stat = RPC_SUCCESS; 481*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 482*7c478bd9Sstevel@tonic-gate fprintf(stderr, "pong_servers: doing an rpc_broadcast\n"); 483*7c478bd9Sstevel@tonic-gate #endif 484*7c478bd9Sstevel@tonic-gate /* 485*7c478bd9Sstevel@tonic-gate * Here we do the real SunOS thing that users love. Do a 486*7c478bd9Sstevel@tonic-gate * broadcast on the network and find out the ypserv. No need 487*7c478bd9Sstevel@tonic-gate * to do "ypinit -c", no setting up /etc/hosts file, and no 488*7c478bd9Sstevel@tonic-gate * recursion looking up the server's IP address. 489*7c478bd9Sstevel@tonic-gate */ 490*7c478bd9Sstevel@tonic-gate process_current_domain = domain_struct; 491*7c478bd9Sstevel@tonic-gate stat = rpc_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, 492*7c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypdomain_wrap_string, (caddr_t)&domain, 493*7c478bd9Sstevel@tonic-gate xdr_int, (caddr_t)&isok, 494*7c478bd9Sstevel@tonic-gate (resultproc_t)ypbind_broadcast_ack, "udp"); 495*7c478bd9Sstevel@tonic-gate if (stat == RPC_SYSTEMERROR || stat == RPC_UNKNOWNPROTO || 496*7c478bd9Sstevel@tonic-gate stat == RPC_CANTRECV || stat == RPC_CANTSEND || 497*7c478bd9Sstevel@tonic-gate stat == RPC_NOBROADCAST || 498*7c478bd9Sstevel@tonic-gate stat == RPC_N2AXLATEFAILURE) { 499*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "RPC/Transport subsystem failure %s\n", 500*7c478bd9Sstevel@tonic-gate clnt_sperrno(stat)); 501*7c478bd9Sstevel@tonic-gate exit(-1); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate if (domain_struct->broadcaster_pipe == 0) 504*7c478bd9Sstevel@tonic-gate /* init binding case */ 505*7c478bd9Sstevel@tonic-gate return (domain_struct->dom_boundp - 1); 506*7c478bd9Sstevel@tonic-gate if (domain_struct->dom_boundp) { 507*7c478bd9Sstevel@tonic-gate res = ypbind_pipe_setdom(NULL, domain, 508*7c478bd9Sstevel@tonic-gate NULL, domain_struct); 509*7c478bd9Sstevel@tonic-gate if (domain_struct->dom_report_success > 0) 510*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 511*7c478bd9Sstevel@tonic-gate "NIS server for domain \"%s\" OK", domain); 512*7c478bd9Sstevel@tonic-gate } else if (firsttime == FALSE) 513*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 514*7c478bd9Sstevel@tonic-gate "NIS server not responding for domain \"%s\"; still trying", domain); 515*7c478bd9Sstevel@tonic-gate return (res); 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 518*7c478bd9Sstevel@tonic-gate fprintf(stderr, "pong_servers: ponging servers one by one\n"); 519*7c478bd9Sstevel@tonic-gate #endif 520*7c478bd9Sstevel@tonic-gate /* 521*7c478bd9Sstevel@tonic-gate * Do the politically correct thing.. transport independent and 522*7c478bd9Sstevel@tonic-gate * secure (trusts only listed servers). 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate /* 526*7c478bd9Sstevel@tonic-gate * get list of possible servers for this domain 527*7c478bd9Sstevel@tonic-gate */ 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* 530*7c478bd9Sstevel@tonic-gate * get alias for domain: Things of the past.. 531*7c478bd9Sstevel@tonic-gate * sysvconfig(); 532*7c478bd9Sstevel@tonic-gate * (void) yp_getalias(domain, domain_alias, NAME_MAX); 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate sprintf(serverfile, "%s/%s/%s", BINDING, domain, YPSERVERS); 535*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 536*7c478bd9Sstevel@tonic-gate fprintf(stderr, "pong_servers: serverfile %s\n", serverfile); 537*7c478bd9Sstevel@tonic-gate #endif 538*7c478bd9Sstevel@tonic-gate list = names(serverfile); 539*7c478bd9Sstevel@tonic-gate if (list == NULL) { 540*7c478bd9Sstevel@tonic-gate if (firsttime == FALSE) 541*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 542*7c478bd9Sstevel@tonic-gate "service not installed, use /usr/sbin/ypinit -c"); 543*7c478bd9Sstevel@tonic-gate return (-1); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate lin = list; 546*7c478bd9Sstevel@tonic-gate for (list = lin; list; list = list->nextname) { 547*7c478bd9Sstevel@tonic-gate servername = strtok(list->name, " \t\n"); 548*7c478bd9Sstevel@tonic-gate if (servername == NULL) continue; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* Check all datagram_v transports for this server */ 551*7c478bd9Sstevel@tonic-gate if ((handle = __rpc_setconf("datagram_v")) == NULL) { 552*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 553*7c478bd9Sstevel@tonic-gate "ypbind: RPC operation on /etc/netconfig failed"); 554*7c478bd9Sstevel@tonic-gate free_listofnames(lin); 555*7c478bd9Sstevel@tonic-gate return (-1); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate nconf_count = 0; 559*7c478bd9Sstevel@tonic-gate clnt2 = 0; 560*7c478bd9Sstevel@tonic-gate while (clnt2 == 0 && (nconf = __rpc_getconf(handle)) != 0) { 561*7c478bd9Sstevel@tonic-gate nconf_count++; 562*7c478bd9Sstevel@tonic-gate /* 563*7c478bd9Sstevel@tonic-gate * We use only datagram here. It is expected to be udp. 564*7c478bd9Sstevel@tonic-gate * VERY IMPORTANT: __clnt_tp_create_bootstrap is a 565*7c478bd9Sstevel@tonic-gate * hacked up version that does not do netdir_getbyname. 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate hostNotKnownLocally = 0; 568*7c478bd9Sstevel@tonic-gate clnt2 = 569*7c478bd9Sstevel@tonic-gate __clnt_tp_create_bootstrap(servername, YPPROG, YPVERS, nconf); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate if (nconf_count == 0) { 572*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 573*7c478bd9Sstevel@tonic-gate "ypbind: RPC operation on /etc/netconfig failed"); 574*7c478bd9Sstevel@tonic-gate free_listofnames(lin); 575*7c478bd9Sstevel@tonic-gate return (-1); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate if (clnt2 == 0) { 579*7c478bd9Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST && 580*7c478bd9Sstevel@tonic-gate hostNotKnownLocally) { 581*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 582*7c478bd9Sstevel@tonic-gate "NIS server %s is not in local host files !", servername); 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate perror(servername); 585*7c478bd9Sstevel@tonic-gate clnt_pcreateerror("ypbind"); 586*7c478bd9Sstevel@tonic-gate continue; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate timeout.tv_sec = PINGTIME; 590*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 591*7c478bd9Sstevel@tonic-gate if ((enum clnt_stat) clnt_call(clnt2, 592*7c478bd9Sstevel@tonic-gate YPPROC_DOMAIN, (xdrproc_t)xdr_ypdomain_wrap_string, 593*7c478bd9Sstevel@tonic-gate (char *)&domain, xdr_int, 594*7c478bd9Sstevel@tonic-gate (char *)&isok, timeout) == RPC_SUCCESS) { 595*7c478bd9Sstevel@tonic-gate if (isok) { 596*7c478bd9Sstevel@tonic-gate if (domain_struct->dom_report_success > 0) { 597*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 598*7c478bd9Sstevel@tonic-gate "NIS server for domain \"%s\" OK", domain); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate if (domain_struct->broadcaster_pipe == 0) { 601*7c478bd9Sstevel@tonic-gate /* init binding case --parent */ 602*7c478bd9Sstevel@tonic-gate struct netconfig *setnc; 603*7c478bd9Sstevel@tonic-gate struct netbuf setua; 604*7c478bd9Sstevel@tonic-gate struct ypbind_binding *b = 605*7c478bd9Sstevel@tonic-gate domain_struct->dom_binding; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate setnc = 608*7c478bd9Sstevel@tonic-gate getnetconfigent(clnt2->cl_netid); 609*7c478bd9Sstevel@tonic-gate if (b == NULL) { 610*7c478bd9Sstevel@tonic-gate /* ASSERT: This shouldn't happen ! */ 611*7c478bd9Sstevel@tonic-gate b = 612*7c478bd9Sstevel@tonic-gate (struct ypbind_binding *)calloc(1, sizeof (*b)); 613*7c478bd9Sstevel@tonic-gate domain_struct->dom_binding = b; 614*7c478bd9Sstevel@tonic-gate if (b == NULL) { 615*7c478bd9Sstevel@tonic-gate __rpc_endconf(handle); 616*7c478bd9Sstevel@tonic-gate clnt_destroy(clnt2); 617*7c478bd9Sstevel@tonic-gate free_listofnames(lin); 618*7c478bd9Sstevel@tonic-gate return (-2); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate b->ypbind_nconf = setnc; 624*7c478bd9Sstevel@tonic-gate clnt_control(clnt2, CLGET_SVC_ADDR, 625*7c478bd9Sstevel@tonic-gate (char *)&setua); 626*7c478bd9Sstevel@tonic-gate if (b->ypbind_svcaddr) { 627*7c478bd9Sstevel@tonic-gate if (b->ypbind_svcaddr->buf) 628*7c478bd9Sstevel@tonic-gate free(b->ypbind_svcaddr->buf); 629*7c478bd9Sstevel@tonic-gate free(b->ypbind_svcaddr); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate b->ypbind_svcaddr = dup_netbuf(&setua); 632*7c478bd9Sstevel@tonic-gate if (b->ypbind_servername) 633*7c478bd9Sstevel@tonic-gate free(b->ypbind_servername); 634*7c478bd9Sstevel@tonic-gate b->ypbind_servername = 635*7c478bd9Sstevel@tonic-gate strdup(servername); 636*7c478bd9Sstevel@tonic-gate b->ypbind_hi_vers = YPVERS; 637*7c478bd9Sstevel@tonic-gate b->ypbind_lo_vers = YPVERS; 638*7c478bd9Sstevel@tonic-gate __rpc_endconf(handle); 639*7c478bd9Sstevel@tonic-gate domain_struct->dom_boundp = TRUE; 640*7c478bd9Sstevel@tonic-gate clnt_destroy(clnt2); 641*7c478bd9Sstevel@tonic-gate free_listofnames(lin); 642*7c478bd9Sstevel@tonic-gate return (0); 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate res = ypbind_pipe_setdom(clnt2, domain, 645*7c478bd9Sstevel@tonic-gate servername, domain_struct); 646*7c478bd9Sstevel@tonic-gate __rpc_endconf(handle); 647*7c478bd9Sstevel@tonic-gate clnt_destroy(clnt2); 648*7c478bd9Sstevel@tonic-gate free_listofnames(lin); 649*7c478bd9Sstevel@tonic-gate return (res); 650*7c478bd9Sstevel@tonic-gate } else { 651*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 652*7c478bd9Sstevel@tonic-gate "server %s doesn't serve domain %s\n", 653*7c478bd9Sstevel@tonic-gate servername, domain); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate } else { 656*7c478bd9Sstevel@tonic-gate clnt_perror(clnt2, servername); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate clnt_destroy(clnt2); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate /* 661*7c478bd9Sstevel@tonic-gate * We tried all servers, none obliged ! 662*7c478bd9Sstevel@tonic-gate * After ypbind is started up it will not be bound 663*7c478bd9Sstevel@tonic-gate * immediately. This is normal, no error message 664*7c478bd9Sstevel@tonic-gate * is needed. Although, with the ypbind_init_default 665*7c478bd9Sstevel@tonic-gate * it will be bound immediately. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate if (firsttime == FALSE) { 668*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 669*7c478bd9Sstevel@tonic-gate "NIS server not responding for domain \"%s\"; still trying", domain); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate free_listofnames(lin); 672*7c478bd9Sstevel@tonic-gate __rpc_endconf(handle); 673*7c478bd9Sstevel@tonic-gate return (-2); 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate struct netbuf * 677*7c478bd9Sstevel@tonic-gate dup_netbuf(inbuf) 678*7c478bd9Sstevel@tonic-gate struct netbuf *inbuf; 679*7c478bd9Sstevel@tonic-gate { 680*7c478bd9Sstevel@tonic-gate struct netbuf *outbuf; 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (inbuf == NULL) 683*7c478bd9Sstevel@tonic-gate return (NULL); 684*7c478bd9Sstevel@tonic-gate if ((outbuf = 685*7c478bd9Sstevel@tonic-gate (struct netbuf *)calloc(1, sizeof (struct netbuf))) == NULL) 686*7c478bd9Sstevel@tonic-gate return (NULL); 687*7c478bd9Sstevel@tonic-gate if ((outbuf->buf = malloc(inbuf->len)) == NULL) { 688*7c478bd9Sstevel@tonic-gate free(outbuf); 689*7c478bd9Sstevel@tonic-gate return (NULL); 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate outbuf->len = inbuf->len; 692*7c478bd9Sstevel@tonic-gate outbuf->maxlen = inbuf->len; 693*7c478bd9Sstevel@tonic-gate (void) memcpy(outbuf->buf, inbuf->buf, inbuf->len); 694*7c478bd9Sstevel@tonic-gate return (outbuf); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate /* 698*7c478bd9Sstevel@tonic-gate * This is called by the broadcast rpc routines to process the responses 699*7c478bd9Sstevel@tonic-gate * coming back from the broadcast request. Since the form of the request 700*7c478bd9Sstevel@tonic-gate * which is used in ypbind_broadcast_bind is "respond only in the positive 701*7c478bd9Sstevel@tonic-gate * case", we know that we have a server. 702*7c478bd9Sstevel@tonic-gate * The internet address of the responding server will be picked up from 703*7c478bd9Sstevel@tonic-gate * the saddr parameter, and stuffed into the domain. The domain's boundp 704*7c478bd9Sstevel@tonic-gate * field will be set TRUE. The first responding server (or the first one 705*7c478bd9Sstevel@tonic-gate * which is on a reserved port) will be the bound server for the domain. 706*7c478bd9Sstevel@tonic-gate */ 707*7c478bd9Sstevel@tonic-gate bool 708*7c478bd9Sstevel@tonic-gate ypbind_broadcast_ack(ptrue, nbuf, nconf) 709*7c478bd9Sstevel@tonic-gate bool *ptrue; 710*7c478bd9Sstevel@tonic-gate struct netbuf *nbuf; 711*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 712*7c478bd9Sstevel@tonic-gate { 713*7c478bd9Sstevel@tonic-gate struct ypbind_binding b; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate process_current_domain->dom_boundp = TRUE; 716*7c478bd9Sstevel@tonic-gate b.ypbind_nconf = nconf; 717*7c478bd9Sstevel@tonic-gate b.ypbind_svcaddr = nbuf; 718*7c478bd9Sstevel@tonic-gate b.ypbind_servername = "\000"; 719*7c478bd9Sstevel@tonic-gate b.ypbind_hi_vers = YPVERS; 720*7c478bd9Sstevel@tonic-gate b.ypbind_lo_vers = YPVERS; 721*7c478bd9Sstevel@tonic-gate free_ypbind_binding(process_current_domain->dom_binding); 722*7c478bd9Sstevel@tonic-gate process_current_domain->dom_binding = dup_ypbind_binding(&b); 723*7c478bd9Sstevel@tonic-gate return (TRUE); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate /* 727*7c478bd9Sstevel@tonic-gate * WARNING: This routine is entered only by the child process. 728*7c478bd9Sstevel@tonic-gate * Called if it pongs/broadcasts okay. 729*7c478bd9Sstevel@tonic-gate */ 730*7c478bd9Sstevel@tonic-gate static int 731*7c478bd9Sstevel@tonic-gate ypbind_pipe_setdom(client, domain, servername, opaque_domain) 732*7c478bd9Sstevel@tonic-gate CLIENT *client; 733*7c478bd9Sstevel@tonic-gate char *servername; 734*7c478bd9Sstevel@tonic-gate char *domain; 735*7c478bd9Sstevel@tonic-gate struct domain *opaque_domain; 736*7c478bd9Sstevel@tonic-gate { 737*7c478bd9Sstevel@tonic-gate struct netconfig *setnc; 738*7c478bd9Sstevel@tonic-gate struct netbuf setua; 739*7c478bd9Sstevel@tonic-gate ypbind_binding setb; 740*7c478bd9Sstevel@tonic-gate ypbind_setdom setd; 741*7c478bd9Sstevel@tonic-gate int retval; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate setd.ypsetdom_domain = domain; 744*7c478bd9Sstevel@tonic-gate if (client == NULL && opaque_domain->dom_binding) { 745*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 746*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind_pipe_setdom: child broadcast case "); 747*7c478bd9Sstevel@tonic-gate #endif 748*7c478bd9Sstevel@tonic-gate /* ypbind_broadcast_ack already setup dom_binding for us */ 749*7c478bd9Sstevel@tonic-gate setd.ypsetdom_bindinfo = opaque_domain->dom_binding; 750*7c478bd9Sstevel@tonic-gate } else if (client) { 751*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 752*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind_pipe_setdom: child unicast case "); 753*7c478bd9Sstevel@tonic-gate #endif 754*7c478bd9Sstevel@tonic-gate setnc = getnetconfigent(client->cl_netid); 755*7c478bd9Sstevel@tonic-gate if (setnc == NULL) { 756*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 757*7c478bd9Sstevel@tonic-gate fprintf(stderr, "PANIC: shouldn't happen\n"); 758*7c478bd9Sstevel@tonic-gate #endif 759*7c478bd9Sstevel@tonic-gate fclose(opaque_domain->broadcaster_pipe); 760*7c478bd9Sstevel@tonic-gate close(opaque_domain->broadcaster_fd); 761*7c478bd9Sstevel@tonic-gate return (-2); 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate clnt_control(client, CLGET_SVC_ADDR, (char *)&setua); 764*7c478bd9Sstevel@tonic-gate setb.ypbind_nconf = setnc; 765*7c478bd9Sstevel@tonic-gate setb.ypbind_svcaddr = &setua; 766*7c478bd9Sstevel@tonic-gate setb.ypbind_servername = servername; 767*7c478bd9Sstevel@tonic-gate setb.ypbind_hi_vers = YPVERS; 768*7c478bd9Sstevel@tonic-gate setb.ypbind_lo_vers = YPVERS; 769*7c478bd9Sstevel@tonic-gate setd.ypsetdom_bindinfo = &setb; 770*7c478bd9Sstevel@tonic-gate /* 771*7c478bd9Sstevel@tonic-gate * Let's hardcode versions, that is the only ypserv we support anyway. 772*7c478bd9Sstevel@tonic-gate * Avoid the song and dance of recursively calling ypbind_ping 773*7c478bd9Sstevel@tonic-gate * for no reason. Consistent with the 4.1 policy, that if ypbind gets 774*7c478bd9Sstevel@tonic-gate * a request on new binder protocol, the requestor is looking for the 775*7c478bd9Sstevel@tonic-gate * new ypserv. And, we have even higher binder protocol version i.e. 3. 776*7c478bd9Sstevel@tonic-gate */ 777*7c478bd9Sstevel@tonic-gate } else 778*7c478bd9Sstevel@tonic-gate return (-1); 779*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 780*7c478bd9Sstevel@tonic-gate fprintf(stderr, 781*7c478bd9Sstevel@tonic-gate " saving server settings, \nsupports versions %d thru %d\n", 782*7c478bd9Sstevel@tonic-gate setd.ypsetdom_bindinfo->ypbind_lo_vers, 783*7c478bd9Sstevel@tonic-gate setd.ypsetdom_bindinfo->ypbind_hi_vers); 784*7c478bd9Sstevel@tonic-gate #endif 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if (opaque_domain->broadcaster_pipe == 0) { 787*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 788*7c478bd9Sstevel@tonic-gate fprintf(stderr, "PANIC: shouldn't be in this function\n"); 789*7c478bd9Sstevel@tonic-gate #endif 790*7c478bd9Sstevel@tonic-gate return (-2); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 793*7c478bd9Sstevel@tonic-gate fprintf(stderr, "child: doing xdr_ypbind_setdom\n"); 794*7c478bd9Sstevel@tonic-gate #endif 795*7c478bd9Sstevel@tonic-gate retval = xdr_ypbind_setdom(&(opaque_domain->broadcaster_xdr), &setd); 796*7c478bd9Sstevel@tonic-gate xdr_destroy(&(opaque_domain->broadcaster_xdr)); 797*7c478bd9Sstevel@tonic-gate fclose(opaque_domain->broadcaster_pipe); 798*7c478bd9Sstevel@tonic-gate close(opaque_domain->broadcaster_fd); 799*7c478bd9Sstevel@tonic-gate /* 800*7c478bd9Sstevel@tonic-gate * This child process is about to exit. Don't bother freeing memory. 801*7c478bd9Sstevel@tonic-gate */ 802*7c478bd9Sstevel@tonic-gate if (!retval) { 803*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 804*7c478bd9Sstevel@tonic-gate fprintf(stderr, 805*7c478bd9Sstevel@tonic-gate "YPBIND pipe_setdom failed \n(xdr failure) to server %s\n", 806*7c478bd9Sstevel@tonic-gate servername ? servername : ""); 807*7c478bd9Sstevel@tonic-gate #endif 808*7c478bd9Sstevel@tonic-gate return (-3); 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 811*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind_pipe_setdom: YPBIND OK-set to server %s\n", 812*7c478bd9Sstevel@tonic-gate servername ? servername : ""); 813*7c478bd9Sstevel@tonic-gate #endif 814*7c478bd9Sstevel@tonic-gate return (0); 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* Same as ypbind_set_binding in SunOS */ 818*7c478bd9Sstevel@tonic-gate /* 819*7c478bd9Sstevel@tonic-gate * We use a trick from SunOS to return an error to the ypset command 820*7c478bd9Sstevel@tonic-gate * when we are not allowing the domain to be set. We do a svcerr_noprog() 821*7c478bd9Sstevel@tonic-gate * to send RPC_PROGUNAVAIL to ypset. We also return NULL so that 822*7c478bd9Sstevel@tonic-gate * our caller (ypbindprog_3) won't try to return a result. This 823*7c478bd9Sstevel@tonic-gate * hack is necessary because the YPBINDPROC_SETDOM procedure is defined 824*7c478bd9Sstevel@tonic-gate * in the protocol to return xdr_void, so we don't have a direct way to 825*7c478bd9Sstevel@tonic-gate * return an error to the client. 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 828*7c478bd9Sstevel@tonic-gate void * 829*7c478bd9Sstevel@tonic-gate ypbindproc_setdom_3(argp, rqstp, transp) 830*7c478bd9Sstevel@tonic-gate ypbind_setdom *argp; 831*7c478bd9Sstevel@tonic-gate struct svc_req *rqstp; 832*7c478bd9Sstevel@tonic-gate SVCXPRT *transp; 833*7c478bd9Sstevel@tonic-gate { 834*7c478bd9Sstevel@tonic-gate struct domain *a_domain; 835*7c478bd9Sstevel@tonic-gate struct netbuf *who; 836*7c478bd9Sstevel@tonic-gate static char res; /* dummy for void * return */ 837*7c478bd9Sstevel@tonic-gate uid_t caller_uid; 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate if ((int)strlen(argp->ypsetdom_domain) > YPMAXDOMAIN) { 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate if (transp) { 842*7c478bd9Sstevel@tonic-gate svcerr_systemerr(transp); 843*7c478bd9Sstevel@tonic-gate return (0); 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate return (&res); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate if (transp != NULL) { 849*7c478bd9Sstevel@tonic-gate /* find out who originated the request */ 850*7c478bd9Sstevel@tonic-gate char *uaddr; 851*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate who = svc_getrpccaller(transp); 854*7c478bd9Sstevel@tonic-gate if ((nconf = getnetconfigent(transp->xp_netid)) 855*7c478bd9Sstevel@tonic-gate == (struct netconfig *)NULL) { 856*7c478bd9Sstevel@tonic-gate svcerr_systemerr(transp); 857*7c478bd9Sstevel@tonic-gate return (0); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { 860*7c478bd9Sstevel@tonic-gate uaddr = strdup("local host"); 861*7c478bd9Sstevel@tonic-gate } else { 862*7c478bd9Sstevel@tonic-gate uaddr = taddr2uaddr(nconf, who); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate if (setok != YPSETALL) { 865*7c478bd9Sstevel@tonic-gate /* for -ypset, it falls through and let anybody do a setdom ! */ 866*7c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0) { 867*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 868*7c478bd9Sstevel@tonic-gate "ypset request from %s not on loopback, \ 869*7c478bd9Sstevel@tonic-gate cannot set ypbind to %s", uaddr ? uaddr : "unknown source", 870*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername); 871*7c478bd9Sstevel@tonic-gate if (uaddr) 872*7c478bd9Sstevel@tonic-gate free(uaddr); 873*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 874*7c478bd9Sstevel@tonic-gate svcerr_noprog(transp); 875*7c478bd9Sstevel@tonic-gate return (0); 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate switch (setok) { 878*7c478bd9Sstevel@tonic-gate case YPSETNONE: 879*7c478bd9Sstevel@tonic-gate if (strcmp(nconf->nc_protofmly, 880*7c478bd9Sstevel@tonic-gate NC_LOOPBACK) == 0) 881*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 882*7c478bd9Sstevel@tonic-gate "ypset request to %s from %s failed - ypset not allowed", 883*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername, uaddr); 884*7c478bd9Sstevel@tonic-gate if (uaddr) 885*7c478bd9Sstevel@tonic-gate free(uaddr); 886*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 887*7c478bd9Sstevel@tonic-gate svcerr_noprog(transp); 888*7c478bd9Sstevel@tonic-gate return (0); 889*7c478bd9Sstevel@tonic-gate case YPSETLOCAL: 890*7c478bd9Sstevel@tonic-gate if (__rpc_get_local_uid(transp, 891*7c478bd9Sstevel@tonic-gate &caller_uid) < 0) { 892*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "ypset request from \ 893*7c478bd9Sstevel@tonic-gate unidentified local user on %s - ypset not allowed", 894*7c478bd9Sstevel@tonic-gate transp->xp_netid); 895*7c478bd9Sstevel@tonic-gate if (uaddr) 896*7c478bd9Sstevel@tonic-gate free(uaddr); 897*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 898*7c478bd9Sstevel@tonic-gate svcerr_noprog(transp); 899*7c478bd9Sstevel@tonic-gate return (0); 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate if (caller_uid != 0) { 902*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 903*7c478bd9Sstevel@tonic-gate "Set domain request to host %s \ 904*7c478bd9Sstevel@tonic-gate from local non-root user %ld failed - ypset not allowed", 905*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername, caller_uid); 906*7c478bd9Sstevel@tonic-gate if (uaddr) 907*7c478bd9Sstevel@tonic-gate free(uaddr); 908*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 909*7c478bd9Sstevel@tonic-gate svcerr_noprog(transp); 910*7c478bd9Sstevel@tonic-gate return (0); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Set domain request from %s : \ 915*7c478bd9Sstevel@tonic-gate setting server for domain %s to %s", uaddr ? uaddr : "UNKNOWN SOURCE", 916*7c478bd9Sstevel@tonic-gate argp->ypsetdom_domain, argp->ypsetdom_bindinfo->ypbind_servername); 917*7c478bd9Sstevel@tonic-gate if (uaddr) 918*7c478bd9Sstevel@tonic-gate free(uaddr); 919*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if ((a_domain = ypbind_point_to_domain(argp->ypsetdom_domain)) 923*7c478bd9Sstevel@tonic-gate != (struct domain *)NULL) { 924*7c478bd9Sstevel@tonic-gate /* setting binding; old may be invalid */ 925*7c478bd9Sstevel@tonic-gate uncache_binding(a_domain); 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate /* this does the set -- should copy the structure */ 928*7c478bd9Sstevel@tonic-gate free_ypbind_binding(a_domain->dom_binding); 929*7c478bd9Sstevel@tonic-gate if ((a_domain->dom_binding = 930*7c478bd9Sstevel@tonic-gate dup_ypbind_binding(argp->ypsetdom_bindinfo)) == NULL) { 931*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "ypbindproc_setdom_3: out of memory, ", 932*7c478bd9Sstevel@tonic-gate "dup_ypbind_binding failed\n"); 933*7c478bd9Sstevel@tonic-gate if (transp) { 934*7c478bd9Sstevel@tonic-gate svcerr_noprog(transp); 935*7c478bd9Sstevel@tonic-gate return (0); 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate return (&res); 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate gettimeofday(&(a_domain->lastping), NULL); 940*7c478bd9Sstevel@tonic-gate a_domain->dom_boundp = TRUE; 941*7c478bd9Sstevel@tonic-gate cache_binding(a_domain); 942*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 943*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbindproc_setdom_3: setting domain %s to server %s\n", 944*7c478bd9Sstevel@tonic-gate argp->ypsetdom_domain, 945*7c478bd9Sstevel@tonic-gate argp->ypsetdom_bindinfo->ypbind_servername); 946*7c478bd9Sstevel@tonic-gate #endif 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate return (&res); 950*7c478bd9Sstevel@tonic-gate } 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate /* 953*7c478bd9Sstevel@tonic-gate * This returns a pointer to a domain entry. If no such domain existed on 954*7c478bd9Sstevel@tonic-gate * the list previously, an entry will be allocated, initialized, and linked 955*7c478bd9Sstevel@tonic-gate * to the list. Note: If no memory can be malloc-ed for the domain structure, 956*7c478bd9Sstevel@tonic-gate * the functional value will be (struct domain *) NULL. 957*7c478bd9Sstevel@tonic-gate */ 958*7c478bd9Sstevel@tonic-gate static struct domain * 959*7c478bd9Sstevel@tonic-gate ypbind_point_to_domain(pname) 960*7c478bd9Sstevel@tonic-gate register char *pname; 961*7c478bd9Sstevel@tonic-gate { 962*7c478bd9Sstevel@tonic-gate register struct domain *pdom; 963*7c478bd9Sstevel@tonic-gate char buf[300]; 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate for (pdom = known_domains; pdom != (struct domain *)NULL; 966*7c478bd9Sstevel@tonic-gate pdom = pdom->dom_pnext) { 967*7c478bd9Sstevel@tonic-gate if (strcmp(pname, pdom->dom_name) == 0) 968*7c478bd9Sstevel@tonic-gate return (pdom); 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate /* Not found. Add it to the list */ 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (pdom = (struct domain *)calloc(1, sizeof (struct domain))) { 974*7c478bd9Sstevel@tonic-gate pdom->dom_name = strdup(pname); 975*7c478bd9Sstevel@tonic-gate if (pdom->dom_name == NULL) { 976*7c478bd9Sstevel@tonic-gate free((char *)pdom); 977*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 978*7c478bd9Sstevel@tonic-gate "ypbind_point_to_domain: strdup failed\n"); 979*7c478bd9Sstevel@tonic-gate return (NULL); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate pdom->dom_pnext = known_domains; 982*7c478bd9Sstevel@tonic-gate known_domains = pdom; 983*7c478bd9Sstevel@tonic-gate pdom->dom_boundp = FALSE; 984*7c478bd9Sstevel@tonic-gate pdom->dom_vers = YPVERS; /* This doesn't talk to old ypserv */ 985*7c478bd9Sstevel@tonic-gate pdom->dom_binding = NULL; 986*7c478bd9Sstevel@tonic-gate pdom->dom_error = YPBIND_ERR_NOSERV; 987*7c478bd9Sstevel@tonic-gate pdom->ping_clnt = (CLIENT *)NULL; 988*7c478bd9Sstevel@tonic-gate pdom->dom_report_success = -1; 989*7c478bd9Sstevel@tonic-gate pdom->dom_broadcaster_pid = 0; 990*7c478bd9Sstevel@tonic-gate pdom->broadcaster_pipe = 0; 991*7c478bd9Sstevel@tonic-gate pdom->bindfile = -1; 992*7c478bd9Sstevel@tonic-gate pdom->lastping.tv_sec = 0; 993*7c478bd9Sstevel@tonic-gate pdom->lastping.tv_usec = 0; /* require ping */ 994*7c478bd9Sstevel@tonic-gate pdom->cache_fp = 0; 995*7c478bd9Sstevel@tonic-gate sprintf(buf, "%s/%s/cache_binding", BINDING, pdom->dom_name); 996*7c478bd9Sstevel@tonic-gate pdom->cache_file = strdup(buf); 997*7c478bd9Sstevel@tonic-gate /* 998*7c478bd9Sstevel@tonic-gate * We don't give an error if pdom->cache_file is not set. 999*7c478bd9Sstevel@tonic-gate * If we got null (out of memory), then we just won't use 1000*7c478bd9Sstevel@tonic-gate * the cache file in cache_binding() (assuming the 1001*7c478bd9Sstevel@tonic-gate * application gets that far. 1002*7c478bd9Sstevel@tonic-gate */ 1003*7c478bd9Sstevel@tonic-gate } 1004*7c478bd9Sstevel@tonic-gate else 1005*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "ypbind_point_to_domain: malloc failed\n"); 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate return (pdom); 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate static void 1011*7c478bd9Sstevel@tonic-gate ypbind_ping(pdom) 1012*7c478bd9Sstevel@tonic-gate struct domain *pdom; 1013*7c478bd9Sstevel@tonic-gate { 1014*7c478bd9Sstevel@tonic-gate struct timeval timeout; 1015*7c478bd9Sstevel@tonic-gate int vers; 1016*7c478bd9Sstevel@tonic-gate int isok; 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate if (pdom->dom_boundp == FALSE) 1019*7c478bd9Sstevel@tonic-gate return; 1020*7c478bd9Sstevel@tonic-gate vers = pdom->dom_vers; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate if (pdom->ping_clnt == (CLIENT *) NULL) { 1023*7c478bd9Sstevel@tonic-gate pdom->ping_clnt = __nis_clnt_create(RPC_ANYFD, 1024*7c478bd9Sstevel@tonic-gate pdom->dom_binding->ypbind_nconf, 0, 1025*7c478bd9Sstevel@tonic-gate pdom->dom_binding->ypbind_svcaddr, 0, 1026*7c478bd9Sstevel@tonic-gate YPPROG, vers, 0, 0); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate if (pdom->ping_clnt == (CLIENT *) NULL) { 1030*7c478bd9Sstevel@tonic-gate perror("clnt_tli_create"); 1031*7c478bd9Sstevel@tonic-gate clnt_pcreateerror("ypbind_ping()"); 1032*7c478bd9Sstevel@tonic-gate pdom->dom_boundp = FALSE; 1033*7c478bd9Sstevel@tonic-gate pdom->dom_error = YPBIND_ERR_NOSERV; 1034*7c478bd9Sstevel@tonic-gate return; 1035*7c478bd9Sstevel@tonic-gate } 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1039*7c478bd9Sstevel@tonic-gate fprintf(stderr, "ypbind: ypbind_ping()\n"); 1040*7c478bd9Sstevel@tonic-gate #endif 1041*7c478bd9Sstevel@tonic-gate timeout.tv_sec = PINGTOTTIM; 1042*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 1043*7c478bd9Sstevel@tonic-gate if (clnt_call(pdom->ping_clnt, 1044*7c478bd9Sstevel@tonic-gate YPPROC_DOMAIN, (xdrproc_t)xdr_ypdomain_wrap_string, 1045*7c478bd9Sstevel@tonic-gate (char *)&pdom->dom_name, xdr_int, (char *)&isok, 1046*7c478bd9Sstevel@tonic-gate timeout) == RPC_SUCCESS) { 1047*7c478bd9Sstevel@tonic-gate pdom->dom_boundp = isok; 1048*7c478bd9Sstevel@tonic-gate pdom->dom_binding->ypbind_lo_vers = vers; 1049*7c478bd9Sstevel@tonic-gate pdom->dom_binding->ypbind_hi_vers = vers; 1050*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1051*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1052*7c478bd9Sstevel@tonic-gate "Server pinged successfully, supports versions %d thru %d\n", 1053*7c478bd9Sstevel@tonic-gate pdom->dom_binding->ypbind_lo_vers, 1054*7c478bd9Sstevel@tonic-gate pdom->dom_binding->ypbind_hi_vers); 1055*7c478bd9Sstevel@tonic-gate #endif 1056*7c478bd9Sstevel@tonic-gate } else { 1057*7c478bd9Sstevel@tonic-gate clnt_perror(pdom->ping_clnt, "ping"); 1058*7c478bd9Sstevel@tonic-gate pdom->dom_boundp = FALSE; 1059*7c478bd9Sstevel@tonic-gate pdom->dom_error = YPBIND_ERR_NOSERV; 1060*7c478bd9Sstevel@tonic-gate } 1061*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&(pdom->lastping), NULL); 1062*7c478bd9Sstevel@tonic-gate if (pdom->ping_clnt) 1063*7c478bd9Sstevel@tonic-gate clnt_destroy(pdom->ping_clnt); 1064*7c478bd9Sstevel@tonic-gate pdom->ping_clnt = (CLIENT *)NULL; 1065*7c478bd9Sstevel@tonic-gate if (pdom->dom_boundp) 1066*7c478bd9Sstevel@tonic-gate cache_binding(pdom); 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate static struct ypbind_binding * 1070*7c478bd9Sstevel@tonic-gate dup_ypbind_binding(a) 1071*7c478bd9Sstevel@tonic-gate struct ypbind_binding *a; 1072*7c478bd9Sstevel@tonic-gate { 1073*7c478bd9Sstevel@tonic-gate struct ypbind_binding *b; 1074*7c478bd9Sstevel@tonic-gate struct netconfig *nca, *ncb; 1075*7c478bd9Sstevel@tonic-gate struct netbuf *nxa, *nxb; 1076*7c478bd9Sstevel@tonic-gate int i; 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate b = (struct ypbind_binding *)calloc(1, sizeof (*b)); 1079*7c478bd9Sstevel@tonic-gate if (b == NULL) 1080*7c478bd9Sstevel@tonic-gate return (b); 1081*7c478bd9Sstevel@tonic-gate b->ypbind_hi_vers = a->ypbind_hi_vers; 1082*7c478bd9Sstevel@tonic-gate b->ypbind_lo_vers = a->ypbind_lo_vers; 1083*7c478bd9Sstevel@tonic-gate b->ypbind_servername = 1084*7c478bd9Sstevel@tonic-gate a->ypbind_servername ? strdup(a->ypbind_servername) : NULL; 1085*7c478bd9Sstevel@tonic-gate ncb = (b->ypbind_nconf = 1086*7c478bd9Sstevel@tonic-gate (struct netconfig *)calloc(1, sizeof (struct netconfig))); 1087*7c478bd9Sstevel@tonic-gate nxb = (b->ypbind_svcaddr = 1088*7c478bd9Sstevel@tonic-gate (struct netbuf *)calloc(1, sizeof (struct netbuf))); 1089*7c478bd9Sstevel@tonic-gate nca = a->ypbind_nconf; 1090*7c478bd9Sstevel@tonic-gate nxa = a->ypbind_svcaddr; 1091*7c478bd9Sstevel@tonic-gate ncb->nc_flag = nca->nc_flag; 1092*7c478bd9Sstevel@tonic-gate ncb->nc_protofmly = 1093*7c478bd9Sstevel@tonic-gate nca->nc_protofmly ? strdup(nca->nc_protofmly) : NULL; 1094*7c478bd9Sstevel@tonic-gate ncb->nc_proto = 1095*7c478bd9Sstevel@tonic-gate nca->nc_proto ? strdup(nca->nc_proto) : NULL; 1096*7c478bd9Sstevel@tonic-gate ncb->nc_semantics = nca->nc_semantics; 1097*7c478bd9Sstevel@tonic-gate ncb->nc_netid = 1098*7c478bd9Sstevel@tonic-gate nca->nc_netid ? strdup(nca->nc_netid) : NULL; 1099*7c478bd9Sstevel@tonic-gate ncb->nc_device = 1100*7c478bd9Sstevel@tonic-gate nca->nc_device ? strdup(nca->nc_device) : NULL; 1101*7c478bd9Sstevel@tonic-gate ncb->nc_nlookups = nca->nc_nlookups; 1102*7c478bd9Sstevel@tonic-gate ncb->nc_lookups = (char **)calloc(nca->nc_nlookups, sizeof (char *)); 1103*7c478bd9Sstevel@tonic-gate if (ncb->nc_lookups == NULL) { 1104*7c478bd9Sstevel@tonic-gate if (ncb->nc_device) 1105*7c478bd9Sstevel@tonic-gate free(ncb->nc_device); 1106*7c478bd9Sstevel@tonic-gate if (ncb->nc_netid) 1107*7c478bd9Sstevel@tonic-gate free(ncb->nc_netid); 1108*7c478bd9Sstevel@tonic-gate if (ncb->nc_proto) 1109*7c478bd9Sstevel@tonic-gate free(ncb->nc_proto); 1110*7c478bd9Sstevel@tonic-gate if (ncb->nc_protofmly) 1111*7c478bd9Sstevel@tonic-gate free(ncb->nc_protofmly); 1112*7c478bd9Sstevel@tonic-gate if (nxb) 1113*7c478bd9Sstevel@tonic-gate free(nxb); 1114*7c478bd9Sstevel@tonic-gate if (ncb) 1115*7c478bd9Sstevel@tonic-gate free(ncb); 1116*7c478bd9Sstevel@tonic-gate if (b->ypbind_servername) 1117*7c478bd9Sstevel@tonic-gate free(b->ypbind_servername); 1118*7c478bd9Sstevel@tonic-gate if (b) 1119*7c478bd9Sstevel@tonic-gate free(b); 1120*7c478bd9Sstevel@tonic-gate return (NULL); 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate for (i = 0; i < nca->nc_nlookups; i++) 1123*7c478bd9Sstevel@tonic-gate ncb->nc_lookups[i] = 1124*7c478bd9Sstevel@tonic-gate nca->nc_lookups[i] ? strdup(nca->nc_lookups[i]) : NULL; 1125*7c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) 1126*7c478bd9Sstevel@tonic-gate ncb->nc_unused[i] = nca->nc_unused[i]; 1127*7c478bd9Sstevel@tonic-gate nxb->maxlen = nxa->maxlen; 1128*7c478bd9Sstevel@tonic-gate nxb->len = nxa->len; 1129*7c478bd9Sstevel@tonic-gate nxb->buf = malloc(nxa->maxlen); 1130*7c478bd9Sstevel@tonic-gate if (nxb->buf == NULL) { 1131*7c478bd9Sstevel@tonic-gate for (i = 0; i < nca->nc_nlookups; i++) 1132*7c478bd9Sstevel@tonic-gate if (ncb->nc_lookups[i]) 1133*7c478bd9Sstevel@tonic-gate free(ncb->nc_lookups[i]); 1134*7c478bd9Sstevel@tonic-gate free(ncb->nc_lookups); 1135*7c478bd9Sstevel@tonic-gate if (ncb->nc_device) 1136*7c478bd9Sstevel@tonic-gate free(ncb->nc_device); 1137*7c478bd9Sstevel@tonic-gate if (ncb->nc_netid) 1138*7c478bd9Sstevel@tonic-gate free(ncb->nc_netid); 1139*7c478bd9Sstevel@tonic-gate if (ncb->nc_proto) 1140*7c478bd9Sstevel@tonic-gate free(ncb->nc_proto); 1141*7c478bd9Sstevel@tonic-gate if (ncb->nc_protofmly) 1142*7c478bd9Sstevel@tonic-gate free(ncb->nc_protofmly); 1143*7c478bd9Sstevel@tonic-gate if (nxb) 1144*7c478bd9Sstevel@tonic-gate free(nxb); 1145*7c478bd9Sstevel@tonic-gate if (ncb) 1146*7c478bd9Sstevel@tonic-gate free(ncb); 1147*7c478bd9Sstevel@tonic-gate if (b->ypbind_servername) 1148*7c478bd9Sstevel@tonic-gate free(b->ypbind_servername); 1149*7c478bd9Sstevel@tonic-gate if (b) 1150*7c478bd9Sstevel@tonic-gate free(b); 1151*7c478bd9Sstevel@tonic-gate return (NULL); 1152*7c478bd9Sstevel@tonic-gate } 1153*7c478bd9Sstevel@tonic-gate memcpy(nxb->buf, nxa->buf, nxb->len); 1154*7c478bd9Sstevel@tonic-gate return (b); 1155*7c478bd9Sstevel@tonic-gate } 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate static void 1158*7c478bd9Sstevel@tonic-gate free_ypbind_binding(b) 1159*7c478bd9Sstevel@tonic-gate struct ypbind_binding *b; 1160*7c478bd9Sstevel@tonic-gate { 1161*7c478bd9Sstevel@tonic-gate if (b == NULL) 1162*7c478bd9Sstevel@tonic-gate return; 1163*7c478bd9Sstevel@tonic-gate netdir_free((char *)b->ypbind_svcaddr, ND_ADDR); 1164*7c478bd9Sstevel@tonic-gate free(b->ypbind_servername); 1165*7c478bd9Sstevel@tonic-gate freenetconfigent(b->ypbind_nconf); 1166*7c478bd9Sstevel@tonic-gate free(b); 1167*7c478bd9Sstevel@tonic-gate } 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate /* 1170*7c478bd9Sstevel@tonic-gate * Preloads teh default domain's domain binding. Domain binding for the 1171*7c478bd9Sstevel@tonic-gate * local node's default domain for ypserv version 2 (YPVERS) will be 1172*7c478bd9Sstevel@tonic-gate * set up. This may make it a little slower to start ypbind during 1173*7c478bd9Sstevel@tonic-gate * boot time, but would make it easy on other domains that rely on 1174*7c478bd9Sstevel@tonic-gate * this binding. 1175*7c478bd9Sstevel@tonic-gate */ 1176*7c478bd9Sstevel@tonic-gate void 1177*7c478bd9Sstevel@tonic-gate ypbind_init_default() 1178*7c478bd9Sstevel@tonic-gate { 1179*7c478bd9Sstevel@tonic-gate char domain[256]; 1180*7c478bd9Sstevel@tonic-gate struct domain *cur_domain; 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate if (getdomainname(domain, 256) == 0) { 1183*7c478bd9Sstevel@tonic-gate cur_domain = ypbind_point_to_domain(domain); 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate if (cur_domain == (struct domain *)NULL) { 1186*7c478bd9Sstevel@tonic-gate abort(); 1187*7c478bd9Sstevel@tonic-gate } 1188*7c478bd9Sstevel@tonic-gate (void) pong_servers(cur_domain); 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate 1192*7c478bd9Sstevel@tonic-gate bool_t 1193*7c478bd9Sstevel@tonic-gate xdr_ypbind_binding_2(xdrs, objp) 1194*7c478bd9Sstevel@tonic-gate register XDR *xdrs; 1195*7c478bd9Sstevel@tonic-gate ypbind_binding_2 *objp; 1196*7c478bd9Sstevel@tonic-gate { 1197*7c478bd9Sstevel@tonic-gate if (!xdr_opaque(xdrs, (char *)&(objp->ypbind_binding_addr), 4)) 1198*7c478bd9Sstevel@tonic-gate return (FALSE); 1199*7c478bd9Sstevel@tonic-gate if (!xdr_opaque(xdrs, (char *)&(objp->ypbind_binding_port), 2)) 1200*7c478bd9Sstevel@tonic-gate return (FALSE); 1201*7c478bd9Sstevel@tonic-gate return (TRUE); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate bool_t 1205*7c478bd9Sstevel@tonic-gate xdr_ypbind_resp_2(xdrs, objp) 1206*7c478bd9Sstevel@tonic-gate register XDR *xdrs; 1207*7c478bd9Sstevel@tonic-gate ypbind_resp_2 *objp; 1208*7c478bd9Sstevel@tonic-gate { 1209*7c478bd9Sstevel@tonic-gate if (!xdr_ypbind_resptype(xdrs, &objp->ypbind_status)) 1210*7c478bd9Sstevel@tonic-gate return (FALSE); 1211*7c478bd9Sstevel@tonic-gate switch (objp->ypbind_status) { 1212*7c478bd9Sstevel@tonic-gate case YPBIND_FAIL_VAL: 1213*7c478bd9Sstevel@tonic-gate if (!xdr_u_long(xdrs, &objp->ypbind_respbody_2.ypbind_error)) 1214*7c478bd9Sstevel@tonic-gate return (FALSE); 1215*7c478bd9Sstevel@tonic-gate break; 1216*7c478bd9Sstevel@tonic-gate case YPBIND_SUCC_VAL: 1217*7c478bd9Sstevel@tonic-gate if (!xdr_ypbind_binding_2(xdrs, 1218*7c478bd9Sstevel@tonic-gate &objp->ypbind_respbody_2.ypbind_bindinfo)) 1219*7c478bd9Sstevel@tonic-gate return (FALSE); 1220*7c478bd9Sstevel@tonic-gate break; 1221*7c478bd9Sstevel@tonic-gate default: 1222*7c478bd9Sstevel@tonic-gate return (FALSE); 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate return (TRUE); 1225*7c478bd9Sstevel@tonic-gate } 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate /* 1228*7c478bd9Sstevel@tonic-gate * The following is some caching code to improve the performance of 1229*7c478bd9Sstevel@tonic-gate * yp clients. In the days of yore, a client would talk to rpcbind 1230*7c478bd9Sstevel@tonic-gate * to get the address for ypbind, then talk to ypbind to get the 1231*7c478bd9Sstevel@tonic-gate * address of the server. If a lot of clients are doing this at 1232*7c478bd9Sstevel@tonic-gate * the same time, then rpcbind and ypbind get bogged down and clients 1233*7c478bd9Sstevel@tonic-gate * start to time out. 1234*7c478bd9Sstevel@tonic-gate * 1235*7c478bd9Sstevel@tonic-gate * We cache two things: the current address for ypserv, and the 1236*7c478bd9Sstevel@tonic-gate * transport addresses for talking to ypbind. These are saved in 1237*7c478bd9Sstevel@tonic-gate * files in /var/yp. To get the address of ypserv, the client opens 1238*7c478bd9Sstevel@tonic-gate * a file and reads the address. It does not have to talk to rpcbind 1239*7c478bd9Sstevel@tonic-gate * or ypbind. If this file is not available, then it can read the 1240*7c478bd9Sstevel@tonic-gate * the transport address for talking to ypbind without bothering 1241*7c478bd9Sstevel@tonic-gate * rpcbind. If this also fails, then it uses the old method of 1242*7c478bd9Sstevel@tonic-gate * talking to rpcbind and then ypbind. 1243*7c478bd9Sstevel@tonic-gate * 1244*7c478bd9Sstevel@tonic-gate * We lock the first byte of the cache files after writing to them. 1245*7c478bd9Sstevel@tonic-gate * This indicates to the client that they contents are valid. The 1246*7c478bd9Sstevel@tonic-gate * client should test the lock. If the lock is held, then it can 1247*7c478bd9Sstevel@tonic-gate * use the contents. If the lock test fails, then the contents should 1248*7c478bd9Sstevel@tonic-gate * be ignored. 1249*7c478bd9Sstevel@tonic-gate */ 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate /* 1252*7c478bd9Sstevel@tonic-gate * Cache new binding information for a domain in a file. If the 1253*7c478bd9Sstevel@tonic-gate * new binding is the same as the old, then we skip it. We xdr 1254*7c478bd9Sstevel@tonic-gate * a 'ypbind_resp', which is what would be returned by a call to 1255*7c478bd9Sstevel@tonic-gate * the YBINDPROCP_DOMAIN service. We xdr the data because it is 1256*7c478bd9Sstevel@tonic-gate * easier than writing the data out field by field. It would be 1257*7c478bd9Sstevel@tonic-gate * nice if there were an xdrfd_create() that was similar to 1258*7c478bd9Sstevel@tonic-gate * xdrstdio_create(). Instead, we do an fdopen and use xdrstdio_create(). 1259*7c478bd9Sstevel@tonic-gate */ 1260*7c478bd9Sstevel@tonic-gate void 1261*7c478bd9Sstevel@tonic-gate cache_binding(pdom) 1262*7c478bd9Sstevel@tonic-gate struct domain *pdom; 1263*7c478bd9Sstevel@tonic-gate { 1264*7c478bd9Sstevel@tonic-gate int st; 1265*7c478bd9Sstevel@tonic-gate int fd; 1266*7c478bd9Sstevel@tonic-gate XDR xdrs; 1267*7c478bd9Sstevel@tonic-gate struct ypbind_resp resp; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate if (!cache_okay) 1270*7c478bd9Sstevel@tonic-gate return; 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate /* if the domain doesn't have a cache file, then skip it */ 1273*7c478bd9Sstevel@tonic-gate if (pdom->cache_file == 0) 1274*7c478bd9Sstevel@tonic-gate return; 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate /* 1277*7c478bd9Sstevel@tonic-gate * If we already had a cache file for this domain, remove it. If 1278*7c478bd9Sstevel@tonic-gate * a client just started accessing it, then it will either find 1279*7c478bd9Sstevel@tonic-gate * it unlocked (and not use it), or continue to use it with 1280*7c478bd9Sstevel@tonic-gate * old information. This is not a problem, the client will 1281*7c478bd9Sstevel@tonic-gate * either fail to talk to ypserv and try to bind again, or 1282*7c478bd9Sstevel@tonic-gate * will continue to use the old server. 1283*7c478bd9Sstevel@tonic-gate */ 1284*7c478bd9Sstevel@tonic-gate if (pdom->cache_fp) { 1285*7c478bd9Sstevel@tonic-gate fclose(pdom->cache_fp); /* automatically unlocks */ 1286*7c478bd9Sstevel@tonic-gate unlink(pdom->cache_file); 1287*7c478bd9Sstevel@tonic-gate pdom->cache_fp = 0; 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate fd = open(pdom->cache_file, O_CREAT|O_WRONLY, 0444); 1291*7c478bd9Sstevel@tonic-gate if (fd == -1) 1292*7c478bd9Sstevel@tonic-gate return; 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate pdom->cache_fp = fdopen(fd, "w"); 1295*7c478bd9Sstevel@tonic-gate if (pdom->cache_fp == 0) { 1296*7c478bd9Sstevel@tonic-gate close(fd); 1297*7c478bd9Sstevel@tonic-gate return; 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate xdrstdio_create(&xdrs, pdom->cache_fp, XDR_ENCODE); 1301*7c478bd9Sstevel@tonic-gate resp.ypbind_status = YPBIND_SUCC_VAL; 1302*7c478bd9Sstevel@tonic-gate resp.ypbind_resp_u.ypbind_bindinfo = pdom->dom_binding; 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate if (!xdr_ypbind_resp(&xdrs, &resp)) { 1305*7c478bd9Sstevel@tonic-gate xdr_destroy(&xdrs); 1306*7c478bd9Sstevel@tonic-gate unlink(pdom->cache_file); 1307*7c478bd9Sstevel@tonic-gate fclose(pdom->cache_fp); 1308*7c478bd9Sstevel@tonic-gate pdom->cache_fp = 0; 1309*7c478bd9Sstevel@tonic-gate return; 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate xdr_destroy(&xdrs); /* flushes xdr but leaves fp open */ 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate /* we lock the first byte to indicate that the file is valid */ 1314*7c478bd9Sstevel@tonic-gate lseek(fd, 0L, SEEK_SET); 1315*7c478bd9Sstevel@tonic-gate st = lockf(fd, F_LOCK, 1); 1316*7c478bd9Sstevel@tonic-gate if (st == -1) { 1317*7c478bd9Sstevel@tonic-gate unlink(pdom->cache_file); 1318*7c478bd9Sstevel@tonic-gate fclose(pdom->cache_fp); 1319*7c478bd9Sstevel@tonic-gate pdom->cache_fp = 0; 1320*7c478bd9Sstevel@tonic-gate } 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate void 1324*7c478bd9Sstevel@tonic-gate uncache_binding(pdom) 1325*7c478bd9Sstevel@tonic-gate struct domain *pdom; 1326*7c478bd9Sstevel@tonic-gate { 1327*7c478bd9Sstevel@tonic-gate if (!cache_okay) 1328*7c478bd9Sstevel@tonic-gate return; 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate if (pdom->cache_fp != 0) { 1331*7c478bd9Sstevel@tonic-gate unlink(pdom->cache_file); 1332*7c478bd9Sstevel@tonic-gate fclose(pdom->cache_fp); 1333*7c478bd9Sstevel@tonic-gate pdom->cache_fp = 0; 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate } 1336*7c478bd9Sstevel@tonic-gate 1337*7c478bd9Sstevel@tonic-gate /* 1338*7c478bd9Sstevel@tonic-gate * Cache a transport address for talking to ypbind. We convert the 1339*7c478bd9Sstevel@tonic-gate * transport address to a universal address and save that in a file. 1340*7c478bd9Sstevel@tonic-gate * The file lives in the binding directory because it does not depend 1341*7c478bd9Sstevel@tonic-gate * on the domain. 1342*7c478bd9Sstevel@tonic-gate */ 1343*7c478bd9Sstevel@tonic-gate void 1344*7c478bd9Sstevel@tonic-gate cache_transport(nconf, xprt, vers) 1345*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 1346*7c478bd9Sstevel@tonic-gate SVCXPRT *xprt; 1347*7c478bd9Sstevel@tonic-gate int vers; 1348*7c478bd9Sstevel@tonic-gate { 1349*7c478bd9Sstevel@tonic-gate char filename[300]; 1350*7c478bd9Sstevel@tonic-gate char *uaddr; 1351*7c478bd9Sstevel@tonic-gate int fd; 1352*7c478bd9Sstevel@tonic-gate int st; 1353*7c478bd9Sstevel@tonic-gate int len; 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate if (!cache_okay) 1356*7c478bd9Sstevel@tonic-gate return; 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate sprintf(filename, "%s/xprt.%s.%d", 1359*7c478bd9Sstevel@tonic-gate BINDING, nconf->nc_netid, vers); 1360*7c478bd9Sstevel@tonic-gate 1361*7c478bd9Sstevel@tonic-gate unlink(filename); /* remove any old version */ 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate uaddr = taddr2uaddr(nconf, &xprt->xp_ltaddr); 1364*7c478bd9Sstevel@tonic-gate if (uaddr == 0) 1365*7c478bd9Sstevel@tonic-gate return; 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate fd = open(filename, O_CREAT|O_WRONLY, 0444); /* readable by all */ 1368*7c478bd9Sstevel@tonic-gate if (fd == -1) { 1369*7c478bd9Sstevel@tonic-gate free(uaddr); 1370*7c478bd9Sstevel@tonic-gate return; 1371*7c478bd9Sstevel@tonic-gate } 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate len = strlen(uaddr) + 1; /* include terminating null */ 1374*7c478bd9Sstevel@tonic-gate st = write(fd, uaddr, len); 1375*7c478bd9Sstevel@tonic-gate if (st != len) { 1376*7c478bd9Sstevel@tonic-gate close(fd); 1377*7c478bd9Sstevel@tonic-gate unlink(filename); 1378*7c478bd9Sstevel@tonic-gate free(uaddr); 1379*7c478bd9Sstevel@tonic-gate return; 1380*7c478bd9Sstevel@tonic-gate } 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate free(uaddr); 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate /* we lock the first byte to indicate that the file is valid */ 1385*7c478bd9Sstevel@tonic-gate lseek(fd, 0L, SEEK_SET); 1386*7c478bd9Sstevel@tonic-gate st = lockf(fd, F_LOCK, 1); 1387*7c478bd9Sstevel@tonic-gate if (st == -1) { 1388*7c478bd9Sstevel@tonic-gate close(fd); 1389*7c478bd9Sstevel@tonic-gate unlink(filename); 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate /* 1394*7c478bd9Sstevel@tonic-gate * Create a file that clients can check to see if we are running. 1395*7c478bd9Sstevel@tonic-gate */ 1396*7c478bd9Sstevel@tonic-gate void 1397*7c478bd9Sstevel@tonic-gate cache_pid() 1398*7c478bd9Sstevel@tonic-gate { 1399*7c478bd9Sstevel@tonic-gate char filename[300]; 1400*7c478bd9Sstevel@tonic-gate char spid[15]; 1401*7c478bd9Sstevel@tonic-gate int fd; 1402*7c478bd9Sstevel@tonic-gate int st; 1403*7c478bd9Sstevel@tonic-gate int len; 1404*7c478bd9Sstevel@tonic-gate 1405*7c478bd9Sstevel@tonic-gate if (!cache_okay) 1406*7c478bd9Sstevel@tonic-gate return; 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate sprintf(filename, "%s/ypbind.pid", BINDING); 1409*7c478bd9Sstevel@tonic-gate 1410*7c478bd9Sstevel@tonic-gate unlink(filename); /* remove any old version */ 1411*7c478bd9Sstevel@tonic-gate 1412*7c478bd9Sstevel@tonic-gate fd = open(filename, O_CREAT|O_WRONLY, 0444); /* readable by all */ 1413*7c478bd9Sstevel@tonic-gate if (fd == -1) { 1414*7c478bd9Sstevel@tonic-gate return; 1415*7c478bd9Sstevel@tonic-gate } 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate sprintf(spid, "%d\n", getpid()); 1418*7c478bd9Sstevel@tonic-gate 1419*7c478bd9Sstevel@tonic-gate len = strlen(spid); 1420*7c478bd9Sstevel@tonic-gate st = write(fd, spid, len); 1421*7c478bd9Sstevel@tonic-gate if (st != len) { 1422*7c478bd9Sstevel@tonic-gate close(fd); 1423*7c478bd9Sstevel@tonic-gate unlink(filename); 1424*7c478bd9Sstevel@tonic-gate return; 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate /* we lock the first byte to indicate that the file is valid */ 1428*7c478bd9Sstevel@tonic-gate lseek(fd, 0L, SEEK_SET); 1429*7c478bd9Sstevel@tonic-gate st = lockf(fd, F_LOCK, 1); 1430*7c478bd9Sstevel@tonic-gate if (st == -1) { 1431*7c478bd9Sstevel@tonic-gate close(fd); 1432*7c478bd9Sstevel@tonic-gate unlink(filename); 1433*7c478bd9Sstevel@tonic-gate } 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate /* we keep 'fd' open so that the lock will continue to be held */ 1436*7c478bd9Sstevel@tonic-gate } 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate /* 1439*7c478bd9Sstevel@tonic-gate * We are called once at startup (when the known_domains list is empty) 1440*7c478bd9Sstevel@tonic-gate * to clean up left-over files. We are also called right before 1441*7c478bd9Sstevel@tonic-gate * exiting. In the latter case case we don't bother closing descriptors 1442*7c478bd9Sstevel@tonic-gate * in the entries in the domain list because they will be closed 1443*7c478bd9Sstevel@tonic-gate * automatically (and unlocked) when we exit. 1444*7c478bd9Sstevel@tonic-gate * 1445*7c478bd9Sstevel@tonic-gate * We ignore the cache_okay flag because it is important that we remove 1446*7c478bd9Sstevel@tonic-gate * all cache files (left-over files can temporarily confuse clients). 1447*7c478bd9Sstevel@tonic-gate */ 1448*7c478bd9Sstevel@tonic-gate void 1449*7c478bd9Sstevel@tonic-gate clean_cache() 1450*7c478bd9Sstevel@tonic-gate { 1451*7c478bd9Sstevel@tonic-gate struct domain *pdom; 1452*7c478bd9Sstevel@tonic-gate DIR *dir; 1453*7c478bd9Sstevel@tonic-gate struct dirent *dirent; 1454*7c478bd9Sstevel@tonic-gate char filename[300]; 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate /* close and unlink cache files for each domain */ 1457*7c478bd9Sstevel@tonic-gate for (pdom = known_domains; pdom != (struct domain *)NULL; 1458*7c478bd9Sstevel@tonic-gate pdom = pdom->dom_pnext) { 1459*7c478bd9Sstevel@tonic-gate if (pdom->cache_file) 1460*7c478bd9Sstevel@tonic-gate unlink(pdom->cache_file); 1461*7c478bd9Sstevel@tonic-gate } 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate sprintf(filename, "%s/ypbind.pid", BINDING); 1464*7c478bd9Sstevel@tonic-gate unlink(filename); 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate dir = opendir(BINDING); 1467*7c478bd9Sstevel@tonic-gate 1468*7c478bd9Sstevel@tonic-gate if (dir == NULL) { 1469*7c478bd9Sstevel@tonic-gate /* Directory could not be opened. */ 1470*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "opendir failed with [%s]", strerror(errno)); 1471*7c478bd9Sstevel@tonic-gate return; 1472*7c478bd9Sstevel@tonic-gate } 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate while ((dirent = readdir(dir)) != 0) { 1475*7c478bd9Sstevel@tonic-gate if (strncmp(dirent->d_name, "xprt.", 5) == 0) { 1476*7c478bd9Sstevel@tonic-gate sprintf(filename, "%s/%s", BINDING, dirent->d_name); 1477*7c478bd9Sstevel@tonic-gate unlink(filename); 1478*7c478bd9Sstevel@tonic-gate rewinddir(dir); /* removing file may harm iteration */ 1479*7c478bd9Sstevel@tonic-gate } 1480*7c478bd9Sstevel@tonic-gate } 1481*7c478bd9Sstevel@tonic-gate closedir(dir); 1482*7c478bd9Sstevel@tonic-gate } 1483*7c478bd9Sstevel@tonic-gate 1484*7c478bd9Sstevel@tonic-gate /* 1485*7c478bd9Sstevel@tonic-gate * We only want to use the cache stuff on local file systems. 1486*7c478bd9Sstevel@tonic-gate * For remote file systems (e.g., NFS, the locking overhead is 1487*7c478bd9Sstevel@tonic-gate * worse than the overhead of loopback RPC, so the caching 1488*7c478bd9Sstevel@tonic-gate * wouldn't buy us anything. In addition, if the remote locking 1489*7c478bd9Sstevel@tonic-gate * software isn't configured before we start, then we would 1490*7c478bd9Sstevel@tonic-gate * block when we try to lock. 1491*7c478bd9Sstevel@tonic-gate * 1492*7c478bd9Sstevel@tonic-gate * We don't have a direct way to tell if a file system is local 1493*7c478bd9Sstevel@tonic-gate * or remote, so we assume it is local unless it is NFS. 1494*7c478bd9Sstevel@tonic-gate */ 1495*7c478bd9Sstevel@tonic-gate int 1496*7c478bd9Sstevel@tonic-gate cache_check() 1497*7c478bd9Sstevel@tonic-gate { 1498*7c478bd9Sstevel@tonic-gate int st; 1499*7c478bd9Sstevel@tonic-gate struct statvfs stbuf; 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate st = statvfs(BINDING, &stbuf); 1502*7c478bd9Sstevel@tonic-gate if (st == -1) { 1503*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statvfs failed with [%s]", strerror(errno)); 1504*7c478bd9Sstevel@tonic-gate return (0); 1505*7c478bd9Sstevel@tonic-gate } 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate /* we use strncasecmp to get NFS, NFS3, nfs, nfs3, etc. */ 1508*7c478bd9Sstevel@tonic-gate if (strncasecmp(stbuf.f_basetype, "NFS", 3) == 0) 1509*7c478bd9Sstevel@tonic-gate return (0); 1510*7c478bd9Sstevel@tonic-gate return (1); 1511*7c478bd9Sstevel@tonic-gate } 1512