In order to keep if_get()/if_put() dances in the same function, I need
to change in6_selectroute() to no longer return an ``ifp''.
This is a first step towards this goal. It moves the multicast code out
of in6_selectroute(). I could simplify things further but I'd prefer to
do that in small diffs.
ok?
Index: netinet6/in6_src.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_src.c,v
retrieving revision 1.58
diff -u -p -r1.58 in6_src.c
--- netinet6/in6_src.c 11 Sep 2015 09:58:33 -0000 1.58
+++ netinet6/in6_src.c 11 Sep 2015 10:33:18 -0000
@@ -295,43 +295,17 @@ in6_selectsrc(struct in6_addr **in6src,
int
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
- struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
- struct rtentry **retrt, int norouteok, u_int rtableid)
+ struct route_in6 *ro, struct ifnet **retifp,
+ struct rtentry **retrt, unsigned int rtableid)
{
int error = 0;
struct ifnet *ifp = NULL;
struct rtentry *rt = NULL;
struct sockaddr_in6 *sin6_next;
- struct in6_pktinfo *pi = NULL;
struct in6_addr *dst;
dst = &dstsock->sin6_addr;
- /* If the caller specify the outgoing interface explicitly, use it. */
- if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
- ifp = if_get(pi->ipi6_ifindex);
- if (ifp != NULL &&
- (norouteok || retrt == NULL ||
- IN6_IS_ADDR_MULTICAST(dst))) {
- /*
- * we do not have to check or get the route for
- * multicast.
- */
- goto done;
- } else
- goto getroute;
- }
-
- /*
- * If the destination address is a multicast address and the outgoing
- * interface for the address is specified by the caller, use it.
- */
- if (IN6_IS_ADDR_MULTICAST(dst) &&
- mopts != NULL && (ifp = if_get(mopts->im6o_ifidx)) != NULL) {
- goto done; /* we do not need a route for multicast. */
- }
-
- getroute:
/*
* If the next hop address for the packet is specified by the caller,
* use it as the gateway.
@@ -467,8 +441,6 @@ in6_selectroute(struct sockaddr_in6 *dst
*/
error = EHOSTUNREACH;
}
- if (error == EHOSTUNREACH)
- ip6stat.ip6s_noroute++;
if (retifp != NULL)
*retifp = ifp;
@@ -484,10 +456,26 @@ in6_selectif(struct sockaddr_in6 *dstsoc
u_int rtableid)
{
struct rtentry *rt = NULL;
+ struct in6_pktinfo *pi = NULL;
int error;
- if ((error = in6_selectroute(dstsock, opts, mopts, ro, retifp,
- &rt, 1, rtableid)) != 0)
+ /* If the caller specify the outgoing interface explicitly, use it. */
+ if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
+ *retifp = if_get(pi->ipi6_ifindex);
+ if (*retifp != NULL)
+ return (0);
+ }
+
+ /*
+ * If the destination address is a multicast address and the outgoing
+ * interface for the address is specified by the caller, use it.
+ */
+ if (IN6_IS_ADDR_MULTICAST(&dstsock->sin6_addr) &&
+ mopts != NULL && (*retifp = if_get(mopts->im6o_ifidx)) != NULL)
+ return (0);
+
+ if ((error = in6_selectroute(dstsock, opts, ro, retifp,
+ &rt, rtableid)) != 0)
return (error);
/*
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.182
diff -u -p -r1.182 ip6_output.c
--- netinet6/ip6_output.c 11 Sep 2015 09:58:33 -0000 1.182
+++ netinet6/ip6_output.c 11 Sep 2015 12:09:42 -0000
@@ -155,7 +155,7 @@ ip6_output(struct mbuf *m0, struct ip6_p
int flags, struct ip6_moptions *im6o, struct inpcb *inp)
{
struct ip6_hdr *ip6;
- struct ifnet *ifp;
+ struct ifnet *ifp = NULL;
struct mbuf *m = m0;
int hlen, tlen;
struct route_in6 ip6route;
@@ -528,17 +528,27 @@ reroute:
dstsock.sin6_addr = ip6->ip6_dst;
dstsock.sin6_len = sizeof(dstsock);
ro->ro_tableid = m->m_pkthdr.ph_rtableid;
- if ((error = in6_selectroute(&dstsock, opt, im6o, ro, &ifp,
- &rt, 0, m->m_pkthdr.ph_rtableid)) != 0) {
- switch (error) {
- case EHOSTUNREACH:
+
+ if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) {
+ struct in6_pktinfo *pi = NULL;
+
+ /*
+ * If the caller specify the outgoing interface
+ * explicitly, use it.
+ */
+ if (opt != NULL && (pi = opt->ip6po_pktinfo) != NULL)
+ ifp = if_get(pi->ipi6_ifindex);
+
+ if (ifp == NULL && im6o != NULL)
+ ifp = if_get(im6o->im6o_ifidx);
+ }
+
+ if (ifp == NULL) {
+ if ((error = in6_selectroute(&dstsock, opt, ro, &ifp,
+ &rt, m->m_pkthdr.ph_rtableid)) != 0) {
ip6stat.ip6s_noroute++;
- break;
- case EADDRNOTAVAIL:
- default:
- break; /* XXX statistics? */
+ goto bad;
}
- goto bad;
}
if (rt == NULL) {
/*
Index: netinet6/ip6_var.h
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.53
diff -u -p -r1.53 ip6_var.h
--- netinet6/ip6_var.h 11 Sep 2015 09:58:33 -0000 1.53
+++ netinet6/ip6_var.h 11 Sep 2015 10:29:26 -0000
@@ -311,8 +311,8 @@ int in6_selectsrc(struct in6_addr **, st
struct ip6_pktopts *, struct ip6_moptions *, struct route_in6 *,
struct in6_addr *, u_int);
int in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
- struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int, u_int rtableid);
+ struct route_in6 *, struct ifnet **,
+ struct rtentry **, unsigned int rtableid);
u_int32_t ip6_randomflowlabel(void);
#endif /* _KERNEL */