Index: freebsd-head/usr.bin/ypwhich/ypwhich.c =================================================================== --- freebsd-head/usr.bin/ypwhich/ypwhich.c (revision 239326) +++ freebsd-head/usr.bin/ypwhich/ypwhich.c (working copy) @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -83,26 +84,68 @@ usage(void) exit(ERR_USAGE); } +#ifdef INET6 +# define ADDRSTRLEN INET6_ADDRSTRLEN +#else +# define ADDRSTRLEN INET_ADDRSTRLEN +#endif + +static void +print_addr(const union ypbf_resp *ypbr, int version) +{ + struct hostent *hent = NULL; + char str[ADDRSTRLEN]; + int family; + size_t len; + union { + struct in_addr in; +#ifdef INET6 + struct in6_addr in6; +#endif + } ss_addr; + +#ifdef YPBIND_COMPAT_V2 + if (version == YPBINDVERS_2) { + family = AF_INET; + len = sizeof(ss_addr.in); + bcopy(&ypbr->ypbf_raddr_v2, &ss_addr, len); + } + else /* YPBINDVERS */ +#endif + { + family = ypbr->ypbf_rfamily; +#ifdef INET6 + if (family == AF_INET6) + len = sizeof(ss_addr.in6); + else /* AF_INET */ +#endif + len = sizeof(ss_addr.in); + bcopy(&ypbr->ypbf_raddr, &ss_addr, len); + } + hent = gethostbyaddr((char *)&ss_addr, len, family); + if (hent) + printf("%s\n", hent->h_name); + else + printf("%s\n", inet_ntop(family, &ss_addr, str, ADDRSTRLEN)); +} /* * Like yp_bind except can query a specific host */ static int -bind_host(char *dom, struct sockaddr_in *lsin) +bind_host(char *dom, const char *host) { - struct hostent *hent = NULL; - struct ypbind_resp ypbr; + union ypbf_resp ypbr; struct timeval tv; CLIENT *client; - int sock, r; - struct in_addr ss_addr; + int r; + int version = YPBINDVERS; - sock = RPC_ANYSOCK; tv.tv_sec = 15; tv.tv_usec = 0; - client = clntudp_create(lsin, YPBINDPROG, YPBINDVERS, tv, &sock); + client = clnt_create_timed(host, YPBINDPROG, version, "udp", &tv); if (client == NULL) { - warnx("can't clntudp_create: %s", yperr_string(YPERR_YPBIND)); + warnx("can't clnt_create_timed: %s", yperr_string(YPERR_YPBIND)); return (YPERR_YPBIND); } @@ -110,28 +153,31 @@ bind_host(char *dom, struct sockaddr_in tv.tv_usec = 0; r = clnt_call(client, YPBINDPROC_DOMAIN, (xdrproc_t)xdr_domainname, &dom, - (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); + (xdrproc_t)xdr_ypbind_resp, &ypbr.resp, tv); +#ifdef YPBIND_COMPAT_V2 + if (r == RPC_PROGVERSMISMATCH) { + fprintf(stderr, "Warning: %s, fallback in V2 compatibility mode\n", clnt_sperrno(r)); + version = YPBINDVERS_2; + if (clnt_control(client, CLSET_VERS, &version) == TRUE) + r = clnt_call(client, YPBINDPROC_DOMAIN, + (xdrproc_t)xdr_domainname, &dom, + (xdrproc_t)xdr_ypbind_resp_v2, &ypbr.resp2, tv); /* TODO libc must define YPBIND_COMPAT_V2 */ + } +#endif 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) { + if (ypbr.ypbf_rstatus != YPBIND_SUCC_VAL) { warnx("can't yp_bind: reason: %s", - ypbinderr_string(ypbr.ypbind_respbody.ypbind_error)); + ypbinderr_string(ypbr.ypbf_rerror)); 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)); + print_addr(&ypbr, version); return (0); } @@ -141,8 +187,7 @@ main(int argc, char *argv[]) char *domnam = NULL, *master; char *map = NULL; struct ypmaplist *ypml, *y; - struct hostent *hent; - struct sockaddr_in lsin; + char *host; int notrans, mode; int c, r; u_int i; @@ -166,38 +211,20 @@ main(int argc, char *argv[]) mode++; break; default: - usage(); + usage(); } if (!domnam) yp_get_default_domain(&domnam); if (mode == 0) { - switch (argc-optind) { - case 0: - bzero(&lsin, sizeof lsin); - lsin.sin_family = AF_INET; - lsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (bind_host(domnam, &lsin)) - exit(ERR_NOBINDING); - break; - case 1: - bzero(&lsin, sizeof lsin); - lsin.sin_family = AF_INET; - if ((lsin.sin_addr.s_addr = inet_addr(argv[optind])) == INADDR_NONE) { - hent = gethostbyname(argv[optind]); - if (!hent) - errx(ERR_NOSUCHHOST, "host %s unknown", argv[optind]); - bcopy((char *)hent->h_addr_list[0], - (char *)&lsin.sin_addr, sizeof lsin.sin_addr); - } - if (bind_host(domnam, &lsin)) + if (argc-optind == 0 || argc-optind == 1) { + host = argc-optind ? argv[optind] : "127.0.0.1"; + if (bind_host(domnam, host)) exit(ERR_NOBINDING); - break; - default: - usage(); } + else + usage(); exit(0); } Index: freebsd-head/usr.bin/ypwhich/Makefile =================================================================== --- freebsd-head/usr.bin/ypwhich/Makefile (revision 239326) +++ freebsd-head/usr.bin/ypwhich/Makefile (working copy) @@ -1,8 +1,15 @@ # from: @(#)Makefile 5.8 (Berkeley) 7/28/90 # $FreeBSD$ +.include + PROG= ypwhich WARNS?= 2 +CFLAGS += -DYPBIND_COMPAT_V2 +.if ${MK_INET6_SUPPORT} != "no" +CFLAGS += -DINET6 +.endif + .include Index: freebsd-head/include/rpcsvc/yp_utils.h =================================================================== --- freebsd-head/include/rpcsvc/yp_utils.h (revision 0) +++ freebsd-head/include/rpcsvc/yp_utils.h (revision 240004) @@ -0,0 +1,109 @@ +/* + * Copyright (c) TODO + * 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. + * + * $FreeBSD: soc2012/exxo/freebsd-head/include/rpcsvc/yp_prot.h 239957 2012-07-31 16:20:04Z exxo $ + */ + +#ifndef _RPCSVC_YP_UTILS_H_ +#define _RPCSVC_YP_UTILS_H_ + +/* YPBIND facilities + * + * This file should be included after or + * It provides facilities to deal with YPBIND protocols + */ + +#define ypresp_status ypbind_status +#define ypsetdom_family ypsetdom_binding.ypbind_binding_family + +#ifdef _RPCSVC_YP_PROT_H_ /* if used with yp_prot.h */ + +# define ypresp_family ypbind_respbody.ypbind_bindinfo.ypbind_binding_family +# define ypresp_error ypbind_respbody.ypbind_error +# define ypresp_addr ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr +# define ypresp_port ypbind_respbody.ypbind_bindinfo.ypbind_binding_port + +#elif defined(_YP_H_RPCGEN) /* if used with yp.h */ + +# define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr +# define ypsetdom_port ypsetdom_binding.ypbind_binding_port + +# define ypresp_family ypbind_resp_u.ypbind_bindinfo.ypbind_binding_family +# define ypresp_error ypbind_resp_u.ypbind_error +# define ypresp_addr ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr +# define ypresp_port ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port +# define ypresp_error_v2 ypbind_resp_v2_u.ypbind_error +# define ypresp_addr_v2 ypbind_resp_v2_u.ypbind_bindinfo.ypbind_binding_addr +# define ypresp_port_v2 ypbind_resp_v2_u.ypbind_bindinfo.ypbind_binding_port + +#endif + +union ypbf_resp { + struct { + enum ypbind_resptype status; + u_int error; + } header; + struct ypbind_resp resp; +#ifdef YPBIND_COMPAT_V2 + struct ypbind_resp_v2 resp2; +#endif +}; +#define ypbf_rstatus header.status +#define ypbf_rerror header.error +#define ypbf_rfamily resp.ypresp_family +#define ypbf_raddr resp.ypresp_addr +#define ypbf_rport resp.ypresp_port +#ifdef YPBIND_COMPAT_V2 +# ifdef _RPCSVC_YP_PROT_H_ /* yp_prot.h */ +# define ypbf_raddr_v2 resp2.ypresp_addr +# define ypbf_rport_v2 resp2.ypresp_port +# elif defined(_YP_H_RPCGEN) /* yp.h */ +# define ypbf_raddr_v2 resp2.ypresp_addr_v2 +# define ypbf_rport_v2 resp2.ypresp_port_v2 +# endif +#endif + +union ypbf_setdom { + char ypsetdom_domain[YPMAXDOMAIN + 1]; + struct ypbind_setdom setdom; +#ifdef YPBIND_COMPAT_V2 + struct ypbind_setdom_v2 setdom2; +#endif +}; +#define ypbf_sdomain ypsetdom_domain +#define ypbf_sfamily setdom.ypsetdom_family +#define ypbf_saddr setdom.ypsetdom_addr +#define ypbf_sport setdom.ypsetdom_port +#define ypbf_svers setdom.ypsetdom_vers +#ifdef YPBIND_COMPAT_V2 +# define ypbf_saddr_v2 setdom2.ypsetdom_addr +# define ypbf_sport_v2 setdom2.ypsetdom_port +# define ypbf_svers_v2 setdom2.ypsetdom_vers +#endif + +#endif /* _RPCSVC_YP_UTILS_H_ */ Index: freebsd-head/include/rpcsvc/yp_prot.h =================================================================== --- freebsd-head/include/rpcsvc/yp_prot.h (revision 239326) +++ freebsd-head/include/rpcsvc/yp_prot.h (working copy) @@ -199,7 +199,7 @@ struct ypresp_maplist { struct dom_binding { struct dom_binding *dom_pnext; char dom_domain[YPMAXDOMAIN + 1]; - struct sockaddr_in dom_server_addr; + struct sockaddr_storage dom_server_addr; /* TODO impact of changing this ? */ u_short dom_server_port; int dom_socket; CLIENT *dom_client; @@ -222,7 +222,8 @@ struct dom_binding { */ #define YPBINDPROG ((u_long)100007) -#define YPBINDVERS ((u_long)2) +#define YPBINDVERS ((u_long)3) +#define YPBINDVERS_2 ((u_long)2) #define YPBINDVERS_ORIG ((u_long)1) /* ypbind procedure numbers */ @@ -238,7 +239,13 @@ enum ypbind_resptype { /* network order, of course */ struct ypbind_binding { - struct in_addr ypbind_binding_addr; + sa_family_t ypbind_binding_family; + union { + struct in_addr in; +#ifdef INET6 + struct in6_addr in6; +#endif + } ypbind_binding_addr; u_short ypbind_binding_port; }; @@ -254,6 +261,7 @@ struct ypbind_resp { #define YPBIND_ERR_ERR 1 /* internal error */ #define YPBIND_ERR_NOSERV 2 /* no bound server for passed domain */ #define YPBIND_ERR_RESC 3 /* system resource allocation failure */ +#define YPBIND_ERR_FAMILY 4 /* unsupported family */ /* * Request data structure for ypbind "Set domain" procedure. @@ -266,6 +274,30 @@ struct ypbind_setdom { #define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr #define ypsetdom_port ypsetdom_binding.ypbind_binding_port +/* Backward compatibility for YPBIND protocol version 2 */ +#ifdef YPBIND_COMPAT_V2 + +struct ypbind_binding_v2 { + struct in_addr ypbind_binding_addr; + u_short ypbind_binding_port; +}; + +struct ypbind_resp_v2 { + enum ypbind_resptype ypbind_status; + union { + u_int ypbind_error; + struct ypbind_binding_v2 ypbind_bindinfo; + } ypbind_respbody; +}; + +struct ypbind_setdom_v2 { + char ypsetdom_domain[YPMAXDOMAIN + 1]; + struct ypbind_binding_v2 ypsetdom_binding; + u_int ypsetdom_vers; +}; + +#endif + /* * YPPUSH PROTOCOL: * @@ -317,6 +349,7 @@ bool_t xdr_ypreq_xfr(XDR *, struct ypreq bool_t xdr_ypresp_val(XDR *, struct ypresp_val *); bool_t xdr_ypresp_key_val(XDR *, struct ypresp_key_val *); bool_t xdr_ypbind_resp(XDR *, struct ypbind_resp *); +bool_t xdr_ypbind_resp_v2(XDR *, struct ypbind_resp_v2 *); bool_t xdr_ypbind_setdom(XDR *, struct ypbind_setdom *); bool_t xdr_yp_inaddr(XDR *, struct inaddr *); bool_t xdr_ypmap_parms(XDR *, struct ypmap_parms *); Index: freebsd-head/include/rpcsvc/yp.x =================================================================== --- freebsd-head/include/rpcsvc/yp.x (revision 239326) +++ freebsd-head/include/rpcsvc/yp.x (working copy) @@ -196,7 +196,8 @@ enum ypbind_resptype { }; struct ypbind_binding { - opaque ypbind_binding_addr[4]; /* In network order */ + unsigned char ypbind_binding_family; + opaque ypbind_binding_addr[16]; /* In network order */ opaque ypbind_binding_port[2]; /* In network order */ }; @@ -207,12 +208,12 @@ case YPBIND_SUCC_VAL: ypbind_binding ypbind_bindinfo; }; -/* Detailed failure reason codes for response field ypbind_error*/ +/* Detailed failure reason codes for response field ypbind_error */ const YPBIND_ERR_ERR = 1; /* Internal error */ const YPBIND_ERR_NOSERV = 2; /* No bound server for passed domain */ const YPBIND_ERR_RESC = 3; /* System resource allocation failure */ - +const YPBIND_ERR_FAMILY = 4; /* Unsupported family */ /* * Request data structure for ypbind "Set domain" procedure. @@ -223,6 +224,30 @@ struct ypbind_setdom { unsigned ypsetdom_vers; }; +/* Backward compatibility for YPBIND protocol version 2 */ +#ifdef YPBIND_COMPAT_V2 + +const YPBINDVERS_2 = 2; + +struct ypbind_binding_v2 { + opaque ypbind_binding_addr[4]; /* In network order */ + opaque ypbind_binding_port[2]; /* In network order */ +}; + +union ypbind_resp_v2 switch (ypbind_resptype ypbind_status) { +case YPBIND_FAIL_VAL: + unsigned ypbind_error; +case YPBIND_SUCC_VAL: + ypbind_binding_v2 ypbind_bindinfo; +}; + +struct ypbind_setdom_v2 { + domainname ypsetdom_domain; + ypbind_binding_v2 ypsetdom_binding; + unsigned ypsetdom_vers; +}; + +#endif /* * NIS v1 support for backwards compatibility @@ -371,7 +396,7 @@ program YPBINDPROG { void YPBINDPROC_SETDOM(ypbind_setdom) = 2; - } = 2; + } = 3; } = 100007; #endif Index: freebsd-head/usr.sbin/ypbind/yp_ping.c =================================================================== --- freebsd-head/usr.sbin/ypbind/yp_ping.c (revision 239326) +++ freebsd-head/usr.sbin/ypbind/yp_ping.c (working copy) @@ -103,6 +103,8 @@ __FBSDID("$FreeBSD$"); */ +#if 0 /* TODO : Does __yp_getport achieve the same result ? */ + static struct timeval timeout = { 1, 0 }; static struct timeval tottimeout = { 1, 0 }; @@ -145,6 +147,7 @@ __pmap_getport(struct sockaddr_in *addre address->sin_port = 0; return (port); } +#endif /* * Transmit to YPPROC_DOMAIN_NONACK, return immediately. @@ -207,104 +210,230 @@ ypproc_domain_nonack_2_recv(domainname * */ struct ping_req { - struct sockaddr_in sin; + struct sockaddr_storage sst; u_int32_t xid; }; +struct transport { + CLIENT *clnt; + u_int32_t xid_lookup; + struct sockaddr_storage *any; + int sock; + struct netbuf addr; +}; +#define V4 0 +#define V6 1 +#ifdef INET6 +# define TSP_LEN (V6 + 1) +#else +# define TSP_LEN (V4 + 1) +#endif + +u_short +__rpcb_getport(const char *hostname, const char *netid, + const rpcprog_t prognum, const rpcvers_t versnum) +{ + struct sockaddr_storage sst; + struct netconfig *nconf; + struct netbuf svcaddr; + u_short port; + + svcaddr.len = 0; + svcaddr.maxlen = sizeof(sst); + svcaddr.buf = &sst; + if ((nconf = getnetconfigent(netid)) == NULL || + !rpcb_getaddr(prognum, versnum, nconf, &svcaddr, hostname)) + return (0); + switch (svcaddr.len) { + case sizeof(struct sockaddr_in) : + port = ss_to_sinport(svcaddr.buf); + break; +#ifdef INET6 + case sizeof(struct sockaddr_in6) : + port = ss_to_sin6port(svcaddr.buf); + break; +#endif + default : + port = 0; + } + return (port); /* Network byte order */ +} + +static u_short +__yp_getport(const struct sockaddr_storage *host, const char *netid) +{ + char str[ADDRSTRLEN]; + int family; + char *ptr; + + if (ss_extract(host, &family, &ptr, 0)) + return (0); + inet_ntop(family, ptr, str, ADDRSTRLEN); + return (__rpcb_getport(str, netid, YPPROG, YPVERS)); +} + +static int +rpc_init(struct transport *tsp) +{ + static struct timeval timenull; + int async = TRUE; + int dontblock = 1; + int validtransp = 0; + int i; + + for (i = 0; i < TSP_LEN; ++i) { + if (tsp[i].any == NULL) + continue; +#ifdef INET6 + if (i == V6) { + tsp[i].sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + tsp[i].addr.len = sizeof(struct sockaddr_in6); + } + else /* V4 */ +#endif + { + tsp[i].sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + tsp[i].addr.len = sizeof(struct sockaddr_in); + } + if (tsp[i].sock < 0) + return (1); + tsp[i].addr.buf = tsp[i].any; + tsp[i].clnt = clnt_dg_create(tsp[i].sock, &tsp[i].addr, YPPROG, YPVERS, 0, 0); + if (tsp[i].clnt == NULL) + return (1); + tsp[i].clnt->cl_auth = authsys_create_default(); + clnt_control(tsp[i].clnt, CLSET_TIMEOUT, (char *)&timenull); + clnt_control(tsp[i].clnt, CLSET_ASYNC, (char *)&async); + ioctl(tsp[i].sock, FIONBIO, &dontblock); + ++validtransp; + } + return (!validtransp); +} + +static void +rpc_destroy(struct transport *tsp) +{ + int i; + + for (i = 0; i < TSP_LEN; ++i) { + if (tsp[i].clnt) { + auth_destroy(tsp[i].clnt->cl_auth); + clnt_destroy(tsp[i].clnt); + tsp[i].clnt = NULL; + } + tsp[i].xid_lookup = 0; + tsp[i].any = NULL; + close(tsp[i].sock); + tsp[i].sock = -1; + tsp[i].addr.buf = NULL; + } +} + int -__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port) +__yp_ping(struct sockaddr_storage *restricted_addrs, int cnt, char *dom, u_short *port) { - struct timeval tv = { 5, 0 }; struct ping_req **reqs; unsigned long i; - int async; - struct sockaddr_in sin, *any = NULL; - struct netbuf addr; + int n; + struct sockaddr_storage *req_addr; int winner = -1; - u_int32_t xid_seed, xid_lookup; - int sock, dontblock = 1; - CLIENT *clnt; + u_int32_t xid_seed; char *foo = dom; int validsrvs = 0; + u_short yp_port; + struct transport tsp[TSP_LEN] = { +#ifdef INET6 + {NULL, 0, NULL, -1}, +#endif + {NULL, 0, NULL, -1} + }; /* Set up handles. */ reqs = calloc(1, sizeof(struct ping_req *) * cnt); xid_seed = time(NULL) ^ getpid(); for (i = 0; i < cnt; i++) { - bzero((char *)&sin, sizeof(sin)); - sin.sin_family = AF_INET; - bcopy((char *)&restricted_addrs[i], - (char *)&sin.sin_addr, sizeof(struct in_addr)); - sin.sin_port = htons(__pmap_getport(&sin, YPPROG, - YPVERS, IPPROTO_UDP)); - if (sin.sin_port == 0) + yp_port = __yp_getport(&restricted_addrs[i], CONNLESS_TSP); + if (yp_port == 0) continue; reqs[i] = calloc(1, sizeof(struct ping_req)); - bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin)); - any = &reqs[i]->sin; + req_addr = &reqs[i]->sst; + bcopy((char *)&restricted_addrs[i], (char *)req_addr, sizeof(*req_addr)); +#ifdef INET6 + if (ss_family(req_addr) == AF_INET6) { + ss_to_sin6port(req_addr) = yp_port; + tsp[V6].any = req_addr; + } + else /* AF_INET */ +#endif + { + ss_to_sinport(req_addr) = yp_port; + tsp[V4].any = req_addr; + } reqs[i]->xid = xid_seed; xid_seed++; validsrvs++; } /* Make sure at least one server was assigned */ - if (!validsrvs) { - free(reqs); - return(-1); - } + if (!validsrvs) + goto err; - /* Create RPC handle */ - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock); - if (clnt == NULL) { - close(sock); - for (i = 0; i < cnt; i++) - if (reqs[i] != NULL) - free(reqs[i]); - free(reqs); - return(-1); - } - clnt->cl_auth = authunix_create_default(); - tv.tv_sec = 0; - - clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv); - async = TRUE; - clnt_control(clnt, CLSET_ASYNC, (char *)&async); - ioctl(sock, FIONBIO, &dontblock); + /* Create RPC transports + * an inet4 transport for any V4 address existing in `reqs' + * an inet6 transport for any V6 address existing in `reqs' + * otherwise, shutdown + * */ + if (rpc_init(tsp)) + goto err; /* Transmit */ - for (i = 0; i < cnt; i++) { + for (i = 0; i < cnt; i++) if (reqs[i] != NULL) { - clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid); - addr.len = sizeof(reqs[i]->sin); - addr.buf = (char *) &reqs[i]->sin; - clnt_control(clnt, CLSET_SVC_ADDR, &addr); - ypproc_domain_nonack_2_send(&foo, clnt); + req_addr = &reqs[i]->sst; + n = (ss_family(req_addr) == AF_INET ? V4 : V6); + clnt_control(tsp[n].clnt, CLSET_XID, (char *)&reqs[i]->xid); + tsp[n].addr.buf = (char *) req_addr; + clnt_control(tsp[n].clnt, CLSET_SVC_ADDR, &tsp[n].addr); + ypproc_domain_nonack_2_send(&foo, tsp[n].clnt); } - } /* Receive reply */ - ypproc_domain_nonack_2_recv(&foo, clnt); + for (i = 0; i < TSP_LEN; ++i) + if (tsp[i].clnt) + ypproc_domain_nonack_2_recv(&foo, tsp[i].clnt); + + /* Get the winner */ + for (i = 0; i < TSP_LEN; ++i) + if (tsp[i].clnt) + clnt_control(tsp[i].clnt, CLGET_XID, (char *)&tsp[i].xid_lookup); - /* Got a winner -- look him up. */ - clnt_control(clnt, CLGET_XID, (char *)&xid_lookup); - for (i = 0; i < cnt; i++) { - if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) { - winner = i; - *port = reqs[i]->sin.sin_port; + /* Look him up */ + for (i = 0; i < cnt; i++) + if (reqs[i] != NULL) { + for (n = 0; n < TSP_LEN; ++n) + if (reqs[i]->xid == tsp[n].xid_lookup) { +#ifdef INET6 + if (n == V6) + *port = ss_to_sin6port(&reqs[i]->sst); /* Network byte order */ + else /* V4 */ +#endif + *port = ss_to_sinport(&reqs[i]->sst); + winner = i; + break; + } + if (winner > 0) + break; } - } - + /* Shut everything down */ - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - close(sock); - - for (i = 0; i < cnt; i++) - if (reqs[i] != NULL) - free(reqs[i]); +err: + rpc_destroy(tsp); + if (validsrvs) { + for (i = 0; i < cnt; i++) + if (reqs[i] != NULL) + free(reqs[i]); + } free(reqs); - return(winner); } Index: freebsd-head/usr.sbin/ypbind/ypbind.c =================================================================== --- freebsd-head/usr.sbin/ypbind/ypbind.c (revision 239326) +++ freebsd-head/usr.sbin/ypbind/ypbind.c (working copy) @@ -57,11 +57,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include +#include #include #include "yp_ping.h" @@ -69,6 +71,10 @@ __FBSDID("$FreeBSD$"); #define BINDINGDIR "/var/yp/binding" #endif +#if !defined(BINDINGDIR_V2) && defined(YPBIND_COMPAT_V2) +#define BINDINGDIR_V2 "/var/yp/binding.2" +#endif + #ifndef YPBINDLOCK #define YPBINDLOCK "/var/run/ypbind.lock" #endif @@ -76,9 +82,12 @@ __FBSDID("$FreeBSD$"); struct _dom_binding { struct _dom_binding *dom_pnext; char dom_domain[YPMAXDOMAIN + 1]; - struct sockaddr_in dom_server_addr; + struct sockaddr_storage dom_server_addr; long int dom_vers; int dom_lockfd; +#ifdef YPBIND_COMPAT_V2 + int dom_lockfd_v2; +#endif int dom_alive; int dom_broadcast_pid; int dom_pipe_fds[2]; @@ -89,22 +98,26 @@ struct _dom_binding { #define WRITEFD ypdb->dom_pipe_fds[1] #define BROADFD broad_domain->dom_pipe_fds[1] -extern bool_t xdr_domainname(), xdr_ypbind_resp(); +extern bool_t xdr_domainname(); extern bool_t xdr_ypreq_key(), xdr_ypresp_val(); -extern bool_t xdr_ypbind_setdom(); +extern bool_t xdr_ypbind_setdom(), xdr_ypbind_setdom_v2(); +extern bool_t xdr_ypbind_resp(), xdr_ypbind_resp_v2(); +void *ypbindproc_null(SVCXPRT *, void *, const rpcvers_t); +void *ypbindproc_setdom(SVCXPRT *, const union ypbf_setdom *, const rpcvers_t); +char *ypbindproc_domain(SVCXPRT *, domainname *, const rpcvers_t); +void ypbindprog(struct svc_req *, register SVCXPRT *); +void reaper(int); +void terminate(int); void checkwork(void); -void *ypbindproc_null_2_yp(SVCXPRT *, void *, CLIENT *); -void *ypbindproc_setdom_2_yp(SVCXPRT *, struct ypbind_setdom *, CLIENT *); -void rpc_received(char *, struct sockaddr_in *, int); +void handle_children(struct _dom_binding *); +int tell_parent(char *, const struct sockaddr_storage *); +bool_t broadcast_result(bool_t *, const struct netbuf *, const struct netconfig *); void broadcast(struct _dom_binding *); int ping(struct _dom_binding *); -int tell_parent(char *, struct sockaddr_in *); -void handle_children(struct _dom_binding *); -void reaper(int); -void terminate(int); +void rpc_received(char *, const struct sockaddr_storage *, int); +int verify(const struct sockaddr_storage *); void yp_restricted_mode(char *); -int verify(struct in_addr); char *domain_name; struct _dom_binding *ypbindlist; @@ -128,7 +141,7 @@ static int not_responding_count = 0; #define RESTRICTED_SERVERS 10 int yp_restricted = 0; int yp_manycast = 0; -struct in_addr restricted_addrs[RESTRICTED_SERVERS]; +struct sockaddr_storage restricted_addrs[RESTRICTED_SERVERS]; /* No more than MAX_CHILDREN child broadcasters at a time. */ #ifndef MAX_CHILDREN @@ -154,32 +167,160 @@ int domains = 0; int yplockfd; fd_set fdsr; -SVCXPRT *udptransp, *tcptransp; +#define CLOSE_LKS 1 +#define FREE_DOMB 2 + +static int +create_domb_file(const struct _dom_binding *ypdb, const char *binding_dir) +{ + char path[MAXPATHLEN]; + int fd; + + sprintf(path, "%s/%s.%ld", binding_dir, + ypdb->dom_domain, ypdb->dom_vers); +#ifdef O_SHLOCK + if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { + (void)mkdir(binding_dir, 0755); + if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) + return (-1); + } +#else + if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { + (void)mkdir(binding_dir, 0755); + if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) + return (-1); + } + flock(fd, LOCK_SH); +#endif + return (fd); +} + +static void +register_domb(struct _dom_binding *ypdb, const struct sockaddr_storage *addr) +{ + struct iovec iov[2]; + struct ypbind_resp ybr; + int family; + u_short port; + + if (ypdb->dom_lockfd != -1) + close(ypdb->dom_lockfd); + + ypdb->dom_lockfd = create_domb_file(ypdb, BINDINGDIR); + if (ypdb->dom_lockfd == -1) + return; + + port = __rpcb_getport("127.0.0.1", CONNLESS_TSP, YPBINDPROG, YPBINDVERS); + iov[0].iov_base = (char *)&port; + iov[0].iov_len = sizeof(port); + iov[1].iov_base = (char *)&ybr; + iov[1].iov_len = sizeof(ybr); + + family = ss_family(addr); + bzero(&ybr, sizeof(ybr)); + ybr.ypresp_status = YPBIND_SUCC_VAL; + ybr.ypresp_family = family; + *(u_short *)&ybr.ypresp_port = *ss_getport(addr); +#ifdef INET6 + if (family == AF_INET6) + bcopy(ss_to_sin6addr(addr), (char *) ybr.ypresp_addr, sizeof(struct in6_addr)); + else +#endif + bcopy(ss_to_sinaddr(addr), (char *) ybr.ypresp_addr, sizeof(struct in_addr)); + + if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { + syslog(LOG_WARNING, "write: %m"); + close(ypdb->dom_lockfd); + ypdb->dom_lockfd = -1; + } +} + +#ifdef YPBIND_COMPAT_V2 +static void +register_domb_v2(struct _dom_binding *ypdb, const struct sockaddr_storage *addr) +{ + struct iovec iov[2]; + struct ypbind_resp_v2 ybr; + int family; + u_short port; + + if (ypdb->dom_lockfd_v2 != -1) + close(ypdb->dom_lockfd_v2); + + ypdb->dom_lockfd_v2 = create_domb_file(ypdb, BINDINGDIR_V2); + if (ypdb->dom_lockfd_v2 == -1) + return; + + port = __rpcb_getport("127.0.0.1", CONNLESS_TSP, YPBINDPROG, YPBINDVERS_2); + iov[0].iov_base = (char *)&port; + iov[0].iov_len = sizeof(port); + iov[1].iov_base = (char *)&ybr; + iov[1].iov_len = sizeof(ybr); + + family = ss_family(addr); + bzero(&ybr, sizeof(ybr)); + if (family != AF_INET) { /* AF_INET6 is not supported in version 2 */ + ybr.ypresp_status = YPBIND_FAIL_VAL; + ybr.ypresp_error_v2 = YPBIND_ERR_FAMILY; + } + else { + ybr.ypresp_status = YPBIND_SUCC_VAL; + bcopy(ss_to_sinaddr(addr), (char *) ybr.ypresp_addr_v2, sizeof(struct in_addr)); + *(u_short *)&ybr.ypresp_port_v2 = ss_to_sinport(addr); + } + + if (writev(ypdb->dom_lockfd_v2, iov, 2) != iov[0].iov_len + iov[1].iov_len) { + syslog(LOG_WARNING, "write: %m"); + close(ypdb->dom_lockfd_v2); + ypdb->dom_lockfd_v2 = -1; + } +} +#endif + +static void +unregister_domb(struct _dom_binding *ypdb, unsigned char mode) +{ + char path[MAXPATHLEN]; + + sprintf(path, "%s/%s.%ld", BINDINGDIR, + ypdb->dom_domain, YPVERS); + if ( (mode & CLOSE_LKS)) + close(ypdb->dom_lockfd); + unlink(path); +#ifdef YPBIND_COMPAT_V2 + sprintf(path, "%s/%s.%ld", BINDINGDIR_V2, + ypdb->dom_domain, YPVERS); + if ( (mode & CLOSE_LKS)) + close(ypdb->dom_lockfd_v2); + unlink(path); +#endif + if ( (mode & FREE_DOMB)) { + free(ypdb); + domains--; + } +} void * -ypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) +ypbindproc_null(SVCXPRT *transp, void *argp, const rpcvers_t version) { - static char res; + static const char res; - bzero(&res, sizeof(res)); - return &res; + return ((void *) &res); } -struct ypbind_resp * -ypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt) +char * +ypbindproc_domain(SVCXPRT *transp, domainname *argp, const rpcvers_t version) { - static struct ypbind_resp res; + static union ypbf_resp res; struct _dom_binding *ypdb; - char path[MAXPATHLEN]; + int family; - bzero(&res, sizeof res); - res.ypbind_status = YPBIND_FAIL_VAL; - res.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; + res.ypbf_rstatus = YPBIND_FAIL_VAL; + res.ypbf_rerror = YPBIND_ERR_NOSERV; if (strchr(*argp, '/')) { - syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ -rejecting.", *argp); - return(&res); + syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- rejecting.", *argp); + return((char *) &res); } for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { @@ -190,20 +331,19 @@ rejecting.", *argp); if (ypdb == NULL) { if (yp_restricted) { syslog(LOG_NOTICE, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp); - return (&res); + return ((char *) &res); } if (domains >= MAX_DOMAINS) { - syslog(LOG_WARNING, "domain limit (%d) exceeded", - MAX_DOMAINS); - res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; - return (&res); + syslog(LOG_WARNING, "domain limit (%d) exceeded", MAX_DOMAINS); + res.ypbf_rerror = YPBIND_ERR_RESC; + return ((char *) &res); } ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); if (ypdb == NULL) { syslog(LOG_WARNING, "malloc: %m"); - res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; - return (&res); + res.ypbf_rerror = YPBIND_ERR_RESC; + return ((char *) &res); } bzero(ypdb, sizeof *ypdb); strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); @@ -211,119 +351,195 @@ rejecting.", *argp); ypdb->dom_alive = 0; ypdb->dom_default = 0; ypdb->dom_lockfd = -1; - sprintf(path, "%s/%s.%ld", BINDINGDIR, - ypdb->dom_domain, ypdb->dom_vers); - unlink(path); +#ifdef YPBIND_COMPAT_V2 + ypdb->dom_lockfd_v2 = -1; +#endif + unregister_domb(ypdb, 0); ypdb->dom_pnext = ypbindlist; ypbindlist = ypdb; domains++; } - if (ping(ypdb)) { - return (&res); - } + if (ping(ypdb)) + return ((char *) &res); - res.ypbind_status = YPBIND_SUCC_VAL; - res.ypbind_resp_u.ypbind_error = 0; /* Success */ - *(u_int32_t *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = - ypdb->dom_server_addr.sin_addr.s_addr; - *(u_short *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = - ypdb->dom_server_addr.sin_port; - /*printf("domain %s at %s/%d\n", ypdb->dom_domain, - inet_ntoa(ypdb->dom_server_addr.sin_addr), - ntohs(ypdb->dom_server_addr.sin_port));*/ - return (&res); + res.ypbf_rstatus = YPBIND_SUCC_VAL; + res.ypbf_rerror = 0; /* Success */ + family = ss_family(&ypdb->dom_server_addr); +#ifdef YPBIND_COMPAT_V2 + if (version == YPBINDVERS_2) { + if (family != AF_INET) { /* AF_INET6 is not supported in version 2 */ + res.ypbf_rstatus = YPBIND_FAIL_VAL; + res.ypbf_rerror = YPBIND_ERR_FAMILY; + } + else { + bcopy(ss_to_sinaddr(&ypdb->dom_server_addr), (char *) res.ypbf_raddr_v2, sizeof(struct in_addr)); + *(u_short *)&res.ypbf_rport_v2 = ss_to_sinport(&ypdb->dom_server_addr); + } + } + else +#endif + { + res.ypbf_rfamily = family; + *(u_short *)&res.ypbf_rport = *ss_getport(&ypdb->dom_server_addr); +#ifdef INET6 + if (family == AF_INET6) + bcopy(ss_to_sin6addr(&ypdb->dom_server_addr), (char *) res.ypbf_raddr, sizeof(struct in6_addr)); + else +#endif + bcopy(ss_to_sinaddr(&ypdb->dom_server_addr), (char *) res.ypbf_raddr, sizeof(struct in_addr)); + } + return ((char *) &res); } -void * -ypbindproc_setdom_2_yp(SVCXPRT *transp, ypbind_setdom *argp, CLIENT *clnt) +static int +is_loopback(const char *buf, size_t len) { - struct sockaddr_in *fromsin, bindsin; - static char *result = NULL; + int ret = 0; - if (strchr(argp->ypsetdom_domain, '/')) { - syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ -rejecting.", argp->ypsetdom_domain); - return(NULL); - } - fromsin = svc_getcaller(transp); - - switch (ypsetmode) { - case YPSET_LOCAL: - if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { - svcerr_noprog(transp); - return(NULL); - } + switch (len) { + case sizeof(struct sockaddr_in) : + if (((struct sockaddr_in *) buf)->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) + ret = 1; break; - case YPSET_ALL: +#ifdef INET6 + case sizeof(struct sockaddr_in6) : + if (IN6_IS_ADDR_LOOPBACK(&((struct sockaddr_in6 *) buf)->sin6_addr)) + ret = 1; break; - case YPSET_NO: - default: - svcerr_noprog(transp); - return(NULL); +#endif + default : + ret = -1; } + return (ret); +} - if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) { - svcerr_noprog(transp); - return(NULL); - } +void * +ypbindproc_setdom(SVCXPRT *transp, const union ypbf_setdom *argp, const rpcvers_t version) +{ + struct sockaddr_storage bindaddr; + static char *result = NULL; + struct netbuf *addr; + int r; - if (argp->ypsetdom_vers != YPVERS) { - svcerr_noprog(transp); - return(NULL); - } + struct sockaddr_in * const sin = (struct sockaddr_in *) &bindaddr; +#ifdef INET6 + struct sockaddr_in6 * const sin6 = (struct sockaddr_in6 *) &bindaddr; +#endif - bzero(&bindsin, sizeof bindsin); - bindsin.sin_family = AF_INET; - bindsin.sin_addr.s_addr = *(u_int32_t *)argp->ypsetdom_binding.ypbind_binding_addr; - bindsin.sin_port = *(u_short *)argp->ypsetdom_binding.ypbind_binding_port; - rpc_received(argp->ypsetdom_domain, &bindsin, 1); + if (strchr(argp->ypbf_sdomain, '/')) { + syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- rejecting.", argp->ypbf_sdomain); + return (NULL); + } + addr = svc_getrpccaller(transp); + r = is_loopback(addr->buf, addr->len); + if (r < 0) { + syslog(LOG_WARNING, "Query from an unsupported address -- rejecting."); + return (NULL); + } + if ((ypsetmode == YPSET_LOCAL && r == 0) || ypsetmode != YPSET_ALL) + goto err; + + /* It's ok to consider addr.buf as a sockaddr_storage structure + * ss_* macros never deal with its real representation */ + if (ntohs(*ss_getport(addr->buf)) >= IPPORT_RESERVED) + goto err; + + bzero(&bindaddr, sizeof(bindaddr)); +#ifdef YPBIND_COMPAT_V2 + if (version == YPBINDVERS_2) { + if (argp->ypbf_svers_v2 != YPVERS) + goto err; + + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + bcopy(argp->ypbf_saddr_v2, &sin->sin_addr, sizeof(struct in_addr)); + sin->sin_port = *(u_short *)&argp->ypbf_sport_v2; + } + else +#endif + { + if (argp->ypbf_svers != YPVERS) + goto err; + + switch (argp->ypbf_sfamily) { + case AF_INET : + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + bcopy(argp->ypbf_saddr, &sin->sin_addr, sizeof(struct in_addr)); + sin->sin_port = *(u_short *)&argp->ypbf_sport; + break; +#ifdef INET6 + case AF_INET6 : + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(struct sockaddr_in6); + bcopy(argp->ypbf_saddr, &sin6->sin6_addr, sizeof(struct in6_addr)); + sin6->sin6_port = *(u_short *)&argp->ypbf_sport; + break; +#endif + default : + syslog(LOG_WARNING, "Request an unsupported family -- rejecting."); + return (NULL); + } + } + rpc_received((char *) argp->ypbf_sdomain, &bindaddr, 1); return((void *) &result); + +err: + svcerr_noprog(transp); + return (NULL); } void -ypbindprog_2(struct svc_req *rqstp, register SVCXPRT *transp) +ypbindprog(struct svc_req *rqstp, register SVCXPRT *transp) { + typedef char *(*funcptr)(); union { - domainname ypbindproc_domain_2_arg; - struct ypbind_setdom ypbindproc_setdom_2_arg; + domainname domain; + union ypbf_setdom setdom_arg; } argument; - struct authunix_parms *creds; + struct authsys_parms *creds; char *result; + const rpcvers_t version = rqstp->rq_vers; bool_t (*xdr_argument)(), (*xdr_result)(); - char *(*local)(); + funcptr local; switch (rqstp->rq_proc) { case YPBINDPROC_NULL: xdr_argument = xdr_void; xdr_result = xdr_void; - local = (char *(*)()) ypbindproc_null_2_yp; + local = (funcptr) ypbindproc_null; break; case YPBINDPROC_DOMAIN: xdr_argument = xdr_domainname; - xdr_result = xdr_ypbind_resp; - local = (char *(*)()) ypbindproc_domain_2_yp; + if (version == YPBINDVERS_2) + xdr_result = xdr_ypbind_resp_v2; + else + xdr_result = xdr_ypbind_resp; + local = (funcptr) ypbindproc_domain; break; case YPBINDPROC_SETDOM: switch (rqstp->rq_cred.oa_flavor) { - case AUTH_UNIX: - creds = (struct authunix_parms *)rqstp->rq_clntcred; + case AUTH_SYS: + creds = (struct authsys_parms *) rqstp->rq_clntcred; if (creds->aup_uid != 0) { svcerr_auth(transp, AUTH_BADCRED); return; } break; default: - svcerr_auth(transp, AUTH_TOOWEAK); + svcerr_weakauth(transp); return; } - - xdr_argument = xdr_ypbind_setdom; + if (version == YPBINDVERS_2) + xdr_argument = xdr_ypbind_setdom_v2; + else + xdr_argument = xdr_ypbind_setdom; xdr_result = xdr_void; - local = (char *(*)()) ypbindproc_setdom_2_yp; + local = (funcptr) ypbindproc_setdom; break; default: @@ -335,7 +551,7 @@ ypbindprog_2(struct svc_req *rqstp, regi svcerr_decode(transp); return; } - result = (*local)(transp, &argument, rqstp); + result = (*local)(transp, &argument, version); if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { svcerr_systemerr(transp); @@ -357,25 +573,43 @@ void terminate(int sig) { struct _dom_binding *ypdb; - char path[MAXPATHLEN]; if (ppid != getpid()) exit(0); for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { - close(ypdb->dom_lockfd); if (ypdb->dom_broadcast_pid) kill(ypdb->dom_broadcast_pid, SIGINT); - sprintf(path, "%s/%s.%ld", BINDINGDIR, - ypdb->dom_domain, ypdb->dom_vers); - unlink(path); + unregister_domb(ypdb, CLOSE_LKS); } close(yplockfd); unlink(YPBINDLOCK); - pmap_unset(YPBINDPROG, YPBINDVERS); + rpcb_unset(YPBINDPROG, YPBINDVERS, NULL); +#ifdef YPBIND_COMPAT_V2 + rpcb_unset(YPBINDPROG, YPBINDVERS_2, NULL); +#endif exit(0); } +/* The string `message' is evaluated two times, thus the correct format to add the address is %%s + * Beware of side effects using other %% notations */ +static void +logwaddr(int priority, const struct sockaddr_storage *addr, const char *message, ...) +{ + char buf[256]; /* Maximum message length */ + va_list args; + int family; + char *ptr; + char str[ADDRSTRLEN]; + + if (ss_extract(addr, &family, &ptr, 0)) + return; + va_start(args, message); + vsnprintf(buf, sizeof(buf), message, args); + syslog(priority, buf, inet_ntop(family, ptr, str, ADDRSTRLEN)); + va_end(args); +} + int main(int argc, char *argv[]) { @@ -384,6 +618,7 @@ main(int argc, char *argv[]) DIR *dird; struct dirent *dirp; struct _dom_binding *ypdb, *next; + char path[MAXPATHLEN]; /* Check that another ypbind isn't already running. */ if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) @@ -412,10 +647,9 @@ main(int argc, char *argv[]) errx(1, "unknown option: %s", argv[i]); } - /* blow away everything in BINDINGDIR (if it exists) */ + /* blow away everything in BINDINGDIR/BINDINGDIR_V2 (if they exist) */ if ((dird = opendir(BINDINGDIR)) != NULL) { - char path[MAXPATHLEN]; while ((dirp = readdir(dird)) != NULL) if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { @@ -424,28 +658,37 @@ main(int argc, char *argv[]) } closedir(dird); } +#ifdef YPBIND_COMPAT_V2 + if ((dird = opendir(BINDINGDIR_V2)) != NULL) { + while ((dirp = readdir(dird)) != NULL) + if (strcmp(dirp->d_name, ".") && + strcmp(dirp->d_name, "..")) { + sprintf(path,"%s/%s",BINDINGDIR_V2,dirp->d_name); + unlink(path); + } + closedir(dird); + } +#endif #ifdef DAEMON if (daemon(0,0)) err(1, "fork"); #endif - pmap_unset(YPBINDPROG, YPBINDVERS); - - udptransp = svcudp_create(RPC_ANYSOCK); - if (udptransp == NULL) - errx(1, "cannot create udp service"); - if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, - IPPROTO_UDP)) - errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)"); - - tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); - if (tcptransp == NULL) - errx(1, "cannot create tcp service"); - - if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, - IPPROTO_TCP)) - errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); + rpcb_unset(YPBINDPROG, YPBINDVERS, NULL); +#ifdef YPBIND_COMPAT_V2 + rpcb_unset(YPBINDPROG, YPBINDVERS_2, NULL); +#endif + if (!svc_create(ypbindprog, YPBINDPROG, YPBINDVERS, CONNLESS_TSP)) + errx(1, "cannot create %s service", CONNLESS_TSP); + if (!svc_create(ypbindprog, YPBINDPROG, YPBINDVERS, CONNFULL_TSP)) + errx(1, "cannot create %s service", CONNFULL_TSP); +#ifdef YPBIND_COMPAT_V2 + if (!svc_create(ypbindprog, YPBINDPROG, YPBINDVERS_2, CONNLESS_TSP)) + errx(1, "cannot create %s service", CONNLESS_TSP); + if (!svc_create(ypbindprog, YPBINDPROG, YPBINDVERS_2, CONNFULL_TSP)) + errx(1, "cannot create %s service", CONNFULL_TSP); +#endif /* build initial domain binding, make it "unsuccessful" */ ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); @@ -456,6 +699,9 @@ main(int argc, char *argv[]) ypbindlist->dom_vers = YPVERS; ypbindlist->dom_alive = 0; ypbindlist->dom_lockfd = -1; +#ifdef YPBIND_COMPAT_V2 + ypbindlist->dom_lockfd_v2 = -1; +#endif ypbindlist->dom_default = 1; domains++; @@ -529,15 +775,14 @@ void handle_children(struct _dom_binding *ypdb) { char buf[YPMAXDOMAIN + 1]; - struct sockaddr_in addr; + struct sockaddr_storage addr; int d = 0, a = 0; struct _dom_binding *y, *prev = NULL; - char path[MAXPATHLEN]; if ((d = read(READFD, &buf, sizeof(buf))) <= 0) syslog(LOG_WARNING, "could not read from child: %m"); - if ((a = read(READFD, &addr, sizeof(struct sockaddr_in))) < 0) + if ((a = read(READFD, &addr, sizeof(addr))) < 0) syslog(LOG_WARNING, "could not read from child: %m"); close(READFD); @@ -558,12 +803,7 @@ handle_children(struct _dom_binding *ypd ypbindlist = y->dom_pnext; else prev->dom_pnext = y->dom_pnext; - sprintf(path, "%s/%s.%ld", BINDINGDIR, - ypdb->dom_domain, YPVERS); - close(ypdb->dom_lockfd); - unlink(path); - free(ypdb); - domains--; + unregister_domb(ypdb, CLOSE_LKS | FREE_DOMB); return; case 1: ypdb->dom_broadcast_pid = 0; @@ -582,7 +822,7 @@ handle_children(struct _dom_binding *ypd * Send our dying words back to our parent before we perish. */ int -tell_parent(char *dom, struct sockaddr_in *addr) +tell_parent(char *dom, const struct sockaddr_storage *addr) { char buf[YPMAXDOMAIN + 1]; struct timeval timeout; @@ -605,7 +845,7 @@ tell_parent(char *dom, struct sockaddr_i if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == -1) return(1); if (FD_ISSET(BROADFD, &fds)) { - if (write(BROADFD, addr, sizeof(struct sockaddr_in)) < 0) + if (write(BROADFD, addr, sizeof(*addr)) < 0) return(1); } else { return(1); @@ -615,23 +855,28 @@ tell_parent(char *dom, struct sockaddr_i return (0); } -bool_t broadcast_result(out, addr) -bool_t *out; -struct sockaddr_in *addr; +bool_t +broadcast_result(bool_t *out, const struct netbuf *addr, + const struct netconfig * netconf) { + struct sockaddr_storage sst; + + if (addr->len > sizeof(sst) || strcmp(netconf->nc_netid, CONNLESS_TSP)) + return (FALSE); + bzero((char*) &sst, sizeof(sst)); if (retries >= MAX_RETRIES) { - bzero(addr, sizeof(struct sockaddr_in)); - if (tell_parent(broad_domain->dom_domain, addr)) + if (tell_parent(broad_domain->dom_domain, &sst)) syslog(LOG_WARNING, "lost connection to parent"); return (TRUE); } - - if (yp_restricted && verify(addr->sin_addr)) { + bcopy(addr->buf, (char *) &sst, addr->len); + if (yp_restricted && verify(&sst)) { retries++; - syslog(LOG_NOTICE, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr->sin_addr)); + logwaddr(LOG_NOTICE, &sst, "NIS server at %%s not in restricted mode access list -- rejecting.\n"); return (FALSE); - } else { - if (tell_parent(broad_domain->dom_domain, addr)) + } + else { + if (tell_parent(broad_domain->dom_domain, &sst)) syslog(LOG_WARNING, "lost connection to parent"); return (TRUE); } @@ -650,6 +895,7 @@ struct sockaddr_in *addr; void broadcast(struct _dom_binding *ypdb) { + static const struct sockaddr_storage null_addr; bool_t out = FALSE; enum clnt_stat stat; @@ -661,16 +907,21 @@ broadcast(struct _dom_binding *ypdb) return; } - if (ypdb->dom_vers == -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr) { + /* bcmp should be safe here due to the earlier dom_server_addr memset which + * prevents us from alignement issues */ + if (ypdb->dom_vers == -1 && bcmp(&ypdb->dom_server_addr, &null_addr, sizeof(null_addr))) { if (not_responding_count++ >= NOT_RESPONDING_HYSTERESIS) { not_responding_count = NOT_RESPONDING_HYSTERESIS; - syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding", - inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain); + logwaddr(LOG_WARNING, &ypdb->dom_server_addr, + "NIS server [%%s] for domain \"%s\" not responding", ypdb->dom_domain); } } broad_domain = ypdb; flock(ypdb->dom_lockfd, LOCK_UN); +#ifdef YPBIND_COMPAT_V2 + flock(ypdb->dom_lockfd_v2, LOCK_UN); +#endif switch ((ypdb->dom_broadcast_pid = fork())) { case 0: @@ -693,6 +944,9 @@ broadcast(struct _dom_binding *ypdb) /* Release all locks before doing anything else. */ while (ypbindlist) { close(ypbindlist->dom_lockfd); +#ifdef YPBIND_COMPAT_V2 + close(ypbindlist->dom_lockfd_v2); +#endif ypbindlist = ypbindlist->dom_pnext; } close(yplockfd); @@ -706,27 +960,20 @@ broadcast(struct _dom_binding *ypdb) * operation: we transmit uni-cast datagrams only. */ if (yp_restricted && yp_manycast) { - short port; + u_short port; int i; - struct sockaddr_in sin; + struct sockaddr_storage sst; - i = __yp_ping(restricted_addrs, yp_restricted, - ypdb->dom_domain, &port); + i = __yp_ping(restricted_addrs, yp_restricted, ypdb->dom_domain, &port); if (i == -1) { - bzero(&ypdb->dom_server_addr, - sizeof(struct sockaddr_in)); - if (tell_parent(ypdb->dom_domain, - &ypdb->dom_server_addr)) + bzero(&ypdb->dom_server_addr, sizeof(struct sockaddr_storage)); + if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) syslog(LOG_WARNING, "lost connection to parent"); } else { - bzero(&sin, sizeof(struct sockaddr_in)); - bcopy(&restricted_addrs[i], - &sin.sin_addr, sizeof(struct in_addr)); - sin.sin_family = AF_INET; - sin.sin_port = port; - if (tell_parent(broad_domain->dom_domain, &sin)) - syslog(LOG_WARNING, - "lost connection to parent"); + bcopy(&restricted_addrs[i], &sst, sizeof(sst)); + *ss_getport(&sst) = port; + if (tell_parent(broad_domain->dom_domain, &sst)) + syslog(LOG_WARNING, "lost connection to parent"); } _exit(0); } @@ -737,15 +984,14 @@ broadcast(struct _dom_binding *ypdb) char *ptr; ptr = ypdb->dom_domain; - stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, - (xdrproc_t)xdr_domainname, &ptr, - (xdrproc_t)xdr_bool, &out, - (resultproc_t)broadcast_result); + stat = rpc_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, + (xdrproc_t)xdr_domainname, (const caddr_t) &ptr, + (xdrproc_t)xdr_bool, (const caddr_t) &out, + (resultproc_t)broadcast_result, CONNLESS_TSP); } if (stat != RPC_SUCCESS) { - bzero(&ypdb->dom_server_addr, - sizeof(struct sockaddr_in)); + bzero(&ypdb->dom_server_addr, sizeof(struct sockaddr_storage)); if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) syslog(LOG_WARNING, "lost connection to parent"); } @@ -753,6 +999,40 @@ broadcast(struct _dom_binding *ypdb) _exit(0); } +static CLIENT * +yp_udpclient(struct sockaddr_storage *sst, int *sock) +{ + int family; + int s = -1; + CLIENT *client = NULL; + struct netbuf addr; + struct timeval interval; + + interval.tv_sec = FAIL_THRESHOLD; + interval.tv_usec = 0; + + family = ss_family(sst); + if (family == AF_INET) + addr.len = sizeof(struct sockaddr_in); + else /* AF_INET6 */ +#ifdef INET6 + addr.len = sizeof(struct sockaddr_in6); +#else + goto err; +#endif + addr.buf = sst; + if ((s = socket(family, SOCK_DGRAM, IPPROTO_UDP)) < 0) + goto err; + client = clnt_dg_create(s, &addr, YPPROG, YPVERS, + RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + clnt_control(client, CLSET_RETRY_TIMEOUT, &interval); +err: + if (!client) + close(s); + *sock = s; + return (client); +} + /* * The right way to check if a server is alive. * Attempt to get a client handle pointing to the server and send a @@ -769,61 +1049,51 @@ int ping(struct _dom_binding *ypdb) { bool_t out; - struct timeval interval, timeout; + struct timeval timeout; enum clnt_stat stat; - int rpcsock = RPC_ANYSOCK; - CLIENT *client_handle; + int rpcsock, err = 0; + CLIENT *client; - interval.tv_sec = FAIL_THRESHOLD; - interval.tv_usec = 0; timeout.tv_sec = FAIL_THRESHOLD; timeout.tv_usec = 0; if (ypdb->dom_broadcast_pid) return(1); - if ((client_handle = clntudp_bufcreate(&ypdb->dom_server_addr, - YPPROG, YPVERS, interval, &rpcsock, RPCSMALLMSGSIZE, - RPCSMALLMSGSIZE)) == (CLIENT *)NULL) { + if ((client = yp_udpclient(&ypdb->dom_server_addr, &rpcsock)) == NULL) { /* Can't get a handle: we're dead. */ - ypdb->dom_alive = 0; - ypdb->dom_vers = -1; - broadcast(ypdb); - return(1); + err = 1; + goto err; } { - char *ptr; + char *ptr = ypdb->dom_domain; - ptr = ypdb->dom_domain; - - stat = clnt_call(client_handle, YPPROC_DOMAIN, + stat = clnt_call(client, YPPROC_DOMAIN, (xdrproc_t)xdr_domainname, &ptr, (xdrproc_t)xdr_bool, &out, timeout); - if (stat != RPC_SUCCESS || out == FALSE) { - ypdb->dom_alive = 0; - ypdb->dom_vers = -1; - clnt_destroy(client_handle); - broadcast(ypdb); - return(1); - } + if (stat != RPC_SUCCESS || out == FALSE) + err = 1; } - - clnt_destroy(client_handle); - return(0); +err: + if (err) { + ypdb->dom_alive = 0; + ypdb->dom_vers = -1; + broadcast(ypdb); + } + if (client) { + close(rpcsock); + clnt_destroy(client); + } + return(err); } void -rpc_received(char *dom, struct sockaddr_in *raddrp, int force) +rpc_received(char *dom, const struct sockaddr_storage *raddrp, int force) { + static const struct sockaddr_storage null_addr; struct _dom_binding *ypdb, *prev = NULL; - struct iovec iov[2]; - struct ypbind_resp ybr; - char path[MAXPATHLEN]; - int fd; - - /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr), - ntohs(raddrp->sin_port), dom);*/ + u_short port; if (dom == NULL) return; @@ -844,11 +1114,10 @@ rpc_received(char *dom, struct sockaddr_ } } + port = ntohs(*ss_getport(raddrp)); /* if in secure mode, check originating port number */ - if ((ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED))) { - syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.", - inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), - dom); + if (ypsecuremode && port >= IPPORT_RESERVED) { + logwaddr(LOG_WARNING, raddrp, "Rejected NIS server on [%%s/%d] for domain %s.", port, dom); if (ypdb != NULL) { ypdb->dom_broadcast_pid = 0; ypdb->dom_alive = 0; @@ -856,19 +1125,16 @@ rpc_received(char *dom, struct sockaddr_ return; } - if (raddrp->sin_addr.s_addr == (long)0) { + /* bcmp should be safe here due to the earlier raddrp memset which + * prevents us from alignement issues */ + if (!bcmp((char *) raddrp, (char *) &null_addr, sizeof(null_addr))) { switch (ypdb->dom_default) { case 0: if (prev == NULL) ypbindlist = ypdb->dom_pnext; else prev->dom_pnext = ypdb->dom_pnext; - sprintf(path, "%s/%s.%ld", BINDINGDIR, - ypdb->dom_domain, YPVERS); - close(ypdb->dom_lockfd); - unlink(path); - free(ypdb); - domains--; + unregister_domb(ypdb, CLOSE_LKS | FREE_DOMB); return; case 1: ypdb->dom_broadcast_pid = 0; @@ -891,17 +1157,20 @@ rpc_received(char *dom, struct sockaddr_ bzero(ypdb, sizeof *ypdb); strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); ypdb->dom_lockfd = -1; +#ifdef YPBIND_COMPAT_V2 + ypdb->dom_lockfd_v2 = -1; +#endif ypdb->dom_default = 0; ypdb->dom_pnext = ypbindlist; ypbindlist = ypdb; } /* We've recovered from a crash: inform the world. */ - if (ypdb->dom_vers == -1 && ypdb->dom_server_addr.sin_addr.s_addr) { + if (ypdb->dom_vers == -1 && bcmp(&ypdb->dom_server_addr, &null_addr, sizeof(null_addr))) { if (not_responding_count >= NOT_RESPONDING_HYSTERESIS) { not_responding_count = 0; - syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" OK", - inet_ntoa(raddrp->sin_addr), ypdb->dom_domain); + logwaddr(LOG_WARNING, raddrp, "NIS server [%%s] for domain \"%s\" OK", + ypdb->dom_domain); } } @@ -912,48 +1181,10 @@ rpc_received(char *dom, struct sockaddr_ ypdb->dom_alive = 1; ypdb->dom_broadcast_pid = 0; - if (ypdb->dom_lockfd != -1) - close(ypdb->dom_lockfd); - - sprintf(path, "%s/%s.%ld", BINDINGDIR, - ypdb->dom_domain, ypdb->dom_vers); -#ifdef O_SHLOCK - if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { - (void)mkdir(BINDINGDIR, 0755); - if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) - return; - } -#else - if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { - (void)mkdir(BINDINGDIR, 0755); - if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) - return; - } - flock(fd, LOCK_SH); + register_domb(ypdb, raddrp); +#ifdef YPBIND_COMPAT_V2 + register_domb_v2(ypdb, raddrp); #endif - - /* - * ok, if BINDINGDIR exists, and we can create the binding file, - * then write to it.. - */ - ypdb->dom_lockfd = fd; - - iov[0].iov_base = (char *)&(udptransp->xp_port); - iov[0].iov_len = sizeof udptransp->xp_port; - iov[1].iov_base = (char *)&ybr; - iov[1].iov_len = sizeof ybr; - - bzero(&ybr, sizeof ybr); - ybr.ypbind_status = YPBIND_SUCC_VAL; - *(u_int32_t *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr.s_addr; - *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port; - - if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { - syslog(LOG_WARNING, "write: %m"); - close(ypdb->dom_lockfd); - ypdb->dom_lockfd = -1; - return; - } } /* @@ -961,14 +1192,20 @@ rpc_received(char *dom, struct sockaddr_ * 1 if not matched. */ int -verify(struct in_addr addr) +verify(const struct sockaddr_storage *addr) { + int restrict_family, addr_family; + char *restrict_ptr, *addr_ptr; + size_t restrict_len, addr_len; int i; - for (i = 0; i < RESTRICTED_SERVERS; i++) - if (!bcmp(&addr, &restricted_addrs[i], sizeof(struct in_addr))) - return(0); - + for (i = 0; i < RESTRICTED_SERVERS; i++) { + if (ss_extract(&restricted_addrs[i], &restrict_family, &restrict_ptr, &restrict_len) + || ss_extract(addr, &addr_family, &addr_ptr, &addr_len)) + return (1); + if (restrict_family == addr_family && !bcmp(addr_ptr, restrict_ptr, addr_len)) + return (0); + } return(1); } @@ -979,7 +1216,7 @@ verify(struct in_addr addr) void yp_restricted_mode(char *args) { - struct hostent *h; + struct addrinfo hint, *res; int i = 0; char *s; @@ -988,12 +1225,19 @@ yp_restricted_mode(char *args) return; domain_name = s; + bzero(&hint, sizeof(hint)); /* Get the addresses of the servers. */ while ((s = strsep(&args, ",")) != NULL && i < RESTRICTED_SERVERS) { - if ((h = gethostbyname(s)) == NULL) + hint.ai_flags = AI_ADDRCONFIG; +#ifdef INET6 + hint.ai_family = PF_UNSPEC; +#else + hint.ai_family = PF_INET; +#endif + if (getaddrinfo(s, 0, &hint, &res)) return; - bcopy (h->h_addr_list[0], &restricted_addrs[i], - sizeof(struct in_addr)); + bcopy ((char *) res->ai_addr, (char *) &restricted_addrs[i], res->ai_addrlen); + freeaddrinfo(res); i++; } Index: freebsd-head/usr.sbin/ypbind/yp_ping.h =================================================================== --- freebsd-head/usr.sbin/ypbind/yp_ping.h (revision 239326) +++ freebsd-head/usr.sbin/ypbind/yp_ping.h (working copy) @@ -2,4 +2,55 @@ * $FreeBSD$ */ -extern int __yp_ping(struct in_addr *, int, char *, short *); +#define CONNFULL_TSP "tcp" +#define CONNLESS_TSP "udp" + +#ifdef INET6 +# define ADDRSTRLEN INET6_ADDRSTRLEN +#else +# define ADDRSTRLEN INET_ADDRSTRLEN +#endif + +#define ss_family(x) (((struct sockaddr *) x)->sa_family) +#define ss_to_sinaddr(x) ((char *) &((struct sockaddr_in *) x)->sin_addr) +#define ss_to_sin6addr(x) ((char *) &((struct sockaddr_in6 *) x)->sin6_addr) +#define ss_to_sinport(x) (((struct sockaddr_in *) x)->sin_port) +#define ss_to_sin6port(x) (((struct sockaddr_in6 *) x)->sin6_port) + +static inline int +ss_extract(const struct sockaddr_storage *ss, int *family, char **addr, size_t *len) +{ + *family = ss_family(ss); + switch (*family) { + case AF_INET: + *addr = ss_to_sinaddr(ss); + if (len) + *len = sizeof(struct in_addr); + break; +#ifdef INET6 + case AF_INET6: + *addr = ss_to_sin6addr(ss); + if (len) + *len = sizeof(struct in6_addr); + break; +#endif + default: + return (1); + } + return (0); +} + +static inline u_short * +ss_getport(const struct sockaddr_storage *ss) +{ +#ifdef INET6 + if (ss_family(ss) == AF_INET6) + return (&ss_to_sin6port(ss)); + else +#endif + return (&ss_to_sinport(ss)); +} + +extern int __yp_ping(struct sockaddr_storage *, int, char *, u_short *); +extern u_short __rpcb_getport(const char *hostname, const char *netid, + const rpcprog_t prognum, const rpcvers_t versnum); Index: freebsd-head/usr.sbin/ypbind/Makefile =================================================================== --- freebsd-head/usr.sbin/ypbind/Makefile (revision 239326) +++ freebsd-head/usr.sbin/ypbind/Makefile (working copy) @@ -1,11 +1,16 @@ # from: @(#)Makefile 5.8 (Berkeley) 7/28/90 # $FreeBSD$ +.include + PROG= ypbind MAN= ypbind.8 SRCS= ypbind.c yp_ping.c -CFLAGS+= -DDAEMON +CFLAGS += -DDAEMON -DYPBIND_COMPAT_V2 +.if ${MK_INET6_SUPPORT} != "no" +CFLAGS += -DINET6 +.endif WARNS?= 2 Index: freebsd-head/lib/libc/yp/yplib.c =================================================================== --- freebsd-head/lib/libc/yp/yplib.c (revision 239326) +++ freebsd-head/lib/libc/yp/yplib.c (working copy) @@ -278,6 +278,8 @@ ypbinderr_string(int incode) return ("Domain not bound"); case YPBIND_ERR_RESC: return ("System resource allocation failure"); + case YPBIND_ERR_FAMILY: + return ("Unsupported family"); } sprintf(err, "Unknown ypbind error: #%d\n", incode); return (err);