svn commit: r206535 - in stable/8/usr.sbin: . dumpcis makefs
makefs/ffs mfiutil rpcbind
Warner Losh
imp at FreeBSD.org
Tue Apr 13 00:48:54 UTC 2010
Author: imp
Date: Tue Apr 13 00:48:54 2010
New Revision: 206535
URL: http://svn.freebsd.org/changeset/base/206535
Log:
MFC r203710:
When you have multiple addresses on the same network on different
interfaces (such as when you are part of a carp pool), and you run
rpcbind -h to restrict which interfaces have rpc services, rpcbind can
none-the-less return addresses that aren't in the -h list. This patch
enforces the rule that when you specify -h on the command line, then
services returned from rpcbind must be to one of the addresses listed
in -h, or be a loopback address (since localhost is implicit when
running -h).
The root cause of this is the assumption in addrmerge that there can
be only one interface that matches a given network IP address. This
turns out not to be the case. To retain historical behavior, I didn't
try to fix the routine to prefer the address that the request came
into, since I didn't know the side effects that might cause in the
normal case. My quick analysis suggests that it wouldn't be a
problem, but since this code is tricky I opted for the more
conservative patch of only restricting the reply when -h is in effect.
Hence, this change will have no effect when you are running rpcbind
without -h.
Reviewed by: alfred@
Sponsored by: iX Systems
MFC after: 2 weeks
Modified:
stable/8/usr.sbin/rpcbind/rpcbind.c
stable/8/usr.sbin/rpcbind/rpcbind.h
stable/8/usr.sbin/rpcbind/util.c
Directory Properties:
stable/8/usr.sbin/ (props changed)
stable/8/usr.sbin/Makefile (props changed)
stable/8/usr.sbin/acpi/ (props changed)
stable/8/usr.sbin/arp/ (props changed)
stable/8/usr.sbin/bsnmpd/ (props changed)
stable/8/usr.sbin/burncd/ (props changed)
stable/8/usr.sbin/cdcontrol/ (props changed)
stable/8/usr.sbin/chown/ (props changed)
stable/8/usr.sbin/cpucontrol/ (props changed)
stable/8/usr.sbin/crashinfo/ (props changed)
stable/8/usr.sbin/cron/ (props changed)
stable/8/usr.sbin/crunch/examples/ (props changed)
stable/8/usr.sbin/cxgbtool/ (props changed)
stable/8/usr.sbin/diskinfo/ (props changed)
stable/8/usr.sbin/dumpcis/cardinfo.h (props changed)
stable/8/usr.sbin/dumpcis/cis.h (props changed)
stable/8/usr.sbin/faithd/ (props changed)
stable/8/usr.sbin/freebsd-update/ (props changed)
stable/8/usr.sbin/inetd/ (props changed)
stable/8/usr.sbin/iostat/ (props changed)
stable/8/usr.sbin/jail/ (props changed)
stable/8/usr.sbin/jls/ (props changed)
stable/8/usr.sbin/lpr/ (props changed)
stable/8/usr.sbin/makefs/ffs/ffs_bswap.c (props changed)
stable/8/usr.sbin/makefs/ffs/ffs_subr.c (props changed)
stable/8/usr.sbin/makefs/ffs/ufs_bswap.h (props changed)
stable/8/usr.sbin/makefs/getid.c (props changed)
stable/8/usr.sbin/mergemaster/ (props changed)
stable/8/usr.sbin/mfiutil/mfiutil.8 (props changed)
stable/8/usr.sbin/mptutil/ (props changed)
stable/8/usr.sbin/ndp/ (props changed)
stable/8/usr.sbin/newsyslog/ (props changed)
stable/8/usr.sbin/ntp/ (props changed)
stable/8/usr.sbin/pmcstat/ (props changed)
stable/8/usr.sbin/powerd/ (props changed)
stable/8/usr.sbin/ppp/ (props changed)
stable/8/usr.sbin/pstat/ (props changed)
stable/8/usr.sbin/rpc.umntall/ (props changed)
stable/8/usr.sbin/rtsold/ (props changed)
stable/8/usr.sbin/service/ (props changed)
stable/8/usr.sbin/sysinstall/ (props changed)
stable/8/usr.sbin/syslogd/ (props changed)
stable/8/usr.sbin/traceroute/ (props changed)
stable/8/usr.sbin/traceroute6/ (props changed)
stable/8/usr.sbin/usbconfig/ (props changed)
stable/8/usr.sbin/vidcontrol/ (props changed)
stable/8/usr.sbin/wpa/ (props changed)
stable/8/usr.sbin/ypserv/ (props changed)
stable/8/usr.sbin/zic/ (props changed)
Modified: stable/8/usr.sbin/rpcbind/rpcbind.c
==============================================================================
--- stable/8/usr.sbin/rpcbind/rpcbind.c Tue Apr 13 00:33:07 2010 (r206534)
+++ stable/8/usr.sbin/rpcbind/rpcbind.c Tue Apr 13 00:48:54 2010 (r206535)
@@ -92,6 +92,7 @@ int oldstyle_local = 0;
int verboselog = 0;
char **hosts = NULL;
+struct sockaddr **bound_sa;
int ipv6_only = 0;
int nhosts = 0;
int on = 1;
@@ -119,6 +120,7 @@ static void rbllist_add(rpcprog_t, rpcve
struct netbuf *);
static void terminate(int);
static void parseargs(int, char *[]);
+static void update_bound_sa(void);
int
main(int argc, char *argv[])
@@ -130,6 +132,8 @@ main(int argc, char *argv[])
parseargs(argc, argv);
+ update_bound_sa();
+
/* Check that another rpcbind isn't already running. */
if ((rpcbindlockfd = (open(RPCBINDDLOCK,
O_RDONLY|O_CREAT, 0444))) == -1)
@@ -323,8 +327,7 @@ init_transport(struct netconfig *nconf)
* 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++;
+ nhostsbak = nhosts + 1;
hosts = realloc(hosts, nhostsbak * sizeof(char *));
if (nhostsbak == 1)
hosts[0] = "*";
@@ -657,6 +660,75 @@ error:
return (1);
}
+/*
+ * Create the list of addresses that we're bound to. Normally, this
+ * list is empty because we're listening on the wildcard address
+ * (nhost == 0). If -h is specified on the command line, then
+ * bound_sa will have a list of the addresses that the program binds
+ * to specifically. This function takes that list and converts them to
+ * struct sockaddr * and stores them in bound_sa.
+ */
+static void
+update_bound_sa(void)
+{
+ struct addrinfo hints, *res = NULL;
+ int i;
+
+ if (nhosts == 0)
+ return;
+ bound_sa = malloc(sizeof(*bound_sa) * nhosts);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ for (i = 0; i < nhosts; i++) {
+ if (getaddrinfo(hosts[i], NULL, &hints, &res) != 0)
+ continue;
+ bound_sa[i] = malloc(res->ai_addrlen);
+ memcpy(bound_sa[i], res->ai_addr, res->ai_addrlen);
+ }
+}
+
+/*
+ * Match the sa against the list of addresses we've bound to. If
+ * we've not specifically bound to anything, we match everything.
+ * Otherwise, if the IPv4 or IPv6 address matches one of the addresses
+ * in bound_sa, we return true. If not, we return false.
+ */
+int
+listen_addr(const struct sockaddr *sa)
+{
+ int i;
+
+ /*
+ * If nhosts == 0, then there were no -h options on the
+ * command line, so all addresses are addresses we're
+ * listening to.
+ */
+ if (nhosts == 0)
+ return 1;
+ for (i = 0; i < nhosts; i++) {
+ if (bound_sa[i] == NULL ||
+ sa->sa_family != bound_sa[i]->sa_family)
+ continue;
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (memcmp(&SA2SINADDR(sa), &SA2SINADDR(bound_sa[i]),
+ sizeof(struct in_addr)) == 0)
+ return (1);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (memcmp(&SA2SIN6ADDR(sa), &SA2SIN6ADDR(bound_sa[i]),
+ sizeof(struct in6_addr)) == 0)
+ return (1);
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+ return (0);
+}
+
static void
rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
struct netbuf *addr)
Modified: stable/8/usr.sbin/rpcbind/rpcbind.h
==============================================================================
--- stable/8/usr.sbin/rpcbind/rpcbind.h Tue Apr 13 00:33:07 2010 (r206534)
+++ stable/8/usr.sbin/rpcbind/rpcbind.h Tue Apr 13 00:48:54 2010 (r206535)
@@ -134,6 +134,7 @@ void read_warmstart(void);
char *addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
char *netid);
+int listen_addr(const struct sockaddr *sa);
void network_init(void);
struct sockaddr *local_sa(int);
@@ -141,4 +142,12 @@ struct sockaddr *local_sa(int);
#define RPCB_ALLVERS 0
#define RPCB_ONEVERS 1
+/* To convert a struct sockaddr to IPv4 or IPv6 address */
+#define SA2SIN(sa) ((struct sockaddr_in *)(sa))
+#define SA2SINADDR(sa) (SA2SIN(sa)->sin_addr)
+#ifdef INET6
+#define SA2SIN6(sa) ((struct sockaddr_in6 *)(sa))
+#define SA2SIN6ADDR(sa) (SA2SIN6(sa)->sin6_addr)
+#endif
+
#endif /* rpcbind_h */
Modified: stable/8/usr.sbin/rpcbind/util.c
==============================================================================
--- stable/8/usr.sbin/rpcbind/util.c Tue Apr 13 00:33:07 2010 (r206534)
+++ stable/8/usr.sbin/rpcbind/util.c Tue Apr 13 00:48:54 2010 (r206535)
@@ -58,13 +58,6 @@
#include "rpcbind.h"
-#define SA2SIN(sa) ((struct sockaddr_in *)(sa))
-#define SA2SINADDR(sa) (SA2SIN(sa)->sin_addr)
-#ifdef INET6
-#define SA2SIN6(sa) ((struct sockaddr_in6 *)(sa))
-#define SA2SIN6ADDR(sa) (SA2SIN6(sa)->sin6_addr)
-#endif
-
static struct sockaddr_in *local_in4;
#ifdef INET6
static struct sockaddr_in6 *local_in6;
@@ -176,9 +169,13 @@ addrmerge(struct netbuf *caller, char *s
goto freeit;
/*
- * Loop through all interfaces. For each interface, see if the
- * network portion of its address is equal to that of the client.
- * If so, we have found the interface that we want to use.
+ * Loop through all interfaces. For each interface, see if it
+ * is either the loopback interface (which we always listen
+ * on) or is one of the addresses the program bound to (the
+ * wildcard by default, or a subset if -h is specified) and
+ * the network portion of its address is equal to that of the
+ * client. If so, we have found the interface that we want to
+ * use.
*/
bestif = NULL;
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
@@ -189,6 +186,9 @@ addrmerge(struct netbuf *caller, char *s
!(ifap->ifa_flags & IFF_UP))
continue;
+ if (!(ifap->ifa_flags & IFF_LOOPBACK) && !listen_addr(ifsa))
+ continue;
+
switch (hint_sa->sa_family) {
case AF_INET:
/*
More information about the svn-src-stable
mailing list