svn commit: r368769 - head/sys/net
Mateusz Guzik
mjguzik at gmail.com
Tue Dec 22 18:31:15 UTC 2020
this makes NOIP kernels fail to compile:
/usr/src/sys/net/rtsock.c:802:11: error: unused variable 'scopeid'
[-Werror,-Wunused-variable]
uint32_t scopeid = 0;
On 12/18/20, Alexander V. Chernikov <melifaro at freebsd.org> wrote:
> Author: melifaro
> Date: Fri Dec 18 22:00:57 2020
> New Revision: 368769
> URL: https://svnweb.freebsd.org/changeset/base/368769
>
> Log:
> Switch direct rt fields access in rtsock.c to newly-create field
> acessors.
>
> rtsock code was build around the assumption that each rtentry record
> in the system radix tree is a ready-to-use sockaddr. This assumptions
> turned out to be not quite true:
> * masks have their length tweaked, so we have rtsock_fix_netmask() hack
> * IPv6 addresses have their scope embedded, so we have another explicit
> deembedding hack.
>
> Change the code to decouple rtentry internals from rtsock code using
> newly-created rtentry accessors. This will allow to eventually eliminate
> both of the hacks and change rtentry dst/mask format.
>
> Differential Revision: https://reviews.freebsd.org/D27451
>
> Modified:
> head/sys/net/rtsock.c
>
> Modified: head/sys/net/rtsock.c
> ==============================================================================
> --- head/sys/net/rtsock.c Fri Dec 18 20:41:23 2020 (r368768)
> +++ head/sys/net/rtsock.c Fri Dec 18 22:00:57 2020 (r368769)
> @@ -158,10 +158,13 @@ MTX_SYSINIT(rtsock, &rtsock_mtx, "rtsock route_cb
> lock
> SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
>
> struct walkarg {
> + int family;
> int w_tmemsize;
> int w_op, w_arg;
> caddr_t w_tmem;
> struct sysctl_req *w_req;
> + struct sockaddr *dst;
> + struct sockaddr *mask;
> };
>
> static void rts_input(struct mbuf *m);
> @@ -170,7 +173,7 @@ static int rtsock_msg_buffer(int type, struct rt_addri
> struct walkarg *w, int *plen);
> static int rt_xaddrs(caddr_t cp, caddr_t cplim,
> struct rt_addrinfo *rtinfo);
> -static int sysctl_dumpentry(struct radix_node *rn, void *vw);
> +static int sysctl_dumpentry(struct rtentry *rt, void *vw);
> static int sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh,
> uint32_t weight, struct walkarg *w);
> static int sysctl_iflist(int af, struct walkarg *w);
> @@ -187,7 +190,8 @@ static int update_rtm_from_rc(struct rt_addrinfo *info
> static void send_rtm_reply(struct socket *so, struct rt_msghdr *rtm,
> struct mbuf *m, sa_family_t saf, u_int fibnum,
> int rtm_errno);
> -static int can_export_rte(struct ucred *td_ucred, const struct rtentry
> *rt);
> +static bool can_export_rte(struct ucred *td_ucred, bool rt_is_host,
> + const struct sockaddr *rt_dst);
>
> static struct netisr_handler rtsock_nh = {
> .nh_name = "rtsock",
> @@ -707,7 +711,7 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
> return (ESRCH);
> }
>
> - nh = select_nhop(rc->rc_rt->rt_nhop, info->rti_info[RTAX_GATEWAY]);
> + nh = select_nhop(rt_get_raw_nhop(rc->rc_rt),
> info->rti_info[RTAX_GATEWAY]);
> if (nh == NULL) {
> RIB_RUNLOCK(rnh);
> return (ESRCH);
> @@ -721,9 +725,7 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
> */
> if (rtm->rtm_flags & RTF_ANNOUNCE) {
> struct sockaddr laddr;
> - struct nhop_object *nh;
>
> - nh = rc->rc_rt->rt_nhop;
> if (nh->nh_ifp != NULL &&
> nh->nh_ifp->if_type == IFT_PROPVIRTUAL) {
> struct ifaddr *ifa;
> @@ -747,7 +749,7 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
> RIB_RUNLOCK(rnh);
> return (ESRCH);
> }
> - nh = select_nhop(rc->rc_rt->rt_nhop, info->rti_info[RTAX_GATEWAY]);
> + nh = select_nhop(rt_get_raw_nhop(rc->rc_rt),
> info->rti_info[RTAX_GATEWAY]);
> if (nh == NULL) {
> RIB_RUNLOCK(rnh);
> return (ESRCH);
> @@ -760,6 +762,66 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
> return (0);
> }
>
> +static void
> +init_sockaddrs_family(int family, struct sockaddr *dst, struct sockaddr
> *mask)
> +{
> +#ifdef INET
> + if (family == AF_INET) {
> + struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
> + struct sockaddr_in *mask4 = (struct sockaddr_in *)mask;
> +
> + bzero(dst4, sizeof(struct sockaddr_in));
> + bzero(mask4, sizeof(struct sockaddr_in));
> +
> + dst4->sin_family = AF_INET;
> + dst4->sin_len = sizeof(struct sockaddr_in);
> + mask4->sin_family = AF_INET;
> + mask4->sin_len = sizeof(struct sockaddr_in);
> + }
> +#endif
> +#ifdef INET6
> + if (family == AF_INET6) {
> + struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
> + struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask;
> +
> + bzero(dst6, sizeof(struct sockaddr_in6));
> + bzero(mask6, sizeof(struct sockaddr_in6));
> +
> + dst6->sin6_family = AF_INET6;
> + dst6->sin6_len = sizeof(struct sockaddr_in6);
> + mask6->sin6_family = AF_INET6;
> + mask6->sin6_len = sizeof(struct sockaddr_in6);
> + }
> +#endif
> +}
> +
> +static void
> +export_rtaddrs(const struct rtentry *rt, struct sockaddr *dst,
> + struct sockaddr *mask)
> +{
> + uint32_t scopeid = 0;
> +#ifdef INET
> + if (dst->sa_family == AF_INET) {
> + struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
> + struct sockaddr_in *mask4 = (struct sockaddr_in *)mask;
> + rt_get_inet_prefix_pmask(rt, &dst4->sin_addr, &mask4->sin_addr,
> + &scopeid);
> + return;
> + }
> +#endif
> +#ifdef INET6
> + if (dst->sa_family == AF_INET6) {
> + struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
> + struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask;
> + rt_get_inet6_prefix_pmask(rt, &dst6->sin6_addr, &mask6->sin6_addr,
> + &scopeid);
> + dst6->sin6_scope_id = scopeid;
> + return;
> + }
> +#endif
> +}
> +
> +
> /*
> * Update sockaddrs, flags, etc in @prtm based on @rc data.
> * rtm can be reallocated.
> @@ -772,7 +834,6 @@ static int
> update_rtm_from_rc(struct rt_addrinfo *info, struct rt_msghdr **prtm,
> int alloc_len, struct rib_cmd_info *rc, struct nhop_object *nh)
> {
> - struct sockaddr_storage netmask_ss;
> struct walkarg w;
> union sockaddr_union saun;
> struct rt_msghdr *rtm, *orig_rtm = NULL;
> @@ -780,11 +841,14 @@ update_rtm_from_rc(struct rt_addrinfo *info, struct
> rt
> int error, len;
>
> rtm = *prtm;
> + union sockaddr_union sa_dst, sa_mask;
> + int family = info->rti_info[RTAX_DST]->sa_family;
> + init_sockaddrs_family(family, &sa_dst.sa, &sa_mask.sa);
> + export_rtaddrs(rc->rc_rt, &sa_dst.sa, &sa_mask.sa);
>
> - info->rti_info[RTAX_DST] = rt_key(rc->rc_rt);
> + info->rti_info[RTAX_DST] = &sa_dst.sa;
> + info->rti_info[RTAX_NETMASK] = rt_is_host(rc->rc_rt) ? NULL :
> &sa_mask.sa;
> info->rti_info[RTAX_GATEWAY] = &nh->gw_sa;
> - info->rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rc->rc_rt),
> - rt_mask(rc->rc_rt), &netmask_ss);
> info->rti_info[RTAX_GENMASK] = 0;
> ifp = nh->nh_ifp;
> if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
> @@ -994,7 +1058,9 @@ route_output(struct mbuf *m, struct socket *so, ...)
> nh = rc.rc_nh_new;
>
> report:
> - if (!can_export_rte(curthread->td_ucred, rc.rc_rt)) {
> + if (!can_export_rte(curthread->td_ucred,
> + info.rti_info[RTAX_NETMASK] == NULL,
> + info.rti_info[RTAX_DST])) {
> senderr(ESRCH);
> }
>
> @@ -1730,35 +1796,34 @@ rt_dispatch(struct mbuf *m, sa_family_t saf)
> *
> * Returns 1 if it can, 0 otherwise.
> */
> -static int
> -can_export_rte(struct ucred *td_ucred, const struct rtentry *rt)
> +static bool
> +can_export_rte(struct ucred *td_ucred, bool rt_is_host,
> + const struct sockaddr *rt_dst)
> {
>
> - if ((rt->rte_flags & RTF_HOST) == 0
> - ? jailed_without_vnet(td_ucred)
> - : prison_if(td_ucred, rt_key_const(rt)) != 0)
> - return (0);
> - return (1);
> + if ((!rt_is_host) ? jailed_without_vnet(td_ucred)
> + : prison_if(td_ucred, rt_dst) != 0)
> + return (false);
> + return (true);
> }
>
> +
> /*
> * This is used in dumping the kernel table via sysctl().
> */
> static int
> -sysctl_dumpentry(struct radix_node *rn, void *vw)
> +sysctl_dumpentry(struct rtentry *rt, void *vw)
> {
> struct walkarg *w = vw;
> - struct rtentry *rt = (struct rtentry *)rn;
> struct nhop_object *nh;
> int error = 0;
>
> NET_EPOCH_ASSERT();
>
> - if (w->w_op == NET_RT_FLAGS && !(rt->rte_flags & w->w_arg))
> - return 0;
> - if (!can_export_rte(w->w_req->td->td_ucred, rt))
> + export_rtaddrs(rt, w->dst, w->mask);
> + if (!can_export_rte(w->w_req->td->td_ucred, rt_is_host(rt), w->dst))
> return (0);
> - nh = rt->rt_nhop;
> + nh = rt_get_raw_nhop(rt);
> #ifdef ROUTE_MPATH
> if (NH_IS_NHGRP(nh)) {
> struct weightened_nhop *wn;
> @@ -1783,13 +1848,17 @@ sysctl_dumpnhop(struct rtentry *rt, struct
> nhop_object
> {
> struct rt_addrinfo info;
> int error = 0, size;
> - struct sockaddr_storage ss;
> + uint32_t rtflags;
>
> + rtflags = nhop_get_rtflags(nh);
> +
> + if (w->w_op == NET_RT_FLAGS && !(rtflags & w->w_arg))
> + return (0);
> +
> bzero((caddr_t)&info, sizeof(info));
> - info.rti_info[RTAX_DST] = rt_key(rt);
> + info.rti_info[RTAX_DST] = w->dst;
> info.rti_info[RTAX_GATEWAY] = &nh->gw_sa;
> - info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
> - rt_mask(rt), &ss);
> + info.rti_info[RTAX_NETMASK] = (rtflags & RTF_HOST) ? NULL : w->mask;
> info.rti_info[RTAX_GENMASK] = 0;
> if (nh->nh_ifp && !(nh->nh_ifp->if_flags & IFF_DYING)) {
> info.rti_info[RTAX_IFP] = nh->nh_ifp->if_addr->ifa_addr;
> @@ -1804,12 +1873,16 @@ sysctl_dumpnhop(struct rtentry *rt, struct
> nhop_object
>
> bzero(&rtm->rtm_index,
> sizeof(*rtm) - offsetof(struct rt_msghdr, rtm_index));
> - if (rt->rte_flags & RTF_GWFLAG_COMPAT)
> +
> + /*
> + * rte flags may consist of RTF_HOST (duplicated in nhop rtflags)
> + * and RTF_UP (if entry is linked, which is always true here).
> + * Given that, use nhop rtflags & add RTF_UP.
> + */
> + rtm->rtm_flags = rtflags | RTF_UP;
> + if (rtm->rtm_flags & RTF_GWFLAG_COMPAT)
> rtm->rtm_flags = RTF_GATEWAY |
> - (rt->rte_flags & ~RTF_GWFLAG_COMPAT);
> - else
> - rtm->rtm_flags = rt->rte_flags;
> - rtm->rtm_flags |= nhop_get_rtflags(nh);
> + (rtm->rtm_flags & ~RTF_GWFLAG_COMPAT);
> rt_getmetrics(rt, nh, &rtm->rtm_rmx);
> rtm->rtm_rmx.rmx_weight = weight;
> rtm->rtm_index = nh->nh_ifp->if_index;
> @@ -2075,10 +2148,23 @@ sysctl_ifmalist(int af, struct walkarg *w)
> return (error);
> }
>
> +static void
> +rtable_sysctl_dump(uint32_t fibnum, int family, struct walkarg *w)
> +{
> + union sockaddr_union sa_dst, sa_mask;
> +
> + w->family = family;
> + w->dst = (struct sockaddr *)&sa_dst;
> + w->mask = (struct sockaddr *)&sa_mask;
> +
> + init_sockaddrs_family(family, w->dst, w->mask);
> +
> + rib_walk(fibnum, family, false, sysctl_dumpentry, w);
> +}
> +
> static int
> sysctl_rtsock(SYSCTL_HANDLER_ARGS)
> {
> - RIB_RLOCK_TRACKER;
> struct epoch_tracker et;
> int *name = (int *)arg1;
> u_int namelen = arg2;
> @@ -2151,10 +2237,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
> for (error = 0; error == 0 && i <= lim; i++) {
> rnh = rt_tables_get_rnh(fib, i);
> if (rnh != NULL) {
> - RIB_RLOCK(rnh);
> - error = rnh->rnh_walktree(&rnh->head,
> - sysctl_dumpentry, &w);
> - RIB_RUNLOCK(rnh);
> + rtable_sysctl_dump(fib, i, &w);
> } else if (af != 0)
> error = EAFNOSUPPORT;
> }
> _______________________________________________
> svn-src-all at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
>
--
Mateusz Guzik <mjguzik gmail.com>
More information about the svn-src-head
mailing list