svn commit: r258837 - user/ae/inet6/sys/netinet6
Andrey V. Elsukov
ae at FreeBSD.org
Mon Dec 2 06:17:30 UTC 2013
Author: ae
Date: Mon Dec 2 06:17:29 2013
New Revision: 258837
URL: http://svnweb.freebsd.org/changeset/base/258837
Log:
Rethink usage of IPV6_USEROIF flag.
We can't just use outgoing interface when destination address is
not link-reachable, because we must use gateway's layer2 address
when constructing packet. Add route information where it can be cached
and then pass it to ip6_output. Also count some errors as bad scope.
Modified:
user/ae/inet6/sys/netinet6/ip6_output.c
user/ae/inet6/sys/netinet6/raw_ip6.c
user/ae/inet6/sys/netinet6/udp6_usrreq.c
Modified: user/ae/inet6/sys/netinet6/ip6_output.c
==============================================================================
--- user/ae/inet6/sys/netinet6/ip6_output.c Mon Dec 2 06:14:05 2013 (r258836)
+++ user/ae/inet6/sys/netinet6/ip6_output.c Mon Dec 2 06:17:29 2013 (r258837)
@@ -684,16 +684,20 @@ again:
ifp = ro->ro_rt->rt_ifp;
} else {
/*
- * We can just use specified by user outgoing interface when
- * IPV6_USEROIF flag is set. But we should determine new
- * outgoing interface if PFIL has changed destination address,
- * or some packet options is set.
+ * The caller can use IPV6_USEROIF flag to suggest outgoing
+ * interface. But destination address should be reachable via
+ * specified interface. This means, that destination address
+ * is multicast, or destination/source address is LLA, or
+ * outgoing interface is PTP tunnel. In other cases we need
+ * to do route lookup to determine gateway and use its layer2
+ * address.
+ * XXX: fwd/nexthop/pktinfo/rthdr ?
*/
- if ((flags & IPV6_USEROIF) != 0 &&
- (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
- (fwd_tag == NULL && (opt == NULL ||
- (opt->ip6po_nexthop == NULL &&
- opt->ip6po_rthdr == NULL)))))
+ if ((flags & IPV6_USEROIF) != 0 && (
+ ((*ifpp)->if_flags & IFF_POINTOPOINT) != 0 ||
+ IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
+ IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src) ||
+ IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)))
ifp = *ifpp;
else {
/*
@@ -717,7 +721,7 @@ again:
IN6_IS_ADDR_MC_INTFACELOCAL(
&ip6->ip6_dst)) {
error = EHOSTUNREACH;
- IP6STAT_INC(ip6s_noroute);
+ IP6STAT_INC(ip6s_badscope);
goto bad;
}
} else if (IN6_IS_ADDR_LINKLOCAL(&dst->sin6_addr) ||
@@ -729,7 +733,7 @@ again:
if (dst->sin6_scope_id == 0 || !(ifp =
in6_getlinkifnet(dst->sin6_scope_id))) {
error = EHOSTUNREACH;
- IP6STAT_INC(ip6s_noroute);
+ IP6STAT_INC(ip6s_badscope);
goto bad;
}
goto oif_found;
Modified: user/ae/inet6/sys/netinet6/raw_ip6.c
==============================================================================
--- user/ae/inet6/sys/netinet6/raw_ip6.c Mon Dec 2 06:14:05 2013 (r258836)
+++ user/ae/inet6/sys/netinet6/raw_ip6.c Mon Dec 2 06:17:29 2013 (r258837)
@@ -392,6 +392,7 @@ rip6_ctlinput(int cmd, struct sockaddr *
int
rip6_output(struct mbuf *m, ...)
{
+ struct route_in6 ro;
struct mbuf *control;
struct m_tag *mtag;
struct socket *so;
@@ -413,6 +414,7 @@ rip6_output(struct mbuf *m, ...)
control = va_arg(ap, struct mbuf *);
va_end(ap);
+ bzero(&ro, sizeof(ro));
in6p = sotoinpcb(so);
INP_WLOCK(in6p);
@@ -453,7 +455,7 @@ rip6_output(struct mbuf *m, ...)
/*
* Source address selection.
*/
- error = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
+ error = in6_selectsrc(dstsock, optp, in6p, &ro, so->so_cred,
&oifp, &in6a);
if (error)
goto bad;
@@ -523,7 +525,7 @@ rip6_output(struct mbuf *m, ...)
}
}
- error = ip6_output(m, optp, NULL, IPV6_USEROIF, in6p->in6p_moptions,
+ error = ip6_output(m, optp, &ro, IPV6_USEROIF, in6p->in6p_moptions,
&oifp, in6p);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
icmp6_ifoutstat_inc(oifp, type, code);
@@ -543,6 +545,7 @@ rip6_output(struct mbuf *m, ...)
m_freem(control);
}
INP_WUNLOCK(in6p);
+ RO_RTFREE(&ro);
return (error);
}
Modified: user/ae/inet6/sys/netinet6/udp6_usrreq.c
==============================================================================
--- user/ae/inet6/sys/netinet6/udp6_usrreq.c Mon Dec 2 06:14:05 2013 (r258836)
+++ user/ae/inet6/sys/netinet6/udp6_usrreq.c Mon Dec 2 06:17:29 2013 (r258837)
@@ -615,6 +615,7 @@ static int
udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
struct mbuf *control, struct thread *td)
{
+ struct route_in6 ro;
u_int32_t ulen = m->m_pkthdr.len;
u_int32_t plen = sizeof(struct udphdr) + ulen;
struct ip6_hdr *ip6;
@@ -631,6 +632,7 @@ udp6_output(struct inpcb *inp, struct mb
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
+ bzero(&ro, sizeof(ro));
/* addr6 has been validated in udp6_send(). */
sin6 = (struct sockaddr_in6 *)addr6;
if (control) {
@@ -694,7 +696,7 @@ udp6_output(struct inpcb *inp, struct mb
}
if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
- error = in6_selectsrc(sin6, optp, inp, NULL,
+ error = in6_selectsrc(sin6, optp, inp, &ro,
td->td_ucred, &oifp, &in6a);
if (error)
goto release;
@@ -785,7 +787,7 @@ udp6_output(struct inpcb *inp, struct mb
UDP_PROBE(send, NULL, inp, ip6, inp, udp6);
UDPSTAT_INC(udps_opackets);
- error = ip6_output(m, optp, NULL, flags, inp->in6p_moptions,
+ error = ip6_output(m, optp, &ro, flags, inp->in6p_moptions,
&oifp, inp);
break;
case AF_INET:
@@ -802,6 +804,7 @@ releaseopt:
ip6_clearpktopts(&opt, -1);
m_freem(control);
}
+ RO_RTFREE(&ro);
return (error);
}
More information about the svn-src-user
mailing list