From 62e4ee4ff895e2851ea3fa6241c2bd32b86f6d5f Mon Sep 17 00:00:00 2001 From: wpaul Date: Mon, 25 Dec 1995 03:07:13 +0000 Subject: Import the new ypxfr, written by yours truly. Functionally equivalent to the old one, except that it supports an additional option (-p path) that lets you specify the top level path wiere your NIS maps live. (ypserv allows you to specify a path like this, so it makes sense that ypxfr should too. ypserv will automagically pass the -p flag to ypxfr if you use a path other than /var/yp when you start it.) This program uses client stub code generated by rpcgen as well as the yp_dblookup.c module from ypserv. --- dist/libexec/ypxfr/Makefile | 26 ++ dist/libexec/ypxfr/yp_dbwrite.c | 105 ++++++++ dist/libexec/ypxfr/ypxfr.8 | 207 ++++++++++++++++ dist/libexec/ypxfr/ypxfr_extern.h | 57 +++++ dist/libexec/ypxfr/ypxfr_getmap.c | 99 ++++++++ dist/libexec/ypxfr/ypxfr_main.c | 490 ++++++++++++++++++++++++++++++++++++++ dist/libexec/ypxfr/ypxfr_misc.c | 240 +++++++++++++++++++ 7 files changed, 1224 insertions(+) create mode 100644 dist/libexec/ypxfr/Makefile create mode 100644 dist/libexec/ypxfr/yp_dbwrite.c create mode 100644 dist/libexec/ypxfr/ypxfr.8 create mode 100644 dist/libexec/ypxfr/ypxfr_extern.h create mode 100644 dist/libexec/ypxfr/ypxfr_getmap.c create mode 100644 dist/libexec/ypxfr/ypxfr_main.c create mode 100644 dist/libexec/ypxfr/ypxfr_misc.c diff --git a/dist/libexec/ypxfr/Makefile b/dist/libexec/ypxfr/Makefile new file mode 100644 index 0000000..0339aee --- /dev/null +++ b/dist/libexec/ypxfr/Makefile @@ -0,0 +1,26 @@ +# $Id: Makefile,v 1.6 1995/12/16 04:03:02 wpaul Exp $ + +PROG= ypxfr +SRCS= ypxfr_clnt.c yp_clnt.c ypxfr_getmap.c yp_dblookup.c \ + yp_error.c ypxfr_misc.c ypxfr_main.c yp_dbwrite.c + +.PATH: ${.CURDIR}/../../usr.sbin/ypserv + +MAN8= ypxfr.8 +CFLAGS+=-I. + +CLEANFILES= yp.h yp_clnt.c ypxfr_clnt.c + +RPCSRC= ${.DESTDIR}/usr/include/rpcsvc/yp.x +RPCGEN= rpcgen -I -C + +ypxfr_clnt.c: ${RPCSRC} yp.h + ${RPCGEN} -DYPPUSH_ONLY -l -o ${.TARGET} ${RPCSRC} + +yp_clnt.c: ${RPCSRC} yp.h + ${RPCGEN} -DYPSERV_ONLY -l -o ${.TARGET} ${RPCSRC} + +yp.h: ${RPCSRC} + ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} + +.include diff --git a/dist/libexec/ypxfr/yp_dbwrite.c b/dist/libexec/ypxfr/yp_dbwrite.c new file mode 100644 index 0000000..f874e9b --- /dev/null +++ b/dist/libexec/ypxfr/yp_dbwrite.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: yp_dbwrite.c,v 1.7 1995/12/24 04:40:58 wpaul Exp $ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "yp.h" +#include "ypxfr_extern.h" + +#ifndef lint +static const char rcsid[] = "$Id: yp_dbwrite.c,v 1.7 1995/12/24 04:40:58 wpaul Exp $"; +#endif + +#define PERM_SECURE (S_IRUSR|S_IWUSR) + +/* + * Open a DB database read/write + */ +DB *yp_open_db_rw(domain, map) + const char *domain; + const char *map; +{ + DB *dbp; + char buf[1025]; + + + yp_errno = YP_TRUE; + + if (map[0] == '.' || strchr(map, '/')) { + yp_errno = YP_BADARGS; + return (NULL); + } + + snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); + + dbp = dbopen(buf,O_RDWR|O_EXCL|O_CREAT, PERM_SECURE, DB_HASH, &openinfo); + + if (dbp == NULL) { + switch(errno) { + case ENOENT: + yp_errno = YP_NOMAP; + break; + case EFTYPE: + yp_errno = YP_BADDB; + break; + default: + yp_errno = YP_YPERR; + break; + } + } + + return (dbp); +} + +int yp_put_record(dbp,key,data) + DB *dbp; + DBT *key; + DBT *data; +{ + + if ((dbp->put)(dbp,key,data,0)) { + (void)(dbp->close)(dbp); + return(YP_BADDB); + } + + return(YP_TRUE); +} diff --git a/dist/libexec/ypxfr/ypxfr.8 b/dist/libexec/ypxfr/ypxfr.8 new file mode 100644 index 0000000..5e41b08 --- /dev/null +++ b/dist/libexec/ypxfr/ypxfr.8 @@ -0,0 +1,207 @@ +.\" Copyright (c) 1995 +.\" Bill Paul . All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Bill Paul. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: ypxfr.8,v 1.2 1995/12/25 02:54:39 wpaul Exp $ +.\" +.Dd February 5, 1995 +.Dt YPXFR 8 +.Os +.Sh NAME +.Nm ypxfr +.Nd "transfer NIS database from remote server to local host" +.Sh SYNOPSIS +.Nm ypxfr +.Op Fl f +.Op Fl c +.Op Fl d Ar target domain +.Op Fl h Ar source host +.Op Fl s Ar source domain +.Op Fl p Ar path +.Op Fl C Ar taskid program-number ipaddr port +.Ar mapname +.Sh DESCRIPTION +.Nm ypxfr +copies an NIS database (or +.Pa map ) +from one NIS server to another using NIS services. In FreeBSD, +.Nm ypxfr +is generally invoked by +.Xr ypserv 8 +when it receives a map transfer request from +.Xr yppush 8 . +.Nm ypxfr +is used primarily in environments where several NIS servers +are in use in a single domain. One server, the NIS master, maintains +the canonical copies of all NIS maps, and all the other servers, +the NIS slaves, copy new versions of the maps from the master whenever +any updates are made (i.e. when a user updates their password via +.Xr yppasswd 1 +). +.Pp +When run, +.Nm ypxfr +creates a temporary database file in +.Pa /var/yp/[domainmame] , +and fills it with the contents of +.Ar mapname +as supplied by the specified +.Ar source host . +When the entire map has been transfered, +.Nm ypxfr +deletes the original copy of +.Ar mapname +and moves the temporary copy into its place. When the transfer is +complete, +.Nm ypxfr +will attempt to send a 'clear current map' request to the local +.Xr ypserv 8 +process to clear any possible references it may still have to the +stale map. +.Pp +Note that all files created by +.Nm ypxfr +are owner readable and writable only for security reasons. Since the +NIS maps and the directory in which they reside are normally owned by +root, this prevents non-privleged users from making unauthorized +modifications. +.Pp +In order to maintain consistency across all NIS servers, +.Nm ypxfr +can be run periodically in a +.Xr cron 8 +job. Maps which change infrequently +need only be updated once a day (preferably late at night when system +usage is lowest), whereas those that are subject to frequent changes +(such a +.Pa passwd.byname +and +.Pa passwd.byuid ) +should be updated perhaps once every hour. Using +.Xr cron 8 +to automatically +update the NIS maps is not strictly mandatory since all updates should +be propagated by +.Xr yppush 8 +when +.Pa /var/yp/Makefile +is run on the NIS master server, however it is good practice +on large networks where possible outages could cause NIS servers to +fall out of sync with each other. +.Pp +When +.Nm ypxfr +is invoked without a controlling terminal, e.g. from inside +.Xr ypserv 8 , +it logs all its output using the +.Xr syslog 3 +facility. +.Sh OPTIONS +The following options and flags are supported by +.Nm ypxfr : +.Bl -tag -width flag +.It Fl f +Force a map transfer. Normally, +.Nm ypxfr +will not transfer a map if it determines that the NIS master's copy +is not newer than the existing copy already on the local host: the +.Fl f +flag forces a transfer regardless of which server's version is more recent. +.It Fl c +Do not send a 'clear current map' request to the +.Xr ypserv 8 +process running on the local host. This flag is normally used when +invoking +.Nm ypxfr +manually on a machine that is not yet running +.Xr ypserv 8 . +Without this flag, failure to contact the local NIS server will cause +.Nm ypxfr +to abort the transfer. +.It Fl d Ar target domain +Specify a target domain other than the current NIS domain. +.It Fl h Ar source host +Specify the name of the host from which to copy the NIS maps. This option +is used to insure that +.Nm ypxfr +only copies maps from the NIS master server. +.It Fl s Ar source domain +Specify the domain from which to transfer a map, in the event that +the transfer is being done across two different NIS domains. +.It Fl p Ar path +Specify the top level directory containing the NIS maps. By +default, this path is +.Pa /var/yp . +The +.Fl p +flag allows you to specify an alternate path should you wish to +store your NIS maps in a different part of the filesystem. The +NIS server, +.Xr ypserv 8 , +passes this flag to +.Nm ypxfr +if it too has been told to use an alternate path. +.It Fl C Ar taskid program-number ipaddr port +These options are used only when +.Nm ypxfr +is invoked by +.Xr ypserv 8 +in response to a map transfer request initiated by +.Xr yppush 8 . +In this instance, +.Nm ypxfr +needs to 'callback' to the +.Xr yppush 8 +process and interact with it, so +.Xr yppush 8 +passes to it an IP address +.Ar ipaddr , +port number +.Ar port , +registered program number +.Ar program-number +and a transaction ID +.Ar taskid +that it can use to contact the waiting +.Xr yppush 8 +process on the master server. +.It Ar mapname +The name of the map to transfer. +.El +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /var/yp/[domainname]/[maps] +The NIS maps for a particular NIS domain. +.El +.Sh SEE ALSO +.Xr ypserv 8 , +.Xr yppush 8 , +.Xr yp 4 +.Sh AUTHOR +Bill Paul diff --git a/dist/libexec/ypxfr/ypxfr_extern.h b/dist/libexec/ypxfr/ypxfr_extern.h new file mode 100644 index 0000000..b2eda88 --- /dev/null +++ b/dist/libexec/ypxfr/ypxfr_extern.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ypxfr_extern.h,v 1.5 1995/12/24 04:37:22 wpaul Exp $ + */ +#include +#include +#include +#include + +#ifndef _PATH_YP +#define _PATH_YP "/var/yp/" +#endif + +extern char *yp_dir; +extern int debug; +extern HASHINFO openinfo; +extern int yp_errno; +extern void yp_error __P(( const char *, ... )); +extern int _yp_check __P(( char ** )); +extern char *ypxfrerr_string __P(( ypxfrstat )); +extern DB *yp_open_db_rw __P(( const char *, const char *)); +extern int yp_put_record __P(( DB *, DBT *, DBT * )); +extern int yp_get_record __P(( const char *, const char *, const DBT *, DBT *, int )); +extern int ypxfr_get_map __P(( char *, char *, char *, int (*)() )); +extern char *ypxfr_get_master __P(( char *, char *, char *, const int )); +extern unsigned long ypxfr_get_order __P(( char *, char *, char *, const int )); +extern char *ypxfxerr_string __P(( ypxfrstat )); +extern int callrpc __P(( char *, int, int, int, xdrproc_t, char *, xdrproc_t, char *)); diff --git a/dist/libexec/ypxfr/ypxfr_getmap.c b/dist/libexec/ypxfr/ypxfr_getmap.c new file mode 100644 index 0000000..702b5cb --- /dev/null +++ b/dist/libexec/ypxfr/ypxfr_getmap.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ypxfr_getmap.c,v 1.6 1995/12/24 04:39:04 wpaul Exp $ + */ +#include +#include +#include +#include +#include +#include +#include "ypxfr_extern.h" + +#ifndef lint +static const char rcsid[] = "$Id: ypxfr_getmap.c,v 1.6 1995/12/24 04:39:04 wpaul Exp $"; +#endif + +extern bool_t xdr_ypresp_all_seq __P(( XDR *, unsigned long * )); + +int (*ypresp_allfn)(); +void *ypresp_data; +extern DB *specdbp; +extern int yp_errno; + +/* + * This is largely the same as yp_all() except we do the transfer + * from a specific server without the aid of ypbind(8). We need to + * be able to specify the source host explicitly since ypxfr may + * only transfer maps from the NIS master server for any given domain. + * However, if we use the libc version of yp_all(), we could end up + * talking to one of the slaves instead. We do need to dig into libc + * a little though, since it contains the magic XDR function we need. + */ +int ypxfr_get_map(map, domain, host, callback) + char *map; + char *domain; + char *host; + int (*callback)(); +{ + CLIENT *clnt; + ypreq_nokey req; + unsigned long status; + struct timeval timeout; + + timeout.tv_usec = 0; + timeout.tv_sec = 10; + + /* YPPROC_ALL is a TCP service */ + if ((clnt = clnt_create(host, YPPROG, YPVERS, "tcp")) == NULL) { + yp_error("%s", clnt_spcreateerror("failed to tcp handle")); + yp_errno = YPXFR_YPERR; + return(1); + } + + req.domain = domain; + req.map = map; + ypresp_allfn = callback; + ypresp_data = NULL; + + (void)clnt_call(clnt, YPPROC_ALL, xdr_ypreq_nokey, &req, + xdr_ypresp_all_seq, &status, timeout); + + clnt_destroy(clnt); + + if (status != YP_TRUE) { + yp_errno = YPXFR_YPERR; + return(1); + } + + return(0); +} diff --git a/dist/libexec/ypxfr/ypxfr_main.c b/dist/libexec/ypxfr/ypxfr_main.c new file mode 100644 index 0000000..e9bddb4 --- /dev/null +++ b/dist/libexec/ypxfr/ypxfr_main.c @@ -0,0 +1,490 @@ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ypxfr_main.c,v 1.11 1995/12/25 02:53:33 wpaul Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +struct dom_binding {}; +#include +#include "ypxfr_extern.h" + +#ifndef lint +static const char rcsid[] = "$Id: ypxfr_main.c,v 1.11 1995/12/25 02:53:33 wpaul Exp $"; +#endif + +char *progname = "ypxfr"; +char *yp_dir = _PATH_YP; +int _rpcpmstart = 0; +int ypxfr_use_yplib = 0; /* Assume the worst. */ +int ypxfr_clear = 1; +int ypxfr_prognum = 0; +struct sockaddr_in ypxfr_callback_addr; +struct yppushresp_xfr ypxfr_resp; +DB *dbp; + +static void ypxfr_exit(retval, temp) + ypxfrstat retval; + char *temp; +{ + CLIENT *clnt; + int sock = RPC_ANYSOCK; + struct timeval timeout; + + /* Clean up no matter what happened previously. */ + if (temp != NULL) { + (void)(dbp->close)(dbp); + if (unlink(temp) == -1) { + yp_error("failed to unlink %s",strerror(errno)); + } + } + + if (_rpcpmstart) { + timeout.tv_sec = 20; + timeout.tv_usec = 0; + + if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum, + 1, timeout, &sock)) == NULL) { + yp_error("%s", clnt_spcreateerror("failed to establish callback handle")); + exit(1); + } + + ypxfr_resp.status = retval; + + if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { + yp_error("%s", clnt_sperror(clnt, "callback failed")); + clnt_destroy(clnt); + exit(1); + } + clnt_destroy(clnt); + } else { + yp_error("Exiting: %s", ypxfrerr_string(retval)); + } + + exit(0); +} + +static void usage() +{ + if (_rpcpmstart) { + ypxfr_exit(YPXFR_BADARGS,NULL); + } else { + fprintf(stderr,"usage: %s [-f] [-c] [-d target domain] \ +[-h source host] [-s source domain]\n", progname); + fprintf(stderr,"\t [-p path] [-C taskid program-number \ +ipaddr port] mapname\n"); + exit(1); + } +} + +int ypxfr_foreach(status, key, keylen, val, vallen, data) + int status; + char *key; + int keylen; + char *val; + int vallen; + char *data; +{ + DBT dbkey, dbval; + + if (status != YP_TRUE) + return (status); + + dbkey.data = key; + dbkey.size = keylen; + dbval.data = val; + dbval.size = vallen; + + if (yp_put_record(dbp, &dbkey, &dbval) != YP_TRUE) + return(yp_errno); + + return (0); +} + +main(argc,argv) + int argc; + char *argv[]; +{ + int ch; + int ypxfr_force = 0; + char *ypxfr_dest_domain = NULL; + char *ypxfr_source_host = NULL; + char *ypxfr_source_domain = NULL; + char *ypxfr_local_domain = NULL; + char *ypxfr_master = NULL; + unsigned long ypxfr_order = -1, ypxfr_skew_check = -1; + char *ypxfr_mapname = NULL; + int ypxfr_args = 0; + char ypxfr_temp_map[MAXPATHLEN + 2]; + char tempmap[MAXPATHLEN + 2]; + char buf[MAXPATHLEN + 2]; + DBT key, data; + + debug = 1; + + if (!isatty(fileno(stderr))) { + openlog(progname, LOG_PID, LOG_DAEMON); + _rpcpmstart = 1; + } + + if (argc < 2) + usage(); + + while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != EOF) { + int my_optind; + switch(ch) { + case 'f': + ypxfr_force++; + ypxfr_args++; + break; + case 'c': + ypxfr_clear = 0; + ypxfr_args++; + break; + case 'd': + ypxfr_dest_domain = optarg; + ypxfr_args += 2; + break; + case 'h': + ypxfr_source_host = optarg; + ypxfr_args += 2; + break; + case 's': + ypxfr_source_domain = optarg; + ypxfr_args += 2; + break; + case 'p': + yp_dir = optarg; + ypxfr_args += 2; + break; + case 'C': + /* + * Whoever decided that the -C flag should take + * four arguments is a twit. + */ + my_optind = optind - 1; + if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { + yp_error("transaction ID not specified"); + usage(); + } + ypxfr_resp.transid = atol(argv[my_optind]); + my_optind++; + if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { + yp_error("RPC program number not specified"); + usage(); + } + ypxfr_prognum = atol(argv[my_optind]); + my_optind++; + if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { + yp_error("address not specified"); + usage(); + } + if (!inet_aton(argv[my_optind], &ypxfr_callback_addr.sin_addr)) { + yp_error("failed to convert '%s' to IP addr", + argv[my_optind]); + exit(1); + } + my_optind++; + if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { + yp_error("port not specified"); + usage(); + } + ypxfr_callback_addr.sin_port = htons((u_short)atoi(argv[my_optind])); + ypxfr_args += 5; + break; + default: + usage(); + break; + } + } + + ypxfr_mapname = argv[ypxfr_args + 1]; + + if (ypxfr_mapname == NULL) { + yp_error("no map name specified"); + usage(); + } + + /* Always the case. */ + ypxfr_callback_addr.sin_family = AF_INET; + + /* Determine if local NIS client facilities are turned on. */ + if (!yp_get_default_domain(&ypxfr_local_domain) && + _yp_check(&ypxfr_local_domain)) + ypxfr_use_yplib = 1; + + /* + * If no destination domain is specified, assume that the + * local default domain is to be used and try to obtain it. + * Fails if NIS client facilities are turned off. + */ + if (ypxfr_dest_domain == NULL) { + if (ypxfr_use_yplib) { + yp_get_default_domain(&ypxfr_dest_domain); + } else { + yp_error("no destination domain specified and \ +the local domain name isn't set"); + ypxfr_exit(YPXFR_BADARGS,NULL); + } + } + + /* + * If a source domain is not specified, assume it to + * be the same as the destination domain. + */ + if (ypxfr_source_domain == NULL) { + ypxfr_source_domain = ypxfr_dest_domain; + } + + /* + * If the source host is not specified, assume it to be the + * master for the specified map. If local NIS client facilities + * are turned on, we can figure this out using yp_master(). + * If not, we have to see if a local copy of the map exists + * and extract its YP_MASTER_NAME record. If _that_ fails, + * we are stuck and must ask the user for more information. + */ + if (ypxfr_source_host == NULL) { + if (!ypxfr_use_yplib) { + /* + * Double whammy: NIS isn't turned on and the user + * didn't specify a source host. + */ + char *dptr; + key.data = "YP_MASTER_NAME"; + key.size = sizeof("YP_MASTER_NAME") - 1; + + if (yp_get_record(ypxfr_dest_domain, ypxfr_mapname, + &key, &data, 1) != YP_TRUE) { + yp_error("no source host specified"); + ypxfr_exit(YPXFR_BADARGS,NULL); + } + dptr = data.data; + dptr[data.size] = '\0'; + ypxfr_master = ypxfr_source_host = strdup(dptr); + } + } else { + if (ypxfr_use_yplib) + ypxfr_use_yplib = 0; + } + + if (ypxfr_master == NULL) { + if ((ypxfr_master = ypxfr_get_master(ypxfr_source_domain, + ypxfr_mapname, + ypxfr_source_host, + ypxfr_use_yplib)) == NULL) { + yp_error("failed to find master of %s in domain %s", + ypxfr_mapname, ypxfr_source_domain); + ypxfr_exit(YPXFR_MADDR,NULL); + } + } + + /* + * If we got here and ypxfr_source_host is still undefined, + * it means we had to resort to using yp_master() to find the + * master server for the map. The source host and master should + * be identical. + */ + if (ypxfr_source_host == NULL) + ypxfr_source_host = ypxfr_master; + + if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain, + ypxfr_mapname, + ypxfr_master, 0)) == 0) { + yp_error("failed to get order number of %s", + ypxfr_mapname); + ypxfr_exit(YPXFR_YPERR,NULL); + } + + key.data = "YP_LAST_MODIFIED"; + key.size = sizeof("YP_LAST_MODIFIED") - 1; + + /* The order number is immaterial when the 'force' flag is set. */ + + if (!ypxfr_force) { + int ignore = 0; + if (yp_get_record(ypxfr_dest_domain,ypxfr_mapname,&key,&data,1) != YP_TRUE) { + switch(yp_errno) { + case YP_NOKEY: + ypxfr_exit(YPXFR_FORCE,NULL); + break; + case YP_NOMAP: + /* + * If the map doesn't exist, we're + * creating it. Ignore the error. + */ + ignore++; + break; + case YP_BADDB: + default: + ypxfr_exit(YPXFR_DBM,NULL); + break; + } + } + if (!ignore && ypxfr_order <= atoi(data.data)) + ypxfr_exit(YPXFR_AGE, NULL); + + } + + /* Construct a temporary map file name */ + snprintf(tempmap, sizeof(tempmap), "%s.%d",ypxfr_mapname, getpid()); + snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir, + ypxfr_dest_domain, tempmap); + + /* Open the temporary map read/write. */ + if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap)) == NULL) { + yp_error("failed to open temporary map file"); + ypxfr_exit(YPXFR_DBM,NULL); + } + + /* + * Fill in the keys we already know, such as the order number, + * master name, input file name (we actually make up a bogus + * name for that) and output file name. + */ + snprintf(buf, sizeof(buf), "%d", ypxfr_order); + data.data = buf; + data.size = strlen(buf); + + if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + yp_error("failed to write order number to database"); + ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); + } + + key.data = "YP_MASTER_NAME"; + key.size = sizeof("YP_MASTER_NAME") - 1; + data.data = ypxfr_master; + data.size = strlen(ypxfr_master); + + if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + yp_error("failed to write master name to database"); + ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); + } + + key.data = "YP_DOMAIN_NAME"; + key.size = sizeof("YP_DOMAIN_NAME") - 1; + data.data = ypxfr_dest_domain; + data.size = strlen(ypxfr_dest_domain); + + if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + yp_error("failed to write domain name to database"); + ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); + } + + snprintf (buf, sizeof(buf), "%s:%s", ypxfr_source_host, ypxfr_mapname); + + key.data = "YP_INPUT_NAME"; + key.size = sizeof("YP_INPUT_NAME") - 1; + data.data = &buf; + data.size = strlen(buf); + + if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + yp_error("failed to write input name to database"); + ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); + + } + + snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, + ypxfr_mapname); + + key.data = "YP_OUTPUT_NAME"; + key.size = sizeof("YP_OUTPUT_NAME") - 1; + data.data = &buf; + data.size = strlen(buf); + + if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + yp_error("failed to write output name to database"); + ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); + } + + /* Now suck over the contents of the map from the master. */ + + if (ypxfr_get_map(ypxfr_mapname,ypxfr_source_domain, + ypxfr_source_host, ypxfr_foreach)){ + yp_error("failed to retrieve map from source host"); + ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map); + } + + (void)(dbp->close)(dbp); + + /* Peek at the order number again and check for skew. */ + if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain, + ypxfr_mapname, + ypxfr_master, 0)) == 0) { + yp_error("failed to get order number of %s", + ypxfr_mapname); + ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map); + } + + if (ypxfr_order != ypxfr_skew_check) + ypxfr_exit(YPXFR_SKEW,&ypxfr_temp_map); + + /* + * Send a YPPROC_CLEAR to the local ypserv. + * The FreeBSD ypserv doesn't really need this, but we send it + * here anyway for the sake of consistency. + */ + if (!ypxfr_clear) { + char in = 0; + char *out = NULL; + if (callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, xdr_void, + (void *)&in, xdr_void, (void *)out) == NULL) { + yp_error("failed to send 'clear' to local ypserv"); + ypxfr_exit(YPXFR_YPERR, &ypxfr_temp_map); + } + } + + if (unlink(buf) == -1 && errno != ENOENT) { + yp_error("unlink(%s) failed: %s", buf, strerror(errno)); + ypxfr_exit(YPXFR_FILE,NULL); + } + + if (rename(ypxfr_temp_map, buf) == -1) { + yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf, + strerror(errno)); + ypxfr_exit(YPXFR_FILE,NULL); + } + + ypxfr_exit(YPXFR_SUCC,NULL); + + return(1); +} diff --git a/dist/libexec/ypxfr/ypxfr_misc.c b/dist/libexec/ypxfr/ypxfr_misc.c new file mode 100644 index 0000000..4093dae --- /dev/null +++ b/dist/libexec/ypxfr/ypxfr_misc.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ypxfr_misc.c,v 1.6 1995/12/24 04:39:55 wpaul Exp $ + */ +#include +#include +struct dom_binding {}; +#include +#include "ypxfr_extern.h" + +#ifndef lint +static const char rcsid[] = "$Id: ypxfr_misc.c,v 1.6 1995/12/24 04:39:55 wpaul Exp $"; +#endif + +char *ypxfrerr_string(code) + ypxfrstat code; +{ + switch(code) { + case YPXFR_SUCC: + return ("Map successfully transfered"); + break; + case YPXFR_AGE: + return ("Master's version not newer"); + break; + case YPXFR_NOMAP: + return ("No such map in server's domain"); + break; + case YPXFR_NODOM: + return ("Domain not supported by server"); + break; + case YPXFR_RSRC: + return ("Local resource allocation failure"); + break; + case YPXFR_RPC: + return ("RPC failure talking to server"); + break; + case YPXFR_MADDR: + return ("Could not get master server address"); + break; + case YPXFR_YPERR: + return ("NIS server/map database error"); + break; + case YPXFR_BADARGS: + return ("Request arguments bad"); + break; + case YPXFR_DBM: + return ("Local database operation failed"); + break; + case YPXFR_FILE: + return ("Local file I/O operation failed"); + break; + case YPXFR_SKEW: + return ("Map version skew during transfer"); + break; + case YPXFR_CLEAR: + return ("Couldn't send \"clear\" request to local ypserv"); + break; + case YPXFR_FORCE: + return ("No local order number in map -- use -f flag"); + break; + case YPXFR_XFRERR: + return ("General ypxfr error"); + break; + case YPXFR_REFUSED: + return ("Transfer request refused by ypserv"); + break; + default: + return ("Unknown error code"); + break; + } +} + +/* + * These are wrappers for the usual yp_master() and yp_order() functions. + * They can use either local yplib functions (the real yp_master() and + * yp_order()) or do direct RPCs to a specified server. The latter is + * necessary if ypxfr is run on a machine that isn't configured as an + * NIS client (this can happen very easily: a given machine need not be + * an NIS client in order to be an NIS server). + */ + +char *ypxfr_get_master(domain,map,source,yplib) + char *domain; + char *map; + char *source; + const int yplib; +{ + if (yplib) { + int res; + char *master; + if ((res = yp_master(domain, map, &master))) { + switch (res) { + case YPERR_DOMAIN: + yp_errno = YPXFR_NODOM; + break; + case YPERR_MAP: + yp_errno = YPXFR_NOMAP; + break; + case YPERR_YPERR: + default: + yp_errno = YPXFR_YPERR; + break; + } + return(NULL); + } else + return(master); + } else { + CLIENT *clnt; + ypresp_master *resp; + ypreq_nokey req; + + if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) { + yp_error("%s",clnt_spcreateerror("failed to \ +create udp handle to ypserv")); + yp_errno = YPXFR_RPC; + return(NULL); + } + + req.map = map; + req.domain = domain; + if ((resp = ypproc_master_2(&req, clnt)) == NULL) { + yp_error("%s",clnt_sperror(clnt,"YPPROC_MASTER \ +failed")); + clnt_destroy(clnt); + yp_errno = YPXFR_RPC; + return(NULL); + } + clnt_destroy(clnt); + if (resp->stat != YP_TRUE) { + switch (resp->stat) { + case YP_NODOM: + yp_errno = YPXFR_NODOM; + break; + case YP_NOMAP: + yp_errno = YPXFR_NOMAP; + break; + case YP_YPERR: + default: + yp_errno = YPXFR_YPERR; + break; + } + return(NULL); + } + return(resp->peer); + } +} + +unsigned long ypxfr_get_order(domain, map, source, yplib) + char *domain; + char *map; + char *source; + const int yplib; +{ + if (yplib) { + unsigned long order; + int res; + if ((res = yp_order(domain, map, (int *)&order))) { + switch (res) { + case (YPERR_DOMAIN): + yp_errno = YPXFR_NODOM; + break; + case (YPERR_MAP): + yp_errno = YPXFR_NOMAP; + break; + case (YPERR_YPERR): + default: + yp_errno = YPXFR_YPERR; + break; + } + return(0); + } else + return(order); + } else { + CLIENT *clnt; + ypresp_order *resp; + ypreq_nokey req; + + if ((clnt = clnt_create(source,YPPROG,YPVERS,"udp")) == NULL) { + yp_error("%s",clnt_spcreateerror("couldn't create \ +udp handle to ypserv")); + yp_errno = YPXFR_RPC; + return(0); + } + req.map = map; + req.domain = domain; + if ((resp = ypproc_order_2(&req, clnt)) == NULL) { + yp_error("%s", clnt_sperror(clnt, "YPPROC_ORDER \ +failed")); + clnt_destroy(clnt); + yp_errno = YPXFR_RPC; + return(0); + } + clnt_destroy(clnt); + if (resp->stat != YP_TRUE) { + switch (resp->stat) { + case (YP_NODOM): + yp_errno = YPXFR_NODOM; + break; + case (YP_NOMAP): + yp_errno = YPXFR_NOMAP; + break; + case (YP_YPERR): + default: + yp_errno = YPXFR_YPERR; + break; + } + return(0); + } + return(resp->ordernum); + } +} -- cgit v1.1