diff options
author | imp <imp@FreeBSD.org> | 2010-02-09 18:10:56 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2010-02-09 18:10:56 +0000 |
commit | 4aa0a8fc65254f7aae5a84358fcad1a6986615b9 (patch) | |
tree | a2158aca71bda968265d0c2429d6757db51f0ef1 /usr.sbin/rpcbind/util.c | |
parent | bcd7bda0dad6382566dc0e40b8415a24b3f1f778 (diff) | |
download | FreeBSD-src-4aa0a8fc65254f7aae5a84358fcad1a6986615b9.zip FreeBSD-src-4aa0a8fc65254f7aae5a84358fcad1a6986615b9.tar.gz |
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
Diffstat (limited to 'usr.sbin/rpcbind/util.c')
-rw-r--r-- | usr.sbin/rpcbind/util.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/usr.sbin/rpcbind/util.c b/usr.sbin/rpcbind/util.c index 66797a7..9cdfa70 100644 --- a/usr.sbin/rpcbind/util.c +++ b/usr.sbin/rpcbind/util.c @@ -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 *serv_uaddr, char *clnt_uaddr, 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 *serv_uaddr, char *clnt_uaddr, !(ifap->ifa_flags & IFF_UP)) continue; + if (!(ifap->ifa_flags & IFF_LOOPBACK) && !listen_addr(ifsa)) + continue; + switch (hint_sa->sa_family) { case AF_INET: /* |