Path: blob/main/tests/sys/net/routing/rtsock_print.h
39604 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2019 Alexander V. Chernikov4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#ifndef _NET_ROUTING_RTSOCK_PRINT_H_28#define _NET_ROUTING_RTSOCK_PRINT_H_293031#define RLOG(_fmt, ...) printf("%s: " _fmt "\n", __func__, ##__VA_ARGS__)32#define RLOG_ERRNO(_fmt, ...) do { \33printf("%s: " _fmt, __func__, ##__VA_ARGS__); \34printf(": %s\n", strerror(errno)); \35} while(0)3637#define RTSOCK_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \38if (!(_cond)) { \39printf("-- CONDITION FAILED, rtm dump --\n\n");\40rtsock_print_message(_rtm); \41rtsock_print_table(AF_INET); \42rtsock_print_table(AF_INET6); \43printf("===================================\n");\44} \45ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \46} while (0);4748#define RTSOCKHD_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \49if (!(_cond)) { \50printf("-- CONDITION FAILED, rtm hexdump--\n\n");\51rtsock_print_message_hd(_rtm); \52} \53ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \54} while (0);555657/* from route.c */58static const char *const msgtypes[] = {59"",60"RTM_ADD",61"RTM_DELETE",62"RTM_CHANGE",63"RTM_GET",64"RTM_LOSING",65"RTM_REDIRECT",66"RTM_MISS",67"RTM_LOCK",68"RTM_OLDADD",69"RTM_OLDDEL",70"RTM_RESOLVE",71"RTM_NEWADDR",72"RTM_DELADDR",73"RTM_IFINFO",74"RTM_NEWMADDR",75"RTM_DELMADDR",76"RTM_IFANNOUNCE",77"RTM_IEEE80211",78};7980static const char metricnames[] =81"\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire"82"\1mtu";83static const char routeflags[] =84"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"85"\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"86"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"87"\024FIXEDMTU\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY";88static const char ifnetflags[] =89"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"90"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"91"\017LINK2\020MULTICAST";92static const char addrnames[] =93"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";9495static int96_printb(char *buf, size_t bufsize, int b, const char *str)97{98int i;99int gotsome = 0;100101char *pbuf = buf;102103if (b == 0) {104*pbuf = '\0';105return (0);106}107while ((i = *str++) != 0) {108if (b & (1 << (i-1))) {109if (gotsome == 0)110i = '<';111else112i = ',';113*pbuf++ = i;114gotsome = 1;115for (; (i = *str) > 32; str++)116*pbuf++ = i;117} else118while (*str > 32)119str++;120}121if (gotsome)122*pbuf++ = '>';123*pbuf = '\0';124125return (int)(pbuf - buf);126}127128const char *129rtsock_print_cmdtype(int cmd)130{131132return (msgtypes[cmd]);133}134135char *136rtsock_print_rtm_flags(char *buf, int buflen, int rtm_flags)137{138139_printb(buf, buflen, rtm_flags, routeflags);140return (buf);141}142143144#define _PRINTX(fmt, ...) do { \145one_len = snprintf(ptr, rem_len, fmt, __VA_ARGS__); \146ptr += one_len; \147rem_len -= one_len; \148} while(0)149150151void152sa_print_hd(char *buf, int buflen, const char *data, int len)153{154char *ptr;155int one_len, rem_len;156157ptr = buf;158rem_len = buflen;159160const char *last_char = NULL;161unsigned char v;162int repeat_count = 0;163for (int i = 0; i < len; i++) {164if (last_char && *last_char == data[i] && data[i] == 0x00) {165repeat_count++;166continue;167}168169if (repeat_count > 1) {170_PRINTX("{%d}", repeat_count);171repeat_count = 0;172}173174v = ((const unsigned char *)data)[i];175if (last_char == NULL)176_PRINTX("x%02X", v);177else178_PRINTX(", x%02X", v);179180last_char = &data[i];181repeat_count = 1;182}183184if (repeat_count > 1)185snprintf(ptr, rem_len, "{%d}", repeat_count);186}187188#undef _PRINTX189190void191sa_print(const struct sockaddr *sa, int include_hexdump)192{193char hdbuf[512], abuf[64];194char ifbuf[128];195const struct sockaddr_dl *sdl;196const struct sockaddr_in6 *sin6;197const struct sockaddr_in *sin;198int i;199200switch (sa->sa_family) {201case AF_INET:202sin = (struct sockaddr_in *)sa;203inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf));204printf(" af=inet len=%d addr=%s", sa->sa_len, abuf);205break;206case AF_INET6:207sin6 = (struct sockaddr_in6 *)sa;208inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, sizeof(abuf));209int scope_id = sin6->sin6_scope_id;210printf(" af=inet6 len=%d addr=%s", sa->sa_len, abuf);211if (scope_id != 0) {212memset(ifbuf, 0, sizeof(ifbuf));213if_indextoname(scope_id, ifbuf);214printf(" scope_id=%d if_name=%s", scope_id, ifbuf);215}216break;217case AF_LINK:218sdl = (const struct sockaddr_dl *)sa;219int sdl_index = sdl->sdl_index;220if (sdl_index != 0) {221memset(ifbuf, 0, sizeof(ifbuf));222if_indextoname(sdl_index, ifbuf);223printf(" af=link len=%d sdl_index=%d if_name=%s", sdl->sdl_len, sdl_index, ifbuf);224}225if (sdl->sdl_nlen) {226char _ifname[IFNAMSIZ];227memcpy(_ifname, sdl->sdl_data, sdl->sdl_nlen);228_ifname[sdl->sdl_nlen] = '\0';229printf(" name=%s", _ifname);230}231if (sdl->sdl_alen) {232printf(" addr=");233const char *lladdr = LLADDR(sdl);234for (int i = 0; i < sdl->sdl_alen; i++) {235if (i + 1 < sdl->sdl_alen)236printf("%02X:", ((const unsigned char *)lladdr)[i]);237else238printf("%02X", ((const unsigned char *)lladdr)[i]);239}240}241break;242default:243printf(" af=%d len=%d", sa->sa_family, sa->sa_len);244}245246if (include_hexdump) {247sa_print_hd(hdbuf, sizeof(hdbuf), ((char *)sa), sa->sa_len);248printf(" hd={%s}", hdbuf);249}250printf("\n");251}252253/*254got message of size 240 on Mon Dec 16 09:23:31 2019255RTM_ADD: Add Route: len 240, pid: 25534, seq 2, errno 0, flags:<HOST,DONE,LLINFO,STATIC>256locks: inits:257sockaddrs: <DST,GATEWAY>258*/259260void261rtsock_print_rtm(struct rt_msghdr *rtm)262{263struct timeval tv;264struct tm tm_res;265char buf[64];266267gettimeofday(&tv, NULL);268localtime_r(&tv.tv_sec, &tm_res);269strftime(buf, sizeof(buf), "%F %T", &tm_res);270printf("Got message of size %hu on %s\n", rtm->rtm_msglen, buf);271272char flags_buf[256];273rtsock_print_rtm_flags(flags_buf, sizeof(flags_buf), rtm->rtm_flags);274275printf("%s: len %hu, pid: %d, seq %d, errno %d, flags: %s\n", msgtypes[rtm->rtm_type],276rtm->rtm_msglen, rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno, flags_buf);277278if (rtm->rtm_inits > 0) {279_printb(flags_buf, sizeof(flags_buf), rtm->rtm_inits, metricnames);280printf("metrics: %s\n", flags_buf);281if (rtm->rtm_inits & RTV_MTU)282printf("mtu: %lu\n", rtm->rtm_rmx.rmx_mtu);283if (rtm->rtm_inits & RTV_EXPIRE) {284struct timeval tv;285gettimeofday(&tv, NULL);286printf("expire: %d (%lu raw)\n",287(int)(rtm->rtm_rmx.rmx_expire - tv.tv_sec), rtm->rtm_rmx.rmx_expire);288}289}290291_printb(flags_buf, sizeof(flags_buf), rtm->rtm_addrs, addrnames);292printf("sockaddrs: 0x%X %s\n", rtm->rtm_addrs, flags_buf);293294char *ptr = (char *)(rtm + 1);295for (int i = 0; i < RTAX_MAX; i++) {296if (rtm->rtm_addrs & (1 << i)) {297struct sockaddr *sa = (struct sockaddr *)ptr;298sa_print(sa, 1);299300/* add */301ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);302}303}304305printf("\n");306307}308309void310rtsock_print_ifa(struct ifa_msghdr *ifam)311{312struct timeval tv;313struct tm tm_res;314char buf[64];315316gettimeofday(&tv, NULL);317localtime_r(&tv.tv_sec, &tm_res);318strftime(buf, sizeof(buf), "%F %T", &tm_res);319printf("Got message of size %hu on %s\n", ifam->ifam_msglen, buf);320321char flags_buf[256];322_printb(flags_buf, sizeof(flags_buf), ifam->ifam_flags, routeflags);323324printf("%s: len %hu, ifindex: %d, flags: %s\n", msgtypes[ifam->ifam_type],325ifam->ifam_msglen, ifam->ifam_index, flags_buf);326327_printb(flags_buf, sizeof(flags_buf), ifam->ifam_addrs, addrnames);328printf("sockaddrs: 0x%X %s\n", ifam->ifam_addrs, flags_buf);329330char *ptr = (char *)(ifam + 1);331for (int i = 0; i < RTAX_MAX; i++) {332if (ifam->ifam_addrs & (1 << i)) {333struct sockaddr *sa = (struct sockaddr *)ptr;334sa_print(sa, 1);335336/* add */337ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);338}339}340341printf("\n");342343}344345void346rtsock_print_message_hd(struct rt_msghdr *rtm)347{348struct timeval tv;349struct tm tm_res;350char buf[64];351char dumpbuf[2048];352353gettimeofday(&tv, NULL);354localtime_r(&tv.tv_sec, &tm_res);355strftime(buf, sizeof(buf), "%F %T", &tm_res);356printf("Got message type %s of size %hu on %s\n",357rtsock_print_cmdtype(rtm->rtm_type),358rtm->rtm_msglen, buf);359360sa_print_hd(dumpbuf, sizeof(dumpbuf), (char *)rtm, rtm->rtm_msglen);361printf(" %s\n", dumpbuf);362}363364void365rtsock_print_message(struct rt_msghdr *rtm)366{367368switch (rtm->rtm_type) {369case RTM_GET:370case RTM_ADD:371case RTM_DELETE:372case RTM_CHANGE:373rtsock_print_rtm(rtm);374break;375case RTM_DELADDR:376case RTM_NEWADDR:377rtsock_print_ifa((struct ifa_msghdr *)rtm);378break;379default:380printf("unknown rt message type %X\n", rtm->rtm_type);381}382}383384static void385print_command(char *cmd)386{387char line[1024];388389FILE *fp = popen(cmd, "r");390if (fp != NULL) {391while (fgets(line, sizeof(line), fp) != NULL)392printf("%s", line);393pclose(fp);394}395}396397void398rtsock_print_table(int family)399{400char cmdbuf[128];401char *key = (family == AF_INET) ? "4" : "6";402403snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%srnW", key);404printf("==== %s ===\n", cmdbuf);405print_command(cmdbuf);406snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%sonW", key);407printf("==== %s ===\n", cmdbuf);408print_command(cmdbuf);409}410411#endif412413414