| 175 | } while(0) |
| 176 | |
| 177 | static int |
| 178 | in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock, |
| 179 | struct ip6_pktopts *opts, struct inpcb *inp, struct ucred *cred, |
| 180 | struct ifnet **ifpp, struct in6_addr *srcp) |
| 181 | { |
| 182 | struct rm_priotracker in6_ifa_tracker; |
| 183 | struct in6_addr dst, tmp; |
| 184 | struct ifnet *ifp = NULL, *oifp = NULL; |
| 185 | struct in6_ifaddr *ia = NULL, *ia_best = NULL; |
| 186 | struct in6_pktinfo *pi = NULL; |
| 187 | int dst_scope = -1, best_scope = -1, best_matchlen = -1; |
| 188 | struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL; |
| 189 | u_int32_t odstzone; |
| 190 | int prefer_tempaddr; |
| 191 | int error; |
| 192 | struct ip6_moptions *mopts; |
| 193 | |
| 194 | KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__)); |
| 195 | |
| 196 | dst = dstsock->sin6_addr; /* make a copy for local operation */ |
| 197 | if (ifpp) { |
| 198 | /* |
| 199 | * Save a possibly passed in ifp for in6_selectsrc. Only |
| 200 | * neighbor discovery code should use this feature, where |
| 201 | * we may know the interface but not the FIB number holding |
| 202 | * the connected subnet in case someone deleted it from the |
| 203 | * default FIB and we need to check the interface. |
| 204 | */ |
| 205 | if (*ifpp != NULL) |
| 206 | oifp = *ifpp; |
| 207 | *ifpp = NULL; |
| 208 | } |
| 209 | |
| 210 | if (inp != NULL) { |
| 211 | INP_LOCK_ASSERT(inp); |
| 212 | mopts = inp->in6p_moptions; |
| 213 | } else { |
| 214 | mopts = NULL; |
| 215 | } |
| 216 | |
| 217 | /* |
| 218 | * If the source address is explicitly specified by the caller, |
| 219 | * check if the requested source address is indeed a unicast address |
| 220 | * assigned to the node, and can be used as the packet's source |
| 221 | * address. If everything is okay, use the address as source. |
| 222 | */ |
| 223 | if (opts && (pi = opts->ip6po_pktinfo) && |
| 224 | !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) { |
| 225 | /* get the outgoing interface */ |
| 226 | if ((error = in6_selectif(dstsock, opts, mopts, &ifp, oifp, |
| 227 | fibnum)) |
| 228 | != 0) |
| 229 | return (error); |
| 230 | |
| 231 | /* |
| 232 | * determine the appropriate zone id of the source based on |
| 233 | * the zone of the destination and the outgoing interface. |
| 234 | * If the specified address is ambiguous wrt the scope zone, |
no test coverage detected