use MAXHOSTNAMELEN, not "50", print if_name correctly
[unix-history] / usr / src / usr.bin / netstat / route.c
CommitLineData
5ff67f98
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
3537c4ea 7#ifndef lint
cb646d4b 8static char sccsid[] = "@(#)route.c 5.12 (Berkeley) 87/12/12";
f1fbb01b 9#endif
3537c4ea 10
f7c99b06
MK
11#include <stdio.h>
12#include <strings.h>
13
6c5bed6c 14#include <sys/param.h>
3537c4ea
SL
15#include <sys/socket.h>
16#include <sys/mbuf.h>
44906619 17
3537c4ea 18#include <net/if.h>
3537c4ea 19#include <net/route.h>
44906619
SL
20#include <netinet/in.h>
21
f1fbb01b
KS
22#include <netns/ns.h>
23
3537c4ea
SL
24#include <netdb.h>
25
26extern int kmem;
27extern int nflag;
f7c99b06
MK
28extern char *routename(), *netname(), *ns_print(), *plural();
29extern char *malloc();
3537c4ea
SL
30
31/*
32 * Definitions for showing gateway flags.
33 */
34struct bits {
35 short b_mask;
36 char b_val;
37} bits[] = {
38 { RTF_UP, 'U' },
39 { RTF_GATEWAY, 'G' },
40 { RTF_HOST, 'H' },
6c5bed6c 41 { RTF_DYNAMIC, 'D' },
3273bd86 42 { RTF_MODIFIED, 'M' },
3537c4ea
SL
43 { 0 }
44};
45
46/*
47 * Print routing tables.
48 */
f508555e
MK
49routepr(hostaddr, netaddr, hashsizeaddr)
50 off_t hostaddr, netaddr, hashsizeaddr;
3537c4ea
SL
51{
52 struct mbuf mb;
53 register struct rtentry *rt;
54 register struct mbuf *m;
55 register struct bits *p;
3537c4ea 56 char name[16], *flags;
f508555e 57 struct mbuf **routehash;
3537c4ea 58 struct ifnet ifnet;
f508555e
MK
59 int hashsize;
60 int i, doinghost = 1;
3537c4ea
SL
61
62 if (hostaddr == 0) {
63 printf("rthost: symbol not in namelist\n");
64 return;
65 }
66 if (netaddr == 0) {
67 printf("rtnet: symbol not in namelist\n");
68 return;
69 }
f508555e
MK
70 if (hashsizeaddr == 0) {
71 printf("rthashsize: symbol not in namelist\n");
72 return;
73 }
74 klseek(kmem, hashsizeaddr, 0);
f7c99b06 75 read(kmem, (char *)&hashsize, sizeof (hashsize));
f508555e 76 routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) );
3537c4ea 77 klseek(kmem, hostaddr, 0);
f7c99b06 78 read(kmem, (char *)routehash, hashsize*sizeof (struct mbuf *));
3537c4ea 79 printf("Routing tables\n");
3cd87273 80 printf("%-16.16s %-18.18s %-6.6s %6.6s%8.8s %s\n",
3537c4ea 81 "Destination", "Gateway",
3cd87273 82 "Flags", "Refs", "Use", "Interface");
3537c4ea 83again:
f508555e 84 for (i = 0; i < hashsize; i++) {
3537c4ea
SL
85 if (routehash[i] == 0)
86 continue;
87 m = routehash[i];
88 while (m) {
89 struct sockaddr_in *sin;
90
f7c99b06
MK
91 klseek(kmem, (off_t)m, 0);
92 read(kmem, (char *)&mb, sizeof (mb));
3537c4ea 93 rt = mtod(&mb, struct rtentry *);
2ff355d6
MK
94 if ((unsigned)rt < (unsigned)&mb ||
95 (unsigned)rt >= (unsigned)(&mb + 1)) {
96 printf("???\n");
97 return;
98 }
99
f1fbb01b 100 switch(rt->rt_dst.sa_family) {
2ff355d6
MK
101 case AF_INET:
102 sin = (struct sockaddr_in *)&rt->rt_dst;
3cd87273 103 printf("%-16.16s ",
2ff355d6
MK
104 (sin->sin_addr.s_addr == 0) ? "default" :
105 (rt->rt_flags & RTF_HOST) ?
106 routename(sin->sin_addr) :
f7c99b06 107 netname(sin->sin_addr, 0L));
2ff355d6 108 sin = (struct sockaddr_in *)&rt->rt_gateway;
3cd87273 109 printf("%-18.18s ", routename(sin->sin_addr));
2ff355d6
MK
110 break;
111 case AF_NS:
3cd87273 112 printf("%-16s ",
2ff355d6 113 ns_print((struct sockaddr_ns *)&rt->rt_dst));
3cd87273 114 printf("%-18s ",
2ff355d6
MK
115 ns_print((struct sockaddr_ns *)&rt->rt_gateway));
116 break;
117 default:
118 {
119 u_short *s = (u_short *)rt->rt_dst.sa_data;
120 printf("(%d)%x %x %x %x %x %x %x ",
121 rt->rt_dst.sa_family,
122 s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
123 s = (u_short *)rt->rt_gateway.sa_data;
124 printf("(%d)%x %x %x %x %x %x %x ",
125 rt->rt_gateway.sa_family,
126 s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
127 }
f1fbb01b 128 }
3537c4ea
SL
129 for (flags = name, p = bits; p->b_mask; p++)
130 if (p->b_mask & rt->rt_flags)
131 *flags++ = p->b_val;
132 *flags = '\0';
3cd87273 133 printf("%-6.6s %6d %8d ", name,
3537c4ea
SL
134 rt->rt_refcnt, rt->rt_use);
135 if (rt->rt_ifp == 0) {
136 putchar('\n');
137 m = mb.m_next;
138 continue;
139 }
f7c99b06
MK
140 klseek(kmem, (off_t)rt->rt_ifp, 0);
141 read(kmem, (char *)&ifnet, sizeof (ifnet));
142 klseek(kmem, (off_t)ifnet.if_name, 0);
3537c4ea 143 read(kmem, name, 16);
cb646d4b 144 printf(" %.15s%d\n", name, ifnet.if_unit);
3537c4ea
SL
145 m = mb.m_next;
146 }
147 }
148 if (doinghost) {
149 klseek(kmem, netaddr, 0);
f7c99b06 150 read(kmem, (char *)routehash, hashsize*sizeof (struct mbuf *));
3537c4ea
SL
151 doinghost = 0;
152 goto again;
153 }
f7c99b06 154 free((char *)routehash);
3537c4ea
SL
155}
156
157char *
158routename(in)
159 struct in_addr in;
160{
6b9930b0 161 register char *cp;
cb646d4b 162 static char line[MAXHOSTNAMELEN + 1];
40f48772 163 struct hostent *hp;
6c5bed6c
MK
164 static char domain[MAXHOSTNAMELEN + 1];
165 static int first = 1;
166 char *index();
3537c4ea 167
6c5bed6c
MK
168 if (first) {
169 first = 0;
170 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
171 (cp = index(domain, '.')))
172 (void) strcpy(domain, cp + 1);
173 else
174 domain[0] = 0;
175 }
6b9930b0 176 cp = 0;
3537c4ea 177 if (!nflag) {
f7c99b06 178 hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
cab3a575 179 AF_INET);
6c5bed6c
MK
180 if (hp) {
181 if ((cp = index(hp->h_name, '.')) &&
182 !strcmp(cp + 1, domain))
183 *cp = 0;
cab3a575 184 cp = hp->h_name;
6c5bed6c 185 }
3537c4ea
SL
186 }
187 if (cp)
cb646d4b 188 strncpy(line, cp, sizeof(line) - 1);
3537c4ea 189 else {
cab3a575
MK
190#define C(x) ((x) & 0xff)
191 in.s_addr = ntohl(in.s_addr);
192 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
193 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
194 }
195 return (line);
196}
197
198/*
199 * Return the name of the network whose address is given.
200 * The address is assumed to be that of a net or subnet, not a host.
201 */
202char *
203netname(in, mask)
204 struct in_addr in;
205 u_long mask;
206{
207 char *cp = 0;
cb646d4b 208 static char line[MAXHOSTNAMELEN + 1];
cab3a575
MK
209 struct netent *np = 0;
210 u_long net;
211 register i;
6c5bed6c 212 int subnetshift;
cab3a575 213
a83ade01
MK
214 i = ntohl(in.s_addr);
215 if (!nflag && i) {
6c5bed6c
MK
216 if (mask == 0) {
217 if (IN_CLASSA(i)) {
218 mask = IN_CLASSA_NET;
219 subnetshift = 8;
220 } else if (IN_CLASSB(i)) {
221 mask = IN_CLASSB_NET;
222 subnetshift = 8;
223 } else {
224 mask = IN_CLASSC_NET;
225 subnetshift = 4;
226 }
cab3a575 227 /*
6c5bed6c
MK
228 * If there are more bits than the standard mask
229 * would suggest, subnets must be in use.
230 * Guess at the subnet mask, assuming reasonable
231 * width subnet fields.
cab3a575 232 */
a83ade01 233 while (i &~ mask)
6c5bed6c 234 mask = (long)mask >> subnetshift;
cab3a575 235 }
a83ade01 236 net = i & mask;
6c5bed6c
MK
237 while ((mask & 1) == 0)
238 mask >>= 1, net >>= 1;
239 np = getnetbyaddr(net, AF_INET);
cab3a575
MK
240 if (np)
241 cp = np->n_name;
f7c99b06 242 }
cab3a575 243 if (cp)
cb646d4b 244 strncpy(line, cp, sizeof(line) - 1);
a83ade01
MK
245 else if ((i & 0xffffff) == 0)
246 sprintf(line, "%u", C(i >> 24));
247 else if ((i & 0xffff) == 0)
248 sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
249 else if ((i & 0xff) == 0)
250 sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
cab3a575 251 else
a83ade01
MK
252 sprintf(line, "%u.%u.%u.%u", C(i >> 24),
253 C(i >> 16), C(i >> 8), C(i));
3537c4ea
SL
254 return (line);
255}
6c5bed6c 256
bbd2d21e
SL
257/*
258 * Print routing statistics
259 */
260rt_stats(off)
261 off_t off;
262{
263 struct rtstat rtstat;
264
265 if (off == 0) {
266 printf("rtstat: symbol not in namelist\n");
267 return;
268 }
269 klseek(kmem, off, 0);
270 read(kmem, (char *)&rtstat, sizeof (rtstat));
271 printf("routing:\n");
bd91d3f9 272 printf("\t%u bad routing redirect%s\n",
bbd2d21e 273 rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
bd91d3f9 274 printf("\t%u dynamically created route%s\n",
bbd2d21e 275 rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
bd91d3f9 276 printf("\t%u new gateway%s due to redirects\n",
bbd2d21e 277 rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
bd91d3f9 278 printf("\t%u destination%s found unreachable\n",
bbd2d21e 279 rtstat.rts_unreach, plural(rtstat.rts_unreach));
bd91d3f9 280 printf("\t%u use%s of a wildcard route\n",
bbd2d21e
SL
281 rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
282}
2ff355d6 283short ns_nullh[] = {0,0,0};
f1fbb01b
KS
284short ns_bh[] = {-1,-1,-1};
285
286char *
287ns_print(sns)
288struct sockaddr_ns *sns;
289{
2ff355d6
MK
290 struct ns_addr work;
291 union { union ns_net net_e; u_long long_e; } net;
292 u_short port;
293 static char mybuf[50], cport[10], chost[25];
294 char *host = "";
f7c99b06 295 register char *p; register u_char *q;
f1fbb01b 296
2ff355d6
MK
297 work = sns->sns_addr;
298 port = ntohs(work.x_port);
299 work.x_port = 0;
300 net.net_e = work.x_net;
301 if (ns_nullhost(work) && net.long_e == 0) {
302 if (port ) {
303 sprintf(mybuf, "*.%xH", port);
304 upHex(mybuf);
305 } else
306 sprintf(mybuf, "*.*");
307 return (mybuf);
308 }
f1fbb01b 309
2ff355d6
MK
310 if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
311 host = "any";
312 } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
313 host = "*";
314 } else {
315 q = work.x_host.c_host;
316 sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
317 q[0], q[1], q[2], q[3], q[4], q[5]);
318 for (p = chost; *p == '0' && p < chost + 12; p++);
319 host = p;
f1fbb01b 320 }
2ff355d6
MK
321 if (port)
322 sprintf(cport, ".%xH", htons(port));
323 else
324 *cport = 0;
325
326 sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
327 upHex(mybuf);
f1fbb01b
KS
328 return(mybuf);
329}
2ff355d6 330
f1fbb01b
KS
331char *
332ns_phost(sns)
333struct sockaddr_ns *sns;
334{
2ff355d6
MK
335 struct sockaddr_ns work;
336 static union ns_net ns_zeronet;
337 char *p;
338
339 work = *sns;
340 work.sns_addr.x_port = 0;
341 work.sns_addr.x_net = ns_zeronet;
342
343 p = ns_print(&work);
344 if (strncmp("0H.", p, 3) == 0) p += 3;
345 return(p);
346}
347upHex(p0)
348char *p0;
349{
350 register char *p = p0;
351 for (; *p; p++) switch (*p) {
352
353 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
354 *p += ('A' - 'a');
355 }
f1fbb01b 356}