Annotation of src/usr.bin/netstat/route.c, Revision 1.104
1.104 ! deraadt 1: /* $OpenBSD: route.c,v 1.103 2019/05/10 01:29:31 guenther Exp $ */
1.2 deraadt 2: /* $NetBSD: route.c,v 1.15 1996/05/07 02:55:06 thorpej Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1983, 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.53 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.95 deraadt 33: #include <sys/types.h>
1.1 deraadt 34: #include <sys/protosw.h>
1.100 guenther 35: #include <sys/select.h>
1.1 deraadt 36: #include <sys/socket.h>
37:
38: #include <net/if.h>
39: #include <net/if_types.h>
40: #include <net/route.h>
1.96 deraadt 41: #include <netinet/ip_ipsp.h>
1.1 deraadt 42: #include <netinet/in.h>
1.13 millert 43: #include <arpa/inet.h>
1.1 deraadt 44:
45: #include <sys/sysctl.h>
46:
1.61 otto 47: #include <err.h>
1.15 millert 48: #include <limits.h>
1.1 deraadt 49: #include <netdb.h>
50: #include <stdio.h>
51: #include <stdlib.h>
52: #include <string.h>
53: #include <unistd.h>
1.9 angelos 54:
1.1 deraadt 55: #include "netstat.h"
56:
57: static union {
1.6 deraadt 58: struct sockaddr u_sa;
59: u_int32_t u_data[64];
1.29 deraadt 60: int u_dummy; /* force word-alignment */
1.1 deraadt 61: } pt_u;
62:
63: struct rtentry rtentry;
64:
1.45 millert 65: static struct sockaddr *kgetsa(struct sockaddr *);
1.102 mpi 66: static struct sockaddr *plentosa(sa_family_t, int, struct sockaddr *);
67: static struct art_node *getdefault(struct art_table *);
68: static void p_table(struct art_table *);
69: static void p_artnode(struct art_node *);
1.72 claudio 70: static void p_krtentry(struct rtentry *);
1.1 deraadt 71:
72: /*
73: * Print routing tables.
74: */
75: void
1.102 mpi 76: routepr(u_long afmap, u_long af2idx, u_long af2idx_max, u_int tableid)
1.1 deraadt 77: {
1.102 mpi 78: struct art_root ar;
79: struct art_node *node;
80: struct srp *afm_head, *afm;
81: struct {
82: unsigned int limit;
83: void **tbl;
84: } map;
85: void **tbl;
86: int i;
87: uint8_t af2i[AF_MAX+1];
88: uint8_t af2i_max;
1.1 deraadt 89:
90: printf("Routing tables\n");
91:
1.102 mpi 92: if (afmap == 0 || af2idx == 0 || af2idx_max == 0) {
93: printf("symbol not in namelist\n");
1.72 claudio 94: return;
95: }
1.1 deraadt 96:
1.102 mpi 97: kread(afmap, &afm_head, sizeof(afm_head));
98: kread(af2idx, af2i, sizeof(af2i));
99: kread(af2idx_max, &af2i_max, sizeof(af2i_max));
1.73 claudio 100:
1.102 mpi 101: if ((afm = calloc(af2i_max + 1, sizeof(*afm))) == NULL)
1.73 claudio 102: err(1, NULL);
103:
1.102 mpi 104: kread((u_long)afm_head, afm, (af2i_max + 1) * sizeof(*afm));
1.73 claudio 105:
1.102 mpi 106: for (i = 1; i <= AF_MAX; i++) {
107: if (af != AF_UNSPEC && af != i)
108: continue;
109: if (af2i[i] == 0 || afm[af2i[i]].ref == NULL)
1.73 claudio 110: continue;
1.102 mpi 111:
112: kread((u_long)afm[af2i[i]].ref, &map, sizeof(map));
113: if (tableid >= map.limit)
1.73 claudio 114: continue;
1.102 mpi 115:
116: if ((tbl = calloc(map.limit, sizeof(*tbl))) == NULL)
117: err(1, NULL);
118:
119: kread((u_long)map.tbl, tbl, map.limit * sizeof(*tbl));
120: if (tbl[tableid] == NULL)
1.73 claudio 121: continue;
1.102 mpi 122:
123: kread((u_long)tbl[tableid], &ar, sizeof(ar));
124:
125: free(tbl);
126:
127: if (ar.ar_root.ref == NULL)
128: continue;
129:
130: pr_family(i);
131: pr_rthdr(i, Aflag);
132:
133: node = getdefault(ar.ar_root.ref);
134: if (node != NULL)
135: p_artnode(node);
136:
137: p_table(ar.ar_root.ref);
1.1 deraadt 138: }
1.102 mpi 139:
140: free(afm);
1.1 deraadt 141: }
142:
143: static struct sockaddr *
1.50 deraadt 144: kgetsa(struct sockaddr *dst)
1.1 deraadt 145: {
146:
1.83 deraadt 147: kread((u_long)dst, &pt_u.u_sa, sizeof(pt_u.u_sa));
1.1 deraadt 148: if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
1.67 jaredy 149: kread((u_long)dst, pt_u.u_data, pt_u.u_sa.sa_len);
1.1 deraadt 150: return (&pt_u.u_sa);
151: }
152:
1.102 mpi 153: static struct sockaddr *
154: plentosa(sa_family_t af, int plen, struct sockaddr *sa_mask)
1.1 deraadt 155: {
1.102 mpi 156: struct sockaddr_in *sin = (struct sockaddr_in *)sa_mask;
157: struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa_mask;
158: uint8_t *p;
159: int i;
160:
161: if (plen < 0)
162: return (NULL);
163:
164: memset(sa_mask, 0, sizeof(struct sockaddr_storage));
165:
166: switch (af) {
167: case AF_INET:
168: if (plen > 32)
169: return (NULL);
170: sin->sin_family = AF_INET;
171: sin->sin_len = sizeof(struct sockaddr_in);
172: memset(&sin->sin_addr, 0, sizeof(sin->sin_addr));
173: p = (uint8_t *)&sin->sin_addr;
174: break;
175: case AF_INET6:
176: if (plen > 128)
177: return (NULL);
178: sin6->sin6_family = AF_INET6;
179: sin6->sin6_len = sizeof(struct sockaddr_in6);
180: memset(&sin6->sin6_addr.s6_addr, 0, sizeof(sin6->sin6_addr.s6_addr));
181: p = sin6->sin6_addr.s6_addr;
182: break;
183: default:
184: return (NULL);
185: }
1.1 deraadt 186:
1.102 mpi 187: for (i = 0; i < plen / 8; i++)
188: p[i] = 0xff;
189: if (plen % 8)
190: p[i] = (0xff00 >> (plen % 8)) & 0xff;
191:
192: return (sa_mask);
1.1 deraadt 193: }
194:
1.102 mpi 195: static struct art_node *
196: getdefault(struct art_table *at)
1.49 deraadt 197: {
1.102 mpi 198: struct art_node *node;
199: struct art_table table;
200: union {
201: struct srp node;
202: unsigned long count;
203: } *heap;
204:
205: kread((u_long)at, &table, sizeof(table));
206: heap = calloc(1, AT_HEAPSIZE(table.at_bits));
207: kread((u_long)table.at_heap, heap, AT_HEAPSIZE(table.at_bits));
208:
209: node = heap[1].node.ref;
210:
211: free(heap);
212:
213: return (node);
1.49 deraadt 214: }
215:
1.1 deraadt 216: static void
1.102 mpi 217: p_table(struct art_table *at)
1.1 deraadt 218: {
1.102 mpi 219: struct art_node *next, *node;
220: struct art_table *nat, table;
221: union {
222: struct srp node;
223: unsigned long count;
224: } *heap;
225: int i, j;
226:
227: kread((u_long)at, &table, sizeof(table));
228: heap = calloc(1, AT_HEAPSIZE(table.at_bits));
229: kread((u_long)table.at_heap, heap, AT_HEAPSIZE(table.at_bits));
230:
231: for (j = 1; j < table.at_minfringe; j += 2) {
232: for (i = (j > 2) ? j : 2; i < table.at_minfringe; i <<= 1) {
233: next = heap[i >> 1].node.ref;
234: node = heap[i].node.ref;
235: if (node != NULL && node != next)
236: p_artnode(node);
237: }
238: }
239:
240: for (i = table.at_minfringe; i < table.at_minfringe << 1; i++) {
241: next = heap[i >> 1].node.ref;
242: node = heap[i].node.ref;
243: if (!ISLEAF(node)) {
244: nat = SUBTABLE(node);
245: node = getdefault(nat);
246: } else
247: nat = NULL;
248:
249: if (node != NULL && node != next)
250: p_artnode(node);
1.1 deraadt 251:
1.102 mpi 252: if (nat != NULL)
253: p_table(nat);
1.1 deraadt 254: }
1.49 deraadt 255:
1.102 mpi 256: free(heap);
257: }
1.49 deraadt 258:
1.102 mpi 259: static void
260: p_artnode(struct art_node *an)
261: {
262: struct art_node node;
263: struct rtentry *rt;
264:
265: kread((u_long)an, &node, sizeof(node));
266: rt = node.an_rtlist.sl_head.ref;
267:
268: while (rt != NULL) {
269: kread((u_long)rt, &rtentry, sizeof(rtentry));
270: if (Aflag)
271: printf("%-16p ", rt);
272: p_krtentry(&rtentry);
273: rt = rtentry.rt_next.se_next.ref;
1.1 deraadt 274: }
275: }
276:
277: static void
1.72 claudio 278: p_krtentry(struct rtentry *rt)
1.1 deraadt 279: {
1.30 itojun 280: struct sockaddr_storage sock1, sock2;
281: struct sockaddr *sa = (struct sockaddr *)&sock1;
282: struct sockaddr *mask = (struct sockaddr *)&sock2;
1.46 deraadt 283:
1.21 peter 284: bcopy(kgetsa(rt_key(rt)), sa, sizeof(struct sockaddr));
1.30 itojun 285: if (sa->sa_len > sizeof(struct sockaddr))
286: bcopy(kgetsa(rt_key(rt)), sa, sa->sa_len);
1.21 peter 287:
1.26 angelos 288: if (sa->sa_family == PF_KEY) {
1.97 reyk 289: /* Ignore PF_KEY entries */
1.10 deraadt 290: return;
1.9 angelos 291: }
1.21 peter 292:
1.102 mpi 293: mask = plentosa(sa->sa_family, rt_plen(rt), mask);
1.46 deraadt 294:
1.72 claudio 295: p_addr(sa, mask, rt->rt_flags);
296: p_gwaddr(kgetsa(rt->rt_gateway), sa->sa_family);
1.1 deraadt 297: p_flags(rt->rt_flags, "%-6.6s ");
1.102 mpi 298: printf("%5u %8lld ", rt->rt_refcnt - 1, rt->rt_use);
1.1 deraadt 299: if (rt->rt_rmx.rmx_mtu)
1.79 claudio 300: printf("%5u ", rt->rt_rmx.rmx_mtu);
1.1 deraadt 301: else
1.79 claudio 302: printf("%5s ", "-");
1.39 provos 303: putchar((rt->rt_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
1.102 mpi 304: printf(" %2d", rt->rt_priority & RTP_MASK);
1.72 claudio 305:
1.102 mpi 306: if (rt->rt_ifidx != 0)
307: printf(" if%d", rt->rt_ifidx);
1.1 deraadt 308: putchar('\n');
1.63 claudio 309: if (vflag)
1.91 bluhm 310: printf("\texpire %10lld%c\n",
311: (long long)rt->rt_rmx.rmx_expire,
1.63 claudio 312: (rt->rt_rmx.rmx_locks & RTV_EXPIRE) ? 'L' : ' ');
1.1 deraadt 313: }
314:
315: /*
316: * Print routing statistics
317: */
318: void
1.78 claudio 319: rt_stats(void)
1.1 deraadt 320: {
321: struct rtstat rtstat;
1.72 claudio 322: int mib[6];
323: size_t size;
1.76 deraadt 324:
1.78 claudio 325: mib[0] = CTL_NET;
326: mib[1] = PF_ROUTE;
327: mib[2] = 0;
328: mib[3] = 0;
329: mib[4] = NET_RT_STATS;
330: mib[5] = 0;
331: size = sizeof (rtstat);
332:
1.104 ! deraadt 333: if (sysctl(mib, 6, &rtstat, &size, NULL, 0) == -1) {
1.78 claudio 334: perror("sysctl of routing table statistics");
335: exit(1);
336: }
1.72 claudio 337:
1.1 deraadt 338: printf("routing:\n");
339: printf("\t%u bad routing redirect%s\n",
1.46 deraadt 340: rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
1.1 deraadt 341: printf("\t%u dynamically created route%s\n",
1.46 deraadt 342: rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
1.1 deraadt 343: printf("\t%u new gateway%s due to redirects\n",
1.46 deraadt 344: rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
1.1 deraadt 345: printf("\t%u destination%s found unreachable\n",
1.46 deraadt 346: rtstat.rts_unreach, plural(rtstat.rts_unreach));
1.1 deraadt 347: printf("\t%u use%s of a wildcard route\n",
1.46 deraadt 348: rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
1.1 deraadt 349: }