#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/queue.h>
+#include <string.h>
#include <net/if.h>
+#include <net/route.h>
#include <netinet/in.h>
#include <netinet6/in6_var.h>
#include <netinet/icmp6.h>
-static int ip6_rthdr0 __P((struct mbuf *, struct ip6_hdr *,
- struct ip6_rthdr0 *));
+#if IP6_RTHDR0_ALLOWED
+static int ip6_rthdr0(struct mbuf *, struct ip6_hdr *,
+ struct ip6_rthdr0 *);
+#endif /* IP6_RTHDR0_ALLOWED */
int
-route6_input(mp, offp)
- struct mbuf **mp;
- int *offp;
+route6_input(struct mbuf **mp, int *offp)
{
struct ip6_hdr *ip6;
struct mbuf *m = *mp;
struct ip6_rthdr *rh;
int off = *offp, rhlen;
- struct mbuf *n;
+ struct ip6aux *ip6a;
- n = ip6_findaux(m);
- if (n) {
- struct ip6aux *ip6a = mtod(n, struct ip6aux *);
+ ip6a = ip6_findaux(m);
+ if (ip6a) {
/* XXX reject home-address option before rthdr */
if (ip6a->ip6a_flags & IP6A_SWAP) {
ip6stat.ip6s_badoptions++;
}
#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, off, sizeof(*rh), IPPROTO_DONE);
+ IP6_EXTHDR_CHECK(m, off, sizeof(*rh), return IPPROTO_DONE);
ip6 = mtod(m, struct ip6_hdr *);
rh = (struct ip6_rthdr *)((caddr_t)ip6 + off);
#else
#endif
switch (rh->ip6r_type) {
+#if IP6_RTHDR0_ALLOWED
case IPV6_RTHDR_TYPE_0:
rhlen = (rh->ip6r_len + 1) << 3;
#ifndef PULLDOWN_TEST
* due to IP6_EXTHDR_CHECK assumption, we cannot handle
* very big routing header (max rhlen == 2048).
*/
- IP6_EXTHDR_CHECK(m, off, rhlen, IPPROTO_DONE);
+ IP6_EXTHDR_CHECK(m, off, rhlen, return IPPROTO_DONE);
#else
/*
* note on option length:
if (ip6_rthdr0(m, ip6, (struct ip6_rthdr0 *)rh))
return(IPPROTO_DONE);
break;
+#endif /* IP6_RTHDR0_ALLOWED */
default:
/* unknown routing type */
if (rh->ip6r_segleft == 0) {
return(rh->ip6r_nxt);
}
+#if IP6_RTHDR0_ALLOWED
/*
* Type0 routing header processing
*
{
int addrs, index;
struct in6_addr *nextaddr, tmpaddr;
+ struct route_in6 ip6forward_rt;
if (rh0->ip6r0_segleft == 0)
return(0);
if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
ip6->ip6_dst.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
+ /*
+ * Don't use the globally cached route to forward packet having
+ * Type 0 routing header(s); instead, do an explicit lookup using
+ * a local route entry variable, in case the next address in the
+ * packet is bogus (which would otherwise unnecessarily invalidate
+ * the globally cached route).
+ */
+ bzero(&ip6forward_rt, sizeof (ip6forward_rt));
+
#if COMPAT_RFC1883
if (rh0->ip6r0_slmap[index / 8] & (1 << (7 - (index % 8))))
- ip6_forward(m, IPV6_SRCRT_NEIGHBOR);
+ ip6_forward(m, &ip6forward_rt, IPV6_SRCRT_NEIGHBOR, 0);
else
- ip6_forward(m, IPV6_SRCRT_NOTNEIGHBOR);
+ ip6_forward(m, &ip6forward_rt, IPV6_SRCRT_NOTNEIGHBOR, 0);
#else
- ip6_forward(m, 1);
+ ip6_forward(m, &ip6forward_rt, 1, 0);
#endif
+ /* Release reference to the looked up route */
+ if (ip6forward_rt.ro_rt != NULL) {
+ rtfree(ip6forward_rt.ro_rt);
+ ip6forward_rt.ro_rt = NULL;
+ }
+
return(-1); /* m would be freed in ip6_forward() */
}
+#endif /* IP6_RTHDR0_ALLOWED */
+