From 0413dd7573f917fec9faa0886247d15555c98c7b Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 17 Jan 2019 11:09:09 -0200 Subject: [PATCH 1/4] zebra: use proper sockaddr size in kernel_rtm `sockaddr` `len` field is the address type size and not the mask length. Signed-off-by: Rafael Zalamena (cherry picked from commit a6c000318226b9c3e5c3010ea31c6941ac1dff43) --- zebra/rt_socket.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 8012498e80..b27171a00f 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -155,23 +155,21 @@ static int kernel_rtm(int cmd, const struct prefix *p, switch (p->family) { case AF_INET: sin_dest.sin.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_dest.sin.sin_len = sizeof(sin_dest); - sin_gate.sin.sin_len = sizeof(sin_gate); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ sin_dest.sin.sin_addr = p->u.prefix4; sin_gate.sin.sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_dest.sin.sin_len = sizeof(struct sockaddr_in); + sin_gate.sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; case AF_INET6: sin_dest.sin6.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_dest.sin6.sin6_len = sizeof(sin_dest); -#endif /* SIN6_LEN */ sin_dest.sin6.sin6_addr = p->u.prefix6; sin_gate.sin6.sin6_family = AF_INET6; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin6.sin6_len = sizeof(sin_gate); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_dest.sin6.sin6_len = sizeof(struct sockaddr_in6); + sin_gate.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; } @@ -193,6 +191,9 @@ static int kernel_rtm(int cmd, const struct prefix *p, case NEXTHOP_TYPE_IPV4_IFINDEX: sin_gate.sin.sin_addr = nexthop->gate.ipv4; sin_gate.sin.sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_gate.sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ ifindex = nexthop->ifindex; gate = true; break; @@ -200,6 +201,9 @@ static int kernel_rtm(int cmd, const struct prefix *p, case NEXTHOP_TYPE_IPV6_IFINDEX: sin_gate.sin6.sin6_addr = nexthop->gate.ipv6; sin_gate.sin6.sin6_family = AF_INET6; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_gate.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ ifindex = nexthop->ifindex; /* Under kame set interface index to link local address */ #ifdef KAME @@ -228,6 +232,10 @@ static int kernel_rtm(int cmd, const struct prefix *p, struct in_addr loopback; loopback.s_addr = htonl(INADDR_LOOPBACK); sin_gate.sin.sin_addr = loopback; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_gate.sin.sin_len = + sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ gate = true; } break; @@ -240,18 +248,16 @@ static int kernel_rtm(int cmd, const struct prefix *p, case AF_INET: masklen2ip(p->prefixlen, &sin_mask.sin.sin_addr); sin_mask.sin.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_mask.sin.sin_len = sin_masklen( - sin_mask.sin.sin_addr); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_mask.sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; case AF_INET6: masklen2ip6(p->prefixlen, &sin_mask.sin6.sin6_addr); sin_mask.sin6.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_mask.sin6.sin6_len = sin6_masklen( - sin_mask.sin6.sin6_addr); -#endif /* SIN6_LEN */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_mask.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; } From b04f70c1b87dd2f11a7c07e18b3cabb68a8628ce Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 17 Jan 2019 13:19:30 -0200 Subject: [PATCH 2/4] zebra: remove unused functions Remove two unused functions in `zebra/rt_socket.c`. Signed-off-by: Rafael Zalamena (cherry picked from commit 914fea09d9e1a5379b7ed9fa43b0505a091395af) --- zebra/rt_socket.c | 48 ----------------------------------------------- 1 file changed, 48 deletions(-) diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index b27171a00f..7dc5ef8b66 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -44,30 +44,6 @@ extern struct zebra_privs_t zserv_privs; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN -/* Adjust netmask socket length. Return value is a adjusted sin_len - value. */ -static int sin_masklen(struct in_addr mask) -{ - char *p, *lim; - int len; - struct sockaddr_in sin; - - if (mask.s_addr == 0) - return sizeof(long); - - sin.sin_addr = mask; - len = sizeof(struct sockaddr_in); - - lim = (char *)&sin.sin_addr; - p = lim + sizeof(sin.sin_addr); - - while (*--p == 0 && p >= lim) - len--; - return len; -} -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - #ifdef __OpenBSD__ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, struct sockaddr_mpls *smpls) @@ -89,30 +65,6 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, } #endif -#ifdef SIN6_LEN -/* Calculate sin6_len value for netmask socket value. */ -static int sin6_masklen(struct in6_addr mask) -{ - struct sockaddr_in6 sin6; - char *p, *lim; - int len; - - if (IN6_IS_ADDR_UNSPECIFIED(&mask)) - return sizeof(long); - - sin6.sin6_addr = mask; - len = sizeof(struct sockaddr_in6); - - lim = (char *)&sin6.sin6_addr; - p = lim + sizeof(sin6.sin6_addr); - - while (*--p == 0 && p >= lim) - len--; - - return len; -} -#endif /* SIN6_LEN */ - /* Interface between zebra message and rtm message. */ static int kernel_rtm(int cmd, const struct prefix *p, const struct nexthop_group *ng, uint32_t metric) From e0f741f46607399736ea0e8e87a4a34923a6dd0b Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 17 Jan 2019 20:46:11 -0200 Subject: [PATCH 3/4] zebra: fix routing socket AF_LINK handling on NETMASK IPv6 netmasks use AF_LINK family type and puts the correct amount of set bits in the data structure. If we only copy the SDL header we won't get all IPv6 address length, we must copy the whole extension of the `sockaddr_in6` struct (which is provided in `destlen` parameter). Signed-off-by: Rafael Zalamena (cherry picked from commit 691e903879bcf88c872d74f6317784bd2187f3ca) --- zebra/kernel_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index f290d456d6..48db481515 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -274,7 +274,7 @@ size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf) if (sa->sa_family == AF_LINK) { sdl = (struct sockaddr_dl *)sa; if (sdl->sdl_index == 0 || sdl->sdl_nlen == 0) - copylen = sizeof(*sdl) - sizeof(sdl->sdl_data); + copylen = destlen; } if (copylen > destlen) { From 1583f8f5ad87c3506e4b49add613c153117d5205 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 18 Jan 2019 18:28:58 -0200 Subject: [PATCH 4/4] zebra: use rta_getattr for NETMASK IPv6 uses AF_LINK to represent netmasks, this commit unbreaks `rtm_read_mesg` that was broke on the `rta_get*` refactory. Signed-off-by: Rafael Zalamena (cherry picked from commit 7a163a7c59bd1a7e94da356ea033040ae17cef29) --- zebra/kernel_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 48db481515..f3561cc19d 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -994,7 +994,7 @@ static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest, pnt += rta_get(pnt, gate, sizeof(*gate)); break; case RTA_NETMASK: - pnt += rta_get(pnt, mask, sizeof(*mask)); + pnt += rta_getattr(pnt, mask, sizeof(*mask)); break; case RTA_IFP: pnt += rta_getsdlname(pnt, ifname, ifnlen);