1)Make it possible for rpcbind(8) to bind TCP listening socket to an IP
other than INADDR_ANY. 2) Add the -6 option to specify "IPv6 only". Glanced at by: bms Requested by: bms [2] PR: bin/84494 [1] Approved by: silence from maintainer (~2 weeks) [1] MFC after: 2 weeks
This commit is contained in:
parent
cf75c506db
commit
55987d865b
@ -2,7 +2,7 @@
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" Copyright 1991 Sun Microsystems, Inc.
|
||||
.\" $FreeBSD$
|
||||
.Dd November 29, 2006
|
||||
.Dd April 23, 2007
|
||||
.Dt RPCBIND 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -10,7 +10,7 @@
|
||||
.Nd universal addresses to RPC program number mapper
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl adiLls
|
||||
.Op Fl 6adiLls
|
||||
.Op Fl h Ar bindip
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
@ -68,6 +68,8 @@ The
|
||||
utility can only be started by the super-user.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width indent
|
||||
.It Fl 6
|
||||
Bind to AF_INET6 (IPv6) addresses only.
|
||||
.It Fl a
|
||||
When debugging
|
||||
.Pq Fl d ,
|
||||
@ -83,7 +85,7 @@ is also specified.
|
||||
With this option, the name-to-address translation consistency
|
||||
checks are shown in detail.
|
||||
.It Fl h Ar bindip
|
||||
Specify specific IP addresses to bind to for UDP requests.
|
||||
Specify specific IP addresses to bind to for TCP and UDP requests.
|
||||
This option
|
||||
may be specified multiple times and is typically necessary when running
|
||||
on a multi-homed host.
|
||||
|
@ -92,6 +92,7 @@ int oldstyle_local = 0;
|
||||
int verboselog = 0;
|
||||
|
||||
char **hosts = NULL;
|
||||
int ipv6_only = 0;
|
||||
int nhosts = 0;
|
||||
int on = 1;
|
||||
int rpcbindlockfd;
|
||||
@ -173,8 +174,12 @@ main(int argc, char *argv[])
|
||||
init_transport(nconf);
|
||||
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
if (nconf->nc_flag & NC_VISIBLE)
|
||||
init_transport(nconf);
|
||||
if (nconf->nc_flag & NC_VISIBLE)
|
||||
if (ipv6_only == 1 && strcmp(nconf->nc_protofmly,
|
||||
"inet") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else
|
||||
init_transport(nconf);
|
||||
}
|
||||
endnetconfig(nc_handle);
|
||||
|
||||
@ -252,261 +257,196 @@ init_transport(struct netconfig *nconf)
|
||||
mode_t oldmask;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return (1); /* not my type */
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return (1); /* not my type */
|
||||
#ifdef ND_DEBUG
|
||||
if (debugging) {
|
||||
int i;
|
||||
char **s;
|
||||
int i;
|
||||
char **s;
|
||||
|
||||
(void) fprintf(stderr, "%s: %ld lookup routines :\n",
|
||||
nconf->nc_netid, nconf->nc_nlookups);
|
||||
for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
|
||||
i++, s++)
|
||||
fprintf(stderr, "[%d] - %s\n", i, *s);
|
||||
(void)fprintf(stderr, "%s: %ld lookup routines :\n",
|
||||
nconf->nc_netid, nconf->nc_nlookups);
|
||||
for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
|
||||
i++, s++)
|
||||
fprintf(stderr, "[%d] - %s\n", i, *s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions. For NC_TPI_CLTS
|
||||
* we call this later, for each socket we like to bind.
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS) {
|
||||
if ((fd = __rpc_nconf2fd(nconf)) < 0) {
|
||||
int non_fatal = 0;
|
||||
|
||||
if (errno == EPROTONOSUPPORT)
|
||||
non_fatal = 1;
|
||||
syslog(non_fatal?LOG_DEBUG:LOG_ERR, "cannot create socket for %s",
|
||||
nconf->nc_netid);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return (1);
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((strcmp(nconf->nc_netid, "local") == 0) ||
|
||||
(strcmp(nconf->nc_netid, "unix") == 0)) {
|
||||
memset(&sun, 0, sizeof sun);
|
||||
sun.sun_family = AF_LOCAL;
|
||||
unlink(_PATH_RPCBINDSOCK);
|
||||
strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
|
||||
sun.sun_len = SUN_LEN(&sun);
|
||||
addrlen = sizeof (struct sockaddr_un);
|
||||
sa = (struct sockaddr *)&sun;
|
||||
memset(&sun, 0, sizeof sun);
|
||||
sun.sun_family = AF_LOCAL;
|
||||
unlink(_PATH_RPCBINDSOCK);
|
||||
strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
|
||||
sun.sun_len = SUN_LEN(&sun);
|
||||
addrlen = sizeof (struct sockaddr_un);
|
||||
sa = (struct sockaddr *)&sun;
|
||||
} else {
|
||||
/* Get rpcbind's address on this transport */
|
||||
/* Get rpcbind's address on this transport */
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = si.si_af;
|
||||
hints.ai_socktype = si.si_socktype;
|
||||
hints.ai_protocol = si.si_proto;
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = si.si_af;
|
||||
hints.ai_socktype = si.si_socktype;
|
||||
hints.ai_protocol = si.si_proto;
|
||||
}
|
||||
if (nconf->nc_semantics == NC_TPI_CLTS) {
|
||||
/*
|
||||
* If no hosts were specified, just bind to INADDR_ANY.
|
||||
* Otherwise make sure 127.0.0.1 is added to the list.
|
||||
*/
|
||||
nhostsbak = nhosts;
|
||||
nhostsbak++;
|
||||
hosts = realloc(hosts, nhostsbak * sizeof(char *));
|
||||
if (nhostsbak == 1)
|
||||
hosts[0] = "*";
|
||||
else {
|
||||
if (hints.ai_family == AF_INET) {
|
||||
hosts[nhostsbak - 1] = "127.0.0.1";
|
||||
} else if (hints.ai_family == AF_INET6) {
|
||||
hosts[nhostsbak - 1] = "::1";
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind to specific IPs if asked to
|
||||
*/
|
||||
checkbind = 1;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if ((fd = __rpc_nconf2fd(nconf)) < 0) {
|
||||
int non_fatal = 0;
|
||||
if (errno == EPROTONOSUPPORT &&
|
||||
nconf->nc_semantics != NC_TPI_CLTS)
|
||||
non_fatal = 1;
|
||||
syslog(non_fatal ? LOG_DEBUG : LOG_ERR,
|
||||
"cannot create socket for %s", nconf->nc_netid);
|
||||
return (1);
|
||||
}
|
||||
switch (hints.ai_family) {
|
||||
case AF_INET:
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET6 adress.
|
||||
*/
|
||||
if (inet_pton(AF_INET6,
|
||||
hosts[nhostsbak], host_addr) == 1)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET adress.
|
||||
*/
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1)
|
||||
continue;
|
||||
}
|
||||
if (setsockopt(fd, IPPROTO_IPV6,
|
||||
IPV6_V6ONLY, &on, sizeof on) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"can't set v6-only binding for "
|
||||
"ipv6 socket: %m");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no hosts were specified, just bind to INADDR_ANY
|
||||
*/
|
||||
if (strcmp("*", hosts[nhostsbak]) == 0)
|
||||
hosts[nhostsbak] = NULL;
|
||||
if ((strcmp(nconf->nc_netid, "local") != 0) &&
|
||||
(strcmp(nconf->nc_netid, "unix") != 0)) {
|
||||
if ((aicode = getaddrinfo(hosts[nhostsbak],
|
||||
servname, &hints, &res)) != 0) {
|
||||
syslog(LOG_ERR,
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
continue;
|
||||
}
|
||||
addrlen = res->ai_addrlen;
|
||||
sa = (struct sockaddr *)res->ai_addr;
|
||||
}
|
||||
oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
|
||||
if (bind(fd, sa, addrlen) != 0) {
|
||||
syslog(LOG_ERR, "cannot bind %s on %s: %m",
|
||||
(hosts[nhostsbak] == NULL) ? "*" :
|
||||
hosts[nhostsbak], nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
continue;
|
||||
} else
|
||||
checkbind++;
|
||||
(void)umask(oldmask);
|
||||
|
||||
/* Copy the address */
|
||||
taddr.addr.len = taddr.addr.maxlen = addrlen;
|
||||
taddr.addr.buf = malloc(addrlen);
|
||||
if (taddr.addr.buf == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"cannot allocate memory for %s address",
|
||||
nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
memcpy(taddr.addr.buf, sa, addrlen);
|
||||
#ifdef ND_DEBUG
|
||||
if (debugging) {
|
||||
/*
|
||||
* If no hosts were specified, just bind to INADDR_ANY. Otherwise
|
||||
* make sure 127.0.0.1 is added to the list.
|
||||
* for debugging print out our universal
|
||||
* address
|
||||
*/
|
||||
nhostsbak = nhosts;
|
||||
nhostsbak++;
|
||||
hosts = realloc(hosts, nhostsbak * sizeof(char *));
|
||||
if (nhostsbak == 1)
|
||||
hosts[0] = "*";
|
||||
else {
|
||||
if (hints.ai_family == AF_INET) {
|
||||
hosts[nhostsbak - 1] = "127.0.0.1";
|
||||
} else if (hints.ai_family == AF_INET6) {
|
||||
hosts[nhostsbak - 1] = "::1";
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
char *uaddr;
|
||||
struct netbuf nb;
|
||||
|
||||
/*
|
||||
* Bind to specific IPs if asked to
|
||||
*/
|
||||
checkbind = 1;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if ((fd = __rpc_nconf2fd(nconf)) < 0) {
|
||||
syslog(LOG_ERR, "cannot create socket for %s",
|
||||
nconf->nc_netid);
|
||||
return (1);
|
||||
}
|
||||
switch (hints.ai_family) {
|
||||
case AF_INET:
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET6 adress.
|
||||
*/
|
||||
if (inet_pton(AF_INET6,
|
||||
hosts[nhostsbak], host_addr) == 1)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET adress.
|
||||
*/
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1)
|
||||
continue;
|
||||
}
|
||||
if (setsockopt(fd, IPPROTO_IPV6,
|
||||
IPV6_V6ONLY, &on, sizeof on) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"can't set v6-only binding for "
|
||||
"udp6 socket: %m");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no hosts were specified, just bind to INADDR_ANY
|
||||
*/
|
||||
if (strcmp("*", hosts[nhostsbak]) == 0)
|
||||
hosts[nhostsbak] = NULL;
|
||||
|
||||
if ((aicode = getaddrinfo(hosts[nhostsbak],
|
||||
servname, &hints, &res)) != 0) {
|
||||
syslog(LOG_ERR,
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
continue;
|
||||
}
|
||||
addrlen = res->ai_addrlen;
|
||||
sa = (struct sockaddr *)res->ai_addr;
|
||||
oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
|
||||
if (bind(fd, sa, addrlen) != 0) {
|
||||
syslog(LOG_ERR, "cannot bind %s on %s: %m",
|
||||
(hosts[nhostsbak] == NULL) ? "*" :
|
||||
hosts[nhostsbak], nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
continue;
|
||||
} else
|
||||
checkbind++;
|
||||
(void) umask(oldmask);
|
||||
|
||||
/* Copy the address */
|
||||
taddr.addr.len = taddr.addr.maxlen = addrlen;
|
||||
taddr.addr.buf = malloc(addrlen);
|
||||
if (taddr.addr.buf == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"cannot allocate memory for %s address",
|
||||
nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
memcpy(taddr.addr.buf, sa, addrlen);
|
||||
#ifdef ND_DEBUG
|
||||
if (debugging) {
|
||||
/*
|
||||
* for debugging print out our universal
|
||||
* address
|
||||
*/
|
||||
char *uaddr;
|
||||
struct netbuf nb;
|
||||
|
||||
nb.buf = sa;
|
||||
nb.len = nb.maxlen = sa->sa_len;
|
||||
uaddr = taddr2uaddr(nconf, &nb);
|
||||
(void) fprintf(stderr,
|
||||
"rpcbind : my address is %s\n", uaddr);
|
||||
(void) free(uaddr);
|
||||
}
|
||||
nb.buf = sa;
|
||||
nb.len = nb.maxlen = sa->sa_len;
|
||||
uaddr = taddr2uaddr(nconf, &nb);
|
||||
(void)fprintf(stderr,
|
||||
"rpcbind : my address is %s\n", uaddr);
|
||||
(void)free(uaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
|
||||
my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
|
||||
RPC_MAXDATASIZE, RPC_MAXDATASIZE);
|
||||
if (my_xprt == (SVCXPRT *)NULL) {
|
||||
syslog(LOG_ERR, "%s: could not create service",
|
||||
nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (!checkbind)
|
||||
return 1;
|
||||
} else {
|
||||
if ((strcmp(nconf->nc_netid, "local") != 0) &&
|
||||
(strcmp(nconf->nc_netid, "unix") != 0)) {
|
||||
if ((aicode = getaddrinfo(NULL, servname, &hints, &res))
|
||||
!= 0) {
|
||||
syslog(LOG_ERR,
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
return 1;
|
||||
}
|
||||
addrlen = res->ai_addrlen;
|
||||
sa = (struct sockaddr *)res->ai_addr;
|
||||
}
|
||||
oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
|
||||
if (bind(fd, sa, addrlen) < 0) {
|
||||
syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
(void) umask(oldmask);
|
||||
|
||||
/* Copy the address */
|
||||
taddr.addr.len = taddr.addr.maxlen = addrlen;
|
||||
taddr.addr.buf = malloc(addrlen);
|
||||
if (taddr.addr.buf == NULL) {
|
||||
syslog(LOG_ERR, "cannot allocate memory for %s address",
|
||||
nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
memcpy(taddr.addr.buf, sa, addrlen);
|
||||
#ifdef ND_DEBUG
|
||||
if (debugging) {
|
||||
/* for debugging print out our universal address */
|
||||
char *uaddr;
|
||||
struct netbuf nb;
|
||||
|
||||
nb.buf = sa;
|
||||
nb.len = nb.maxlen = sa->sa_len;
|
||||
uaddr = taddr2uaddr(nconf, &nb);
|
||||
(void) fprintf(stderr, "rpcbind : my address is %s\n",
|
||||
uaddr);
|
||||
(void) free(uaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
|
||||
my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
|
||||
if (my_xprt == (SVCXPRT *)NULL) {
|
||||
syslog(LOG_ERR, "%s: could not create service",
|
||||
nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
|
||||
RPC_MAXDATASIZE, RPC_MAXDATASIZE);
|
||||
if (my_xprt == (SVCXPRT *)NULL) {
|
||||
syslog(LOG_ERR, "%s: could not create service",
|
||||
nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (!checkbind)
|
||||
return 1;
|
||||
|
||||
#ifdef PORTMAP
|
||||
/*
|
||||
@ -704,8 +644,11 @@ parseargs(int argc, char *argv[])
|
||||
#else
|
||||
#define WSOP ""
|
||||
#endif
|
||||
while ((c = getopt(argc, argv, "adh:iLls" WSOP)) != -1) {
|
||||
while ((c = getopt(argc, argv, "6adh:iLls" WSOP)) != -1) {
|
||||
switch (c) {
|
||||
case '6':
|
||||
ipv6_only = 1;
|
||||
break;
|
||||
case 'a':
|
||||
doabort = 1; /* when debugging, do an abort on */
|
||||
break; /* errors; for rpcbind developers */
|
||||
@ -741,7 +684,7 @@ parseargs(int argc, char *argv[])
|
||||
#endif
|
||||
default: /* error */
|
||||
fprintf(stderr,
|
||||
"usage: rpcbind [-adiLls%s] [-h bindip]\n",
|
||||
"usage: rpcbind [-6adiLls%s] [-h bindip]\n",
|
||||
WSOP);
|
||||
exit (1);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user