xref: /freebsd/tests/sys/net/routing/rtsock_print.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
1775dc861SAlexander V. Chernikov /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3775dc861SAlexander V. Chernikov  *
4775dc861SAlexander V. Chernikov  * Copyright (c) 2019 Alexander V. Chernikov
5775dc861SAlexander V. Chernikov  *
6775dc861SAlexander V. Chernikov  * Redistribution and use in source and binary forms, with or without
7775dc861SAlexander V. Chernikov  * modification, are permitted provided that the following conditions
8775dc861SAlexander V. Chernikov  * are met:
9775dc861SAlexander V. Chernikov  * 1. Redistributions of source code must retain the above copyright
10775dc861SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer.
11775dc861SAlexander V. Chernikov  * 2. Redistributions in binary form must reproduce the above copyright
12775dc861SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer in the
13775dc861SAlexander V. Chernikov  *    documentation and/or other materials provided with the distribution.
14775dc861SAlexander V. Chernikov  *
15775dc861SAlexander V. Chernikov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16775dc861SAlexander V. Chernikov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17775dc861SAlexander V. Chernikov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18775dc861SAlexander V. Chernikov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19775dc861SAlexander V. Chernikov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20775dc861SAlexander V. Chernikov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21775dc861SAlexander V. Chernikov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22775dc861SAlexander V. Chernikov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23775dc861SAlexander V. Chernikov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24775dc861SAlexander V. Chernikov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25775dc861SAlexander V. Chernikov  * SUCH DAMAGE.
26775dc861SAlexander V. Chernikov  */
27775dc861SAlexander V. Chernikov 
28775dc861SAlexander V. Chernikov #ifndef _NET_ROUTING_RTSOCK_PRINT_H_
29775dc861SAlexander V. Chernikov #define _NET_ROUTING_RTSOCK_PRINT_H_
30775dc861SAlexander V. Chernikov 
31775dc861SAlexander V. Chernikov 
32775dc861SAlexander V. Chernikov #define	RLOG(_fmt, ...)	printf("%s: " _fmt "\n", __func__, ##__VA_ARGS__)
33775dc861SAlexander V. Chernikov #define	RLOG_ERRNO(_fmt, ...)	do {			\
34775dc861SAlexander V. Chernikov 	printf("%s: " _fmt, __func__, ##__VA_ARGS__);	\
35775dc861SAlexander V. Chernikov 	printf(": %s\n", strerror(errno));		\
36775dc861SAlexander V. Chernikov } while(0)
37775dc861SAlexander V. Chernikov 
38775dc861SAlexander V. Chernikov #define	RTSOCK_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...)	 do {	\
39775dc861SAlexander V. Chernikov 	if (!(_cond)) {						\
40775dc861SAlexander V. Chernikov 		printf("-- CONDITION FAILED, rtm dump  --\n\n");\
41e02d3fe7SAlexander V. Chernikov 		rtsock_print_message(_rtm);			\
42bddae5c8SAlexander V. Chernikov 		rtsock_print_table(AF_INET);			\
43bddae5c8SAlexander V. Chernikov 		rtsock_print_table(AF_INET6);			\
44bddae5c8SAlexander V. Chernikov 		printf("===================================\n");\
45e02d3fe7SAlexander V. Chernikov 	}							\
46e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__);		\
47e02d3fe7SAlexander V. Chernikov } while (0);
48e02d3fe7SAlexander V. Chernikov 
49e02d3fe7SAlexander V. Chernikov #define	RTSOCKHD_ATF_REQUIRE_MSG(_rtm, _cond, _fmt, ...) do {	\
50e02d3fe7SAlexander V. Chernikov 	if (!(_cond)) {						\
51e02d3fe7SAlexander V. Chernikov 		printf("-- CONDITION FAILED, rtm hexdump--\n\n");\
52e02d3fe7SAlexander V. Chernikov 		rtsock_print_message_hd(_rtm);				\
53775dc861SAlexander V. Chernikov 	}							\
54775dc861SAlexander V. Chernikov 	ATF_REQUIRE_MSG(_cond, _fmt, ##__VA_ARGS__);		\
55775dc861SAlexander V. Chernikov } while (0);
56775dc861SAlexander V. Chernikov 
57775dc861SAlexander V. Chernikov 
58775dc861SAlexander V. Chernikov /* from route.c */
59775dc861SAlexander V. Chernikov static const char *const msgtypes[] = {
60775dc861SAlexander V. Chernikov 	"",
61775dc861SAlexander V. Chernikov 	"RTM_ADD",
62775dc861SAlexander V. Chernikov 	"RTM_DELETE",
63775dc861SAlexander V. Chernikov 	"RTM_CHANGE",
64775dc861SAlexander V. Chernikov 	"RTM_GET",
65775dc861SAlexander V. Chernikov 	"RTM_LOSING",
66775dc861SAlexander V. Chernikov 	"RTM_REDIRECT",
67775dc861SAlexander V. Chernikov 	"RTM_MISS",
68775dc861SAlexander V. Chernikov 	"RTM_LOCK",
69775dc861SAlexander V. Chernikov 	"RTM_OLDADD",
70775dc861SAlexander V. Chernikov 	"RTM_OLDDEL",
71775dc861SAlexander V. Chernikov 	"RTM_RESOLVE",
72775dc861SAlexander V. Chernikov 	"RTM_NEWADDR",
73775dc861SAlexander V. Chernikov 	"RTM_DELADDR",
74775dc861SAlexander V. Chernikov 	"RTM_IFINFO",
75775dc861SAlexander V. Chernikov 	"RTM_NEWMADDR",
76775dc861SAlexander V. Chernikov 	"RTM_DELMADDR",
77775dc861SAlexander V. Chernikov 	"RTM_IFANNOUNCE",
78775dc861SAlexander V. Chernikov 	"RTM_IEEE80211",
79775dc861SAlexander V. Chernikov };
80775dc861SAlexander V. Chernikov 
81775dc861SAlexander V. Chernikov static const char metricnames[] =
82775dc861SAlexander V. Chernikov     "\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire"
83775dc861SAlexander V. Chernikov     "\1mtu";
84775dc861SAlexander V. Chernikov static const char routeflags[] =
85775dc861SAlexander V. Chernikov     "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"
86775dc861SAlexander V. Chernikov     "\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
87775dc861SAlexander V. Chernikov     "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"
88775dc861SAlexander V. Chernikov     "\024FIXEDMTU\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY";
89775dc861SAlexander V. Chernikov static const char ifnetflags[] =
90775dc861SAlexander V. Chernikov     "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
91775dc861SAlexander V. Chernikov     "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
92775dc861SAlexander V. Chernikov     "\017LINK2\020MULTICAST";
93775dc861SAlexander V. Chernikov static const char addrnames[] =
94775dc861SAlexander V. Chernikov     "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
95775dc861SAlexander V. Chernikov 
96775dc861SAlexander V. Chernikov static int
_printb(char * buf,size_t bufsize,int b,const char * str)97775dc861SAlexander V. Chernikov _printb(char *buf, size_t bufsize, int b, const char *str)
98775dc861SAlexander V. Chernikov {
99775dc861SAlexander V. Chernikov 	int i;
100775dc861SAlexander V. Chernikov 	int gotsome = 0;
101775dc861SAlexander V. Chernikov 
102775dc861SAlexander V. Chernikov 	char *pbuf = buf;
103775dc861SAlexander V. Chernikov 
104775dc861SAlexander V. Chernikov 	if (b == 0) {
105775dc861SAlexander V. Chernikov 		*pbuf = '\0';
106775dc861SAlexander V. Chernikov 		return (0);
107775dc861SAlexander V. Chernikov 	}
108775dc861SAlexander V. Chernikov 	while ((i = *str++) != 0) {
109775dc861SAlexander V. Chernikov 		if (b & (1 << (i-1))) {
110775dc861SAlexander V. Chernikov 			if (gotsome == 0)
111775dc861SAlexander V. Chernikov 				i = '<';
112775dc861SAlexander V. Chernikov 			else
113775dc861SAlexander V. Chernikov 				i = ',';
114775dc861SAlexander V. Chernikov 			*pbuf++ = i;
115775dc861SAlexander V. Chernikov 			gotsome = 1;
116775dc861SAlexander V. Chernikov 			for (; (i = *str) > 32; str++)
117775dc861SAlexander V. Chernikov 				*pbuf++ = i;
118775dc861SAlexander V. Chernikov 		} else
119775dc861SAlexander V. Chernikov 			while (*str > 32)
120775dc861SAlexander V. Chernikov 				str++;
121775dc861SAlexander V. Chernikov 	}
122775dc861SAlexander V. Chernikov 	if (gotsome)
123775dc861SAlexander V. Chernikov 		*pbuf++ = '>';
124775dc861SAlexander V. Chernikov 	*pbuf = '\0';
125775dc861SAlexander V. Chernikov 
126775dc861SAlexander V. Chernikov 	return (int)(pbuf - buf);
127775dc861SAlexander V. Chernikov }
128775dc861SAlexander V. Chernikov 
129775dc861SAlexander V. Chernikov const char *
rtsock_print_cmdtype(int cmd)130775dc861SAlexander V. Chernikov rtsock_print_cmdtype(int cmd)
131775dc861SAlexander V. Chernikov {
132775dc861SAlexander V. Chernikov 
133775dc861SAlexander V. Chernikov 	return (msgtypes[cmd]);
134775dc861SAlexander V. Chernikov }
135775dc861SAlexander V. Chernikov 
136ac0bea76SAlexander V. Chernikov char *
rtsock_print_rtm_flags(char * buf,int buflen,int rtm_flags)137ac0bea76SAlexander V. Chernikov rtsock_print_rtm_flags(char *buf, int buflen, int rtm_flags)
138ac0bea76SAlexander V. Chernikov {
139ac0bea76SAlexander V. Chernikov 
140ac0bea76SAlexander V. Chernikov 	_printb(buf, buflen, rtm_flags, routeflags);
141ac0bea76SAlexander V. Chernikov 	return (buf);
142ac0bea76SAlexander V. Chernikov }
143ac0bea76SAlexander V. Chernikov 
144775dc861SAlexander V. Chernikov 
145775dc861SAlexander V. Chernikov #define	_PRINTX(fmt, ...)	do {				\
146775dc861SAlexander V. Chernikov 	one_len = snprintf(ptr, rem_len, fmt, __VA_ARGS__);	\
147775dc861SAlexander V. Chernikov 	ptr += one_len;						\
148775dc861SAlexander V. Chernikov 	rem_len -= one_len;					\
149775dc861SAlexander V. Chernikov } while(0)
150775dc861SAlexander V. Chernikov 
151775dc861SAlexander V. Chernikov 
152775dc861SAlexander V. Chernikov void
sa_print_hd(char * buf,int buflen,const char * data,int len)153775dc861SAlexander V. Chernikov sa_print_hd(char *buf, int buflen, const char *data, int len)
154775dc861SAlexander V. Chernikov {
155775dc861SAlexander V. Chernikov 	char *ptr;
156775dc861SAlexander V. Chernikov 	int one_len, rem_len;
157775dc861SAlexander V. Chernikov 
158775dc861SAlexander V. Chernikov 	ptr = buf;
159775dc861SAlexander V. Chernikov 	rem_len = buflen;
160775dc861SAlexander V. Chernikov 
161775dc861SAlexander V. Chernikov 	const char *last_char = NULL;
162775dc861SAlexander V. Chernikov 	unsigned char v;
163775dc861SAlexander V. Chernikov 	int repeat_count = 0;
164775dc861SAlexander V. Chernikov 	for (int i = 0; i < len; i++) {
165e02d3fe7SAlexander V. Chernikov 		if (last_char && *last_char == data[i] && data[i] == 0x00) {
166775dc861SAlexander V. Chernikov 			repeat_count++;
167775dc861SAlexander V. Chernikov 			continue;
168775dc861SAlexander V. Chernikov 		}
169775dc861SAlexander V. Chernikov 
170775dc861SAlexander V. Chernikov 		if (repeat_count > 1) {
171775dc861SAlexander V. Chernikov 			_PRINTX("{%d}", repeat_count);
172775dc861SAlexander V. Chernikov 			repeat_count = 0;
173775dc861SAlexander V. Chernikov 		}
174775dc861SAlexander V. Chernikov 
175775dc861SAlexander V. Chernikov 		v = ((const unsigned char *)data)[i];
176775dc861SAlexander V. Chernikov 		if (last_char == NULL)
177e02d3fe7SAlexander V. Chernikov 			_PRINTX("x%02X", v);
178775dc861SAlexander V. Chernikov 		else
179e02d3fe7SAlexander V. Chernikov 			_PRINTX(", x%02X", v);
180775dc861SAlexander V. Chernikov 
181775dc861SAlexander V. Chernikov 		last_char = &data[i];
182775dc861SAlexander V. Chernikov 		repeat_count = 1;
183775dc861SAlexander V. Chernikov 	}
184775dc861SAlexander V. Chernikov 
185775dc861SAlexander V. Chernikov 	if (repeat_count > 1)
186775dc861SAlexander V. Chernikov 		snprintf(ptr, rem_len, "{%d}", repeat_count);
187775dc861SAlexander V. Chernikov }
188775dc861SAlexander V. Chernikov 
189775dc861SAlexander V. Chernikov #undef _PRINTX
190775dc861SAlexander V. Chernikov 
191775dc861SAlexander V. Chernikov void
sa_print(const struct sockaddr * sa,int include_hexdump)192775dc861SAlexander V. Chernikov sa_print(const struct sockaddr *sa, int include_hexdump)
193775dc861SAlexander V. Chernikov {
194775dc861SAlexander V. Chernikov 	char hdbuf[512], abuf[64];
195775dc861SAlexander V. Chernikov 	char ifbuf[128];
196775dc861SAlexander V. Chernikov 	const struct sockaddr_dl *sdl;
197775dc861SAlexander V. Chernikov 	const struct sockaddr_in6 *sin6;
198775dc861SAlexander V. Chernikov 	const struct sockaddr_in *sin;
199775dc861SAlexander V. Chernikov 	int i;
200775dc861SAlexander V. Chernikov 
201775dc861SAlexander V. Chernikov 	switch (sa->sa_family) {
202775dc861SAlexander V. Chernikov 		case AF_INET:
203775dc861SAlexander V. Chernikov 			sin = (struct sockaddr_in *)sa;
204775dc861SAlexander V. Chernikov 			inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf));
205775dc861SAlexander V. Chernikov 			printf(" af=inet len=%d addr=%s", sa->sa_len, abuf);
206775dc861SAlexander V. Chernikov 			break;
207775dc861SAlexander V. Chernikov 		case AF_INET6:
208775dc861SAlexander V. Chernikov 			sin6 = (struct sockaddr_in6 *)sa;
209775dc861SAlexander V. Chernikov 			inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, sizeof(abuf));
210775dc861SAlexander V. Chernikov 			int scope_id = sin6->sin6_scope_id;
211775dc861SAlexander V. Chernikov 			printf(" af=inet6 len=%d addr=%s", sa->sa_len, abuf);
212775dc861SAlexander V. Chernikov 			if (scope_id != 0) {
213775dc861SAlexander V. Chernikov 				memset(ifbuf, 0, sizeof(ifbuf));
214775dc861SAlexander V. Chernikov 				if_indextoname(scope_id, ifbuf);
215775dc861SAlexander V. Chernikov 				printf(" scope_id=%d if_name=%s", scope_id, ifbuf);
216775dc861SAlexander V. Chernikov 			}
217775dc861SAlexander V. Chernikov 			break;
218775dc861SAlexander V. Chernikov 		case AF_LINK:
219775dc861SAlexander V. Chernikov 			sdl = (const struct sockaddr_dl *)sa;
220775dc861SAlexander V. Chernikov 			int sdl_index = sdl->sdl_index;
221775dc861SAlexander V. Chernikov 			if (sdl_index != 0) {
222775dc861SAlexander V. Chernikov 				memset(ifbuf, 0, sizeof(ifbuf));
223775dc861SAlexander V. Chernikov 				if_indextoname(sdl_index, ifbuf);
224775dc861SAlexander V. Chernikov 				printf(" af=link len=%d sdl_index=%d if_name=%s", sdl->sdl_len, sdl_index, ifbuf);
225775dc861SAlexander V. Chernikov 			}
226775dc861SAlexander V. Chernikov 			if (sdl->sdl_nlen) {
227775dc861SAlexander V. Chernikov 				char _ifname[IFNAMSIZ];
228775dc861SAlexander V. Chernikov 				memcpy(_ifname, sdl->sdl_data, sdl->sdl_nlen);
229775dc861SAlexander V. Chernikov 				_ifname[sdl->sdl_nlen] = '\0';
230775dc861SAlexander V. Chernikov 				printf(" name=%s", _ifname);
231775dc861SAlexander V. Chernikov 			}
232775dc861SAlexander V. Chernikov 			if (sdl->sdl_alen) {
233775dc861SAlexander V. Chernikov 				printf(" addr=");
234775dc861SAlexander V. Chernikov 				const char *lladdr = LLADDR(sdl);
235775dc861SAlexander V. Chernikov 				for (int i = 0; i < sdl->sdl_alen; i++) {
236775dc861SAlexander V. Chernikov 					if (i + 1 < sdl->sdl_alen)
237775dc861SAlexander V. Chernikov 						printf("%02X:", ((const unsigned char *)lladdr)[i]);
238775dc861SAlexander V. Chernikov 					else
239775dc861SAlexander V. Chernikov 						printf("%02X", ((const unsigned char *)lladdr)[i]);
240775dc861SAlexander V. Chernikov 				}
241775dc861SAlexander V. Chernikov 			}
242775dc861SAlexander V. Chernikov 			break;
243775dc861SAlexander V. Chernikov 		default:
244775dc861SAlexander V. Chernikov 			printf(" af=%d len=%d", sa->sa_family, sa->sa_len);
245775dc861SAlexander V. Chernikov 	}
246775dc861SAlexander V. Chernikov 
247775dc861SAlexander V. Chernikov 	if (include_hexdump) {
248775dc861SAlexander V. Chernikov 		sa_print_hd(hdbuf, sizeof(hdbuf), ((char *)sa), sa->sa_len);
249775dc861SAlexander V. Chernikov 		printf(" hd={%s}", hdbuf);
250775dc861SAlexander V. Chernikov 	}
251775dc861SAlexander V. Chernikov 	printf("\n");
252775dc861SAlexander V. Chernikov }
253775dc861SAlexander V. Chernikov 
254775dc861SAlexander V. Chernikov /*
255775dc861SAlexander V. Chernikov got message of size 240 on Mon Dec 16 09:23:31 2019
256775dc861SAlexander V. Chernikov RTM_ADD: Add Route: len 240, pid: 25534, seq 2, errno 0, flags:<HOST,DONE,LLINFO,STATIC>
257775dc861SAlexander V. Chernikov locks:  inits:
258775dc861SAlexander V. Chernikov sockaddrs: <DST,GATEWAY>
259775dc861SAlexander V. Chernikov */
260775dc861SAlexander V. Chernikov 
261775dc861SAlexander V. Chernikov void
rtsock_print_rtm(struct rt_msghdr * rtm)262775dc861SAlexander V. Chernikov rtsock_print_rtm(struct rt_msghdr *rtm)
263775dc861SAlexander V. Chernikov {
264775dc861SAlexander V. Chernikov 	struct timeval tv;
265775dc861SAlexander V. Chernikov 	struct tm tm_res;
266775dc861SAlexander V. Chernikov 	char buf[64];
267775dc861SAlexander V. Chernikov 
268775dc861SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
269775dc861SAlexander V. Chernikov 	localtime_r(&tv.tv_sec, &tm_res);
270775dc861SAlexander V. Chernikov 	strftime(buf, sizeof(buf), "%F %T", &tm_res);
271775dc861SAlexander V. Chernikov 	printf("Got message of size %hu on %s\n", rtm->rtm_msglen, buf);
272775dc861SAlexander V. Chernikov 
273775dc861SAlexander V. Chernikov 	char flags_buf[256];
274ac0bea76SAlexander V. Chernikov 	rtsock_print_rtm_flags(flags_buf, sizeof(flags_buf), rtm->rtm_flags);
275775dc861SAlexander V. Chernikov 
276775dc861SAlexander V. Chernikov 	printf("%s: len %hu, pid: %d, seq %d, errno %d, flags: %s\n", msgtypes[rtm->rtm_type],
277775dc861SAlexander V. Chernikov 		rtm->rtm_msglen, rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno, flags_buf);
278775dc861SAlexander V. Chernikov 
279e02d3fe7SAlexander V. Chernikov 	if (rtm->rtm_inits > 0) {
280e02d3fe7SAlexander V. Chernikov 		_printb(flags_buf, sizeof(flags_buf), rtm->rtm_inits, metricnames);
281e02d3fe7SAlexander V. Chernikov 		printf("metrics: %s\n", flags_buf);
282e02d3fe7SAlexander V. Chernikov 		if (rtm->rtm_inits & RTV_MTU)
283e02d3fe7SAlexander V. Chernikov 			printf("mtu: %lu\n", rtm->rtm_rmx.rmx_mtu);
284e02d3fe7SAlexander V. Chernikov 		if (rtm->rtm_inits & RTV_EXPIRE) {
285e02d3fe7SAlexander V. Chernikov 			struct timeval tv;
286e02d3fe7SAlexander V. Chernikov 			gettimeofday(&tv, NULL);
287e02d3fe7SAlexander V. Chernikov 			printf("expire: %d (%lu raw)\n",
288e02d3fe7SAlexander V. Chernikov 			    (int)(rtm->rtm_rmx.rmx_expire - tv.tv_sec), rtm->rtm_rmx.rmx_expire);
289e02d3fe7SAlexander V. Chernikov 		}
290e02d3fe7SAlexander V. Chernikov 	}
291e02d3fe7SAlexander V. Chernikov 
292775dc861SAlexander V. Chernikov 	_printb(flags_buf, sizeof(flags_buf), rtm->rtm_addrs, addrnames);
293775dc861SAlexander V. Chernikov 	printf("sockaddrs: 0x%X %s\n", rtm->rtm_addrs, flags_buf);
294775dc861SAlexander V. Chernikov 
295775dc861SAlexander V. Chernikov 	char *ptr = (char *)(rtm + 1);
296775dc861SAlexander V. Chernikov 	for (int i = 0; i < RTAX_MAX; i++) {
297775dc861SAlexander V. Chernikov 		if (rtm->rtm_addrs & (1 << i)) {
298775dc861SAlexander V. Chernikov 			struct sockaddr *sa = (struct sockaddr *)ptr;
299775dc861SAlexander V. Chernikov 			sa_print(sa, 1);
300775dc861SAlexander V. Chernikov 
301775dc861SAlexander V. Chernikov 			/* add */
302775dc861SAlexander V. Chernikov 			ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
303775dc861SAlexander V. Chernikov 		}
304775dc861SAlexander V. Chernikov 	}
305775dc861SAlexander V. Chernikov 
306775dc861SAlexander V. Chernikov 	printf("\n");
307775dc861SAlexander V. Chernikov 
308775dc861SAlexander V. Chernikov }
309775dc861SAlexander V. Chernikov 
310e02d3fe7SAlexander V. Chernikov void
rtsock_print_ifa(struct ifa_msghdr * ifam)311e02d3fe7SAlexander V. Chernikov rtsock_print_ifa(struct ifa_msghdr *ifam)
312e02d3fe7SAlexander V. Chernikov {
313e02d3fe7SAlexander V. Chernikov 	struct timeval tv;
314e02d3fe7SAlexander V. Chernikov 	struct tm tm_res;
315e02d3fe7SAlexander V. Chernikov 	char buf[64];
316e02d3fe7SAlexander V. Chernikov 
317e02d3fe7SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
318e02d3fe7SAlexander V. Chernikov 	localtime_r(&tv.tv_sec, &tm_res);
319e02d3fe7SAlexander V. Chernikov 	strftime(buf, sizeof(buf), "%F %T", &tm_res);
320e02d3fe7SAlexander V. Chernikov 	printf("Got message of size %hu on %s\n", ifam->ifam_msglen, buf);
321e02d3fe7SAlexander V. Chernikov 
322e02d3fe7SAlexander V. Chernikov 	char flags_buf[256];
323e02d3fe7SAlexander V. Chernikov 	_printb(flags_buf, sizeof(flags_buf), ifam->ifam_flags, routeflags);
324e02d3fe7SAlexander V. Chernikov 
325e02d3fe7SAlexander V. Chernikov 	printf("%s: len %hu, ifindex: %d, flags: %s\n", msgtypes[ifam->ifam_type],
326e02d3fe7SAlexander V. Chernikov 		ifam->ifam_msglen, ifam->ifam_index, flags_buf);
327e02d3fe7SAlexander V. Chernikov 
328e02d3fe7SAlexander V. Chernikov 	_printb(flags_buf, sizeof(flags_buf), ifam->ifam_addrs, addrnames);
329e02d3fe7SAlexander V. Chernikov 	printf("sockaddrs: 0x%X %s\n", ifam->ifam_addrs, flags_buf);
330e02d3fe7SAlexander V. Chernikov 
331e02d3fe7SAlexander V. Chernikov 	char *ptr = (char *)(ifam + 1);
332e02d3fe7SAlexander V. Chernikov 	for (int i = 0; i < RTAX_MAX; i++) {
333e02d3fe7SAlexander V. Chernikov 		if (ifam->ifam_addrs & (1 << i)) {
334e02d3fe7SAlexander V. Chernikov 			struct sockaddr *sa = (struct sockaddr *)ptr;
335e02d3fe7SAlexander V. Chernikov 			sa_print(sa, 1);
336e02d3fe7SAlexander V. Chernikov 
337e02d3fe7SAlexander V. Chernikov 			/* add */
338e02d3fe7SAlexander V. Chernikov 			ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
339e02d3fe7SAlexander V. Chernikov 		}
340e02d3fe7SAlexander V. Chernikov 	}
341e02d3fe7SAlexander V. Chernikov 
342e02d3fe7SAlexander V. Chernikov 	printf("\n");
343e02d3fe7SAlexander V. Chernikov 
344e02d3fe7SAlexander V. Chernikov }
345e02d3fe7SAlexander V. Chernikov 
346e02d3fe7SAlexander V. Chernikov void
rtsock_print_message_hd(struct rt_msghdr * rtm)347e02d3fe7SAlexander V. Chernikov rtsock_print_message_hd(struct rt_msghdr *rtm)
348e02d3fe7SAlexander V. Chernikov {
349e02d3fe7SAlexander V. Chernikov 	struct timeval tv;
350e02d3fe7SAlexander V. Chernikov 	struct tm tm_res;
351e02d3fe7SAlexander V. Chernikov 	char buf[64];
352e02d3fe7SAlexander V. Chernikov 	char dumpbuf[2048];
353e02d3fe7SAlexander V. Chernikov 
354e02d3fe7SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
355e02d3fe7SAlexander V. Chernikov 	localtime_r(&tv.tv_sec, &tm_res);
356e02d3fe7SAlexander V. Chernikov 	strftime(buf, sizeof(buf), "%F %T", &tm_res);
357e02d3fe7SAlexander V. Chernikov 	printf("Got message type %s of size %hu on %s\n",
358e02d3fe7SAlexander V. Chernikov 	    rtsock_print_cmdtype(rtm->rtm_type),
359e02d3fe7SAlexander V. Chernikov 	    rtm->rtm_msglen, buf);
360e02d3fe7SAlexander V. Chernikov 
361e02d3fe7SAlexander V. Chernikov 	sa_print_hd(dumpbuf, sizeof(dumpbuf), (char *)rtm, rtm->rtm_msglen);
362e02d3fe7SAlexander V. Chernikov 	printf(" %s\n", dumpbuf);
363e02d3fe7SAlexander V. Chernikov }
364e02d3fe7SAlexander V. Chernikov 
365e02d3fe7SAlexander V. Chernikov void
rtsock_print_message(struct rt_msghdr * rtm)366e02d3fe7SAlexander V. Chernikov rtsock_print_message(struct rt_msghdr *rtm)
367e02d3fe7SAlexander V. Chernikov {
368e02d3fe7SAlexander V. Chernikov 
369e02d3fe7SAlexander V. Chernikov 	switch (rtm->rtm_type) {
370e02d3fe7SAlexander V. Chernikov 	case RTM_GET:
371e02d3fe7SAlexander V. Chernikov 	case RTM_ADD:
372e02d3fe7SAlexander V. Chernikov 	case RTM_DELETE:
373e02d3fe7SAlexander V. Chernikov 	case RTM_CHANGE:
374e02d3fe7SAlexander V. Chernikov 		rtsock_print_rtm(rtm);
375e02d3fe7SAlexander V. Chernikov 		break;
376e02d3fe7SAlexander V. Chernikov 	case RTM_DELADDR:
377e02d3fe7SAlexander V. Chernikov 	case RTM_NEWADDR:
378e02d3fe7SAlexander V. Chernikov 		rtsock_print_ifa((struct ifa_msghdr *)rtm);
379e02d3fe7SAlexander V. Chernikov 		break;
380e02d3fe7SAlexander V. Chernikov 	default:
381e02d3fe7SAlexander V. Chernikov 		printf("unknown rt message type %X\n", rtm->rtm_type);
382e02d3fe7SAlexander V. Chernikov 	}
383e02d3fe7SAlexander V. Chernikov }
384e02d3fe7SAlexander V. Chernikov 
385bddae5c8SAlexander V. Chernikov static void
print_command(char * cmd)386bddae5c8SAlexander V. Chernikov print_command(char *cmd)
387bddae5c8SAlexander V. Chernikov {
388bddae5c8SAlexander V. Chernikov 	char line[1024];
389bddae5c8SAlexander V. Chernikov 
390bddae5c8SAlexander V. Chernikov 	FILE *fp = popen(cmd, "r");
391bddae5c8SAlexander V. Chernikov 	if (fp != NULL) {
392bddae5c8SAlexander V. Chernikov 		while (fgets(line, sizeof(line), fp) != NULL)
393bddae5c8SAlexander V. Chernikov 			printf("%s", line);
394bddae5c8SAlexander V. Chernikov 		pclose(fp);
395bddae5c8SAlexander V. Chernikov 	}
396bddae5c8SAlexander V. Chernikov }
397bddae5c8SAlexander V. Chernikov 
398bddae5c8SAlexander V. Chernikov void
rtsock_print_table(int family)399bddae5c8SAlexander V. Chernikov rtsock_print_table(int family)
400bddae5c8SAlexander V. Chernikov {
401bddae5c8SAlexander V. Chernikov 	char cmdbuf[128];
402bddae5c8SAlexander V. Chernikov 	char *key = (family == AF_INET) ? "4" : "6";
403bddae5c8SAlexander V. Chernikov 
404bddae5c8SAlexander V. Chernikov 	snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%srnW", key);
405bddae5c8SAlexander V. Chernikov 	printf("==== %s ===\n", cmdbuf);
406bddae5c8SAlexander V. Chernikov 	print_command(cmdbuf);
407bddae5c8SAlexander V. Chernikov 	snprintf(cmdbuf, sizeof(cmdbuf), "/usr/bin/netstat -%sonW", key);
408bddae5c8SAlexander V. Chernikov 	printf("==== %s ===\n", cmdbuf);
409bddae5c8SAlexander V. Chernikov 	print_command(cmdbuf);
410bddae5c8SAlexander V. Chernikov }
411bddae5c8SAlexander V. Chernikov 
412775dc861SAlexander V. Chernikov #endif
413