diff --git a/usr.sbin/ypbind/yp_ping.h b/usr.sbin/ypbind/yp_ping.h --- a/usr.sbin/ypbind/yp_ping.h +++ b/usr.sbin/ypbind/yp_ping.h @@ -1,4 +1,4 @@ /* */ -extern int __yp_ping(struct in_addr *, int, char *, short *); +extern int __yp_ping(struct sockaddr_storage *, int, char *, short *); diff --git a/usr.sbin/ypbind/yp_ping.c b/usr.sbin/ypbind/yp_ping.c --- a/usr.sbin/ypbind/yp_ping.c +++ b/usr.sbin/ypbind/yp_ping.c @@ -203,7 +203,7 @@ }; 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, short *port) { struct timeval tv = { 5, 0 }; struct ping_req **reqs; @@ -234,6 +234,7 @@ reqs[i] = calloc(1, sizeof(struct ping_req)); bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin)); any = &reqs[i]->sin; + reqs[i]->xid = xid_seed; xid_seed++; validsrvs++; diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c --- a/usr.sbin/ypbind/ypbind.c +++ b/usr.sbin/ypbind/ypbind.c @@ -29,6 +29,7 @@ * SUCH DAMAGE. */ +#define kola #include #include #include @@ -64,6 +65,17 @@ #include #include "yp_ping.h" +#ifdef kola +#include +#include +#include +#include +#include +#define YPBINDVERS_1 ((unsigned long)(1)) +#define YPBINDVERS_2 ((unsigned long)(2)) +typedef char *domainname_2; +#endif + #ifndef BINDINGDIR #define BINDINGDIR "/var/yp/binding" #endif @@ -88,22 +100,70 @@ #define WRITEFD ypdb->dom_pipe_fds[1] #define BROADFD broad_domain->dom_pipe_fds[1] +#ifdef kola +struct ypbind_domain { + char *ypbind_domainname; + rpcvers_t ypbind_vers; +}; +typedef struct ypbind_domain ypbind_domain; + +struct ypbind_binding_3 { + struct netconfig *ypbind_nconf; + struct netbuf *ypbind_svcaddr; + char *ypbind_servername; + rpcvers_t ypbind_hi_vers; + rpcvers_t ypbind_lo_vers; +}; +typedef struct ypbind_binding_3 ypbind_binding_3; + +struct ypbind_setdom_3 { + char *ypsetdom_domain; + struct ypbind_binding_3 *ypsetdom_bindinfo; + u_int ypsetdom_vers; +}; +typedef struct ypbind_setdom_3 ypbind_setdom_3; +struct dom_binding { + struct dom_binding *dom_pnext; + char dom_domain[YPMAXDOMAIN + 1]; + struct ypbind_binding_3 *dom_binding; + long int dom_vers; + int dom_lockfd; + int dom_alive; + int dom_broadcast_pid; + int dom_pipe_fds[2]; + int dom_default; +}; +typedef struct dom_binding dom_binding; + +struct ypbind_resp_3 { + ypbind_resptype ypbind_status; + union { + u_int ypbind_error; + ypbind_binding_3 ypbind_bindinfo; + } ypbind_resp_u; +}; +typedef struct ypbind_resp_3 ypbind_resp_3; +#endif + void checkwork(void); -void *ypbindproc_null_2_yp(SVCXPRT *, void *, CLIENT *); +void *ypbindproc_null_3_yp(SVCXPRT *, void *, CLIENT *); +static struct ypbind_resp_3 *ypbindproc_domain_3_yp(SVCXPRT *transp, ypbind_domain *argp, CLIENT *clnt); +static struct ypbind_resp_3 *ypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt); +void *ypbindproc_setdom_3_yp(SVCXPRT *, struct ypbind_setdom_3 *, CLIENT *); void *ypbindproc_setdom_2_yp(SVCXPRT *, struct ypbind_setdom *, CLIENT *); -void rpc_received(char *, struct sockaddr_in *, int); -void broadcast(struct _dom_binding *); -int ping(struct _dom_binding *); -int tell_parent(char *, struct sockaddr_in *); -void handle_children(struct _dom_binding *); +void rpc_received(char *, struct netbuf *, int); +void broadcast(struct dom_binding *); +int ping(struct dom_binding *); +int tell_parent(char *, struct netbuf *); +void handle_children(struct dom_binding *); void reaper(int); void terminate(int); void yp_restricted_mode(char *); -int verify(struct in_addr); +int verify(struct netbuf *); static char *domain_name; -static struct _dom_binding *ypbindlist; -static struct _dom_binding *broad_domain; +static struct dom_binding *ypbindlist; +static struct dom_binding *broad_domain; #define YPSET_NO 0 #define YPSET_LOCAL 1 @@ -123,7 +183,7 @@ #define RESTRICTED_SERVERS 10 static int yp_restricted = 0; static int yp_manycast = 0; -static struct in_addr restricted_addrs[RESTRICTED_SERVERS]; +static struct sockaddr_storage restricted_addrs[RESTRICTED_SERVERS]; /* No more than MAX_CHILDREN child broadcasters at a time. */ #ifndef MAX_CHILDREN @@ -149,10 +209,10 @@ static int yplockfd; static fd_set fdsr; -static SVCXPRT *udptransp, *tcptransp; +static u_short port; void * -ypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) +ypbindproc_null_3_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) { static char res; @@ -160,59 +220,62 @@ return &res; } -static struct ypbind_resp * -ypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt) +static struct ypbind_resp_3 * +ypbindproc_domain_3_yp(SVCXPRT *transp, struct ypbind_domain *argp, CLIENT *clnt) { - static struct ypbind_resp res; - struct _dom_binding *ypdb; + static struct ypbind_resp_3 res; + struct dom_binding *ypdb; char path[MAXPATHLEN]; bzero(&res, sizeof res); res.ypbind_status = YPBIND_FAIL_VAL; res.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; - if (strchr(*argp, '/')) { + if (strchr(argp->ypbind_domainname, '/')) { syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ -rejecting.", *argp); +rejecting.", argp->ypbind_domainname); return(&res); } for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { - if (strcmp(ypdb->dom_domain, *argp) == 0) + if (strcmp(ypdb->dom_domain, argp->ypbind_domainname) == 0) break; } if (ypdb == NULL) { if (yp_restricted) { - syslog(LOG_NOTICE, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp); + syslog(LOG_NOTICE, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", argp->ypbind_domainname); return (&res); } if (domains >= MAX_DOMAINS) { syslog(LOG_WARNING, "domain limit (%d) exceeded", - MAX_DOMAINS); + MAX_DOMAINS); res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; return (&res); } - if (strlen(*argp) > YPMAXDOMAIN) { - syslog(LOG_WARNING, "domain %s too long", *argp); + + if (strlen(argp->ypbind_domainname) > YPMAXDOMAIN) { + syslog(LOG_WARNING, "domain %s too long", argp->ypbind_domainname); res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; return (&res); } + ypdb = malloc(sizeof *ypdb); if (ypdb == NULL) { syslog(LOG_WARNING, "malloc: %m"); res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; return (&res); } + bzero(ypdb, sizeof *ypdb); - strlcpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); + strlcpy(ypdb->dom_domain, argp->ypbind_domainname, sizeof ypdb->dom_domain); ypdb->dom_vers = YPVERS; ypdb->dom_alive = 0; ypdb->dom_default = 0; ypdb->dom_lockfd = -1; sprintf(path, "%s/%s.%ld", BINDINGDIR, - ypdb->dom_domain, ypdb->dom_vers); + ypdb->dom_domain, ypdb->dom_vers); unlink(path); ypdb->dom_pnext = ypbindlist; ypbindlist = ypdb; @@ -225,34 +288,62 @@ res.ypbind_status = YPBIND_SUCC_VAL; res.ypbind_resp_u.ypbind_error = 0; /* Success */ - memcpy(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, - &ypdb->dom_server_addr.sin_addr.s_addr, sizeof(u_int32_t)); - memcpy(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, - &ypdb->dom_server_addr.sin_port, sizeof(u_short)); + memcpy(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_svcaddr, + &ypdb->dom_binding->ypbind_svcaddr, sizeof(struct netbuf)); /*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); } +static struct ypbind_resp_3 * +ypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt) +{ + ypbind_resp_3 *res; + ypbind_domain arg; + arg.ypbind_domainname = *argp; + res = ypbindproc_domain_3_yp(transp, &arg, clnt); + return res; +} + void * -ypbindproc_setdom_2_yp(SVCXPRT *transp, ypbind_setdom *argp, CLIENT *clnt) +ypbindproc_setdom_3_yp(SVCXPRT *transp, ypbind_setdom_3 *argp, CLIENT *clnt) { - struct sockaddr_in *fromsin, bindsin; + struct netbuf *from, bind; + struct sockaddr_storage *fromsin; static char *result = NULL; + char host[NI_MAXHOST], service[NI_MAXSERV]; + int ret, port; if (strchr(argp->ypsetdom_domain, '/')) { syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ rejecting.", argp->ypsetdom_domain); return(NULL); } - fromsin = svc_getcaller(transp); + + from = svc_getrpccaller(transp); + fromsin = (struct sockaddr_storage *)from->buf; + ret = getnameinfo((struct sockaddr *)fromsin, fromsin->ss_len, + host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret != 0) { + syslog(LOG_ERR, "getnameinfo: %s\n", gai_strerror(ret)); + return(NULL); + } switch (ypsetmode) { case YPSET_LOCAL: - if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { - svcerr_noprog(transp); - return(NULL); + if (fromsin->ss_family == AF_INET) { + if (!strcmp(host, "127.0.0.1")) { + svcerr_noprog(transp); + return(NULL); + } + } + else if (fromsin->ss_family == AF_INET6) { + if (!strcmp(host, "::1")) { + svcerr_noprog(transp); + return(NULL); + } } break; case YPSET_ALL: @@ -263,16 +354,37 @@ return(NULL); } - if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) { + port = atoi(service); + if (port >= IPPORT_RESERVED) { svcerr_noprog(transp); - return(NULL); + return NULL; } - if (argp->ypsetdom_vers != YPVERS) { + if (argp->ypsetdom_bindinfo->ypbind_hi_vers != YPVERS && + argp->ypsetdom_bindinfo->ypbind_lo_vers != YPVERS) { svcerr_noprog(transp); return(NULL); } + bzero(&bind, sizeof bind); + memcpy(&bind, &argp->ypsetdom_bindinfo->ypbind_svcaddr, sizeof(struct netbuf)); + rpc_received(argp->ypsetdom_domain, &bind, 1); + + return((void *) &result); +} + + +void * +ypbindproc_setdom_2_yp(SVCXPRT *transp, ypbind_setdom *argp, CLIENT *clnt) +{ + // Translate ypbind_setdom to ypbind_setdom_3 then call ypbindproc_setdom_3_yp + struct sockaddr_in bindsin; + struct netbuf bindnb; + ypbind_setdom_3 argp_2; + + strncpy(argp_2.ypsetdom_domain, argp->ypsetdom_domain, sizeof(argp->ypsetdom_domain) - 1); + argp_2.ypsetdom_bindinfo->ypbind_hi_vers = argp->ypsetdom_vers; + argp_2.ypsetdom_bindinfo->ypbind_lo_vers = argp->ypsetdom_vers; bzero(&bindsin, sizeof bindsin); bindsin.sin_family = AF_INET; memcpy(&bindsin.sin_addr.s_addr, @@ -281,9 +393,74 @@ memcpy(&bindsin.sin_port, &argp->ypsetdom_binding.ypbind_binding_port, sizeof(u_short)); - rpc_received(argp->ypsetdom_domain, &bindsin, 1); + bindnb.buf = &bindsin; + bindnb.len = sizeof(bindsin); + bindnb.maxlen = sizeof(bindsin); + argp_2.ypsetdom_bindinfo->ypbind_svcaddr = &bindnb; + return ypbindproc_setdom_3_yp(transp, &argp_2, clnt); +} - return((void *) &result); +void +ypbindprog_3(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + struct ypbind_domain ypbindproc_domain_3_arg; + struct ypbind_setdom_3 ypbindproc_setdom_3_arg; + } argument; + struct authunix_parms *creds; + void *result; + xdrproc_t xdr_argument, xdr_result; + typedef void *(svc_cb)(SVCXPRT *transp, void *arg, + struct svc_req *rqstp); + svc_cb *local; + + switch (rqstp->rq_proc) { + case YPBINDPROC_NULL: + xdr_argument = (xdrproc_t)xdr_void; + xdr_result = (xdrproc_t)xdr_void; + local = (svc_cb *)ypbindproc_null_3_yp; + break; + + case YPBINDPROC_DOMAIN: + xdr_argument = (xdrproc_t)xdr_domainname; + xdr_result = (xdrproc_t)xdr_ypbind_resp; + local = (svc_cb *)ypbindproc_domain_3_yp; + break; + + case YPBINDPROC_SETDOM: + switch (rqstp->rq_cred.oa_flavor) { + case AUTH_UNIX: + creds = (struct authunix_parms *)rqstp->rq_clntcred; + if (creds->aup_uid != 0) { + svcerr_auth(transp, AUTH_BADCRED); + return; + } + break; + default: + svcerr_auth(transp, AUTH_TOOWEAK); + return; + } + + xdr_argument = (xdrproc_t)xdr_ypbind_setdom; + xdr_result = (xdrproc_t)xdr_void; + local = (svc_cb *)ypbindproc_setdom_3_yp; + break; + + default: + svcerr_noproc(transp); + return; + } + bzero(&argument, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { + svcerr_decode(transp); + return; + } + result = (*local)(transp, &argument, rqstp); + if (result != NULL && + !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + return; } void @@ -304,7 +481,7 @@ case YPBINDPROC_NULL: xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_void; - local = (svc_cb *)ypbindproc_null_2_yp; + local = (svc_cb *)ypbindproc_null_3_yp; break; case YPBINDPROC_DOMAIN: @@ -362,7 +539,7 @@ void terminate(int sig) { - struct _dom_binding *ypdb; + struct dom_binding *ypdb; char path[MAXPATHLEN]; if (ppid != getpid()) @@ -389,7 +566,10 @@ int i; DIR *dird; struct dirent *dirp; - struct _dom_binding *ypdb, *next; + struct dom_binding *ypdb, *next; + void *handle; + struct netconfig *nconf; + SVCXPRT *xprt; /* Check that another ypbind isn't already running. */ if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) @@ -441,20 +621,31 @@ 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)"); + if ((handle = setnetconfig()) == NULL) { + errx(1, "setnetconfig failed"); + exit(1); + } - tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); - if (tcptransp == NULL) - errx(1, "cannot create tcp service"); + while ((nconf = getnetconfig(handle)) != NULL) { + // Bind version 3 ypbind + if((xprt = svc_tp_create(ypbindprog_3, YPBINDPROG, YPBINDVERS, nconf)) == NULL) { + errx(1, "terminating: cannot create rpcgind handle"); + exit(1); + } - if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, - IPPROTO_TCP)) - errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); + // Version 2 ypbind only support IPv4 on TCP and UDP + if ((!strcmp(nconf->nc_protofmly, NC_INET)) && + ((nconf->nc_semantics == NC_TPI_CLTS) || (nconf->nc_semantics == NC_TPI_COTS_ORD))) { + + // Unregister any existing RPC binding for ypbind V2 + rpcb_unset(YPBINDPROG, YPBINDVERS_2, nconf); + if (!svc_reg(xprt, YPBINDPROG, YPBINDVERS_2, ypbindprog_2, nconf)) { + errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); + continue; + } + } + } + port = xprt->xp_port; // Store port as global variable /* build initial domain binding, make it "unsuccessful" */ ypbindlist = malloc(sizeof *ypbindlist); @@ -516,7 +707,7 @@ void checkwork(void) { - struct _dom_binding *ypdb; + struct dom_binding *ypdb; for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) ping(ypdb); @@ -535,12 +726,12 @@ * the mistake much sooner), even though logically it should. */ void -handle_children(struct _dom_binding *ypdb) +handle_children(struct dom_binding *ypdb) { char buf[YPMAXDOMAIN + 1]; - struct sockaddr_in addr; + struct netbuf addr; int d = 0, a = 0; - struct _dom_binding *y, *prev = NULL; + struct dom_binding *y, *prev = NULL; char path[MAXPATHLEN]; if ((d = read(READFD, &buf, sizeof(buf))) <= 0) @@ -591,7 +782,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 netbuf *addr) { char buf[YPMAXDOMAIN + 1]; struct timeval timeout; @@ -614,7 +805,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->buf, addr->len) < 0) return(1); } else { return(1); @@ -625,21 +816,27 @@ } static bool_t -broadcast_result(bool_t *out, struct sockaddr_in *addr) +broadcast_result(bool_t *out, struct netbuf *addr) // TODO: parameter { + char host[NI_MAXHOST]; + int ret; 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, (struct netbuf *)addr)) syslog(LOG_WARNING, "lost connection to parent"); return (TRUE); } - if (yp_restricted && verify(addr->sin_addr)) { + if (yp_restricted && verify(addr)) { + ret = getnameinfo((struct sockaddr *)addr->buf, addr->len, host, sizeof(host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + if (ret != 0) { + syslog(LOG_ERR, "getnameinfo failed: %s", gai_strerror(ret)); + } retries++; - syslog(LOG_NOTICE, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr->sin_addr)); + syslog(LOG_NOTICE, "NIS server at %s not in restricted mode access list -- rejecting.\n", host); return (FALSE); } else { - if (tell_parent(broad_domain->dom_domain, addr)) + if (tell_parent(broad_domain->dom_domain, (struct netbuf *)addr)) syslog(LOG_WARNING, "lost connection to parent"); return (TRUE); } @@ -656,10 +853,13 @@ * the 'eachresult' callback function. */ void -broadcast(struct _dom_binding *ypdb) +broadcast(struct dom_binding *ypdb) { bool_t out = FALSE; enum clnt_stat stat; + struct sockaddr *sa; + char host[NI_MAXHOST]; + int ret; if (children >= MAX_CHILDREN || ypdb->dom_broadcast_pid) return; @@ -669,11 +869,16 @@ return; } - if (ypdb->dom_vers == -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr) { + if (ypdb->dom_vers == -1 && ypdb->dom_binding != NULL) { if (not_responding_count++ >= NOT_RESPONDING_HYSTERESIS) { not_responding_count = NOT_RESPONDING_HYSTERESIS; + sa = (struct sockaddr *)ypdb->dom_binding->ypbind_svcaddr->buf; + ret = getnameinfo((struct sockaddr *)sa, sa->sa_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + if (ret != 0) { + syslog(LOG_ERR, "getnameinfo failed: %s", gai_strerror(ret)); + } syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding", - inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain); + host, ypdb->dom_domain); } } @@ -721,10 +926,10 @@ i = __yp_ping(restricted_addrs, yp_restricted, ypdb->dom_domain, &port); if (i == -1) { - bzero(&ypdb->dom_server_addr, - sizeof(struct sockaddr_in)); + bzero(ypdb->dom_binding->ypbind_svcaddr, + sizeof(struct netbuf)); if (tell_parent(ypdb->dom_domain, - &ypdb->dom_server_addr)) + ypdb->dom_binding->ypbind_svcaddr)) syslog(LOG_WARNING, "lost connection to parent"); } else { bzero(&sin, sizeof(struct sockaddr_in)); @@ -732,7 +937,7 @@ &sin.sin_addr, sizeof(struct in_addr)); sin.sin_family = AF_INET; sin.sin_port = port; - if (tell_parent(broad_domain->dom_domain, &sin)) + if (tell_parent(broad_domain->dom_domain, (struct netbuf *)&sin)) syslog(LOG_WARNING, "lost connection to parent"); } @@ -752,9 +957,9 @@ } if (stat != RPC_SUCCESS) { - bzero(&ypdb->dom_server_addr, - sizeof(struct sockaddr_in)); - if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) + bzero(ypdb->dom_binding->ypbind_svcaddr, + sizeof(struct netbuf)); + if (tell_parent(ypdb->dom_domain, ypdb->dom_binding->ypbind_svcaddr)) syslog(LOG_WARNING, "lost connection to parent"); } @@ -774,7 +979,7 @@ * need it to keep the system on its feet. */ int -ping(struct _dom_binding *ypdb) +ping(struct dom_binding *ypdb) { bool_t out; struct timeval interval, timeout; @@ -790,8 +995,8 @@ if (ypdb->dom_broadcast_pid) return(1); - if ((client_handle = clntudp_bufcreate(&ypdb->dom_server_addr, - YPPROG, YPVERS, interval, &rpcsock, RPCSMALLMSGSIZE, + if ((client_handle = clnt_tli_create(rpcsock, ypdb->dom_binding->ypbind_nconf, + ypdb->dom_binding->ypbind_svcaddr, YPPROG, YPVERS, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) == (CLIENT *)NULL) { /* Can't get a handle: we're dead. */ ypdb->dom_alive = 0; @@ -822,13 +1027,13 @@ } void -rpc_received(char *dom, struct sockaddr_in *raddrp, int force) +rpc_received(char *dom, struct netbuf *raddrp, int force) { - struct _dom_binding *ypdb, *prev = NULL; + struct dom_binding *ypdb, *prev = NULL; struct iovec iov[2]; - struct ypbind_resp ybr; - char path[MAXPATHLEN]; - int fd; + struct ypbind_resp_3 ybr; + char path[MAXPATHLEN], host[NI_MAXHOST], service[NI_MAXSERV]; + int fd, ret, port; /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), dom);*/ @@ -852,10 +1057,20 @@ } } + struct sockaddr_storage *ss = (struct sockaddr_storage *)raddrp->buf; + + ret = getnameinfo((struct sockaddr *)ss, ss->ss_len, + host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret != 0) { + syslog(LOG_ERR, "getnameinfo failed: %s", gai_strerror(ret)); + } + + port = atoi(service); /* if in secure mode, check originating port number */ - if ((ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED))) { + if ((ypsecuremode && atoi(service) >= IPPORT_RESERVED)) { syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.", - inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), + host, port, dom); if (ypdb != NULL) { ypdb->dom_broadcast_pid = 0; @@ -864,7 +1079,7 @@ return; } - if (raddrp->sin_addr.s_addr == (long)0) { + if ((!strcmp(host, "0.0.0.0")) || !strcmp(host, "::")) { switch (ypdb->dom_default) { case 0: if (prev == NULL) @@ -909,16 +1124,16 @@ } /* 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 && ypdb->dom_binding->ypbind_svcaddr) { 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); + host, ypdb->dom_domain); } } - bcopy(raddrp, &ypdb->dom_server_addr, - sizeof ypdb->dom_server_addr); + bcopy(raddrp, ypdb->dom_binding->ypbind_svcaddr, + sizeof *ypdb->dom_binding->ypbind_svcaddr); ypdb->dom_vers = YPVERS; ypdb->dom_alive = 1; @@ -950,17 +1165,15 @@ */ ypdb->dom_lockfd = fd; - iov[0].iov_base = (char *)&(udptransp->xp_port); - iov[0].iov_len = sizeof udptransp->xp_port; + iov[0].iov_base = (char *)&(port); + iov[0].iov_len = sizeof port; iov[1].iov_base = (char *)&ybr; iov[1].iov_len = sizeof ybr; bzero(&ybr, sizeof ybr); ybr.ypbind_status = YPBIND_SUCC_VAL; - memcpy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, - &raddrp->sin_addr.s_addr, sizeof(u_int32_t)); - memcpy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, - &raddrp->sin_port, sizeof(u_short)); + memcpy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_svcaddr, + &raddrp, sizeof(struct netbuf)); if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { syslog(LOG_WARNING, "write: %m"); @@ -975,13 +1188,30 @@ * 1 if not matched. */ int -verify(struct in_addr addr) +verify(struct netbuf *addr) { int i; - - for (i = 0; i < RESTRICTED_SERVERS; i++) - if (!bcmp(&addr, &restricted_addrs[i], sizeof(struct in_addr))) - return(0); + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct sockaddr_storage *sa = (struct sockaddr_storage *)addr->buf; + + if (sa->ss_family == AF_INET) { + sin = (struct sockaddr_in *)sa; + for (i = 0; i < RESTRICTED_SERVERS; i++) { + if (restricted_addrs[i].ss_family== AF_INET && + !memcmp(&sin->sin_addr, &((struct sockaddr_in *)&restricted_addrs[i])->sin_addr, sizeof(struct in_addr))) { + return 0; + } + } + } else if (sa->ss_family == AF_INET6) { + sin6 = (struct sockaddr_in6 *)sa; + for (i = 0; i < RESTRICTED_SERVERS; i++) { + if (restricted_addrs[i].ss_family == AF_INET6 && + !memcmp(&sin6->sin6_addr, &((struct sockaddr_in6 *)&restricted_addrs[i])->sin6_addr, sizeof(struct in6_addr))) { + return 0; + } + } + } return(1); } diff --git a/usr.sbin/ypset/ypset.c b/usr.sbin/ypset/ypset.c --- a/usr.sbin/ypset/ypset.c +++ b/usr.sbin/ypset/ypset.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -54,11 +55,10 @@ } static int -bind_tohost(struct sockaddr_in *sin, char *dom, char *server) +bind_tohost(struct sockaddr_storage *ss, char *dom, char *server) { struct ypbind_setdom ypsd; - struct in_addr iaddr; - struct hostent *hp; + struct addrinfo hints, *res; struct timeval tv; CLIENT *client; int sock, port, r; @@ -70,12 +70,13 @@ memset(&ypsd, 0, sizeof ypsd); - if (inet_aton(server, &iaddr) == 0) { - hp = gethostbyname(server); - if (hp == NULL) - errx(1, "can't find address for %s", server); - memmove(&iaddr.s_addr, hp->h_addr, sizeof(iaddr.s_addr)); - } + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + + if (getaddrinfo(server, NULL, &hints, &res) != 0) + errx(1, "can't find address for %s", server); + ypsd.ypsetdom_domain = dom; bcopy(&iaddr.s_addr, &ypsd.ypsetdom_binding.ypbind_binding_addr, sizeof(ypsd.ypsetdom_binding.ypbind_binding_addr)); @@ -110,14 +111,14 @@ int main(int argc, char *argv[]) { - struct sockaddr_in sin; - struct hostent *hent; + struct sockaddr_storage ss; + struct addrinfo hints, *res; char *domainname; int c; yp_get_default_domain(&domainname); - bzero(&sin, sizeof sin); + memset(&ss, 0, sizeof ss); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); @@ -127,13 +128,15 @@ domainname = optarg; break; case 'h': - if (inet_aton(optarg, &sin.sin_addr) == 0) { - hent = gethostbyname(optarg); - if (hent == NULL) - errx(1, "host %s unknown\n", optarg); - bcopy(hent->h_addr, &sin.sin_addr, - sizeof(sin.sin_addr)); - } + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + + if (getaddrinfo(optarg, NULL, &hints, &res) != 0) + errx(1, "host %s unknown\n", optarg); + + memcpy(&ss, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); break; default: usage();