2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2019 Alexander V. Chernikov
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #ifndef _NET_ROUTING_RTSOCK_PRINT_H_
31 #define _NET_ROUTING_RTSOCK_PRINT_H_
34 #define RLOG(_fmt, ...) printf("%s: " _fmt "\n", __func__, ##__VA_ARGS__)
35 #define RLOG_ERRNO(_fmt, ...) do { \
36 printf("%s: " _fmt, __func__, ##__VA_ARGS__); \
37 printf(": %s\n", strerror(errno)); \
40 #define RTSOCK_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \
42 printf("-- CONDITION FAILED, rtm dump --\n\n");\
43 rtsock_print_message(_rtm); \
44 rtsock_print_table(AF_INET); \
45 rtsock_print_table(AF_INET6); \
46 printf("===================================\n");\
48 ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \
51 #define RTSOCKHD_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do { \
53 printf("-- CONDITION FAILED, rtm hexdump--\n\n");\
54 rtsock_print_message_hd(_rtm); \
56 ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__); \
61 static const char *const msgtypes[] = {
83 static const char metricnames[] =
84 "\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire"
86 static const char routeflags[] =
87 "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"
88 "\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
89 "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"
90 "\024FIXEDMTU\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY";
91 static const char ifnetflags[] =
92 "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
93 "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
94 "\017LINK2\020MULTICAST";
95 static const char addrnames[] =
96 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
99 _printb(char *buf, size_t bufsize, int b, const char *str)
110 while ((i = *str++) != 0) {
111 if (b & (1 << (i-1))) {
118 for (; (i = *str) > 32; str++)
128 return (int)(pbuf - buf);
132 rtsock_print_cmdtype(int cmd)
135 return (msgtypes[cmd]);
139 rtsock_print_rtm_flags(char *buf, int buflen, int rtm_flags)
142 _printb(buf, buflen, rtm_flags, routeflags);
147 #define _PRINTX(fmt, ...) do { \
148 one_len = snprintf(ptr, rem_len, fmt, __VA_ARGS__); \
150 rem_len -= one_len; \
155 sa_print_hd(char *buf, int buflen, const char *data, int len)
158 int one_len, rem_len;
163 const char *last_char = NULL;
165 int repeat_count = 0;
166 for (int i = 0; i < len; i++) {
167 if (last_char && *last_char == data[i] && data[i] == 0x00) {
172 if (repeat_count > 1) {
173 _PRINTX("{%d}", repeat_count);
177 v = ((const unsigned char *)data)[i];
178 if (last_char == NULL)
181 _PRINTX(", x%02X", v);
183 last_char = &data[i];
187 if (repeat_count > 1)
188 snprintf(ptr, rem_len, "{%d}", repeat_count);
194 sa_print(const struct sockaddr *sa, int include_hexdump)
196 char hdbuf[512], abuf[64];
198 const struct sockaddr_dl *sdl;
199 const struct sockaddr_in6 *sin6;
200 const struct sockaddr_in *sin;
203 switch (sa->sa_family) {
205 sin = (struct sockaddr_in *)sa;
206 inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf));
207 printf(" af=inet len=%d addr=%s", sa->sa_len, abuf);
210 sin6 = (struct sockaddr_in6 *)sa;
211 inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, sizeof(abuf));
212 int scope_id = sin6->sin6_scope_id;
213 printf(" af=inet6 len=%d addr=%s", sa->sa_len, abuf);
215 memset(ifbuf, 0, sizeof(ifbuf));
216 if_indextoname(scope_id, ifbuf);
217 printf(" scope_id=%d if_name=%s", scope_id, ifbuf);
221 sdl = (const struct sockaddr_dl *)sa;
222 int sdl_index = sdl->sdl_index;
223 if (sdl_index != 0) {
224 memset(ifbuf, 0, sizeof(ifbuf));
225 if_indextoname(sdl_index, ifbuf);
226 printf(" af=link len=%d sdl_index=%d if_name=%s", sdl->sdl_len, sdl_index, ifbuf);
229 char _ifname[IFNAMSIZ];
230 memcpy(_ifname, sdl->sdl_data, sdl->sdl_nlen);
231 _ifname[sdl->sdl_nlen] = '\0';
232 printf(" name=%s", _ifname);
236 const char *lladdr = LLADDR(sdl);
237 for (int i = 0; i < sdl->sdl_alen; i++) {
238 if (i + 1 < sdl->sdl_alen)
239 printf("%02X:", ((const unsigned char *)lladdr)[i]);
241 printf("%02X", ((const unsigned char *)lladdr)[i]);
246 printf(" af=%d len=%d", sa->sa_family, sa->sa_len);
249 if (include_hexdump) {
250 sa_print_hd(hdbuf, sizeof(hdbuf), ((char *)sa), sa->sa_len);
251 printf(" hd={%s}", hdbuf);
257 got message of size 240 on Mon Dec 16 09:23:31 2019
258 RTM_ADD: Add Route: len 240, pid: 25534, seq 2, errno 0, flags:<HOST,DONE,LLINFO,STATIC>
260 sockaddrs: <DST,GATEWAY>
264 rtsock_print_rtm(struct rt_msghdr *rtm)
270 gettimeofday(&tv, NULL);
271 localtime_r(&tv.tv_sec, &tm_res);
272 strftime(buf, sizeof(buf), "%F %T", &tm_res);
273 printf("Got message of size %hu on %s\n", rtm->rtm_msglen, buf);
276 rtsock_print_rtm_flags(flags_buf, sizeof(flags_buf), rtm->rtm_flags);
278 printf("%s: len %hu, pid: %d, seq %d, errno %d, flags: %s\n", msgtypes[rtm->rtm_type],
279 rtm->rtm_msglen, rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno, flags_buf);
281 if (rtm->rtm_inits > 0) {
282 _printb(flags_buf, sizeof(flags_buf), rtm->rtm_inits, metricnames);
283 printf("metrics: %s\n", flags_buf);
284 if (rtm->rtm_inits & RTV_MTU)
285 printf("mtu: %lu\n", rtm->rtm_rmx.rmx_mtu);
286 if (rtm->rtm_inits & RTV_EXPIRE) {
288 gettimeofday(&tv, NULL);
289 printf("expire: %d (%lu raw)\n",
290 (int)(rtm->rtm_rmx.rmx_expire - tv.tv_sec), rtm->rtm_rmx.rmx_expire);
294 _printb(flags_buf, sizeof(flags_buf), rtm->rtm_addrs, addrnames);
295 printf("sockaddrs: 0x%X %s\n", rtm->rtm_addrs, flags_buf);
297 char *ptr = (char *)(rtm + 1);
298 for (int i = 0; i < RTAX_MAX; i++) {
299 if (rtm->rtm_addrs & (1 << i)) {
300 struct sockaddr *sa = (struct sockaddr *)ptr;
304 ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
313 rtsock_print_ifa(struct ifa_msghdr *ifam)
319 gettimeofday(&tv, NULL);
320 localtime_r(&tv.tv_sec, &tm_res);
321 strftime(buf, sizeof(buf), "%F %T", &tm_res);
322 printf("Got message of size %hu on %s\n", ifam->ifam_msglen, buf);
325 _printb(flags_buf, sizeof(flags_buf), ifam->ifam_flags, routeflags);
327 printf("%s: len %hu, ifindex: %d, flags: %s\n", msgtypes[ifam->ifam_type],
328 ifam->ifam_msglen, ifam->ifam_index, flags_buf);
330 _printb(flags_buf, sizeof(flags_buf), ifam->ifam_addrs, addrnames);
331 printf("sockaddrs: 0x%X %s\n", ifam->ifam_addrs, flags_buf);
333 char *ptr = (char *)(ifam + 1);
334 for (int i = 0; i < RTAX_MAX; i++) {
335 if (ifam->ifam_addrs & (1 << i)) {
336 struct sockaddr *sa = (struct sockaddr *)ptr;
340 ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
349 rtsock_print_message_hd(struct rt_msghdr *rtm)
356 gettimeofday(&tv, NULL);
357 localtime_r(&tv.tv_sec, &tm_res);
358 strftime(buf, sizeof(buf), "%F %T", &tm_res);
359 printf("Got message type %s of size %hu on %s\n",
360 rtsock_print_cmdtype(rtm->rtm_type),
361 rtm->rtm_msglen, buf);
363 sa_print_hd(dumpbuf, sizeof(dumpbuf), (char *)rtm, rtm->rtm_msglen);
364 printf(" %s\n", dumpbuf);
368 rtsock_print_message(struct rt_msghdr *rtm)
371 switch (rtm->rtm_type) {
376 rtsock_print_rtm(rtm);
380 rtsock_print_ifa((struct ifa_msghdr *)rtm);
383 printf("unknown rt message type %X\n", rtm->rtm_type);
388 print_command(char *cmd)
392 FILE *fp = popen(cmd, "r");
394 while (fgets(line, sizeof(line), fp) != NULL)
401 rtsock_print_table(int family)
404 char *key = (family == AF_INET) ? "4" : "6";
406 snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%srnW", key);
407 printf("==== %s ===\n", cmdbuf);
408 print_command(cmdbuf);
409 snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%sonW", key);
410 printf("==== %s ===\n", cmdbuf);
411 print_command(cmdbuf);