logic error
[unix-history] / usr / src / usr.bin / netstat / route.c
CommitLineData
3537c4ea 1#ifndef lint
40f48772 2static char sccsid[] = "@(#)route.c 4.7 84/05/11";
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;
3537c4ea 134 } else {
3394f0b5
SL
135 hp = gethostbyaddr(&in, sizeof (struct in_addr),
136 AF_INET);
3537c4ea
SL
137 if (hp)
138 cp = hp->h_name;
139 }
140 }
141 if (cp)
142 strcpy(line, cp);
143 else {
144 u_char *ucp = (u_char *)&in;
145 if (lna == INADDR_ANY)
146 sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]);
147 else
148 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1],
149 ucp[2], ucp[3]);
150 }
151 return (line);
152}
bbd2d21e
SL
153/*
154 * Print routing statistics
155 */
156rt_stats(off)
157 off_t off;
158{
159 struct rtstat rtstat;
160
161 if (off == 0) {
162 printf("rtstat: symbol not in namelist\n");
163 return;
164 }
165 klseek(kmem, off, 0);
166 read(kmem, (char *)&rtstat, sizeof (rtstat));
167 printf("routing:\n");
168 printf("\t%d bad routing redirect%s\n",
169 rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
170 printf("\t%d dynamically created route%s\n",
171 rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
172 printf("\t%d new gateway%s due to redirects\n",
173 rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
174 printf("\t%d destination%s found unreachable\n",
175 rtstat.rts_unreach, plural(rtstat.rts_unreach));
176 printf("\t%d use%s of a wildcard route\n",
177 rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
178}
40f48772
MK
179
180/*
181 * Return the possible subnetwork number from an internet address.
182 * If the address is of the form of a subnet address (most significant
183 * bit of the host part is set), believe the subnet exists.
184 * Otherwise, return the network number.
185 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
186 * INSIDE OF THE HOST PART. We can only believe this if we have other
187 * information (e.g., we can find a name for this number).
188 */
189inet_subnetof(in)
190 struct in_addr in;
191{
192 register u_long i = ntohl(in.s_addr);
193
194 if (IN_CLASSA(i)) {
195 if (IN_SUBNETA(i))
196 return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
197 else
198 return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
199 } else if (IN_CLASSB(i)) {
200 if (IN_SUBNETB(i))
201 return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
202 else
203 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
204 } else
205 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
206}