xref: /illumos-gate/usr/src/cmd/ypcmd/yppush.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5b892d001Svt  * Common Development and Distribution License (the "License").
6b892d001Svt  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  *
21b892d001Svt  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
227c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
237c478bd9Sstevel@tonic-gate  *
247c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
257c478bd9Sstevel@tonic-gate  * All Rights Reserved
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
287c478bd9Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
297c478bd9Sstevel@tonic-gate  * California.
307c478bd9Sstevel@tonic-gate  */
31*48bbca81SDaniel Hoffman /*
32*48bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
33*48bbca81SDaniel Hoffman  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define	_SVID_GETTOD
367c478bd9Sstevel@tonic-gate #include	<sys/time.h>
377c478bd9Sstevel@tonic-gate extern int gettimeofday(struct timeval *);
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include	<sys/types.h>
407c478bd9Sstevel@tonic-gate #include	<stdio.h>
417c478bd9Sstevel@tonic-gate #include	<string.h>
427c478bd9Sstevel@tonic-gate #include	<malloc.h>
437c478bd9Sstevel@tonic-gate #include	<errno.h>
447c478bd9Sstevel@tonic-gate #include	<signal.h>
457c478bd9Sstevel@tonic-gate #include	<limits.h>
467c478bd9Sstevel@tonic-gate #include	<stdlib.h>
477c478bd9Sstevel@tonic-gate #include	<unistd.h>
487c478bd9Sstevel@tonic-gate #include	<sys/types.h>
497c478bd9Sstevel@tonic-gate #include	<sys/wait.h>
507c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
517c478bd9Sstevel@tonic-gate #include	<ctype.h>
527c478bd9Sstevel@tonic-gate #include	<dirent.h>
537c478bd9Sstevel@tonic-gate #include	<rpc/rpc.h>
547c478bd9Sstevel@tonic-gate #include	<rpc/nettype.h>
557c478bd9Sstevel@tonic-gate #include	<rpc/rpcb_prot.h>
567c478bd9Sstevel@tonic-gate #include	<rpc/rpcb_clnt.h>
577c478bd9Sstevel@tonic-gate #include	<sys/systeminfo.h>
587c478bd9Sstevel@tonic-gate #include	<sys/select.h>
597c478bd9Sstevel@tonic-gate #include	"ypsym.h"
607c478bd9Sstevel@tonic-gate #include	"ypdefs.h"
617c478bd9Sstevel@tonic-gate #include	"yp_b.h"
627c478bd9Sstevel@tonic-gate #include	"shim.h"
637c478bd9Sstevel@tonic-gate #include	"yptol.h"
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #ifdef DEBUG
677c478bd9Sstevel@tonic-gate #undef YPPROG
687c478bd9Sstevel@tonic-gate #define	YPPROG ((ulong_t)109999)
697c478bd9Sstevel@tonic-gate #undef YPBINDPROG
707c478bd9Sstevel@tonic-gate #define	YPBINDPROG ((ulong_t)109998)
717c478bd9Sstevel@tonic-gate #endif
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #define	INTER_TRY 12			/* Seconds between tries */
747c478bd9Sstevel@tonic-gate #define	PORTMAP_TIME 30			/* Seconds before decide its down */
757c478bd9Sstevel@tonic-gate #define	TIMEOUT INTER_TRY*4		/* Total time for timeout */
767c478bd9Sstevel@tonic-gate #define	CUR_PAR 4			/* Total  parallal yppushes */
777c478bd9Sstevel@tonic-gate #define	MIN_GRACE 25			/* select timeout and minimum grace */
787c478bd9Sstevel@tonic-gate #define	GRACE_PERIOD 800		/* Total seconds we'll wait for	*/
797c478bd9Sstevel@tonic-gate 					/* responses from ypxfrs, yes	*/
807c478bd9Sstevel@tonic-gate 					/* virginia yp map transfers	*/
817c478bd9Sstevel@tonic-gate 					/* can take a long time, we	*/
827c478bd9Sstevel@tonic-gate 					/* only worry if the slave 	*/
837c478bd9Sstevel@tonic-gate 					/* crashes ...			*/
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate USE_YPDBPATH
867c478bd9Sstevel@tonic-gate static char *pusage;
877c478bd9Sstevel@tonic-gate static char *domain = NULL;
887c478bd9Sstevel@tonic-gate static char *host = NULL;
897c478bd9Sstevel@tonic-gate static char my_name[YPMAXPEER +1];
907c478bd9Sstevel@tonic-gate static char default_domain_name[YPMAXDOMAIN];
917c478bd9Sstevel@tonic-gate static char domain_alias[MAXNAMLEN]; 	/* nickname for domain -	*/
927c478bd9Sstevel@tonic-gate 					/*	used in sysv filesystems */
937c478bd9Sstevel@tonic-gate static char map_alias[MAXNAMLEN];	/* nickname for map -		*/
947c478bd9Sstevel@tonic-gate 					/*	used in sysv filesystems */
957c478bd9Sstevel@tonic-gate static char *map = NULL;
967c478bd9Sstevel@tonic-gate static bool verbose = FALSE;
977c478bd9Sstevel@tonic-gate static bool onehost = FALSE;
987c478bd9Sstevel@tonic-gate static bool oldxfr = FALSE;
997c478bd9Sstevel@tonic-gate static bool callback_timeout = FALSE;	/* set when a callback times out */
1007c478bd9Sstevel@tonic-gate int grace_period = GRACE_PERIOD;
1017c478bd9Sstevel@tonic-gate int curpar = CUR_PAR;			/* should be set by other stuff */
1027c478bd9Sstevel@tonic-gate static char ypmapname[1024];		/* Used to check for map's existence */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate static struct timeval intertry = {
1057c478bd9Sstevel@tonic-gate 	INTER_TRY,			/* Seconds */
1067c478bd9Sstevel@tonic-gate 	0				/* Microseconds */
1077c478bd9Sstevel@tonic-gate };
1087c478bd9Sstevel@tonic-gate static struct timeval timeout = {
1097c478bd9Sstevel@tonic-gate 	TIMEOUT,			/* Seconds */
1107c478bd9Sstevel@tonic-gate 	0				/* Microseconds */
1117c478bd9Sstevel@tonic-gate };
1127c478bd9Sstevel@tonic-gate static SVCXPRT *transport4;
1137c478bd9Sstevel@tonic-gate static SVCXPRT *transport6;
1147c478bd9Sstevel@tonic-gate struct server {
1157c478bd9Sstevel@tonic-gate 	struct server *pnext;
1167c478bd9Sstevel@tonic-gate 	struct dom_binding domb;
1177c478bd9Sstevel@tonic-gate 	char svc_name[YPMAXPEER+1];
1187c478bd9Sstevel@tonic-gate 	unsigned long xactid;
1197c478bd9Sstevel@tonic-gate 	unsigned short state;
1207c478bd9Sstevel@tonic-gate 	unsigned long status;
1217c478bd9Sstevel@tonic-gate 	bool oldvers;
1227c478bd9Sstevel@tonic-gate 	int start_time;
1237c478bd9Sstevel@tonic-gate };
1247c478bd9Sstevel@tonic-gate #define	n_conf dom_binding->ypbind_nconf
1257c478bd9Sstevel@tonic-gate #define	svc_addr dom_binding->ypbind_svcaddr
1267c478bd9Sstevel@tonic-gate static struct server *server_list = (struct server *)NULL;
1277c478bd9Sstevel@tonic-gate static struct server *active_list = (struct server *)NULL;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate /*  State values for server.state field */
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate #define	SSTAT_INIT 0
1327c478bd9Sstevel@tonic-gate #define	SSTAT_CALLED 1
1337c478bd9Sstevel@tonic-gate #define	SSTAT_RESPONDED 2
1347c478bd9Sstevel@tonic-gate #define	SSTAT_PROGNOTREG 3
1357c478bd9Sstevel@tonic-gate #define	SSTAT_RPC 4
1367c478bd9Sstevel@tonic-gate #define	SSTAT_RSCRC 5
1377c478bd9Sstevel@tonic-gate #define	SSTAT_SYSTEM 6
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate static char err_usage[] =
1407c478bd9Sstevel@tonic-gate "Usage:\n\typpush [-p <par>] [-d <domainname>] [-h <hostname>] [-v] map\n";
1417c478bd9Sstevel@tonic-gate static char err_bad_args[] =
1427c478bd9Sstevel@tonic-gate 	"The %s argument is bad.\n";
1437c478bd9Sstevel@tonic-gate static char err_cant_get_kname[] =
1447c478bd9Sstevel@tonic-gate 	"Can't get %s from system call.\n";
1457c478bd9Sstevel@tonic-gate static char err_null_kname[] =
1467c478bd9Sstevel@tonic-gate 	"The %s hasn't been set on this machine.\n";
1477c478bd9Sstevel@tonic-gate static char err_bad_domainname[] = "domainname";
1487c478bd9Sstevel@tonic-gate static char err_cant_bind[] =
1497c478bd9Sstevel@tonic-gate 	"Can't find a yp server for domain %s.  Reason:  %s.\n";
1507c478bd9Sstevel@tonic-gate static char err_cant_build_serverlist[] =
1517c478bd9Sstevel@tonic-gate 	"Can't build server list from map \"ypservers\".  Reason:  %s.\n";
1527c478bd9Sstevel@tonic-gate static char err_cant_find_host[] =
1537c478bd9Sstevel@tonic-gate 	"Can't find host %s in map \"ypservers\".\n";
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate  * State_duple table.  All messages should take 1 arg - the node name.
1567c478bd9Sstevel@tonic-gate  */
1577c478bd9Sstevel@tonic-gate struct state_duple {
1587c478bd9Sstevel@tonic-gate 	int state;
1597c478bd9Sstevel@tonic-gate 	char *state_msg;
1607c478bd9Sstevel@tonic-gate };
1617c478bd9Sstevel@tonic-gate static struct state_duple state_duples[] = {
1627c478bd9Sstevel@tonic-gate 	{SSTAT_INIT, "Internal error trying to talk to %s."},
1637c478bd9Sstevel@tonic-gate 	{SSTAT_CALLED, "%s has been called."},
1647c478bd9Sstevel@tonic-gate 	{SSTAT_RESPONDED, "%s (v1 ypserv) sent an old-style request."},
1657c478bd9Sstevel@tonic-gate 	{SSTAT_PROGNOTREG, "nis server not registered at %s."},
1667c478bd9Sstevel@tonic-gate 	{SSTAT_RPC, "RPC error to %s:  "},
1677c478bd9Sstevel@tonic-gate 	{SSTAT_RSCRC, "Local resource allocation failure - can't talk to %s."},
1687c478bd9Sstevel@tonic-gate 	{SSTAT_SYSTEM, "System error talking to %s:  "},
1697c478bd9Sstevel@tonic-gate 	{0, (char *)NULL}
1707c478bd9Sstevel@tonic-gate };
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Status_duple table.  No messages should require any args.
1737c478bd9Sstevel@tonic-gate  */
174a506a34cSth struct status_duple {
1757c478bd9Sstevel@tonic-gate 	long status;
1767c478bd9Sstevel@tonic-gate 	char *status_msg;
1777c478bd9Sstevel@tonic-gate };
1787c478bd9Sstevel@tonic-gate static struct status_duple status_duples[] = {
1797c478bd9Sstevel@tonic-gate 	{YPPUSH_SUCC, "Map successfully transferred."},
1807c478bd9Sstevel@tonic-gate 	{YPPUSH_AGE,
1817c478bd9Sstevel@tonic-gate 	    "Transfer not done:  master's version isn't newer."},
1827c478bd9Sstevel@tonic-gate 	{YPPUSH_NOMAP, "Failed - ypxfr there can't find a server for map."},
1837c478bd9Sstevel@tonic-gate 	{YPPUSH_NODOM, "Failed - domain isn't supported."},
1847c478bd9Sstevel@tonic-gate 	{YPPUSH_RSRC, "Failed - local resource allocation failure."},
1857c478bd9Sstevel@tonic-gate 	{YPPUSH_RPC, "Failed - ypxfr had an RPC failure"},
1867c478bd9Sstevel@tonic-gate 	{YPPUSH_MADDR, "Failed - ypxfr couldn't get the map master's address."},
1877c478bd9Sstevel@tonic-gate 	{YPPUSH_YPERR, "Failed - nis server or map format error."},
1887c478bd9Sstevel@tonic-gate 	{YPPUSH_BADARGS, "Failed - args to ypxfr were bad."},
1897c478bd9Sstevel@tonic-gate 	{YPPUSH_DBM, "Failed - dbm operation on map failed."},
1907c478bd9Sstevel@tonic-gate 	{YPPUSH_FILE, "Failed - file I/O operation on map failed"},
1917c478bd9Sstevel@tonic-gate 	{YPPUSH_SKEW, "Failed - map version skew during transfer."},
1927c478bd9Sstevel@tonic-gate 	{YPPUSH_CLEAR,
1937c478bd9Sstevel@tonic-gate 		"Map successfully transferred, but ypxfr \
1947c478bd9Sstevel@tonic-gate 		couldn't send \"Clear map\" to ypserv "},
1957c478bd9Sstevel@tonic-gate 	{YPPUSH_FORCE,
1967c478bd9Sstevel@tonic-gate 	    "Failed - no local order number in map - use -f flag to ypxfr."},
1977c478bd9Sstevel@tonic-gate 	{YPPUSH_XFRERR, "Failed - ypxfr internal error."},
1987c478bd9Sstevel@tonic-gate 	{YPPUSH_REFUSED, "Failed - Transfer request refused."},
1997c478bd9Sstevel@tonic-gate 	{YPPUSH_NOALIAS,
2007c478bd9Sstevel@tonic-gate 		"Failed - System V domain/map alias not in alias file."},
2017c478bd9Sstevel@tonic-gate 	{0, (char *)NULL}
2027c478bd9Sstevel@tonic-gate };
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * rpcerr_duple table
2057c478bd9Sstevel@tonic-gate  */
206a506a34cSth struct rpcerr_duple {
2077c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
2087c478bd9Sstevel@tonic-gate 	char *rpc_msg;
2097c478bd9Sstevel@tonic-gate };
2107c478bd9Sstevel@tonic-gate static struct rpcerr_duple rpcerr_duples[] = {
2117c478bd9Sstevel@tonic-gate 	{RPC_SUCCESS, "RPC success"},
2127c478bd9Sstevel@tonic-gate 	{RPC_CANTENCODEARGS, "RPC Can't encode args"},
2137c478bd9Sstevel@tonic-gate 	{RPC_CANTDECODERES, "RPC Can't decode results"},
2147c478bd9Sstevel@tonic-gate 	{RPC_CANTSEND, "RPC Can't send"},
2157c478bd9Sstevel@tonic-gate 	{RPC_CANTRECV, "RPC Can't recv"},
2167c478bd9Sstevel@tonic-gate 	{RPC_TIMEDOUT, "NIS server registered, but does not respond"},
2177c478bd9Sstevel@tonic-gate 	{RPC_VERSMISMATCH, "RPC version mismatch"},
2187c478bd9Sstevel@tonic-gate 	{RPC_AUTHERROR, "RPC auth error"},
2197c478bd9Sstevel@tonic-gate 	{RPC_PROGUNAVAIL, "RPC remote program unavailable"},
2207c478bd9Sstevel@tonic-gate 	{RPC_PROGVERSMISMATCH, "RPC program mismatch"},
2217c478bd9Sstevel@tonic-gate 	{RPC_PROCUNAVAIL, "RPC unknown procedure"},
2227c478bd9Sstevel@tonic-gate 	{RPC_CANTDECODEARGS, "RPC Can't decode args"},
2237c478bd9Sstevel@tonic-gate 	{RPC_UNKNOWNHOST, "unknown host"},
2247c478bd9Sstevel@tonic-gate 	{RPC_RPCBFAILURE, "rpcbind failure (host is down?)"},
2257c478bd9Sstevel@tonic-gate 	{RPC_PROGNOTREGISTERED, "RPC prog not registered"},
2267c478bd9Sstevel@tonic-gate 	{RPC_SYSTEMERROR, "RPC system error"},
2277c478bd9Sstevel@tonic-gate 	{RPC_SUCCESS, (char *)NULL}		/* Duplicate rpc_stat 	*/
2287c478bd9Sstevel@tonic-gate 						/* unused in list-end 	*/
2297c478bd9Sstevel@tonic-gate 						/* entry */
2307c478bd9Sstevel@tonic-gate };
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate static void get_default_domain_name(void);
2337c478bd9Sstevel@tonic-gate static void get_command_line_args(int argc, char **argv);
2347c478bd9Sstevel@tonic-gate static unsigned short send_message(struct server *ps,
2357c478bd9Sstevel@tonic-gate 					unsigned long program, long *err);
2367c478bd9Sstevel@tonic-gate static void make_server_list(void);
2377c478bd9Sstevel@tonic-gate static void one_host_list(void);
2387c478bd9Sstevel@tonic-gate static void add_server(char *sname, int namelen);
2397c478bd9Sstevel@tonic-gate static int  generate_callback(unsigned long *program);
2407c478bd9Sstevel@tonic-gate static void xactid_seed(unsigned long *xactid);
2417c478bd9Sstevel@tonic-gate static void main_loop(unsigned long program);
2427c478bd9Sstevel@tonic-gate static void listener_exit(unsigned long program, int stat);
2437c478bd9Sstevel@tonic-gate static void listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp);
2447c478bd9Sstevel@tonic-gate static void print_state_msg(struct server *s, long e);
2457c478bd9Sstevel@tonic-gate static void print_callback_msg(struct server *s);
2467c478bd9Sstevel@tonic-gate static void rpcerr_msg(enum clnt_stat e);
2477c478bd9Sstevel@tonic-gate static void get_xfr_response(SVCXPRT *transp);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate #ifdef SYSVCONFIG
2507c478bd9Sstevel@tonic-gate extern void sysvconfig(void);
2517c478bd9Sstevel@tonic-gate #endif
2527c478bd9Sstevel@tonic-gate extern int yp_getalias(char *key, char *key_alias, int maxlen);
2537c478bd9Sstevel@tonic-gate extern int getdomainname(char *, int);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate extern struct rpc_createerr rpc_createerr;
2567c478bd9Sstevel@tonic-gate extern CLIENT *__yp_clnt_create_rsvdport();
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)2597c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate 	unsigned long program;
262b892d001Svt 	struct stat64 sbuf;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	get_command_line_args(argc, argv);
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	if (!domain) {
2677c478bd9Sstevel@tonic-gate 		get_default_domain_name();
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate #ifdef SYSVCONFIG
2717c478bd9Sstevel@tonic-gate 	sysvconfig();
2727c478bd9Sstevel@tonic-gate #endif
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if (yp_getalias(domain, domain_alias, NAME_MAX) != 0)
2757c478bd9Sstevel@tonic-gate 		fprintf(stderr, "domain alias for %s not found\n", domain);
2767c478bd9Sstevel@tonic-gate 	if (yp_getalias(map, map_alias, MAXALIASLEN) != 0)
2777c478bd9Sstevel@tonic-gate 		fprintf(stderr, "map alias for %s not found\n", map);
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	/* check to see if the map exists in this domain */
2807c478bd9Sstevel@tonic-gate 	if (is_yptol_mode())
2817c478bd9Sstevel@tonic-gate 		sprintf(ypmapname, "%s/%s/%s%s.dir", ypdbpath, domain_alias,
282b892d001Svt 		    NTOL_PREFIX, map_alias);
2837c478bd9Sstevel@tonic-gate 	else
2847c478bd9Sstevel@tonic-gate 		sprintf(ypmapname, "%s/%s/%s.dir", ypdbpath, domain_alias,
285b892d001Svt 		    map_alias);
286b892d001Svt 	if (stat64(ypmapname, &sbuf) < 0) {
2877c478bd9Sstevel@tonic-gate 		fprintf(stderr, "yppush: Map does not exist.\n");
2887c478bd9Sstevel@tonic-gate 		exit(1);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	if (onehost) {
2927c478bd9Sstevel@tonic-gate 		one_host_list();
2937c478bd9Sstevel@tonic-gate 	} else {
2947c478bd9Sstevel@tonic-gate 		make_server_list();
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/*
2987c478bd9Sstevel@tonic-gate 	 * All process exits after the call to generate_callback should be
2997c478bd9Sstevel@tonic-gate 	 * through listener_exit(program, status), not exit(status), so the
3007c478bd9Sstevel@tonic-gate 	 * transient server can get unregistered with the portmapper.
3017c478bd9Sstevel@tonic-gate 	 */
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	if (!generate_callback(&program)) {
3047c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Can't set up transient callback server.\n");
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	main_loop(program);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	listener_exit(program, 0);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
3127c478bd9Sstevel@tonic-gate 	return (0);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate  * This does the command line parsing.
3177c478bd9Sstevel@tonic-gate  */
3187c478bd9Sstevel@tonic-gate static void
get_command_line_args(int argc,char ** argv)3197c478bd9Sstevel@tonic-gate get_command_line_args(int argc, char **argv)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate 	pusage = err_usage;
3227c478bd9Sstevel@tonic-gate 	argv++;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	if (argc < 2) {
3257c478bd9Sstevel@tonic-gate 		fprintf(stderr, pusage);
3267c478bd9Sstevel@tonic-gate 		exit(1);
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	while (--argc) {
3307c478bd9Sstevel@tonic-gate 		if ((*argv)[0] == '-') {
3317c478bd9Sstevel@tonic-gate 			switch ((*argv)[1]) {
3327c478bd9Sstevel@tonic-gate 			case 'v':
3337c478bd9Sstevel@tonic-gate 				verbose = TRUE;
3347c478bd9Sstevel@tonic-gate 				argv++;
3357c478bd9Sstevel@tonic-gate 				break;
3367c478bd9Sstevel@tonic-gate 			case 'd':
3377c478bd9Sstevel@tonic-gate 				if (argc > 1) {
3387c478bd9Sstevel@tonic-gate 					argv++;
3397c478bd9Sstevel@tonic-gate 					argc--;
3407c478bd9Sstevel@tonic-gate 					domain = *argv;
3417c478bd9Sstevel@tonic-gate 					argv++;
3427c478bd9Sstevel@tonic-gate 					if (((int)strlen(domain)) >
343b892d001Svt 					    YPMAXDOMAIN) {
3447c478bd9Sstevel@tonic-gate 						fprintf(stderr,
345b892d001Svt 						    err_bad_args,
346b892d001Svt 						    err_bad_domainname);
3477c478bd9Sstevel@tonic-gate 						exit(1);
3487c478bd9Sstevel@tonic-gate 					}
3497c478bd9Sstevel@tonic-gate 				} else {
3507c478bd9Sstevel@tonic-gate 					fprintf(stderr, pusage);
3517c478bd9Sstevel@tonic-gate 					exit(1);
3527c478bd9Sstevel@tonic-gate 				}
3537c478bd9Sstevel@tonic-gate 				break;
3547c478bd9Sstevel@tonic-gate 			case 'h':
3557c478bd9Sstevel@tonic-gate 				if (argc > 1) {
3567c478bd9Sstevel@tonic-gate 					onehost = TRUE;
3577c478bd9Sstevel@tonic-gate 					argv++;
3587c478bd9Sstevel@tonic-gate 					argc--;
3597c478bd9Sstevel@tonic-gate 					host = *argv;
3607c478bd9Sstevel@tonic-gate 					argv++;
3617c478bd9Sstevel@tonic-gate 				} else {
3627c478bd9Sstevel@tonic-gate 					fprintf(stderr, pusage);
3637c478bd9Sstevel@tonic-gate 					exit(1);
3647c478bd9Sstevel@tonic-gate 				}
3657c478bd9Sstevel@tonic-gate 				break;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 			case 'p':
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 				if (argc > 1) {
3707c478bd9Sstevel@tonic-gate 					argv++;
3717c478bd9Sstevel@tonic-gate 					argc--;
3727c478bd9Sstevel@tonic-gate 					if (sscanf(*argv, "%d", &curpar) != 1) {
3737c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, pusage);
3747c478bd9Sstevel@tonic-gate 						exit(1);
3757c478bd9Sstevel@tonic-gate 					}
3767c478bd9Sstevel@tonic-gate 					argv++;
3777c478bd9Sstevel@tonic-gate 					if (curpar < 1) {
3787c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, pusage);
3797c478bd9Sstevel@tonic-gate 						exit(1);
3807c478bd9Sstevel@tonic-gate 					}
3817c478bd9Sstevel@tonic-gate 				} else {
3827c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, pusage);
3837c478bd9Sstevel@tonic-gate 					exit(1);
3847c478bd9Sstevel@tonic-gate 				}
3857c478bd9Sstevel@tonic-gate 				break;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 			default:
3887c478bd9Sstevel@tonic-gate 				fprintf(stderr, pusage);
3897c478bd9Sstevel@tonic-gate 				exit(1);
3907c478bd9Sstevel@tonic-gate 			}
3917c478bd9Sstevel@tonic-gate 		} else {
3927c478bd9Sstevel@tonic-gate 			if (!map) {
3937c478bd9Sstevel@tonic-gate 				map = *argv;
3947c478bd9Sstevel@tonic-gate 			} else {
3957c478bd9Sstevel@tonic-gate 				fprintf(stderr, pusage);
3967c478bd9Sstevel@tonic-gate 				exit(1);
3977c478bd9Sstevel@tonic-gate 			}
3987c478bd9Sstevel@tonic-gate 			argv++;
3997c478bd9Sstevel@tonic-gate 		}
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	if (!map) {
4037c478bd9Sstevel@tonic-gate 		fprintf(stderr, pusage);
4047c478bd9Sstevel@tonic-gate 		exit(1);
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate  *  This gets the local kernel domainname, and sets the global domain to it.
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate static void
get_default_domain_name(void)4127c478bd9Sstevel@tonic-gate get_default_domain_name(void)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
4157c478bd9Sstevel@tonic-gate 		domain = default_domain_name;
4167c478bd9Sstevel@tonic-gate 	} else {
4177c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_get_kname, err_bad_domainname);
4187c478bd9Sstevel@tonic-gate 		exit(1);
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	if ((int)strlen(domain) == 0) {
4227c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_null_kname, err_bad_domainname);
4237c478bd9Sstevel@tonic-gate 		exit(1);
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /*
4287c478bd9Sstevel@tonic-gate  * This verifies that the hostname supplied by the user is in the map
4297c478bd9Sstevel@tonic-gate  * "ypservers" then calls add_server to make it the only entry on the
4307c478bd9Sstevel@tonic-gate  * list of servers.
4317c478bd9Sstevel@tonic-gate  */
4327c478bd9Sstevel@tonic-gate static void
one_host_list(void)4337c478bd9Sstevel@tonic-gate one_host_list(void)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	char *key;
4367c478bd9Sstevel@tonic-gate 	int keylen;
4377c478bd9Sstevel@tonic-gate 	char *val;
4387c478bd9Sstevel@tonic-gate 	int vallen;
4397c478bd9Sstevel@tonic-gate 	int err;
4407c478bd9Sstevel@tonic-gate 	char *ypservers = "ypservers";
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	if (verbose) {
4437c478bd9Sstevel@tonic-gate 		printf("Verifying YP server: %s\n", host);
4447c478bd9Sstevel@tonic-gate 		fflush(stdout);
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	if (err = yp_bind(domain_alias)) {
4487c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
4497c478bd9Sstevel@tonic-gate 		exit(1);
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	keylen = strlen(host);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	if (yp_match(domain_alias, ypservers, host, keylen,
455b892d001Svt 	    &val, &vallen)) {
4567c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_find_host, host);
4577c478bd9Sstevel@tonic-gate 		exit(1);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	add_server(host, keylen);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate  * This uses yp operations to retrieve each server name in the map
4657c478bd9Sstevel@tonic-gate  *  "ypservers".  add_server is called for each one to add it to the list of
4667c478bd9Sstevel@tonic-gate  *  servers.
4677c478bd9Sstevel@tonic-gate  */
4687c478bd9Sstevel@tonic-gate static void
make_server_list(void)4697c478bd9Sstevel@tonic-gate make_server_list(void)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate 	char *key;
4727c478bd9Sstevel@tonic-gate 	int keylen;
4737c478bd9Sstevel@tonic-gate 	char *outkey;
4747c478bd9Sstevel@tonic-gate 	int outkeylen;
4757c478bd9Sstevel@tonic-gate 	char *val;
4767c478bd9Sstevel@tonic-gate 	int vallen;
4777c478bd9Sstevel@tonic-gate 	int err;
4787c478bd9Sstevel@tonic-gate 	char *ypservers = "ypservers";
4797c478bd9Sstevel@tonic-gate 	int count;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (verbose) {
4827c478bd9Sstevel@tonic-gate 		printf("Finding YP servers: ");
4837c478bd9Sstevel@tonic-gate 		fflush(stdout);
4847c478bd9Sstevel@tonic-gate 		count = 4;
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if (err = yp_bind(domain_alias)) {
4887c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
4897c478bd9Sstevel@tonic-gate 		exit(1);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	if (err = yp_first(domain_alias, ypservers, &outkey, &outkeylen,
493b892d001Svt 	    &val, &vallen)) {
4947c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_build_serverlist, yperr_string(err));
4957c478bd9Sstevel@tonic-gate 		exit(1);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	for (;;) {
4997c478bd9Sstevel@tonic-gate 		add_server(outkey, outkeylen);
5007c478bd9Sstevel@tonic-gate 		if (verbose) {
5017c478bd9Sstevel@tonic-gate 			printf(" %s", outkey);
5027c478bd9Sstevel@tonic-gate 			fflush(stdout);
5037c478bd9Sstevel@tonic-gate 			if (count++ == 8) {
5047c478bd9Sstevel@tonic-gate 				printf("\n");
5057c478bd9Sstevel@tonic-gate 				count = 0;
5067c478bd9Sstevel@tonic-gate 			}
5077c478bd9Sstevel@tonic-gate 		}
5087c478bd9Sstevel@tonic-gate 		free(val);
5097c478bd9Sstevel@tonic-gate 		key = outkey;
5107c478bd9Sstevel@tonic-gate 		keylen = outkeylen;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		if (err = yp_next(domain_alias, ypservers, key, keylen,
513b892d001Svt 		    &outkey, &outkeylen, &val, &vallen)) {
5147c478bd9Sstevel@tonic-gate 
515b892d001Svt 			if (err == YPERR_NOMORE) {
516b892d001Svt 				break;
517b892d001Svt 			} else {
518b892d001Svt 				fprintf(stderr, err_cant_build_serverlist,
519b892d001Svt 				    yperr_string(err));
520b892d001Svt 				exit(1);
521b892d001Svt 			}
5227c478bd9Sstevel@tonic-gate 		}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 		free(key);
5257c478bd9Sstevel@tonic-gate 	}
5267c478bd9Sstevel@tonic-gate 	if (count != 0) {
5277c478bd9Sstevel@tonic-gate 		if (verbose)
5287c478bd9Sstevel@tonic-gate 			printf("\n");
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate  *  This adds a single server to the server list.
5347c478bd9Sstevel@tonic-gate  */
5357c478bd9Sstevel@tonic-gate static void
add_server(char * sname,int namelen)5367c478bd9Sstevel@tonic-gate add_server(char *sname, int namelen)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	struct server *ps;
5397c478bd9Sstevel@tonic-gate 	static unsigned long seq;
5407c478bd9Sstevel@tonic-gate 	static unsigned long xactid = 0;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	if (strcmp(sname, my_name) == 0)
5437c478bd9Sstevel@tonic-gate 		return;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	if (xactid == 0) {
5467c478bd9Sstevel@tonic-gate 		xactid_seed(&xactid);
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	if ((ps = (struct server *)malloc((unsigned)sizeof (struct server)))
5507c478bd9Sstevel@tonic-gate 		== (struct server *)NULL) {
5517c478bd9Sstevel@tonic-gate 		perror("yppush: malloc failure");
5527c478bd9Sstevel@tonic-gate 		exit(1);
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	sname[namelen] = '\0';
5567c478bd9Sstevel@tonic-gate 	strcpy(ps->svc_name, sname);
5577c478bd9Sstevel@tonic-gate 	ps->state = SSTAT_INIT;
5587c478bd9Sstevel@tonic-gate 	ps->status = 0;
5597c478bd9Sstevel@tonic-gate 	ps->oldvers = FALSE;
5607c478bd9Sstevel@tonic-gate 	ps->xactid = xactid + seq++;
5617c478bd9Sstevel@tonic-gate 	ps->pnext = server_list;
5627c478bd9Sstevel@tonic-gate 	server_list = ps;
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate /*
5667c478bd9Sstevel@tonic-gate  * This sets the base range for the transaction ids used in speaking the the
5677c478bd9Sstevel@tonic-gate  *  server ypxfr processes.
5687c478bd9Sstevel@tonic-gate  */
5697c478bd9Sstevel@tonic-gate static void
xactid_seed(unsigned long * xactid)5707c478bd9Sstevel@tonic-gate xactid_seed(unsigned long *xactid)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	struct timeval t;
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	if (gettimeofday(&t) == -1) {
5757c478bd9Sstevel@tonic-gate 		perror("yppush gettimeofday failure");
5767c478bd9Sstevel@tonic-gate 		*xactid = 1234567;
5777c478bd9Sstevel@tonic-gate 	} else {
5787c478bd9Sstevel@tonic-gate 		*xactid = t.tv_sec;
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate  *  This generates the channel which will be used as the listener process'
5847c478bd9Sstevel@tonic-gate  *  service rendezvous point, and comes up with a transient program number
5857c478bd9Sstevel@tonic-gate  *  for the use of the RPC messages from the ypxfr processes.
5867c478bd9Sstevel@tonic-gate  */
5877c478bd9Sstevel@tonic-gate static int
generate_callback(unsigned long * program)5887c478bd9Sstevel@tonic-gate generate_callback(unsigned long *program)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate 	unsigned long prognum = 0x40000000, maxprognum;
5917c478bd9Sstevel@tonic-gate 	union {
5927c478bd9Sstevel@tonic-gate 		unsigned long	p;
5937c478bd9Sstevel@tonic-gate 		unsigned char	b[sizeof (unsigned long)];
5947c478bd9Sstevel@tonic-gate 	} u;
5957c478bd9Sstevel@tonic-gate 	int ret, i;
5967c478bd9Sstevel@tonic-gate 	struct netconfig *nc4, *nc6, *nc;
5977c478bd9Sstevel@tonic-gate 	SVCXPRT *trans;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	nc4 = getnetconfigent("udp");
6007c478bd9Sstevel@tonic-gate 	nc6 = getnetconfigent("udp6");
6017c478bd9Sstevel@tonic-gate 	if (nc4 == 0 && nc6 == 0) {
6027c478bd9Sstevel@tonic-gate 		fprintf(stderr,
603b892d001Svt 		    "yppush: Could not get udp or udp6 netconfig entry\n");
6047c478bd9Sstevel@tonic-gate 		exit(1);
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	transport4 = (nc4 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc4, 0, 0, 0);
6087c478bd9Sstevel@tonic-gate 	transport6 = (nc6 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc6, 0, 0, 0);
6097c478bd9Sstevel@tonic-gate 	if (transport4 == 0 && transport6 == 0) {
6107c478bd9Sstevel@tonic-gate 		fprintf(stderr, "yppush: Could not create server handle(s)\n");
6117c478bd9Sstevel@tonic-gate 		exit(1);
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	/* Find the maximum possible program number using an unsigned long */
6157c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (u.b); i++)
6167c478bd9Sstevel@tonic-gate 		u.b[i] = 0xff;
6177c478bd9Sstevel@tonic-gate 	maxprognum = u.p;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	if (transport4 != 0) {
6207c478bd9Sstevel@tonic-gate 		trans = transport4;
6217c478bd9Sstevel@tonic-gate 		nc = nc4;
6227c478bd9Sstevel@tonic-gate 	} else {
6237c478bd9Sstevel@tonic-gate 		trans = transport6;
6247c478bd9Sstevel@tonic-gate 		nc = nc6;
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 	while (prognum < maxprognum && (ret =
627b892d001Svt 	    rpcb_set(prognum, YPPUSHVERS, nc, &trans->xp_ltaddr)) == 0)
6287c478bd9Sstevel@tonic-gate 		prognum++;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	if (ret == 0) {
6317c478bd9Sstevel@tonic-gate 		fprintf(stderr, "yppush: Could not create callback service\n");
6327c478bd9Sstevel@tonic-gate 		exit(1);
6337c478bd9Sstevel@tonic-gate 	} else {
6347c478bd9Sstevel@tonic-gate 		if (trans == transport4 && transport6 != 0) {
6357c478bd9Sstevel@tonic-gate 			ret = rpcb_set(prognum, YPPUSHVERS, nc6,
636b892d001Svt 			    &transport6->xp_ltaddr);
6377c478bd9Sstevel@tonic-gate 			if (ret == 0) {
6387c478bd9Sstevel@tonic-gate 				fprintf(stderr,
6397c478bd9Sstevel@tonic-gate 			"yppush: Could not create udp6 callback service\n");
6407c478bd9Sstevel@tonic-gate 				exit(1);
6417c478bd9Sstevel@tonic-gate 			}
6427c478bd9Sstevel@tonic-gate 		}
6437c478bd9Sstevel@tonic-gate 		*program = prognum;
6447c478bd9Sstevel@tonic-gate 	}
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	return (ret);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate  * This is the main loop. Send messages to each server,
6517c478bd9Sstevel@tonic-gate  * and then wait for a response.
6527c478bd9Sstevel@tonic-gate  */
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 
655a506a34cSth int
add_to_active()6567c478bd9Sstevel@tonic-gate add_to_active()
6577c478bd9Sstevel@tonic-gate {
6587c478bd9Sstevel@tonic-gate 	struct server  *ps;
6597c478bd9Sstevel@tonic-gate 	ps = server_list;
6607c478bd9Sstevel@tonic-gate 	if (ps == NULL)
6617c478bd9Sstevel@tonic-gate 		return (0);
6627c478bd9Sstevel@tonic-gate 	server_list = server_list->pnext;	/* delete from server_list */
6637c478bd9Sstevel@tonic-gate 	ps->pnext = active_list;
6647c478bd9Sstevel@tonic-gate 	active_list = ps;
6657c478bd9Sstevel@tonic-gate 	return (1);
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate 
668a506a34cSth int
delete_active(in)6697c478bd9Sstevel@tonic-gate delete_active(in)
6707c478bd9Sstevel@tonic-gate 	struct server  *in;
6717c478bd9Sstevel@tonic-gate {
6727c478bd9Sstevel@tonic-gate 	struct server  *p;
6737c478bd9Sstevel@tonic-gate 	struct server  *n;
6747c478bd9Sstevel@tonic-gate 	if (in == active_list) {
6757c478bd9Sstevel@tonic-gate 		active_list = active_list->pnext;
6767c478bd9Sstevel@tonic-gate 		return (1);
6777c478bd9Sstevel@tonic-gate 	}
6787c478bd9Sstevel@tonic-gate 	p = active_list;
6797c478bd9Sstevel@tonic-gate 	for (n = active_list; n; n = n->pnext) {
6807c478bd9Sstevel@tonic-gate 		if (in == n) {
6817c478bd9Sstevel@tonic-gate 			p->pnext = n->pnext;
6827c478bd9Sstevel@tonic-gate 			return (0);
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		}
6857c478bd9Sstevel@tonic-gate 		p = n;
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 	return (-1);
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate void
main_loop(program)6917c478bd9Sstevel@tonic-gate main_loop(program)
6927c478bd9Sstevel@tonic-gate 	unsigned long   program;
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate 	pollfd_t	*pollset = NULL;
6957c478bd9Sstevel@tonic-gate 	int		npollfds = 0;
6967c478bd9Sstevel@tonic-gate 	int		pollret;
6977c478bd9Sstevel@tonic-gate 	struct server	*ps;
6987c478bd9Sstevel@tonic-gate 	long		error;
6997c478bd9Sstevel@tonic-gate 	int		hpar;	/* this times par count */
7007c478bd9Sstevel@tonic-gate 	int		i;
7017c478bd9Sstevel@tonic-gate 	int		j;
7027c478bd9Sstevel@tonic-gate 	int		time_now;
7037c478bd9Sstevel@tonic-gate 	int		docb;
7047c478bd9Sstevel@tonic-gate 	int		actives = 0;
7057c478bd9Sstevel@tonic-gate 	int		dead = 0;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	if (grace_period < MIN_GRACE)
7087c478bd9Sstevel@tonic-gate 		grace_period = MIN_GRACE;
7097c478bd9Sstevel@tonic-gate 	if (transport4 != 0) {
7107c478bd9Sstevel@tonic-gate 		if (!svc_reg(transport4, program, YPPUSHVERS,
7117c478bd9Sstevel@tonic-gate 				listener_dispatch, 0)) {
7127c478bd9Sstevel@tonic-gate 			fprintf(stderr,
7137c478bd9Sstevel@tonic-gate 			"Can't set up transient udp callback server.\n");
7147c478bd9Sstevel@tonic-gate 		}
7157c478bd9Sstevel@tonic-gate 	}
7167c478bd9Sstevel@tonic-gate 	if (transport6 != 0) {
7177c478bd9Sstevel@tonic-gate 		if (!svc_reg(transport6, program, YPPUSHVERS,
7187c478bd9Sstevel@tonic-gate 				listener_dispatch, 0)) {
7197c478bd9Sstevel@tonic-gate 			fprintf(stderr,
7207c478bd9Sstevel@tonic-gate 			"Can't set up transient udp6 callback server.\n");
7217c478bd9Sstevel@tonic-gate 		}
7227c478bd9Sstevel@tonic-gate 	}
7237c478bd9Sstevel@tonic-gate 	for (;;) {
7247c478bd9Sstevel@tonic-gate 		time_now = time(0);
7257c478bd9Sstevel@tonic-gate 		if (server_list == NULL) {
7267c478bd9Sstevel@tonic-gate 			actives = 0;
7277c478bd9Sstevel@tonic-gate 			dead = 0;
7287c478bd9Sstevel@tonic-gate 			for (ps = active_list; ps; ps = ps->pnext)
7297c478bd9Sstevel@tonic-gate 				if (ps->state == SSTAT_CALLED) {
7307c478bd9Sstevel@tonic-gate 					if ((time_now - ps->start_time) <
7317c478bd9Sstevel@tonic-gate 								grace_period)
7327c478bd9Sstevel@tonic-gate 						actives++;
7337c478bd9Sstevel@tonic-gate 					else
7347c478bd9Sstevel@tonic-gate 						dead++;
7357c478bd9Sstevel@tonic-gate 				}
7367c478bd9Sstevel@tonic-gate 			if (actives == 0) {
7377c478bd9Sstevel@tonic-gate 				if (verbose) {
7387c478bd9Sstevel@tonic-gate 					printf("terminating %d dead\n", dead);
7397c478bd9Sstevel@tonic-gate 					fflush(stdout);
7407c478bd9Sstevel@tonic-gate 				}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 				for (ps = active_list; ps; ps = ps->pnext)
7437c478bd9Sstevel@tonic-gate 					if (ps->state == SSTAT_CALLED) {
7447c478bd9Sstevel@tonic-gate 						if ((time_now - ps->start_time)
7457c478bd9Sstevel@tonic-gate 							>= grace_period) {
7467c478bd9Sstevel@tonic-gate 							if (verbose) {
7477c478bd9Sstevel@tonic-gate 								printf(
7487c478bd9Sstevel@tonic-gate 		    "no response from %s -- grace of %d seconds expired.\n",
7497c478bd9Sstevel@tonic-gate 		    ps->svc_name, grace_period);
7507c478bd9Sstevel@tonic-gate 								fflush(stdout);
7517c478bd9Sstevel@tonic-gate 							}
7527c478bd9Sstevel@tonic-gate 							fprintf(stderr,
7537c478bd9Sstevel@tonic-gate 		    "No response from ypxfr on %s\n", ps->svc_name);
7547c478bd9Sstevel@tonic-gate 						}
7557c478bd9Sstevel@tonic-gate 					}
7567c478bd9Sstevel@tonic-gate 				break;
7577c478bd9Sstevel@tonic-gate 			}
7587c478bd9Sstevel@tonic-gate 		}
7597c478bd9Sstevel@tonic-gate 		actives = 0;
7607c478bd9Sstevel@tonic-gate 		for (ps = active_list; ps; ps = ps->pnext) {
7617c478bd9Sstevel@tonic-gate 			if (ps->state == SSTAT_CALLED) {
7627c478bd9Sstevel@tonic-gate 				if ((time_now - ps->start_time)
7637c478bd9Sstevel@tonic-gate 						< grace_period) {
7647c478bd9Sstevel@tonic-gate 					actives++;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 					if (verbose) {
7677c478bd9Sstevel@tonic-gate 						printf(
7687c478bd9Sstevel@tonic-gate 		    "No response yet from ypxfr on %s\n", ps->svc_name);
7697c478bd9Sstevel@tonic-gate 						fflush(stdout);
7707c478bd9Sstevel@tonic-gate 					}
7717c478bd9Sstevel@tonic-gate 				}
7727c478bd9Sstevel@tonic-gate 			} else {
7737c478bd9Sstevel@tonic-gate 				if (verbose) {
7747c478bd9Sstevel@tonic-gate 					printf("Deactivating  %s\n",
7757c478bd9Sstevel@tonic-gate 						ps->svc_name);
7767c478bd9Sstevel@tonic-gate 					fflush(stdout);
7777c478bd9Sstevel@tonic-gate 				}
7787c478bd9Sstevel@tonic-gate 				delete_active(ps);
7797c478bd9Sstevel@tonic-gate 			}
7807c478bd9Sstevel@tonic-gate 		}
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 		/* add someone to the active list keep up with curpar */
7837c478bd9Sstevel@tonic-gate 		for (i = 0; i < (curpar - actives); i++) {
7847c478bd9Sstevel@tonic-gate 			if (add_to_active()) {
7857c478bd9Sstevel@tonic-gate 				ps = active_list;
7867c478bd9Sstevel@tonic-gate 				ps->state = send_message(ps, program, &error);
7877c478bd9Sstevel@tonic-gate 				print_state_msg(ps, error);
7887c478bd9Sstevel@tonic-gate 				if (ps->state != SSTAT_CALLED)
7897c478bd9Sstevel@tonic-gate 					delete_active(ps);	/* zorch it */
7907c478bd9Sstevel@tonic-gate 				else
7917c478bd9Sstevel@tonic-gate 					ps->start_time = time(0); /* set time */
7927c478bd9Sstevel@tonic-gate 			}
7937c478bd9Sstevel@tonic-gate 		}
7947c478bd9Sstevel@tonic-gate 		docb = 0;
7957c478bd9Sstevel@tonic-gate 		for (ps = active_list; ps; ps = ps->pnext)
7967c478bd9Sstevel@tonic-gate 			if (ps->state == SSTAT_CALLED) {
7977c478bd9Sstevel@tonic-gate 				docb = 1;
7987c478bd9Sstevel@tonic-gate 				break;
7997c478bd9Sstevel@tonic-gate 			}
8007c478bd9Sstevel@tonic-gate 		if (docb == 0) {
8017c478bd9Sstevel@tonic-gate 			if (verbose) {
8027c478bd9Sstevel@tonic-gate 				printf("No one to wait for this pass.\n");
8037c478bd9Sstevel@tonic-gate 				fflush(stdout);
8047c478bd9Sstevel@tonic-gate 			}
8057c478bd9Sstevel@tonic-gate 			continue;	/* try curpar more */
8067c478bd9Sstevel@tonic-gate 		}
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 		if (npollfds != svc_max_pollfd) {
8097c478bd9Sstevel@tonic-gate 			pollset = realloc(pollset,
8107c478bd9Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
8117c478bd9Sstevel@tonic-gate 			npollfds = svc_max_pollfd;
8127c478bd9Sstevel@tonic-gate 		}
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 		/*
8157c478bd9Sstevel@tonic-gate 		 * Get existing array of pollfd's, should really compress
8167c478bd9Sstevel@tonic-gate 		 * this but it shouldn't get very large (or sparse).
8177c478bd9Sstevel@tonic-gate 		 */
8187c478bd9Sstevel@tonic-gate 		(void) memcpy(pollset, svc_pollfd,
8197c478bd9Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 		errno = 0;
8227c478bd9Sstevel@tonic-gate 		switch (pollret = poll(pollset, npollfds, MIN_GRACE * 1000)) {
8237c478bd9Sstevel@tonic-gate 		    case -1:
8247c478bd9Sstevel@tonic-gate 			if (errno != EINTR) {
8257c478bd9Sstevel@tonic-gate 				(void) perror("main loop select");
8267c478bd9Sstevel@tonic-gate 			}
8277c478bd9Sstevel@tonic-gate 			break;
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 		    case 0:
8307c478bd9Sstevel@tonic-gate 			if (verbose) {
8317c478bd9Sstevel@tonic-gate 				(void) printf("timeout in main loop select.\n");
8327c478bd9Sstevel@tonic-gate 				fflush(stdout);
8337c478bd9Sstevel@tonic-gate 			}
8347c478bd9Sstevel@tonic-gate 			break;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 		    default:
8377c478bd9Sstevel@tonic-gate 			svc_getreq_poll(pollset, pollret);
8387c478bd9Sstevel@tonic-gate 			break;
8397c478bd9Sstevel@tonic-gate 		}		/* switch */
8407c478bd9Sstevel@tonic-gate 	}			/* for */
8417c478bd9Sstevel@tonic-gate }
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate  * This does the listener process cleanup and process exit.
8457c478bd9Sstevel@tonic-gate  */
8467c478bd9Sstevel@tonic-gate static void
listener_exit(unsigned long program,int stat)8477c478bd9Sstevel@tonic-gate listener_exit(unsigned long program, int stat)
8487c478bd9Sstevel@tonic-gate {
8497c478bd9Sstevel@tonic-gate 	svc_unreg(program, YPPUSHVERS);
8507c478bd9Sstevel@tonic-gate 	exit(stat);
8517c478bd9Sstevel@tonic-gate }
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate /*
8547c478bd9Sstevel@tonic-gate  * This is the listener process' RPC service dispatcher.
8557c478bd9Sstevel@tonic-gate  */
8567c478bd9Sstevel@tonic-gate static void
listener_dispatch(struct svc_req * rqstp,SVCXPRT * transp)8577c478bd9Sstevel@tonic-gate listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
8587c478bd9Sstevel@tonic-gate {
8597c478bd9Sstevel@tonic-gate 	switch (rqstp->rq_proc) {
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	case YPPUSHPROC_NULL:
8627c478bd9Sstevel@tonic-gate 		if (!svc_sendreply(transp, xdr_void, 0)) {
863b892d001Svt 			fprintf(stderr, "Can't reply to rpc call.\n");
8647c478bd9Sstevel@tonic-gate 		}
8657c478bd9Sstevel@tonic-gate 		break;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	case YPPUSHPROC_XFRRESP:
8687c478bd9Sstevel@tonic-gate 		get_xfr_response(transp);
8697c478bd9Sstevel@tonic-gate 		break;
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	default:
8727c478bd9Sstevel@tonic-gate 		svcerr_noproc(transp);
8737c478bd9Sstevel@tonic-gate 		break;
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate  *  This dumps a server state message to stdout.  It is called in cases where
8807c478bd9Sstevel@tonic-gate  *  we have no expectation of receiving a callback from the remote ypxfr.
8817c478bd9Sstevel@tonic-gate  */
8827c478bd9Sstevel@tonic-gate static void
print_state_msg(struct server * s,long e)8837c478bd9Sstevel@tonic-gate print_state_msg(struct server *s, long e)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate 	struct state_duple *sd;
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	if (s->state == SSTAT_SYSTEM)
8887c478bd9Sstevel@tonic-gate 		return;			/* already printed */
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	if (!verbose && (s->state == SSTAT_RESPONDED ||
891b892d001Svt 	    s->state == SSTAT_CALLED))
8927c478bd9Sstevel@tonic-gate 		return;
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	for (sd = state_duples; sd->state_msg; sd++) {
8957c478bd9Sstevel@tonic-gate 		if (sd->state == s->state) {
8967c478bd9Sstevel@tonic-gate 			printf(sd->state_msg, s->svc_name);
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 			if (s->state == SSTAT_RPC) {
8997c478bd9Sstevel@tonic-gate 				rpcerr_msg((enum clnt_stat) e);
9007c478bd9Sstevel@tonic-gate 			}
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 			printf("\n");
9037c478bd9Sstevel@tonic-gate 			fflush(stdout);
9047c478bd9Sstevel@tonic-gate 			return;
9057c478bd9Sstevel@tonic-gate 		}
9067c478bd9Sstevel@tonic-gate 	}
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yppush: Bad server state value %d.\n", s->state);
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate /*
9127c478bd9Sstevel@tonic-gate  *  This dumps a transfer status message to stdout.  It is called in
9137c478bd9Sstevel@tonic-gate  *  response to a received RPC message from the called ypxfr.
9147c478bd9Sstevel@tonic-gate  */
9157c478bd9Sstevel@tonic-gate static void
print_callback_msg(struct server * s)9167c478bd9Sstevel@tonic-gate print_callback_msg(struct server *s)
9177c478bd9Sstevel@tonic-gate {
9187c478bd9Sstevel@tonic-gate 	register struct status_duple *sd;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	if (!verbose &&
921b892d001Svt 	    (s->status == YPPUSH_AGE) ||
922b892d001Svt 	    (s->status == YPPUSH_SUCC))
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 		return;
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	for (sd = status_duples; sd->status_msg; sd++) {
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 		if (sd->status == s->status) {
9297c478bd9Sstevel@tonic-gate 			printf("Status received from ypxfr on %s:\n\t%s\n",
930b892d001Svt 			    s->svc_name, sd->status_msg);
9317c478bd9Sstevel@tonic-gate 			fflush(stdout);
9327c478bd9Sstevel@tonic-gate 			return;
9337c478bd9Sstevel@tonic-gate 		}
9347c478bd9Sstevel@tonic-gate 	}
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yppush listener: Garbage transaction "
937b892d001Svt 	    "status (value %d) from ypxfr on %s.\n",
938b892d001Svt 	    (int)s->status, s->svc_name);
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate  *  This dumps an RPC error message to stdout.  This is basically a rewrite
9437c478bd9Sstevel@tonic-gate  *  of clnt_perrno, but writes to stdout instead of stderr.
9447c478bd9Sstevel@tonic-gate  */
9457c478bd9Sstevel@tonic-gate static void
rpcerr_msg(enum clnt_stat e)9467c478bd9Sstevel@tonic-gate rpcerr_msg(enum clnt_stat e)
9477c478bd9Sstevel@tonic-gate {
9487c478bd9Sstevel@tonic-gate 	struct rpcerr_duple *rd;
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	for (rd = rpcerr_duples; rd->rpc_msg; rd++) {
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 		if (rd->rpc_stat == e) {
9537c478bd9Sstevel@tonic-gate 			printf(rd->rpc_msg);
9547c478bd9Sstevel@tonic-gate 			return;
9557c478bd9Sstevel@tonic-gate 		}
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	fprintf(stderr, "Bad error code passed to rpcerr_msg: %d.\n", e);
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate /*
9627c478bd9Sstevel@tonic-gate  * This picks up the response from the ypxfr process which has been started
9637c478bd9Sstevel@tonic-gate  * up on the remote node.  The response status must be non-zero, otherwise
9647c478bd9Sstevel@tonic-gate  * the status will be set to "ypxfr error".
9657c478bd9Sstevel@tonic-gate  */
9667c478bd9Sstevel@tonic-gate static void
get_xfr_response(SVCXPRT * transp)9677c478bd9Sstevel@tonic-gate get_xfr_response(SVCXPRT *transp)
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate 	struct yppushresp_xfr resp;
9707c478bd9Sstevel@tonic-gate 	register struct server *s;
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 	if (!svc_getargs(transp, (xdrproc_t)xdr_yppushresp_xfr,
973b892d001Svt 	    (caddr_t)&resp)) {
9747c478bd9Sstevel@tonic-gate 		svcerr_decode(transp);
9757c478bd9Sstevel@tonic-gate 		return;
9767c478bd9Sstevel@tonic-gate 	}
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 	if (!svc_sendreply(transp, xdr_void, 0)) {
9797c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Can't reply to rpc call.\n");
9807c478bd9Sstevel@tonic-gate 	}
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	for (s = active_list; s; s = s->pnext) {
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 		if (s->xactid == resp.transid) {
9857c478bd9Sstevel@tonic-gate 			s->status  = resp.status ? resp.status: YPPUSH_XFRERR;
9867c478bd9Sstevel@tonic-gate 			print_callback_msg(s);
9877c478bd9Sstevel@tonic-gate 			s->state = SSTAT_RESPONDED;
9887c478bd9Sstevel@tonic-gate 			return;
9897c478bd9Sstevel@tonic-gate 		}
9907c478bd9Sstevel@tonic-gate 	}
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate  * This sends a message to a single ypserv process.  The return value is
9957c478bd9Sstevel@tonic-gate  * a state value.  If the RPC call fails because of a version
9967c478bd9Sstevel@tonic-gate  * mismatch, we'll assume that we're talking to a version 1 ypserv process,
997*48bbca81SDaniel Hoffman  * and will send it an old "YPPROC_GET" request, as was defined in the
9987c478bd9Sstevel@tonic-gate  * earlier version of yp_prot.h
9997c478bd9Sstevel@tonic-gate  */
10007c478bd9Sstevel@tonic-gate static unsigned short
send_message(struct server * ps,unsigned long program,long * err)10017c478bd9Sstevel@tonic-gate send_message(struct server *ps, unsigned long program, long *err)
10027c478bd9Sstevel@tonic-gate {
10037c478bd9Sstevel@tonic-gate 	struct ypreq_newxfr req;
10047c478bd9Sstevel@tonic-gate 	struct ypreq_xfr oldreq;
10057c478bd9Sstevel@tonic-gate 	enum clnt_stat s;
10067c478bd9Sstevel@tonic-gate 	struct rpc_err rpcerr;
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 	if ((ps->domb.dom_client = __yp_clnt_create_rsvdport(ps->svc_name,
1009b892d001Svt 	    YPPROG, YPVERS, (char *)NULL, 0, 0))  == NULL) {
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) {
10127c478bd9Sstevel@tonic-gate 			return (SSTAT_PROGNOTREG);
10137c478bd9Sstevel@tonic-gate 		} else {
10147c478bd9Sstevel@tonic-gate 			printf("Error talking to %s: ", ps->svc_name);
10157c478bd9Sstevel@tonic-gate 			rpcerr_msg(rpc_createerr.cf_stat);
10167c478bd9Sstevel@tonic-gate 			printf("\n");
10177c478bd9Sstevel@tonic-gate 			fflush(stdout);
10187c478bd9Sstevel@tonic-gate 			return (SSTAT_SYSTEM);
10197c478bd9Sstevel@tonic-gate 		}
10207c478bd9Sstevel@tonic-gate 	}
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, my_name, sizeof (my_name)) == -1) {
10237c478bd9Sstevel@tonic-gate 		return (SSTAT_RSCRC);
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 	if (!oldxfr) {
10277c478bd9Sstevel@tonic-gate 		req.ypxfr_domain = domain;
10287c478bd9Sstevel@tonic-gate 		req.ypxfr_map = map;
10297c478bd9Sstevel@tonic-gate 		req.ypxfr_ordernum = 0;
10307c478bd9Sstevel@tonic-gate 		req.ypxfr_owner = my_name;
10317c478bd9Sstevel@tonic-gate 		req.name = ps->svc_name;
10327c478bd9Sstevel@tonic-gate 		/*
10337c478bd9Sstevel@tonic-gate 		 * the creation of field req.name, instead of ypreq_xfr (old)
10347c478bd9Sstevel@tonic-gate 		 * req.port, does not make any sense. it doesn't give any
10357c478bd9Sstevel@tonic-gate 		 * information to receiving ypserv except its own name !!
10367c478bd9Sstevel@tonic-gate 		 * new ypserv duplicates work for YPPROC_XFR and YPPROC_NEWXFR
10377c478bd9Sstevel@tonic-gate 		 */
10387c478bd9Sstevel@tonic-gate 		req.transid = ps->xactid;
10397c478bd9Sstevel@tonic-gate 		req.proto = program;
10407c478bd9Sstevel@tonic-gate 		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1041b892d001Svt 		    YPPROC_NEWXFR, (xdrproc_t)xdr_ypreq_newxfr, (caddr_t)&req,
1042b892d001Svt 		    xdr_void, 0, timeout);
10437c478bd9Sstevel@tonic-gate 	}
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	clnt_geterr(ps->domb.dom_client, &rpcerr);
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	if (s == RPC_PROCUNAVAIL) {
10487c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_domain = domain;
10497c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_map = map;
10507c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_ordernum = 0;
10517c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_owner = my_name;
10527c478bd9Sstevel@tonic-gate 		oldreq.transid = ps->xactid;
10537c478bd9Sstevel@tonic-gate 		oldreq.proto = program;
10547c478bd9Sstevel@tonic-gate 		oldreq.port = 0;
10557c478bd9Sstevel@tonic-gate 		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1056b892d001Svt 		    YPPROC_XFR, (xdrproc_t)xdr_ypreq_xfr, (caddr_t)&oldreq,
1057b892d001Svt 		    xdr_void, 0, timeout);
10587c478bd9Sstevel@tonic-gate 		clnt_geterr(ps->domb.dom_client, &rpcerr);
10597c478bd9Sstevel@tonic-gate 	}
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	clnt_destroy(ps->domb.dom_client);
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 	if (s == RPC_SUCCESS) {
10647c478bd9Sstevel@tonic-gate 		return (SSTAT_CALLED);
10657c478bd9Sstevel@tonic-gate 	} else {
10667c478bd9Sstevel@tonic-gate 		*err = (long)rpcerr.re_status;
10677c478bd9Sstevel@tonic-gate 		return (SSTAT_RPC);
10687c478bd9Sstevel@tonic-gate 	}
10697c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate /*
10737c478bd9Sstevel@tonic-gate  * FUNCTION:    is_yptol_mode();
10747c478bd9Sstevel@tonic-gate  *
10757c478bd9Sstevel@tonic-gate  * DESCRIPTION: Determines if we should run in N2L or traditional mode based
10767c478bd9Sstevel@tonic-gate  *              on the presence of the N2L mapping file.
10777c478bd9Sstevel@tonic-gate  *
10787c478bd9Sstevel@tonic-gate  *		This is a copy of a function from libnisdb. If more than this
10797c478bd9Sstevel@tonic-gate  *		one function become required it may be worth linking the
10807c478bd9Sstevel@tonic-gate  *		entire lib.
10817c478bd9Sstevel@tonic-gate  *
10827c478bd9Sstevel@tonic-gate  * INPUTS:      Nothing
10837c478bd9Sstevel@tonic-gate  *
10847c478bd9Sstevel@tonic-gate  * OUTPUTS:     TRUE = Run in N2L mode
10857c478bd9Sstevel@tonic-gate  *              FALSE = Run in traditional mode.
10867c478bd9Sstevel@tonic-gate  */
10877c478bd9Sstevel@tonic-gate bool_t
is_yptol_mode()10887c478bd9Sstevel@tonic-gate is_yptol_mode()
10897c478bd9Sstevel@tonic-gate {
10907c478bd9Sstevel@tonic-gate 	struct stat filestat;
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	if (stat(NTOL_MAP_FILE, &filestat) != -1)
10937c478bd9Sstevel@tonic-gate 		return (TRUE);
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	return (FALSE);
10967c478bd9Sstevel@tonic-gate }
1097