Page MenuHomeFreeBSD

D45515.diff
No OneTemporary

D45515.diff

diff --git a/include/rpcsvc/yp.x b/include/rpcsvc/yp.x
--- a/include/rpcsvc/yp.x
+++ b/include/rpcsvc/yp.x
@@ -190,11 +190,31 @@
YPBIND_FAIL_VAL = 2
};
+struct ypbind_domain_3 {
+ char *ypbind_domainname;
+ unsigned int ypbind_vers;
+};
+
+struct ypbind_binding_3 {
+ struct netbuf *ypbind_svcaddr;
+ char *ypbind_servername;
+ unsigned int ypbind_hi_vers;
+ unsigned int ypbind_lo_vers;
+};
+
struct ypbind_binding {
opaque ypbind_binding_addr[4]; /* In network order */
opaque ypbind_binding_port[2]; /* In network order */
};
+union ypbind_resp_3 switch (ypbind_resptype ypbind_status)
+{
+case YPBIND_FAIL_VAL:
+ unsigned ypbind_error;
+case YPBIND_SUCC_VAL:
+ ypbind_binding_3 ypbind_bindinfo;
+};
+
union ypbind_resp switch (ypbind_resptype ypbind_status) {
case YPBIND_FAIL_VAL:
unsigned ypbind_error;
@@ -212,6 +232,12 @@
/*
* Request data structure for ypbind "Set domain" procedure.
*/
+struct ypbind_setdom_3 {
+ char *ypsetdom_domain;
+ struct ypbind_binding_3 *ypsetdom_bindinfo;
+ unsigned ypsetdom_vers;
+};
+
struct ypbind_setdom {
domainname ypsetdom_domain;
ypbind_binding ypsetdom_binding;
@@ -367,6 +393,17 @@
void
YPBINDPROC_SETDOM(ypbind_setdom) = 2;
} = 2;
+
+ version YPBINDVERS_3 {
+ void
+ YPBINDPROC_NULL(void) = 0;
+
+ ypbind_resp
+ YPBINDPROC_DOMAIN(ypbind_domain_3) = 1;
+
+ void
+ YPBINDPROC_SETDOM(ypbind_setdom_3) = 2;
+ } = 3;
} = 100007;
#endif
diff --git a/lib/libc/yp/Symbol.map b/lib/libc/yp/Symbol.map
--- a/lib/libc/yp/Symbol.map
+++ b/lib/libc/yp/Symbol.map
@@ -49,5 +49,8 @@
xdr_ypresptype;
xdr_ypstat;
xdr_ypxfrstat;
+ xdr_ypbind_resp_3;
+ xdr_ypbind_domain_3;
+ xdr_ypbind_setdom_3;
};
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 *, 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
@@ -103,18 +103,26 @@
* Returns 0 if no map exists.
*/
static u_short
-__pmap_getport(struct sockaddr_in *address, u_long program, u_long version,
+__pmap_getport(struct sockaddr *address, u_long program, u_long version,
u_int protocol)
{
+ struct netbuf nb;
u_short port = 0;
int sock = -1;
register CLIENT *client;
struct pmap parms;
- address->sin_port = htons(PMAPPORT);
+ if (address->sa_family == AF_INET) {
+ ((struct sockaddr_in *)address)->sin_port = htons(PMAPPORT);
+ nb.len = nb.maxlen = sizeof(struct sockaddr_in);
+ }
+ else if (address->sa_family == AF_INET6) {
+ ((struct sockaddr_in6 *)address)->sin6_port = htons(PMAPPORT);
+ nb.len = nb.maxlen = sizeof(struct sockaddr_in6);
+ }
+ nb.buf = address;
- client = clntudp_bufcreate(address, PMAPPROG,
- PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ client = clnt_dg_create(sock, &nb, PMAPPROG, PMAPVERS, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client != (CLIENT *)NULL) {
parms.pm_prog = program;
parms.pm_vers = version;
@@ -131,9 +139,13 @@
}
CLNT_DESTROY(client);
}
+ clnt_control(client, CLSET_TIMEOUT, (char *)&timeout);
if (sock != -1)
(void)close(sock);
- address->sin_port = 0;
+ if (address->sa_family == AF_INET)
+ ((struct sockaddr_in *)address)->sin_port = 0;
+ else if (address->sa_family == AF_INET6)
+ ((struct sockaddr_in6 *)address)->sin6_port = 0;
return (port);
}
@@ -198,18 +210,20 @@
*/
struct ping_req {
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
u_int32_t xid;
};
int
-__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port)
+__yp_ping(struct sockaddr *restricted_addrs, int cnt, char *dom, short *port)
{
struct timeval tv = { 5, 0 };
struct ping_req **reqs;
unsigned long i;
int async;
- struct sockaddr_in sin, *any = NULL;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *any = NULL;
struct netbuf addr;
int winner = -1;
u_int32_t xid_seed, xid_lookup;
@@ -217,23 +231,38 @@
CLIENT *clnt;
char *foo = dom;
int validsrvs = 0;
+ char host[NI_MAXHOST];
+ int ret;
/* Set up handles. */
reqs = calloc(cnt, sizeof(struct ping_req *));
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)
- continue;
- reqs[i] = calloc(1, sizeof(struct ping_req));
- bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin));
- any = &reqs[i]->sin;
+ if (restricted_addrs[i].sa_family == AF_INET) {
+ bzero((char *)&sin, sizeof(sin));
+ bcopy((char *)&restricted_addrs[i],
+ (char *)&sin.sin_addr, sizeof(struct in_addr));
+ sin.sin_port = htons(__pmap_getport((struct sockaddr *)&sin, YPPROG,
+ YPVERS, IPPROTO_UDP));
+ if (sin.sin_port == 0)
+ continue;
+ reqs[i] = calloc(1, sizeof(struct ping_req));
+ bcopy((char *)&sin, (char *)&reqs[i]->ss, sizeof(sin));
+ any = (struct sockaddr *)&reqs[i]->ss;
+ }
+ else if (restricted_addrs[i].sa_family == AF_INET6) {
+ bzero((char *)&sin6, sizeof(sin6));
+ bcopy((char *)&restricted_addrs[i],
+ (char *)&sin6.sin6_addr, sizeof(struct in6_addr));
+ sin6.sin6_port = htons(__pmap_getport((struct sockaddr *)&sin6, YPPROG,
+ YPVERS, IPPROTO_UDP));
+ if (sin6.sin6_port == 0)
+ continue;
+ reqs[i] = calloc(1, sizeof(struct ping_req));
+ bcopy((char *)&sin6, (char *)&reqs[i]->ss, sizeof(sin6));
+ any = (struct sockaddr *)&reqs[i]->ss;
+ }
reqs[i]->xid = xid_seed;
xid_seed++;
validsrvs++;
@@ -246,8 +275,13 @@
}
/* Create RPC handle */
- sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock);
+ sock = socket(any->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ ret = getnameinfo(any, any->sa_len, host, sizeof(host), NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (ret != 0)
+ return(-1);
+
+ clnt = clnt_create(host, YPPROG, YPVERS, "udp");
if (clnt == NULL) {
close(sock);
for (i = 0; i < cnt; i++)
@@ -268,8 +302,8 @@
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;
+ addr.len = sizeof(reqs[i]->ss);
+ addr.buf = (char *) &reqs[i]->ss;
clnt_control(clnt, CLSET_SVC_ADDR, &addr);
ypproc_domain_nonack_2_send(&foo, clnt);
}
@@ -283,7 +317,10 @@
for (i = 0; i < cnt; i++) {
if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) {
winner = i;
- *port = reqs[i]->sin.sin_port;
+ if (reqs[i]->ss.ss_family == AF_INET)
+ *port = ((struct sockaddr_in *)&reqs[i]->ss)->sin_port;
+ else if (reqs[i]->ss.ss_family == AF_INET6)
+ *port = ((struct sockaddr_in6 *)&reqs[i]->ss)->sin6_port;
}
}
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
@@ -52,6 +52,7 @@
#include <syslog.h>
#include <unistd.h>
#include <rpc/rpc.h>
+#include <rpc/clnt.h>
#include <rpc/xdr.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -72,10 +73,13 @@
#define YPBINDLOCK "/var/run/ypbind.lock"
#endif
+typedef void *(svc_cb)(SVCXPRT *transp, void *arg,
+ struct svc_req *rqstp);
+
struct _dom_binding {
struct _dom_binding *dom_pnext;
char dom_domain[YPMAXDOMAIN + 1];
- struct sockaddr_in dom_server_addr;
+ struct ypbind_binding_3 *dom_binding;
long int dom_vers;
int dom_lockfd;
int dom_alive;
@@ -90,16 +94,20 @@
void checkwork(void);
void *ypbindproc_null_2_yp(SVCXPRT *, void *, CLIENT *);
+static struct ypbind_resp_3 *ypbindproc_domain_3_yp(SVCXPRT *transp, ypbind_domain_3 *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 rpc_received(char *, struct netbuf *, int);
void broadcast(struct _dom_binding *);
int ping(struct _dom_binding *);
-int tell_parent(char *, struct sockaddr_in *);
+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 *);
+void copy_netbuf(struct netbuf *, struct netbuf *);
static char *domain_name;
static struct _dom_binding *ypbindlist;
@@ -123,7 +131,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,7 +157,7 @@
static int yplockfd;
static fd_set fdsr;
-static SVCXPRT *udptransp, *tcptransp;
+static u_short xprt_port;
void *
ypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt)
@@ -160,53 +168,55 @@
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_3 *argp, CLIENT *clnt)
{
- static struct ypbind_resp res;
+ 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;
+ res.ypbind_resp_3_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);
- res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC;
+ res.ypbind_resp_3_u.ypbind_error = YPBIND_ERR_RESC;
return (&res);
}
- if (strlen(*argp) > YPMAXDOMAIN) {
- syslog(LOG_WARNING, "domain %s too long", *argp);
- res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC;
+ if (strlen(argp->ypbind_domainname) > YPMAXDOMAIN) {
+ syslog(LOG_WARNING, "domain %s too long", argp->ypbind_domainname);
+ res.ypbind_resp_3_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;
+ res.ypbind_resp_3_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;
@@ -224,33 +234,50 @@
}
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));
+ res.ypbind_resp_3_u.ypbind_error = 0; /* Success */
+ res.ypbind_resp_3_u.ypbind_bindinfo.ypbind_svcaddr = malloc(sizeof(struct netbuf));
+ copy_netbuf(res.ypbind_resp_3_u.ypbind_bindinfo.ypbind_svcaddr,
+ ypdb->dom_binding->ypbind_svcaddr);
/*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_domain_3 arg;
+ arg.ypbind_domainname = *argp;
+ return ypbindproc_domain_3_yp(transp, &arg, clnt);
+}
+
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 *from_sin;
static char *result = NULL;
+ char host[NI_MAXHOST];
+ int ret;
+ u_short port = 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);
+ from = svc_getrpccaller(transp);
+ from_sin = (struct sockaddr *)from->buf;
+ ret = getnameinfo(from_sin, from_sin->sa_len, host, sizeof(host), NULL, 0, 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)) {
+ if (strcmp(host, "127.0.0.1") == 0 || strcmp(host, "::1") == 0) {
svcerr_noprog(transp);
return(NULL);
}
@@ -263,27 +290,113 @@
return(NULL);
}
- if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) {
+ if (from_sin->sa_family == AF_INET)
+ port = ntohs(((struct sockaddr_in *)from_sin)->sin_port);
+ else if (from_sin->sa_family == AF_INET6)
+ port = ntohs(((struct sockaddr_in6 *)from_sin)->sin6_port);
+
+ if (port >= IPPORT_RESERVED) {
svcerr_noprog(transp);
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(&bindsin, sizeof bindsin);
- bindsin.sin_family = AF_INET;
- memcpy(&bindsin.sin_addr.s_addr,
+ bzero(&bind, sizeof bind);
+ copy_netbuf(&bind, argp->ypsetdom_bindinfo->ypbind_svcaddr);
+ rpc_received(argp->ypsetdom_domain, &bind, 1);
+
+ return((void *) &result);
+}
+
+void *
+ypbindproc_setdom_2_yp(SVCXPRT *transp, ypbind_setdom *argp, CLIENT *clnt)
+{
+ struct netbuf nb;
+ struct sockaddr_in sin;
+ ypbind_setdom_3 argp_2;
+
+ bzero(&sin, sizeof sin);
+ sin.sin_family = AF_INET;
+ memcpy(&sin.sin_addr.s_addr,
&argp->ypsetdom_binding.ypbind_binding_addr,
sizeof(u_int32_t));
- memcpy(&bindsin.sin_port,
+ memcpy(&sin.sin_port,
&argp->ypsetdom_binding.ypbind_binding_port,
sizeof(u_short));
- rpc_received(argp->ypsetdom_domain, &bindsin, 1);
+ nb.buf = &sin;
+ nb.len = nb.maxlen = sizeof(struct sockaddr_in);
+ strlcpy(argp_2.ypsetdom_domain, argp->ypsetdom_domain, sizeof(argp_2.ypsetdom_domain));
+ argp_2.ypsetdom_bindinfo->ypbind_hi_vers = argp->ypsetdom_vers;
+ argp_2.ypsetdom_bindinfo->ypbind_lo_vers = argp->ypsetdom_vers;
+ argp_2.ypsetdom_bindinfo->ypbind_svcaddr = &nb;
+
+ 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_3 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;
+ 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_2_yp;
+ break;
+
+ case YPBINDPROC_DOMAIN:
+ xdr_argument = (xdrproc_t)xdr_ypbind_domain_3;
+ xdr_result = (xdrproc_t)xdr_ypbind_resp_3;
+ 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_3;
+ 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
@@ -296,8 +409,6 @@
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) {
@@ -362,8 +473,10 @@
void
terminate(int sig)
{
+ struct netconfig *nconf;
struct _dom_binding *ypdb;
char path[MAXPATHLEN];
+ void *handle;
if (ppid != getpid())
exit(0);
@@ -378,18 +491,31 @@
}
close(yplockfd);
unlink(YPBINDLOCK);
- pmap_unset(YPBINDPROG, YPBINDVERS);
+ if ((handle = setnetconfig()) == NULL)
+ errx(1, "setnetconfig failed");
+
+ while ((nconf = getnetconfig(handle)) != NULL) {
+ rpcb_unset(YPBINDPROG, YPBINDVERS_3, nconf);
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
+ (nconf->nc_semantics == NC_TPI_CLTS ||
+ nconf->nc_semantics == NC_TPI_COTS_ORD)) {
+ rpcb_unset(YPBINDPROG, YPBINDVERS, nconf);
+ }
+ }
exit(0);
}
int
main(int argc, char *argv[])
{
+ struct netconfig *nconf;
struct timeval tv;
int i;
DIR *dird;
struct dirent *dirp;
struct _dom_binding *ypdb, *next;
+ SVCXPRT *xprt;
+ void *handle;
/* Check that another ypbind isn't already running. */
if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1)
@@ -439,22 +565,29 @@
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)");
+ if ((handle = setnetconfig()) == NULL)
+ errx(1, "setnetconfig failed");
+
+ while ((nconf = getnetconfig(handle)) != NULL) {
+ rpcb_unset(YPBINDPROG, YPBINDVERS_3, nconf);
+ /* Bind version 3 ypbind */
+ if((xprt = svc_tp_create(ypbindprog_3, YPBINDPROG, YPBINDVERS_3, nconf)) == NULL)
+ errx(1, "terminating: cannot create rpcgind handle");
+
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
+ nconf->nc_semantics == NC_TPI_CLTS)
+ xprt_port = xprt->xp_port; /* Store port as global variable */
+
+ /* Version 2 ypbind only support IPv4 on TCP and UDP */
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
+ (nconf->nc_semantics == NC_TPI_CLTS ||
+ nconf->nc_semantics == NC_TPI_COTS_ORD)) {
+ rpcb_unset(YPBINDPROG, YPBINDVERS, nconf);
+ if (!svc_reg(xprt, YPBINDPROG, YPBINDVERS, ypbindprog_2, nconf))
+ errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)");
+ }
+ }
+ freenetconfigent(nconf);
/* build initial domain binding, make it "unsuccessful" */
ypbindlist = malloc(sizeof *ypbindlist);
@@ -537,8 +670,9 @@
void
handle_children(struct _dom_binding *ypdb)
{
+ struct netbuf nb;
+ struct sockaddr addr;
char buf[YPMAXDOMAIN + 1];
- struct sockaddr_in addr;
int d = 0, a = 0;
struct _dom_binding *y, *prev = NULL;
char path[MAXPATHLEN];
@@ -546,15 +680,17 @@
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(struct sockaddr))) < 0)
syslog(LOG_WARNING, "could not read from child: %m");
close(READFD);
FD_CLR(READFD, &fdsr);
FD_CLR(READFD, &svc_fdset);
READFD = WRITEFD = -1;
+ nb.len = nb.maxlen = sizeof(struct sockaddr);
+ nb.buf = &addr;
if (d > 0 && a > 0)
- rpc_received(buf, &addr, 0);
+ rpc_received(buf, &nb, 0);
else {
for (y = ypbindlist; y; y = y->dom_pnext) {
if (y == ypdb)
@@ -591,8 +727,9 @@
* 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)
{
+ struct sockaddr * sa;
char buf[YPMAXDOMAIN + 1];
struct timeval timeout;
fd_set fds;
@@ -614,7 +751,8 @@
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)
+ sa = (struct sockaddr *)addr->buf;
+ if (write(BROADFD, sa, sizeof(*sa)) < 0)
return(1);
} else {
return(1);
@@ -625,8 +763,11 @@
}
static bool_t
-broadcast_result(bool_t *out, struct sockaddr_in *addr)
+broadcast_result(bool_t *out, struct netbuf *addr, struct netconfig *nconf)
{
+ char host[NI_MAXHOST];
+ int ret;
+
if (retries >= MAX_RETRIES) {
bzero(addr, sizeof(struct sockaddr_in));
if (tell_parent(broad_domain->dom_domain, addr))
@@ -634,9 +775,13 @@
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))
@@ -658,8 +803,10 @@
void
broadcast(struct _dom_binding *ypdb)
{
- bool_t out = FALSE;
+ struct sockaddr *sa;
+ char host[NI_MAXHOST];
enum clnt_stat stat;
+ int ret;
if (children >= MAX_CHILDREN || ypdb->dom_broadcast_pid)
return;
@@ -669,11 +816,16 @@
return;
}
- if (ypdb->dom_vers == -1 && (long)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 = NOT_RESPONDING_HYSTERESIS;
+ sa = (struct sockaddr *)ypdb->dom_binding->ypbind_svcaddr->buf;
+ ret = getnameinfo(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);
}
}
@@ -716,23 +868,23 @@
if (yp_restricted && yp_manycast) {
short port;
int i;
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
+ struct netbuf nb;
- i = __yp_ping(restricted_addrs, yp_restricted,
+ i = __yp_ping((struct sockaddr *)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));
- 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))
+ bzero(&ss, sizeof(struct sockaddr_storage));
+ bcopy(&restricted_addrs[i], &ss, sizeof(struct sockaddr_storage));
+ nb.len = nb.maxlen = sizeof(struct sockaddr_storage);
+ nb.buf = &ss;
+ if (tell_parent(broad_domain->dom_domain, &nb))
syslog(LOG_WARNING,
"lost connection to parent");
}
@@ -745,16 +897,16 @@
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, ptr,
+ (xdrproc_t)xdr_bool, (char *)NULL,
+ (resultproc_t)broadcast_result, NULL);
}
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");
}
@@ -789,16 +941,15 @@
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_handle = clnt_dg_create(rpcsock, ypdb->dom_binding->ypbind_svcaddr, YPPROG, YPVERS,
+ RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) == (CLIENT *)NULL) {
/* Can't get a handle: we're dead. */
ypdb->dom_alive = 0;
ypdb->dom_vers = -1;
broadcast(ypdb);
return(1);
}
+ clnt_control(client_handle, CLSET_TIMEOUT, (char *)&timeout);
{
char *ptr;
@@ -822,13 +973,15 @@
}
void
-rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
+rpc_received(char *dom, struct netbuf *raddrp, int force)
{
+ struct sockaddr * sa;
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];
+ int fd, ret;
+ u_short port = 0;
/*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr),
ntohs(raddrp->sin_port), dom);*/
@@ -852,10 +1005,21 @@
}
}
+ sa = (struct sockaddr *)raddrp->buf;
+ ret = getnameinfo(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));
+
+ if (sa->sa_family == AF_INET)
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+ else if (sa->sa_family == AF_INET6)
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
/* if in secure mode, check originating port number */
- if ((ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED))) {
+ if ((ypsecuremode && port >= 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 +1028,7 @@
return;
}
- if (raddrp->sin_addr.s_addr == (long)0) {
+ if (strcmp(host, "0.0.0.0") == 0 || strcmp(host, "::") == 0) {
switch (ypdb->dom_default) {
case 0:
if (prev == NULL)
@@ -909,16 +1073,15 @@
}
/* 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);
+ copy_netbuf(ypdb->dom_binding->ypbind_svcaddr, raddrp);
ypdb->dom_vers = YPVERS;
ypdb->dom_alive = 1;
@@ -950,17 +1113,16 @@
*/
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 *)&(xprt_port);
+ iov[0].iov_len = sizeof xprt_port;
iov[1].iov_base = (char *)&ybr;
iov[1].iov_len = sizeof ybr;
+ ybr.ypbind_resp_3_u.ypbind_bindinfo.ypbind_svcaddr = malloc(sizeof(struct netbuf));
+ if (ybr.ypbind_resp_3_u.ypbind_bindinfo.ypbind_svcaddr == NULL)
+ errx(1, "malloc");
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));
+ copy_netbuf(ybr.ypbind_resp_3_u.ypbind_bindinfo.ypbind_svcaddr, raddrp);
if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) {
syslog(LOG_WARNING, "write: %m");
@@ -975,13 +1137,32 @@
* 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 *sa = (struct sockaddr *)addr->buf;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ if (sa->sa_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->sa_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);
}
@@ -993,8 +1174,8 @@
void
yp_restricted_mode(char *args)
{
- struct hostent *h;
- int i = 0;
+ struct addrinfo hints, *res;
+ int i = 0, status;
char *s;
/* Find the restricted domain. */
@@ -1002,14 +1183,25 @@
return;
domain_name = s;
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
/* Get the addresses of the servers. */
while ((s = strsep(&args, ",")) != NULL && i < RESTRICTED_SERVERS) {
- if ((h = gethostbyname(s)) == NULL)
+ if ((status = getaddrinfo(s, NULL, &hints, &res)) != 0)
return;
- bcopy (h->h_addr_list[0], &restricted_addrs[i],
- sizeof(struct in_addr));
+
+ if (res->ai_family == AF_INET) {
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
+ memcpy(&restricted_addrs[i], ipv4, sizeof(struct sockaddr_in));
+ } else if (res->ai_family == AF_INET6) {
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
+ memcpy(&restricted_addrs[i], ipv6, sizeof(struct sockaddr_in6));
+ }
i++;
}
+ freeaddrinfo(res);
/* ypset and ypsetme not allowed with restricted mode */
ypsetmode = YPSET_NO;
@@ -1017,3 +1209,19 @@
yp_restricted = i;
return;
}
+
+void
+copy_netbuf(struct netbuf *dst, struct netbuf *src)
+{
+ if (src == NULL || dst == NULL)
+ errx(1, "Invalid input: src or dst is NULL");
+ if (src->len > src->maxlen)
+ errx(1, "Invalid input: src len is greater than maxlen");
+ dst->maxlen = src->maxlen;
+ dst->len = src->len;
+ dst->buf = (char *)malloc(src->maxlen);
+ if (dst->buf == NULL)
+ errx(1, "malloc");
+ memcpy(dst->buf, src->buf, src->len);
+ return;
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 27, 11:35 PM (4 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15618625
Default Alt Text
D45515.diff (31 KB)

Event Timeline