Hi, The algorithm in route(8) and arp(6) is still not correct. While the values written to the kernel are fine, the bytes for padding are taken from memory after the sockaddr structs.
In route(8) the union of sockaddr can be made larger so that the padding is taken from there. In arp(8) we know the size of the struct. Copy only the struct and advance over the padding. The memory has been zeroed before. ndp(8) can take all the fixes from arp(8). ok? bluhm Index: sbin/route/route.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sbin/route/route.c,v retrieving revision 1.232 diff -u -p -r1.232 route.c --- sbin/route/route.c 29 Aug 2019 22:42:16 -0000 1.232 +++ sbin/route/route.c 30 Aug 2019 13:24:31 -0000 @@ -137,10 +137,6 @@ usage(char *cp) exit(1); } -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) -#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) - int main(int argc, char **argv) { Index: sbin/route/show.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sbin/route/show.h,v retrieving revision 1.14 diff -u -p -r1.14 show.h --- sbin/route/show.h 1 May 2018 18:13:21 -0000 1.14 +++ sbin/route/show.h 30 Aug 2019 13:22:57 -0000 @@ -19,6 +19,18 @@ #ifndef __SHOW_H__ #define __SHOW_H__ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) +#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b)) +#define SAMAXSIZE \ + MAXIMUM(sizeof(struct sockaddr), \ + MAXIMUM(sizeof(struct sockaddr_in), \ + MAXIMUM(sizeof(struct sockaddr_in6), \ + MAXIMUM(sizeof(struct sockaddr_dl), \ + MAXIMUM(sizeof(struct sockaddr_rtlabel), \ + sizeof(struct sockaddr_mpls)))))) + union sockunion { struct sockaddr sa; struct sockaddr_in sin; @@ -26,6 +38,7 @@ union sockunion { struct sockaddr_dl sdl; struct sockaddr_rtlabel rtlabel; struct sockaddr_mpls smpls; + char padding[ROUNDUP(SAMAXSIZE)]; }; void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); Index: usr.sbin/arp/arp.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/arp/arp.c,v retrieving revision 1.85 diff -u -p -r1.85 arp.c --- usr.sbin/arp/arp.c 29 Aug 2019 19:11:15 -0000 1.85 +++ usr.sbin/arp/arp.c 30 Aug 2019 13:57:15 -0000 @@ -675,9 +675,8 @@ rtmsg(int cmd) #define NEXTADDR(w, s) \ if (rtm->rtm_addrs & (w)) { \ - l = ROUNDUP(((struct sockaddr *)&(s))->sa_len); \ - memcpy(cp, &(s), l); \ - cp += l; \ + memcpy(cp, &(s), sizeof(s)); \ + ADVANCE(cp, (struct sockaddr *)&(s)); \ } NEXTADDR(RTA_DST, sin_m); Index: usr.sbin/ndp/ndp.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/ndp/ndp.c,v retrieving revision 1.97 diff -u -p -r1.97 ndp.c --- usr.sbin/ndp/ndp.c 27 Aug 2019 20:42:40 -0000 1.97 +++ usr.sbin/ndp/ndp.c 30 Aug 2019 14:08:52 -0000 @@ -108,6 +108,7 @@ /* packing rule for routing socket */ #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) static pid_t pid; static int nflag; @@ -323,7 +324,7 @@ parse_host(const char *host, struct in6_ struct sockaddr_in6 so_mask = {sizeof(so_mask), AF_INET6 }; struct sockaddr_in6 blank_sin = {sizeof(blank_sin), AF_INET6 }, sin_m; struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m; -struct sockaddr_dl ifp_m = { sizeof(&ifp_m), AF_LINK }; +struct sockaddr_dl ifp_m = { sizeof(ifp_m), AF_LINK }; time_t expire_time; int flags, found_entry; struct { @@ -766,9 +767,12 @@ rtmsg(int cmd) case RTM_GET: rtm->rtm_addrs |= (RTA_DST | RTA_IFP); } -#define NEXTADDR(w, s) \ - if (rtm->rtm_addrs & (w)) { \ - bcopy((char *)&s, cp, sizeof(s)); cp += ROUNDUP(sizeof(s));} + +#define NEXTADDR(w, s) \ + if (rtm->rtm_addrs & (w)) { \ + memcpy(cp, &(s), sizeof(s)); \ + ADVANCE(cp, (struct sockaddr *)&(s)); \ + } NEXTADDR(RTA_DST, sin_m); NEXTADDR(RTA_GATEWAY, sdl_m); @@ -825,7 +829,7 @@ rtget(struct sockaddr_in6 **sinp, struct default: break; } - cp += ROUNDUP(sa->sa_len); + ADVANCE(cp, sa); } } }