subnet fixes
[unix-history] / usr / src / usr.bin / netstat / route.c
CommitLineData
3537c4ea 1#ifndef lint
f6d7bbb7 2static char sccsid[] = "@(#)route.c 4.8 84/05/17";
3537c4ea
SL
3#endif
4
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <sys/mbuf.h>
44906619 8
3537c4ea 9#include <net/if.h>
3537c4ea
SL
10#define KERNEL /* to get routehash and RTHASHSIZ */
11#include <net/route.h>
44906619
SL
12#include <netinet/in.h>
13
3537c4ea
SL
14#include <netdb.h>
15
16extern int kmem;
17extern int nflag;
18extern char *routename();
19
20/*
21 * Definitions for showing gateway flags.
22 */
23struct bits {
24 short b_mask;
25 char b_val;
26} bits[] = {
27 { RTF_UP, 'U' },
28 { RTF_GATEWAY, 'G' },
29 { RTF_HOST, 'H' },
30 { 0 }
31};
32
33/*
34 * Print routing tables.
35 */
36routepr(hostaddr, netaddr)
37 off_t hostaddr, netaddr;
38{
39 struct mbuf mb;
40 register struct rtentry *rt;
41 register struct mbuf *m;
42 register struct bits *p;
43 struct netent *np;
44 struct hostent *hp;
45 char name[16], *flags;
46 struct mbuf *routehash[RTHASHSIZ];
47 struct ifnet ifnet;
48 int first = 1, i, doinghost = 1;
49
50 if (hostaddr == 0) {
51 printf("rthost: symbol not in namelist\n");
52 return;
53 }
54 if (netaddr == 0) {
55 printf("rtnet: symbol not in namelist\n");
56 return;
57 }
58 klseek(kmem, hostaddr, 0);
59 read(kmem, routehash, sizeof (routehash));
60 printf("Routing tables\n");
61 printf("%-15.15s %-15.15s %-8.8s %-6.6s %-10.10s %s\n",
62 "Destination", "Gateway",
63 "Flags", "Refcnt", "Use", "Interface");
64again:
65 for (i = 0; i < RTHASHSIZ; i++) {
66 if (routehash[i] == 0)
67 continue;
68 m = routehash[i];
69 while (m) {
70 struct sockaddr_in *sin;
71
72 klseek(kmem, m, 0);
73 read(kmem, &mb, sizeof (mb));
74 rt = mtod(&mb, struct rtentry *);
75 sin = (struct sockaddr_in *)&rt->rt_dst;
bbd2d21e
SL
76 printf("%-15.15s ",
77 sin->sin_addr.s_addr ?
78 routename(sin->sin_addr) : "default");
3537c4ea
SL
79 sin = (struct sockaddr_in *)&rt->rt_gateway;
80 printf("%-15.15s ", routename(sin->sin_addr));
81 for (flags = name, p = bits; p->b_mask; p++)
82 if (p->b_mask & rt->rt_flags)
83 *flags++ = p->b_val;
84 *flags = '\0';
85 printf("%-8.8s %-6d %-10d ", name,
86 rt->rt_refcnt, rt->rt_use);
87 if (rt->rt_ifp == 0) {
88 putchar('\n');
89 m = mb.m_next;
90 continue;
91 }
92 klseek(kmem, rt->rt_ifp, 0);
93 read(kmem, &ifnet, sizeof (ifnet));
94 klseek(kmem, (int)ifnet.if_name, 0);
95 read(kmem, name, 16);
96 printf("%s%d\n", name, ifnet.if_unit);
97 m = mb.m_next;
98 }
99 }
100 if (doinghost) {
101 klseek(kmem, netaddr, 0);
102 read(kmem, routehash, sizeof (routehash));
103 doinghost = 0;
104 goto again;
105 }
106}
107
108char *
109routename(in)
110 struct in_addr in;
111{
112 char *cp = 0;
113 static char line[50];
40f48772
MK
114 struct hostent *hp;
115 struct netent *np;
116 int lna, net, subnet;
3537c4ea 117
444a708d 118 net = inet_netof(in);
40f48772 119 subnet = inet_subnetof(in);
444a708d 120 lna = inet_lnaof(in);
3537c4ea
SL
121 if (!nflag) {
122 if (lna == INADDR_ANY) {
40f48772 123 np = getnetbyaddr(net, AF_INET);
3537c4ea
SL
124 if (np)
125 cp = np->n_name;
40f48772
MK
126 else if (net == 0)
127 cp = "default";
128 } else if ((subnet != net) && ((lna & 0xff) == 0) &&
129 (np = getnetbyaddr(subnet, AF_INET))) {
130 struct in_addr subnaddr, inet_makeaddr();
131 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
132 if (bcmp(&in, &subnaddr, sizeof(in)) == 0)
133 cp = np->n_name;
f6d7bbb7
MK
134 else
135 goto host;
3537c4ea 136 } else {
f6d7bbb7 137host:
3394f0b5
SL
138 hp = gethostbyaddr(&in, sizeof (struct in_addr),
139 AF_INET);
3537c4ea
SL
140 if (hp)
141 cp = hp->h_name;
142 }
143 }
144 if (cp)
145 strcpy(line, cp);
146 else {
147 u_char *ucp = (u_char *)&in;
148 if (lna == INADDR_ANY)
149 sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]);
150 else
151 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1],
152 ucp[2], ucp[3]);
153 }
154 return (line);
155}
bbd2d21e
SL
156/*
157 * Print routing statistics
158 */
159rt_stats(off)
160 off_t off;
161{
162 struct rtstat rtstat;
163
164 if (off == 0) {
165 printf("rtstat: symbol not in namelist\n");
166 return;
167 }
168 klseek(kmem, off, 0);
169 read(kmem, (char *)&rtstat, sizeof (rtstat));
170 printf("routing:\n");
171 printf("\t%d bad routing redirect%s\n",
172 rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
173 printf("\t%d dynamically created route%s\n",
174 rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
175 printf("\t%d new gateway%s due to redirects\n",
176 rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
177 printf("\t%d destination%s found unreachable\n",
178 rtstat.rts_unreach, plural(rtstat.rts_unreach));
179 printf("\t%d use%s of a wildcard route\n",
180 rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
181}
40f48772
MK
182
183/*
184 * Return the possible subnetwork number from an internet address.
185 * If the address is of the form of a subnet address (most significant
186 * bit of the host part is set), believe the subnet exists.
187 * Otherwise, return the network number.
188 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
189 * INSIDE OF THE HOST PART. We can only believe this if we have other
190 * information (e.g., we can find a name for this number).
191 */
192inet_subnetof(in)
193 struct in_addr in;
194{
195 register u_long i = ntohl(in.s_addr);
196
197 if (IN_CLASSA(i)) {
198 if (IN_SUBNETA(i))
199 return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
200 else
201 return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
202 } else if (IN_CLASSB(i)) {
203 if (IN_SUBNETB(i))
204 return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
205 else
206 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
207 } else
208 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
209}