From cfa9db5160a6c391b48cdaa5f955af40eb976b74 Mon Sep 17 00:00:00 2001 From: wpaul Date: Wed, 5 Jun 1996 05:42:52 +0000 Subject: Add support for rpc.ypxfrd and document it in the man page. Also generallize the yp_dbwrite functions a little: allow the caller to specify certain flags. I need this mostly for some changes to rpc.yppasswdd to allow in-place updates. Also change Makefile a little to use the same format as ypserv. --- libexec/ypxfr/Makefile | 32 ++++++++--- libexec/ypxfr/yp_dbwrite.c | 18 +++--- libexec/ypxfr/ypxfr.8 | 26 ++++++++- libexec/ypxfr/ypxfr_extern.h | 14 +++-- libexec/ypxfr/ypxfr_getmap.c | 7 ++- libexec/ypxfr/ypxfr_main.c | 37 ++++++++---- libexec/ypxfr/ypxfr_misc.c | 6 +- libexec/ypxfr/ypxfrd_getmap.c | 130 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 230 insertions(+), 40 deletions(-) create mode 100644 libexec/ypxfr/ypxfrd_getmap.c (limited to 'libexec/ypxfr') diff --git a/libexec/ypxfr/Makefile b/libexec/ypxfr/Makefile index 0339aee..b672219 100644 --- a/libexec/ypxfr/Makefile +++ b/libexec/ypxfr/Makefile @@ -2,25 +2,39 @@ 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 + yp_error.c ypxfr_misc.c ypxfr_main.c yp_dbwrite.c \ + ypxfrd_xdr.c ypxfrd_getmap.c .PATH: ${.CURDIR}/../../usr.sbin/ypserv MAN8= ypxfr.8 -CFLAGS+=-I. + +CFLAGS+= -I. +LDADD+= -lrpcsvc CLEANFILES= yp.h yp_clnt.c ypxfr_clnt.c -RPCSRC= ${.DESTDIR}/usr/include/rpcsvc/yp.x +RPCDIR= ${.CURDIR}/../../include/rpcsvc RPCGEN= rpcgen -I -C -ypxfr_clnt.c: ${RPCSRC} yp.h - ${RPCGEN} -DYPPUSH_ONLY -l -o ${.TARGET} ${RPCSRC} +ypxfr_clnt.c: ${RPCDIR}/yp.x yp.h + rm -f ${.TARGET} + ${RPCGEN} -DYPPUSH_ONLY -l -o ${.TARGET} ${RPCDIR}/yp.x + +yp_clnt.c: ${RPCDIR}/yp.x yp.h + rm -f ${.TARGET} + ${RPCGEN} -DYPSERV_ONLY -l -o ${.TARGET} ${RPCDIR}/yp.x + +yp.h: ${RPCDIR}/yp.x + rm -f ${.TARGET} + ${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/yp.x -yp_clnt.c: ${RPCSRC} yp.h - ${RPCGEN} -DYPSERV_ONLY -l -o ${.TARGET} ${RPCSRC} +# ypxfrd_xdr.c: ${RPCDIR}/ypxfrd.x ypxfrd.h +# rm -f ${.TARGET} +# ${RPCGEN} -c -o ${.TARGET} ${RPCDIR}/ypxfrd.x -yp.h: ${RPCSRC} - ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} +ypxfrd.h: ${RPCDIR}/ypxfrd.x + rm -f ${.TARGET} + ${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/ypxfrd.x .include diff --git a/libexec/ypxfr/yp_dbwrite.c b/libexec/ypxfr/yp_dbwrite.c index 8d0c007..2989d2a 100644 --- a/libexec/ypxfr/yp_dbwrite.c +++ b/libexec/ypxfr/yp_dbwrite.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: yp_dbwrite.c,v 1.9 1996/02/04 04:08:11 wpaul Exp wpaul $ + * $Id: yp_dbwrite.c,v 1.10 1996/06/03 03:11:25 wpaul Exp $ * */ #include @@ -46,7 +46,7 @@ #include "ypxfr_extern.h" #ifndef lint -static const char rcsid[] = "$Id: yp_dbwrite.c,v 1.9 1996/02/04 04:08:11 wpaul Exp wpaul $"; +static const char rcsid[] = "$Id: yp_dbwrite.c,v 1.10 1996/06/03 03:11:25 wpaul Exp $"; #endif #define PERM_SECURE (S_IRUSR|S_IWUSR) @@ -54,9 +54,10 @@ static const char rcsid[] = "$Id: yp_dbwrite.c,v 1.9 1996/02/04 04:08:11 wpaul E /* * Open a DB database read/write */ -DB *yp_open_db_rw(domain, map) +DB *yp_open_db_rw(domain, map, flags) const char *domain; const char *map; + const int flags; { DB *dbp; char buf[1025]; @@ -69,9 +70,10 @@ DB *yp_open_db_rw(domain, map) return (NULL); } - snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); +#define FLAGS O_RDWR|O_EXLOCK|O_EXCL|O_CREAT - dbp = dbopen(buf,O_RDWR|O_EXLOCK|O_EXCL|O_CREAT, PERM_SECURE, DB_HASH, &openinfo); + snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); + dbp = dbopen(buf,flags ? flags : FLAGS,PERM_SECURE,DB_HASH,&openinfo); if (dbp == NULL) { switch(errno) { @@ -90,14 +92,16 @@ DB *yp_open_db_rw(domain, map) return (dbp); } -int yp_put_record(dbp,key,data) +int yp_put_record(dbp,key,data,allow_overwrite) DB *dbp; DBT *key; DBT *data; + int allow_overwrite; { int rval; - if ((rval = (dbp->put)(dbp,key,data,R_NOOVERWRITE))) { + if ((rval = (dbp->put)(dbp,key,data, allow_overwrite ? 0 : + R_NOOVERWRITE))) { switch(rval) { case 1: return(YP_FALSE); diff --git a/libexec/ypxfr/ypxfr.8 b/libexec/ypxfr/ypxfr.8 index 188f22b..285c258 100644 --- a/libexec/ypxfr/ypxfr.8 +++ b/libexec/ypxfr/ypxfr.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ypxfr.8,v 1.1.1.1 1995/12/25 03:07:13 wpaul Exp $ +.\" $Id: ypxfr.8,v 1.3 1996/06/05 04:07:04 wpaul Exp $ .\" .Dd February 5, 1995 .Dt YPXFR 8 @@ -122,6 +122,30 @@ is invoked without a controlling terminal, e.g. from inside it logs all its output using the .Xr syslog 3 facility. +.Sh NOTES +The FreeBSD version of +.Nm ypxfr +has support for a special map transfer protocol which works in +conjunction with the FreeBSD +.Xr rpc.ypxfrd 8 +server. This protocol allows it to transfer raw map database files from +the NIS master server and can be many times faster than the standard +transfer method, particularly for very large NIS maps. The +.Nm ypxfr +command will check to see if the +.Xr rpc.ypxfrd 8 +server is registered on the NIS master server and attempt to use +it if it is present. If it isn't it will fall back to the standard +transfer method, copying the map contents from +.Xr ypserv 8 +and creating new maps instead. +.Pp +Note that while the FreeBSD ypxfrd protocol is conceptually similar +to the SunOS ypxfrd protocol, FreeBSD's protocol is not compatible with +Sun's, therefore it will not work with Sun's ypxfrd server. FreeBSD +slave systems can still transfer maps from any non-FreeBSD NIS server, +however they will only be able to take advantage of the faster protocol +if the master server is also running FreeBSD. .Sh OPTIONS The following options and flags are supported by .Nm ypxfr : diff --git a/libexec/ypxfr/ypxfr_extern.h b/libexec/ypxfr/ypxfr_extern.h index b2eda88..b18282e 100644 --- a/libexec/ypxfr/ypxfr_extern.h +++ b/libexec/ypxfr/ypxfr_extern.h @@ -29,12 +29,15 @@ * 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 $ + * $Id: ypxfr_extern.h,v 1.7 1996/06/03 03:10:42 wpaul Exp $ */ #include #include -#include #include +#include + +extern HASHINFO openinfo; +extern BTREEINFO openinfo_b; #ifndef _PATH_YP #define _PATH_YP "/var/yp/" @@ -42,16 +45,17 @@ 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 DB *yp_open_db_rw __P(( const char *, const char *, const int)); +extern void yp_init_dbs __P(( void )); +extern int yp_put_record __P(( DB *, DBT *, DBT * , int )); 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 ypxfrd_get_map __P(( char *, char *, char *, char *)); extern int callrpc __P(( char *, int, int, int, xdrproc_t, char *, xdrproc_t, char *)); diff --git a/libexec/ypxfr/ypxfr_getmap.c b/libexec/ypxfr/ypxfr_getmap.c index bac203c..a73ee5d 100644 --- a/libexec/ypxfr/ypxfr_getmap.c +++ b/libexec/ypxfr/ypxfr_getmap.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ypxfr_getmap.c,v 1.7 1996/02/03 23:09:28 wpaul Exp $ + * $Id: ypxfr_getmap.c,v 1.8 1996/06/02 05:12:24 wpaul Exp $ */ #include #include @@ -40,7 +40,7 @@ #include "ypxfr_extern.h" #ifndef lint -static const char rcsid[] = "$Id: ypxfr_getmap.c,v 1.7 1996/02/03 23:09:28 wpaul Exp $"; +static const char rcsid[] = "$Id: ypxfr_getmap.c,v 1.8 1996/06/02 05:12:24 wpaul Exp $"; #endif extern bool_t xdr_ypresp_all_seq __P(( XDR *, unsigned long * )); @@ -75,7 +75,8 @@ int ypxfr_get_map(map, domain, host, callback) /* 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_error("%s", clnt_spcreateerror("failed to \ +create tcp handle")); yp_errno = YPXFR_YPERR; return(1); } diff --git a/libexec/ypxfr/ypxfr_main.c b/libexec/ypxfr/ypxfr_main.c index cc4e1b4..47684fb 100644 --- a/libexec/ypxfr/ypxfr_main.c +++ b/libexec/ypxfr/ypxfr_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ypxfr_main.c,v 1.15 1996/01/10 17:41:55 wpaul Exp $ + * $Id: ypxfr_main.c,v 1.17 1996/06/03 03:11:39 wpaul Exp $ */ #include #include @@ -47,10 +47,11 @@ #include struct dom_binding {}; #include +#include #include "ypxfr_extern.h" #ifndef lint -static const char rcsid[] = "$Id: ypxfr_main.c,v 1.15 1996/01/10 17:41:55 wpaul Exp $"; +static const char rcsid[] = "$Id: ypxfr_main.c,v 1.17 1996/06/03 03:11:39 wpaul Exp $"; #endif char *progname = "ypxfr"; @@ -86,7 +87,8 @@ static void ypxfr_exit(retval, temp) if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum, 1, timeout, &sock)) == NULL) { - yp_error("%s", clnt_spcreateerror("failed to establish callback handle")); + yp_error("%s", clnt_spcreateerror("failed to \ +establish callback handle")); exit(1); } @@ -136,7 +138,7 @@ int ypxfr_foreach(status, key, keylen, val, vallen, data) dbval.data = val; dbval.size = vallen; - if (yp_put_record(dbp, &dbkey, &dbval) != YP_TRUE) + if (yp_put_record(dbp, &dbkey, &dbval, 0) != YP_TRUE) return(yp_errno); return (0); @@ -374,8 +376,16 @@ the local domain name isn't set"); snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir, ypxfr_dest_domain, tempmap); + if (getrpcport(ypxfr_master, YPXFRD_FREEBSD_PROG, + YPXFRD_FREEBSD_VERS, IPPROTO_TCP)) { + /* Try to send using ypxfrd. If it fails, use old method. */ + if (!ypxfrd_get_map(ypxfr_master, ypxfr_mapname, + ypxfr_source_domain, ypxfr_temp_map)) + goto leave; + } + /* Open the temporary map read/write. */ - if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap)) == NULL) { + if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap, 0)) == NULL) { yp_error("failed to open temporary map file"); ypxfr_exit(YPXFR_DBM,NULL); } @@ -389,7 +399,7 @@ the local domain name isn't set"); data.data = buf; data.size = strlen(buf); - if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write order number to database"); ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); } @@ -399,7 +409,7 @@ the local domain name isn't set"); data.data = ypxfr_master; data.size = strlen(ypxfr_master); - if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write master name to database"); ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); } @@ -409,7 +419,7 @@ the local domain name isn't set"); data.data = ypxfr_dest_domain; data.size = strlen(ypxfr_dest_domain); - if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write domain name to database"); ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); } @@ -421,7 +431,7 @@ the local domain name isn't set"); data.data = &buf; data.size = strlen(buf); - if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write input name to database"); ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); @@ -435,7 +445,7 @@ the local domain name isn't set"); data.data = &buf; data.size = strlen(buf); - if (yp_put_record(dbp, &key, &data) != YP_TRUE) { + if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write output name to database"); ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); } @@ -451,6 +461,11 @@ the local domain name isn't set"); (void)(dbp->close)(dbp); dbp = NULL; /* <- yes, it seems this is necessary. */ +leave: + + snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, + ypxfr_mapname); + /* Peek at the order number again and check for skew. */ if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, @@ -466,8 +481,6 @@ the local domain name isn't set"); /* * 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; diff --git a/libexec/ypxfr/ypxfr_misc.c b/libexec/ypxfr/ypxfr_misc.c index 77183f4..2c0e895 100644 --- a/libexec/ypxfr/ypxfr_misc.c +++ b/libexec/ypxfr/ypxfr_misc.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ypxfr_misc.c,v 1.2 1996/02/04 05:18:44 wpaul Exp $ + * $Id: ypxfr_misc.c,v 1.8 1996/06/02 05:12:00 wpaul Exp $ */ #include #include @@ -41,7 +41,7 @@ struct dom_binding {}; #include "ypxfr_extern.h" #ifndef lint -static const char rcsid[] = "$Id: ypxfr_misc.c,v 1.2 1996/02/04 05:18:44 wpaul Exp $"; +static const char rcsid[] = "$Id: ypxfr_misc.c,v 1.8 1996/06/02 05:12:00 wpaul Exp $"; #endif char *ypxfrerr_string(code) @@ -188,7 +188,7 @@ failed")); return(NULL); } snprintf(mastername, sizeof(mastername), "%s", resp->peer); -/* xdr_free(xdr_ypresp_master, (char *)&resp); */ +/* xdr_free(xdr_ypresp_master, (char *)&resp); */ return((char *)&mastername); } } diff --git a/libexec/ypxfr/ypxfrd_getmap.c b/libexec/ypxfr/ypxfrd_getmap.c new file mode 100644 index 0000000..7af9a52 --- /dev/null +++ b/libexec/ypxfr/ypxfrd_getmap.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1995, 1996 + * 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: ypxfrd_getmap.c,v 1.7 1996/06/02 19:51:33 wpaul Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ypxfr_extern.h" + +#ifndef lint +static const char rcsid[] = "$Id: ypxfrd_getmap.c,v 1.7 1996/06/02 19:51:33 wpaul Exp $"; +#endif + +int fp = 0; + +static bool_t xdr_my_xfr(register XDR *xdrs, xfr *objp) +{ + while(1) { + if (!xdr_xfr(xdrs, objp)) + return(FALSE); + if (objp->ok == TRUE) { + if (write(fp, objp->xfr_u.xfrblock_buf.xfrblock_buf_val, + objp->xfr_u.xfrblock_buf.xfrblock_buf_len) == -1) { + yp_error("write failed: %s", strerror(errno)); + return(FALSE); + } + } + xdr_free(xdr_xfr, (char *)objp); + if (objp->ok == FALSE) { + switch(objp->xfr_u.xfrstat) { + case(XFR_DONE): + return(TRUE); + break; + case(XFR_READ_ERR): + yp_error("got read error from rpc.ypxfrd"); + return(FALSE); + break; + case(XFR_ACCESS): + yp_error("rpc.ypxfrd couldn't access the map"); + return(FALSE); + break; + case(XFR_DENIED): + yp_error("access to map denied by rpc.ypxfrd"); + return(FALSE); + break; + default: + yp_error("got unknown status from rpc.ypxfrd"); + return(FALSE); + break; + } + } + } +} + +#define PERM_SECURE (S_IRUSR|S_IWUSR) + +int ypxfrd_get_map(host, map, domain, tmpname) + char *host; + char *map; + char *domain; + char *tmpname; +{ + CLIENT *clnt; + struct ypxfr_mapname req; + struct xfr resp; + struct timeval timeout = { 0, 25 }; + int status = 0; + + req.xfrmap = map; + req.xfrdomain = domain; + bzero((char *)&resp, sizeof(resp)); + + if ((clnt = clnt_create(host, YPXFRD_FREEBSD_PROG, + YPXFRD_FREEBSD_VERS, "tcp")) == NULL) { + return(1); + } + + if ((fp = open(tmpname, O_RDWR|O_CREAT, PERM_SECURE)) == -1) { + clnt_destroy(clnt); + yp_error("couldn't open %s: %s", tmpname, strerror(errno)); + return(1); + } + + if (clnt_call(clnt,YPXFRD_GETMAP,xdr_ypxfr_mapname,(char *)&req, + xdr_my_xfr, (char *)&resp, timeout) != RPC_SUCCESS) { + yp_error("%s", clnt_sperror(clnt,"call to rpc.ypxfrd failed")); + status++; + unlink(tmpname); + } + + clnt_destroy(clnt); + close(fp); + return(status); +} -- cgit v1.1