diff options
Diffstat (limited to 'tests/sys/net/routing/rtsock_print.h')
| -rw-r--r-- | tests/sys/net/routing/rtsock_print.h | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/tests/sys/net/routing/rtsock_print.h b/tests/sys/net/routing/rtsock_print.h new file mode 100644 index 000000000000..61d70dc55670 --- /dev/null +++ b/tests/sys/net/routing/rtsock_print.h @@ -0,0 +1,412 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Alexander V. Chernikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NET_ROUTING_RTSOCK_PRINT_H_ +#define _NET_ROUTING_RTSOCK_PRINT_H_ + + +#define RLOG(_fmt, ...) printf("%s: " _fmt "\n", __func__, ##__VA_ARGS__) +#define RLOG_ERRNO(_fmt, ...) do { \ + printf("%s: " _fmt, __func__, ##__VA_ARGS__); \ + printf(": %s\n", strerror(errno)); \ +} while(0) + +#define RTSOCK_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \ + if (!(_cond)) { \ + printf("-- CONDITION FAILED, rtm dump --\n\n");\ + rtsock_print_message(_rtm); \ + rtsock_print_table(AF_INET); \ + rtsock_print_table(AF_INET6); \ + printf("===================================\n");\ + } \ + ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \ +} while (0); + +#define RTSOCKHD_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \ + if (!(_cond)) { \ + printf("-- CONDITION FAILED, rtm hexdump--\n\n");\ + rtsock_print_message_hd(_rtm); \ + } \ + ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \ +} while (0); + + +/* from route.c */ +static const char *const msgtypes[] = { + "", + "RTM_ADD", + "RTM_DELETE", + "RTM_CHANGE", + "RTM_GET", + "RTM_LOSING", + "RTM_REDIRECT", + "RTM_MISS", + "RTM_LOCK", + "RTM_OLDADD", + "RTM_OLDDEL", + "RTM_RESOLVE", + "RTM_NEWADDR", + "RTM_DELADDR", + "RTM_IFINFO", + "RTM_NEWMADDR", + "RTM_DELMADDR", + "RTM_IFANNOUNCE", + "RTM_IEEE80211", +}; + +static const char metricnames[] = + "\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire" + "\1mtu"; +static const char routeflags[] = + "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" + "\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE" + "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3" + "\024FIXEDMTU\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY"; +static const char ifnetflags[] = + "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" + "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" + "\017LINK2\020MULTICAST"; +static const char addrnames[] = + "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; + +static int +_printb(char *buf, size_t bufsize, int b, const char *str) +{ + int i; + int gotsome = 0; + + char *pbuf = buf; + + if (b == 0) { + *pbuf = '\0'; + return (0); + } + while ((i = *str++) != 0) { + if (b & (1 << (i-1))) { + if (gotsome == 0) + i = '<'; + else + i = ','; + *pbuf++ = i; + gotsome = 1; + for (; (i = *str) > 32; str++) + *pbuf++ = i; + } else + while (*str > 32) + str++; + } + if (gotsome) + *pbuf++ = '>'; + *pbuf = '\0'; + + return (int)(pbuf - buf); +} + +const char * +rtsock_print_cmdtype(int cmd) +{ + + return (msgtypes[cmd]); +} + +char * +rtsock_print_rtm_flags(char *buf, int buflen, int rtm_flags) +{ + + _printb(buf, buflen, rtm_flags, routeflags); + return (buf); +} + + +#define _PRINTX(fmt, ...) do { \ + one_len = snprintf(ptr, rem_len, fmt, __VA_ARGS__); \ + ptr += one_len; \ + rem_len -= one_len; \ +} while(0) + + +void +sa_print_hd(char *buf, int buflen, const char *data, int len) +{ + char *ptr; + int one_len, rem_len; + + ptr = buf; + rem_len = buflen; + + const char *last_char = NULL; + unsigned char v; + int repeat_count = 0; + for (int i = 0; i < len; i++) { + if (last_char && *last_char == data[i] && data[i] == 0x00) { + repeat_count++; + continue; + } + + if (repeat_count > 1) { + _PRINTX("{%d}", repeat_count); + repeat_count = 0; + } + + v = ((const unsigned char *)data)[i]; + if (last_char == NULL) + _PRINTX("x%02X", v); + else + _PRINTX(", x%02X", v); + + last_char = &data[i]; + repeat_count = 1; + } + + if (repeat_count > 1) + snprintf(ptr, rem_len, "{%d}", repeat_count); +} + +#undef _PRINTX + +void +sa_print(const struct sockaddr *sa, int include_hexdump) +{ + char hdbuf[512], abuf[64]; + char ifbuf[128]; + const struct sockaddr_dl *sdl; + const struct sockaddr_in6 *sin6; + const struct sockaddr_in *sin; + int i; + + switch (sa->sa_family) { + case AF_INET: + sin = (struct sockaddr_in *)sa; + inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf)); + printf(" af=inet len=%d addr=%s", sa->sa_len, abuf); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)sa; + inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, sizeof(abuf)); + int scope_id = sin6->sin6_scope_id; + printf(" af=inet6 len=%d addr=%s", sa->sa_len, abuf); + if (scope_id != 0) { + memset(ifbuf, 0, sizeof(ifbuf)); + if_indextoname(scope_id, ifbuf); + printf(" scope_id=%d if_name=%s", scope_id, ifbuf); + } + break; + case AF_LINK: + sdl = (const struct sockaddr_dl *)sa; + int sdl_index = sdl->sdl_index; + if (sdl_index != 0) { + memset(ifbuf, 0, sizeof(ifbuf)); + if_indextoname(sdl_index, ifbuf); + printf(" af=link len=%d sdl_index=%d if_name=%s", sdl->sdl_len, sdl_index, ifbuf); + } + if (sdl->sdl_nlen) { + char _ifname[IFNAMSIZ]; + memcpy(_ifname, sdl->sdl_data, sdl->sdl_nlen); + _ifname[sdl->sdl_nlen] = '\0'; + printf(" name=%s", _ifname); + } + if (sdl->sdl_alen) { + printf(" addr="); + const char *lladdr = LLADDR(sdl); + for (int i = 0; i < sdl->sdl_alen; i++) { + if (i + 1 < sdl->sdl_alen) + printf("%02X:", ((const unsigned char *)lladdr)[i]); + else + printf("%02X", ((const unsigned char *)lladdr)[i]); + } + } + break; + default: + printf(" af=%d len=%d", sa->sa_family, sa->sa_len); + } + + if (include_hexdump) { + sa_print_hd(hdbuf, sizeof(hdbuf), ((char *)sa), sa->sa_len); + printf(" hd={%s}", hdbuf); + } + printf("\n"); +} + +/* +got message of size 240 on Mon Dec 16 09:23:31 2019 +RTM_ADD: Add Route: len 240, pid: 25534, seq 2, errno 0, flags:<HOST,DONE,LLINFO,STATIC> +locks: inits: +sockaddrs: <DST,GATEWAY> +*/ + +void +rtsock_print_rtm(struct rt_msghdr *rtm) +{ + struct timeval tv; + struct tm tm_res; + char buf[64]; + + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &tm_res); + strftime(buf, sizeof(buf), "%F %T", &tm_res); + printf("Got message of size %hu on %s\n", rtm->rtm_msglen, buf); + + char flags_buf[256]; + rtsock_print_rtm_flags(flags_buf, sizeof(flags_buf), rtm->rtm_flags); + + printf("%s: len %hu, pid: %d, seq %d, errno %d, flags: %s\n", msgtypes[rtm->rtm_type], + rtm->rtm_msglen, rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno, flags_buf); + + if (rtm->rtm_inits > 0) { + _printb(flags_buf, sizeof(flags_buf), rtm->rtm_inits, metricnames); + printf("metrics: %s\n", flags_buf); + if (rtm->rtm_inits & RTV_MTU) + printf("mtu: %lu\n", rtm->rtm_rmx.rmx_mtu); + if (rtm->rtm_inits & RTV_EXPIRE) { + struct timeval tv; + gettimeofday(&tv, NULL); + printf("expire: %d (%lu raw)\n", + (int)(rtm->rtm_rmx.rmx_expire - tv.tv_sec), rtm->rtm_rmx.rmx_expire); + } + } + + _printb(flags_buf, sizeof(flags_buf), rtm->rtm_addrs, addrnames); + printf("sockaddrs: 0x%X %s\n", rtm->rtm_addrs, flags_buf); + + char *ptr = (char *)(rtm + 1); + for (int i = 0; i < RTAX_MAX; i++) { + if (rtm->rtm_addrs & (1 << i)) { + struct sockaddr *sa = (struct sockaddr *)ptr; + sa_print(sa, 1); + + /* add */ + ptr += ALIGN(((struct sockaddr *)ptr)->sa_len); + } + } + + printf("\n"); + +} + +void +rtsock_print_ifa(struct ifa_msghdr *ifam) +{ + struct timeval tv; + struct tm tm_res; + char buf[64]; + + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &tm_res); + strftime(buf, sizeof(buf), "%F %T", &tm_res); + printf("Got message of size %hu on %s\n", ifam->ifam_msglen, buf); + + char flags_buf[256]; + _printb(flags_buf, sizeof(flags_buf), ifam->ifam_flags, routeflags); + + printf("%s: len %hu, ifindex: %d, flags: %s\n", msgtypes[ifam->ifam_type], + ifam->ifam_msglen, ifam->ifam_index, flags_buf); + + _printb(flags_buf, sizeof(flags_buf), ifam->ifam_addrs, addrnames); + printf("sockaddrs: 0x%X %s\n", ifam->ifam_addrs, flags_buf); + + char *ptr = (char *)(ifam + 1); + for (int i = 0; i < RTAX_MAX; i++) { + if (ifam->ifam_addrs & (1 << i)) { + struct sockaddr *sa = (struct sockaddr *)ptr; + sa_print(sa, 1); + + /* add */ + ptr += ALIGN(((struct sockaddr *)ptr)->sa_len); + } + } + + printf("\n"); + +} + +void +rtsock_print_message_hd(struct rt_msghdr *rtm) +{ + struct timeval tv; + struct tm tm_res; + char buf[64]; + char dumpbuf[2048]; + + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &tm_res); + strftime(buf, sizeof(buf), "%F %T", &tm_res); + printf("Got message type %s of size %hu on %s\n", + rtsock_print_cmdtype(rtm->rtm_type), + rtm->rtm_msglen, buf); + + sa_print_hd(dumpbuf, sizeof(dumpbuf), (char *)rtm, rtm->rtm_msglen); + printf(" %s\n", dumpbuf); +} + +void +rtsock_print_message(struct rt_msghdr *rtm) +{ + + switch (rtm->rtm_type) { + case RTM_GET: + case RTM_ADD: + case RTM_DELETE: + case RTM_CHANGE: + rtsock_print_rtm(rtm); + break; + case RTM_DELADDR: + case RTM_NEWADDR: + rtsock_print_ifa((struct ifa_msghdr *)rtm); + break; + default: + printf("unknown rt message type %X\n", rtm->rtm_type); + } +} + +static void +print_command(char *cmd) +{ + char line[1024]; + + FILE *fp = popen(cmd, "r"); + if (fp != NULL) { + while (fgets(line, sizeof(line), fp) != NULL) + printf("%s", line); + pclose(fp); + } +} + +void +rtsock_print_table(int family) +{ + char cmdbuf[128]; + char *key = (family == AF_INET) ? "4" : "6"; + + snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%srnW", key); + printf("==== %s ===\n", cmdbuf); + print_command(cmdbuf); + snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%sonW", key); + printf("==== %s ===\n", cmdbuf); + print_command(cmdbuf); +} + +#endif |
