The IPv6 stack labels incoming packets with an m_tag whose payload
is a struct ip6aux. A struct ip6aux used to contain a pointer to an in6_ifaddr, but that pointer could become a dangling reference in the lifetime of the m_tag, because ip6_setdstifaddr() did not increase the in6_ifaddr's reference count. I have removed the pointer from ip6aux. I load it with the interesting fields from the in6_ifaddr (an IPv6 address, a scope ID, and some flags), instead.
This commit is contained in:
parent
40ffc8b91f
commit
6709ce7762
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: icmp6.c,v 1.138 2007/10/24 06:37:20 dyoung Exp $ */
|
||||
/* $NetBSD: icmp6.c,v 1.139 2007/10/29 16:54:42 dyoung Exp $ */
|
||||
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.138 2007/10/24 06:37:20 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.139 2007/10/29 16:54:42 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
@ -1926,11 +1926,13 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
{
|
||||
struct ip6_hdr *ip6;
|
||||
struct icmp6_hdr *icmp6;
|
||||
struct in6_ifaddr *ia;
|
||||
const struct in6_ifaddr *ia;
|
||||
const struct ip6aux *ip6a;
|
||||
int plen;
|
||||
int type, code;
|
||||
struct ifnet *outif = NULL;
|
||||
struct in6_addr origdst, *src = NULL;
|
||||
struct in6_addr origdst;
|
||||
const struct in6_addr *src = NULL;
|
||||
|
||||
/* too short to reflect */
|
||||
if (off < sizeof(struct ip6_hdr)) {
|
||||
@ -1994,26 +1996,27 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
* procedure of an outgoing packet of our own, in which case we need
|
||||
* to search in the ifaddr list.
|
||||
*/
|
||||
if (!IN6_IS_ADDR_MULTICAST(&origdst)) {
|
||||
if ((ia = ip6_getdstifaddr(m))) {
|
||||
if (!(ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
|
||||
src = &ia->ia_addr.sin6_addr;
|
||||
} else {
|
||||
struct sockaddr_in6 d;
|
||||
if (IN6_IS_ADDR_MULTICAST(&origdst))
|
||||
;
|
||||
else if ((ip6a = ip6_getdstifaddr(m)) != NULL) {
|
||||
if ((ip6a->ip6a_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0)
|
||||
src = &ip6a->ip6a_src;
|
||||
} else {
|
||||
union {
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr sa;
|
||||
} u;
|
||||
|
||||
bzero(&d, sizeof(d));
|
||||
d.sin6_family = AF_INET6;
|
||||
d.sin6_len = sizeof(d);
|
||||
d.sin6_addr = origdst;
|
||||
ia = (struct in6_ifaddr *)
|
||||
ifa_ifwithaddr((struct sockaddr *)&d);
|
||||
if (ia &&
|
||||
!(ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
|
||||
src = &ia->ia_addr.sin6_addr;
|
||||
}
|
||||
}
|
||||
sockaddr_in6_init(&u.sin6, &origdst, 0, 0, 0);
|
||||
|
||||
ia = (struct in6_ifaddr *)ifa_ifwithaddr(&u.sa);
|
||||
|
||||
if (ia == NULL)
|
||||
;
|
||||
else if ((ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0)
|
||||
src = &ia->ia_addr.sin6_addr;
|
||||
}
|
||||
|
||||
if (src == NULL) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip6_input.c,v 1.111 2007/10/24 06:37:22 dyoung Exp $ */
|
||||
/* $NetBSD: ip6_input.c,v 1.112 2007/10/29 16:54:42 dyoung Exp $ */
|
||||
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.111 2007/10/24 06:37:22 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.112 2007/10/29 16:54:42 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
@ -149,7 +149,7 @@ struct pfil_head inet6_pfil_hook;
|
||||
struct ip6stat ip6stat;
|
||||
|
||||
static void ip6_init2(void *);
|
||||
static struct m_tag *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
|
||||
static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *);
|
||||
|
||||
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
|
||||
static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
|
||||
@ -827,24 +827,30 @@ ip6_input(struct mbuf *m)
|
||||
* set/grab in6_ifaddr correspond to IPv6 destination address.
|
||||
*/
|
||||
static struct m_tag *
|
||||
ip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
|
||||
ip6_setdstifaddr(struct mbuf *m, const struct in6_ifaddr *ia)
|
||||
{
|
||||
struct m_tag *mtag;
|
||||
|
||||
mtag = ip6_addaux(m);
|
||||
if (mtag)
|
||||
((struct ip6aux *)(mtag + 1))->ip6a_dstia6 = ia6;
|
||||
if (mtag != NULL) {
|
||||
struct ip6aux *ip6a;
|
||||
|
||||
ip6a = (struct ip6aux *)(mtag + 1);
|
||||
in6_setscope(&ip6a->ip6a_src, ia->ia_ifp, &ip6a->ip6a_scope_id);
|
||||
ip6a->ip6a_src = ia->ia_addr.sin6_addr;
|
||||
ip6a->ip6a_flags = ia->ia6_flags;
|
||||
}
|
||||
return mtag; /* NULL if failed to set */
|
||||
}
|
||||
|
||||
struct in6_ifaddr *
|
||||
const struct ip6aux *
|
||||
ip6_getdstifaddr(struct mbuf *m)
|
||||
{
|
||||
struct m_tag *mtag;
|
||||
|
||||
mtag = ip6_findaux(m);
|
||||
if (mtag)
|
||||
return ((struct ip6aux *)(mtag + 1))->ip6a_dstia6;
|
||||
if (mtag != NULL)
|
||||
return (struct ip6aux *)(mtag + 1);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip6_var.h,v 1.45 2007/07/19 20:48:57 dyoung Exp $ */
|
||||
/* $NetBSD: ip6_var.h,v 1.46 2007/10/29 16:54:43 dyoung Exp $ */
|
||||
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -248,7 +248,9 @@ struct ip6flow {
|
||||
*/
|
||||
struct ip6aux {
|
||||
/* ip6.ip6_dst */
|
||||
struct in6_ifaddr *ip6a_dstia6; /* my ifaddr that matches ip6_dst */
|
||||
struct in6_addr ip6a_src;
|
||||
uint32_t ip6a_scope_id;
|
||||
int ip6a_flags;
|
||||
};
|
||||
|
||||
/* flags passed to ip6_output as last parameter */
|
||||
@ -314,7 +316,7 @@ int icmp6_ctloutput(int, struct socket *, int, int, struct mbuf **);
|
||||
void ip6_init(void);
|
||||
void ip6intr(void);
|
||||
void ip6_input(struct mbuf *);
|
||||
struct in6_ifaddr *ip6_getdstifaddr(struct mbuf *);
|
||||
const struct ip6aux *ip6_getdstifaddr(struct mbuf *);
|
||||
void ip6_freepcbopts(struct ip6_pktopts *);
|
||||
void ip6_freemoptions(struct ip6_moptions *);
|
||||
int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: route6.c,v 1.20 2007/05/23 17:15:04 christos Exp $ */
|
||||
/* $NetBSD: route6.c,v 1.21 2007/10/29 16:54:43 dyoung Exp $ */
|
||||
/* $KAME: route6.c,v 1.22 2000/12/03 00:54:00 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: route6.c,v 1.20 2007/05/23 17:15:04 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: route6.c,v 1.21 2007/10/29 16:54:43 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mbuf.h>
|
||||
@ -133,7 +133,7 @@ ip6_rthdr0(struct mbuf *m, struct ip6_hdr *ip6,
|
||||
{
|
||||
int addrs, index;
|
||||
struct in6_addr *nextaddr, tmpaddr;
|
||||
struct in6_ifaddr *ifa;
|
||||
const struct ip6aux *ip6a;
|
||||
|
||||
if (rh0->ip6r0_segleft == 0)
|
||||
return (0);
|
||||
@ -190,9 +190,9 @@ ip6_rthdr0(struct mbuf *m, struct ip6_hdr *ip6,
|
||||
* of the current hop. [RFC4007, Section 9]
|
||||
* Then disambiguate the scope zone for the next hop (if necessary).
|
||||
*/
|
||||
if ((ifa = ip6_getdstifaddr(m)) == NULL)
|
||||
if ((ip6a = ip6_getdstifaddr(m)) == NULL)
|
||||
goto bad;
|
||||
if (in6_setscope(nextaddr, ifa->ia_ifp, NULL) != 0) {
|
||||
if (in6_setzoneid(nextaddr, ip6a->ip6a_scope_id) != 0) {
|
||||
ip6stat.ip6s_badscope++;
|
||||
goto bad;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user