aboutsummaryrefslogtreecommitdiff
path: root/tests/sys/net/routing/rtsock_print.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/sys/net/routing/rtsock_print.h')
-rw-r--r--tests/sys/net/routing/rtsock_print.h412
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