Date: Mon, 2 Dec 2013 06:17:30 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r258837 - user/ae/inet6/sys/netinet6 Message-ID: <201312020617.rB26HUfl067251@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201312020617.rB26HUfl067251>