Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/rtsock.c
Show First 20 Lines • Show All 451 Lines • ▼ Show 20 Lines | union sockaddr_union { | ||||
struct sockaddr sa; | struct sockaddr sa; | ||||
struct sockaddr_in sin; | struct sockaddr_in sin; | ||||
struct sockaddr_in6 sin6; | struct sockaddr_in6 sin6; | ||||
}; | }; | ||||
#endif /* _SOCKADDR_UNION_DEFINED */ | #endif /* _SOCKADDR_UNION_DEFINED */ | ||||
static int | static int | ||||
rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, | rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, | ||||
struct rtentry *rt, union sockaddr_union *saun, struct ucred *cred) | struct nhop_object *nh, union sockaddr_union *saun, struct ucred *cred) | ||||
{ | { | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
#endif | #endif | ||||
/* First, see if the returned address is part of the jail. */ | /* First, see if the returned address is part of the jail. */ | ||||
if (prison_if(cred, rt->rt_ifa->ifa_addr) == 0) { | if (prison_if(cred, nh->nh_ifa->ifa_addr) == 0) { | ||||
info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; | info->rti_info[RTAX_IFA] = nh->nh_ifa->ifa_addr; | ||||
return (0); | return (0); | ||||
} | } | ||||
switch (info->rti_info[RTAX_DST]->sa_family) { | switch (info->rti_info[RTAX_DST]->sa_family) { | ||||
#ifdef INET | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
{ | { | ||||
struct in_addr ia; | struct in_addr ia; | ||||
Show All 17 Lines | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
if (!found) { | if (!found) { | ||||
/* | /* | ||||
* As a last resort return the 'default' jail address. | * As a last resort return the 'default' jail address. | ||||
*/ | */ | ||||
ia = ((struct sockaddr_in *)rt->rt_ifa->ifa_addr)-> | ia = ((struct sockaddr_in *)nh->nh_ifa->ifa_addr)-> | ||||
sin_addr; | sin_addr; | ||||
if (prison_get_ip4(cred, &ia) != 0) | if (prison_get_ip4(cred, &ia) != 0) | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
bzero(&saun->sin, sizeof(struct sockaddr_in)); | bzero(&saun->sin, sizeof(struct sockaddr_in)); | ||||
saun->sin.sin_len = sizeof(struct sockaddr_in); | saun->sin.sin_len = sizeof(struct sockaddr_in); | ||||
saun->sin.sin_family = AF_INET; | saun->sin.sin_family = AF_INET; | ||||
saun->sin.sin_addr.s_addr = ia.s_addr; | saun->sin.sin_addr.s_addr = ia.s_addr; | ||||
Show All 26 Lines | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
if (!found) { | if (!found) { | ||||
/* | /* | ||||
* As a last resort return the 'default' jail address. | * As a last resort return the 'default' jail address. | ||||
*/ | */ | ||||
ia6 = ((struct sockaddr_in6 *)rt->rt_ifa->ifa_addr)-> | ia6 = ((struct sockaddr_in6 *)nh->nh_ifa->ifa_addr)-> | ||||
sin6_addr; | sin6_addr; | ||||
if (prison_get_ip6(cred, &ia6) != 0) | if (prison_get_ip6(cred, &ia6) != 0) | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
bzero(&saun->sin6, sizeof(struct sockaddr_in6)); | bzero(&saun->sin6, sizeof(struct sockaddr_in6)); | ||||
saun->sin6.sin6_len = sizeof(struct sockaddr_in6); | saun->sin6.sin6_len = sizeof(struct sockaddr_in6); | ||||
saun->sin6.sin6_family = AF_INET6; | saun->sin6.sin6_family = AF_INET6; | ||||
bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr)); | bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr)); | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | if (info->rti_info[RTAX_GATEWAY] != NULL && | ||||
/* | /* | ||||
* A host route through the loopback interface is | * A host route through the loopback interface is | ||||
* installed for each interface adddress. In pre 8.0 | * installed for each interface adddress. In pre 8.0 | ||||
* releases the interface address of a PPP link type | * releases the interface address of a PPP link type | ||||
* is not reachable locally. This behavior is fixed as | * is not reachable locally. This behavior is fixed as | ||||
* part of the new L2/L3 redesign and rewrite work. The | * part of the new L2/L3 redesign and rewrite work. The | ||||
* signature of this interface address route is the | * signature of this interface address route is the | ||||
* AF_LINK sa_family type of the rt_gateway, and the | * AF_LINK sa_family type of the gateway, and the | ||||
* rt_ifp has the IFF_LOOPBACK flag set. | * rt_ifp has the IFF_LOOPBACK flag set. | ||||
*/ | */ | ||||
if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) { | if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) { | ||||
if (ss.ss_family == AF_LINK && | if (ss.ss_family == AF_LINK && | ||||
ginfo.rti_ifp->if_flags & IFF_LOOPBACK) { | ginfo.rti_ifp->if_flags & IFF_LOOPBACK) { | ||||
info->rti_flags &= ~RTF_GATEWAY; | info->rti_flags &= ~RTF_GATEWAY; | ||||
info->rti_flags |= RTF_GWFLAG_COMPAT; | info->rti_flags |= RTF_GWFLAG_COMPAT; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | if (rt_mpath_capable(rnh) && info->rti_info[RTAX_GATEWAY]) { | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* If performing proxied L2 entry insertion, and | * If performing proxied L2 entry insertion, and | ||||
* the actual PPP host entry is found, perform | * the actual PPP host entry is found, perform | ||||
* another search to retrieve the prefix route of | * another search to retrieve the prefix route of | ||||
* the local end point of the PPP link. | * the local end point of the PPP link. | ||||
* TODO: move this logic to userland. | |||||
*/ | */ | ||||
if (rtm->rtm_flags & RTF_ANNOUNCE) { | if (rtm->rtm_flags & RTF_ANNOUNCE) { | ||||
struct sockaddr laddr; | struct sockaddr laddr; | ||||
struct nhop_object *nh; | |||||
if (rt->rt_ifp != NULL && | nh = rt->rt_nhop; | ||||
rt->rt_ifp->if_type == IFT_PROPVIRTUAL) { | if (nh->nh_ifp != NULL && | ||||
nh->nh_ifp->if_type == IFT_PROPVIRTUAL) { | |||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
ifa = ifa_ifwithnet(info->rti_info[RTAX_DST], 1, | ifa = ifa_ifwithnet(info->rti_info[RTAX_DST], 1, | ||||
RT_ALL_FIBS); | RT_ALL_FIBS); | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
if (ifa != NULL) | if (ifa != NULL) | ||||
rt_maskedcopy(ifa->ifa_addr, | rt_maskedcopy(ifa->ifa_addr, | ||||
&laddr, | &laddr, | ||||
ifa->ifa_netmask); | ifa->ifa_netmask); | ||||
} else | } else | ||||
rt_maskedcopy(rt->rt_ifa->ifa_addr, | rt_maskedcopy(nh->nh_ifa->ifa_addr, | ||||
&laddr, | &laddr, | ||||
rt->rt_ifa->ifa_netmask); | nh->nh_ifa->ifa_netmask); | ||||
/* | /* | ||||
* refactor rt and no lock operation necessary | * refactor rt and no lock operation necessary | ||||
*/ | */ | ||||
rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, | rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, | ||||
&rnh->head); | &rnh->head); | ||||
if (rt == NULL) { | if (rt == NULL) { | ||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
return (ESRCH); | return (ESRCH); | ||||
} | } | ||||
} | } | ||||
RT_LOCK(rt); | RT_LOCK(rt); | ||||
RT_ADDREF(rt); | RT_ADDREF(rt); | ||||
RIB_RUNLOCK(rnh); | RIB_RUNLOCK(rnh); | ||||
*ret_nrt = rt; | *ret_nrt = rt; | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 10 Lines | |||||
static int | static int | ||||
update_rtm_from_rte(struct rt_addrinfo *info, struct rt_msghdr **prtm, | update_rtm_from_rte(struct rt_addrinfo *info, struct rt_msghdr **prtm, | ||||
int alloc_len, struct rtentry *rt) | int alloc_len, struct rtentry *rt) | ||||
{ | { | ||||
struct sockaddr_storage netmask_ss; | struct sockaddr_storage netmask_ss; | ||||
struct walkarg w; | struct walkarg w; | ||||
union sockaddr_union saun; | union sockaddr_union saun; | ||||
struct rt_msghdr *rtm, *orig_rtm = NULL; | struct rt_msghdr *rtm, *orig_rtm = NULL; | ||||
struct nhop_object *nh; | |||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int error, len; | int error, len; | ||||
RT_LOCK_ASSERT(rt); | RT_LOCK_ASSERT(rt); | ||||
rtm = *prtm; | rtm = *prtm; | ||||
nh = rt->rt_nhop; | |||||
info->rti_info[RTAX_DST] = rt_key(rt); | info->rti_info[RTAX_DST] = rt_key(rt); | ||||
info->rti_info[RTAX_GATEWAY] = rt->rt_gateway; | info->rti_info[RTAX_GATEWAY] = &nh->gw_sa; | ||||
info->rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), | info->rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), | ||||
rt_mask(rt), &netmask_ss); | rt_mask(rt), &netmask_ss); | ||||
info->rti_info[RTAX_GENMASK] = 0; | info->rti_info[RTAX_GENMASK] = 0; | ||||
ifp = rt->rt_ifp; | ifp = nh->nh_ifp; | ||||
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { | if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { | ||||
if (ifp) { | if (ifp) { | ||||
info->rti_info[RTAX_IFP] = | info->rti_info[RTAX_IFP] = | ||||
ifp->if_addr->ifa_addr; | ifp->if_addr->ifa_addr; | ||||
error = rtm_get_jailed(info, ifp, rt, | error = rtm_get_jailed(info, ifp, nh, | ||||
&saun, curthread->td_ucred); | &saun, curthread->td_ucred); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (ifp->if_flags & IFF_POINTOPOINT) | if (ifp->if_flags & IFF_POINTOPOINT) | ||||
info->rti_info[RTAX_BRD] = | info->rti_info[RTAX_BRD] = | ||||
rt->rt_ifa->ifa_dstaddr; | nh->nh_ifa->ifa_dstaddr; | ||||
rtm->rtm_index = ifp->if_index; | rtm->rtm_index = ifp->if_index; | ||||
} else { | } else { | ||||
info->rti_info[RTAX_IFP] = NULL; | info->rti_info[RTAX_IFP] = NULL; | ||||
info->rti_info[RTAX_IFA] = NULL; | info->rti_info[RTAX_IFA] = NULL; | ||||
} | } | ||||
} else if (ifp != NULL) | } else if (ifp != NULL) | ||||
rtm->rtm_index = ifp->if_index; | rtm->rtm_index = ifp->if_index; | ||||
▲ Show 20 Lines • Show All 267 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out) | rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out) | ||||
{ | { | ||||
bzero(out, sizeof(*out)); | bzero(out, sizeof(*out)); | ||||
out->rmx_mtu = rt->rt_mtu; | out->rmx_mtu = rt->rt_nhop->nh_mtu; | ||||
out->rmx_weight = rt->rt_weight; | out->rmx_weight = rt->rt_weight; | ||||
out->rmx_pksent = counter_u64_fetch(rt->rt_pksent); | out->rmx_pksent = counter_u64_fetch(rt->rt_pksent); | ||||
out->rmx_nhidx = nhop_get_idx(rt->rt_nhop); | out->rmx_nhidx = nhop_get_idx(rt->rt_nhop); | ||||
/* Kernel -> userland timebase conversion. */ | /* Kernel -> userland timebase conversion. */ | ||||
out->rmx_expire = rt->rt_expire ? | out->rmx_expire = rt->rt_expire ? | ||||
rt->rt_expire - time_uptime + time_second : 0; | rt->rt_expire - time_uptime + time_second : 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 404 Lines • ▼ Show 20 Lines | rtsock_routemsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int rti_addrs, | ||||
struct rt_addrinfo info; | struct rt_addrinfo info; | ||||
if (V_route_cb.any_count == 0) | if (V_route_cb.any_count == 0) | ||||
return (0); | return (0); | ||||
bzero((caddr_t)&info, sizeof(info)); | bzero((caddr_t)&info, sizeof(info)); | ||||
info.rti_info[RTAX_DST] = rt_key(rt); | info.rti_info[RTAX_DST] = rt_key(rt); | ||||
info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), rt_mask(rt), &ss); | info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), rt_mask(rt), &ss); | ||||
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; | info.rti_info[RTAX_GATEWAY] = &rt->rt_nhop->gw_sa; | ||||
info.rti_flags = rt->rt_flags; | info.rti_flags = rt->rt_flags; | ||||
info.rti_ifp = ifp; | info.rti_ifp = ifp; | ||||
return (rtsock_routemsg_info(cmd, &info, fibnum)); | return (rtsock_routemsg_info(cmd, &info, fibnum)); | ||||
} | } | ||||
int | int | ||||
rtsock_routemsg_info(int cmd, struct rt_addrinfo *info, int fibnum) | rtsock_routemsg_info(int cmd, struct rt_addrinfo *info, int fibnum) | ||||
▲ Show 20 Lines • Show All 212 Lines • ▼ Show 20 Lines | sysctl_dumpentry(struct radix_node *rn, void *vw) | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) | if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) | ||||
return 0; | return 0; | ||||
if (!can_export_rte(w->w_req->td->td_ucred, rt)) | if (!can_export_rte(w->w_req->td->td_ucred, rt)) | ||||
return (0); | return (0); | ||||
bzero((caddr_t)&info, sizeof(info)); | bzero((caddr_t)&info, sizeof(info)); | ||||
info.rti_info[RTAX_DST] = rt_key(rt); | info.rti_info[RTAX_DST] = rt_key(rt); | ||||
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; | info.rti_info[RTAX_GATEWAY] = &rt->rt_nhop->gw_sa; | ||||
info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), | info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), | ||||
rt_mask(rt), &ss); | rt_mask(rt), &ss); | ||||
info.rti_info[RTAX_GENMASK] = 0; | info.rti_info[RTAX_GENMASK] = 0; | ||||
if (rt->rt_ifp && !(rt->rt_ifp->if_flags & IFF_DYING)) { | if (rt->rt_ifp && !(rt->rt_ifp->if_flags & IFF_DYING)) { | ||||
info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr; | info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr; | ||||
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; | info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; | ||||
if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) | if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) | ||||
info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; | info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; | ||||
▲ Show 20 Lines • Show All 502 Lines • ▼ Show 20 Lines | rt_dumpentry_ddb(struct radix_node *rn, void *arg __unused) | ||||
struct sockaddr_storage ss; | struct sockaddr_storage ss; | ||||
struct rtentry *rt; | struct rtentry *rt; | ||||
int flags, idx; | int flags, idx; | ||||
/* If RNTORT is important, put it in a header. */ | /* If RNTORT is important, put it in a header. */ | ||||
rt = (void *)rn; | rt = (void *)rn; | ||||
rt_dumpaddr_ddb("dst", rt_key(rt)); | rt_dumpaddr_ddb("dst", rt_key(rt)); | ||||
rt_dumpaddr_ddb("gateway", rt->rt_gateway); | rt_dumpaddr_ddb("gateway", &rt->rt_nhop->gw_sa); | ||||
rt_dumpaddr_ddb("netmask", rtsock_fix_netmask(rt_key(rt), rt_mask(rt), | rt_dumpaddr_ddb("netmask", rtsock_fix_netmask(rt_key(rt), rt_mask(rt), | ||||
&ss)); | &ss)); | ||||
if (rt->rt_ifp != NULL && (rt->rt_ifp->if_flags & IFF_DYING) == 0) { | if (rt->rt_ifp != NULL && (rt->rt_ifp->if_flags & IFF_DYING) == 0) { | ||||
rt_dumpaddr_ddb("ifp", rt->rt_ifp->if_addr->ifa_addr); | rt_dumpaddr_ddb("ifp", rt->rt_ifp->if_addr->ifa_addr); | ||||
rt_dumpaddr_ddb("ifa", rt->rt_ifa->ifa_addr); | rt_dumpaddr_ddb("ifa", rt->rt_ifa->ifa_addr); | ||||
} | } | ||||
db_printf("flags "); | db_printf("flags "); | ||||
▲ Show 20 Lines • Show All 310 Lines • Show Last 20 Lines |