PR/27286: Tom Ivar Helbekkmo: Allow RTM_GET to work with RTA_IFA|RTA_IFP set.

Quiting Tom: The problem is the special case of an RTM_GET message
that wants interface information included in the response, and
therefore include the RTA_IFA or RTA_IFP (or both) flags in the
bitmask that says what addresses are supplied in the message.  For
the RTM_GET message, it doesn't make sense to supply addresses
other than the one you're asking about, so those two other bits
are, in that specific case, overloaded with this meaning.

There is code in sys/net/rtsock.c to handle the case, but at some
time, extra sanity checking of the received message was added, that
failed to take this possibility into account.

The patch, is needed for the Asterisk software PBX to work properly
when it has multiple interfaces active: it needs to ask the kernel
for the IP address of the interface that will be used to communicate
with a given host.
This commit is contained in:
christos 2004-10-23 19:13:22 +00:00
parent dfc3ead10a
commit fbbeedbe63

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtsock.c,v 1.71 2004/05/25 04:33:59 atatat Exp $ */
/* $NetBSD: rtsock.c,v 1.72 2004/10/23 19:13:22 christos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.71 2004/05/25 04:33:59 atatat Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.72 2004/10/23 19:13:22 christos Exp $");
#include "opt_inet.h"
@ -100,7 +100,7 @@ struct walkarg {
static struct mbuf *rt_msg1(int, struct rt_addrinfo *, caddr_t, int);
static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *, int *);
static int rt_xaddrs(const char *, const char *, struct rt_addrinfo *);
static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *);
static int sysctl_dumpentry(struct radix_node *, void *);
static int sysctl_iflist(int, struct walkarg *, int);
static int sysctl_rtable(SYSCTLFN_PROTO);
@ -235,7 +235,7 @@ route_output(struct mbuf *m, ...)
rtm->rtm_pid = curproc->p_pid;
memset(&info, 0, sizeof(info));
info.rti_addrs = rtm->rtm_addrs;
if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info))
if (rt_xaddrs(rtm->rtm_type, (caddr_t)(rtm + 1), len + (caddr_t)rtm, &info))
senderr(EINVAL);
info.rti_flags = rtm->rtm_flags;
if (dst == 0 || (dst->sa_family >= AF_MAX))
@ -470,7 +470,7 @@ rt_setmetrics(u_long which, const struct rt_metrics *in, struct rt_metrics *out)
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
static int
rt_xaddrs(const char *cp, const char *cplim, struct rt_addrinfo *rtinfo)
rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, struct rt_addrinfo *rtinfo)
{
const struct sockaddr *sa = NULL; /* Quell compiler warning */
int i;
@ -482,9 +482,14 @@ rt_xaddrs(const char *cp, const char *cplim, struct rt_addrinfo *rtinfo)
ADVANCE(cp, sa);
}
/* Check for extra addresses specified. */
if ((rtinfo->rti_addrs & (~0 << i)) != 0)
return (1);
/* Check for extra addresses specified, except RTM_GET asking for interface info. */
if (rtmtype == RTM_GET) {
if (((rtinfo->rti_addrs & (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0)
return (1);
} else {
if ((rtinfo->rti_addrs & (~0 << i)) != 0)
return (1);
}
/* Check for bad data length. */
if (cp != cplim) {
if (i == RTAX_NETMASK + 1 &&