xref: /freebsd/libexec/ypxfr/ypxfr_main.c (revision 81a82d4dfd8407c94eaf04f2164f7c9d15ad784f)
1665823d0SBill Paul /*
2665823d0SBill Paul  * Copyright (c) 1995
3665823d0SBill Paul  *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4665823d0SBill Paul  *
5665823d0SBill Paul  * Redistribution and use in source and binary forms, with or without
6665823d0SBill Paul  * modification, are permitted provided that the following conditions
7665823d0SBill Paul  * are met:
8665823d0SBill Paul  * 1. Redistributions of source code must retain the above copyright
9665823d0SBill Paul  *    notice, this list of conditions and the following disclaimer.
10665823d0SBill Paul  * 2. Redistributions in binary form must reproduce the above copyright
11665823d0SBill Paul  *    notice, this list of conditions and the following disclaimer in the
12665823d0SBill Paul  *    documentation and/or other materials provided with the distribution.
13665823d0SBill Paul  * 3. All advertising materials mentioning features or use of this software
14665823d0SBill Paul  *    must display the following acknowledgement:
15665823d0SBill Paul  *	This product includes software developed by Bill Paul.
16665823d0SBill Paul  * 4. Neither the name of the author nor the names of any co-contributors
17665823d0SBill Paul  *    may be used to endorse or promote products derived from this software
18665823d0SBill Paul  *    without specific prior written permission.
19665823d0SBill Paul  *
20665823d0SBill Paul  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21665823d0SBill Paul  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22665823d0SBill Paul  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23665823d0SBill Paul  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24665823d0SBill Paul  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25665823d0SBill Paul  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26665823d0SBill Paul  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27665823d0SBill Paul  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28665823d0SBill Paul  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29665823d0SBill Paul  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30665823d0SBill Paul  * SUCH DAMAGE.
31665823d0SBill Paul  *
3281a82d4dSBill Paul  *	$Id: ypxfr_main.c,v 1.19 1996/10/25 15:58:15 wpaul Exp $
33665823d0SBill Paul  */
34665823d0SBill Paul #include <stdio.h>
35665823d0SBill Paul #include <stdlib.h>
36665823d0SBill Paul #include <unistd.h>
37665823d0SBill Paul #include <string.h>
38665823d0SBill Paul #include <syslog.h>
39665823d0SBill Paul #include <errno.h>
40665823d0SBill Paul #include <sys/types.h>
41665823d0SBill Paul #include <sys/param.h>
42665823d0SBill Paul #include <sys/socket.h>
43665823d0SBill Paul #include <netinet/in.h>
44665823d0SBill Paul #include <arpa/inet.h>
45665823d0SBill Paul #include <rpc/rpc.h>
4634a042e8SBill Paul #include <rpc/clnt.h>
47665823d0SBill Paul #include <rpcsvc/yp.h>
48665823d0SBill Paul struct dom_binding {};
49665823d0SBill Paul #include <rpcsvc/ypclnt.h>
5016deb43aSBill Paul #include <rpcsvc/ypxfrd.h>
51665823d0SBill Paul #include "ypxfr_extern.h"
52665823d0SBill Paul 
53665823d0SBill Paul #ifndef lint
5481a82d4dSBill Paul static const char rcsid[] = "$Id: ypxfr_main.c,v 1.19 1996/10/25 15:58:15 wpaul Exp $";
55665823d0SBill Paul #endif
56665823d0SBill Paul 
57665823d0SBill Paul char *progname = "ypxfr";
58665823d0SBill Paul char *yp_dir = _PATH_YP;
59665823d0SBill Paul int _rpcpmstart = 0;
60665823d0SBill Paul int ypxfr_use_yplib = 0; /* Assume the worst. */
61665823d0SBill Paul int ypxfr_clear = 1;
62665823d0SBill Paul int ypxfr_prognum = 0;
63665823d0SBill Paul struct sockaddr_in ypxfr_callback_addr;
64665823d0SBill Paul struct yppushresp_xfr ypxfr_resp;
65665823d0SBill Paul DB *dbp;
66665823d0SBill Paul 
67665823d0SBill Paul static void ypxfr_exit(retval, temp)
68665823d0SBill Paul 	ypxfrstat retval;
69665823d0SBill Paul 	char *temp;
70665823d0SBill Paul {
71665823d0SBill Paul 	CLIENT *clnt;
72665823d0SBill Paul 	int sock = RPC_ANYSOCK;
73665823d0SBill Paul 	struct timeval timeout;
74665823d0SBill Paul 
75665823d0SBill Paul 	/* Clean up no matter what happened previously. */
76665823d0SBill Paul 	if (temp != NULL) {
77d6cab902SBill Paul 		if (dbp != NULL)
78665823d0SBill Paul 			(void)(dbp->close)(dbp);
79665823d0SBill Paul 		if (unlink(temp) == -1) {
80665823d0SBill Paul 			yp_error("failed to unlink %s",strerror(errno));
81665823d0SBill Paul 		}
82665823d0SBill Paul 	}
83665823d0SBill Paul 
84665823d0SBill Paul 	if (_rpcpmstart) {
85665823d0SBill Paul 		timeout.tv_sec = 20;
86665823d0SBill Paul 		timeout.tv_usec = 0;
87665823d0SBill Paul 
88665823d0SBill Paul 		if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum,
89665823d0SBill Paul 					1, timeout, &sock)) == NULL) {
9016deb43aSBill Paul 			yp_error("%s", clnt_spcreateerror("failed to \
9116deb43aSBill Paul establish callback handle"));
92665823d0SBill Paul 			exit(1);
93665823d0SBill Paul 		}
94665823d0SBill Paul 
95665823d0SBill Paul 		ypxfr_resp.status = retval;
96665823d0SBill Paul 
97665823d0SBill Paul 		if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) {
98665823d0SBill Paul 			yp_error("%s", clnt_sperror(clnt, "callback failed"));
99665823d0SBill Paul 			clnt_destroy(clnt);
100665823d0SBill Paul 			exit(1);
101665823d0SBill Paul 		}
102665823d0SBill Paul 		clnt_destroy(clnt);
103665823d0SBill Paul 	} else {
104665823d0SBill Paul 		yp_error("Exiting: %s", ypxfrerr_string(retval));
105665823d0SBill Paul 	}
106665823d0SBill Paul 
107665823d0SBill Paul 	exit(0);
108665823d0SBill Paul }
109665823d0SBill Paul 
110665823d0SBill Paul static void usage()
111665823d0SBill Paul {
112665823d0SBill Paul 	if (_rpcpmstart) {
113665823d0SBill Paul 		ypxfr_exit(YPXFR_BADARGS,NULL);
114665823d0SBill Paul 	} else {
115665823d0SBill Paul 		fprintf(stderr,"usage: %s [-f] [-c] [-d target domain] \
116665823d0SBill Paul [-h source host] [-s source domain]\n", progname);
117665823d0SBill Paul 		fprintf(stderr,"\t     [-p path] [-C taskid program-number \
118665823d0SBill Paul ipaddr port] mapname\n");
119665823d0SBill Paul 		exit(1);
120665823d0SBill Paul 	}
121665823d0SBill Paul }
122665823d0SBill Paul 
123665823d0SBill Paul int ypxfr_foreach(status, key, keylen, val, vallen, data)
124665823d0SBill Paul 	int status;
125665823d0SBill Paul 	char *key;
126665823d0SBill Paul 	int keylen;
127665823d0SBill Paul 	char *val;
128665823d0SBill Paul 	int vallen;
129665823d0SBill Paul 	char *data;
130665823d0SBill Paul {
131665823d0SBill Paul 	DBT dbkey, dbval;
132665823d0SBill Paul 
133665823d0SBill Paul 	if (status != YP_TRUE)
134665823d0SBill Paul 		return (status);
135665823d0SBill Paul 
136665823d0SBill Paul 	dbkey.data = key;
137665823d0SBill Paul 	dbkey.size = keylen;
138665823d0SBill Paul 	dbval.data = val;
139665823d0SBill Paul 	dbval.size = vallen;
140665823d0SBill Paul 
14116deb43aSBill Paul 	if (yp_put_record(dbp, &dbkey, &dbval, 0) != YP_TRUE)
142665823d0SBill Paul 		return(yp_errno);
143665823d0SBill Paul 
144665823d0SBill Paul 	return (0);
145665823d0SBill Paul }
146665823d0SBill Paul 
147665823d0SBill Paul main(argc,argv)
148665823d0SBill Paul 	int argc;
149665823d0SBill Paul 	char *argv[];
150665823d0SBill Paul {
151665823d0SBill Paul 	int ch;
152665823d0SBill Paul 	int ypxfr_force = 0;
153665823d0SBill Paul 	char *ypxfr_dest_domain = NULL;
154665823d0SBill Paul 	char *ypxfr_source_host = NULL;
155665823d0SBill Paul 	char *ypxfr_source_domain = NULL;
156665823d0SBill Paul 	char *ypxfr_local_domain = NULL;
157665823d0SBill Paul 	char *ypxfr_master = NULL;
158665823d0SBill Paul 	unsigned long ypxfr_order = -1, ypxfr_skew_check = -1;
159665823d0SBill Paul 	char *ypxfr_mapname = NULL;
160665823d0SBill Paul 	int ypxfr_args = 0;
161665823d0SBill Paul 	char ypxfr_temp_map[MAXPATHLEN + 2];
162665823d0SBill Paul 	char tempmap[MAXPATHLEN + 2];
163665823d0SBill Paul 	char buf[MAXPATHLEN + 2];
164665823d0SBill Paul 	DBT key, data;
1652c33b20aSBill Paul 	int remoteport;
16681a82d4dSBill Paul 	int interdom = 0;
16781a82d4dSBill Paul 	int secure = 0;
168665823d0SBill Paul 
169665823d0SBill Paul 	debug = 1;
170665823d0SBill Paul 
171665823d0SBill Paul 	if (!isatty(fileno(stderr))) {
172665823d0SBill Paul 		openlog(progname, LOG_PID, LOG_DAEMON);
173665823d0SBill Paul 		_rpcpmstart = 1;
174665823d0SBill Paul 	}
175665823d0SBill Paul 
176665823d0SBill Paul 	if (argc < 2)
177665823d0SBill Paul 		usage();
178665823d0SBill Paul 
179665823d0SBill Paul 	while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != EOF) {
180665823d0SBill Paul 		int my_optind;
181665823d0SBill Paul 		switch(ch) {
182665823d0SBill Paul 		case 'f':
183665823d0SBill Paul 			ypxfr_force++;
184665823d0SBill Paul 			ypxfr_args++;
185665823d0SBill Paul 			break;
186665823d0SBill Paul 		case 'c':
187665823d0SBill Paul 			ypxfr_clear = 0;
188665823d0SBill Paul 			ypxfr_args++;
189665823d0SBill Paul 			break;
190665823d0SBill Paul 		case 'd':
191665823d0SBill Paul 			ypxfr_dest_domain = optarg;
192665823d0SBill Paul 			ypxfr_args += 2;
193665823d0SBill Paul 			break;
194665823d0SBill Paul 		case 'h':
195665823d0SBill Paul 			ypxfr_source_host = optarg;
196665823d0SBill Paul 			ypxfr_args += 2;
197665823d0SBill Paul 			break;
198665823d0SBill Paul 		case 's':
199665823d0SBill Paul 			ypxfr_source_domain = optarg;
200665823d0SBill Paul 			ypxfr_args += 2;
201665823d0SBill Paul 			break;
202665823d0SBill Paul 		case 'p':
203665823d0SBill Paul 			yp_dir = optarg;
204665823d0SBill Paul 			ypxfr_args += 2;
205665823d0SBill Paul 			break;
206665823d0SBill Paul 		case 'C':
207665823d0SBill Paul 			/*
208665823d0SBill Paul 			 * Whoever decided that the -C flag should take
209665823d0SBill Paul 			 * four arguments is a twit.
210665823d0SBill Paul 			 */
211665823d0SBill Paul 			my_optind = optind - 1;
212665823d0SBill Paul 			if (argv[my_optind] == NULL || !strlen(argv[my_optind])) {
213665823d0SBill Paul 				yp_error("transaction ID not specified");
214665823d0SBill Paul 				usage();
215665823d0SBill Paul 			}
216665823d0SBill Paul 			ypxfr_resp.transid = atol(argv[my_optind]);
217665823d0SBill Paul 			my_optind++;
218665823d0SBill Paul 			if (argv[my_optind] == NULL || !strlen(argv[my_optind])) {
219665823d0SBill Paul 				yp_error("RPC program number not specified");
220665823d0SBill Paul 				usage();
221665823d0SBill Paul 			}
222665823d0SBill Paul 			ypxfr_prognum = atol(argv[my_optind]);
223665823d0SBill Paul 			my_optind++;
224665823d0SBill Paul 			if (argv[my_optind] == NULL || !strlen(argv[my_optind])) {
225665823d0SBill Paul 				yp_error("address not specified");
226665823d0SBill Paul 				usage();
227665823d0SBill Paul 			}
228665823d0SBill Paul 			if (!inet_aton(argv[my_optind], &ypxfr_callback_addr.sin_addr)) {
229665823d0SBill Paul 				yp_error("failed to convert '%s' to IP addr",
230665823d0SBill Paul 					argv[my_optind]);
231665823d0SBill Paul 				exit(1);
232665823d0SBill Paul 			}
233665823d0SBill Paul 			my_optind++;
234665823d0SBill Paul 			if (argv[my_optind] == NULL || !strlen(argv[my_optind])) {
235665823d0SBill Paul 				yp_error("port not specified");
236665823d0SBill Paul 				usage();
237665823d0SBill Paul 			}
238665823d0SBill Paul 			ypxfr_callback_addr.sin_port = htons((u_short)atoi(argv[my_optind]));
239665823d0SBill Paul 			ypxfr_args += 5;
240665823d0SBill Paul 			break;
241665823d0SBill Paul 		default:
242665823d0SBill Paul 			usage();
243665823d0SBill Paul 			break;
244665823d0SBill Paul 		}
245665823d0SBill Paul 	}
246665823d0SBill Paul 
247665823d0SBill Paul 	ypxfr_mapname = argv[ypxfr_args + 1];
248665823d0SBill Paul 
249665823d0SBill Paul 	if (ypxfr_mapname == NULL) {
250665823d0SBill Paul 		yp_error("no map name specified");
251665823d0SBill Paul 		usage();
252665823d0SBill Paul 	}
253665823d0SBill Paul 
254665823d0SBill Paul 	/* Always the case. */
255665823d0SBill Paul 	ypxfr_callback_addr.sin_family = AF_INET;
256665823d0SBill Paul 
257665823d0SBill Paul 	/* Determine if local NIS client facilities are turned on. */
258665823d0SBill Paul 	if (!yp_get_default_domain(&ypxfr_local_domain) &&
259665823d0SBill Paul 	    _yp_check(&ypxfr_local_domain))
260665823d0SBill Paul 		ypxfr_use_yplib = 1;
261665823d0SBill Paul 
262665823d0SBill Paul 	/*
263665823d0SBill Paul 	 * If no destination domain is specified, assume that the
264665823d0SBill Paul 	 * local default domain is to be used and try to obtain it.
265665823d0SBill Paul 	 * Fails if NIS client facilities are turned off.
266665823d0SBill Paul 	 */
267665823d0SBill Paul 	if (ypxfr_dest_domain == NULL) {
268665823d0SBill Paul 		if (ypxfr_use_yplib) {
269665823d0SBill Paul 			yp_get_default_domain(&ypxfr_dest_domain);
270665823d0SBill Paul 		} else {
271665823d0SBill Paul 			yp_error("no destination domain specified and \
272665823d0SBill Paul the local domain name isn't set");
273665823d0SBill Paul 			ypxfr_exit(YPXFR_BADARGS,NULL);
274665823d0SBill Paul 		}
275665823d0SBill Paul 	}
276665823d0SBill Paul 
277665823d0SBill Paul 	/*
278665823d0SBill Paul 	 * If a source domain is not specified, assume it to
279665823d0SBill Paul 	 * be the same as the destination domain.
280665823d0SBill Paul 	 */
281665823d0SBill Paul 	if (ypxfr_source_domain == NULL) {
282665823d0SBill Paul 		ypxfr_source_domain = ypxfr_dest_domain;
283665823d0SBill Paul 	}
284665823d0SBill Paul 
285665823d0SBill Paul 	/*
286665823d0SBill Paul 	 * If the source host is not specified, assume it to be the
287665823d0SBill Paul 	 * master for the specified map. If local NIS client facilities
288665823d0SBill Paul 	 * are turned on, we can figure this out using yp_master().
289665823d0SBill Paul 	 * If not, we have to see if a local copy of the map exists
290665823d0SBill Paul 	 * and extract its YP_MASTER_NAME record. If _that_ fails,
291665823d0SBill Paul 	 * we are stuck and must ask the user for more information.
292665823d0SBill Paul 	 */
293665823d0SBill Paul 	if (ypxfr_source_host == NULL) {
294665823d0SBill Paul 		if (!ypxfr_use_yplib) {
295665823d0SBill Paul 		/*
296665823d0SBill Paul 		 * Double whammy: NIS isn't turned on and the user
297665823d0SBill Paul 		 * didn't specify a source host.
298665823d0SBill Paul 		 */
299665823d0SBill Paul 			char *dptr;
300665823d0SBill Paul 			key.data = "YP_MASTER_NAME";
301665823d0SBill Paul 			key.size = sizeof("YP_MASTER_NAME") - 1;
302665823d0SBill Paul 
303665823d0SBill Paul 			if (yp_get_record(ypxfr_dest_domain, ypxfr_mapname,
304665823d0SBill Paul 					 &key, &data, 1) != YP_TRUE) {
305665823d0SBill Paul 				yp_error("no source host specified");
306665823d0SBill Paul 				ypxfr_exit(YPXFR_BADARGS,NULL);
307665823d0SBill Paul 			}
308665823d0SBill Paul 			dptr = data.data;
309665823d0SBill Paul 			dptr[data.size] = '\0';
310665823d0SBill Paul 			ypxfr_master = ypxfr_source_host = strdup(dptr);
311665823d0SBill Paul 		}
312665823d0SBill Paul 	} else {
313665823d0SBill Paul 		if (ypxfr_use_yplib)
314665823d0SBill Paul 			ypxfr_use_yplib = 0;
315665823d0SBill Paul 	}
316665823d0SBill Paul 
317665823d0SBill Paul 	if (ypxfr_master == NULL) {
318665823d0SBill Paul 		if ((ypxfr_master = ypxfr_get_master(ypxfr_source_domain,
319665823d0SBill Paul 					    	 ypxfr_mapname,
320665823d0SBill Paul 					     	ypxfr_source_host,
321665823d0SBill Paul 					     	ypxfr_use_yplib)) == NULL) {
322d6cab902SBill Paul 			yp_error("failed to find master of %s in domain %s: %s",
323d6cab902SBill Paul 				  ypxfr_mapname, ypxfr_source_domain,
324d6cab902SBill Paul 				  ypxfrerr_string(yp_errno));
325665823d0SBill Paul 			ypxfr_exit(YPXFR_MADDR,NULL);
326665823d0SBill Paul 		}
327665823d0SBill Paul 	}
328665823d0SBill Paul 
329665823d0SBill Paul 	/*
330665823d0SBill Paul 	 * If we got here and ypxfr_source_host is still undefined,
331665823d0SBill Paul 	 * it means we had to resort to using yp_master() to find the
332665823d0SBill Paul 	 * master server for the map. The source host and master should
333665823d0SBill Paul 	 * be identical.
334665823d0SBill Paul 	 */
335665823d0SBill Paul 	if (ypxfr_source_host == NULL)
336665823d0SBill Paul 		ypxfr_source_host = ypxfr_master;
337665823d0SBill Paul 
3382c33b20aSBill Paul 	/*
3392c33b20aSBill Paul 	 * Don't talk to ypservs on unprivileged ports.
3402c33b20aSBill Paul 	 */
3412c33b20aSBill Paul 	remoteport = getrpcport(ypxfr_source_host, YPPROG, YPVERS, IPPROTO_UDP);
3422c33b20aSBill Paul 	if (remoteport >= IPPORT_RESERVED) {
3432c33b20aSBill Paul 		yp_error("ypserv on %s not running on reserved port",
3442c33b20aSBill Paul 						ypxfr_source_host);
3452c33b20aSBill Paul 		ypxfr_exit(YPXFR_REFUSED, NULL);
3462c33b20aSBill Paul 	}
3472c33b20aSBill Paul 
348665823d0SBill Paul 	if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain,
349665823d0SBill Paul 					     ypxfr_mapname,
350665823d0SBill Paul 					     ypxfr_master, 0)) == 0) {
351d6cab902SBill Paul 		yp_error("failed to get order number of %s: %s",
35234a042e8SBill Paul 				ypxfr_mapname, yp_errno == YPXFR_SUCC ?
35334a042e8SBill Paul 				"map has order 0" : ypxfrerr_string(yp_errno));
354665823d0SBill Paul 		ypxfr_exit(YPXFR_YPERR,NULL);
355665823d0SBill Paul 	}
356665823d0SBill Paul 
35781a82d4dSBill Paul 	if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname,
35881a82d4dSBill Paul 			"YP_INTERDOMAIN", sizeof("YP_INTERDOMAIN") - 1))
35981a82d4dSBill Paul 		interdom++;
36081a82d4dSBill Paul 
36181a82d4dSBill Paul 	if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname,
36281a82d4dSBill Paul 			"YP_SECURE", sizeof("YP_SECURE") - 1))
36381a82d4dSBill Paul 		secure++;
36481a82d4dSBill Paul 
365665823d0SBill Paul 	key.data = "YP_LAST_MODIFIED";
366665823d0SBill Paul 	key.size = sizeof("YP_LAST_MODIFIED") - 1;
367665823d0SBill Paul 
368665823d0SBill Paul 	/* The order number is immaterial when the 'force' flag is set. */
369665823d0SBill Paul 
370665823d0SBill Paul 	if (!ypxfr_force) {
371665823d0SBill Paul 		int ignore = 0;
372665823d0SBill Paul 		if (yp_get_record(ypxfr_dest_domain,ypxfr_mapname,&key,&data,1) != YP_TRUE) {
373665823d0SBill Paul 			switch(yp_errno) {
374665823d0SBill Paul 			case YP_NOKEY:
375665823d0SBill Paul 				ypxfr_exit(YPXFR_FORCE,NULL);
376665823d0SBill Paul 				break;
377665823d0SBill Paul 			case YP_NOMAP:
378665823d0SBill Paul 				/*
379665823d0SBill Paul 				 * If the map doesn't exist, we're
380665823d0SBill Paul 				 * creating it. Ignore the error.
381665823d0SBill Paul 				 */
382665823d0SBill Paul 				ignore++;
383665823d0SBill Paul 				break;
384665823d0SBill Paul 			case YP_BADDB:
385665823d0SBill Paul 			default:
386665823d0SBill Paul 				ypxfr_exit(YPXFR_DBM,NULL);
387665823d0SBill Paul 				break;
388665823d0SBill Paul 			}
389665823d0SBill Paul 		}
390665823d0SBill Paul 		if (!ignore && ypxfr_order <= atoi(data.data))
391665823d0SBill Paul 			ypxfr_exit(YPXFR_AGE, NULL);
392665823d0SBill Paul 
393665823d0SBill Paul 	}
394665823d0SBill Paul 
395665823d0SBill Paul 	/* Construct a temporary map file name */
396665823d0SBill Paul 	snprintf(tempmap, sizeof(tempmap), "%s.%d",ypxfr_mapname, getpid());
397665823d0SBill Paul 	snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir,
398665823d0SBill Paul 		 ypxfr_dest_domain, tempmap);
399665823d0SBill Paul 
4002c33b20aSBill Paul 	if ((remoteport = getrpcport(ypxfr_source_host, YPXFRD_FREEBSD_PROG,
4012c33b20aSBill Paul 					YPXFRD_FREEBSD_VERS, IPPROTO_TCP))) {
4022c33b20aSBill Paul 
4032c33b20aSBill Paul 		/* Don't talk to rpc.ypxfrds on unprovileged ports. */
4042c33b20aSBill Paul 		if (remoteport >= IPPORT_RESERVED) {
4052c33b20aSBill Paul 			yp_error("rpc.ypxfrd on %s not using privileged port",
4062c33b20aSBill Paul 							ypxfr_source_host);
4072c33b20aSBill Paul 			ypxfr_exit(YPXFR_REFUSED, NULL);
4082c33b20aSBill Paul 		}
4092c33b20aSBill Paul 
41016deb43aSBill Paul 		/* Try to send using ypxfrd. If it fails, use old method. */
4112c33b20aSBill Paul 		if (!ypxfrd_get_map(ypxfr_source_host, ypxfr_mapname,
41216deb43aSBill Paul 					ypxfr_source_domain, ypxfr_temp_map))
41316deb43aSBill Paul 			goto leave;
41416deb43aSBill Paul 	}
41516deb43aSBill Paul 
416665823d0SBill Paul 	/* Open the temporary map read/write. */
41716deb43aSBill Paul 	if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap, 0)) == NULL) {
418665823d0SBill Paul 		yp_error("failed to open temporary map file");
419665823d0SBill Paul 		ypxfr_exit(YPXFR_DBM,NULL);
420665823d0SBill Paul 	}
421665823d0SBill Paul 
422665823d0SBill Paul 	/*
423665823d0SBill Paul 	 * Fill in the keys we already know, such as the order number,
424665823d0SBill Paul 	 * master name, input file name (we actually make up a bogus
425665823d0SBill Paul 	 * name for that) and output file name.
426665823d0SBill Paul 	 */
427665823d0SBill Paul 	snprintf(buf, sizeof(buf), "%d", ypxfr_order);
428665823d0SBill Paul 	data.data = buf;
429665823d0SBill Paul 	data.size = strlen(buf);
430665823d0SBill Paul 
43116deb43aSBill Paul 	if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
432665823d0SBill Paul 		yp_error("failed to write order number to database");
433665823d0SBill Paul 		ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
434665823d0SBill Paul 	}
435665823d0SBill Paul 
436665823d0SBill Paul 	key.data = "YP_MASTER_NAME";
437665823d0SBill Paul 	key.size = sizeof("YP_MASTER_NAME") - 1;
438665823d0SBill Paul 	data.data = ypxfr_master;
439665823d0SBill Paul 	data.size = strlen(ypxfr_master);
440665823d0SBill Paul 
44116deb43aSBill Paul 	if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
442665823d0SBill Paul 		yp_error("failed to write master name to database");
443665823d0SBill Paul 		ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
444665823d0SBill Paul 	}
445665823d0SBill Paul 
446665823d0SBill Paul 	key.data = "YP_DOMAIN_NAME";
447665823d0SBill Paul 	key.size = sizeof("YP_DOMAIN_NAME") - 1;
448665823d0SBill Paul 	data.data = ypxfr_dest_domain;
449665823d0SBill Paul 	data.size = strlen(ypxfr_dest_domain);
450665823d0SBill Paul 
45116deb43aSBill Paul 	if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
452665823d0SBill Paul 		yp_error("failed to write domain name to database");
453665823d0SBill Paul 		ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
454665823d0SBill Paul 	}
455665823d0SBill Paul 
456665823d0SBill Paul 	snprintf (buf, sizeof(buf), "%s:%s", ypxfr_source_host, ypxfr_mapname);
457665823d0SBill Paul 
458665823d0SBill Paul 	key.data = "YP_INPUT_NAME";
459665823d0SBill Paul 	key.size = sizeof("YP_INPUT_NAME") - 1;
460665823d0SBill Paul 	data.data = &buf;
461665823d0SBill Paul 	data.size = strlen(buf);
462665823d0SBill Paul 
46316deb43aSBill Paul 	if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
464665823d0SBill Paul 		yp_error("failed to write input name to database");
465665823d0SBill Paul 		ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
466665823d0SBill Paul 
467665823d0SBill Paul 	}
468665823d0SBill Paul 
469665823d0SBill Paul 	snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain,
470665823d0SBill Paul 							ypxfr_mapname);
471665823d0SBill Paul 
472665823d0SBill Paul 	key.data = "YP_OUTPUT_NAME";
473665823d0SBill Paul 	key.size = sizeof("YP_OUTPUT_NAME") - 1;
474665823d0SBill Paul 	data.data = &buf;
475665823d0SBill Paul 	data.size = strlen(buf);
476665823d0SBill Paul 
47716deb43aSBill Paul 	if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
478665823d0SBill Paul 		yp_error("failed to write output name to database");
479665823d0SBill Paul 		ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
480665823d0SBill Paul 	}
481665823d0SBill Paul 
48281a82d4dSBill Paul 	if (interdom) {
48381a82d4dSBill Paul 		key.data = "YP_INTERDOMAIN";
48481a82d4dSBill Paul 		key.size = sizeof("YP_INTERDOMAIN") - 1;
48581a82d4dSBill Paul 		data.data = "";
48681a82d4dSBill Paul 		data.size = 0;
48781a82d4dSBill Paul 
48881a82d4dSBill Paul 		if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
48981a82d4dSBill Paul 			yp_error("failed to add interdomain flag to database");
49081a82d4dSBill Paul 			ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
49181a82d4dSBill Paul 		}
49281a82d4dSBill Paul 	}
49381a82d4dSBill Paul 
49481a82d4dSBill Paul 	if (secure) {
49581a82d4dSBill Paul 		key.data = "YP_SECURE";
49681a82d4dSBill Paul 		key.size = sizeof("YP_SECURE") - 1;
49781a82d4dSBill Paul 		data.data = "";
49881a82d4dSBill Paul 		data.size = 0;
49981a82d4dSBill Paul 
50081a82d4dSBill Paul 		if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) {
50181a82d4dSBill Paul 			yp_error("failed to add secure flag to database");
50281a82d4dSBill Paul 			ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map);
50381a82d4dSBill Paul 		}
50481a82d4dSBill Paul 	}
50581a82d4dSBill Paul 
506665823d0SBill Paul 	/* Now suck over the contents of the map from the master. */
507665823d0SBill Paul 
508665823d0SBill Paul 	if (ypxfr_get_map(ypxfr_mapname,ypxfr_source_domain,
509665823d0SBill Paul 			  ypxfr_source_host, ypxfr_foreach)){
510665823d0SBill Paul 		yp_error("failed to retrieve map from source host");
511665823d0SBill Paul 		ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map);
512665823d0SBill Paul 	}
513665823d0SBill Paul 
514665823d0SBill Paul 	(void)(dbp->close)(dbp);
515d6cab902SBill Paul 	dbp = NULL; /* <- yes, it seems this is necessary. */
516665823d0SBill Paul 
51716deb43aSBill Paul leave:
51816deb43aSBill Paul 
51916deb43aSBill Paul 	snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain,
52016deb43aSBill Paul 							ypxfr_mapname);
52116deb43aSBill Paul 
522665823d0SBill Paul 	/* Peek at the order number again and check for skew. */
523665823d0SBill Paul 	if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain,
524665823d0SBill Paul 					     ypxfr_mapname,
525665823d0SBill Paul 					     ypxfr_master, 0)) == 0) {
526d6cab902SBill Paul 		yp_error("failed to get order number of %s: %s",
52734a042e8SBill Paul 				ypxfr_mapname, yp_errno == YPXFR_SUCC ?
52834a042e8SBill Paul 				"map has order 0" : ypxfrerr_string(yp_errno));
529665823d0SBill Paul 		ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map);
530665823d0SBill Paul 	}
531665823d0SBill Paul 
532665823d0SBill Paul 	if (ypxfr_order != ypxfr_skew_check)
533665823d0SBill Paul 		ypxfr_exit(YPXFR_SKEW,&ypxfr_temp_map);
534665823d0SBill Paul 
535665823d0SBill Paul 	/*
536665823d0SBill Paul 	 * Send a YPPROC_CLEAR to the local ypserv.
537665823d0SBill Paul 	 */
53834a042e8SBill Paul 	if (ypxfr_clear) {
539665823d0SBill Paul 		char in = 0;
540665823d0SBill Paul 		char *out = NULL;
54134a042e8SBill Paul 		int stat;
54234a042e8SBill Paul 		if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR,
54334a042e8SBill Paul 			xdr_void, (void *)&in,
54434a042e8SBill Paul 			xdr_void, (void *)out)) != RPC_SUCCESS) {
54534a042e8SBill Paul 			yp_error("failed to send 'clear' to local ypserv: %s",
54634a042e8SBill Paul 				 clnt_sperrno((enum clnt_stat) stat));
54734a042e8SBill Paul 			ypxfr_exit(YPXFR_CLEAR, &ypxfr_temp_map);
548665823d0SBill Paul 		}
549665823d0SBill Paul 	}
550665823d0SBill Paul 
55134a042e8SBill Paul 	/*
55234a042e8SBill Paul 	 * Put the new map in place immediately. I'm not sure if the
55334a042e8SBill Paul 	 * kernel does an unlink() and rename() atomically in the event
55434a042e8SBill Paul 	 * that we move a new copy of a map over the top of an existing
55534a042e8SBill Paul 	 * one, but there's less chance of a race condition happening
55634a042e8SBill Paul 	 * than if we were to do the unlink() ourselves.
55734a042e8SBill Paul 	 */
558665823d0SBill Paul 	if (rename(ypxfr_temp_map, buf) == -1) {
559665823d0SBill Paul 		yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf,
560665823d0SBill Paul 							strerror(errno));
561665823d0SBill Paul 		ypxfr_exit(YPXFR_FILE,NULL);
562665823d0SBill Paul 	}
563665823d0SBill Paul 
564665823d0SBill Paul 	ypxfr_exit(YPXFR_SUCC,NULL);
565665823d0SBill Paul 
566665823d0SBill Paul 	return(1);
567665823d0SBill Paul }
568