In this context I meant NOINET and NOINET6 Anyhow I see the following: sys/net/rtsock.c:1427:2: error: implicit declaration of function 'IN6_MASK_ADDR' is invalid in C99 [-Werror,-Wimplicit-function-declaration] IN6_MASK_ADDR(&dst_sa->sin6_addr, &mask); ^
On 2/16/21, Alexander V. Chernikov <melif...@freebsd.org> wrote: > 16.02.2021, 20:43, "Mateusz Guzik" <mjgu...@gmail.com>: >> This breaks the built at least without INET6. > It would help if you could share the actual build error. > I see -Wunused for 2 function (which I will fix soon), but I'm not sure if > that's the error you're running into. >> >> can you please start testing your patches on NOINET kernels > Well, it actually builds for me: > -------------------------------------------------------------- >>>> Kernel build for LINT-NOINET completed on Tue Feb 16 21:21:39 UTC 2021 > -------------------------------------------------------------- >>>> Kernel(s) LINT-NOINET built in 28 seconds, ncpu: 2, make -j6 > -------------------------------------------------------------- > >> >> On 2/16/21, Alexander V. Chernikov <melif...@freebsd.org> wrote: >>> The branch main has been updated by melifaro: >>> >>> URL: >>> >>> https://cgit.FreeBSD.org/src/commit/?id=2fe5a79425c79f7b828acd91da66d97230925fc8 >>> >>> commit 2fe5a79425c79f7b828acd91da66d97230925fc8 >>> Author: Alexander V. Chernikov <melif...@freebsd.org> >>> AuthorDate: 2021-02-16 20:30:04 +0000 >>> Commit: Alexander V. Chernikov <melif...@freebsd.org> >>> CommitDate: 2021-02-16 20:30:04 +0000 >>> >>> Fix dst/netmask handling in routing socket code. >>> >>> Traditionally routing socket code did almost zero checks on >>> the input message except for the most basic size checks. >>> >>> This resulted in the unclear KPI boundary for the routing system >>> code >>> (`rtrequest*` and now `rib_action()`) w.r.t message validness. >>> >>> Multiple potential problems and nuances exists: >>> * Host bits in RTAX_DST sockaddr. Existing applications do send >>> prefixes >>> with hostbits uncleared. Even `route(8)` does this, as they hope >>> the >>> kernel >>> would do the job of fixing it. Code inside `rib_action()` needs to >>> handle >>> it on its own (see `rt_maskedcopy()` ugly hack). >>> * There are multiple way of adding the host route: it can be DST >>> without >>> netmask or DST with /32(/128) netmask. Also, RTF_HOST has to be >>> set >>> correspondingly. >>> Currently, these 2 options create 2 DIFFERENT routes in the >>> kernel. >>> * no sockaddr length/content checking for the "secondary" fields >>> exists: >>> nothing >>> stops rtsock application to send sockaddr_in with length of 25 >>> (instead >>> of 16). >>> Kernel will accept it, install to RIB as is and propagate to all >>> rtsock >>> consumers, >>> potentially triggering bugs in their code. Same goes for sin_port, >>> sin_zero, etc. >>> >>> The goal of this change is to make rtsock verify all sockaddr and >>> prefix >>> consistency. >>> Said differently, `rib_action()` or internals should NOT require to >>> change any of the >>> sockaddrs supplied by `rt_addrinfo` structure due to >>> incorrectness. >>> >>> To be more specific, this change implements the following: >>> * sockaddr cleanup/validation check is added immediately after >>> getting >>> sockaddrs from rtm. >>> * Per-family dst/netmask checks clears host bits in dst and zeros >>> all >>> dst/netmask "secondary" fields. >>> * The same netmask checking code converts /32(/128) netmasks to >>> "host" >>> route case >>> (NULL netmask, RTF_HOST), removing the dualism. >>> * Instead of allowing ANY "known" sockaddr families (0<..<AF_MAX), >>> allow >>> only actually >>> supported ones (inet, inet6, link). >>> * Automatically convert `sockaddr_sdl` (AF_LINK) gateways to >>> `sockaddr_sdl_short`. >>> >>> Reported by: Guy Yur <guyyur at gmail.com> >>> Reviewed By: donner >>> Differential Revision: https://reviews.freebsd.org/D28668 >>> MFC after: 3 days >>> --- >>> sys/net/rtsock.c | 201 >>> +++++++++++++++++++++++++++++++++- >>> tests/sys/net/routing/rtsock_common.h | 4 - >>> 2 files changed, 195 insertions(+), 10 deletions(-) >>> >>> diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c >>> index 3a98b366dfc3..40ce62c77c2a 100644 >>> --- a/sys/net/rtsock.c >>> +++ b/sys/net/rtsock.c >>> @@ -70,6 +70,7 @@ >>> #include <netinet/if_ether.h> >>> #include <netinet/ip_carp.h> >>> #ifdef INET6 >>> +#include <netinet6/in6_var.h> >>> #include <netinet6/ip6_var.h> >>> #include <netinet6/scope6_var.h> >>> #endif >>> @@ -173,6 +174,7 @@ static int rtsock_msg_buffer(int type, struct >>> rt_addrinfo *rtinfo, >>> struct walkarg *w, int *plen); >>> static int rt_xaddrs(caddr_t cp, caddr_t cplim, >>> struct rt_addrinfo *rtinfo); >>> +static int cleanup_xaddrs(struct rt_addrinfo *info); >>> 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); >>> @@ -636,11 +638,9 @@ fill_addrinfo(struct rt_msghdr *rtm, int len, >>> u_int >>> fibnum, struct rt_addrinfo * >>> return (EINVAL); >>> >>> info->rti_flags = rtm->rtm_flags; >>> - if (info->rti_info[RTAX_DST] == NULL || >>> - info->rti_info[RTAX_DST]->sa_family >= AF_MAX || >>> - (info->rti_info[RTAX_GATEWAY] != NULL && >>> - info->rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) >>> - return (EINVAL); >>> + error = cleanup_xaddrs(info); >>> + if (error != 0) >>> + return (error); >>> saf = info->rti_info[RTAX_DST]->sa_family; >>> /* >>> * Verify that the caller has the appropriate privilege; >>> RTM_GET >>> @@ -739,7 +739,14 @@ handle_rtm_get(struct rt_addrinfo *info, u_int >>> fibnum, >>> >>> RIB_RLOCK(rnh); >>> >>> - if (info->rti_info[RTAX_NETMASK] == NULL) { >>> + /* >>> + * By (implicit) convention host route (one without netmask) >>> + * means longest-prefix-match request and the route with netmask >>> + * means exact-match lookup. >>> + * As cleanup_xaddrs() cleans up info flags&addrs for the /32,/128 >>> + * prefixes, use original data to check for the netmask presence. >>> + */ >>> + if ((rtm->rtm_addrs & RTA_NETMASK) == 0) { >>> /* >>> * Provide longest prefix match for >>> * address lookup (no mask). >>> @@ -1286,6 +1293,188 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct >>> rt_addrinfo *rtinfo) >>> return (0); >>> } >>> >>> +static inline void >>> +fill_sockaddr_inet(struct sockaddr_in *sin, struct in_addr addr) >>> +{ >>> + >>> + const struct sockaddr_in nsin = { >>> + .sin_family = AF_INET, >>> + .sin_len = sizeof(struct sockaddr_in), >>> + .sin_addr = addr, >>> + }; >>> + *sin = nsin; >>> +} >>> + >>> +static inline void >>> +fill_sockaddr_inet6(struct sockaddr_in6 *sin6, const struct in6_addr >>> *addr6, >>> + uint32_t scopeid) >>> +{ >>> + >>> + const struct sockaddr_in6 nsin6 = { >>> + .sin6_family = AF_INET6, >>> + .sin6_len = sizeof(struct sockaddr_in6), >>> + .sin6_addr = *addr6, >>> + .sin6_scope_id = scopeid, >>> + }; >>> + *sin6 = nsin6; >>> +} >>> + >>> +static int >>> +cleanup_xaddrs_gateway(struct rt_addrinfo *info) >>> +{ >>> + struct sockaddr *gw = info->rti_info[RTAX_GATEWAY]; >>> + >>> + switch (gw->sa_family) { >>> +#ifdef INET >>> + case AF_INET: >>> + { >>> + struct sockaddr_in *gw_sin = (struct sockaddr_in *)gw; >>> + if (gw_sin->sin_len < sizeof(struct sockaddr_in)) { >>> + printf("gw sin_len too small\n"); >>> + return (EINVAL); >>> + } >>> + fill_sockaddr_inet(gw_sin, gw_sin->sin_addr); >>> + } >>> + break; >>> +#endif >>> +#ifdef INET6 >>> + case AF_INET6: >>> + { >>> + struct sockaddr_in6 *gw_sin6 = (struct sockaddr_in6 *)gw; >>> + if (gw_sin6->sin6_len < sizeof(struct sockaddr_in6)) { >>> + printf("gw sin6_len too small\n"); >>> + return (EINVAL); >>> + } >>> + fill_sockaddr_inet6(gw_sin6, &gw_sin6->sin6_addr, 0); >>> + break; >>> + } >>> +#endif >>> + case AF_LINK: >>> + { >>> + struct sockaddr_dl_short *gw_sdl; >>> + >>> + gw_sdl = (struct sockaddr_dl_short *)gw; >>> + if (gw_sdl->sdl_len < sizeof(struct sockaddr_dl_short)) { >>> + printf("gw sdl_len too small\n"); >>> + return (EINVAL); >>> + } >>> + >>> + const struct sockaddr_dl_short sdl = { >>> + .sdl_family = AF_LINK, >>> + .sdl_len = sizeof(struct sockaddr_dl_short), >>> + .sdl_index = gw_sdl->sdl_index, >>> + }; >>> + *gw_sdl = sdl; >>> + break; >>> + } >>> + } >>> + >>> + return (0); >>> +} >>> + >>> +static int >>> +cleanup_xaddrs_inet(struct rt_addrinfo *info) >>> +{ >>> + struct sockaddr_in *dst_sa, *mask_sa; >>> + >>> + /* Check & fixup dst/netmask combination first */ >>> + dst_sa = (struct sockaddr_in *)info->rti_info[RTAX_DST]; >>> + mask_sa = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; >>> + >>> + struct in_addr mask = { >>> + .s_addr = mask_sa ? mask_sa->sin_addr.s_addr : INADDR_BROADCAST, >>> + }; >>> + struct in_addr dst = { >>> + .s_addr = htonl(ntohl(dst_sa->sin_addr.s_addr) & ntohl(mask.s_addr)) >>> + }; >>> + >>> + if (dst_sa->sin_len < sizeof(struct sockaddr_in)) { >>> + printf("dst sin_len too small\n"); >>> + return (EINVAL); >>> + } >>> + if (mask_sa && mask_sa->sin_len < sizeof(struct sockaddr_in)) { >>> + printf("mask sin_len too small\n"); >>> + return (EINVAL); >>> + } >>> + fill_sockaddr_inet(dst_sa, dst); >>> + >>> + if (mask.s_addr != INADDR_BROADCAST) >>> + fill_sockaddr_inet(mask_sa, mask); >>> + else { >>> + info->rti_info[RTAX_NETMASK] = NULL; >>> + info->rti_flags |= RTF_HOST; >>> + info->rti_addrs &= ~RTA_NETMASK; >>> + } >>> + >>> + /* Check gateway */ >>> + if (info->rti_info[RTAX_GATEWAY] != NULL) >>> + return (cleanup_xaddrs_gateway(info)); >>> + >>> + return (0); >>> +} >>> + >>> +static int >>> +cleanup_xaddrs_inet6(struct rt_addrinfo *info) >>> +{ >>> + struct sockaddr_in6 *dst_sa, *mask_sa; >>> + struct in6_addr mask; >>> + >>> + /* Check & fixup dst/netmask combination first */ >>> + dst_sa = (struct sockaddr_in6 *)info->rti_info[RTAX_DST]; >>> + mask_sa = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; >>> + >>> + mask = mask_sa ? mask_sa->sin6_addr : in6mask128; >>> + IN6_MASK_ADDR(&dst_sa->sin6_addr, &mask); >>> + >>> + if (dst_sa->sin6_len < sizeof(struct sockaddr_in6)) { >>> + printf("dst sin6_len too small\n"); >>> + return (EINVAL); >>> + } >>> + if (mask_sa && mask_sa->sin6_len < sizeof(struct sockaddr_in6)) { >>> + printf("mask sin6_len too small\n"); >>> + return (EINVAL); >>> + } >>> + fill_sockaddr_inet6(dst_sa, &dst_sa->sin6_addr, 0); >>> + >>> + if (!IN6_ARE_ADDR_EQUAL(&mask, &in6mask128)) >>> + fill_sockaddr_inet6(mask_sa, &mask, 0); >>> + else { >>> + info->rti_info[RTAX_NETMASK] = NULL; >>> + info->rti_flags |= RTF_HOST; >>> + info->rti_addrs &= ~RTA_NETMASK; >>> + } >>> + >>> + /* Check gateway */ >>> + if (info->rti_info[RTAX_GATEWAY] != NULL) >>> + return (cleanup_xaddrs_gateway(info)); >>> + >>> + return (0); >>> +} >>> + >>> +static int >>> +cleanup_xaddrs(struct rt_addrinfo *info) >>> +{ >>> + int error = EAFNOSUPPORT; >>> + >>> + if (info->rti_info[RTAX_DST] == NULL) >>> + return (EINVAL); >>> + >>> + switch (info->rti_info[RTAX_DST]->sa_family) { >>> +#ifdef INET >>> + case AF_INET: >>> + error = cleanup_xaddrs_inet(info); >>> + break; >>> +#endif >>> +#ifdef INET6 >>> + case AF_INET6: >>> + error = cleanup_xaddrs_inet6(info); >>> + break; >>> +#endif >>> + } >>> + >>> + return (error); >>> +} >>> + >>> /* >>> * Fill in @dmask with valid netmask leaving original @smask >>> * intact. Mostly used with radix netmasks. >>> diff --git a/tests/sys/net/routing/rtsock_common.h >>> b/tests/sys/net/routing/rtsock_common.h >>> index 7da88e0eb512..71476d2b5f3c 100644 >>> --- a/tests/sys/net/routing/rtsock_common.h >>> +++ b/tests/sys/net/routing/rtsock_common.h >>> @@ -826,10 +826,6 @@ _validate_message_sockaddrs(char *buffer, int >>> rtm_len, >>> size_t offset, int rtm_ad >>> } >>> sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); >>> } >>> - >>> - RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len == >>> rtm_len, >>> - "message len != parsed len: expected %d parsed %d", >>> - rtm_len, (int)parsed_len); >>> } >>> >>> /* >>> _______________________________________________ >>> dev-commits-src-all@freebsd.org mailing list >>> https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all >>> To unsubscribe, send any mail to >>> "dev-commits-src-all-unsubscr...@freebsd.org" >> >> -- >> Mateusz Guzik <mjguzik gmail.com> > -- Mateusz Guzik <mjguzik gmail.com> _______________________________________________ dev-commits-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"