xref: /onnv-gate/usr/src/cmd/ypcmd/ypxfr.c (revision 702:9495c7c1ed3a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  *
22*702Sth160488  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /*	  All Rights Reserved   */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
310Sstevel@tonic-gate  * under license from the Regents of the University of
320Sstevel@tonic-gate  * California.
330Sstevel@tonic-gate  */
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * This is a user command which gets a NIS data base from some running
390Sstevel@tonic-gate  * server, and gets it to the local site by using the normal NIS client
400Sstevel@tonic-gate  * enumeration functions.  The map is copied to a temp name, then the real
410Sstevel@tonic-gate  * map is removed and the temp map is moved to the real name.  ypxfr then
420Sstevel@tonic-gate  * sends a "YPPROC_CLEAR" message to the local server to insure that he will
430Sstevel@tonic-gate  * not hold a removed map open, so serving an obsolete version.
440Sstevel@tonic-gate  *
450Sstevel@tonic-gate  * ypxfr [ -h <host> ] [ -d <domainname> ]
460Sstevel@tonic-gate  *		[ -s <domainname> ] [-f] [-c] [-C tid prot name] map
470Sstevel@tonic-gate  *
480Sstevel@tonic-gate  * If the host is ommitted, ypxfr will attempt to discover the master by
490Sstevel@tonic-gate  * using normal NIS services.  If it can't get the record, it will use
500Sstevel@tonic-gate  * the address of the callback, if specified. If the host is specified
510Sstevel@tonic-gate  * as an internet address, no NIS services need to be locally available.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * If the domain is not specified, the default domain of the local machine
540Sstevel@tonic-gate  * is used.
550Sstevel@tonic-gate  *
560Sstevel@tonic-gate  * If the -f flag is used, the transfer will be done even if the master's
570Sstevel@tonic-gate  * copy is not newer than the local copy.
580Sstevel@tonic-gate  *
590Sstevel@tonic-gate  * The -c flag suppresses the YPPROC_CLEAR request to the local ypserv.  It
600Sstevel@tonic-gate  * may be used if ypserv isn't currently running to suppress the error message.
610Sstevel@tonic-gate  *
620Sstevel@tonic-gate  * The -C flag is used to pass callback information to ypxfr when it is
630Sstevel@tonic-gate  * activated by ypserv.  The callback information is used to send a
640Sstevel@tonic-gate  * yppushresp_xfr message with transaction id "tid" to a yppush process
650Sstevel@tonic-gate  * speaking a transient protocol number "prot".  The yppush program is
660Sstevel@tonic-gate  * running on the host "name".
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * The -s option is used to specify a source domain which may be
690Sstevel@tonic-gate  * different from the destination domain, for transfer of maps
700Sstevel@tonic-gate  * that are identical in different domains (e.g. services.byname)
710Sstevel@tonic-gate  *
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #include <ndbm.h>
750Sstevel@tonic-gate #undef NULL
760Sstevel@tonic-gate #define	DATUM
770Sstevel@tonic-gate 
780Sstevel@tonic-gate #include <stdio.h>
790Sstevel@tonic-gate #include <errno.h>
800Sstevel@tonic-gate #include <time.h>
810Sstevel@tonic-gate #include <ctype.h>
820Sstevel@tonic-gate #include <netdb.h>
830Sstevel@tonic-gate #include <netconfig.h>
840Sstevel@tonic-gate #include <netdir.h>
850Sstevel@tonic-gate #include <rpc/rpc.h>
860Sstevel@tonic-gate #include <sys/file.h>
870Sstevel@tonic-gate #include <sys/stat.h>
880Sstevel@tonic-gate #include <dirent.h>
890Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
900Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
910Sstevel@tonic-gate #include <unistd.h>
920Sstevel@tonic-gate #include <stdlib.h>
930Sstevel@tonic-gate #include <rpcsvc/nis.h>
940Sstevel@tonic-gate #include "ypdefs.h"
950Sstevel@tonic-gate #include "yp_b.h"
960Sstevel@tonic-gate #include "shim.h"
970Sstevel@tonic-gate #include "yptol.h"
980Sstevel@tonic-gate 
990Sstevel@tonic-gate USE_YP_MASTER_NAME
1000Sstevel@tonic-gate USE_YP_SECURE
1010Sstevel@tonic-gate USE_YP_INTERDOMAIN
1020Sstevel@tonic-gate USE_YP_LAST_MODIFIED
1030Sstevel@tonic-gate USE_YPDBPATH
1040Sstevel@tonic-gate USE_DBM
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate #define	PARANOID 1	/* make sure maps have the right # entries */
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate #define	CALLINTER_TRY 10		/* Seconds between callback tries */
1090Sstevel@tonic-gate #define	CALLTIMEOUT CALLINTER_TRY*6	/* Total timeout for callback */
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate DBM *db;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate /* ypxfr never uses N2L mode */
1140Sstevel@tonic-gate bool_t yptol_mode = FALSE;
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate int	debug = FALSE;
1170Sstevel@tonic-gate int	treepush = FALSE;
1180Sstevel@tonic-gate #define	TREEPUSH 1
1190Sstevel@tonic-gate int	defwrite = TRUE;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate char *domain = NULL;
1220Sstevel@tonic-gate char *source = NULL;
1230Sstevel@tonic-gate char *map = NULL;
1240Sstevel@tonic-gate char *master = NULL;
1250Sstevel@tonic-gate char *pushhost = NULL;
1260Sstevel@tonic-gate /*
1270Sstevel@tonic-gate  * The name of the xfer peer as specified as a
1280Sstevel@tonic-gate  * -h option, -C name option or from querying the NIS
1290Sstevel@tonic-gate  */
1300Sstevel@tonic-gate struct dom_binding master_server; /* To talk to above */
1310Sstevel@tonic-gate unsigned int master_prog_vers;	/* YPVERS (barfs at YPOLDVERS !) */
1320Sstevel@tonic-gate char *master_name = NULL;	/* Map's master as contained in the map */
1330Sstevel@tonic-gate unsigned *master_version = NULL; /* Order number as contained in the map */
1340Sstevel@tonic-gate char *master_ascii_version;	/* ASCII order number as contained in the map */
1350Sstevel@tonic-gate bool fake_master_version = FALSE;
1360Sstevel@tonic-gate /*
1370Sstevel@tonic-gate  * TRUE only if there's no order number in
1380Sstevel@tonic-gate  *  the map, and the user specified -f
1390Sstevel@tonic-gate  */
1400Sstevel@tonic-gate bool force = FALSE;		/* TRUE iff user specified -f flag */
1410Sstevel@tonic-gate bool logging = FALSE;		/* TRUE iff no tty, but log file exists */
1420Sstevel@tonic-gate bool check_count = FALSE;	/* TRUE causes counts to be checked */
1430Sstevel@tonic-gate bool send_clear = TRUE;		/* FALSE iff user specified -c flag */
1440Sstevel@tonic-gate bool callback = FALSE;
1450Sstevel@tonic-gate /*
1460Sstevel@tonic-gate  * TRUE iff -C flag set.  tid, proto and name
1470Sstevel@tonic-gate  * will be set to point to the command line args.
1480Sstevel@tonic-gate  */
1490Sstevel@tonic-gate bool secure_map = FALSE;	/* TRUE if there is yp_secure in the map */
1500Sstevel@tonic-gate bool interdomain_map = FALSE;
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate  * TRUE if there is yp_interdomain in either
1530Sstevel@tonic-gate  * the local or the master version of the map
1540Sstevel@tonic-gate  */
1550Sstevel@tonic-gate int interdomain_sz = 0;		/* Size of the interdomain value */
1560Sstevel@tonic-gate #define	UDPINTER_TRY 10		/* Seconds between tries for udp */
1570Sstevel@tonic-gate #define	UDPTIMEOUT UDPINTER_TRY*4	/* Total timeout for udp */
1580Sstevel@tonic-gate #define	CALLINTER_TRY 10	/* Seconds between callback tries */
1590Sstevel@tonic-gate #define	CALLTIMEOUT CALLINTER_TRY*6	/* Total timeout for callback */
1600Sstevel@tonic-gate struct timeval udp_timeout = { UDPTIMEOUT, 0};
1610Sstevel@tonic-gate struct timeval tcp_timeout = { 180, 0}; /* Timeout for map enumeration */
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate char *interdomain_value; 	/* place to store the interdomain value */
1640Sstevel@tonic-gate char *tid;
1650Sstevel@tonic-gate char *proto;
1660Sstevel@tonic-gate int entry_count;		/* counts entries in the map */
1670Sstevel@tonic-gate char logfile[] = "/var/yp/ypxfr.log";
1680Sstevel@tonic-gate static char err_usage[] =
1690Sstevel@tonic-gate "Usage:\n\
1700Sstevel@tonic-gate ypxfr [-f] [ -h host ] [ -d domainname ]\n\
1710Sstevel@tonic-gate 	[ -s domainname ] [-c] [-C tid prot servname ] map\n\n\
1720Sstevel@tonic-gate where\n\
1730Sstevel@tonic-gate 	-f forces transfer even if the master's copy is not newer.\n\
1740Sstevel@tonic-gate 	host is the server from where the map should be transfered\n\
1750Sstevel@tonic-gate 	-d domainname is specified if other than the default domain\n\
1760Sstevel@tonic-gate 	-s domainname is a source for the map that is same across domains\n\
1770Sstevel@tonic-gate 	-c inhibits sending a \"Clear map\" message to the local ypserv.\n\
1780Sstevel@tonic-gate 	-C is for use only by ypserv to pass callback information.\n";
1790Sstevel@tonic-gate char err_bad_args[] =
1800Sstevel@tonic-gate 	"%s argument is bad.\n";
1810Sstevel@tonic-gate char err_cant_get_kname[] =
1820Sstevel@tonic-gate 	"Can't get %s back from system call.\n";
1830Sstevel@tonic-gate char err_null_kname[] =
1840Sstevel@tonic-gate 	"%s hasn't been set on this machine.\n";
1850Sstevel@tonic-gate char err_bad_hostname[] = "hostname";
1860Sstevel@tonic-gate char err_bad_mapname[] = "mapname";
1870Sstevel@tonic-gate char err_bad_domainname[] = "domainname";
1880Sstevel@tonic-gate char err_udp_failure[] =
1890Sstevel@tonic-gate 	"Can't set up a udp connection to ypserv on host %s.\n";
1900Sstevel@tonic-gate char yptempname_prefix[] = "ypxfr_map.";
1910Sstevel@tonic-gate char ypbkupname_prefix[] = "ypxfr_bkup.";
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate void get_command_line_args();
1940Sstevel@tonic-gate bool bind_to_server();
1950Sstevel@tonic-gate bool ping_server();
1960Sstevel@tonic-gate bool  get_private_recs();
1970Sstevel@tonic-gate bool get_order();
1980Sstevel@tonic-gate bool get_v1order();
1990Sstevel@tonic-gate bool get_v2order();
2000Sstevel@tonic-gate bool get_misc_recs();
2010Sstevel@tonic-gate bool get_master_name();
2020Sstevel@tonic-gate bool get_v1master_name();
2030Sstevel@tonic-gate bool get_v2master_name();
2040Sstevel@tonic-gate void find_map_master();
2050Sstevel@tonic-gate bool move_map();
2060Sstevel@tonic-gate unsigned get_local_version();
2070Sstevel@tonic-gate void mkfilename();
2080Sstevel@tonic-gate void mk_tmpname();
2090Sstevel@tonic-gate bool get_map();
2100Sstevel@tonic-gate bool add_private_entries();
2110Sstevel@tonic-gate bool new_mapfiles();
2120Sstevel@tonic-gate void del_mapfiles();
2130Sstevel@tonic-gate void set_output();
2140Sstevel@tonic-gate void logprintf();
2150Sstevel@tonic-gate bool send_ypclear();
2160Sstevel@tonic-gate void xfr_exit();
2170Sstevel@tonic-gate void send_callback();
2180Sstevel@tonic-gate int ypall_callback();
2190Sstevel@tonic-gate int map_yperr_to_pusherr();
2200Sstevel@tonic-gate extern CLIENT *__yp_clnt_create_rsvdport();
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate bool_t is_yptol_mode();
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate extern int errno;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate /*
2280Sstevel@tonic-gate  * This is the mainline for the ypxfr process.
2290Sstevel@tonic-gate  */
2300Sstevel@tonic-gate 
231*702Sth160488 int
main(argc,argv)2320Sstevel@tonic-gate main(argc, argv)
2330Sstevel@tonic-gate 	int argc;
2340Sstevel@tonic-gate 	char **argv;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate {
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	static char default_domain_name[YPMAXDOMAIN];
2390Sstevel@tonic-gate 	static unsigned big = 0xffffffff;
2400Sstevel@tonic-gate 	int status;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	set_output();
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	/*
2450Sstevel@tonic-gate 	 * Inter-process lock synchronization structure. Since slave servers
2460Sstevel@tonic-gate 	 * get their maps from another NIS server rather than LDAP they can
2470Sstevel@tonic-gate 	 * never run in N2L mode. We thus do not have to init the update
2480Sstevel@tonic-gate 	 * locking mechanism.
2490Sstevel@tonic-gate 	 */
2500Sstevel@tonic-gate 	if (init_lock_map() == FALSE) {
2510Sstevel@tonic-gate 		exit(1);
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	get_command_line_args(argc, argv);
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	if (!domain) {
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 		if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
2590Sstevel@tonic-gate 			domain = default_domain_name;
2600Sstevel@tonic-gate 		} else {
2610Sstevel@tonic-gate 			logprintf(err_cant_get_kname,
2620Sstevel@tonic-gate 			    err_bad_domainname);
2630Sstevel@tonic-gate 			xfr_exit(YPPUSH_RSRC);
2640Sstevel@tonic-gate 		}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 		if (strlen(domain) == 0) {
2670Sstevel@tonic-gate 			logprintf(err_null_kname,
2680Sstevel@tonic-gate 			    err_bad_domainname);
2690Sstevel@tonic-gate 			xfr_exit(YPPUSH_RSRC);
2700Sstevel@tonic-gate 		}
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 	if (!source)
2730Sstevel@tonic-gate 		source = domain;
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	if (!master) {
2760Sstevel@tonic-gate 		find_map_master();
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 	/*
2790Sstevel@tonic-gate 	 * if we were unable to get the master name, either from
2800Sstevel@tonic-gate 	 * the -h option or from -C "name" option or from NIS,
2810Sstevel@tonic-gate 	 * we are doomed !
2820Sstevel@tonic-gate 	 */
2830Sstevel@tonic-gate 	if (!master) {
2840Sstevel@tonic-gate 		xfr_exit(YPPUSH_MADDR);
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if (!bind_to_server(master, &master_server,
2880Sstevel@tonic-gate 	    &master_prog_vers, &status)) {
2890Sstevel@tonic-gate 		xfr_exit(status);
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	if (!get_private_recs(&status)) {
2930Sstevel@tonic-gate 		xfr_exit(status);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	if (!master_version) {
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 		if (force) {
2990Sstevel@tonic-gate 			master_version = &big;
3000Sstevel@tonic-gate 			fake_master_version = TRUE;
3010Sstevel@tonic-gate 		} else {
3020Sstevel@tonic-gate 			logprintf(
3030Sstevel@tonic-gate "Can't get order number for map %s from server at %s: use the -f flag.\n",
3040Sstevel@tonic-gate 			    map, master);
3050Sstevel@tonic-gate 			xfr_exit(YPPUSH_FORCE);
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if (!move_map(&status)) {
3100Sstevel@tonic-gate 		xfr_exit(status);
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	if (send_clear && !send_ypclear(&status)) {
3140Sstevel@tonic-gate 		xfr_exit(status);
3150Sstevel@tonic-gate 	}
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	if (logging) {
3180Sstevel@tonic-gate 		logprintf("Transferred map %s from %s (%d entries).\n",
3190Sstevel@tonic-gate 		    map, master, entry_count);
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	xfr_exit(YPPUSH_SUCC);
323*702Sth160488 	return (0);
3240Sstevel@tonic-gate 	/* NOTREACHED */
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate /*
3280Sstevel@tonic-gate  * This decides whether we're being run interactively or not, and, if not,
3290Sstevel@tonic-gate  * whether we're supposed to be logging or not.  If we are logging, it sets
3300Sstevel@tonic-gate  * up stderr to point to the log file, and sets the "logging"
3310Sstevel@tonic-gate  * variable.  If there's no logging, the output goes in the bit bucket.
3320Sstevel@tonic-gate  * Logging output differs from interactive output in the presence of a
3330Sstevel@tonic-gate  * timestamp, present only in the log file.  stderr is reset, too, because it
3340Sstevel@tonic-gate  * it's used by various library functions, including clnt_perror.
3350Sstevel@tonic-gate  */
3360Sstevel@tonic-gate void
set_output()3370Sstevel@tonic-gate set_output()
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate 	if (!isatty(1)) {
3400Sstevel@tonic-gate 		if (access(logfile, W_OK)) {
3410Sstevel@tonic-gate 			(void) freopen("/dev/null", "w", stderr);
3420Sstevel@tonic-gate 		} else {
3430Sstevel@tonic-gate 			(void) freopen(logfile, "a", stderr);
3440Sstevel@tonic-gate 			logging = TRUE;
3450Sstevel@tonic-gate 		}
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate /*
3490Sstevel@tonic-gate  * This constructs a logging record.
3500Sstevel@tonic-gate  */
3510Sstevel@tonic-gate void
logprintf(arg1,arg2,arg3,arg4,arg5,arg6,arg7)3520Sstevel@tonic-gate logprintf(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
3530Sstevel@tonic-gate /*VARARGS*/
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate 	struct timeval t;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	fseek(stderr, 0, 2);
3580Sstevel@tonic-gate 	if (logging) {
3590Sstevel@tonic-gate 		(void) gettimeofday(&t, NULL);
3600Sstevel@tonic-gate 		(void) fprintf(stderr, "%19.19s: ", ctime(&t.tv_sec));
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 	(void) fprintf(stderr, (char *)arg1, arg2, arg3, arg4, arg5,
3630Sstevel@tonic-gate 				arg6, arg7);
3640Sstevel@tonic-gate 	fflush(stderr);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate /*
3680Sstevel@tonic-gate  * This does the command line argument processing.
3690Sstevel@tonic-gate  */
3700Sstevel@tonic-gate void
get_command_line_args(argc,argv)3710Sstevel@tonic-gate get_command_line_args(argc, argv)
3720Sstevel@tonic-gate 	int argc;
3730Sstevel@tonic-gate 	char **argv;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate {
3760Sstevel@tonic-gate 	argv++;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	if (argc < 2) {
3790Sstevel@tonic-gate 		logprintf(err_usage);
3800Sstevel@tonic-gate 		xfr_exit(YPPUSH_BADARGS);
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	while (--argc) {
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 		if ((*argv)[0] == '-') {
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 			switch ((*argv)[1]) {
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 			case 'f': {
3900Sstevel@tonic-gate 				force = TRUE;
3910Sstevel@tonic-gate 				argv++;
3920Sstevel@tonic-gate 				break;
3930Sstevel@tonic-gate 			}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 			case 'D': {
3960Sstevel@tonic-gate 				debug = TRUE;
3970Sstevel@tonic-gate 				argv++;
3980Sstevel@tonic-gate 				break;
3990Sstevel@tonic-gate 			}
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 			case 'T': {
4020Sstevel@tonic-gate 				treepush = TRUE;
4030Sstevel@tonic-gate 				argv++;
4040Sstevel@tonic-gate 				break;
4050Sstevel@tonic-gate 			}
4060Sstevel@tonic-gate 			case 'P': {
4070Sstevel@tonic-gate 				check_count = TRUE;
4080Sstevel@tonic-gate 				argv++;
4090Sstevel@tonic-gate 				break;
4100Sstevel@tonic-gate 			}
4110Sstevel@tonic-gate 			case 'W': {
4120Sstevel@tonic-gate 				defwrite = FALSE;
4130Sstevel@tonic-gate 				argv++;
4140Sstevel@tonic-gate 				break;
4150Sstevel@tonic-gate 			}
4160Sstevel@tonic-gate 			case 'c': {
4170Sstevel@tonic-gate 				send_clear = FALSE;
4180Sstevel@tonic-gate 				argv++;
4190Sstevel@tonic-gate 				break;
4200Sstevel@tonic-gate 			}
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 			case 'h': {
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 				if (argc > 1) {
4250Sstevel@tonic-gate 					argv++;
4260Sstevel@tonic-gate 					argc--;
4270Sstevel@tonic-gate 					master = *argv;
4280Sstevel@tonic-gate 					argv++;
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 					if (strlen(master) > 256) {
4310Sstevel@tonic-gate 						logprintf(
4320Sstevel@tonic-gate 						    err_bad_args,
4330Sstevel@tonic-gate 						    err_bad_hostname);
4340Sstevel@tonic-gate 						xfr_exit(YPPUSH_BADARGS);
4350Sstevel@tonic-gate 					}
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 				} else {
4380Sstevel@tonic-gate 					logprintf(err_usage);
4390Sstevel@tonic-gate 					xfr_exit(YPPUSH_BADARGS);
4400Sstevel@tonic-gate 				}
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 				break;
4430Sstevel@tonic-gate 			}
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 			case 'd':
4460Sstevel@tonic-gate 				if (argc > 1) {
4470Sstevel@tonic-gate 					argv++;
4480Sstevel@tonic-gate 					argc--;
4490Sstevel@tonic-gate 					domain = *argv;
4500Sstevel@tonic-gate 					argv++;
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 					if (strlen(domain) > YPMAXDOMAIN) {
4530Sstevel@tonic-gate 						logprintf(
4540Sstevel@tonic-gate 						    err_bad_args,
4550Sstevel@tonic-gate 						    err_bad_domainname);
4560Sstevel@tonic-gate 						xfr_exit(YPPUSH_BADARGS);
4570Sstevel@tonic-gate 					}
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 				} else {
4600Sstevel@tonic-gate 					logprintf(err_usage);
4610Sstevel@tonic-gate 					xfr_exit(YPPUSH_BADARGS);
4620Sstevel@tonic-gate 				}
4630Sstevel@tonic-gate 				break;
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 			case 's':
4660Sstevel@tonic-gate 				if (argc > 1) {
4670Sstevel@tonic-gate 					argv++;
4680Sstevel@tonic-gate 					argc--;
4690Sstevel@tonic-gate 					source = *argv;
4700Sstevel@tonic-gate 					argv++;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 					if (strlen(source) > YPMAXDOMAIN) {
4730Sstevel@tonic-gate 						logprintf(
4740Sstevel@tonic-gate 						    err_bad_args,
4750Sstevel@tonic-gate 						    err_bad_domainname);
4760Sstevel@tonic-gate 						xfr_exit(YPPUSH_BADARGS);
4770Sstevel@tonic-gate 					}
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 				} else {
4800Sstevel@tonic-gate 					logprintf(err_usage);
4810Sstevel@tonic-gate 					xfr_exit(YPPUSH_BADARGS);
4820Sstevel@tonic-gate 				}
4830Sstevel@tonic-gate 				break;
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 			case 'C':
4860Sstevel@tonic-gate 			    if (argc > 3) {
4870Sstevel@tonic-gate 				callback = TRUE;
4880Sstevel@tonic-gate 				tid = *(++argv);
4890Sstevel@tonic-gate 				proto = *(++argv);
4900Sstevel@tonic-gate 				pushhost = *(++argv);
4910Sstevel@tonic-gate 				if (strlen(pushhost) > 256) {
4920Sstevel@tonic-gate 				    logprintf(err_bad_args, err_bad_hostname);
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 				    xfr_exit(YPPUSH_BADARGS);
4950Sstevel@tonic-gate 				}
4960Sstevel@tonic-gate 				argc -= 3;
4970Sstevel@tonic-gate 				argv++;
4980Sstevel@tonic-gate 			    } else {
4990Sstevel@tonic-gate 				logprintf(err_usage);
5000Sstevel@tonic-gate 				xfr_exit(YPPUSH_BADARGS);
5010Sstevel@tonic-gate 			    }
5020Sstevel@tonic-gate 			    break;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 			case 'b': {
5050Sstevel@tonic-gate 				interdomain_map = TRUE;
5060Sstevel@tonic-gate 				interdomain_value = "";
5070Sstevel@tonic-gate 				interdomain_sz = 0;
5080Sstevel@tonic-gate 				argv++;
5090Sstevel@tonic-gate 				break;
5100Sstevel@tonic-gate 			}
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 			default: {
5140Sstevel@tonic-gate 				logprintf(err_usage);
5150Sstevel@tonic-gate 				xfr_exit(YPPUSH_BADARGS);
5160Sstevel@tonic-gate 			}
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 			}
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 		} else {
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 			if (!map) {
5230Sstevel@tonic-gate 				map = *argv;
5240Sstevel@tonic-gate 				argv++;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 				if (strlen(map) > YPMAXMAP) {
5270Sstevel@tonic-gate 					logprintf(err_bad_args,
5280Sstevel@tonic-gate 					err_bad_mapname);
5290Sstevel@tonic-gate 					xfr_exit(YPPUSH_BADARGS);
5300Sstevel@tonic-gate 				}
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 			} else {
5330Sstevel@tonic-gate 				logprintf(err_usage);
5340Sstevel@tonic-gate 				xfr_exit(YPPUSH_BADARGS);
5350Sstevel@tonic-gate 			}
5360Sstevel@tonic-gate 		}
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	if (!map) {
5400Sstevel@tonic-gate 		logprintf(err_usage);
5410Sstevel@tonic-gate 		xfr_exit(YPPUSH_BADARGS);
5420Sstevel@tonic-gate 	}
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate  * This tries to get the master name for the named map, from any
5470Sstevel@tonic-gate  * server's version, using the vanilla NIS client interface.  If we get a
5480Sstevel@tonic-gate  * name back, the global "master" gets pointed to it.
5490Sstevel@tonic-gate  */
5500Sstevel@tonic-gate void
find_map_master()5510Sstevel@tonic-gate find_map_master()
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate 	int err;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	if (err = __yp_master_rsvdport(source, map, &master)) {
5560Sstevel@tonic-gate 		logprintf("Can't get master of %s. Reason: %s.\n", map,
5570Sstevel@tonic-gate 		    yperr_string(err));
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	yp_unbind(source);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate #ifdef TREEPUSH
564*702Sth160488 int
chk_treepush(name)5650Sstevel@tonic-gate chk_treepush(name)
5660Sstevel@tonic-gate char *name;
5670Sstevel@tonic-gate {
5680Sstevel@tonic-gate 	char inmap[256];
5690Sstevel@tonic-gate 	char inkey[256];
5700Sstevel@tonic-gate 	int inkeylen;
5710Sstevel@tonic-gate 	char *outval;
5720Sstevel@tonic-gate 	int outvallen;
5730Sstevel@tonic-gate 	int err;
5740Sstevel@tonic-gate 	outval = NULL;
5750Sstevel@tonic-gate 	inkey[0] = 0;
5760Sstevel@tonic-gate 	strcpy(inmap, "ypslaves.");
5770Sstevel@tonic-gate 	strcat(inmap, name);
5780Sstevel@tonic-gate 	gethostname(inkey, 256);
5790Sstevel@tonic-gate 	inkeylen = strlen(inkey);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	err = yp_match(source, inmap, inkey, inkeylen, &outval, &outvallen);
5820Sstevel@tonic-gate 	yp_unbind(source);
5830Sstevel@tonic-gate 	return (err);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate #endif
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate /*
5880Sstevel@tonic-gate  * This sets up a udp connection to speak the correct program and version
5890Sstevel@tonic-gate  * to a NIS server.  vers is set to YPVERS, doesn't give a damn about
5900Sstevel@tonic-gate  * YPOLDVERS.
5910Sstevel@tonic-gate  */
5920Sstevel@tonic-gate bool
bind_to_server(host,pdomb,vers,status)5930Sstevel@tonic-gate bind_to_server(host, pdomb, vers, status)
5940Sstevel@tonic-gate 	char *host;
5950Sstevel@tonic-gate 	struct dom_binding *pdomb;
5960Sstevel@tonic-gate 	unsigned int *vers;
5970Sstevel@tonic-gate 	int *status;
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate 	if (ping_server(host, pdomb, YPVERS, status)) {
6000Sstevel@tonic-gate 		*vers = YPVERS;
6010Sstevel@tonic-gate 		return (TRUE);
6020Sstevel@tonic-gate 	} else
6030Sstevel@tonic-gate 		return (FALSE);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate /*
6070Sstevel@tonic-gate  * This sets up a UDP channel to a server which is assumed to speak an input
6080Sstevel@tonic-gate  * version of YPPROG.  The channel is tested by pinging the server.  In all
6090Sstevel@tonic-gate  * error cases except "Program Version Number Mismatch", the error is
6100Sstevel@tonic-gate  * reported, and in all error cases, the client handle is destroyed and the
6110Sstevel@tonic-gate  * socket associated with the channel is closed.
6120Sstevel@tonic-gate  */
6130Sstevel@tonic-gate bool
ping_server(host,pdomb,vers,status)6140Sstevel@tonic-gate ping_server(host, pdomb, vers, status)
6150Sstevel@tonic-gate 	char *host;
6160Sstevel@tonic-gate 	struct dom_binding *pdomb;
6170Sstevel@tonic-gate 	unsigned int vers;
6180Sstevel@tonic-gate 	int *status;
6190Sstevel@tonic-gate {
6200Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	if ((pdomb->dom_client = __yp_clnt_create_rsvdport(host, YPPROG, vers,
6230Sstevel@tonic-gate 							0, 0, 0)) != 0) {
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 		/*
6260Sstevel@tonic-gate 		 * if we are on a c2 system, we should only accept data
6270Sstevel@tonic-gate 		 * from a server which is on a reserved port.
6280Sstevel@tonic-gate 		 */
6290Sstevel@tonic-gate 	/*
6300Sstevel@tonic-gate 	 * NUKE this for 5.0DR.
6310Sstevel@tonic-gate 	 *
6320Sstevel@tonic-gate 	 *	if (issecure() &&
6330Sstevel@tonic-gate 	 *	    (pdomb->dom_server_addr.sin_family != AF_INET ||
6340Sstevel@tonic-gate 	 *	    pdomb->dom_server_addr.sin_port >= IPPORT_RESERVED)) {
6350Sstevel@tonic-gate 	 *		clnt_destroy(pdomb->dom_client);
6360Sstevel@tonic-gate 	 *		close(pdomb->dom_socket);
6370Sstevel@tonic-gate 	 *		(void) logprintf("bind_to_server: \
6380Sstevel@tonic-gate 	 *			server is not using a privileged port\n");
6390Sstevel@tonic-gate 	 *		*status = YPPUSH_YPERR;
6400Sstevel@tonic-gate 	 *		return (FALSE);
6410Sstevel@tonic-gate 	 *	}
6420Sstevel@tonic-gate 	 */
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 		rpc_stat = clnt_call(pdomb->dom_client, YPBINDPROC_NULL,
6450Sstevel@tonic-gate 		    xdr_void, 0, xdr_void, 0, udp_timeout);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		if (rpc_stat == RPC_SUCCESS) {
6480Sstevel@tonic-gate 			return (TRUE);
6490Sstevel@tonic-gate 		} else {
6500Sstevel@tonic-gate 			clnt_destroy(pdomb->dom_client);
6510Sstevel@tonic-gate 			if (rpc_stat != RPC_PROGVERSMISMATCH) {
6520Sstevel@tonic-gate 				(void) clnt_perror(pdomb->dom_client,
6530Sstevel@tonic-gate 				    "ypxfr: bind_to_server clnt_call error");
6540Sstevel@tonic-gate 			}
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 			*status = YPPUSH_RPC;
6570Sstevel@tonic-gate 			return (FALSE);
6580Sstevel@tonic-gate 		}
6590Sstevel@tonic-gate 	} else {
6600Sstevel@tonic-gate 		logprintf("bind_to_server __clnt_create_rsvd error");
6610Sstevel@tonic-gate 		(void) clnt_pcreateerror("");
6620Sstevel@tonic-gate 		fflush(stderr);
6630Sstevel@tonic-gate 		*status = YPPUSH_RPC;
6640Sstevel@tonic-gate 		return (FALSE);
6650Sstevel@tonic-gate 	}
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate /*
6690Sstevel@tonic-gate  * This gets values for the YP_LAST_MODIFIED and YP_MASTER_NAME keys from the
6700Sstevel@tonic-gate  * master server's version of the map.  Values are held in static variables
6710Sstevel@tonic-gate  * here.  In the success cases, global pointer variables are set to point at
6720Sstevel@tonic-gate  * the local statics.
6730Sstevel@tonic-gate  */
6740Sstevel@tonic-gate bool
get_private_recs(pushstat)6750Sstevel@tonic-gate get_private_recs(pushstat)
6760Sstevel@tonic-gate 	int *pushstat;
6770Sstevel@tonic-gate {
6780Sstevel@tonic-gate 	static char anumber[20];
6790Sstevel@tonic-gate 	static unsigned number;
6800Sstevel@tonic-gate 	static char name[YPMAXPEER + 1];
6810Sstevel@tonic-gate 	int status;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	status = 0;
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	if (get_order(anumber, &number, &status)) {
6860Sstevel@tonic-gate 		master_version = &number;
6870Sstevel@tonic-gate 		master_ascii_version = anumber;
6880Sstevel@tonic-gate 		if (debug) fprintf(stderr,
6890Sstevel@tonic-gate 			"ypxfr: Master Version is %s\n", master_ascii_version);
6900Sstevel@tonic-gate 	} else {
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 		if (status != 0) {
6930Sstevel@tonic-gate 			*pushstat = status;
6940Sstevel@tonic-gate 			if (debug) fprintf(stderr,
6950Sstevel@tonic-gate 		"ypxfr: Couldn't get map's master version number, \
6960Sstevel@tonic-gate 		status was %d\n", status);
6970Sstevel@tonic-gate 			return (FALSE);
6980Sstevel@tonic-gate 		}
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	if (get_master_name(name, &status)) {
7020Sstevel@tonic-gate 		master_name = name;
7030Sstevel@tonic-gate 		if (debug) fprintf(stderr,
7040Sstevel@tonic-gate 			"ypxfr: Maps master is '%s'\n", master_name);
7050Sstevel@tonic-gate 	} else {
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 		if (status != 0) {
7080Sstevel@tonic-gate 			*pushstat = status;
7090Sstevel@tonic-gate 			if (debug) fprintf(stderr,
7100Sstevel@tonic-gate 		"ypxfr: Couldn't get map's master name, status was %d\n",
7110Sstevel@tonic-gate 			status);
7120Sstevel@tonic-gate 			return (FALSE);
7130Sstevel@tonic-gate 		}
7140Sstevel@tonic-gate 		master_name = master;
7150Sstevel@tonic-gate 	}
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	if (debug)
7180Sstevel@tonic-gate 		fprintf(stderr,
7190Sstevel@tonic-gate 			"ypxfr: Getting private records from master.\n");
7200Sstevel@tonic-gate 	if (get_misc_recs(&status)) {
7210Sstevel@tonic-gate 		if (debug)
7220Sstevel@tonic-gate 			fprintf(stderr,
7230Sstevel@tonic-gate 		    "ypxfr: Masters map %s secure and %s an interdomain map.\n",
7240Sstevel@tonic-gate 			(secure_map) ? "is" : "is not",
7250Sstevel@tonic-gate 			(interdomain_map) ? "is" : "is not");
7260Sstevel@tonic-gate 	} else {
7270Sstevel@tonic-gate 		if (status != 0) {
7280Sstevel@tonic-gate 			*pushstat = status;
7290Sstevel@tonic-gate 			if (debug)
7300Sstevel@tonic-gate 				fprintf(stderr,
7310Sstevel@tonic-gate 	"ypxfr: Couldn't get state of secure and interdomain flags in map.\n");
7320Sstevel@tonic-gate 			return (FALSE);
7330Sstevel@tonic-gate 		}
7340Sstevel@tonic-gate 	}
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	return (TRUE);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate /*
7400Sstevel@tonic-gate  * This gets the map's order number from the master server
7410Sstevel@tonic-gate  */
7420Sstevel@tonic-gate bool
get_order(an,n,pushstat)7430Sstevel@tonic-gate get_order(an, n, pushstat)
7440Sstevel@tonic-gate 	char *an;
7450Sstevel@tonic-gate 	unsigned *n;
7460Sstevel@tonic-gate 	int *pushstat;
7470Sstevel@tonic-gate {
7480Sstevel@tonic-gate 	if (master_prog_vers == YPVERS) {
7490Sstevel@tonic-gate 		return (get_v2order(an, n, pushstat));
7500Sstevel@tonic-gate 	} else
7510Sstevel@tonic-gate 		return (FALSE);
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate bool
get_v2order(an,n,pushstat)7550Sstevel@tonic-gate get_v2order(an, n, pushstat)
7560Sstevel@tonic-gate 	char *an;
7570Sstevel@tonic-gate 	unsigned *n;
7580Sstevel@tonic-gate 	int *pushstat;
7590Sstevel@tonic-gate {
7600Sstevel@tonic-gate 	struct ypreq_nokey req;
7610Sstevel@tonic-gate 	struct ypresp_order resp;
7620Sstevel@tonic-gate 	int retval;
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate 	req.domain = source;
7650Sstevel@tonic-gate 	req.map = map;
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	/*
7680Sstevel@tonic-gate 	 * Get the map''s order number, null-terminate it and store it,
7690Sstevel@tonic-gate 	 * and convert it to binary and store it again.
7700Sstevel@tonic-gate 	 */
7710Sstevel@tonic-gate 	retval = FALSE;
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	if ((enum clnt_stat) clnt_call(master_server.dom_client,
7740Sstevel@tonic-gate 	    YPPROC_ORDER, (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
7750Sstevel@tonic-gate 	    (xdrproc_t)xdr_ypresp_order, (char *)&resp,
7760Sstevel@tonic-gate 	    udp_timeout) == RPC_SUCCESS) {
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 		if (resp.status == YP_TRUE) {
7790Sstevel@tonic-gate 			sprintf(an, "%d", resp.ordernum);
7800Sstevel@tonic-gate 			*n = resp.ordernum;
7810Sstevel@tonic-gate 			retval = TRUE;
7820Sstevel@tonic-gate 		} else if (resp.status != YP_BADDB) {
7830Sstevel@tonic-gate 			*pushstat = ypprot_err(resp.status);
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 			if (!logging) {
7860Sstevel@tonic-gate 				logprintf(
7870Sstevel@tonic-gate 	"(info) Can't get order number from ypserv at %s.  Reason: %s.\n",
7880Sstevel@tonic-gate 				    master, yperr_string(
7890Sstevel@tonic-gate 				    ypprot_err(resp.status)));
7900Sstevel@tonic-gate 			}
7910Sstevel@tonic-gate 		}
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 		CLNT_FREERES(master_server.dom_client,
7940Sstevel@tonic-gate 			(xdrproc_t)xdr_ypresp_order,
7950Sstevel@tonic-gate 		    (char *)&resp);
7960Sstevel@tonic-gate 	} else {
7970Sstevel@tonic-gate 		*pushstat = YPPUSH_RPC;
7980Sstevel@tonic-gate 		logprintf("ypxfr(get_v2order) RPC call to %s failed", master);
7990Sstevel@tonic-gate 		clnt_perror(master_server.dom_client, "");
8000Sstevel@tonic-gate 	}
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	return (retval);
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate  * Pick up the state of the YP_SECURE and YP_INTERDOMAIN records from the
8070Sstevel@tonic-gate  * master. Only works on 4.0 V2 masters that will match a YP_ private key
8080Sstevel@tonic-gate  * when asked to explicitly.
8090Sstevel@tonic-gate  */
8100Sstevel@tonic-gate bool
get_misc_recs(pushstat)8110Sstevel@tonic-gate get_misc_recs(pushstat)
8120Sstevel@tonic-gate 	int *pushstat;
8130Sstevel@tonic-gate {
8140Sstevel@tonic-gate 	struct ypreq_key req;
8150Sstevel@tonic-gate 	struct ypresp_val resp;
8160Sstevel@tonic-gate 	int retval;
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	req.domain = source;
8190Sstevel@tonic-gate 	req.map = map;
8200Sstevel@tonic-gate 	req.keydat.dptr   = yp_secure;
8210Sstevel@tonic-gate 	req.keydat.dsize  = yp_secure_sz;
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	resp.valdat.dptr = NULL;
8240Sstevel@tonic-gate 	resp.valdat.dsize = 0;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	/*
8270Sstevel@tonic-gate 	 * Get the value of the IS_SECURE key in the map.
8280Sstevel@tonic-gate 	 */
8290Sstevel@tonic-gate 	retval = FALSE;
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	if (debug)
8320Sstevel@tonic-gate 		fprintf(stderr, "ypxfr: Checking masters secure key.\n");
8330Sstevel@tonic-gate 	if ((enum clnt_stat) clnt_call(master_server.dom_client,
8340Sstevel@tonic-gate 	    YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, (char *)&req,
8350Sstevel@tonic-gate 	(xdrproc_t)xdr_ypresp_val, (char *)&resp,
8360Sstevel@tonic-gate 	    udp_timeout) == RPC_SUCCESS) {
8370Sstevel@tonic-gate 		if (resp.status == YP_TRUE) {
8380Sstevel@tonic-gate 			if (debug)
8390Sstevel@tonic-gate 				fprintf(stderr, "ypxfr: SECURE\n");
8400Sstevel@tonic-gate 			secure_map = TRUE;
8410Sstevel@tonic-gate 			retval = TRUE;
8420Sstevel@tonic-gate 		} else if ((resp.status != YP_NOKEY) &&
8430Sstevel@tonic-gate 			    (resp.status != YP_VERS) &&
8440Sstevel@tonic-gate 			    (resp.status != YP_NOMORE)) {
8450Sstevel@tonic-gate 			*pushstat = ypprot_err(resp.status);
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 			if (!logging) {
8480Sstevel@tonic-gate 				logprintf(
8490Sstevel@tonic-gate 	"(info) Can't get secure flag from ypserv at %s.  Reason: %s.\n",
8500Sstevel@tonic-gate 				    master, yperr_string(
8510Sstevel@tonic-gate 				    ypprot_err(resp.status)));
8520Sstevel@tonic-gate 			}
8530Sstevel@tonic-gate 		}
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 		CLNT_FREERES(master_server.dom_client,
8560Sstevel@tonic-gate 			(xdrproc_t)xdr_ypresp_val,
8570Sstevel@tonic-gate 		    (char *)&resp);
8580Sstevel@tonic-gate 	} else {
8590Sstevel@tonic-gate 		*pushstat = YPPUSH_RPC;
8600Sstevel@tonic-gate 		logprintf("ypxfr(get_misc_recs) RPC call to %s failed", master);
8610Sstevel@tonic-gate 		clnt_perror(master_server.dom_client, "");
8620Sstevel@tonic-gate 	}
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	if (debug)
8650Sstevel@tonic-gate 		fprintf(stderr, "ypxfr: Checking masters INTERDOMAIN key.\n");
8660Sstevel@tonic-gate 	req.keydat.dptr   = yp_interdomain;
8670Sstevel@tonic-gate 	req.keydat.dsize  = yp_interdomain_sz;
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 	resp.valdat.dptr = NULL;
8700Sstevel@tonic-gate 	resp.valdat.dsize = 0;
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 	/*
8730Sstevel@tonic-gate 	 * Get the value of the INTERDOMAIN key in the map.
8740Sstevel@tonic-gate 	 */
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 	if ((enum clnt_stat) clnt_call(master_server.dom_client,
8770Sstevel@tonic-gate 	    YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, (char *)&req,
8780Sstevel@tonic-gate 	(xdrproc_t)xdr_ypresp_val, (char *)&resp,
8790Sstevel@tonic-gate 	    udp_timeout) == RPC_SUCCESS) {
8800Sstevel@tonic-gate 		if (resp.status == YP_TRUE) {
8810Sstevel@tonic-gate 			if (debug)
8820Sstevel@tonic-gate 				fprintf(stderr, "ypxfr: INTERDOMAIN\n");
8830Sstevel@tonic-gate 			interdomain_map = TRUE;
8840Sstevel@tonic-gate 			interdomain_value = (char *)malloc(resp.valdat.dsize+1);
8850Sstevel@tonic-gate 			(void) memmove(interdomain_value, resp.valdat.dptr,
8860Sstevel@tonic-gate 					resp.valdat.dsize);
8870Sstevel@tonic-gate 			*(interdomain_value+resp.valdat.dsize) = '\0';
8880Sstevel@tonic-gate 			interdomain_sz = resp.valdat.dsize;
8890Sstevel@tonic-gate 			retval = TRUE;
8900Sstevel@tonic-gate 		} else if ((resp.status != YP_NOKEY) &&
8910Sstevel@tonic-gate 			    (resp.status != YP_VERS) &&
8920Sstevel@tonic-gate 			    (resp.status != YP_NOMORE)) {
8930Sstevel@tonic-gate 			*pushstat = ypprot_err(resp.status);
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 			if (!logging) {
8960Sstevel@tonic-gate 				logprintf(
8970Sstevel@tonic-gate 	"(info) Can't get interdomain flag from ypserv at %s.  Reason: %s.\n",
8980Sstevel@tonic-gate 				    master, yperr_string(
8990Sstevel@tonic-gate 				    ypprot_err(resp.status)));
9000Sstevel@tonic-gate 			}
9010Sstevel@tonic-gate 		}
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 		CLNT_FREERES(master_server.dom_client,
9040Sstevel@tonic-gate 			(xdrproc_t)xdr_ypresp_val,
9050Sstevel@tonic-gate 		    (char *)&resp);
9060Sstevel@tonic-gate 	} else {
9070Sstevel@tonic-gate 		*pushstat = YPPUSH_RPC;
9080Sstevel@tonic-gate 		logprintf("ypxfr(get_misc_recs) RPC call to %s failed", master);
9090Sstevel@tonic-gate 		clnt_perror(master_server.dom_client, "");
9100Sstevel@tonic-gate 	}
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	return (retval);
9140Sstevel@tonic-gate }
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate /*
9170Sstevel@tonic-gate  * This gets the map's master name from the master server
9180Sstevel@tonic-gate  */
9190Sstevel@tonic-gate bool
get_master_name(name,pushstat)9200Sstevel@tonic-gate get_master_name(name, pushstat)
9210Sstevel@tonic-gate 	char *name;
9220Sstevel@tonic-gate 	int *pushstat;
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate 	if (master_prog_vers == YPVERS) {
9250Sstevel@tonic-gate 		return (get_v2master_name(name, pushstat));
9260Sstevel@tonic-gate 	} else
9270Sstevel@tonic-gate 		return (FALSE);
9280Sstevel@tonic-gate }
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate bool
get_v2master_name(name,pushstat)9310Sstevel@tonic-gate get_v2master_name(name, pushstat)
9320Sstevel@tonic-gate 	char *name;
9330Sstevel@tonic-gate 	int *pushstat;
9340Sstevel@tonic-gate {
9350Sstevel@tonic-gate 	struct ypreq_nokey req;
9360Sstevel@tonic-gate 	struct ypresp_master resp;
9370Sstevel@tonic-gate 	int retval;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	req.domain = source;
9400Sstevel@tonic-gate 	req.map = map;
9410Sstevel@tonic-gate 	resp.master = NULL;
9420Sstevel@tonic-gate 	retval = FALSE;
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	if ((enum clnt_stat) clnt_call(master_server.dom_client,
9450Sstevel@tonic-gate 	    YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
9460Sstevel@tonic-gate 	    (xdrproc_t)xdr_ypresp_master, (char *)&resp,
9470Sstevel@tonic-gate 	    udp_timeout) == RPC_SUCCESS) {
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 		if (resp.status == YP_TRUE) {
9500Sstevel@tonic-gate 			strcpy(name, resp.master);
9510Sstevel@tonic-gate 			retval = TRUE;
9520Sstevel@tonic-gate 		} else if (resp.status != YP_BADDB) {
9530Sstevel@tonic-gate 			*pushstat = ypprot_err(resp.status);
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 			if (!logging) {
9560Sstevel@tonic-gate 				logprintf(
9570Sstevel@tonic-gate "(info) Can't get master name from ypserv at %s. Reason: %s.\n",
9580Sstevel@tonic-gate 				    master, yperr_string(
9590Sstevel@tonic-gate 				    ypprot_err(resp.status)));
9600Sstevel@tonic-gate 			}
9610Sstevel@tonic-gate 		}
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 		CLNT_FREERES(master_server.dom_client,
9640Sstevel@tonic-gate 			(xdrproc_t)xdr_ypresp_master,
9650Sstevel@tonic-gate 		    (char *)&resp);
9660Sstevel@tonic-gate 	} else {
9670Sstevel@tonic-gate 		*pushstat = YPPUSH_RPC;
9680Sstevel@tonic-gate 		logprintf(
9690Sstevel@tonic-gate 		    "ypxfr(get_v2master_name) RPC call to %s failed", master);
9700Sstevel@tonic-gate 		clnt_perror(master_server.dom_client, "");
9710Sstevel@tonic-gate 	}
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 	return (retval);
9740Sstevel@tonic-gate }
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate /*
9770Sstevel@tonic-gate  * This does the work of transferring the map.
9780Sstevel@tonic-gate  */
9790Sstevel@tonic-gate bool
move_map(pushstat)9800Sstevel@tonic-gate move_map(pushstat)
9810Sstevel@tonic-gate 	int *pushstat;
9820Sstevel@tonic-gate {
9830Sstevel@tonic-gate 	unsigned local_version;
9840Sstevel@tonic-gate 	char map_name[MAXNAMLEN + 1];
9850Sstevel@tonic-gate 	char tmp_name[MAXNAMLEN + 1];
9860Sstevel@tonic-gate 	char bkup_name[MAXNAMLEN + 1];
9870Sstevel@tonic-gate 	char an[11];
9880Sstevel@tonic-gate 	unsigned n;
9890Sstevel@tonic-gate 	datum key;
9900Sstevel@tonic-gate 	datum val;
9910Sstevel@tonic-gate 	int  hgstatus;
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	mkfilename(map_name);
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	if (!force) {
9960Sstevel@tonic-gate 		local_version = get_local_version(map_name);
9970Sstevel@tonic-gate 		if (debug) fprintf(stderr,
9980Sstevel@tonic-gate 			"ypxfr: Local version of map '%s' is %d\n",
9990Sstevel@tonic-gate 			map_name, local_version);
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 		if (local_version >= *master_version) {
10020Sstevel@tonic-gate 			logprintf(
10030Sstevel@tonic-gate 			    "Map %s at %s is not more recent than local.\n",
10040Sstevel@tonic-gate 			    map, master);
10050Sstevel@tonic-gate 			*pushstat = YPPUSH_AGE;
10060Sstevel@tonic-gate 			return (FALSE);
10070Sstevel@tonic-gate 		}
10080Sstevel@tonic-gate 	}
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 	mk_tmpname(yptempname_prefix, tmp_name);
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 	if (!new_mapfiles(tmp_name)) {
10130Sstevel@tonic-gate 		logprintf(
10140Sstevel@tonic-gate 		    "Can't create temp map %s.\n", tmp_name);
10150Sstevel@tonic-gate 		*pushstat = YPPUSH_FILE;
10160Sstevel@tonic-gate 		return (FALSE);
10170Sstevel@tonic-gate 	}
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	if ((hgstatus = ypxfrd_getdbm(tmp_name, master, source, map)) < 0)
10200Sstevel@tonic-gate 	{
10210Sstevel@tonic-gate 	logprintf(
10220Sstevel@tonic-gate "(info) %s %s %s ypxfrd getdbm failed (reason = %d) -- using ypxfr\n",
10230Sstevel@tonic-gate 		master, domain, map, hgstatus);
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	    db = dbm_open(tmp_name, O_RDWR + O_CREAT + O_TRUNC, 0644);
10260Sstevel@tonic-gate 	if (db == NULL) {
10270Sstevel@tonic-gate 		logprintf(
10280Sstevel@tonic-gate 		    "Can't dbm init temp map %s.\n", tmp_name);
10290Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10300Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
10310Sstevel@tonic-gate 		return (FALSE);
10320Sstevel@tonic-gate 	}
10330Sstevel@tonic-gate 	if (defwrite) dbm_setdefwrite(db);
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 	if (!get_map(tmp_name, pushstat)) {
10360Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10370Sstevel@tonic-gate 		return (FALSE);
10380Sstevel@tonic-gate 	}
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	if (!add_private_entries(tmp_name)) {
10410Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10420Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
10430Sstevel@tonic-gate 		return (FALSE);
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	/*
10470Sstevel@tonic-gate 	 * Decide whether the map just transferred is a secure map.
10480Sstevel@tonic-gate 	 * If we already know the local version was secure, we do not
10490Sstevel@tonic-gate 	 * need to check this version.
10500Sstevel@tonic-gate 	 */
10510Sstevel@tonic-gate 	if (!secure_map) {
10520Sstevel@tonic-gate 		key.dptr = yp_secure;
10530Sstevel@tonic-gate 		key.dsize = yp_secure_sz;
10540Sstevel@tonic-gate 		val = dbm_fetch(db, key);
10550Sstevel@tonic-gate 		if (val.dptr != NULL) {
10560Sstevel@tonic-gate 			secure_map = TRUE;
10570Sstevel@tonic-gate 		}
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	if (dbm_close_status(db) < 0) {
10610Sstevel@tonic-gate 		logprintf(
10620Sstevel@tonic-gate 		    "Can't do dbm close operation on temp map %s.\n",
10630Sstevel@tonic-gate 		    tmp_name);
10640Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10650Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
10660Sstevel@tonic-gate 		return (FALSE);
10670Sstevel@tonic-gate 	}
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	if (!get_order(an, &n, pushstat)) {
10700Sstevel@tonic-gate 		return (FALSE);
10710Sstevel@tonic-gate 	}
10720Sstevel@tonic-gate 	if (n != *master_version) {
10730Sstevel@tonic-gate 		logprintf(
10740Sstevel@tonic-gate 		    "Version skew at %s while transferring map %s.\n",
10750Sstevel@tonic-gate 		    master, map);
10760Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10770Sstevel@tonic-gate 		*pushstat = YPPUSH_SKEW;
10780Sstevel@tonic-gate 		return (FALSE);
10790Sstevel@tonic-gate 	}
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate 	if (check_count)
10820Sstevel@tonic-gate 	if (!count_mismatch(tmp_name, entry_count)) {
10830Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10840Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
10850Sstevel@tonic-gate 		return (FALSE);
10860Sstevel@tonic-gate 	}
10870Sstevel@tonic-gate 	} else {
10880Sstevel@tonic-gate 	/* touch up the map */
10890Sstevel@tonic-gate 	    db = dbm_open(tmp_name, 2, 0644);
10900Sstevel@tonic-gate 	if (db == NULL) {
10910Sstevel@tonic-gate 		logprintf(
10920Sstevel@tonic-gate 		    "Can't dbm init temp map %s.\n", tmp_name);
10930Sstevel@tonic-gate 		del_mapfiles(tmp_name);
10940Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
10950Sstevel@tonic-gate 		return (FALSE);
10960Sstevel@tonic-gate 		}
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	if (!add_private_entries(tmp_name)) {
11000Sstevel@tonic-gate 		del_mapfiles(tmp_name);
11010Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
11020Sstevel@tonic-gate 		return (FALSE);
11030Sstevel@tonic-gate 	}
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	/*
11060Sstevel@tonic-gate 	 * Decide whether the map just transferred is a secure map.
11070Sstevel@tonic-gate 	 * If we already know the local version was secure, we do not
11080Sstevel@tonic-gate 	 * need to check this version.
11090Sstevel@tonic-gate 	 */
11100Sstevel@tonic-gate 	if (!secure_map) {
11110Sstevel@tonic-gate 		key.dptr = yp_secure;
11120Sstevel@tonic-gate 		key.dsize = yp_secure_sz;
11130Sstevel@tonic-gate 		val = dbm_fetch(db, key);
11140Sstevel@tonic-gate 		if (val.dptr != NULL) {
11150Sstevel@tonic-gate 			secure_map = TRUE;
11160Sstevel@tonic-gate 		}
11170Sstevel@tonic-gate 	}
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	if (dbm_close_status(db) < 0) {
11200Sstevel@tonic-gate 		logprintf(
11210Sstevel@tonic-gate 		    "Can't do dbm close operation on temp map %s.\n",
11220Sstevel@tonic-gate 		    tmp_name);
11230Sstevel@tonic-gate 		del_mapfiles(tmp_name);
11240Sstevel@tonic-gate 		*pushstat = YPPUSH_DBM;
11250Sstevel@tonic-gate 		return (FALSE);
11260Sstevel@tonic-gate 	}
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate 	if (lock_map(map_name) == 0) {
11310Sstevel@tonic-gate 		del_mapfiles(tmp_name);
11320Sstevel@tonic-gate 		logprintf("Lock error on %s\n", map_name);
11330Sstevel@tonic-gate 		*pushstat = YPPUSH_FILE;
11340Sstevel@tonic-gate 		return (FALSE);
11350Sstevel@tonic-gate 	}
11360Sstevel@tonic-gate 	if (!check_map_existence(map_name)) {
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 		if (!rename_map(tmp_name, map_name, secure_map)) {
11390Sstevel@tonic-gate 			del_mapfiles(tmp_name);
11400Sstevel@tonic-gate 			logprintf(
11410Sstevel@tonic-gate 			    "Rename error:  couldn't mv %s to %s.\n",
11420Sstevel@tonic-gate 			    tmp_name, map_name);
11430Sstevel@tonic-gate 			*pushstat = YPPUSH_FILE;
11440Sstevel@tonic-gate 			unlock_map(map_name);
11450Sstevel@tonic-gate 			return (FALSE);
11460Sstevel@tonic-gate 		}
11470Sstevel@tonic-gate 
11480Sstevel@tonic-gate 	} else {
11490Sstevel@tonic-gate 		mk_tmpname(ypbkupname_prefix, bkup_name);
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 		if (!rename_map(map_name, bkup_name, secure_map)) {
11520Sstevel@tonic-gate 			(void) rename_map(bkup_name, map_name, secure_map);
11530Sstevel@tonic-gate 			logprintf(
11540Sstevel@tonic-gate 		"Rename error:  check that old %s is still intact.\n",
11550Sstevel@tonic-gate 		map_name);
11560Sstevel@tonic-gate 			del_mapfiles(tmp_name);
11570Sstevel@tonic-gate 			*pushstat = YPPUSH_FILE;
11580Sstevel@tonic-gate 			unlock_map(map_name);
11590Sstevel@tonic-gate 			return (FALSE);
11600Sstevel@tonic-gate 		}
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 		if (rename_map(tmp_name, map_name, secure_map)) {
11630Sstevel@tonic-gate 			del_mapfiles(bkup_name);
11640Sstevel@tonic-gate 		} else {
11650Sstevel@tonic-gate 			del_mapfiles(tmp_name);
11660Sstevel@tonic-gate 			(void) rename_map(bkup_name, map_name, secure_map);
11670Sstevel@tonic-gate 				logprintf(
11680Sstevel@tonic-gate 		"Rename error:  check that old %s is still intact.\n",
11690Sstevel@tonic-gate 			    map_name);
11700Sstevel@tonic-gate 			*pushstat = YPPUSH_FILE;
11710Sstevel@tonic-gate 			unlock_map(map_name);
11720Sstevel@tonic-gate 			return (FALSE);
11730Sstevel@tonic-gate 		}
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 	if (unlock_map(map_name) == 0)
11760Sstevel@tonic-gate 		return (FALSE);
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 	return (TRUE);
11790Sstevel@tonic-gate }
11800Sstevel@tonic-gate 
11810Sstevel@tonic-gate /*
11820Sstevel@tonic-gate  * This tries to get the order number out of the local version of the map.
11830Sstevel@tonic-gate  * If the attempt fails for any version, the function will return "0"
11840Sstevel@tonic-gate  */
11850Sstevel@tonic-gate unsigned
get_local_version(name)11860Sstevel@tonic-gate get_local_version(name)
11870Sstevel@tonic-gate 	char *name;
11880Sstevel@tonic-gate {
11890Sstevel@tonic-gate 	datum key;
11900Sstevel@tonic-gate 	datum val;
11910Sstevel@tonic-gate 	char number[11];
11920Sstevel@tonic-gate 	DBM *db;
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 	if (!check_map_existence(name)) {
11950Sstevel@tonic-gate 		return (0);
11960Sstevel@tonic-gate 	}
11970Sstevel@tonic-gate 	if (debug) fprintf(stderr,
11980Sstevel@tonic-gate 		"ypxfr: Map does exist, checking version now.\n");
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	if ((db = dbm_open(name, 0, 0)) == 0) {
12010Sstevel@tonic-gate 		return (0);
12020Sstevel@tonic-gate 	}
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 	key.dptr = yp_last_modified;
12050Sstevel@tonic-gate 	key.dsize = yp_last_modified_sz;
12060Sstevel@tonic-gate 	val = dbm_fetch(db, key);
12070Sstevel@tonic-gate 	if (!val.dptr) {	/* Check to see if dptr is NULL */
12080Sstevel@tonic-gate 		return (0);
12090Sstevel@tonic-gate 	}
12100Sstevel@tonic-gate 	if (val.dsize == 0 || val.dsize > 10) {
12110Sstevel@tonic-gate 		return (0);
12120Sstevel@tonic-gate 	}
12130Sstevel@tonic-gate 	/* Now save this value while we have it available */
12140Sstevel@tonic-gate 	(void) memmove(number, val.dptr, val.dsize);
12150Sstevel@tonic-gate 	number[val.dsize] = '\0';
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	/*
12180Sstevel@tonic-gate 	 * Now check to see if it is 'secure'. If we haven't already
12190Sstevel@tonic-gate 	 * determined that it is secure in get_private_recs() then we check
12200Sstevel@tonic-gate 	 * the local map here.
12210Sstevel@tonic-gate 	 */
12220Sstevel@tonic-gate 	if (!secure_map) {
12230Sstevel@tonic-gate 		key.dptr = yp_secure;
12240Sstevel@tonic-gate 		key.dsize = yp_secure_sz;
12250Sstevel@tonic-gate 		val = dbm_fetch(db, key);
12260Sstevel@tonic-gate 		secure_map = (val.dptr != NULL);
12270Sstevel@tonic-gate 	}
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 	/*
12300Sstevel@tonic-gate 	 * Now check to see if interdomain requests are made of the local
12310Sstevel@tonic-gate 	 * map. Keep the value around if they are.
12320Sstevel@tonic-gate 	 */
12330Sstevel@tonic-gate 	if (!interdomain_map) {
12340Sstevel@tonic-gate 		key.dptr = yp_interdomain;
12350Sstevel@tonic-gate 		key.dsize = yp_interdomain_sz;
12360Sstevel@tonic-gate 		val = dbm_fetch(db, key);
12370Sstevel@tonic-gate 		if (interdomain_map = (val.dptr != NULL)) {
12380Sstevel@tonic-gate 			interdomain_value = (char *)malloc(val.dsize+1);
12390Sstevel@tonic-gate 			(void) memmove(interdomain_value, val.dptr, val.dsize);
12400Sstevel@tonic-gate 			*(interdomain_value+val.dsize) = '\0';
12410Sstevel@tonic-gate 			interdomain_sz = val.dsize;
12420Sstevel@tonic-gate 		}
12430Sstevel@tonic-gate 	}
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 	/* finish up */
12460Sstevel@tonic-gate 	(void) dbm_close_status(db);
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 	return ((unsigned)atoi(number));
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate /*
12520Sstevel@tonic-gate  * This constructs a file name for a map, minus its dbm_dir
12530Sstevel@tonic-gate  * or dbm_pag extensions
12540Sstevel@tonic-gate  */
12550Sstevel@tonic-gate void
mkfilename(ppath)12560Sstevel@tonic-gate mkfilename(ppath)
12570Sstevel@tonic-gate 	char *ppath;
12580Sstevel@tonic-gate {
12590Sstevel@tonic-gate 	bool_t yptol_mode;
12600Sstevel@tonic-gate 	int len;
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	/* Work out if we are in yptol mode */
12630Sstevel@tonic-gate 	yptol_mode = is_yptol_mode();
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	len = strlen(domain) + strlen(map) + strlen(ypdbpath) + 3;
12660Sstevel@tonic-gate 	if (yptol_mode)
12670Sstevel@tonic-gate 		len += strlen(NTOL_PREFIX);
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	if (len > (MAXNAMLEN + 1)) {
12700Sstevel@tonic-gate 		logprintf("Map name string too long.\n");
12710Sstevel@tonic-gate 	}
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 	(void) strcpy(ppath, ypdbpath);
12740Sstevel@tonic-gate 	(void) strcat(ppath, "/");
12750Sstevel@tonic-gate 	(void) strcat(ppath, domain);
12760Sstevel@tonic-gate 	(void) strcat(ppath, "/");
12770Sstevel@tonic-gate 	if (yptol_mode)
12780Sstevel@tonic-gate 		(void) strcat(ppath, NTOL_PREFIX);
12790Sstevel@tonic-gate 	(void) strcat(ppath, map);
12800Sstevel@tonic-gate }
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate /*
12830Sstevel@tonic-gate  * This returns a temporary name for a map transfer minus its dbm_dir or
12840Sstevel@tonic-gate  * dbm_pag extensions.
12850Sstevel@tonic-gate  */
12860Sstevel@tonic-gate void
mk_tmpname(prefix,xfr_name)12870Sstevel@tonic-gate mk_tmpname(prefix, xfr_name)
12880Sstevel@tonic-gate 	char *prefix;
12890Sstevel@tonic-gate 	char *xfr_name;
12900Sstevel@tonic-gate {
12910Sstevel@tonic-gate 	char xfr_anumber[10];
12920Sstevel@tonic-gate 	long xfr_number;
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	if (!xfr_name) {
12950Sstevel@tonic-gate 		return;
12960Sstevel@tonic-gate 	}
12970Sstevel@tonic-gate 
12980Sstevel@tonic-gate 	xfr_number = getpid();
12990Sstevel@tonic-gate 	(void) sprintf(xfr_anumber, "%d", xfr_number);
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 	(void) strcpy(xfr_name, ypdbpath);
13020Sstevel@tonic-gate 	(void) strcat(xfr_name, "/");
13030Sstevel@tonic-gate 	(void) strcat(xfr_name, domain);
13040Sstevel@tonic-gate 	(void) strcat(xfr_name, "/");
13050Sstevel@tonic-gate 	(void) strcat(xfr_name, prefix);
13060Sstevel@tonic-gate 	(void) strcat(xfr_name, map);
13070Sstevel@tonic-gate 	(void) strcat(xfr_name, ".");
13080Sstevel@tonic-gate 	(void) strcat(xfr_name, xfr_anumber);
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate /*
13120Sstevel@tonic-gate  * This deletes the .pag and .dir files which implement a map.
13130Sstevel@tonic-gate  *
13140Sstevel@tonic-gate  * Note:  No error checking is done here for a garbage input file name or for
13150Sstevel@tonic-gate  * failed unlink operations.
13160Sstevel@tonic-gate  */
13170Sstevel@tonic-gate void
del_mapfiles(basename)13180Sstevel@tonic-gate del_mapfiles(basename)
13190Sstevel@tonic-gate 	char *basename;
13200Sstevel@tonic-gate {
13210Sstevel@tonic-gate 	char dbfilename[MAXNAMLEN + 1];
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate 	if (!basename) {
13240Sstevel@tonic-gate 		return;
13250Sstevel@tonic-gate 	}
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 	strcpy(dbfilename, basename);
13280Sstevel@tonic-gate 	strcat(dbfilename, dbm_pag);
13290Sstevel@tonic-gate 	unlink(dbfilename);
13300Sstevel@tonic-gate 	strcpy(dbfilename, basename);
13310Sstevel@tonic-gate 	strcat(dbfilename, dbm_dir);
13320Sstevel@tonic-gate 	unlink(dbfilename);
13330Sstevel@tonic-gate }
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate /*
13360Sstevel@tonic-gate  * This creates <pname>.dir and <pname>.pag
13370Sstevel@tonic-gate  */
13380Sstevel@tonic-gate bool
new_mapfiles(pname)13390Sstevel@tonic-gate new_mapfiles(pname)
13400Sstevel@tonic-gate 	char *pname;
13410Sstevel@tonic-gate {
13420Sstevel@tonic-gate 	char dbfile[MAXNAMLEN + 1];
13430Sstevel@tonic-gate 	int f;
13440Sstevel@tonic-gate 	int len;
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 	if (!pname || ((len = strlen(pname)) == 0) ||
13470Sstevel@tonic-gate 	    (len + 5) > (MAXNAMLEN + 1)) {
13480Sstevel@tonic-gate 		return (FALSE);
13490Sstevel@tonic-gate 	}
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	errno = 0;
13520Sstevel@tonic-gate 	(void) strcpy(dbfile, pname);
13530Sstevel@tonic-gate 	(void) strcat(dbfile, dbm_dir);
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 	if ((f = open(dbfile, (O_WRONLY | O_CREAT | O_TRUNC), 0600)) >= 0) {
13560Sstevel@tonic-gate 		(void) close(f);
13570Sstevel@tonic-gate 		(void) strcpy(dbfile, pname);
13580Sstevel@tonic-gate 		(void) strcat(dbfile, dbm_pag);
13590Sstevel@tonic-gate 
13600Sstevel@tonic-gate 		if ((f = open(dbfile, (O_WRONLY | O_CREAT | O_TRUNC),
13610Sstevel@tonic-gate 		    0600)) >= 0) {
13620Sstevel@tonic-gate 			(void) close(f);
13630Sstevel@tonic-gate 			return (TRUE);
13640Sstevel@tonic-gate 		} else {
13650Sstevel@tonic-gate 			return (FALSE);
13660Sstevel@tonic-gate 		}
13670Sstevel@tonic-gate 
13680Sstevel@tonic-gate 	} else {
13690Sstevel@tonic-gate 		return (FALSE);
13700Sstevel@tonic-gate 	}
13710Sstevel@tonic-gate }
13720Sstevel@tonic-gate 
1373*702Sth160488 int
count_callback(status)13740Sstevel@tonic-gate count_callback(status)
13750Sstevel@tonic-gate 	int status;
13760Sstevel@tonic-gate {
13770Sstevel@tonic-gate 	if (status != YP_TRUE) {
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate 		if (status != YP_NOMORE) {
13800Sstevel@tonic-gate 			logprintf(
13810Sstevel@tonic-gate 			    "Error from ypserv on %s (ypall_callback) = %s.\n",
13820Sstevel@tonic-gate 			    master, yperr_string(ypprot_err(status)));
13830Sstevel@tonic-gate 		}
13840Sstevel@tonic-gate 
13850Sstevel@tonic-gate 		return (TRUE);
13860Sstevel@tonic-gate 	}
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate 	entry_count++;
13890Sstevel@tonic-gate 	return (FALSE);
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate /*
13930Sstevel@tonic-gate  * This counts the entries in the dbm file after the transfer to
13940Sstevel@tonic-gate  * make sure that the dbm file was built correctly.
13950Sstevel@tonic-gate  * Returns TRUE if everything is OK, FALSE if they mismatch.
13960Sstevel@tonic-gate  */
1397*702Sth160488 int
count_mismatch(pname,oldcount)13980Sstevel@tonic-gate count_mismatch(pname, oldcount)
13990Sstevel@tonic-gate 	char *pname;
14000Sstevel@tonic-gate 	int oldcount;
14010Sstevel@tonic-gate {
14020Sstevel@tonic-gate 	datum key;
14030Sstevel@tonic-gate 	DBM *db;
14040Sstevel@tonic-gate #ifdef REALLY_PARANOID
14050Sstevel@tonic-gate 	struct ypall_callback cbinfo;
14060Sstevel@tonic-gate 	struct ypreq_nokey allreq;
14070Sstevel@tonic-gate 	enum clnt_stat s;
14080Sstevel@tonic-gate 	struct dom_binding domb;
14090Sstevel@tonic-gate 	datum value;
14100Sstevel@tonic-gate #endif /* REALLY_PARANOID */
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	entry_count = 0;
14130Sstevel@tonic-gate 	db = dbm_open(pname, 0, 0);
14140Sstevel@tonic-gate 	if (db) {
14150Sstevel@tonic-gate 	    for (key = dbm_firstkey(db);
14160Sstevel@tonic-gate 				key.dptr != NULL; key = dbm_nextkey(db))
14170Sstevel@tonic-gate 		entry_count++;
14180Sstevel@tonic-gate 	    dbm_close_status(db);
14190Sstevel@tonic-gate 	}
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 	if (oldcount != entry_count) {
14220Sstevel@tonic-gate 	logprintf(
14230Sstevel@tonic-gate 		    "*** Count mismatch in dbm file %s: old=%d, new=%d ***\n",
14240Sstevel@tonic-gate 		    map, oldcount, entry_count);
14250Sstevel@tonic-gate 	return (FALSE);
14260Sstevel@tonic-gate 	}
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate #ifdef REALLY_PARANOID
14290Sstevel@tonic-gate 
14300Sstevel@tonic-gate 	if ((domb.dom_client = __yp_clnt_create_rsvdport(master, YPPROG,
14310Sstevel@tonic-gate 						    master_prog_vers,
14320Sstevel@tonic-gate 						    "tcp6", 0, 0)) == 0 &&
14330Sstevel@tonic-gate 		(domb.dom_client = __yp_clnt_create_rsvdport(master, YPPROG,
14340Sstevel@tonic-gate 						    master_prog_vers,
14350Sstevel@tonic-gate 						    "tcp", 0, 0)) == 0) {
14360Sstevel@tonic-gate 		clnt_pcreateerror("ypxfr (mismatch) - TCP channel "
14370Sstevel@tonic-gate 					"create failure");
14380Sstevel@tonic-gate 		return (FALSE);
14390Sstevel@tonic-gate 	}
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 	if (master_prog_vers == YPVERS) {
14420Sstevel@tonic-gate 		int tmpstat;
14430Sstevel@tonic-gate 
14440Sstevel@tonic-gate 		allreq.domain = source;
14450Sstevel@tonic-gate 		allreq.map = map;
14460Sstevel@tonic-gate 		cbinfo.foreach = count_callback;
14470Sstevel@tonic-gate 		tmpstat = 0;
14480Sstevel@tonic-gate 		cbinfo.data = (char *)&tmpstat;
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 		entry_count = 0;
14510Sstevel@tonic-gate 		s = clnt_call(domb.dom_client, YPPROC_ALL, xdr_ypreq_nokey,
14520Sstevel@tonic-gate 		    &allreq, xdr_ypall, &cbinfo, tcp_timeout);
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 		if (tmpstat == 0) {
14550Sstevel@tonic-gate 			if (s == RPC_SUCCESS) {
14560Sstevel@tonic-gate 			} else {
14570Sstevel@tonic-gate 				clnt_perror(domb.dom_client,
14580Sstevel@tonic-gate 		"ypxfr (get_map/all) - RPC clnt_call (TCP) failure");
14590Sstevel@tonic-gate 		    return (FALSE);
14600Sstevel@tonic-gate 			}
14610Sstevel@tonic-gate 
14620Sstevel@tonic-gate 		} else {
14630Sstevel@tonic-gate 		    return (FALSE);
14640Sstevel@tonic-gate 		}
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 	} else {
14670Sstevel@tonic-gate 	    logprintf("Wrong version number!\n");
14680Sstevel@tonic-gate 	    return (FALSE);
14690Sstevel@tonic-gate 	}
14700Sstevel@tonic-gate 	clnt_destroy(domb.dom_client);
14710Sstevel@tonic-gate 	close(domb.dom_socket);
14720Sstevel@tonic-gate 	entry_count += 2;			/* add in YP_entries */
14730Sstevel@tonic-gate 	if (oldcount != entry_count) {
14740Sstevel@tonic-gate 		logprintf(
14750Sstevel@tonic-gate 	"*** Count mismatch after enumerate %s: old=%d, new=%d ***\n",
14760Sstevel@tonic-gate 		    map, oldcount, entry_count);
14770Sstevel@tonic-gate 		return (FALSE);
14780Sstevel@tonic-gate 	}
14790Sstevel@tonic-gate #endif /* REALLY_PARANOID */
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 	return (TRUE);
14820Sstevel@tonic-gate }
14830Sstevel@tonic-gate 
14840Sstevel@tonic-gate /*
14850Sstevel@tonic-gate  * This sets up a TCP connection to the master server, and either gets
14860Sstevel@tonic-gate  * ypall_callback to do all the work of writing it to the local dbm file
14870Sstevel@tonic-gate  * (if the ypserv is current version), or does it itself for an old ypserv.
14880Sstevel@tonic-gate  */
14890Sstevel@tonic-gate bool
get_map(pname,pushstat)14900Sstevel@tonic-gate get_map(pname, pushstat)
14910Sstevel@tonic-gate 	char *pname;
14920Sstevel@tonic-gate 	int *pushstat;
14930Sstevel@tonic-gate {
14940Sstevel@tonic-gate 	struct dom_binding domb;
14950Sstevel@tonic-gate 	enum clnt_stat s;
14960Sstevel@tonic-gate 	struct ypreq_nokey allreq;
14970Sstevel@tonic-gate 	struct ypall_callback cbinfo;
14980Sstevel@tonic-gate 	bool retval = FALSE;
14990Sstevel@tonic-gate 	int tmpstat;
15000Sstevel@tonic-gate 	int	recvsiz = 24 * 1024;
15010Sstevel@tonic-gate 	struct netconfig *nconf;
15020Sstevel@tonic-gate 	int fd;
15030Sstevel@tonic-gate 	struct netbuf *svcaddr;
15040Sstevel@tonic-gate 	char *netid[] = { "tcp6", "tcp" };
15050Sstevel@tonic-gate 	int i, lastnetid = (sizeof (netid)/sizeof (netid[0])) - 1;
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate 	svcaddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
15080Sstevel@tonic-gate 	if (! svcaddr)
15090Sstevel@tonic-gate 		return (FALSE);
15100Sstevel@tonic-gate 	svcaddr->maxlen = 32;
15110Sstevel@tonic-gate 	svcaddr->len = 32;
15120Sstevel@tonic-gate 	svcaddr->buf = (char *)malloc(32);
15130Sstevel@tonic-gate 	if (! svcaddr->buf) {
15140Sstevel@tonic-gate 		free(svcaddr);
15150Sstevel@tonic-gate 		return (FALSE);
15160Sstevel@tonic-gate 	}
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate 	for (i = 0; i <= lastnetid; i++) {
15190Sstevel@tonic-gate 		fd = RPC_ANYFD;
15200Sstevel@tonic-gate 		if ((nconf = getnetconfigent(netid[i])) == NULL) {
15210Sstevel@tonic-gate 			if (i != lastnetid)
15220Sstevel@tonic-gate 				continue;
15230Sstevel@tonic-gate 			logprintf("ypxfr: tcp transport not supported\n");
15240Sstevel@tonic-gate 			free(svcaddr->buf);
15250Sstevel@tonic-gate 			free(svcaddr);
15260Sstevel@tonic-gate 			return (FALSE);
15270Sstevel@tonic-gate 		}
15280Sstevel@tonic-gate 		if (rpcb_getaddr(YPPROG, master_prog_vers, nconf, svcaddr,
15290Sstevel@tonic-gate 				master) == FALSE) {
15300Sstevel@tonic-gate 			freenetconfigent(nconf);
15310Sstevel@tonic-gate 			if (i != lastnetid)
15320Sstevel@tonic-gate 				continue;
15330Sstevel@tonic-gate 			logprintf("ypxfr: could not get %s address\n", master);
15340Sstevel@tonic-gate 			free(svcaddr->buf);
15350Sstevel@tonic-gate 			free(svcaddr);
15360Sstevel@tonic-gate 			return (FALSE);
15370Sstevel@tonic-gate 		}
15380Sstevel@tonic-gate 		if ((domb.dom_client = __nis_clnt_create(fd, nconf, 0, svcaddr,
15390Sstevel@tonic-gate 			0, YPPROG, master_prog_vers, recvsiz, 0)) == 0) {
15400Sstevel@tonic-gate 			freenetconfigent(nconf);
15410Sstevel@tonic-gate 			if (i != lastnetid)
15420Sstevel@tonic-gate 				continue;
15430Sstevel@tonic-gate 			clnt_pcreateerror(
15440Sstevel@tonic-gate 				"ypxfr (get_map) - TCP channel create failure");
15450Sstevel@tonic-gate 			*pushstat = YPPUSH_RPC;
15460Sstevel@tonic-gate 			free(svcaddr->buf);
15470Sstevel@tonic-gate 			free(svcaddr);
15480Sstevel@tonic-gate 			return (FALSE);
15490Sstevel@tonic-gate 		}
15500Sstevel@tonic-gate 		break;
15510Sstevel@tonic-gate 	}
15520Sstevel@tonic-gate 
15530Sstevel@tonic-gate 	entry_count = 0;
15540Sstevel@tonic-gate 	if (master_prog_vers == YPVERS) {
15550Sstevel@tonic-gate 		allreq.domain = source;
15560Sstevel@tonic-gate 		allreq.map = map;
15570Sstevel@tonic-gate 		cbinfo.foreach = ypall_callback;
15580Sstevel@tonic-gate 		tmpstat = 0;
15590Sstevel@tonic-gate 		cbinfo.data = (char *)&tmpstat;
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate 		s = clnt_call(domb.dom_client, YPPROC_ALL,
15620Sstevel@tonic-gate 			(xdrproc_t)xdr_ypreq_nokey,
15630Sstevel@tonic-gate 			(char *)&allreq, (xdrproc_t)xdr_ypall, (char *)&cbinfo,
15640Sstevel@tonic-gate 			tcp_timeout);
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate 		if (tmpstat == 0) {
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate 			if (s == RPC_SUCCESS) {
15690Sstevel@tonic-gate 				retval = TRUE;
15700Sstevel@tonic-gate 			} else {
15710Sstevel@tonic-gate 				clnt_perror(domb.dom_client,
15720Sstevel@tonic-gate 			"ypxfr (get_map/all) - RPC clnt_call (TCP) failure");
15730Sstevel@tonic-gate 				*pushstat = YPPUSH_RPC;
15740Sstevel@tonic-gate 			}
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate 		} else {
15770Sstevel@tonic-gate 			*pushstat = tmpstat;
15780Sstevel@tonic-gate 		}
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate 	} else
15810Sstevel@tonic-gate 		retval = FALSE; /* barf again at YPOLDVERS */
15820Sstevel@tonic-gate cleanup:
15830Sstevel@tonic-gate 	clnt_destroy(domb.dom_client);
15840Sstevel@tonic-gate 	return (retval);
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate /*
15880Sstevel@tonic-gate  * This sticks each key-value pair into the current map.  It returns FALSE as
15890Sstevel@tonic-gate  * long as it wants to keep getting called back, and TRUE on error conditions
15900Sstevel@tonic-gate  * and "No more k-v pairs".
15910Sstevel@tonic-gate  */
15920Sstevel@tonic-gate int
ypall_callback(status,key,kl,val,vl,pushstat)15930Sstevel@tonic-gate ypall_callback(status, key, kl, val, vl, pushstat)
15940Sstevel@tonic-gate 	int status;
15950Sstevel@tonic-gate 	char *key;
15960Sstevel@tonic-gate 	int kl;
15970Sstevel@tonic-gate 	char *val;
15980Sstevel@tonic-gate 	int vl;
15990Sstevel@tonic-gate 	int *pushstat;
16000Sstevel@tonic-gate {
16010Sstevel@tonic-gate 	datum keydat;
16020Sstevel@tonic-gate 	datum valdat;
16030Sstevel@tonic-gate 	datum test;
16040Sstevel@tonic-gate 
16050Sstevel@tonic-gate 	if (status != YP_TRUE) {
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 		if (status != YP_NOMORE) {
16080Sstevel@tonic-gate 			logprintf(
16090Sstevel@tonic-gate 			    "Error from ypserv on %s (ypall_callback) = %s.\n",
16100Sstevel@tonic-gate 			    master, yperr_string(ypprot_err(status)));
16110Sstevel@tonic-gate 			*pushstat = map_yperr_to_pusherr(status);
16120Sstevel@tonic-gate 		}
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate 		return (TRUE);
16150Sstevel@tonic-gate 	}
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 	keydat.dptr = key;
16180Sstevel@tonic-gate 	keydat.dsize = kl;
16190Sstevel@tonic-gate 	valdat.dptr = val;
16200Sstevel@tonic-gate 	valdat.dsize = vl;
16210Sstevel@tonic-gate 	entry_count++;
16220Sstevel@tonic-gate /* way too many fetches */
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate #ifdef PARANOID
16250Sstevel@tonic-gate 	test = dbm_fetch(db, keydat);
16260Sstevel@tonic-gate 	if (test.dptr != NULL) {
16270Sstevel@tonic-gate 		logprintf("Duplicate key %s in map %s\n", key, map);
16280Sstevel@tonic-gate 		*pushstat  = YPPUSH_DBM;
16290Sstevel@tonic-gate 		return (TRUE);
16300Sstevel@tonic-gate 	}
16310Sstevel@tonic-gate #endif /* PARANOID */
16320Sstevel@tonic-gate 	if (dbm_store(db, keydat, valdat, 0) < 0) {
16330Sstevel@tonic-gate 		logprintf(
16340Sstevel@tonic-gate 		    "Can't do dbm store into temp map %s.\n", map);
16350Sstevel@tonic-gate 		*pushstat  = YPPUSH_DBM;
16360Sstevel@tonic-gate 		return (TRUE);
16370Sstevel@tonic-gate 	}
16380Sstevel@tonic-gate #ifdef PARANOID
16390Sstevel@tonic-gate 	test = dbm_fetch(db, keydat);
16400Sstevel@tonic-gate 	if (test.dptr == NULL) {
16410Sstevel@tonic-gate 		logprintf("Key %s was not inserted into dbm file %s\n",
16420Sstevel@tonic-gate 			key, map);
16430Sstevel@tonic-gate 		*pushstat  = YPPUSH_DBM;
16440Sstevel@tonic-gate 		return (TRUE);
16450Sstevel@tonic-gate 	}
16460Sstevel@tonic-gate #endif /* PARANOID */
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 	if (dbm_error(db)) {
16490Sstevel@tonic-gate 		logprintf("Key %s dbm_error raised in file %s\n",
16500Sstevel@tonic-gate 			key, map);
16510Sstevel@tonic-gate 		*pushstat  = YPPUSH_DBM;
16520Sstevel@tonic-gate 		return (TRUE);
16530Sstevel@tonic-gate 	}
16540Sstevel@tonic-gate 	return (FALSE);
16550Sstevel@tonic-gate }
16560Sstevel@tonic-gate 
16570Sstevel@tonic-gate /*
16580Sstevel@tonic-gate  * This maps a YP_xxxx error code into a YPPUSH_xxxx error code
16590Sstevel@tonic-gate  */
16600Sstevel@tonic-gate int
map_yperr_to_pusherr(yperr)16610Sstevel@tonic-gate map_yperr_to_pusherr(yperr)
16620Sstevel@tonic-gate 	int yperr;
16630Sstevel@tonic-gate {
16640Sstevel@tonic-gate 	int reason;
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 	switch (yperr) {
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 	case YP_NOMORE:
16690Sstevel@tonic-gate 		reason = YPPUSH_SUCC;
16700Sstevel@tonic-gate 		break;
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	case YP_NOMAP:
16730Sstevel@tonic-gate 		reason = YPPUSH_NOMAP;
16740Sstevel@tonic-gate 		break;
16750Sstevel@tonic-gate 
16760Sstevel@tonic-gate 	case YP_NODOM:
16770Sstevel@tonic-gate 		reason = YPPUSH_NODOM;
16780Sstevel@tonic-gate 		break;
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 	case YP_NOKEY:
16810Sstevel@tonic-gate 		reason = YPPUSH_YPERR;
16820Sstevel@tonic-gate 		break;
16830Sstevel@tonic-gate 
16840Sstevel@tonic-gate 	case YP_BADARGS:
16850Sstevel@tonic-gate 		reason = YPPUSH_BADARGS;
16860Sstevel@tonic-gate 		break;
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	case YP_BADDB:
16890Sstevel@tonic-gate 		reason = YPPUSH_YPERR;
16900Sstevel@tonic-gate 		break;
16910Sstevel@tonic-gate 
16920Sstevel@tonic-gate 	default:
16930Sstevel@tonic-gate 		reason = YPPUSH_XFRERR;
16940Sstevel@tonic-gate 		break;
16950Sstevel@tonic-gate 	}
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate 	return (reason);
16980Sstevel@tonic-gate }
16990Sstevel@tonic-gate 
17000Sstevel@tonic-gate /*
17010Sstevel@tonic-gate  * This writes the last-modified and master entries into the new dbm file
17020Sstevel@tonic-gate  */
17030Sstevel@tonic-gate bool
add_private_entries(pname)17040Sstevel@tonic-gate add_private_entries(pname)
17050Sstevel@tonic-gate 	char *pname;
17060Sstevel@tonic-gate {
17070Sstevel@tonic-gate 	datum key;
17080Sstevel@tonic-gate 	datum val;
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 	if (!fake_master_version) {
17110Sstevel@tonic-gate 		key.dptr = yp_last_modified;
17120Sstevel@tonic-gate 		key.dsize = yp_last_modified_sz;
17130Sstevel@tonic-gate 		val.dptr = master_ascii_version;
17140Sstevel@tonic-gate 		val.dsize = strlen(master_ascii_version);
17150Sstevel@tonic-gate 
17160Sstevel@tonic-gate 		if (dbm_store(db, key, val, 1) < 0) {
17170Sstevel@tonic-gate 			logprintf(
17180Sstevel@tonic-gate 			    "Can't do dbm store into temp map %s.\n",
17190Sstevel@tonic-gate 			    pname);
17200Sstevel@tonic-gate 			return (FALSE);
17210Sstevel@tonic-gate 		}
17220Sstevel@tonic-gate 		entry_count++;
17230Sstevel@tonic-gate 	}
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 	if (master_name) {
17260Sstevel@tonic-gate 		key.dptr = yp_master_name;
17270Sstevel@tonic-gate 		key.dsize = yp_master_name_sz;
17280Sstevel@tonic-gate 		val.dptr = master_name;
17290Sstevel@tonic-gate 		val.dsize = strlen(master_name);
17300Sstevel@tonic-gate 		if (dbm_store(db, key, val, 1) < 0) {
17310Sstevel@tonic-gate 			logprintf(
17320Sstevel@tonic-gate 			    "Can't do dbm store into temp map %s.\n",
17330Sstevel@tonic-gate 			    pname);
17340Sstevel@tonic-gate 			return (FALSE);
17350Sstevel@tonic-gate 		}
17360Sstevel@tonic-gate 		entry_count++;
17370Sstevel@tonic-gate 	}
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 	if (interdomain_map) {
17400Sstevel@tonic-gate 		key.dptr = yp_interdomain;
17410Sstevel@tonic-gate 		key.dsize = yp_interdomain_sz;
17420Sstevel@tonic-gate 		val.dptr = interdomain_value;
17430Sstevel@tonic-gate 		val.dsize = interdomain_sz;
17440Sstevel@tonic-gate 		if (dbm_store(db, key, val, 1) < 0) {
17450Sstevel@tonic-gate 			logprintf(
17460Sstevel@tonic-gate 			    "Can't do dbm store into temp map %s.\n",
17470Sstevel@tonic-gate 			    pname);
17480Sstevel@tonic-gate 			return (FALSE);
17490Sstevel@tonic-gate 		}
17500Sstevel@tonic-gate 		entry_count++;
17510Sstevel@tonic-gate 	}
17520Sstevel@tonic-gate 
17530Sstevel@tonic-gate 	if (secure_map) {
17540Sstevel@tonic-gate 		key.dptr = yp_secure;
17550Sstevel@tonic-gate 		key.dsize = yp_secure_sz;
17560Sstevel@tonic-gate 		val.dptr = yp_secure;
17570Sstevel@tonic-gate 		val.dsize = yp_secure_sz;
17580Sstevel@tonic-gate 		if (dbm_store(db, key, val, 1) < 0) {
17590Sstevel@tonic-gate 			logprintf(
17600Sstevel@tonic-gate 			    "Can't do dbm store into temp map %s.\n",
17610Sstevel@tonic-gate 			    pname);
17620Sstevel@tonic-gate 			return (FALSE);
17630Sstevel@tonic-gate 		}
17640Sstevel@tonic-gate 		entry_count++;
17650Sstevel@tonic-gate 	}
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate 	return (TRUE);
17680Sstevel@tonic-gate }
17690Sstevel@tonic-gate 
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate /*
17720Sstevel@tonic-gate  * This sends a YPPROC_CLEAR message to the local ypserv process.
17730Sstevel@tonic-gate  */
17740Sstevel@tonic-gate bool
send_ypclear(pushstat)17750Sstevel@tonic-gate send_ypclear(pushstat)
17760Sstevel@tonic-gate 	int *pushstat;
17770Sstevel@tonic-gate {
17780Sstevel@tonic-gate 	struct dom_binding domb;
17790Sstevel@tonic-gate 	char local_host_name[256];
17800Sstevel@tonic-gate 	unsigned int progvers;
17810Sstevel@tonic-gate 	int status;
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 	if (gethostname(local_host_name, 256)) {
17840Sstevel@tonic-gate 		logprintf("Can't get local machine name.\n");
17850Sstevel@tonic-gate 		*pushstat = YPPUSH_RSRC;
17860Sstevel@tonic-gate 		return (FALSE);
17870Sstevel@tonic-gate 	}
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	if (!bind_to_server(local_host_name, &domb,
17900Sstevel@tonic-gate 	    &progvers, &status)) {
17910Sstevel@tonic-gate 		*pushstat = YPPUSH_CLEAR;
17920Sstevel@tonic-gate 		return (FALSE);
17930Sstevel@tonic-gate 	}
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate 	if ((enum clnt_stat) clnt_call(domb.dom_client,
17960Sstevel@tonic-gate 	    YPPROC_CLEAR, xdr_void, 0, xdr_void, 0,
17970Sstevel@tonic-gate 	    udp_timeout) != RPC_SUCCESS) {
17980Sstevel@tonic-gate 		logprintf(
17990Sstevel@tonic-gate 		"Can't send ypclear message to ypserv on the local machine.\n");
18000Sstevel@tonic-gate 		xfr_exit(YPPUSH_CLEAR);
18010Sstevel@tonic-gate 	}
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 	return (TRUE);
18040Sstevel@tonic-gate }
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate /*
18070Sstevel@tonic-gate  * This decides if send_callback has to get called, and does the process exit.
18080Sstevel@tonic-gate  */
18090Sstevel@tonic-gate void
xfr_exit(status)18100Sstevel@tonic-gate xfr_exit(status)
18110Sstevel@tonic-gate 	int status;
18120Sstevel@tonic-gate {
18130Sstevel@tonic-gate 	if (callback) {
18140Sstevel@tonic-gate 		send_callback(&status);
18150Sstevel@tonic-gate 	}
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 	if (status == YPPUSH_SUCC) {
18180Sstevel@tonic-gate #ifdef TREEPUSH
18190Sstevel@tonic-gate 		if (treepush) {
18200Sstevel@tonic-gate 		if (debug)
18210Sstevel@tonic-gate 		execlp("./yppush", "yppush", "-T", map, 0);
18220Sstevel@tonic-gate 		execlp("/usr/etc/yp/yppush", "yppush", "-T", map, 0);
18230Sstevel@tonic-gate 		perror("yppush");
18240Sstevel@tonic-gate 		}
18250Sstevel@tonic-gate #endif
18260Sstevel@tonic-gate 		exit(0);
18270Sstevel@tonic-gate 	} else {
18280Sstevel@tonic-gate 		exit(1);
18290Sstevel@tonic-gate 	}
18300Sstevel@tonic-gate }
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate /*
18330Sstevel@tonic-gate  * This sets up a UDP connection to the yppush process which contacted our
18340Sstevel@tonic-gate  * parent ypserv, and sends him a status on the requested transfer.
18350Sstevel@tonic-gate  */
18360Sstevel@tonic-gate void
send_callback(status)18370Sstevel@tonic-gate send_callback(status)
18380Sstevel@tonic-gate 	int *status;
18390Sstevel@tonic-gate {
18400Sstevel@tonic-gate 	struct yppushresp_xfr resp;
18410Sstevel@tonic-gate 	struct dom_binding domb;
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 	resp.transid = (unsigned long) atoi(tid);
18440Sstevel@tonic-gate 	resp.status = (unsigned long) *status;
18450Sstevel@tonic-gate 
18460Sstevel@tonic-gate 	udp_timeout.tv_sec = CALLTIMEOUT;
18470Sstevel@tonic-gate 
18480Sstevel@tonic-gate 	if ((domb.dom_client = __yp_clnt_create_rsvdport(pushhost,
18490Sstevel@tonic-gate 						    (ulong_t)atoi(proto),
18500Sstevel@tonic-gate 						    YPPUSHVERS,
18510Sstevel@tonic-gate 						    0, 0, 0)) == NULL) {
18520Sstevel@tonic-gate 		*status = YPPUSH_RPC;
18530Sstevel@tonic-gate 		return;
18540Sstevel@tonic-gate 	}
18550Sstevel@tonic-gate 
18560Sstevel@tonic-gate 	if ((enum clnt_stat) clnt_call(domb.dom_client,
18570Sstevel@tonic-gate 	    YPPUSHPROC_XFRRESP, (xdrproc_t)xdr_yppushresp_xfr,
18580Sstevel@tonic-gate 	    (char *)&resp, xdr_void, 0,
18590Sstevel@tonic-gate 	    udp_timeout) != RPC_SUCCESS) {
18600Sstevel@tonic-gate 		*status = YPPUSH_RPC;
18610Sstevel@tonic-gate 		return;
18620Sstevel@tonic-gate 	}
18630Sstevel@tonic-gate }
18640Sstevel@tonic-gate 
18650Sstevel@tonic-gate /*
18660Sstevel@tonic-gate  * FUNCTION:    is_yptol_mode();
18670Sstevel@tonic-gate  *
18680Sstevel@tonic-gate  * DESCRIPTION: Determines if we should run in N2L or traditional mode based
18690Sstevel@tonic-gate  *              on the presence of the N2L mapping file.
18700Sstevel@tonic-gate  *
18710Sstevel@tonic-gate  *		This is a copy of a function from libnisdb. If more than this
18720Sstevel@tonic-gate  *		one function become required it may be worth linking the
18730Sstevel@tonic-gate  *		entire lib.
18740Sstevel@tonic-gate  *
18750Sstevel@tonic-gate  * INPUTS:      Nothing
18760Sstevel@tonic-gate  *
18770Sstevel@tonic-gate  * OUTPUTS:     TRUE = Run in N2L mode
18780Sstevel@tonic-gate  *              FALSE = Run in traditional mode.
18790Sstevel@tonic-gate  */
18800Sstevel@tonic-gate bool_t
is_yptol_mode()18810Sstevel@tonic-gate is_yptol_mode()
18820Sstevel@tonic-gate {
18830Sstevel@tonic-gate 	struct stat filestat;
18840Sstevel@tonic-gate 
18850Sstevel@tonic-gate 	if (stat(NTOL_MAP_FILE, &filestat) != -1)
18860Sstevel@tonic-gate 		return (TRUE);
18870Sstevel@tonic-gate 
18880Sstevel@tonic-gate 	return (FALSE);
18890Sstevel@tonic-gate }
1890