Index: head/libexec/ypxfr/ypxfr_getmap.c =================================================================== --- head/libexec/ypxfr/ypxfr_getmap.c (revision 285925) +++ head/libexec/ypxfr/ypxfr_getmap.c (revision 285926) @@ -1,99 +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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "ypxfr_extern.h" extern bool_t xdr_ypresp_all_seq(XDR *, unsigned long *); -int (*ypresp_allfn)(); -void *ypresp_data; +static int (*ypresp_allfn)(); +static void *ypresp_data; extern DB *specdbp; extern enum ypstat 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(char *map, char *domain, char *host, int (*callback)(int, char *, int, char *, int, char*)) { 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 \ create tcp handle")); yp_errno = (enum ypstat)YPXFR_YPERR; return(1); } req.domain = domain; req.map = map; ypresp_allfn = callback; ypresp_data = NULL; (void)clnt_call(clnt, YPPROC_ALL, (xdrproc_t)xdr_ypreq_nokey, &req, (xdrproc_t)xdr_ypresp_all_seq, &status, timeout); clnt_destroy(clnt); if (status == YP_NOMORE) return(0); if (status != YP_TRUE) { yp_errno = (enum ypstat)YPXFR_YPERR; return(1); } return(0); } Index: head/libexec/ypxfr/ypxfr_main.c =================================================================== --- head/libexec/ypxfr/ypxfr_main.c (revision 285925) +++ head/libexec/ypxfr/ypxfr_main.c (revision 285926) @@ -1,577 +1,577 @@ /* * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ypxfr_extern.h" 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 int ypxfr_use_yplib = 0; /* Assume the worst. */ +static int ypxfr_clear = 1; +static int ypxfr_prognum = 0; +static struct sockaddr_in ypxfr_callback_addr; +static struct yppushresp_xfr ypxfr_resp; +static DB *dbp; static void ypxfr_exit(ypxfrstat retval, char *temp) { CLIENT *clnt; int sock = RPC_ANYSOCK; struct timeval timeout; /* Clean up no matter what happened previously. */ if (temp != NULL) { if (dbp != NULL) (void)(dbp->close)(dbp); if (unlink(temp) == -1) { yp_error("failed to unlink %s",strerror(errno)); } } if (ypxfr_prognum) { 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 = (yppush_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(void) { if (_rpcpmstart) { ypxfr_exit(YPXFR_BADARGS,NULL); } else { fprintf(stderr, "%s\n%s\n%s\n", "usage: ypxfr [-f] [-c] [-d target domain] [-h source host]", " [-s source domain] [-p path]", " [-C taskid program-number ipaddr port] mapname"); exit(1); } } int ypxfr_foreach(int status, char *key, int keylen, char *val, int vallen, char *data) { DBT dbkey, dbval; if (status != YP_TRUE) return (status); /* * XXX Do not attempt to write zero-length keys or * data into a Berkeley DB hash database. It causes a * strange failure mode where sequential searches get * caught in an infinite loop. */ if (keylen) { dbkey.data = key; dbkey.size = keylen; } else { dbkey.data = ""; dbkey.size = 1; } if (vallen) { dbval.data = val; dbval.size = vallen; } else { dbval.data = ""; dbval.size = 1; } if (yp_put_record(dbp, &dbkey, &dbval, 0) != YP_TRUE) return(yp_errno); return (0); } int main(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; int remoteport; int interdom = 0; int secure = 0; debug = 1; if (!isatty(fileno(stderr))) { openlog("ypxfr", LOG_PID, LOG_DAEMON); _rpcpmstart = 1; } if (argc < 2) usage(); while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != -1) { 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: %s", ypxfr_mapname, ypxfr_source_domain, ypxfrerr_string((ypxfrstat)yp_errno)); 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; /* * Don't talk to ypservs on unprivileged ports. */ remoteport = getrpcport(ypxfr_source_host, YPPROG, YPVERS, IPPROTO_UDP); if (remoteport >= IPPORT_RESERVED) { yp_error("ypserv on %s not running on reserved port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,NULL); } if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_INTERDOMAIN", sizeof("YP_INTERDOMAIN") - 1)) interdom++; if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_SECURE", sizeof("YP_SECURE") - 1)) secure++; 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); if ((remoteport = getrpcport(ypxfr_source_host, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, IPPROTO_TCP))) { /* Don't talk to rpc.ypxfrds on unprovileged ports. */ if (remoteport >= IPPORT_RESERVED) { yp_error("rpc.ypxfrd on %s not using privileged port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } /* Try to send using ypxfrd. If it fails, use old method. */ if (!ypxfrd_get_map(ypxfr_source_host, 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, 0)) == 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), "%lu", ypxfr_order); data.data = buf; data.size = strlen(buf); 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); } 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, 0) != 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, 0) != 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, 0) != 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, 0) != YP_TRUE) { yp_error("failed to write output name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } if (interdom) { key.data = "YP_INTERDOMAIN"; key.size = sizeof("YP_INTERDOMAIN") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add interdomain flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } if (secure) { key.data = "YP_SECURE"; key.size = sizeof("YP_SECURE") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add secure flag 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); 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, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); 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. */ if (ypxfr_clear) { char in = 0; char *out = NULL; int stat; if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, (xdrproc_t)xdr_void, (void *)&in, (xdrproc_t)xdr_void, (void *)out)) != RPC_SUCCESS) { yp_error("failed to send 'clear' to local ypserv: %s", clnt_sperrno((enum clnt_stat) stat)); ypxfr_exit(YPXFR_CLEAR, ypxfr_temp_map); } } /* * Put the new map in place immediately. I'm not sure if the * kernel does an unlink() and rename() atomically in the event * that we move a new copy of a map over the top of an existing * one, but there's less chance of a race condition happening * than if we were to do the unlink() ourselves. */ 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); } Index: head/libexec/ypxfr/ypxfrd_getmap.c =================================================================== --- head/libexec/ypxfr/ypxfrd_getmap.c (revision 285925) +++ head/libexec/ypxfr/ypxfrd_getmap.c (revision 285926) @@ -1,144 +1,144 @@ /* * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "ypxfr_extern.h" -int fp = 0; +static 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((xdrproc_t)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; case(XFR_DB_TYPE_MISMATCH): yp_error("client/server DB type mismatch"); return(FALSE); break; case(XFR_DB_ENDIAN_MISMATCH): yp_error("client/server byte order mismatch"); 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(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; req.xfrmap_filename = ""; req.xfr_db_type = XFR_DB_BSD_HASH; /* req.xfr_byte_order = XFR_ENDIAN_ANY; * Berkeley DB isn't * byte-order sensitive. */ 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, (xdrproc_t)xdr_ypxfr_mapname, (char *)&req, (xdrproc_t)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); } Index: head/usr.bin/ypcat/ypcat.c =================================================================== --- head/usr.bin/ypcat/ypcat.c (revision 285925) +++ head/usr.bin/ypcat/ypcat.c (revision 285926) @@ -1,143 +1,143 @@ /* * Copyright (c) 1992/3 Theo de Raadt * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include -struct ypalias { +const struct ypalias { char *alias, *name; -} ypaliases[] = { +} static ypaliases[] = { { "passwd", "passwd.byname" }, { "master.passwd", "master.passwd.byname" }, { "shadow", "shadow.byname" }, { "group", "group.byname" }, { "networks", "networks.byaddr" }, { "hosts", "hosts.byaddr" }, { "protocols", "protocols.bynumber" }, { "services", "services.byname" }, { "aliases", "mail.aliases" }, { "ethers", "ethers.byname" }, }; -int key; +static int key; static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: ypcat [-kt] [-d domainname] mapname", " ypcat -x"); exit(1); } static int printit(unsigned long instatus, char *inkey, int inkeylen, char *inval, int invallen, void *dummy __unused) { if (instatus != YP_TRUE) return (instatus); if (key) printf("%*.*s ", inkeylen, inkeylen, inkey); printf("%*.*s\n", invallen, invallen, inval); return (0); } int main(int argc, char *argv[]) { char *domainname = NULL; struct ypall_callback ypcb; char *inmap; int notrans; int c, r; u_int i; notrans = key = 0; while ((c = getopt(argc, argv, "xd:kt")) != -1) switch (c) { case 'x': for (i = 0; i * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include -struct ypalias { +const struct ypalias { char *alias, *name; -} ypaliases[] = { +} static ypaliases[] = { { "passwd", "passwd.byname" }, { "master.passwd", "master.passwd.byname" }, { "shadow", "shadow.byname" }, { "group", "group.byname" }, { "networks", "networks.byaddr" }, { "hosts", "hosts.byname" }, { "protocols", "protocols.bynumber" }, { "services", "services.byname" }, { "aliases", "mail.aliases" }, { "ethers", "ethers.byname" }, }; static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: ypmatch [-kt] [-d domainname] key ... mapname", " ypmatch -x"); exit(1); } int main(int argc, char *argv[]) { char *domainname = NULL; char *inkey, *inmap, *outbuf; int outbuflen, key, notrans; int c, r; u_int i; notrans = key = 0; while ((c = getopt(argc, argv, "xd:kt")) != -1) switch (c) { case 'x': for (i = 0; i * 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ERR_USAGE 1 /* bad arguments - display 'usage' message */ #define ERR_NOSUCHHOST 2 /* no such host */ #define ERR_NOBINDING 3 /* error from ypbind -- domain not bound */ #define ERR_NOYPBIND 4 /* ypbind not running */ #define ERR_NOMASTER 5 /* could not find master server */ extern bool_t xdr_domainname(); -struct ypalias { +const struct ypalias { char *alias, *name; -} ypaliases[] = { +} static ypaliases[] = { { "passwd", "passwd.byname" }, { "master.passwd", "master.passwd.byname" }, { "shadow", "shadow.byname" }, { "group", "group.byname" }, { "networks", "networks.byaddr" }, { "hosts", "hosts.byaddr" }, { "protocols", "protocols.bynumber" }, { "services", "services.byname" }, { "aliases", "mail.aliases" }, { "ethers", "ethers.byname" }, }; static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: ypwhich [-d domain] [[-t] -m [mname] | host]", " ypwhich -x"); exit(ERR_USAGE); } /* * Like yp_bind except can query a specific host */ static int bind_host(char *dom, struct sockaddr_in *lsin) { struct hostent *hent = NULL; struct ypbind_resp ypbr; struct timeval tv; CLIENT *client; int sock, r; struct in_addr ss_addr; sock = RPC_ANYSOCK; tv.tv_sec = 15; tv.tv_usec = 0; client = clntudp_create(lsin, YPBINDPROG, YPBINDVERS, tv, &sock); if (client == NULL) { warnx("can't clntudp_create: %s", yperr_string(YPERR_YPBIND)); return (YPERR_YPBIND); } tv.tv_sec = 5; tv.tv_usec = 0; r = clnt_call(client, YPBINDPROC_DOMAIN, (xdrproc_t)xdr_domainname, &dom, (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); if (r != RPC_SUCCESS) { warnx("can't clnt_call: %s", yperr_string(YPERR_YPBIND)); clnt_destroy(client); return (YPERR_YPBIND); } else { if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { warnx("can't yp_bind: reason: %s", ypbinderr_string(ypbr.ypbind_respbody.ypbind_error)); clnt_destroy(client); return (r); } } clnt_destroy(client); ss_addr = ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr; /*printf("%08x\n", ss_addr);*/ hent = gethostbyaddr((char *)&ss_addr, sizeof(ss_addr), AF_INET); if (hent) printf("%s\n", hent->h_name); else printf("%s\n", inet_ntoa(ss_addr)); return (0); } int main(int argc, char *argv[]) { char *domnam = NULL, *master; char *map = NULL; struct ypmaplist *ypml, *y; struct hostent *hent; struct sockaddr_in lsin; int notrans, mode; int c, r; u_int i; notrans = mode = 0; while ((c = getopt(argc, argv, "xd:mt")) != -1) switch (c) { case 'x': for (i = 0; ih_addr_list[0], (char *)&lsin.sin_addr, sizeof lsin.sin_addr); } if (bind_host(domnam, &lsin)) exit(ERR_NOBINDING); break; default: usage(); } exit(0); } if (argc-optind > 1) usage(); if (argv[optind]) { map = argv[optind]; for (i = 0; (!notrans) && iypml_name, &master); switch (r) { case 0: printf("%s %s\n", ypml->ypml_name, master); free(master); break; default: warnx("can't find the master of %s: reason: %s", ypml->ypml_name, yperr_string(r)); break; } y = ypml->ypml_next; free(ypml); } break; case YPERR_YPBIND: errx(ERR_NOYPBIND, "not running ypbind"); default: errx(ERR_NOMASTER, "can't get map list for domain %s: reason: %s", domnam, yperr_string(r)); } exit(0); } Index: head/usr.sbin/yp_mkdb/yp_mkdb.c =================================================================== --- head/usr.sbin/yp_mkdb/yp_mkdb.c (revision 285925) +++ head/usr.sbin/yp_mkdb/yp_mkdb.c (revision 285926) @@ -1,344 +1,340 @@ /* * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "yp_extern.h" #include "ypxfr_extern.h" char *yp_dir = ""; /* No particular default needed. */ -int _rpcpmstart = 0; int debug = 1; static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n", "usage: yp_mkdb -c", " yp_mkdb -u dbname", " yp_mkdb [-c] [-b] [-s] [-f] [-i inputfile] [-o outputfile]", " [-d domainname ] [-m mastername] inputfile dbname"); exit(1); } #define PERM_SECURE (S_IRUSR|S_IWUSR) - static DB * open_db(char *path, int flags) { extern HASHINFO openinfo; return(dbopen(path, flags, PERM_SECURE, DB_HASH, &openinfo)); } static void unwind(char *map) { DB *dbp; DBT key, data; dbp = open_db(map, O_RDONLY); if (dbp == NULL) err(1, "open_db(%s) failed", map); key.data = NULL; while (yp_next_record(dbp, &key, &data, 1, 1) == YP_TRUE) printf("%.*s %.*s\n", (int)key.size, key.data, (int)data.size, data.data); (void)(dbp->close)(dbp); return; } int main(int argc, char *argv[]) { int ch; int un = 0; int clear = 0; int filter_plusminus = 0; char *infile = NULL; char *map = NULL; char *domain = NULL; char *infilename = NULL; char *outfilename = NULL; char *mastername = NULL; int interdom = 0; int secure = 0; DB *dbp; DBT key, data; char buf[10240]; char *keybuf, *datbuf; FILE *ifp; char hname[MAXHOSTNAMELEN + 2]; while ((ch = getopt(argc, argv, "uhcbsfd:i:o:m:")) != -1) { switch (ch) { case 'f': filter_plusminus++; break; case 'u': un++; break; case 'c': clear++; break; case 'b': interdom++; break; case 's': secure++; break; case 'd': domain = optarg; break; case 'i': infilename = optarg; break; case 'o': outfilename = optarg; break; case 'm': mastername = optarg; break; case 'h': default: usage(); break; } } argc -= optind; argv += optind; if (un) { map = argv[0]; if (map == NULL) usage(); unwind(map); exit(0); } infile = argv[0]; map = argv[1]; if (infile == NULL || map == NULL) { if (clear) goto doclear; usage(); } if (mastername == NULL) { if (gethostname((char *)&hname, sizeof(hname)) == -1) err(1, "gethostname() failed"); mastername = (char *)&hname; } /* * Note that while we can read from stdin, we can't * write to stdout; the db library doesn't let you * write to a file stream like that. */ - if (!strcmp(infile, "-")) { ifp = stdin; } else { if ((ifp = fopen(infile, "r")) == NULL) err(1, "failed to open %s", infile); } if ((dbp = open_db(map, O_RDWR|O_EXLOCK|O_EXCL|O_CREAT)) == NULL) err(1, "open_db(%s) failed", map); if (interdom) { key.data = "YP_INTERDOMAIN"; key.size = sizeof("YP_INTERDOMAIN") - 1; data.data = ""; data.size = 0; yp_put_record(dbp, &key, &data, 0); } if (secure) { key.data = "YP_SECURE"; key.size = sizeof("YP_SECURE") - 1; data.data = ""; data.size = 0; yp_put_record(dbp, &key, &data, 0); } key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; data.data = mastername; data.size = strlen(mastername); yp_put_record(dbp, &key, &data, 0); key.data = "YP_LAST_MODIFIED"; key.size = sizeof("YP_LAST_MODIFIED") - 1; snprintf(buf, sizeof(buf), "%jd", (intmax_t)time(NULL)); data.data = (char *)&buf; data.size = strlen(buf); yp_put_record(dbp, &key, &data, 0); if (infilename) { key.data = "YP_INPUT_FILE"; key.size = sizeof("YP_INPUT_FILE") - 1; data.data = infilename; data.size = strlen(infilename); yp_put_record(dbp, &key, &data, 0); } if (outfilename) { key.data = "YP_OUTPUT_FILE"; key.size = sizeof("YP_OUTPUT_FILE") - 1; data.data = outfilename; data.size = strlen(outfilename); yp_put_record(dbp, &key, &data, 0); } if (domain) { key.data = "YP_DOMAIN_NAME"; key.size = sizeof("YP_DOMAIN_NAME") - 1; data.data = domain; data.size = strlen(domain); yp_put_record(dbp, &key, &data, 0); } while (fgets((char *)&buf, sizeof(buf), ifp)) { char *sep = NULL; int rval; /* NUL terminate */ if ((sep = strchr(buf, '\n'))) *sep = '\0'; /* handle backslash line continuations */ while (buf[strlen(buf) - 1] == '\\') { fgets((char *)&buf[strlen(buf) - 1], sizeof(buf) - strlen(buf), ifp); if ((sep = strchr(buf, '\n'))) *sep = '\0'; } /* find the separation between the key and data */ if ((sep = strpbrk(buf, " \t")) == NULL) { warnx("bad input -- no white space: %s", buf); continue; } /* separate the strings */ keybuf = (char *)&buf; datbuf = sep + 1; *sep = '\0'; /* set datbuf to start at first non-whitespace character */ while (*datbuf == ' ' || *datbuf == '\t') datbuf++; /* Check for silliness. */ if (filter_plusminus) { if (*keybuf == '+' || *keybuf == '-' || *datbuf == '+' || *datbuf == '-') { warnx("bad character at " "start of line: %s", buf); continue; } } if (strlen(keybuf) > YPMAXRECORD) { warnx("key too long: %s", keybuf); continue; } if (!strlen(keybuf)) { warnx("no key -- check source file for blank lines"); continue; } if (strlen(datbuf) > YPMAXRECORD) { warnx("data too long: %s", datbuf); continue; } key.data = keybuf; key.size = strlen(keybuf); data.data = datbuf; data.size = strlen(datbuf); if ((rval = yp_put_record(dbp, &key, &data, 0)) != YP_TRUE) { switch (rval) { case YP_FALSE: warnx("duplicate key '%s' - skipping", keybuf); break; case YP_BADDB: default: err(1,"failed to write new record - exiting"); break; } } } (void)(dbp->close)(dbp); doclear: - if (clear) { char in = 0; char *out = NULL; int stat; if ((stat = callrpc("localhost", YPPROG,YPVERS, YPPROC_CLEAR, (xdrproc_t)xdr_void, &in, (xdrproc_t)xdr_void, out)) != RPC_SUCCESS) { warnx("failed to send 'clear' to local ypserv: %s", clnt_sperrno((enum clnt_stat) stat)); } } exit(0); } Index: head/usr.sbin/yppush/yppush_main.c =================================================================== --- head/usr.sbin/yppush/yppush_main.c (revision 285925) +++ head/usr.sbin/yppush/yppush_main.c (revision 285926) @@ -1,620 +1,620 @@ /* * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ypxfr_extern.h" #include "yppush_extern.h" char *progname = "yppush"; int debug = 1; int _rpcpmstart = 0; char *yp_dir = _PATH_YP; -char *yppush_mapname = NULL; /* Map to transfer. */ -char *yppush_domain = NULL; /* Domain in which map resides. */ -char *yppush_master = NULL; /* Master NIS server for said domain. */ -int skip_master = 0; /* Do not attempt to push map to master. */ -int verbose = 0; /* Toggle verbose mode. */ -unsigned long yppush_transid = 0; -int yppush_timeout = 80; /* Default timeout. */ -int yppush_jobs = 1; /* Number of allowed concurrent jobs. */ -int yppush_running_jobs = 0; /* Number of currently running jobs. */ +static char *yppush_mapname = NULL; /* Map to transfer. */ +static char *yppush_domain = NULL; /* Domain in which map resides. */ +static char *yppush_master = NULL; /* Master NIS server for said domain. */ +static int skip_master = 0; /* Do not attempt to push map to master. */ +static int verbose = 0; /* Toggle verbose mode. */ +static unsigned long yppush_transid = 0; +static int yppush_timeout = 80; /* Default timeout. */ +static int yppush_jobs = 1; /* Number of allowed concurrent jobs. */ +static int yppush_running_jobs = 0; /* Number of currently running jobs. */ /* Structure for holding information about a running job. */ struct jobs { unsigned long tid; int port; ypxfrstat stat; unsigned long prognum; char *server; char *map; int polled; struct jobs *next; }; -struct jobs *yppush_joblist; /* Linked list of running jobs. */ - +static struct jobs *yppush_joblist; /* Linked list of running jobs. */ static int yppush_svc_run(int); /* * Local error messages. */ static const char * yppusherr_string(int err) { switch (err) { case YPPUSH_TIMEDOUT: return("transfer or callback timed out"); case YPPUSH_YPSERV: return("failed to contact ypserv"); case YPPUSH_NOHOST: return("no such host"); case YPPUSH_PMAP: return("portmapper failure"); default: return("unknown error code"); } } /* * Report state of a job. */ static int yppush_show_status(ypxfrstat status, unsigned long tid) { struct jobs *job; job = yppush_joblist; while (job != NULL) { if (job->tid == tid) break; job = job->next; } if (job == NULL) { yp_error("warning: received callback with invalid transaction ID: %lu", tid); return (0); } if (job->polled) { yp_error("warning: received callback with duplicate transaction ID: %lu", tid); return (0); } if (verbose > 1) { yp_error("checking return status: transaction ID: %lu", job->tid); } if (status != YPXFR_SUCC || verbose) { yp_error("transfer of map %s to server %s %s", job->map, job->server, status == YPXFR_SUCC ? "succeeded" : "failed"); yp_error("status returned by ypxfr: %s", status > YPXFR_AGE ? yppusherr_string(status) : ypxfrerr_string(status)); } job->polled = 1; svc_unregister(job->prognum, 1); yppush_running_jobs--; return(0); } /* Exit routine. */ static void yppush_exit(int now) { struct jobs *jptr; int still_pending = 1; /* Let all the information trickle in. */ while (!now && still_pending) { jptr = yppush_joblist; still_pending = 0; while (jptr) { if (jptr->polled == 0) { still_pending++; if (verbose > 1) yp_error("%s has not responded", jptr->server); } else { if (verbose > 1) yp_error("%s has responded", jptr->server); } jptr = jptr->next; } if (still_pending) { if (verbose > 1) yp_error("%d transfer%sstill pending", still_pending, still_pending > 1 ? "s " : " "); if (yppush_svc_run (YPPUSH_RESPONSE_TIMEOUT) == 0) { yp_error("timed out"); now = 1; } } else { if (verbose) yp_error("all transfers complete"); break; } } /* All stats collected and reported -- kill all the stragglers. */ jptr = yppush_joblist; while (jptr) { if (!jptr->polled) yp_error("warning: exiting with transfer \ to %s (transid = %lu) still pending", jptr->server, jptr->tid); svc_unregister(jptr->prognum, 1); jptr = jptr->next; } exit(0); } /* * Handler for 'normal' signals. */ static void handler(int sig) { yppush_exit (1); return; } /* * Dispatch loop for callback RPC services. * Return value: * -1 error * 0 timeout * >0 request serviced */ static int yppush_svc_run(int timeout_secs) { int rc; fd_set readfds; struct timeval timeout; timeout.tv_usec = 0; timeout.tv_sec = timeout_secs; retry: readfds = svc_fdset; rc = select(svc_maxfd + 1, &readfds, NULL, NULL, &timeout); switch (rc) { case -1: if (errno == EINTR) goto retry; yp_error("select failed: %s", strerror(errno)); break; case 0: yp_error("select() timed out"); break; default: svc_getreqset(&readfds); break; } return rc; } /* * RPC service routines for callbacks. */ void * yppushproc_null_1_svc(void *argp, struct svc_req *rqstp) { static char * result; /* Do nothing -- RPC conventions call for all a null proc. */ return((void *) &result); } void * yppushproc_xfrresp_1_svc(yppushresp_xfr *argp, struct svc_req *rqstp) { static char * result; yppush_show_status(argp->status, argp->transid); return((void *) &result); } /* * Transmit a YPPROC_XFR request to ypserv. */ static int yppush_send_xfr(struct jobs *job) { ypreq_xfr req; /* ypresp_xfr *resp; */ DBT key, data; CLIENT *clnt; struct rpc_err err; struct timeval timeout; timeout.tv_usec = 0; timeout.tv_sec = 0; /* * The ypreq_xfr structure has a member of type map_parms, * which seems to require the order number of the map. * It isn't actually used at the other end (at least the * FreeBSD ypserv doesn't use it) but we fill it in here * for the sake of completeness. */ key.data = "YP_LAST_MODIFIED"; key.size = sizeof ("YP_LAST_MODIFIED") - 1; if (yp_get_record(yppush_domain, yppush_mapname, &key, &data, 1) != YP_TRUE) { yp_error("failed to read order number from %s: %s: %s", yppush_mapname, yperr_string(yp_errno), strerror(errno)); return(1); } /* Fill in the request arguments */ req.map_parms.ordernum = atoi(data.data); req.map_parms.domain = yppush_domain; req.map_parms.peer = yppush_master; req.map_parms.map = job->map; req.transid = job->tid; req.prog = job->prognum; req.port = job->port; /* Get a handle to the remote ypserv. */ if ((clnt = clnt_create(job->server, YPPROG, YPVERS, "udp")) == NULL) { yp_error("%s: %s",job->server,clnt_spcreateerror("couldn't \ create udp handle to NIS server")); switch (rpc_createerr.cf_stat) { case RPC_UNKNOWNHOST: job->stat = YPPUSH_NOHOST; break; case RPC_PMAPFAILURE: job->stat = YPPUSH_PMAP; break; default: job->stat = YPPUSH_RPC; break; } return(1); } /* * Reduce timeout to nothing since we may not * get a response from ypserv and we don't want to block. */ if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) yp_error("failed to set timeout on ypproc_xfr call"); /* Invoke the ypproc_xfr service. */ if (ypproc_xfr_2(&req, clnt) == NULL) { clnt_geterr(clnt, &err); if (err.re_status != RPC_SUCCESS && err.re_status != RPC_TIMEDOUT) { yp_error("%s: %s", job->server, clnt_sperror(clnt, "yp_xfr failed")); job->stat = YPPUSH_YPSERV; clnt_destroy(clnt); return(1); } } clnt_destroy(clnt); return(0); } /* * Main driver function. Register the callback service, add the transfer * request to the internal list, send the YPPROC_XFR request to ypserv * do other magic things. */ static int yp_push(char *server, char *map, unsigned long tid) { unsigned long prognum; int sock = RPC_ANYSOCK; SVCXPRT *xprt; struct jobs *job; /* Register the job in our linked list of jobs. */ /* First allocate job structure */ if ((job = (struct jobs *)malloc(sizeof (struct jobs))) == NULL) { yp_error("malloc failed"); yppush_exit (1); } /* * Register the callback service on the first free transient * program number. */ xprt = svcudp_create(sock); for (prognum = 0x40000000; prognum < 0x5FFFFFFF; prognum++) { if (svc_register(xprt, prognum, 1, yppush_xfrrespprog_1, IPPROTO_UDP) == TRUE) break; } if (prognum == 0x5FFFFFFF) { yp_error ("can't register yppush_xfrrespprog_1"); yppush_exit (1); } /* Initialize the info for this job. */ job->stat = 0; job->tid = tid; job->port = xprt->xp_port; job->server = strdup(server); job->map = strdup(map); job->prognum = prognum; job->polled = 0; job->next = yppush_joblist; yppush_joblist = job; if (verbose) { yp_error("initiating transfer: %s -> %s (transid = %lu)", yppush_mapname, server, tid); } /* * Send the XFR request to ypserv. We don't have to wait for * a response here since we handle them asynchronously. */ if (yppush_send_xfr(job)){ /* Transfer request blew up. */ yppush_show_status(job->stat ? job->stat : YPPUSH_YPSERV,job->tid); } else { if (verbose > 1) yp_error("%s has been called", server); } return(0); } /* * Called for each entry in the ypservers map from yp_get_map(), which * is our private yp_all() routine. */ static int yppush_foreach(int status, char *key, int keylen, char *val, int vallen, char *data) { char server[YPMAXRECORD + 2]; if (status != YP_TRUE) return (status); snprintf(server, sizeof(server), "%.*s", vallen, val); if (skip_master && strcasecmp(server, yppush_master) == 0) return (0); /* * Restrict the number of concurrent jobs: if yppush_jobs number * of jobs have already been dispatched and are still pending, * wait for one of them to finish so we can reuse its slot. */ while (yppush_running_jobs >= yppush_jobs && (yppush_svc_run (yppush_timeout) > 0)) ; /* Cleared for takeoff: set everything in motion. */ if (yp_push(server, yppush_mapname, yppush_transid)) return(yp_errno); /* Bump the job counter and transaction ID. */ yppush_running_jobs++; yppush_transid++; return (0); } -static void usage() +static void +usage() { fprintf (stderr, "%s\n%s\n", "usage: yppush [-d domain] [-t timeout] [-j #parallel jobs] [-h host]", " [-p path] mapname"); exit(1); } /* * Entry point. (About time!) */ int main(int argc, char *argv[]) { int ch; DBT key, data; char myname[MAXHOSTNAMELEN]; struct hostlist { char *name; struct hostlist *next; }; struct hostlist *yppush_hostlist = NULL; struct hostlist *tmp; while ((ch = getopt(argc, argv, "d:j:p:h:t:v")) != -1) { switch (ch) { case 'd': yppush_domain = optarg; break; case 'j': yppush_jobs = atoi(optarg); if (yppush_jobs <= 0) yppush_jobs = 1; break; case 'p': yp_dir = optarg; break; case 'h': /* we can handle multiple hosts */ if ((tmp = (struct hostlist *)malloc(sizeof(struct hostlist))) == NULL) { yp_error("malloc failed"); yppush_exit(1); } tmp->name = strdup(optarg); tmp->next = yppush_hostlist; yppush_hostlist = tmp; break; case 't': yppush_timeout = atoi(optarg); break; case 'v': verbose++; break; default: usage(); break; } } argc -= optind; argv += optind; yppush_mapname = argv[0]; if (yppush_mapname == NULL) { /* "No guts, no glory." */ usage(); } /* * If no domain was specified, try to find the default * domain. If we can't find that, we're doomed and must bail. */ if (yppush_domain == NULL) { char *yppush_check_domain; if (!yp_get_default_domain(&yppush_check_domain) && !_yp_check(&yppush_check_domain)) { yp_error("no domain specified and NIS not running"); usage(); } else yp_get_default_domain(&yppush_domain); } /* Check to see that we are the master for this map. */ if (gethostname ((char *)&myname, sizeof(myname))) { yp_error("failed to get name of local host: %s", strerror(errno)); yppush_exit(1); } key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; if (yp_get_record(yppush_domain, yppush_mapname, &key, &data, 1) != YP_TRUE) { yp_error("couldn't open %s map: %s", yppush_mapname, strerror(errno)); yppush_exit(1); } if (strncasecmp(myname, data.data, data.size) == 0) { /* I am master server, and no explicit host list was specified: do not push map to myself -- this will fail with YPPUSH_AGE anyway. */ if (yppush_hostlist == NULL) skip_master = 1; } else { yp_error("warning: this host is not the master for %s", yppush_mapname); #ifdef NITPICKY yppush_exit(1); #endif } yppush_master = malloc(data.size + 1); strncpy(yppush_master, data.data, data.size); yppush_master[data.size] = '\0'; /* Install some handy handlers. */ signal(SIGTERM, handler); signal(SIGINT, handler); /* set initial transaction ID */ yppush_transid = time((time_t *)NULL); if (yppush_hostlist) { /* * Host list was specified on the command line: * kick off the transfers by hand. */ tmp = yppush_hostlist; while (tmp) { yppush_foreach(YP_TRUE, NULL, 0, tmp->name, strlen(tmp->name), NULL); tmp = tmp->next; } } else { /* * Do a yp_all() on the ypservers map and initiate a ypxfr * for each one. */ ypxfr_get_map("ypservers", yppush_domain, "localhost", yppush_foreach); } if (verbose > 1) yp_error("all jobs dispatched"); /* All done -- normal exit. */ yppush_exit(0); /* Just in case. */ exit(0); } Index: head/usr.sbin/ypserv/yp_access.c =================================================================== --- head/usr.sbin/ypserv/yp_access.c (revision 285925) +++ head/usr.sbin/ypserv/yp_access.c (revision 285926) @@ -1,334 +1,334 @@ /* * 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. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "yp_extern.h" #ifdef TCP_WRAPPER #include "tcpd.h" #endif extern int debug; - /* NIS v1 */ -const char *yp_procs[] = { +static const char *yp_procs[] = { + /* NIS v1 */ "ypoldproc_null", "ypoldproc_domain", "ypoldproc_domain_nonack", "ypoldproc_match", "ypoldproc_first", "ypoldproc_next", "ypoldproc_poll", "ypoldproc_push", "ypoldproc_get", "badproc1", /* placeholder */ "badproc2", /* placeholder */ "badproc3", /* placeholder */ - + /* NIS v2 */ "ypproc_null", "ypproc_domain", "ypproc_domain_nonack", "ypproc_match", "ypproc_first", "ypproc_next", "ypproc_xfr", "ypproc_clear", "ypproc_all", "ypproc_master", "ypproc_order", "ypproc_maplist" }; struct securenet { struct in_addr net; struct in_addr mask; struct securenet *next; }; -struct securenet *securenets; +static struct securenet *securenets; #define LINEBUFSZ 1024 #ifdef TCP_WRAPPER int hosts_ctl(char *, char *, char *, char *); #endif /* * Read /var/yp/securenets file and initialize the securenets * list. If the file doesn't exist, we set up a dummy entry that * allows all hosts to connect. */ void load_securenets(void) { FILE *fp; char path[MAXPATHLEN + 2]; char linebuf[1024 + 2]; struct securenet *tmp; /* * If securenets is not NULL, we are being called to reload * the list; free the existing list before re-reading the * securenets file. */ while (securenets) { tmp = securenets->next; free(securenets); securenets = tmp; } snprintf(path, MAXPATHLEN, "%s/securenets", yp_dir); if ((fp = fopen(path, "r")) == NULL) { if (errno == ENOENT) { securenets = (struct securenet *)malloc(sizeof(struct securenet)); securenets->net.s_addr = INADDR_ANY; securenets->mask.s_addr = INADDR_ANY; securenets->next = NULL; return; } else { yp_error("fopen(%s) failed: %s", path, strerror(errno)); exit(1); } } securenets = NULL; while (fgets(linebuf, LINEBUFSZ, fp)) { char addr1[20], addr2[20]; if ((linebuf[0] == '#') || (strspn(linebuf, " \t\r\n") == strlen(linebuf))) continue; if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) { yp_error("badly formatted securenets entry: %s", linebuf); continue; } tmp = (struct securenet *)malloc(sizeof(struct securenet)); if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) { yp_error("badly formatted securenets entry: %s", addr1); free(tmp); continue; } if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) { yp_error("badly formatted securenets entry: %s", addr2); free(tmp); continue; } tmp->next = securenets; securenets = tmp; } fclose(fp); } /* * Access control functions. * * yp_access() checks the mapname and client host address and watches for * the following things: * * - If the client is referencing one of the master.passwd.* or shadow.* maps, * it must be using a privileged port to make its RPC to us. If it is, then * we can assume that the caller is root and allow the RPC to succeed. If it * isn't access is denied. * * - The client's IP address is checked against the securenets rules. * There are two kinds of securenets support: the built-in support, * which is very simple and depends on the presence of a * /var/yp/securenets file, and tcp-wrapper support, which requires * Wietse Venema's libwrap.a and tcpd.h. (Since the tcp-wrapper * package does not ship with FreeBSD, we use the built-in support * by default. Users can recompile the server with the tcp-wrapper library * if they already have it installed and want to use hosts.allow and * hosts.deny to control access instead of having a separate securenets * file.) * * If no /var/yp/securenets file is present, the host access checks * are bypassed and all hosts are allowed to connect. * * The yp_validdomain() function checks the domain specified by the caller * to make sure it's actually served by this server. This is more a sanity * check than an a security check, but this seems to be the best place for * it. */ #ifdef DB_CACHE int yp_access(const char *map, const char *domain, const struct svc_req *rqstp) #else int yp_access(const char *map, const struct svc_req *rqstp) #endif { struct sockaddr_in *rqhost; int status_securenets = 0; #ifdef TCP_WRAPPER int status_tcpwrap; #endif static unsigned long oldaddr = 0; struct securenet *tmp; const char *yp_procedure = NULL; char procbuf[50]; if (rqstp->rq_prog != YPPASSWDPROG && rqstp->rq_prog != YPPROG) { snprintf(procbuf, sizeof(procbuf), "#%lu/#%lu", (unsigned long)rqstp->rq_prog, (unsigned long)rqstp->rq_proc); yp_procedure = (char *)&procbuf; } else { yp_procedure = rqstp->rq_prog == YPPASSWDPROG ? "yppasswdprog_update" : yp_procs[rqstp->rq_proc + (12 * (rqstp->rq_vers - 1))]; } rqhost = svc_getcaller(rqstp->rq_xprt); if (debug) { yp_error("procedure %s called from %s:%d", yp_procedure, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); if (map != NULL) yp_error("client is referencing map \"%s\".", map); } /* Check the map name if one was supplied. */ if (map != NULL) { if (strchr(map, '/')) { yp_error("embedded slash in map name \"%s\" -- \ possible spoof attempt from %s:%d", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); return(1); } #ifdef DB_CACHE if ((yp_testflag((char *)map, (char *)domain, YP_SECURE) || #else if ((strstr(map, "master.passwd.") || strstr(map, "shadow.") || #endif (rqstp->rq_prog == YPPROG && rqstp->rq_proc == YPPROC_XFR) || (rqstp->rq_prog == YPXFRD_FREEBSD_PROG && rqstp->rq_proc == YPXFRD_GETMAP)) && ntohs(rqhost->sin_port) >= IPPORT_RESERVED) { yp_error("access to %s denied -- client %s:%d \ not privileged", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); return(1); } } #ifdef TCP_WRAPPER status_tcpwrap = hosts_ctl("ypserv", STRING_UNKNOWN, inet_ntoa(rqhost->sin_addr), ""); #endif tmp = securenets; while (tmp) { if (((rqhost->sin_addr.s_addr & ~tmp->mask.s_addr) | tmp->net.s_addr) == rqhost->sin_addr.s_addr) { status_securenets = 1; break; } tmp = tmp->next; } #ifdef TCP_WRAPPER if (status_securenets == 0 || status_tcpwrap == 0) { #else if (status_securenets == 0) { #endif /* * One of the following two events occurred: * * (1) The /var/yp/securenets exists and the remote host does not * match any of the networks specified in it. * (2) The hosts.allow file has denied access and TCP_WRAPPER is * defined. * * In either case deny access. */ if (rqhost->sin_addr.s_addr != oldaddr) { yp_error("connect from %s:%d to procedure %s refused", inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port), yp_procedure); oldaddr = rqhost->sin_addr.s_addr; } return(1); } return(0); } int yp_validdomain(const char *domain) { struct stat statbuf; char dompath[MAXPATHLEN + 2]; if (domain == NULL || strstr(domain, "binding") || !strcmp(domain, ".") || !strcmp(domain, "..") || strchr(domain, '/') || strlen(domain) > YPMAXDOMAIN) return(1); snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain); if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) return(1); return(0); } Index: head/usr.sbin/ypserv/yp_dblookup.c =================================================================== --- head/usr.sbin/ypserv/yp_dblookup.c (revision 285925) +++ head/usr.sbin/ypserv/yp_dblookup.c (revision 285926) @@ -1,733 +1,733 @@ /* * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "yp_extern.h" int ypdb_debug = 0; enum ypstat yp_errno = YP_TRUE; #define PERM_SECURE (S_IRUSR|S_IWUSR) HASHINFO openinfo = { 4096, /* bsize */ 32, /* ffactor */ 256, /* nelem */ 2048 * 512, /* cachesize */ NULL, /* hash */ 0, /* lorder */ }; #ifdef DB_CACHE #include #ifndef MAXDBS #define MAXDBS 20 #endif static int numdbs = 0; struct dbent { DB *dbp; char *name; char *key; int size; int flags; }; static TAILQ_HEAD(circlehead, circleq_entry) qhead; struct circleq_entry { struct dbent *dbptr; TAILQ_ENTRY(circleq_entry) links; }; /* * Initialize the circular queue. */ void yp_init_dbs(void) { TAILQ_INIT(&qhead); return; } /* * Dynamically allocate an entry for the circular queue. * Return a NULL pointer on failure. */ static struct circleq_entry * yp_malloc_qent(void) { register struct circleq_entry *q; q = (struct circleq_entry *)malloc(sizeof(struct circleq_entry)); if (q == NULL) { yp_error("failed to malloc() circleq entry"); return(NULL); } bzero((char *)q, sizeof(struct circleq_entry)); q->dbptr = (struct dbent *)malloc(sizeof(struct dbent)); if (q->dbptr == NULL) { yp_error("failed to malloc() circleq entry"); free(q); return(NULL); } bzero((char *)q->dbptr, sizeof(struct dbent)); return(q); } /* * Free a previously allocated circular queue * entry. */ static void yp_free_qent(struct circleq_entry *q) { /* * First, close the database. In theory, this is also * supposed to free the resources allocated by the DB * package, including the memory pointed to by q->dbptr->key. * This means we don't have to free q->dbptr->key here. */ if (q->dbptr->dbp) { (void)(q->dbptr->dbp->close)(q->dbptr->dbp); q->dbptr->dbp = NULL; } /* * Then free the database name, which was strdup()'ed. */ free(q->dbptr->name); /* * Free the rest of the dbent struct. */ free(q->dbptr); q->dbptr = NULL; /* * Free the circleq struct. */ free(q); q = NULL; return; } /* * Zorch a single entry in the dbent queue and release * all its resources. (This always removes the last entry * in the queue.) */ static void yp_flush(void) { register struct circleq_entry *qptr; qptr = TAILQ_LAST(&qhead, circlehead); TAILQ_REMOVE(&qhead, qptr, links); yp_free_qent(qptr); numdbs--; return; } /* * Close all databases, erase all database names and empty the queue. */ void yp_flush_all(void) { register struct circleq_entry *qptr; while (!TAILQ_EMPTY(&qhead)) { qptr = TAILQ_FIRST(&qhead); /* save this */ TAILQ_REMOVE(&qhead, qptr, links); yp_free_qent(qptr); } numdbs = 0; return; } static char *inter_string = "YP_INTERDOMAIN"; static char *secure_string = "YP_SECURE"; static int inter_sz = sizeof("YP_INTERDOMAIN") - 1; static int secure_sz = sizeof("YP_SECURE") - 1; static int yp_setflags(DB *dbp) { DBT key = { NULL, 0 }, data = { NULL, 0 }; int flags = 0; key.data = inter_string; key.size = inter_sz; if (!(dbp->get)(dbp, &key, &data, 0)) flags |= YP_INTERDOMAIN; key.data = secure_string; key.size = secure_sz; if (!(dbp->get)(dbp, &key, &data, 0)) flags |= YP_SECURE; return(flags); } int yp_testflag(char *map, char *domain, int flag) { char buf[MAXPATHLEN + 2]; register struct circleq_entry *qptr; if (map == NULL || domain == NULL) return(0); strcpy(buf, domain); strcat(buf, "/"); strcat(buf, map); TAILQ_FOREACH(qptr, &qhead, links) { if (!strcmp(qptr->dbptr->name, buf)) { if (qptr->dbptr->flags & flag) return(1); else return(0); } } if (yp_open_db_cache(domain, map, NULL, 0) == NULL) return(0); if (TAILQ_FIRST(&qhead)->dbptr->flags & flag) return(1); return(0); } /* * Add a DB handle and database name to the cache. We only maintain * fixed number of entries in the cache, so if we're asked to store * a new entry when all our slots are already filled, we have to kick * out the entry in the last slot to make room. */ static int yp_cache_db(DB *dbp, char *name, int size) { register struct circleq_entry *qptr; if (numdbs == MAXDBS) { if (ypdb_debug) yp_error("queue overflow -- releasing last slot"); yp_flush(); } /* * Allocate a new queue entry. */ if ((qptr = yp_malloc_qent()) == NULL) { yp_error("failed to allocate a new cache entry"); return(1); } qptr->dbptr->dbp = dbp; qptr->dbptr->name = strdup(name); qptr->dbptr->size = size; qptr->dbptr->key = NULL; qptr->dbptr->flags = yp_setflags(dbp); TAILQ_INSERT_HEAD(&qhead, qptr, links); numdbs++; return(0); } /* * Search the list for a database matching 'name.' If we find it, * move it to the head of the list and return its DB handle. If * not, just fail: yp_open_db_cache() will subsequently try to open * the database itself and call yp_cache_db() to add it to the * list. * * The search works like this: * * - The caller specifies the name of a database to locate. We try to * find an entry in our queue with a matching name. * * - If the caller doesn't specify a key or size, we assume that the * first entry that we encounter with a matching name is returned. * This will result in matches regardless of the key/size values * stored in the queue entry. * * - If the caller also specifies a key and length, we check to see * if the key and length saved in the queue entry also matches. * This lets us return a DB handle that's already positioned at the * correct location within a database. * * - Once we have a match, it gets migrated to the top of the queue * so that it will be easier to find if another request for * the same database comes in later. */ static DB * yp_find_db(const char *name, const char *key, int size) { register struct circleq_entry *qptr; TAILQ_FOREACH(qptr, &qhead, links) { if (!strcmp(qptr->dbptr->name, name)) { if (size) { if (size != qptr->dbptr->size || strncmp(qptr->dbptr->key, key, size)) continue; } else { if (qptr->dbptr->size) continue; } if (qptr != TAILQ_FIRST(&qhead)) { TAILQ_REMOVE(&qhead, qptr, links); TAILQ_INSERT_HEAD(&qhead, qptr, links); } return(qptr->dbptr->dbp); } } return(NULL); } /* * Open a DB database and cache the handle for later use. We first * check the cache to see if the required database is already open. * If so, we fetch the handle from the cache. If not, we try to open * the database and save the handle in the cache for later use. */ DB * yp_open_db_cache(const char *domain, const char *map, const char *key, const int size) { DB *dbp = NULL; char buf[MAXPATHLEN + 2]; /* snprintf(buf, sizeof(buf), "%s/%s", domain, map); */ yp_errno = YP_TRUE; strcpy(buf, domain); strcat(buf, "/"); strcat(buf, map); if ((dbp = yp_find_db(buf, key, size)) != NULL) { return(dbp); } else { if ((dbp = yp_open_db(domain, map)) != NULL) { if (yp_cache_db(dbp, buf, size)) { (void)(dbp->close)(dbp); yp_errno = YP_YPERR; return(NULL); } } } return (dbp); } #endif /* * Open a DB database. */ DB * yp_open_db(const char *domain, const char *map) { DB *dbp = NULL; char buf[MAXPATHLEN + 2]; yp_errno = YP_TRUE; if (map[0] == '.' || strchr(map, '/')) { yp_errno = YP_BADARGS; return (NULL); } #ifdef DB_CACHE if (yp_validdomain(domain)) { yp_errno = YP_NODOM; return(NULL); } #endif snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); #ifdef DB_CACHE again: #endif - dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL); + dbp = dbopen(buf, O_RDONLY, PERM_SECURE, DB_HASH, NULL); if (dbp == NULL) { switch (errno) { #ifdef DB_CACHE case ENFILE: /* * We ran out of file descriptors. Nuke an * open one and try again. */ yp_error("ran out of file descriptors"); yp_flush(); goto again; break; #endif case ENOENT: yp_errno = YP_NOMAP; break; case EFTYPE: yp_errno = YP_BADDB; break; default: yp_errno = YP_YPERR; break; } } return (dbp); } /* * Database access routines. * * - yp_get_record(): retrieve an arbitrary key/data pair given one key * to match against. * * - yp_first_record(): retrieve first key/data base in a database. * * - yp_next_record(): retrieve key/data pair that sequentially follows * the supplied key value in the database. */ #ifdef DB_CACHE int yp_get_record(DB *dbp, const DBT *key, DBT *data, int allow) #else int yp_get_record(const char *domain, const char *map, const DBT *key, DBT *data, int allow) #endif { #ifndef DB_CACHE DB *dbp; #endif int rval = 0; #ifndef DB_CACHE static unsigned char buf[YPMAXRECORD]; #endif if (ypdb_debug) yp_error("looking up key [%.*s]", (int)key->size, (char *)key->data); /* * Avoid passing back magic "YP_*" entries unless * the caller specifically requested them by setting * the 'allow' flag. */ if (!allow && !strncmp(key->data, "YP_", 3)) return(YP_NOKEY); #ifndef DB_CACHE if ((dbp = yp_open_db(domain, map)) == NULL) { return(yp_errno); } #endif if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->size = 0; #else (void)(dbp->close)(dbp); #endif if (rval == 1) return(YP_NOKEY); else return(YP_BADDB); } if (ypdb_debug) yp_error("result of lookup: key: [%.*s] data: [%.*s]", (int)key->size, (char *)key->data, (int)data->size, (char *)data->data); #ifdef DB_CACHE if (TAILQ_FIRST(&qhead)->dbptr->size) { TAILQ_FIRST(&qhead)->dbptr->key = ""; TAILQ_FIRST(&qhead)->dbptr->size = 0; } #else bcopy(data->data, &buf, data->size); data->data = &buf; (void)(dbp->close)(dbp); #endif return(YP_TRUE); } int yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) { int rval; #ifndef DB_CACHE static unsigned char buf[YPMAXRECORD]; #endif if (ypdb_debug) yp_error("retrieving first key in map"); if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif if (rval == 1) return(YP_NOKEY); else return(YP_BADDB); } /* Avoid passing back magic "YP_*" records. */ while (!strncmp(key->data, "YP_", 3) && !allow) { if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif if (rval == 1) return(YP_NOKEY); else return(YP_BADDB); } } if (ypdb_debug) yp_error("result of lookup: key: [%.*s] data: [%.*s]", (int)key->size, (char *)key->data, (int)data->size, (char *)data->data); #ifdef DB_CACHE if (TAILQ_FIRST(&qhead)->dbptr->size) { TAILQ_FIRST(&qhead)->dbptr->key = key->data; TAILQ_FIRST(&qhead)->dbptr->size = key->size; } #else bcopy(data->data, &buf, data->size); data->data = &buf; #endif return(YP_TRUE); } int yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) { static DBT lkey = { NULL, 0 }; static DBT ldata = { NULL, 0 }; int rval; #ifndef DB_CACHE static unsigned char keybuf[YPMAXRECORD]; static unsigned char datbuf[YPMAXRECORD]; #endif if (key == NULL || !key->size || key->data == NULL) { rval = yp_first_record(dbp,key,data,allow); if (rval == YP_NOKEY) return(YP_NOMORE); else { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->key = key->data; TAILQ_FIRST(&qhead)->dbptr->size = key->size; #endif return(rval); } } if (ypdb_debug) yp_error("retrieving next key, previous was: [%.*s]", (int)key->size, (char *)key->data); if (!all) { #ifdef DB_CACHE if (TAILQ_FIRST(&qhead)->dbptr->key == NULL) { #endif (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); while (key->size != lkey.size || strncmp(key->data, lkey.data, (int)key->size)) if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif return(YP_NOKEY); } #ifdef DB_CACHE } #endif } if ((dbp->seq)(dbp,key,data,R_NEXT)) { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif return(YP_NOMORE); } /* Avoid passing back magic "YP_*" records. */ while (!strncmp(key->data, "YP_", 3) && !allow) if ((dbp->seq)(dbp,key,data,R_NEXT)) { #ifdef DB_CACHE TAILQ_FIRST(&qhead)->dbptr->size = 0; #endif return(YP_NOMORE); } if (ypdb_debug) yp_error("result of lookup: key: [%.*s] data: [%.*s]", (int)key->size, (char *)key->data, (int)data->size, (char *)data->data); #ifdef DB_CACHE if (TAILQ_FIRST(&qhead)->dbptr->size) { TAILQ_FIRST(&qhead)->dbptr->key = key->data; TAILQ_FIRST(&qhead)->dbptr->size = key->size; } #else bcopy(key->data, &keybuf, key->size); lkey.data = &keybuf; lkey.size = key->size; bcopy(data->data, &datbuf, data->size); data->data = &datbuf; #endif return(YP_TRUE); } #ifdef DB_CACHE /* * Database glue functions. */ static DB *yp_currmap_db = NULL; static int yp_allow_db = 0; ypstat yp_select_map(char *map, char *domain, keydat *key, int allow) { if (key == NULL) yp_currmap_db = yp_open_db_cache(domain, map, NULL, 0); else yp_currmap_db = yp_open_db_cache(domain, map, key->keydat_val, key->keydat_len); yp_allow_db = allow; return(yp_errno); } ypstat yp_getbykey(keydat *key, valdat *val) { DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; ypstat rval; db_key.data = key->keydat_val; db_key.size = key->keydat_len; rval = yp_get_record(yp_currmap_db, &db_key, &db_val, yp_allow_db); if (rval == YP_TRUE) { val->valdat_val = db_val.data; val->valdat_len = db_val.size; } return(rval); } ypstat yp_firstbykey(keydat *key, valdat *val) { DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; ypstat rval; rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db); if (rval == YP_TRUE) { key->keydat_val = db_key.data; key->keydat_len = db_key.size; val->valdat_val = db_val.data; val->valdat_len = db_val.size; } return(rval); } ypstat yp_nextbykey(keydat *key, valdat *val) { DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; ypstat rval; db_key.data = key->keydat_val; db_key.size = key->keydat_len; rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db); if (rval == YP_TRUE) { key->keydat_val = db_key.data; key->keydat_len = db_key.size; val->valdat_val = db_val.data; val->valdat_len = db_val.size; } return(rval); } #endif Index: head/usr.sbin/ypserv/yp_error.c =================================================================== --- head/usr.sbin/ypserv/yp_error.c (revision 285925) +++ head/usr.sbin/ypserv/yp_error.c (revision 285926) @@ -1,73 +1,73 @@ /* * 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. * */ #include __FBSDID("$FreeBSD$"); /* * error logging/reporting facilities * stolen from /usr/libexec/mail.local via ypserv */ #include #include #include #include #include "yp_extern.h" int debug; -extern int _rpcpmstart; +extern int _rpcpmstart; extern char *progname; - static void __verr(const char *fmt, va_list ap) __printflike(1, 0); -static void __verr(const char *fmt, va_list ap) +static void +__verr(const char *fmt, va_list ap) { if (debug && !_rpcpmstart) { fprintf(stderr,"%s: ",progname); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } else { vsyslog(LOG_NOTICE, fmt, ap); } } void yp_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); __verr(fmt,ap); va_end(ap); } Index: head/usr.sbin/ypserv/yp_main.c =================================================================== --- head/usr.sbin/ypserv/yp_main.c (revision 285925) +++ head/usr.sbin/ypserv/yp_main.c (revision 285926) @@ -1,581 +1,579 @@ /* * 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. */ #include __FBSDID("$FreeBSD$"); /* * ypserv startup function. * We need out own main() since we have to do some additional work * that rpcgen won't do for us. Most of this file was generated using * rpcgen.new, and later modified. */ #include #include #include #include #include #include "yp.h" #include #include #include #include #include #include #include /* getenv, exit */ #include /* strcmp */ #include #include #ifdef __cplusplus #include /* getdtablesize, open */ #endif /* __cplusplus */ #include #include #include "yp_extern.h" #include #include #include #ifndef SIG_PF #define SIG_PF void(*)(int) #endif #define _RPCSVC_CLOSEDOWN 120 int _rpcpmstart; /* Started by a port monitor ? */ -static int _rpcfdtype; - /* Whether Stream or Datagram ? */ +static int _rpcfdtype; /* Whether Stream or Datagram? */ static int _rpcaf; static int _rpcfd; - /* States a server can be in wrt request */ - +/* States a server can be in wrt request */ #define _IDLE 0 #define _SERVED 1 #define _SERVING 2 extern void ypprog_1(struct svc_req *, SVCXPRT *); extern void ypprog_2(struct svc_req *, SVCXPRT *); extern int _rpc_dtablesize(void); extern int _rpcsvcstate; /* Set when a request is serviced */ char *progname = "ypserv"; char *yp_dir = _PATH_YP; /*int debug = 0;*/ int do_dns = 0; int resfd; struct socklistent { int sle_sock; struct sockaddr_storage sle_ss; SLIST_ENTRY(socklistent) sle_next; }; static SLIST_HEAD(, socklistent) sle_head = SLIST_HEAD_INITIALIZER(sle_head); struct bindaddrlistent { const char *ble_hostname; SLIST_ENTRY(bindaddrlistent) ble_next; }; static SLIST_HEAD(, bindaddrlistent) ble_head = SLIST_HEAD_INITIALIZER(ble_head); static char *servname = "0"; static void _msgout(char* msg, ...) { va_list ap; va_start(ap, msg); if (debug) { if (_rpcpmstart) vsyslog(LOG_ERR, msg, ap); else vwarnx(msg, ap); } else vsyslog(LOG_ERR, msg, ap); va_end(ap); } pid_t yp_pid; static void yp_svc_run(void) { #ifdef FD_SETSIZE fd_set readfds; #else int readfds; #endif /* def FD_SETSIZE */ int fd_setsize = _rpc_dtablesize(); struct timeval timeout; /* Establish the identity of the parent ypserv process. */ yp_pid = getpid(); for (;;) { #ifdef FD_SETSIZE readfds = svc_fdset; #else readfds = svc_fds; #endif /* def FD_SETSIZE */ FD_SET(resfd, &readfds); timeout.tv_sec = RESOLVER_TIMEOUT; timeout.tv_usec = 0; switch (select(fd_setsize, &readfds, NULL, NULL, &timeout)) { case -1: if (errno == EINTR) { continue; } warn("svc_run: - select failed"); return; case 0: if (getpid() == yp_pid) yp_prune_dnsq(); break; default: if (getpid() == yp_pid) { if (FD_ISSET(resfd, &readfds)) { yp_run_dnsq(); FD_CLR(resfd, &readfds); } svc_getreqset(&readfds); } } if (yp_pid != getpid()) _exit(0); } } static void unregister(void) { (void)svc_unreg(YPPROG, YPVERS); (void)svc_unreg(YPPROG, YPOLDVERS); } static void reaper(int sig) { int status; int saved_errno; saved_errno = errno; if (sig == SIGHUP) { load_securenets(); #ifdef DB_CACHE yp_flush_all(); #endif errno = saved_errno; return; } if (sig == SIGCHLD) { while (wait3(&status, WNOHANG, NULL) > 0) children--; } else { unregister(); exit(0); } errno = saved_errno; return; } static void usage(void) { fprintf(stderr, "usage: ypserv [-h addr] [-d] [-n] [-p path] [-P port]\n"); exit(1); } static void closedown(int sig) { if (_rpcsvcstate == _IDLE) { extern fd_set svc_fdset; static int size; int i, openfd; if (_rpcfdtype == SOCK_DGRAM) { unregister(); exit(0); } if (size == 0) { size = getdtablesize(); } for (i = 0, openfd = 0; i < size && openfd < 2; i++) if (FD_ISSET(i, &svc_fdset)) openfd++; if (openfd <= 1) { unregister(); exit(0); } } if (_rpcsvcstate == _SERVED) _rpcsvcstate = _IDLE; (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } static int create_service(const int sock, const struct netconfig *nconf, const struct __rpc_sockinfo *si) { int error; SVCXPRT *transp; struct addrinfo hints, *res, *res0; struct socklistent *slep; struct bindaddrlistent *blep; struct netbuf svcaddr; SLIST_INIT(&sle_head); memset(&hints, 0, sizeof(hints)); memset(&svcaddr, 0, sizeof(svcaddr)); hints.ai_family = si->si_af; hints.ai_socktype = si->si_socktype; hints.ai_protocol = si->si_proto; /* * Build socketlist from bindaddrlist. */ if (sock == RPC_ANYFD) { SLIST_FOREACH(blep, &ble_head, ble_next) { if (blep->ble_hostname == NULL) hints.ai_flags = AI_PASSIVE; else hints.ai_flags = 0; error = getaddrinfo(blep->ble_hostname, servname, &hints, &res0); if (error) { _msgout("getaddrinfo(): %s", gai_strerror(error)); return -1; } for (res = res0; res; res = res->ai_next) { int s; s = __rpc_nconf2fd(nconf); if (s < 0) { if (errno == EAFNOSUPPORT) _msgout("unsupported" " transport: %s", nconf->nc_netid); else _msgout("cannot create" " %s socket: %s", nconf->nc_netid, strerror(errno)); freeaddrinfo(res0); return -1; } if (bindresvport_sa(s, res->ai_addr) == -1) { if ((errno != EPERM) || (bind(s, res->ai_addr, res->ai_addrlen) == -1)) { _msgout("cannot bind " "%s socket: %s", nconf->nc_netid, strerror(errno)); freeaddrinfo(res0); close(sock); return -1; } } if (nconf->nc_semantics != NC_TPI_CLTS) listen(s, SOMAXCONN); slep = malloc(sizeof(*slep)); if (slep == NULL) { _msgout("malloc failed: %s", strerror(errno)); freeaddrinfo(res0); close(s); return -1; } memset(slep, 0, sizeof(*slep)); memcpy(&slep->sle_ss, res->ai_addr, res->ai_addrlen); slep->sle_sock = s; SLIST_INSERT_HEAD(&sle_head, slep, sle_next); /* * If servname == "0", redefine it by using * the bound socket. */ if (strncmp("0", servname, 1) == 0) { struct sockaddr *sap; socklen_t slen; char *sname; sname = malloc(NI_MAXSERV); if (sname == NULL) { _msgout("malloc(): %s", strerror(errno)); freeaddrinfo(res0); close(s); return -1; } memset(sname, 0, NI_MAXSERV); sap = (struct sockaddr *)&slep->sle_ss; slen = sizeof(*sap); error = getsockname(s, sap, &slen); if (error) { _msgout("getsockname(): %s", strerror(errno)); freeaddrinfo(res0); close(s); free(sname); return -1; } error = getnameinfo(sap, slen, NULL, 0, sname, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if (error) { _msgout("getnameinfo(): %s", strerror(errno)); freeaddrinfo(res0); close(s); free(sname); return -1; } servname = sname; } } freeaddrinfo(res0); } } else { slep = malloc(sizeof(*slep)); if (slep == NULL) { _msgout("malloc failed: %s", strerror(errno)); return -1; } memset(slep, 0, sizeof(*slep)); slep->sle_sock = sock; SLIST_INSERT_HEAD(&sle_head, slep, sle_next); } /* * Traverse socketlist and create rpc service handles for each socket. */ SLIST_FOREACH(slep, &sle_head, sle_next) { if (nconf->nc_semantics == NC_TPI_CLTS) transp = svc_dg_create(slep->sle_sock, 0, 0); else transp = svc_vc_create(slep->sle_sock, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (transp == NULL) { _msgout("unable to create service: %s", nconf->nc_netid); continue; } if (!svc_reg(transp, YPPROG, YPOLDVERS, ypprog_1, NULL)) { svc_destroy(transp); close(slep->sle_sock); _msgout("unable to register (YPPROG, YPOLDVERS, %s):" " %s", nconf->nc_netid, strerror(errno)); continue; } if (!svc_reg(transp, YPPROG, YPVERS, ypprog_2, NULL)) { svc_destroy(transp); close(slep->sle_sock); _msgout("unable to register (YPPROG, YPVERS, %s): %s", nconf->nc_netid, strerror(errno)); continue; } } while(!(SLIST_EMPTY(&sle_head))) SLIST_REMOVE_HEAD(&sle_head, sle_next); /* * Register RPC service to rpcbind by using AI_PASSIVE address. */ hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, servname, &hints, &res0); if (error) { _msgout("getaddrinfo(): %s", gai_strerror(error)); return -1; } svcaddr.buf = res0->ai_addr; svcaddr.len = res0->ai_addrlen; if (si->si_af == AF_INET) { /* XXX: ignore error intentionally */ rpcb_set(YPPROG, YPOLDVERS, nconf, &svcaddr); } /* XXX: ignore error intentionally */ rpcb_set(YPPROG, YPVERS, nconf, &svcaddr); freeaddrinfo(res0); return 0; } int main(int argc, char *argv[]) { int ch; int error; int ntrans; void *nc_handle; struct netconfig *nconf; struct __rpc_sockinfo si; struct bindaddrlistent *blep; memset(&si, 0, sizeof(si)); SLIST_INIT(&ble_head); while ((ch = getopt(argc, argv, "dh:np:P:")) != -1) { switch (ch) { case 'd': debug = ypdb_debug = 1; break; case 'h': blep = malloc(sizeof(*blep)); if (blep == NULL) err(1, "malloc() failed: -h %s", optarg); blep->ble_hostname = optarg; SLIST_INSERT_HEAD(&ble_head, blep, ble_next); break; case 'n': do_dns = 1; break; case 'p': yp_dir = optarg; break; case 'P': servname = optarg; break; default: usage(); } } /* * Add "anyaddr" entry if no -h is specified. */ if (SLIST_EMPTY(&ble_head)) { blep = malloc(sizeof(*blep)); if (blep == NULL) err(1, "malloc() failed"); memset(blep, 0, sizeof(*blep)); SLIST_INSERT_HEAD(&ble_head, blep, ble_next); } load_securenets(); yp_init_resolver(); #ifdef DB_CACHE yp_init_dbs(); #endif nc_handle = setnetconfig(); if (nc_handle == NULL) err(1, "cannot read %s", NETCONFIG); if (__rpc_fd2sockinfo(0, &si) != 0) { /* invoked from inetd */ _rpcpmstart = 1; _rpcfdtype = si.si_socktype; _rpcaf = si.si_af; _rpcfd = 0; openlog("ypserv", LOG_PID, LOG_DAEMON); } else { /* standalone mode */ if (!debug) { if (daemon(0,0)) { err(1,"cannot fork"); } openlog("ypserv", LOG_PID, LOG_DAEMON); } _rpcpmstart = 0; _rpcaf = AF_INET; _rpcfd = RPC_ANYFD; unregister(); } if (madvise(NULL, 0, MADV_PROTECT) != 0) _msgout("madvise(): %s", strerror(errno)); /* * Create RPC service for each transport. */ ntrans = 0; while((nconf = getnetconfig(nc_handle))) { if ((nconf->nc_flag & NC_VISIBLE)) { if (__rpc_nconf2sockinfo(nconf, &si) == 0) { _msgout("cannot get information for %s. " "Ignored.", nconf->nc_netid); continue; } if (_rpcpmstart) { if (si.si_socktype != _rpcfdtype || si.si_af != _rpcaf) continue; } else if (si.si_af != _rpcaf) continue; error = create_service(_rpcfd, nconf, &si); if (error) { endnetconfig(nc_handle); exit(1); } ntrans++; } } endnetconfig(nc_handle); while(!(SLIST_EMPTY(&ble_head))) SLIST_REMOVE_HEAD(&ble_head, ble_next); if (ntrans == 0) { _msgout("no transport is available. Aborted."); exit(1); } if (_rpcpmstart) { (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } /* * Make sure SIGPIPE doesn't blow us away while servicing TCP * connections. */ (void) signal(SIGPIPE, SIG_IGN); (void) signal(SIGCHLD, (SIG_PF) reaper); (void) signal(SIGTERM, (SIG_PF) reaper); (void) signal(SIGINT, (SIG_PF) reaper); (void) signal(SIGHUP, (SIG_PF) reaper); yp_svc_run(); _msgout("svc_run returned"); exit(1); /* NOTREACHED */ }