| 265 | } |
| 266 | |
| 267 | struct ifaddr * |
| 268 | ifa_ifwithroute(int flags, const struct sockaddr *dst, |
| 269 | const struct sockaddr *gateway, u_int fibnum) |
| 270 | { |
| 271 | struct ifaddr *ifa; |
| 272 | |
| 273 | NET_EPOCH_ASSERT(); |
| 274 | if ((flags & RTF_GATEWAY) == 0) { |
| 275 | /* |
| 276 | * If we are adding a route to an interface, |
| 277 | * and the interface is a pt to pt link |
| 278 | * we should search for the destination |
| 279 | * as our clue to the interface. Otherwise |
| 280 | * we can use the local address. |
| 281 | */ |
| 282 | ifa = NULL; |
| 283 | if (flags & RTF_HOST) |
| 284 | ifa = ifa_ifwithdstaddr(dst, fibnum); |
| 285 | if (ifa == NULL) |
| 286 | ifa = ifa_ifwithaddr(gateway); |
| 287 | } else { |
| 288 | /* |
| 289 | * If we are adding a route to a remote net |
| 290 | * or host, the gateway may still be on the |
| 291 | * other end of a pt to pt link. |
| 292 | */ |
| 293 | ifa = ifa_ifwithdstaddr(gateway, fibnum); |
| 294 | } |
| 295 | if (ifa == NULL) |
| 296 | ifa = ifa_ifwithnet(gateway, 0, fibnum); |
| 297 | if (ifa == NULL) { |
| 298 | struct nhop_object *nh; |
| 299 | |
| 300 | nh = rib_lookup(fibnum, gateway, NHR_NONE, 0); |
| 301 | |
| 302 | /* |
| 303 | * dismiss a gateway that is reachable only |
| 304 | * through the default router |
| 305 | */ |
| 306 | if ((nh == NULL) || (nh->nh_flags & NHF_DEFAULT)) |
| 307 | return (NULL); |
| 308 | ifa = nh->nh_ifa; |
| 309 | } |
| 310 | if (ifa->ifa_addr->sa_family != dst->sa_family) { |
| 311 | struct ifaddr *oifa = ifa; |
| 312 | ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); |
| 313 | if (ifa == NULL) |
| 314 | ifa = oifa; |
| 315 | } |
| 316 | |
| 317 | return (ifa); |
| 318 | } |
| 319 | |
| 320 | /* |
| 321 | * Copy most of @rt data into @info. |
no test coverage detected