From owner-svn-soc-all@FreeBSD.ORG Tue Jul 31 16:20:08 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id D84F2106566B for ; Tue, 31 Jul 2012 16:20:05 +0000 (UTC) (envelope-from exxo@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Tue, 31 Jul 2012 16:20:05 +0000 Date: Tue, 31 Jul 2012 16:20:05 +0000 From: exxo@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120731162005.D84F2106566B@hub.freebsd.org> Cc: Subject: socsvn commit: r239957 - in soc2012/exxo/freebsd-head: include/rpcsvc lib/libc/yp usr.sbin/ypbind X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 Jul 2012 16:20:08 -0000 Author: exxo Date: Tue Jul 31 16:20:04 2012 New Revision: 239957 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=239957 Log: Updating ypbind Modified: soc2012/exxo/freebsd-head/include/rpcsvc/yp.x soc2012/exxo/freebsd-head/include/rpcsvc/yp_prot.h soc2012/exxo/freebsd-head/lib/libc/yp/yplib.c soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c Modified: soc2012/exxo/freebsd-head/include/rpcsvc/yp.x ============================================================================== --- soc2012/exxo/freebsd-head/include/rpcsvc/yp.x Tue Jul 31 15:47:50 2012 (r239956) +++ soc2012/exxo/freebsd-head/include/rpcsvc/yp.x Tue Jul 31 16:20:04 2012 (r239957) @@ -208,12 +208,12 @@ 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 +223,8 @@ ypbind_binding ypsetdom_binding; unsigned ypsetdom_vers; }; +%#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 @@ -247,8 +249,17 @@ unsigned ypsetdom_vers; }; +%#define yprespv2_error ypbind_resp_v2_u.ypbind_error +%#define yprespv2_addr ypbind_resp_v2_u.ypbind_bindinfo.ypbind_binding_addr +%#define yprespv2_port ypbind_resp_v2_u.ypbind_bindinfo.ypbind_binding_port + #endif +%#define ypresp_error ypbind_resp_u.ypbind_error +%#define ypresp_family ypbind_resp_u.ypbind_bindinfo.ypbind_binding_family +%#define ypresp_addr ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr +%#define ypresp_port ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port + /* * NIS v1 support for backwards compatibility */ Modified: soc2012/exxo/freebsd-head/include/rpcsvc/yp_prot.h ============================================================================== --- soc2012/exxo/freebsd-head/include/rpcsvc/yp_prot.h Tue Jul 31 15:47:50 2012 (r239956) +++ soc2012/exxo/freebsd-head/include/rpcsvc/yp_prot.h Tue Jul 31 16:20:04 2012 (r239957) @@ -261,6 +261,7 @@ #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. @@ -295,8 +296,17 @@ u_int ypsetdom_vers; }; +#define yprespv2_error ypbind_resp_v2_u.ypbind_error +#define yprespv2_addr ypbind_resp_v2_u.ypbind_bindinfo.ypbind_binding_addr +#define yprespv2_port ypbind_resp_v2_u.ypbind_bindinfo.ypbind_binding_port + #endif +#define ypresp_error ypbind_resp_u.ypbind_error +#define ypresp_family ypbind_resp_u.ypbind_bindinfo.ypbind_binding_family +#define ypresp_addr ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr +#define ypresp_port ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port + /* * YPPUSH PROTOCOL: * Modified: soc2012/exxo/freebsd-head/lib/libc/yp/yplib.c ============================================================================== --- soc2012/exxo/freebsd-head/lib/libc/yp/yplib.c Tue Jul 31 15:47:50 2012 (r239956) +++ soc2012/exxo/freebsd-head/lib/libc/yp/yplib.c Tue Jul 31 16:20:04 2012 (r239957) @@ -278,6 +278,8 @@ 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); Modified: soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c ============================================================================== --- soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c Tue Jul 31 15:47:50 2012 (r239956) +++ soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c Tue Jul 31 16:20:04 2012 (r239957) @@ -229,25 +229,20 @@ # define TSP_LEN (V4 + 1) #endif -static u_short -__yp_getport(const struct sockaddr_storage *host, const char *netid) +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; - char str[ADDRSTRLEN]; - int family; - char *ptr; svcaddr.len = 0; svcaddr.maxlen = sizeof(sst); svcaddr.buf = &sst; - if (ss_extract(host, &family, &ptr, 0)) - return (0); - inet_ntop(family, ptr, str, ADDRSTRLEN); if ((nconf = getnetconfigent(netid)) == NULL || - !rpcb_getaddr(YPPROG, YPVERS, nconf, &svcaddr, str)) + !rpcb_getaddr(prognum, versnum, nconf, &svcaddr, hostname)) return (0); switch (svcaddr.len) { case sizeof(struct sockaddr_in) : @@ -264,6 +259,19 @@ 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) { @@ -278,13 +286,13 @@ continue; #ifdef INET6 if (i == V6) { - tsp[i]->sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + 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(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + tsp[i]->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); tsp[i]->addr.len = sizeof(struct sockaddr_in); } if (tsp[i]->sock < 0) @@ -322,7 +330,7 @@ } int -__yp_ping(struct sockaddr_storage *restricted_addrs, int cnt, char *dom, short *port) +__yp_ping(struct sockaddr_storage *restricted_addrs, int cnt, char *dom, u_short *port) { struct ping_req **reqs; unsigned long i; @@ -345,7 +353,7 @@ xid_seed = time(NULL) ^ getpid(); for (i = 0; i < cnt; i++) { - yp_port = __yp_getport(&restricted_addrs[i], "udp"); + yp_port = __yp_getport(&restricted_addrs[i], CONNLESS_TSP); if (yp_port == 0) continue; reqs[i] = calloc(1, sizeof(struct ping_req)); Modified: soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h ============================================================================== --- soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h Tue Jul 31 15:47:50 2012 (r239956) +++ soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h Tue Jul 31 16:20:04 2012 (r239957) @@ -2,6 +2,9 @@ * $FreeBSD$ */ +#define CONNFULL_TSP "tcp" +#define CONNLESS_TSP "udp" + #ifdef INET6 # define ADDRSTRLEN INET6_ADDRSTRLEN #else @@ -22,13 +25,13 @@ case AF_INET: *addr = ss_to_sinaddr(ss); if (len) - *len = sizeof(struct sockaddr_in); + *len = sizeof(struct in_addr); break; #ifdef INET6 case AF_INET6: *addr = ss_to_sin6addr(ss); if (len) - *len = sizeof(struct sockaddr_in6); + *len = sizeof(struct in6_addr); break; #endif default: @@ -37,4 +40,17 @@ return (0); } -extern int __yp_ping(struct sockaddr_storage *, int, char *, short *); +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); Modified: soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c ============================================================================== --- soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c Tue Jul 31 15:47:50 2012 (r239956) +++ soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c Tue Jul 31 16:20:04 2012 (r239957) @@ -69,6 +69,10 @@ #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 @@ -79,6 +83,9 @@ struct sockaddr_storage dom_server_addr; /* TODO */ 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]; @@ -148,6 +155,9 @@ #define MAX_RETRIES 30 #endif +#define CLOSE_LKS 1 +#define FREE_DOMB 2 + int retries = 0; int children = 0; int domains = 0; @@ -168,7 +178,6 @@ { static struct ypbind_resp res; struct _dom_binding *ypdb; - char path[MAXPATHLEN]; bzero(&res, sizeof res); res.ypbind_status = YPBIND_FAIL_VAL; @@ -209,9 +218,10 @@ 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++; @@ -355,18 +365,14 @@ 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); @@ -396,6 +402,136 @@ va_end(args); } +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.ypbind_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 */ + ybr2.ypbind_status = YPBIND_FAIL_VAL; + ybr2.yprespv2_error = YPBIND_ERR_FAMILY; + } + else { + ybr2.ypbind_status = YPBIND_SUCC_VAL; + bcopy(ss_to_sinaddr(addr), (char *) ybr2.yprespv2_addr, sizeof(struct in_addr)); + *(u_short *)&ybr2.yprespv2_port = 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(const 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--; + } +} + int main(int argc, char *argv[]) { @@ -404,6 +540,7 @@ 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) @@ -432,10 +569,9 @@ 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, "..")) { @@ -444,6 +580,17 @@ } 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)) @@ -454,15 +601,15 @@ #ifdef YPBIND_COMPAT_V2 rpcb_unset(YPBINDPROG, YPBINDVERS_2, NULL); #endif - if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS, "udp")) /* TODO see how to retrieve xp_port */ - errx(1, "cannot create udp service"); - if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS, "tcp")) - errx(1, "cannot create tcp service"); -#ifdef YPBIND_COMPAT_V2 - if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS_2, "udp")) - errx(1, "cannot create udp service"); - if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS_2, "tcp")) - errx(1, "cannot create tcp service"); + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS, CONNLESS_TSP)) /* TODO see how to retrieve xp_port */ + errx(1, "cannot create %s service", CONNLESS_TSP); + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS, CONNFULL_TSP)) + errx(1, "cannot create %s service", CONNFULL_TSP); +#ifdef YPBIND_COMPAT_V2 + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS_2, CONNLESS_TSP)) + errx(1, "cannot create %s service", CONNLESS_TSP); + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS_2, CONNFULL_TSP)) + errx(1, "cannot create %s service", CONNFULL_TSP); #endif /* build initial domain binding, make it "unsuccessful" */ @@ -474,6 +621,9 @@ 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++; @@ -547,15 +697,14 @@ 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); @@ -576,12 +725,7 @@ 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; @@ -600,7 +744,7 @@ * Send our dying words back to our parent before we perish. */ int -tell_parent(char *dom, struct sockaddr_in *addr) +tell_parent(char *dom, struct sockaddr_storage *addr) { char buf[YPMAXDOMAIN + 1]; struct timeval timeout; @@ -623,7 +767,7 @@ 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); @@ -633,23 +777,28 @@ 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)) { + bcpy(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); } @@ -692,6 +841,9 @@ 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: @@ -714,6 +866,9 @@ /* 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); @@ -727,27 +882,20 @@ * 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); } @@ -758,15 +906,14 @@ char *ptr; ptr = ypdb->dom_domain; - stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, + stat = rpc_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, (xdrproc_t)xdr_domainname, &ptr, (xdrproc_t)xdr_bool, &out, - (resultproc_t)broadcast_result); + (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"); } @@ -774,6 +921,40 @@ _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_sin); + else /* AF_INET6 */ +#ifdef INET6 + addr.len = sizeof(struct sockaddr_sin6); +#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 @@ -790,61 +971,50 @@ 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; - - ptr = ypdb->dom_domain; + char *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, struct sockaddr_storage *raddrp, int force) { + static 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);*/ if (dom == NULL) return; @@ -865,11 +1035,10 @@ } } + 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; @@ -877,19 +1046,16 @@ 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; @@ -912,17 +1078,20 @@ 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); } } @@ -933,48 +1102,10 @@ 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; - } } /* @@ -982,14 +1113,20 @@ * 1 if not matched. */ int -verify(struct in_addr addr) +verify(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); } @@ -1000,7 +1137,7 @@ void yp_restricted_mode(char *args) { - struct hostent *h; + struct addrinfo hint, *res; int i = 0; char *s; @@ -1009,12 +1146,19 @@ 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++; }