1#
2# $FreeBSD$
3#
4
5document netstat-anr
6Print routing tables as 'netstat -anr' does.
7end
8
9set $debug = 0
10
11set $AF_INET = 2
12set $AF_LINK = 18
13
14set $RNF_ROOT = 2
15set $RNF_ACTIVE = 4
16
17set $RTF_UP		= 0x1
18set $RTF_GATEWAY	= 0x2
19set $RTF_HOST		= 0x4
20set $RTF_STATIC		= 0x800
21
22#
23# XXX: alas, we can't script "show endian"
24#
25if (machine[0] == 'a' && machine[1] == 'm' && machine[2] == 'd') || \
26   (machine[0] == 'i' && machine[1] == '3' && machine[2] == '8')
27	set $byteswap = 1
28else
29	set $byteswap = 0
30end
31
32define routename
33	if ($byteswap)
34		printf "%u.%u.%u.%u", \
35		    $arg0 & 0xff, ($arg0 >> 8) & 0xff, \
36		    ($arg0 >> 16) & 0xff, ($arg0 >> 24) & 0xff
37	else
38		printf "%u.%u.%u.%u", \
39		    ($arg0 >> 24) & 0xff, ($arg0 >> 16) & 0xff, \
40		    ($arg0 >> 8) & 0xff, $arg0 & 0xff
41	end
42end
43
44define domask
45	set $i = 0
46	set $b = 0
47	while $b < 32
48		if ($arg0 & (1 << $b))
49			set $i = $i + 1
50		end
51		set $b = $b + 1
52	end
53	printf "/%d", $i
54end
55
56define p_flags
57	if ($arg0 & $RTF_UP)
58		printf "U"
59	end
60	if ($arg0 & $RTF_GATEWAY)
61		printf "G"
62	end
63	if ($arg0 & $RTF_HOST)
64		printf "H"
65	end
66	if ($arg0 & $RTF_STATIC)
67		printf "S"
68	end
69end
70
71define p_sockaddr
72	set $sa = (struct sockaddr *)$arg0
73	set $flags = $arg2
74	if ($sa->sa_family == $AF_INET)
75		set $sin = (struct sockaddr_in *)$arg0
76		set $mask = (struct sockaddr_in *)$arg1
77		if ($flags & $RTF_HOST)
78			routename $sin->sin_addr.s_addr
79		else
80			routename $sin->sin_addr.s_addr
81			if ($mask != 0)
82				domask $mask->sin_addr.s_addr
83			else
84				domask 0
85			end
86		end
87	end
88	if ($sa->sa_family == $AF_LINK)
89		set $sdl = (struct sockaddr_dl *)$arg0
90		if ($sdl->sdl_nlen == 0 && $sdl->sdl_alen == 0 && \
91		    $sdl->sdl_slen == 0)
92			printf "link#%d", $sdl->sdl_index
93		end
94	end
95end
96
97define p_rtentry
98	set $rte = (struct rtentry *)$arg0
99	set $rn = (struct radix_node *)$arg0
100	set $sa = ((struct sockaddr **)($rn->rn_u.rn_leaf.rn_Key))
101	set $sam = ((struct sockaddr **)($rn->rn_u.rn_leaf.rn_Mask))
102	set $gw = $rte->rt_gateway
103
104	p_sockaddr $sa $sam $rte->rt_flags
105	printf "\t"
106	p_sockaddr $gw 0 $RTF_HOST
107	printf "\t"
108	p_flags $rte->rt_flags
109	printf "\t"
110	if ($rte->rt_ifp != 0)
111		printf "%s", $rte->rt_ifp->if_xname
112	end
113	printf "\n"
114end
115
116define p_rtree
117	set $rn_$arg0 = (struct radix_node *)$arg1
118	set $left_$arg0 = $arg0 + 1
119	set $right_$arg0 = $arg0 + 2
120	set $duped_$arg0 = $arg0 + 3
121
122	if ($rn_$arg0->rn_bit < 0 || ($rn_$arg0->rn_flags & $RNF_ACTIVE) == 0)
123		if ($debug == 1)
124			printf "print "
125			p $rn_$arg0
126		end
127		if (($rn_$arg0->rn_flags & ($RNF_ACTIVE | $RNF_ROOT)) == \
128		    $RNF_ACTIVE)
129			p_rtentry $rn_$arg0
130		end
131		if (($rn_$arg0->rn_flags & $RNF_ACTIVE) != 0 && \
132		    $rn_$arg0->rn_u.rn_leaf.rn_Dupedkey != 0)
133			if ($debug == 1)
134				printf "duped "
135				p $rn_$arg0
136			end
137			p_rtree $duped_$arg0 $rn_$arg0->rn_u.rn_leaf.rn_Dupedkey
138		end
139	else
140		if ($rn_$arg0->rn_u.rn_node.rn_R != 0)
141			if ($debug == 1)
142				printf "right "
143				p $rn_$arg0
144			end
145			p_rtree $right_$arg0 $rn_$arg0->rn_u.rn_node.rn_R
146		end
147		if ($rn_$arg0->rn_u.rn_node.rn_L != 0)
148			if ($debug == 1)
149				printf "left "
150				p $rn_$arg0
151			end
152			p_rtree $left_$arg0 $rn_$arg0->rn_u.rn_node.rn_L
153		end
154	end
155end
156
157define netstat-anr
158	printf "Routing tables\n\nInternet:\n"
159	set $af = $AF_INET
160	set $rt = (struct radix_node_head **)rt_tables + $af
161	printf "Destination\tGateway\tFlags\tNetif\n"
162	p_rtree 0 $rt->rnh_treetop
163end
164