Remove ip6_getdstifaddr() and all functions to work with auxiliary data.
It isn't safe to keep unreferenced ifaddrs. Use in6ifa_ifwithaddr() to determine ifaddr corresponding to destination address. Since currently we keep addresses with embedded scope zone, in6ifa_ifwithaddr is called with zero zoneid and marked with XXX. Also remove route and lle lookups from ip6_input. Use in6ifa_ifwithaddr() instead. Sponsored by: Yandex LLC
This commit is contained in:
parent
e977d70f45
commit
3e88eb903b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=274300
@ -513,6 +513,7 @@ tcp6_input(struct mbuf **mp, int *offp, int proto)
|
||||
{
|
||||
struct mbuf *m = *mp;
|
||||
struct in6_ifaddr *ia6;
|
||||
struct ip6_hdr *ip6;
|
||||
|
||||
IP6_EXTHDR_CHECK(m, *offp, sizeof(struct tcphdr), IPPROTO_DONE);
|
||||
|
||||
@ -520,7 +521,8 @@ tcp6_input(struct mbuf **mp, int *offp, int proto)
|
||||
* draft-itojun-ipv6-tcp-to-anycast
|
||||
* better place to put this in?
|
||||
*/
|
||||
ia6 = ip6_getdstifaddr(m);
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia6 && (ia6->ia6_flags & IN6_IFF_ANYCAST)) {
|
||||
struct ip6_hdr *ip6;
|
||||
|
||||
@ -1251,7 +1253,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
|
||||
if (isipv6 && !V_ip6_use_deprecated) {
|
||||
struct in6_ifaddr *ia6;
|
||||
|
||||
ia6 = ip6_getdstifaddr(m);
|
||||
ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia6 != NULL &&
|
||||
(ia6->ia6_flags & IN6_IFF_DEPRECATED)) {
|
||||
ifa_free(&ia6->ia_ifa);
|
||||
|
@ -59,13 +59,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
/*
|
||||
* Define it to get a correct behavior on per-interface statistics.
|
||||
* You will need to perform an extra routing table lookup, per fragment,
|
||||
* to do it. This may, or may not be, a performance hit.
|
||||
*/
|
||||
#define IN6_IFSTAT_STRICT
|
||||
|
||||
static void frag6_enq(struct ip6asfrag *, struct ip6asfrag *);
|
||||
static void frag6_deq(struct ip6asfrag *);
|
||||
static void frag6_insque(struct ip6q *, struct ip6q *);
|
||||
@ -160,9 +153,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
||||
struct ip6_frag *ip6f;
|
||||
struct ip6q *q6;
|
||||
struct ip6asfrag *af6, *ip6af, *af6dwn;
|
||||
#ifdef IN6_IFSTAT_STRICT
|
||||
struct in6_ifaddr *ia;
|
||||
#endif
|
||||
int offset = *offp, nxt, i, next;
|
||||
int first_frag = 0;
|
||||
int fragoff, frgpartlen; /* must be larger than u_int16_t */
|
||||
@ -183,18 +174,12 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
||||
#endif
|
||||
|
||||
dstifp = NULL;
|
||||
#ifdef IN6_IFSTAT_STRICT
|
||||
/* find the destination interface of the packet. */
|
||||
if ((ia = ip6_getdstifaddr(m)) != NULL) {
|
||||
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia != NULL) {
|
||||
dstifp = ia->ia_ifp;
|
||||
ifa_free(&ia->ia_ifa);
|
||||
}
|
||||
#else
|
||||
/* we are violating the spec, this is not the destination interface */
|
||||
if ((m->m_flags & M_PKTHDR) != 0)
|
||||
dstifp = m->m_pkthdr.rcvif;
|
||||
#endif
|
||||
|
||||
/* jumbo payload can't contain a fragment header */
|
||||
if (ip6->ip6_plen == 0) {
|
||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
|
||||
|
@ -1313,7 +1313,8 @@ ni6_input(struct mbuf *m, int off)
|
||||
goto bad;
|
||||
/* else it's a link-local multicast, fine */
|
||||
} else { /* unicast or anycast */
|
||||
if ((ia6 = ip6_getdstifaddr(m)) == NULL)
|
||||
ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia6 == NULL)
|
||||
goto bad; /* XXX impossible */
|
||||
|
||||
if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) &&
|
||||
@ -2136,13 +2137,13 @@ icmp6_rip6_input(struct mbuf **mp, int off)
|
||||
void
|
||||
icmp6_reflect(struct mbuf *m, size_t off)
|
||||
{
|
||||
struct in6_addr src, *srcp = NULL;
|
||||
struct ip6_hdr *ip6;
|
||||
struct icmp6_hdr *icmp6;
|
||||
struct in6_ifaddr *ia = NULL;
|
||||
struct ifnet *outif = NULL;
|
||||
int plen;
|
||||
int type, code;
|
||||
struct ifnet *outif = NULL;
|
||||
struct in6_addr origdst, src, *srcp = NULL;
|
||||
|
||||
/* too short to reflect */
|
||||
if (off < sizeof(struct ip6_hdr)) {
|
||||
@ -2189,43 +2190,18 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
type = icmp6->icmp6_type; /* keep type for statistics */
|
||||
code = icmp6->icmp6_code; /* ditto. */
|
||||
|
||||
origdst = ip6->ip6_dst;
|
||||
/*
|
||||
* ip6_input() drops a packet if its src is multicast.
|
||||
* So, the src is never multicast.
|
||||
*/
|
||||
ip6->ip6_dst = ip6->ip6_src;
|
||||
|
||||
/*
|
||||
* If the incoming packet was addressed directly to us (i.e. unicast),
|
||||
* use dst as the src for the reply.
|
||||
* The IN6_IFF_NOTREADY case should be VERY rare, but is possible
|
||||
* (for example) when we encounter an error while forwarding procedure
|
||||
* destined to a duplicated address of ours.
|
||||
* Note that ip6_getdstifaddr() may fail if we are in an error handling
|
||||
* 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)))
|
||||
srcp = &ia->ia_addr.sin6_addr;
|
||||
} else {
|
||||
struct sockaddr_in6 d;
|
||||
|
||||
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))) {
|
||||
srcp = &ia->ia_addr.sin6_addr;
|
||||
}
|
||||
}
|
||||
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia != NULL && !(ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
|
||||
srcp = &ia->ia_addr.sin6_addr;
|
||||
}
|
||||
|
||||
if (srcp == NULL) {
|
||||
@ -2257,7 +2233,11 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
}
|
||||
srcp = &src;
|
||||
}
|
||||
|
||||
/*
|
||||
* ip6_input() drops a packet if its src is multicast.
|
||||
* So, the src is never multicast.
|
||||
*/
|
||||
ip6->ip6_dst = ip6->ip6_src;
|
||||
ip6->ip6_src = *srcp;
|
||||
ip6->ip6_flow = 0;
|
||||
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
|
||||
|
@ -148,10 +148,6 @@ struct rwlock in6_ifaddr_lock;
|
||||
RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
|
||||
|
||||
static void ip6_init2(void *);
|
||||
static struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
|
||||
static struct ip6aux *ip6_addaux(struct mbuf *);
|
||||
static struct ip6aux *ip6_findaux(struct mbuf *m);
|
||||
static void ip6_delaux (struct mbuf *);
|
||||
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
|
||||
#ifdef PULLDOWN_TEST
|
||||
static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
|
||||
@ -399,19 +395,15 @@ ip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off,
|
||||
void
|
||||
ip6_input(struct mbuf *m)
|
||||
{
|
||||
struct in6_addr odst;
|
||||
struct ip6_hdr *ip6;
|
||||
int off = sizeof(struct ip6_hdr), nest;
|
||||
struct in6_ifaddr *ia;
|
||||
u_int32_t plen;
|
||||
u_int32_t rtalert = ~0;
|
||||
int off = sizeof(struct ip6_hdr), nest;
|
||||
int nxt, ours = 0;
|
||||
struct ifnet *deliverifp = NULL, *ifp = NULL;
|
||||
struct in6_addr odst;
|
||||
struct route_in6 rin6;
|
||||
int srcrt = 0;
|
||||
struct llentry *lle = NULL;
|
||||
struct sockaddr_in6 dst6, *dst;
|
||||
|
||||
bzero(&rin6, sizeof(struct route_in6));
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* should the inner packet be considered authentic?
|
||||
@ -424,18 +416,12 @@ ip6_input(struct mbuf *m)
|
||||
|
||||
#endif /* IPSEC */
|
||||
|
||||
/*
|
||||
* make sure we don't have onion peering information into m_tag.
|
||||
*/
|
||||
ip6_delaux(m);
|
||||
|
||||
if (m->m_flags & M_FASTFWD_OURS) {
|
||||
/*
|
||||
* Firewall changed destination to local.
|
||||
*/
|
||||
m->m_flags &= ~M_FASTFWD_OURS;
|
||||
ours = 1;
|
||||
deliverifp = m->m_pkthdr.rcvif;
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
goto hbhcheck;
|
||||
}
|
||||
@ -462,10 +448,8 @@ ip6_input(struct mbuf *m)
|
||||
}
|
||||
|
||||
/* drop the packet if IPv6 operation is disabled on the IF */
|
||||
if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) {
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED))
|
||||
goto bad;
|
||||
|
||||
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
|
||||
IP6STAT_INC(ip6s_total);
|
||||
@ -626,7 +610,6 @@ ip6_input(struct mbuf *m)
|
||||
if (m->m_flags & M_FASTFWD_OURS) {
|
||||
m->m_flags &= ~M_FASTFWD_OURS;
|
||||
ours = 1;
|
||||
deliverifp = m->m_pkthdr.rcvif;
|
||||
goto hbhcheck;
|
||||
}
|
||||
if ((m->m_flags & M_IP6_NEXTHOP) &&
|
||||
@ -637,7 +620,7 @@ ip6_input(struct mbuf *m)
|
||||
* connected host.
|
||||
*/
|
||||
ip6_forward(m, 1);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
passin:
|
||||
@ -660,7 +643,6 @@ ip6_input(struct mbuf *m)
|
||||
IP6STAT_INC(ip6s_badscope);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Multicast check. Assume packet is for us to avoid
|
||||
* prematurely taking locks.
|
||||
@ -668,53 +650,16 @@ ip6_input(struct mbuf *m)
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
ours = 1;
|
||||
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
|
||||
deliverifp = m->m_pkthdr.rcvif;
|
||||
goto hbhcheck;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unicast check
|
||||
* Unicast check
|
||||
* XXX: For now we keep link-local IPv6 addresses with embedded
|
||||
* scope zone id, therefore we use zero zoneid here.
|
||||
*/
|
||||
|
||||
bzero(&dst6, sizeof(dst6));
|
||||
dst6.sin6_family = AF_INET6;
|
||||
dst6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
dst6.sin6_addr = ip6->ip6_dst;
|
||||
ifp = m->m_pkthdr.rcvif;
|
||||
IF_AFDATA_RLOCK(ifp);
|
||||
lle = lla_lookup(LLTABLE6(ifp), 0,
|
||||
(struct sockaddr *)&dst6);
|
||||
IF_AFDATA_RUNLOCK(ifp);
|
||||
if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
|
||||
struct ifaddr *ifa;
|
||||
struct in6_ifaddr *ia6;
|
||||
int bad;
|
||||
|
||||
bad = 1;
|
||||
IF_ADDR_RLOCK(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family != dst6.sin6_family)
|
||||
continue;
|
||||
if (sa_equal(&dst6, ifa->ifa_addr))
|
||||
break;
|
||||
}
|
||||
KASSERT(ifa != NULL, ("%s: ifa not found for lle %p",
|
||||
__func__, lle));
|
||||
|
||||
ia6 = (struct in6_ifaddr *)ifa;
|
||||
if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
|
||||
/* Count the packet in the ip address stats */
|
||||
counter_u64_add(ia6->ia_ifa.ifa_ipackets, 1);
|
||||
counter_u64_add(ia6->ia_ifa.ifa_ibytes,
|
||||
m->m_pkthdr.len);
|
||||
|
||||
/*
|
||||
* record address information into m_tag.
|
||||
*/
|
||||
(void)ip6_setdstifaddr(m, ia6);
|
||||
|
||||
bad = 0;
|
||||
} else {
|
||||
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia != NULL) {
|
||||
if (ia->ia6_flags & IN6_IFF_NOTREADY) {
|
||||
char ip6bufs[INET6_ADDRSTRLEN];
|
||||
char ip6bufd[INET6_ADDRSTRLEN];
|
||||
/* address is not ready, so discard the packet. */
|
||||
@ -722,137 +667,15 @@ ip6_input(struct mbuf *m)
|
||||
"ip6_input: packet to an unready address %s->%s\n",
|
||||
ip6_sprintf(ip6bufs, &ip6->ip6_src),
|
||||
ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
|
||||
}
|
||||
IF_ADDR_RUNLOCK(ifp);
|
||||
LLE_RUNLOCK(lle);
|
||||
if (bad)
|
||||
goto bad;
|
||||
else {
|
||||
ours = 1;
|
||||
deliverifp = ifp;
|
||||
goto hbhcheck;
|
||||
}
|
||||
}
|
||||
if (lle != NULL)
|
||||
LLE_RUNLOCK(lle);
|
||||
|
||||
dst = &rin6.ro_dst;
|
||||
dst->sin6_len = sizeof(struct sockaddr_in6);
|
||||
dst->sin6_family = AF_INET6;
|
||||
dst->sin6_addr = ip6->ip6_dst;
|
||||
rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m));
|
||||
if (rin6.ro_rt)
|
||||
RT_UNLOCK(rin6.ro_rt);
|
||||
|
||||
#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
|
||||
|
||||
/*
|
||||
* Accept the packet if the forwarding interface to the destination
|
||||
* according to the routing table is the loopback interface,
|
||||
* unless the associated route has a gateway.
|
||||
* Note that this approach causes to accept a packet if there is a
|
||||
* route to the loopback interface for the destination of the packet.
|
||||
* But we think it's even useful in some situations, e.g. when using
|
||||
* a special daemon which wants to intercept the packet.
|
||||
*
|
||||
* XXX: some OSes automatically make a cloned route for the destination
|
||||
* of an outgoing packet. If the outgoing interface of the packet
|
||||
* is a loopback one, the kernel would consider the packet to be
|
||||
* accepted, even if we have no such address assinged on the interface.
|
||||
* We check the cloned flag of the route entry to reject such cases,
|
||||
* assuming that route entries for our own addresses are not made by
|
||||
* cloning (it should be true because in6_addloop explicitly installs
|
||||
* the host route). However, we might have to do an explicit check
|
||||
* while it would be less efficient. Or, should we rather install a
|
||||
* reject route for such a case?
|
||||
*/
|
||||
if (rin6.ro_rt &&
|
||||
(rin6.ro_rt->rt_flags &
|
||||
(RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
|
||||
#ifdef RTF_WASCLONED
|
||||
!(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
|
||||
#endif
|
||||
#ifdef RTF_CLONED
|
||||
!(rin6.ro_rt->rt_flags & RTF_CLONED) &&
|
||||
#endif
|
||||
#if 0
|
||||
/*
|
||||
* The check below is redundant since the comparison of
|
||||
* the destination and the key of the rtentry has
|
||||
* already done through looking up the routing table.
|
||||
*/
|
||||
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
|
||||
&rt6_key(rin6.ro_rt)->sin6_addr)
|
||||
#endif
|
||||
rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
|
||||
int free_ia6 = 0;
|
||||
struct in6_ifaddr *ia6;
|
||||
|
||||
/*
|
||||
* found the loopback route to the interface address
|
||||
*/
|
||||
if (rin6.ro_rt->rt_gateway->sa_family == AF_LINK) {
|
||||
struct sockaddr_in6 dest6;
|
||||
|
||||
bzero(&dest6, sizeof(dest6));
|
||||
dest6.sin6_family = AF_INET6;
|
||||
dest6.sin6_len = sizeof(dest6);
|
||||
dest6.sin6_addr = ip6->ip6_dst;
|
||||
ia6 = (struct in6_ifaddr *)
|
||||
ifa_ifwithaddr((struct sockaddr *)&dest6);
|
||||
if (ia6 == NULL)
|
||||
goto bad;
|
||||
free_ia6 = 1;
|
||||
}
|
||||
else
|
||||
ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
|
||||
|
||||
/*
|
||||
* record address information into m_tag.
|
||||
*/
|
||||
(void)ip6_setdstifaddr(m, ia6);
|
||||
|
||||
/*
|
||||
* packets to a tentative, duplicated, or somehow invalid
|
||||
* address must not be accepted.
|
||||
*/
|
||||
if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
|
||||
/* this address is ready */
|
||||
ours = 1;
|
||||
deliverifp = ia6->ia_ifp; /* correct? */
|
||||
/* Count the packet in the ip address stats */
|
||||
counter_u64_add(ia6->ia_ifa.ifa_ipackets, 1);
|
||||
counter_u64_add(ia6->ia_ifa.ifa_ibytes,
|
||||
m->m_pkthdr.len);
|
||||
if (free_ia6)
|
||||
ifa_free(&ia6->ia_ifa);
|
||||
goto hbhcheck;
|
||||
} else {
|
||||
char ip6bufs[INET6_ADDRSTRLEN];
|
||||
char ip6bufd[INET6_ADDRSTRLEN];
|
||||
/* address is not ready, so discard the packet. */
|
||||
nd6log((LOG_INFO,
|
||||
"ip6_input: packet to an unready address %s->%s\n",
|
||||
ip6_sprintf(ip6bufs, &ip6->ip6_src),
|
||||
ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
|
||||
|
||||
if (free_ia6)
|
||||
ifa_free(&ia6->ia_ifa);
|
||||
ifa_free(&ia->ia_ifa);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FAITH (Firewall Aided Internet Translator)
|
||||
*/
|
||||
if (V_ip6_keepfaith) {
|
||||
if (rin6.ro_rt && rin6.ro_rt->rt_ifp &&
|
||||
rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) {
|
||||
/* XXX do we need more sanity checks? */
|
||||
ours = 1;
|
||||
deliverifp = rin6.ro_rt->rt_ifp; /* faith */
|
||||
goto hbhcheck;
|
||||
}
|
||||
/* Count the packet in the ip address stats */
|
||||
counter_u64_add(ia->ia_ifa.ifa_ipackets, 1);
|
||||
counter_u64_add(ia->ia_ifa.ifa_ibytes, m->m_pkthdr.len);
|
||||
ifa_free(&ia->ia_ifa);
|
||||
ours = 1;
|
||||
goto hbhcheck;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -866,32 +689,6 @@ ip6_input(struct mbuf *m)
|
||||
}
|
||||
|
||||
hbhcheck:
|
||||
/*
|
||||
* record address information into m_tag, if we don't have one yet.
|
||||
* note that we are unable to record it, if the address is not listed
|
||||
* as our interface address (e.g. multicast addresses, addresses
|
||||
* within FAITH prefixes and such).
|
||||
*/
|
||||
if (deliverifp) {
|
||||
struct in6_ifaddr *ia6;
|
||||
|
||||
if ((ia6 = ip6_getdstifaddr(m)) != NULL) {
|
||||
ifa_free(&ia6->ia_ifa);
|
||||
} else {
|
||||
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
|
||||
if (ia6) {
|
||||
if (!ip6_setdstifaddr(m, ia6)) {
|
||||
/*
|
||||
* XXX maybe we should drop the packet here,
|
||||
* as we could not provide enough information
|
||||
* to the upper layers.
|
||||
*/
|
||||
}
|
||||
ifa_free(&ia6->ia_ifa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process Hop-by-Hop options header if it's contained.
|
||||
* m may be modified in ip6_hopopts_input().
|
||||
@ -899,11 +696,8 @@ ip6_input(struct mbuf *m)
|
||||
*/
|
||||
plen = (u_int32_t)ntohs(ip6->ip6_plen);
|
||||
if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
|
||||
int error;
|
||||
|
||||
error = ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
if (ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours) != 0)
|
||||
return;
|
||||
} else
|
||||
nxt = ip6->ip6_nxt;
|
||||
|
||||
@ -950,7 +744,7 @@ ip6_input(struct mbuf *m)
|
||||
}
|
||||
} else if (!ours) {
|
||||
ip6_forward(m, srcrt);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
@ -975,7 +769,7 @@ ip6_input(struct mbuf *m)
|
||||
* Tell launch routine the next header
|
||||
*/
|
||||
IP6STAT_INC(ip6s_delivered);
|
||||
in6_ifstat_inc(deliverifp, ifs6_in_deliver);
|
||||
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_deliver);
|
||||
nest = 0;
|
||||
|
||||
while (nxt != IPPROTO_DONE) {
|
||||
@ -1013,47 +807,9 @@ ip6_input(struct mbuf *m)
|
||||
|
||||
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
|
||||
}
|
||||
goto out;
|
||||
return;
|
||||
bad:
|
||||
m_freem(m);
|
||||
out:
|
||||
if (rin6.ro_rt)
|
||||
RTFREE(rin6.ro_rt);
|
||||
}
|
||||
|
||||
/*
|
||||
* set/grab in6_ifaddr correspond to IPv6 destination address.
|
||||
* XXX backward compatibility wrapper
|
||||
*
|
||||
* XXXRW: We should bump the refcount on ia6 before sticking it in the m_tag,
|
||||
* and then bump it when the tag is copied, and release it when the tag is
|
||||
* freed. Unfortunately, m_tags don't support deep copies (yet), so instead
|
||||
* we just bump the ia refcount when we receive it. This should be fixed.
|
||||
*/
|
||||
static struct ip6aux *
|
||||
ip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
|
||||
{
|
||||
struct ip6aux *ip6a;
|
||||
|
||||
ip6a = ip6_addaux(m);
|
||||
if (ip6a)
|
||||
ip6a->ip6a_dstia6 = ia6;
|
||||
return ip6a; /* NULL if failed to set */
|
||||
}
|
||||
|
||||
struct in6_ifaddr *
|
||||
ip6_getdstifaddr(struct mbuf *m)
|
||||
{
|
||||
struct ip6aux *ip6a;
|
||||
struct in6_ifaddr *ia;
|
||||
|
||||
ip6a = ip6_findaux(m);
|
||||
if (ip6a) {
|
||||
ia = ip6a->ip6a_dstia6;
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
return ia;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1816,42 +1572,6 @@ ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ip6aux *
|
||||
ip6_addaux(struct mbuf *m)
|
||||
{
|
||||
struct m_tag *mtag;
|
||||
|
||||
mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
|
||||
if (!mtag) {
|
||||
mtag = m_tag_get(PACKET_TAG_IPV6_INPUT, sizeof(struct ip6aux),
|
||||
M_NOWAIT);
|
||||
if (mtag) {
|
||||
m_tag_prepend(m, mtag);
|
||||
bzero(mtag + 1, sizeof(struct ip6aux));
|
||||
}
|
||||
}
|
||||
return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
|
||||
}
|
||||
|
||||
static struct ip6aux *
|
||||
ip6_findaux(struct mbuf *m)
|
||||
{
|
||||
struct m_tag *mtag;
|
||||
|
||||
mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
|
||||
return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_delaux(struct mbuf *m)
|
||||
{
|
||||
struct m_tag *mtag;
|
||||
|
||||
mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
|
||||
if (mtag)
|
||||
m_tag_delete(m, mtag);
|
||||
}
|
||||
|
||||
/*
|
||||
* System control for IP6
|
||||
*/
|
||||
|
@ -256,37 +256,6 @@ VNET_PCPUSTAT_DECLARE(struct ip6stat, ip6stat);
|
||||
#define IP6STAT_DEC(name) IP6STAT_SUB(name, 1)
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* IPv6 onion peeling state.
|
||||
* it will be initialized when we come into ip6_input().
|
||||
* XXX do not make it a kitchen sink!
|
||||
*/
|
||||
struct ip6aux {
|
||||
u_int32_t ip6a_flags;
|
||||
#define IP6A_SWAP 0x01 /* swapped home/care-of on packet */
|
||||
#define IP6A_HASEEN 0x02 /* HA was present */
|
||||
#define IP6A_BRUID 0x04 /* BR Unique Identifier was present */
|
||||
#define IP6A_RTALERTSEEN 0x08 /* rtalert present */
|
||||
|
||||
/* ip6.ip6_src */
|
||||
struct in6_addr ip6a_careof; /* care-of address of the peer */
|
||||
struct in6_addr ip6a_home; /* home address of the peer */
|
||||
u_int16_t ip6a_bruid; /* BR unique identifier */
|
||||
|
||||
/* ip6.ip6_dst */
|
||||
struct in6_ifaddr *ip6a_dstia6; /* my ifaddr that matches ip6_dst */
|
||||
|
||||
/* rtalert */
|
||||
u_int16_t ip6a_rtalert; /* rtalert option value */
|
||||
|
||||
/*
|
||||
* decapsulation history will be here.
|
||||
* with IPsec it may not be accurate.
|
||||
*/
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* flags passed to ip6_output as last parameter */
|
||||
#define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */
|
||||
@ -386,7 +355,6 @@ int ip6proto_register(short);
|
||||
int ip6proto_unregister(short);
|
||||
|
||||
void ip6_input(struct mbuf *);
|
||||
struct in6_ifaddr *ip6_getdstifaddr(struct mbuf *);
|
||||
void ip6_freepcbopts(struct ip6_pktopts *);
|
||||
|
||||
int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
|
||||
@ -394,10 +362,6 @@ char * ip6_get_prevhdr(struct mbuf *, int);
|
||||
int ip6_nexthdr(struct mbuf *, int, int, int *);
|
||||
int ip6_lasthdr(struct mbuf *, int, int, int *);
|
||||
|
||||
#ifdef __notyet__
|
||||
struct ip6aux *ip6_findaux(struct mbuf *);
|
||||
#endif
|
||||
|
||||
extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
|
||||
struct mbuf *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user