From caf8c9cda16f3804f93f34046fdd127c292e18f2 Mon Sep 17 00:00:00 2001 From: matteo Date: Mon, 23 Apr 2007 07:09:25 +0000 Subject: 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 --- usr.sbin/rpcbind/rpcbind.8 | 8 +- usr.sbin/rpcbind/rpcbind.c | 409 +++++++++++++++++++-------------------------- 2 files changed, 181 insertions(+), 236 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/rpcbind/rpcbind.8 b/usr.sbin/rpcbind/rpcbind.8 index 950d366..0ecf895 100644 --- a/usr.sbin/rpcbind/rpcbind.8 +++ b/usr.sbin/rpcbind/rpcbind.8 @@ -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. diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c index 46370ec..0125cb4 100644 --- a/usr.sbin/rpcbind/rpcbind.c +++ b/usr.sbin/rpcbind/rpcbind.c @@ -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; - - (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); + 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); } #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 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; } - 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) { - 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); - } -#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; - } + /* + * 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; } - 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; + 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; } - 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; + 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; } - (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; + 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; } - memcpy(taddr.addr.buf, sa, addrlen); + 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); - } + 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); + 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); } -- cgit v1.1