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