* Adds or delete interface "prefix" route corresponding to @ifa. * Returns 0 on success or errno. */
| 851 | * Returns 0 on success or errno. |
| 852 | */ |
| 853 | int |
| 854 | in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia) |
| 855 | { |
| 856 | struct ifaddr *ifa = &ia->ia_ifa; |
| 857 | struct in_addr daddr, maddr; |
| 858 | struct sockaddr_in *pmask; |
| 859 | struct epoch_tracker et; |
| 860 | int error; |
| 861 | |
| 862 | ia_getrtprefix(ia, &daddr, &maddr); |
| 863 | |
| 864 | struct sockaddr_in mask = { |
| 865 | .sin_family = AF_INET, |
| 866 | .sin_len = sizeof(struct sockaddr_in), |
| 867 | .sin_addr = maddr, |
| 868 | }; |
| 869 | |
| 870 | pmask = (maddr.s_addr != INADDR_BROADCAST) ? &mask : NULL; |
| 871 | |
| 872 | struct sockaddr_in dst = { |
| 873 | .sin_family = AF_INET, |
| 874 | .sin_len = sizeof(struct sockaddr_in), |
| 875 | .sin_addr.s_addr = daddr.s_addr & maddr.s_addr, |
| 876 | }; |
| 877 | |
| 878 | struct ifnet *ifp = ia->ia_ifp; |
| 879 | |
| 880 | if ((maddr.s_addr == INADDR_BROADCAST) && |
| 881 | (!(ia->ia_ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)))) { |
| 882 | /* Case 2: host route on broadcast interface */ |
| 883 | ifp = V_loif; |
| 884 | } |
| 885 | |
| 886 | uint32_t fibnum = ifa->ifa_ifp->if_fib; |
| 887 | NET_EPOCH_ENTER(et); |
| 888 | error = in_handle_prefix_route(fibnum, cmd, &dst, pmask, ifa, ifp); |
| 889 | NET_EPOCH_EXIT(et); |
| 890 | |
| 891 | return (error); |
| 892 | } |
| 893 | |
| 894 | /* |
| 895 | * Check if we have a route for the given prefix already. |
no test coverage detected