9804 hal-set-property should support --direct option
[unleashed.git] / usr / src / cmd / ypcmd / ypxfr.c
blobe8fb1652972b80c8708d63c65c8ed55cba7dc7e8
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * Portions of this source code were derived from Berkeley
32 * under license from the Regents of the University of
33 * California.
37 * This is a user command which gets a NIS data base from some running
38 * server, and gets it to the local site by using the normal NIS client
39 * enumeration functions. The map is copied to a temp name, then the real
40 * map is removed and the temp map is moved to the real name. ypxfr then
41 * sends a "YPPROC_CLEAR" message to the local server to insure that it will
42 * not hold a removed map open, so serving an obsolete version.
44 * ypxfr [ -h <host> ] [ -d <domainname> ]
45 * [ -s <domainname> ] [-f] [-c] [-C tid prot name] map
47 * If the host is ommitted, ypxfr will attempt to discover the master by
48 * using normal NIS services. If it can't get the record, it will use
49 * the address of the callback, if specified. If the host is specified
50 * as an internet address, no NIS services need to be locally available.
52 * If the domain is not specified, the default domain of the local machine
53 * is used.
55 * If the -f flag is used, the transfer will be done even if the master's
56 * copy is not newer than the local copy.
58 * The -c flag suppresses the YPPROC_CLEAR request to the local ypserv. It
59 * may be used if ypserv isn't currently running to suppress the error message.
61 * The -C flag is used to pass callback information to ypxfr when it is
62 * activated by ypserv. The callback information is used to send a
63 * yppushresp_xfr message with transaction id "tid" to a yppush process
64 * speaking a transient protocol number "prot". The yppush program is
65 * running on the host "name".
67 * The -s option is used to specify a source domain which may be
68 * different from the destination domain, for transfer of maps
69 * that are identical in different domains (e.g. services.byname)
73 #include <ndbm.h>
74 #define DATUM
76 #include <stdio.h>
77 #include <errno.h>
78 #include <time.h>
79 #include <ctype.h>
80 #include <netdb.h>
81 #include <netconfig.h>
82 #include <netdir.h>
83 #include <rpc/rpc.h>
84 #include <sys/file.h>
85 #include <sys/stat.h>
86 #include <dirent.h>
87 #include <rpcsvc/ypclnt.h>
88 #include <rpcsvc/yp_prot.h>
89 #include <unistd.h>
90 #include <stdlib.h>
91 #include <rpcsvc/nis.h>
92 #include "ypdefs.h"
93 #include "yp_b.h"
94 #include "shim.h"
95 #include "yptol.h"
97 USE_YP_MASTER_NAME
98 USE_YP_SECURE
99 USE_YP_INTERDOMAIN
100 USE_YP_LAST_MODIFIED
101 USE_YPDBPATH
102 USE_DBM
104 #define PARANOID 1 /* make sure maps have the right # entries */
106 #define CALLINTER_TRY 10 /* Seconds between callback tries */
107 #define CALLTIMEOUT CALLINTER_TRY*6 /* Total timeout for callback */
109 DBM *db;
111 /* ypxfr never uses N2L mode */
112 bool_t yptol_mode = FALSE;
114 int debug = FALSE;
115 int treepush = FALSE;
116 #define TREEPUSH 1
117 int defwrite = TRUE;
119 char *domain = NULL;
120 char *source = NULL;
121 char *map = NULL;
122 char *master = NULL;
123 char *pushhost = NULL;
125 * The name of the xfer peer as specified as a
126 * -h option, -C name option or from querying the NIS
128 struct dom_binding master_server; /* To talk to above */
129 unsigned int master_prog_vers; /* YPVERS (barfs at YPOLDVERS !) */
130 char *master_name = NULL; /* Map's master as contained in the map */
131 unsigned *master_version = NULL; /* Order number as contained in the map */
132 char *master_ascii_version; /* ASCII order number as contained in the map */
133 bool fake_master_version = FALSE;
135 * TRUE only if there's no order number in
136 * the map, and the user specified -f
138 bool force = FALSE; /* TRUE iff user specified -f flag */
139 bool logging = FALSE; /* TRUE iff no tty, but log file exists */
140 bool check_count = FALSE; /* TRUE causes counts to be checked */
141 bool send_clear = TRUE; /* FALSE iff user specified -c flag */
142 bool callback = FALSE;
144 * TRUE iff -C flag set. tid, proto and name
145 * will be set to point to the command line args.
147 bool secure_map = FALSE; /* TRUE if there is yp_secure in the map */
148 bool interdomain_map = FALSE;
150 * TRUE if there is yp_interdomain in either
151 * the local or the master version of the map
153 int interdomain_sz = 0; /* Size of the interdomain value */
154 #define UDPINTER_TRY 10 /* Seconds between tries for udp */
155 #define UDPTIMEOUT UDPINTER_TRY*4 /* Total timeout for udp */
156 #define CALLINTER_TRY 10 /* Seconds between callback tries */
157 #define CALLTIMEOUT CALLINTER_TRY*6 /* Total timeout for callback */
158 struct timeval udp_timeout = { UDPTIMEOUT, 0};
159 struct timeval tcp_timeout = { 180, 0}; /* Timeout for map enumeration */
161 char *interdomain_value; /* place to store the interdomain value */
162 char *tid;
163 char *proto;
164 int entry_count; /* counts entries in the map */
165 char logfile[] = "/var/yp/ypxfr.log";
166 static char err_usage[] =
167 "Usage:\n\
168 ypxfr [-f] [ -h host ] [ -d domainname ]\n\
169 [ -s domainname ] [-c] [-C tid prot servname ] map\n\n\
170 where\n\
171 -f forces transfer even if the master's copy is not newer.\n\
172 host is the server from where the map should be transfered\n\
173 -d domainname is specified if other than the default domain\n\
174 -s domainname is a source for the map that is same across domains\n\
175 -c inhibits sending a \"Clear map\" message to the local ypserv.\n\
176 -C is for use only by ypserv to pass callback information.\n";
177 char err_bad_args[] =
178 "%s argument is bad.\n";
179 char err_cant_get_kname[] =
180 "Can't get %s back from system call.\n";
181 char err_null_kname[] =
182 "%s hasn't been set on this machine.\n";
183 char err_bad_hostname[] = "hostname";
184 char err_bad_mapname[] = "mapname";
185 char err_bad_domainname[] = "domainname";
186 char err_udp_failure[] =
187 "Can't set up a udp connection to ypserv on host %s.\n";
188 char yptempname_prefix[] = "ypxfr_map.";
189 char ypbkupname_prefix[] = "ypxfr_bkup.";
191 void get_command_line_args();
192 bool bind_to_server();
193 bool ping_server();
194 bool get_private_recs();
195 bool get_order();
196 bool get_v1order();
197 bool get_v2order();
198 bool get_misc_recs();
199 bool get_master_name();
200 bool get_v1master_name();
201 bool get_v2master_name();
202 void find_map_master();
203 bool move_map();
204 unsigned get_local_version();
205 void mkfilename();
206 void mk_tmpname();
207 bool get_map();
208 bool add_private_entries();
209 bool new_mapfiles();
210 void del_mapfiles();
211 void set_output();
212 void logprintf();
213 bool send_ypclear();
214 void xfr_exit();
215 void send_callback();
216 int ypall_callback();
217 int map_yperr_to_pusherr();
218 extern CLIENT *__yp_clnt_create_rsvdport();
220 bool_t is_yptol_mode();
222 extern int errno;
226 * This is the mainline for the ypxfr process.
230 main(argc, argv)
231 int argc;
232 char **argv;
236 static char default_domain_name[YPMAXDOMAIN];
237 static unsigned big = 0xffffffff;
238 int status;
240 set_output();
243 * Inter-process lock synchronization structure. Since slave servers
244 * get their maps from another NIS server rather than LDAP they can
245 * never run in N2L mode. We thus do not have to init the update
246 * locking mechanism.
248 if (init_lock_map() == FALSE) {
249 exit(1);
252 get_command_line_args(argc, argv);
254 if (!domain) {
256 if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
257 domain = default_domain_name;
258 } else {
259 logprintf(err_cant_get_kname,
260 err_bad_domainname);
261 xfr_exit(YPPUSH_RSRC);
264 if (strlen(domain) == 0) {
265 logprintf(err_null_kname,
266 err_bad_domainname);
267 xfr_exit(YPPUSH_RSRC);
270 if (!source)
271 source = domain;
273 if (!master) {
274 find_map_master();
277 * if we were unable to get the master name, either from
278 * the -h option or from -C "name" option or from NIS,
279 * we are doomed !
281 if (!master) {
282 xfr_exit(YPPUSH_MADDR);
285 if (!bind_to_server(master, &master_server,
286 &master_prog_vers, &status)) {
287 xfr_exit(status);
290 if (!get_private_recs(&status)) {
291 xfr_exit(status);
294 if (!master_version) {
296 if (force) {
297 master_version = &big;
298 fake_master_version = TRUE;
299 } else {
300 logprintf(
301 "Can't get order number for map %s from server at %s: use the -f flag.\n",
302 map, master);
303 xfr_exit(YPPUSH_FORCE);
307 if (!move_map(&status)) {
308 xfr_exit(status);
311 if (send_clear && !send_ypclear(&status)) {
312 xfr_exit(status);
315 if (logging) {
316 logprintf("Transferred map %s from %s (%d entries).\n",
317 map, master, entry_count);
320 xfr_exit(YPPUSH_SUCC);
321 return (0);
322 /* NOTREACHED */
326 * This decides whether we're being run interactively or not, and, if not,
327 * whether we're supposed to be logging or not. If we are logging, it sets
328 * up stderr to point to the log file, and sets the "logging"
329 * variable. If there's no logging, the output goes in the bit bucket.
330 * Logging output differs from interactive output in the presence of a
331 * timestamp, present only in the log file. stderr is reset, too, because it
332 * it's used by various library functions, including clnt_perror.
334 void
335 set_output()
337 if (!isatty(1)) {
338 if (access(logfile, W_OK)) {
339 (void) freopen("/dev/null", "w", stderr);
340 } else {
341 (void) freopen(logfile, "a", stderr);
342 logging = TRUE;
347 * This constructs a logging record.
349 void
350 logprintf(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
351 /*VARARGS*/
353 struct timeval t;
355 fseek(stderr, 0, 2);
356 if (logging) {
357 (void) gettimeofday(&t, NULL);
358 (void) fprintf(stderr, "%19.19s: ", ctime(&t.tv_sec));
360 (void) fprintf(stderr, (char *)arg1, arg2, arg3, arg4, arg5,
361 arg6, arg7);
362 fflush(stderr);
366 * This does the command line argument processing.
368 void
369 get_command_line_args(argc, argv)
370 int argc;
371 char **argv;
374 argv++;
376 if (argc < 2) {
377 logprintf(err_usage);
378 xfr_exit(YPPUSH_BADARGS);
381 while (--argc) {
383 if ((*argv)[0] == '-') {
385 switch ((*argv)[1]) {
387 case 'f': {
388 force = TRUE;
389 argv++;
390 break;
393 case 'D': {
394 debug = TRUE;
395 argv++;
396 break;
399 case 'T': {
400 treepush = TRUE;
401 argv++;
402 break;
404 case 'P': {
405 check_count = TRUE;
406 argv++;
407 break;
409 case 'W': {
410 defwrite = FALSE;
411 argv++;
412 break;
414 case 'c': {
415 send_clear = FALSE;
416 argv++;
417 break;
420 case 'h': {
422 if (argc > 1) {
423 argv++;
424 argc--;
425 master = *argv;
426 argv++;
428 if (strlen(master) > 256) {
429 logprintf(
430 err_bad_args,
431 err_bad_hostname);
432 xfr_exit(YPPUSH_BADARGS);
435 } else {
436 logprintf(err_usage);
437 xfr_exit(YPPUSH_BADARGS);
440 break;
443 case 'd':
444 if (argc > 1) {
445 argv++;
446 argc--;
447 domain = *argv;
448 argv++;
450 if (strlen(domain) > YPMAXDOMAIN) {
451 logprintf(
452 err_bad_args,
453 err_bad_domainname);
454 xfr_exit(YPPUSH_BADARGS);
457 } else {
458 logprintf(err_usage);
459 xfr_exit(YPPUSH_BADARGS);
461 break;
463 case 's':
464 if (argc > 1) {
465 argv++;
466 argc--;
467 source = *argv;
468 argv++;
470 if (strlen(source) > YPMAXDOMAIN) {
471 logprintf(
472 err_bad_args,
473 err_bad_domainname);
474 xfr_exit(YPPUSH_BADARGS);
477 } else {
478 logprintf(err_usage);
479 xfr_exit(YPPUSH_BADARGS);
481 break;
483 case 'C':
484 if (argc > 3) {
485 callback = TRUE;
486 tid = *(++argv);
487 proto = *(++argv);
488 pushhost = *(++argv);
489 if (strlen(pushhost) > 256) {
490 logprintf(err_bad_args, err_bad_hostname);
492 xfr_exit(YPPUSH_BADARGS);
494 argc -= 3;
495 argv++;
496 } else {
497 logprintf(err_usage);
498 xfr_exit(YPPUSH_BADARGS);
500 break;
502 case 'b': {
503 interdomain_map = TRUE;
504 interdomain_value = "";
505 interdomain_sz = 0;
506 argv++;
507 break;
511 default: {
512 logprintf(err_usage);
513 xfr_exit(YPPUSH_BADARGS);
518 } else {
520 if (!map) {
521 map = *argv;
522 argv++;
524 if (strlen(map) > YPMAXMAP) {
525 logprintf(err_bad_args,
526 err_bad_mapname);
527 xfr_exit(YPPUSH_BADARGS);
530 } else {
531 logprintf(err_usage);
532 xfr_exit(YPPUSH_BADARGS);
537 if (!map) {
538 logprintf(err_usage);
539 xfr_exit(YPPUSH_BADARGS);
544 * This tries to get the master name for the named map, from any
545 * server's version, using the vanilla NIS client interface. If we get a
546 * name back, the global "master" gets pointed to it.
548 void
549 find_map_master()
551 int err;
553 if (err = __yp_master_rsvdport(source, map, &master)) {
554 logprintf("Can't get master of %s. Reason: %s.\n", map,
555 yperr_string(err));
558 yp_unbind(source);
561 #ifdef TREEPUSH
563 chk_treepush(name)
564 char *name;
566 char inmap[256];
567 char inkey[256];
568 int inkeylen;
569 char *outval;
570 int outvallen;
571 int err;
572 outval = NULL;
573 inkey[0] = 0;
574 strcpy(inmap, "ypslaves.");
575 strcat(inmap, name);
576 gethostname(inkey, 256);
577 inkeylen = strlen(inkey);
579 err = yp_match(source, inmap, inkey, inkeylen, &outval, &outvallen);
580 yp_unbind(source);
581 return (err);
583 #endif
586 * This sets up a udp connection to speak the correct program and version
587 * to a NIS server. vers is set to YPVERS, doesn't give a damn about
588 * YPOLDVERS.
590 bool
591 bind_to_server(host, pdomb, vers, status)
592 char *host;
593 struct dom_binding *pdomb;
594 unsigned int *vers;
595 int *status;
597 if (ping_server(host, pdomb, YPVERS, status)) {
598 *vers = YPVERS;
599 return (TRUE);
600 } else
601 return (FALSE);
605 * This sets up a UDP channel to a server which is assumed to speak an input
606 * version of YPPROG. The channel is tested by pinging the server. In all
607 * error cases except "Program Version Number Mismatch", the error is
608 * reported, and in all error cases, the client handle is destroyed and the
609 * socket associated with the channel is closed.
611 bool
612 ping_server(host, pdomb, vers, status)
613 char *host;
614 struct dom_binding *pdomb;
615 unsigned int vers;
616 int *status;
618 enum clnt_stat rpc_stat;
620 if ((pdomb->dom_client = __yp_clnt_create_rsvdport(host, YPPROG, vers,
621 0, 0, 0)) != 0) {
624 * if we are on a c2 system, we should only accept data
625 * from a server which is on a reserved port.
628 * NUKE this for 5.0DR.
630 * if (issecure() &&
631 * (pdomb->dom_server_addr.sin_family != AF_INET ||
632 * pdomb->dom_server_addr.sin_port >= IPPORT_RESERVED)) {
633 * clnt_destroy(pdomb->dom_client);
634 * close(pdomb->dom_socket);
635 * (void) logprintf("bind_to_server: \
636 * server is not using a privileged port\n");
637 * *status = YPPUSH_YPERR;
638 * return (FALSE);
642 rpc_stat = clnt_call(pdomb->dom_client, YPBINDPROC_NULL,
643 xdr_void, 0, xdr_void, 0, udp_timeout);
645 if (rpc_stat == RPC_SUCCESS) {
646 return (TRUE);
647 } else {
648 clnt_destroy(pdomb->dom_client);
649 if (rpc_stat != RPC_PROGVERSMISMATCH) {
650 (void) clnt_perror(pdomb->dom_client,
651 "ypxfr: bind_to_server clnt_call error");
654 *status = YPPUSH_RPC;
655 return (FALSE);
657 } else {
658 logprintf("bind_to_server __clnt_create_rsvd error");
659 (void) clnt_pcreateerror("");
660 fflush(stderr);
661 *status = YPPUSH_RPC;
662 return (FALSE);
667 * This gets values for the YP_LAST_MODIFIED and YP_MASTER_NAME keys from the
668 * master server's version of the map. Values are held in static variables
669 * here. In the success cases, global pointer variables are set to point at
670 * the local statics.
672 bool
673 get_private_recs(pushstat)
674 int *pushstat;
676 static char anumber[20];
677 static unsigned number;
678 static char name[YPMAXPEER + 1];
679 int status;
681 status = 0;
683 if (get_order(anumber, &number, &status)) {
684 master_version = &number;
685 master_ascii_version = anumber;
686 if (debug) fprintf(stderr,
687 "ypxfr: Master Version is %s\n", master_ascii_version);
688 } else {
690 if (status != 0) {
691 *pushstat = status;
692 if (debug) fprintf(stderr,
693 "ypxfr: Couldn't get map's master version number, \
694 status was %d\n", status);
695 return (FALSE);
699 if (get_master_name(name, &status)) {
700 master_name = name;
701 if (debug) fprintf(stderr,
702 "ypxfr: Maps master is '%s'\n", master_name);
703 } else {
705 if (status != 0) {
706 *pushstat = status;
707 if (debug) fprintf(stderr,
708 "ypxfr: Couldn't get map's master name, status was %d\n",
709 status);
710 return (FALSE);
712 master_name = master;
715 if (debug)
716 fprintf(stderr,
717 "ypxfr: Getting private records from master.\n");
718 if (get_misc_recs(&status)) {
719 if (debug)
720 fprintf(stderr,
721 "ypxfr: Masters map %s secure and %s an interdomain map.\n",
722 (secure_map) ? "is" : "is not",
723 (interdomain_map) ? "is" : "is not");
724 } else {
725 if (status != 0) {
726 *pushstat = status;
727 if (debug)
728 fprintf(stderr,
729 "ypxfr: Couldn't get state of secure and interdomain flags in map.\n");
730 return (FALSE);
734 return (TRUE);
738 * This gets the map's order number from the master server
740 bool
741 get_order(an, n, pushstat)
742 char *an;
743 unsigned *n;
744 int *pushstat;
746 if (master_prog_vers == YPVERS) {
747 return (get_v2order(an, n, pushstat));
748 } else
749 return (FALSE);
752 bool
753 get_v2order(an, n, pushstat)
754 char *an;
755 unsigned *n;
756 int *pushstat;
758 struct ypreq_nokey req;
759 struct ypresp_order resp;
760 int retval;
762 req.domain = source;
763 req.map = map;
766 * Get the map''s order number, null-terminate it and store it,
767 * and convert it to binary and store it again.
769 retval = FALSE;
771 if ((enum clnt_stat) clnt_call(master_server.dom_client,
772 YPPROC_ORDER, (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
773 (xdrproc_t)xdr_ypresp_order, (char *)&resp,
774 udp_timeout) == RPC_SUCCESS) {
776 if (resp.status == YP_TRUE) {
777 sprintf(an, "%d", resp.ordernum);
778 *n = resp.ordernum;
779 retval = TRUE;
780 } else if (resp.status != YP_BADDB) {
781 *pushstat = ypprot_err(resp.status);
783 if (!logging) {
784 logprintf(
785 "(info) Can't get order number from ypserv at %s. Reason: %s.\n",
786 master, yperr_string(
787 ypprot_err(resp.status)));
791 CLNT_FREERES(master_server.dom_client,
792 (xdrproc_t)xdr_ypresp_order,
793 (char *)&resp);
794 } else {
795 *pushstat = YPPUSH_RPC;
796 logprintf("ypxfr(get_v2order) RPC call to %s failed", master);
797 clnt_perror(master_server.dom_client, "");
800 return (retval);
804 * Pick up the state of the YP_SECURE and YP_INTERDOMAIN records from the
805 * master. Only works on 4.0 V2 masters that will match a YP_ private key
806 * when asked to explicitly.
808 bool
809 get_misc_recs(pushstat)
810 int *pushstat;
812 struct ypreq_key req;
813 struct ypresp_val resp;
814 int retval;
816 req.domain = source;
817 req.map = map;
818 req.keydat.dptr = yp_secure;
819 req.keydat.dsize = yp_secure_sz;
821 resp.valdat.dptr = NULL;
822 resp.valdat.dsize = 0;
825 * Get the value of the IS_SECURE key in the map.
827 retval = FALSE;
829 if (debug)
830 fprintf(stderr, "ypxfr: Checking masters secure key.\n");
831 if ((enum clnt_stat) clnt_call(master_server.dom_client,
832 YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, (char *)&req,
833 (xdrproc_t)xdr_ypresp_val, (char *)&resp,
834 udp_timeout) == RPC_SUCCESS) {
835 if (resp.status == YP_TRUE) {
836 if (debug)
837 fprintf(stderr, "ypxfr: SECURE\n");
838 secure_map = TRUE;
839 retval = TRUE;
840 } else if ((resp.status != YP_NOKEY) &&
841 (resp.status != YP_VERS) &&
842 (resp.status != YP_NOMORE)) {
843 *pushstat = ypprot_err(resp.status);
845 if (!logging) {
846 logprintf(
847 "(info) Can't get secure flag from ypserv at %s. Reason: %s.\n",
848 master, yperr_string(
849 ypprot_err(resp.status)));
853 CLNT_FREERES(master_server.dom_client,
854 (xdrproc_t)xdr_ypresp_val,
855 (char *)&resp);
856 } else {
857 *pushstat = YPPUSH_RPC;
858 logprintf("ypxfr(get_misc_recs) RPC call to %s failed", master);
859 clnt_perror(master_server.dom_client, "");
862 if (debug)
863 fprintf(stderr, "ypxfr: Checking masters INTERDOMAIN key.\n");
864 req.keydat.dptr = yp_interdomain;
865 req.keydat.dsize = yp_interdomain_sz;
867 resp.valdat.dptr = NULL;
868 resp.valdat.dsize = 0;
871 * Get the value of the INTERDOMAIN key in the map.
874 if ((enum clnt_stat) clnt_call(master_server.dom_client,
875 YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, (char *)&req,
876 (xdrproc_t)xdr_ypresp_val, (char *)&resp,
877 udp_timeout) == RPC_SUCCESS) {
878 if (resp.status == YP_TRUE) {
879 if (debug)
880 fprintf(stderr, "ypxfr: INTERDOMAIN\n");
881 interdomain_map = TRUE;
882 interdomain_value = (char *)malloc(resp.valdat.dsize+1);
883 (void) memmove(interdomain_value, resp.valdat.dptr,
884 resp.valdat.dsize);
885 *(interdomain_value+resp.valdat.dsize) = '\0';
886 interdomain_sz = resp.valdat.dsize;
887 retval = TRUE;
888 } else if ((resp.status != YP_NOKEY) &&
889 (resp.status != YP_VERS) &&
890 (resp.status != YP_NOMORE)) {
891 *pushstat = ypprot_err(resp.status);
893 if (!logging) {
894 logprintf(
895 "(info) Can't get interdomain flag from ypserv at %s. Reason: %s.\n",
896 master, yperr_string(
897 ypprot_err(resp.status)));
901 CLNT_FREERES(master_server.dom_client,
902 (xdrproc_t)xdr_ypresp_val,
903 (char *)&resp);
904 } else {
905 *pushstat = YPPUSH_RPC;
906 logprintf("ypxfr(get_misc_recs) RPC call to %s failed", master);
907 clnt_perror(master_server.dom_client, "");
911 return (retval);
915 * This gets the map's master name from the master server
917 bool
918 get_master_name(name, pushstat)
919 char *name;
920 int *pushstat;
922 if (master_prog_vers == YPVERS) {
923 return (get_v2master_name(name, pushstat));
924 } else
925 return (FALSE);
928 bool
929 get_v2master_name(name, pushstat)
930 char *name;
931 int *pushstat;
933 struct ypreq_nokey req;
934 struct ypresp_master resp;
935 int retval;
937 req.domain = source;
938 req.map = map;
939 resp.master = NULL;
940 retval = FALSE;
942 if ((enum clnt_stat) clnt_call(master_server.dom_client,
943 YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey, (char *)&req,
944 (xdrproc_t)xdr_ypresp_master, (char *)&resp,
945 udp_timeout) == RPC_SUCCESS) {
947 if (resp.status == YP_TRUE) {
948 strcpy(name, resp.master);
949 retval = TRUE;
950 } else if (resp.status != YP_BADDB) {
951 *pushstat = ypprot_err(resp.status);
953 if (!logging) {
954 logprintf(
955 "(info) Can't get master name from ypserv at %s. Reason: %s.\n",
956 master, yperr_string(
957 ypprot_err(resp.status)));
961 CLNT_FREERES(master_server.dom_client,
962 (xdrproc_t)xdr_ypresp_master,
963 (char *)&resp);
964 } else {
965 *pushstat = YPPUSH_RPC;
966 logprintf(
967 "ypxfr(get_v2master_name) RPC call to %s failed", master);
968 clnt_perror(master_server.dom_client, "");
971 return (retval);
975 * This does the work of transferring the map.
977 bool
978 move_map(pushstat)
979 int *pushstat;
981 unsigned local_version;
982 char map_name[MAXNAMLEN + 1];
983 char tmp_name[MAXNAMLEN + 1];
984 char bkup_name[MAXNAMLEN + 1];
985 char an[11];
986 unsigned n;
987 datum key;
988 datum val;
989 int hgstatus;
991 mkfilename(map_name);
993 if (!force) {
994 local_version = get_local_version(map_name);
995 if (debug) fprintf(stderr,
996 "ypxfr: Local version of map '%s' is %d\n",
997 map_name, local_version);
999 if (local_version >= *master_version) {
1000 logprintf(
1001 "Map %s at %s is not more recent than local.\n",
1002 map, master);
1003 *pushstat = YPPUSH_AGE;
1004 return (FALSE);
1008 mk_tmpname(yptempname_prefix, tmp_name);
1010 if (!new_mapfiles(tmp_name)) {
1011 logprintf(
1012 "Can't create temp map %s.\n", tmp_name);
1013 *pushstat = YPPUSH_FILE;
1014 return (FALSE);
1017 if ((hgstatus = ypxfrd_getdbm(tmp_name, master, source, map)) < 0)
1019 logprintf(
1020 "(info) %s %s %s ypxfrd getdbm failed (reason = %d) -- using ypxfr\n",
1021 master, domain, map, hgstatus);
1023 db = dbm_open(tmp_name, O_RDWR + O_CREAT + O_TRUNC, 0644);
1024 if (db == NULL) {
1025 logprintf(
1026 "Can't dbm init temp map %s.\n", tmp_name);
1027 del_mapfiles(tmp_name);
1028 *pushstat = YPPUSH_DBM;
1029 return (FALSE);
1031 if (defwrite) dbm_setdefwrite(db);
1033 if (!get_map(tmp_name, pushstat)) {
1034 del_mapfiles(tmp_name);
1035 return (FALSE);
1038 if (!add_private_entries(tmp_name)) {
1039 del_mapfiles(tmp_name);
1040 *pushstat = YPPUSH_DBM;
1041 return (FALSE);
1045 * Decide whether the map just transferred is a secure map.
1046 * If we already know the local version was secure, we do not
1047 * need to check this version.
1049 if (!secure_map) {
1050 key.dptr = yp_secure;
1051 key.dsize = yp_secure_sz;
1052 val = dbm_fetch(db, key);
1053 if (val.dptr != NULL) {
1054 secure_map = TRUE;
1058 if (dbm_close_status(db) < 0) {
1059 logprintf(
1060 "Can't do dbm close operation on temp map %s.\n",
1061 tmp_name);
1062 del_mapfiles(tmp_name);
1063 *pushstat = YPPUSH_DBM;
1064 return (FALSE);
1067 if (!get_order(an, &n, pushstat)) {
1068 return (FALSE);
1070 if (n != *master_version) {
1071 logprintf(
1072 "Version skew at %s while transferring map %s.\n",
1073 master, map);
1074 del_mapfiles(tmp_name);
1075 *pushstat = YPPUSH_SKEW;
1076 return (FALSE);
1079 if (check_count)
1080 if (!count_mismatch(tmp_name, entry_count)) {
1081 del_mapfiles(tmp_name);
1082 *pushstat = YPPUSH_DBM;
1083 return (FALSE);
1085 } else {
1086 /* touch up the map */
1087 db = dbm_open(tmp_name, 2, 0644);
1088 if (db == NULL) {
1089 logprintf(
1090 "Can't dbm init temp map %s.\n", tmp_name);
1091 del_mapfiles(tmp_name);
1092 *pushstat = YPPUSH_DBM;
1093 return (FALSE);
1097 if (!add_private_entries(tmp_name)) {
1098 del_mapfiles(tmp_name);
1099 *pushstat = YPPUSH_DBM;
1100 return (FALSE);
1104 * Decide whether the map just transferred is a secure map.
1105 * If we already know the local version was secure, we do not
1106 * need to check this version.
1108 if (!secure_map) {
1109 key.dptr = yp_secure;
1110 key.dsize = yp_secure_sz;
1111 val = dbm_fetch(db, key);
1112 if (val.dptr != NULL) {
1113 secure_map = TRUE;
1117 if (dbm_close_status(db) < 0) {
1118 logprintf(
1119 "Can't do dbm close operation on temp map %s.\n",
1120 tmp_name);
1121 del_mapfiles(tmp_name);
1122 *pushstat = YPPUSH_DBM;
1123 return (FALSE);
1128 if (lock_map(map_name) == 0) {
1129 del_mapfiles(tmp_name);
1130 logprintf("Lock error on %s\n", map_name);
1131 *pushstat = YPPUSH_FILE;
1132 return (FALSE);
1134 if (!check_map_existence(map_name)) {
1136 if (!rename_map(tmp_name, map_name, secure_map)) {
1137 del_mapfiles(tmp_name);
1138 logprintf(
1139 "Rename error: couldn't mv %s to %s.\n",
1140 tmp_name, map_name);
1141 *pushstat = YPPUSH_FILE;
1142 unlock_map(map_name);
1143 return (FALSE);
1146 } else {
1147 mk_tmpname(ypbkupname_prefix, bkup_name);
1149 if (!rename_map(map_name, bkup_name, secure_map)) {
1150 (void) rename_map(bkup_name, map_name, secure_map);
1151 logprintf(
1152 "Rename error: check that old %s is still intact.\n",
1153 map_name);
1154 del_mapfiles(tmp_name);
1155 *pushstat = YPPUSH_FILE;
1156 unlock_map(map_name);
1157 return (FALSE);
1160 if (rename_map(tmp_name, map_name, secure_map)) {
1161 del_mapfiles(bkup_name);
1162 } else {
1163 del_mapfiles(tmp_name);
1164 (void) rename_map(bkup_name, map_name, secure_map);
1165 logprintf(
1166 "Rename error: check that old %s is still intact.\n",
1167 map_name);
1168 *pushstat = YPPUSH_FILE;
1169 unlock_map(map_name);
1170 return (FALSE);
1173 if (unlock_map(map_name) == 0)
1174 return (FALSE);
1176 return (TRUE);
1180 * This tries to get the order number out of the local version of the map.
1181 * If the attempt fails for any version, the function will return "0"
1183 unsigned
1184 get_local_version(name)
1185 char *name;
1187 datum key;
1188 datum val;
1189 char number[11];
1190 DBM *db;
1192 if (!check_map_existence(name)) {
1193 return (0);
1195 if (debug) fprintf(stderr,
1196 "ypxfr: Map does exist, checking version now.\n");
1198 if ((db = dbm_open(name, 0, 0)) == 0) {
1199 return (0);
1202 key.dptr = yp_last_modified;
1203 key.dsize = yp_last_modified_sz;
1204 val = dbm_fetch(db, key);
1205 if (!val.dptr) { /* Check to see if dptr is NULL */
1206 return (0);
1208 if (val.dsize == 0 || val.dsize > 10) {
1209 return (0);
1211 /* Now save this value while we have it available */
1212 (void) memmove(number, val.dptr, val.dsize);
1213 number[val.dsize] = '\0';
1216 * Now check to see if it is 'secure'. If we haven't already
1217 * determined that it is secure in get_private_recs() then we check
1218 * the local map here.
1220 if (!secure_map) {
1221 key.dptr = yp_secure;
1222 key.dsize = yp_secure_sz;
1223 val = dbm_fetch(db, key);
1224 secure_map = (val.dptr != NULL);
1228 * Now check to see if interdomain requests are made of the local
1229 * map. Keep the value around if they are.
1231 if (!interdomain_map) {
1232 key.dptr = yp_interdomain;
1233 key.dsize = yp_interdomain_sz;
1234 val = dbm_fetch(db, key);
1235 if (interdomain_map = (val.dptr != NULL)) {
1236 interdomain_value = (char *)malloc(val.dsize+1);
1237 (void) memmove(interdomain_value, val.dptr, val.dsize);
1238 *(interdomain_value+val.dsize) = '\0';
1239 interdomain_sz = val.dsize;
1243 /* finish up */
1244 (void) dbm_close_status(db);
1246 return ((unsigned)atoi(number));
1250 * This constructs a file name for a map, minus its dbm_dir
1251 * or dbm_pag extensions
1253 void
1254 mkfilename(ppath)
1255 char *ppath;
1257 bool_t yptol_mode;
1258 int len;
1260 /* Work out if we are in yptol mode */
1261 yptol_mode = is_yptol_mode();
1263 len = strlen(domain) + strlen(map) + strlen(ypdbpath) + 3;
1264 if (yptol_mode)
1265 len += strlen(NTOL_PREFIX);
1267 if (len > (MAXNAMLEN + 1)) {
1268 logprintf("Map name string too long.\n");
1271 (void) strcpy(ppath, ypdbpath);
1272 (void) strcat(ppath, "/");
1273 (void) strcat(ppath, domain);
1274 (void) strcat(ppath, "/");
1275 if (yptol_mode)
1276 (void) strcat(ppath, NTOL_PREFIX);
1277 (void) strcat(ppath, map);
1281 * This returns a temporary name for a map transfer minus its dbm_dir or
1282 * dbm_pag extensions.
1284 void
1285 mk_tmpname(prefix, xfr_name)
1286 char *prefix;
1287 char *xfr_name;
1289 char xfr_anumber[10];
1290 long xfr_number;
1292 if (!xfr_name) {
1293 return;
1296 xfr_number = getpid();
1297 (void) sprintf(xfr_anumber, "%d", xfr_number);
1299 (void) strcpy(xfr_name, ypdbpath);
1300 (void) strcat(xfr_name, "/");
1301 (void) strcat(xfr_name, domain);
1302 (void) strcat(xfr_name, "/");
1303 (void) strcat(xfr_name, prefix);
1304 (void) strcat(xfr_name, map);
1305 (void) strcat(xfr_name, ".");
1306 (void) strcat(xfr_name, xfr_anumber);
1310 * This deletes the .pag and .dir files which implement a map.
1312 * Note: No error checking is done here for a garbage input file name or for
1313 * failed unlink operations.
1315 void
1316 del_mapfiles(basename)
1317 char *basename;
1319 char dbfilename[MAXNAMLEN + 1];
1321 if (!basename) {
1322 return;
1325 strcpy(dbfilename, basename);
1326 strcat(dbfilename, dbm_pag);
1327 unlink(dbfilename);
1328 strcpy(dbfilename, basename);
1329 strcat(dbfilename, dbm_dir);
1330 unlink(dbfilename);
1334 * This creates <pname>.dir and <pname>.pag
1336 bool
1337 new_mapfiles(pname)
1338 char *pname;
1340 char dbfile[MAXNAMLEN + 1];
1341 int f;
1342 int len;
1344 if (!pname || ((len = strlen(pname)) == 0) ||
1345 (len + 5) > (MAXNAMLEN + 1)) {
1346 return (FALSE);
1349 errno = 0;
1350 (void) strcpy(dbfile, pname);
1351 (void) strcat(dbfile, dbm_dir);
1353 if ((f = open(dbfile, (O_WRONLY | O_CREAT | O_TRUNC), 0600)) >= 0) {
1354 (void) close(f);
1355 (void) strcpy(dbfile, pname);
1356 (void) strcat(dbfile, dbm_pag);
1358 if ((f = open(dbfile, (O_WRONLY | O_CREAT | O_TRUNC),
1359 0600)) >= 0) {
1360 (void) close(f);
1361 return (TRUE);
1362 } else {
1363 return (FALSE);
1366 } else {
1367 return (FALSE);
1372 count_callback(status)
1373 int status;
1375 if (status != YP_TRUE) {
1377 if (status != YP_NOMORE) {
1378 logprintf(
1379 "Error from ypserv on %s (ypall_callback) = %s.\n",
1380 master, yperr_string(ypprot_err(status)));
1383 return (TRUE);
1386 entry_count++;
1387 return (FALSE);
1391 * This counts the entries in the dbm file after the transfer to
1392 * make sure that the dbm file was built correctly.
1393 * Returns TRUE if everything is OK, FALSE if they mismatch.
1396 count_mismatch(pname, oldcount)
1397 char *pname;
1398 int oldcount;
1400 datum key;
1401 DBM *db;
1402 #ifdef REALLY_PARANOID
1403 struct ypall_callback cbinfo;
1404 struct ypreq_nokey allreq;
1405 enum clnt_stat s;
1406 struct dom_binding domb;
1407 datum value;
1408 #endif /* REALLY_PARANOID */
1410 entry_count = 0;
1411 db = dbm_open(pname, 0, 0);
1412 if (db) {
1413 for (key = dbm_firstkey(db);
1414 key.dptr != NULL; key = dbm_nextkey(db))
1415 entry_count++;
1416 dbm_close_status(db);
1419 if (oldcount != entry_count) {
1420 logprintf(
1421 "*** Count mismatch in dbm file %s: old=%d, new=%d ***\n",
1422 map, oldcount, entry_count);
1423 return (FALSE);
1426 #ifdef REALLY_PARANOID
1428 if ((domb.dom_client = __yp_clnt_create_rsvdport(master, YPPROG,
1429 master_prog_vers,
1430 "tcp6", 0, 0)) == 0 &&
1431 (domb.dom_client = __yp_clnt_create_rsvdport(master, YPPROG,
1432 master_prog_vers,
1433 "tcp", 0, 0)) == 0) {
1434 clnt_pcreateerror("ypxfr (mismatch) - TCP channel "
1435 "create failure");
1436 return (FALSE);
1439 if (master_prog_vers == YPVERS) {
1440 int tmpstat;
1442 allreq.domain = source;
1443 allreq.map = map;
1444 cbinfo.foreach = count_callback;
1445 tmpstat = 0;
1446 cbinfo.data = (char *)&tmpstat;
1448 entry_count = 0;
1449 s = clnt_call(domb.dom_client, YPPROC_ALL, xdr_ypreq_nokey,
1450 &allreq, xdr_ypall, &cbinfo, tcp_timeout);
1452 if (tmpstat == 0) {
1453 if (s == RPC_SUCCESS) {
1454 } else {
1455 clnt_perror(domb.dom_client,
1456 "ypxfr (get_map/all) - RPC clnt_call (TCP) failure");
1457 return (FALSE);
1460 } else {
1461 return (FALSE);
1464 } else {
1465 logprintf("Wrong version number!\n");
1466 return (FALSE);
1468 clnt_destroy(domb.dom_client);
1469 close(domb.dom_socket);
1470 entry_count += 2; /* add in YP_entries */
1471 if (oldcount != entry_count) {
1472 logprintf(
1473 "*** Count mismatch after enumerate %s: old=%d, new=%d ***\n",
1474 map, oldcount, entry_count);
1475 return (FALSE);
1477 #endif /* REALLY_PARANOID */
1479 return (TRUE);
1483 * This sets up a TCP connection to the master server, and either gets
1484 * ypall_callback to do all the work of writing it to the local dbm file
1485 * (if the ypserv is current version), or does it itself for an old ypserv.
1487 bool
1488 get_map(pname, pushstat)
1489 char *pname;
1490 int *pushstat;
1492 struct dom_binding domb;
1493 enum clnt_stat s;
1494 struct ypreq_nokey allreq;
1495 struct ypall_callback cbinfo;
1496 bool retval = FALSE;
1497 int tmpstat;
1498 int recvsiz = 24 * 1024;
1499 struct netconfig *nconf;
1500 int fd;
1501 struct netbuf *svcaddr;
1502 char *netid[] = { "tcp6", "tcp" };
1503 int i, lastnetid = (sizeof (netid)/sizeof (netid[0])) - 1;
1505 svcaddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
1506 if (! svcaddr)
1507 return (FALSE);
1508 svcaddr->maxlen = 32;
1509 svcaddr->len = 32;
1510 svcaddr->buf = (char *)malloc(32);
1511 if (! svcaddr->buf) {
1512 free(svcaddr);
1513 return (FALSE);
1516 for (i = 0; i <= lastnetid; i++) {
1517 fd = RPC_ANYFD;
1518 if ((nconf = getnetconfigent(netid[i])) == NULL) {
1519 if (i != lastnetid)
1520 continue;
1521 logprintf("ypxfr: tcp transport not supported\n");
1522 free(svcaddr->buf);
1523 free(svcaddr);
1524 return (FALSE);
1526 if (rpcb_getaddr(YPPROG, master_prog_vers, nconf, svcaddr,
1527 master) == FALSE) {
1528 freenetconfigent(nconf);
1529 if (i != lastnetid)
1530 continue;
1531 logprintf("ypxfr: could not get %s address\n", master);
1532 free(svcaddr->buf);
1533 free(svcaddr);
1534 return (FALSE);
1536 if ((domb.dom_client = __nis_clnt_create(fd, nconf, 0, svcaddr,
1537 0, YPPROG, master_prog_vers, recvsiz, 0)) == 0) {
1538 freenetconfigent(nconf);
1539 if (i != lastnetid)
1540 continue;
1541 clnt_pcreateerror(
1542 "ypxfr (get_map) - TCP channel create failure");
1543 *pushstat = YPPUSH_RPC;
1544 free(svcaddr->buf);
1545 free(svcaddr);
1546 return (FALSE);
1548 break;
1551 entry_count = 0;
1552 if (master_prog_vers == YPVERS) {
1553 allreq.domain = source;
1554 allreq.map = map;
1555 cbinfo.foreach = ypall_callback;
1556 tmpstat = 0;
1557 cbinfo.data = (char *)&tmpstat;
1559 s = clnt_call(domb.dom_client, YPPROC_ALL,
1560 (xdrproc_t)xdr_ypreq_nokey,
1561 (char *)&allreq, (xdrproc_t)xdr_ypall, (char *)&cbinfo,
1562 tcp_timeout);
1564 if (tmpstat == 0) {
1566 if (s == RPC_SUCCESS) {
1567 retval = TRUE;
1568 } else {
1569 clnt_perror(domb.dom_client,
1570 "ypxfr (get_map/all) - RPC clnt_call (TCP) failure");
1571 *pushstat = YPPUSH_RPC;
1574 } else {
1575 *pushstat = tmpstat;
1578 } else
1579 retval = FALSE; /* barf again at YPOLDVERS */
1580 cleanup:
1581 clnt_destroy(domb.dom_client);
1582 return (retval);
1586 * This sticks each key-value pair into the current map. It returns FALSE as
1587 * long as it wants to keep getting called back, and TRUE on error conditions
1588 * and "No more k-v pairs".
1591 ypall_callback(status, key, kl, val, vl, pushstat)
1592 int status;
1593 char *key;
1594 int kl;
1595 char *val;
1596 int vl;
1597 int *pushstat;
1599 datum keydat;
1600 datum valdat;
1601 datum test;
1603 if (status != YP_TRUE) {
1605 if (status != YP_NOMORE) {
1606 logprintf(
1607 "Error from ypserv on %s (ypall_callback) = %s.\n",
1608 master, yperr_string(ypprot_err(status)));
1609 *pushstat = map_yperr_to_pusherr(status);
1612 return (TRUE);
1615 keydat.dptr = key;
1616 keydat.dsize = kl;
1617 valdat.dptr = val;
1618 valdat.dsize = vl;
1619 entry_count++;
1620 /* way too many fetches */
1622 #ifdef PARANOID
1623 test = dbm_fetch(db, keydat);
1624 if (test.dptr != NULL) {
1625 logprintf("Duplicate key %s in map %s\n", key, map);
1626 *pushstat = YPPUSH_DBM;
1627 return (TRUE);
1629 #endif /* PARANOID */
1630 if (dbm_store(db, keydat, valdat, 0) < 0) {
1631 logprintf(
1632 "Can't do dbm store into temp map %s.\n", map);
1633 *pushstat = YPPUSH_DBM;
1634 return (TRUE);
1636 #ifdef PARANOID
1637 test = dbm_fetch(db, keydat);
1638 if (test.dptr == NULL) {
1639 logprintf("Key %s was not inserted into dbm file %s\n",
1640 key, map);
1641 *pushstat = YPPUSH_DBM;
1642 return (TRUE);
1644 #endif /* PARANOID */
1646 if (dbm_error(db)) {
1647 logprintf("Key %s dbm_error raised in file %s\n",
1648 key, map);
1649 *pushstat = YPPUSH_DBM;
1650 return (TRUE);
1652 return (FALSE);
1656 * This maps a YP_xxxx error code into a YPPUSH_xxxx error code
1659 map_yperr_to_pusherr(yperr)
1660 int yperr;
1662 int reason;
1664 switch (yperr) {
1666 case YP_NOMORE:
1667 reason = YPPUSH_SUCC;
1668 break;
1670 case YP_NOMAP:
1671 reason = YPPUSH_NOMAP;
1672 break;
1674 case YP_NODOM:
1675 reason = YPPUSH_NODOM;
1676 break;
1678 case YP_NOKEY:
1679 reason = YPPUSH_YPERR;
1680 break;
1682 case YP_BADARGS:
1683 reason = YPPUSH_BADARGS;
1684 break;
1686 case YP_BADDB:
1687 reason = YPPUSH_YPERR;
1688 break;
1690 default:
1691 reason = YPPUSH_XFRERR;
1692 break;
1695 return (reason);
1699 * This writes the last-modified and master entries into the new dbm file
1701 bool
1702 add_private_entries(pname)
1703 char *pname;
1705 datum key;
1706 datum val;
1708 if (!fake_master_version) {
1709 key.dptr = yp_last_modified;
1710 key.dsize = yp_last_modified_sz;
1711 val.dptr = master_ascii_version;
1712 val.dsize = strlen(master_ascii_version);
1714 if (dbm_store(db, key, val, 1) < 0) {
1715 logprintf(
1716 "Can't do dbm store into temp map %s.\n",
1717 pname);
1718 return (FALSE);
1720 entry_count++;
1723 if (master_name) {
1724 key.dptr = yp_master_name;
1725 key.dsize = yp_master_name_sz;
1726 val.dptr = master_name;
1727 val.dsize = strlen(master_name);
1728 if (dbm_store(db, key, val, 1) < 0) {
1729 logprintf(
1730 "Can't do dbm store into temp map %s.\n",
1731 pname);
1732 return (FALSE);
1734 entry_count++;
1737 if (interdomain_map) {
1738 key.dptr = yp_interdomain;
1739 key.dsize = yp_interdomain_sz;
1740 val.dptr = interdomain_value;
1741 val.dsize = interdomain_sz;
1742 if (dbm_store(db, key, val, 1) < 0) {
1743 logprintf(
1744 "Can't do dbm store into temp map %s.\n",
1745 pname);
1746 return (FALSE);
1748 entry_count++;
1751 if (secure_map) {
1752 key.dptr = yp_secure;
1753 key.dsize = yp_secure_sz;
1754 val.dptr = yp_secure;
1755 val.dsize = yp_secure_sz;
1756 if (dbm_store(db, key, val, 1) < 0) {
1757 logprintf(
1758 "Can't do dbm store into temp map %s.\n",
1759 pname);
1760 return (FALSE);
1762 entry_count++;
1765 return (TRUE);
1770 * This sends a YPPROC_CLEAR message to the local ypserv process.
1772 bool
1773 send_ypclear(pushstat)
1774 int *pushstat;
1776 struct dom_binding domb;
1777 char local_host_name[256];
1778 unsigned int progvers;
1779 int status;
1781 if (gethostname(local_host_name, 256)) {
1782 logprintf("Can't get local machine name.\n");
1783 *pushstat = YPPUSH_RSRC;
1784 return (FALSE);
1787 if (!bind_to_server(local_host_name, &domb,
1788 &progvers, &status)) {
1789 *pushstat = YPPUSH_CLEAR;
1790 return (FALSE);
1793 if ((enum clnt_stat) clnt_call(domb.dom_client,
1794 YPPROC_CLEAR, xdr_void, 0, xdr_void, 0,
1795 udp_timeout) != RPC_SUCCESS) {
1796 logprintf(
1797 "Can't send ypclear message to ypserv on the local machine.\n");
1798 xfr_exit(YPPUSH_CLEAR);
1801 return (TRUE);
1805 * This decides if send_callback has to get called, and does the process exit.
1807 void
1808 xfr_exit(status)
1809 int status;
1811 if (callback) {
1812 send_callback(&status);
1815 if (status == YPPUSH_SUCC) {
1816 #ifdef TREEPUSH
1817 if (treepush) {
1818 if (debug)
1819 execlp("./yppush", "yppush", "-T", map, 0);
1820 execlp("/usr/etc/yp/yppush", "yppush", "-T", map, 0);
1821 perror("yppush");
1823 #endif
1824 exit(0);
1825 } else {
1826 exit(1);
1831 * This sets up a UDP connection to the yppush process which contacted our
1832 * parent ypserv, and sends it a status on the requested transfer.
1834 void
1835 send_callback(status)
1836 int *status;
1838 struct yppushresp_xfr resp;
1839 struct dom_binding domb;
1841 resp.transid = (unsigned long) atoi(tid);
1842 resp.status = (unsigned long) *status;
1844 udp_timeout.tv_sec = CALLTIMEOUT;
1846 if ((domb.dom_client = __yp_clnt_create_rsvdport(pushhost,
1847 (ulong_t)atoi(proto),
1848 YPPUSHVERS,
1849 0, 0, 0)) == NULL) {
1850 *status = YPPUSH_RPC;
1851 return;
1854 if ((enum clnt_stat) clnt_call(domb.dom_client,
1855 YPPUSHPROC_XFRRESP, (xdrproc_t)xdr_yppushresp_xfr,
1856 (char *)&resp, xdr_void, 0,
1857 udp_timeout) != RPC_SUCCESS) {
1858 *status = YPPUSH_RPC;
1859 return;
1864 * FUNCTION: is_yptol_mode();
1866 * DESCRIPTION: Determines if we should run in N2L or traditional mode based
1867 * on the presence of the N2L mapping file.
1869 * This is a copy of a function from libnisdb. If more than this
1870 * one function become required it may be worth linking the
1871 * entire lib.
1873 * INPUTS: Nothing
1875 * OUTPUTS: TRUE = Run in N2L mode
1876 * FALSE = Run in traditional mode.
1878 bool_t
1879 is_yptol_mode()
1881 struct stat filestat;
1883 if (stat(NTOL_MAP_FILE, &filestat) != -1)
1884 return (TRUE);
1886 return (FALSE);