Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106195600
D45515.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
D45515.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D45515: ypbind: IPv6 clean by adding version 3 of ypbind
Attached
Detach File
Event Timeline
Log In to Comment