File: | src/usr.bin/netstat/route.c |
Warning: | line 208, column 9 Result of 'calloc' is converted to a pointer of type 'union (unnamed union at /usr/src/usr.bin/netstat/route.c:202:2)', which is incompatible with sizeof operand type 'void *' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: route.c,v 1.108 2021/12/05 22:36:19 deraadt Exp $ */ |
2 | /* $NetBSD: route.c,v 1.15 1996/05/07 02:55:06 thorpej Exp $ */ |
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. |
16 | * 3. Neither the name of the University nor the names of its contributors |
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 | |
33 | #include <sys/types.h> |
34 | #include <sys/protosw.h> |
35 | #include <sys/socket.h> |
36 | |
37 | #include <net/if.h> |
38 | #include <net/if_types.h> |
39 | #define _KERNEL |
40 | #include <net/route.h> |
41 | #undef _KERNEL |
42 | #include <netinet/ip_ipsp.h> |
43 | #include <netinet/in.h> |
44 | #include <arpa/inet.h> |
45 | |
46 | #include <sys/sysctl.h> |
47 | |
48 | #include <err.h> |
49 | #include <limits.h> |
50 | #include <netdb.h> |
51 | #include <stdio.h> |
52 | #include <stdlib.h> |
53 | #include <string.h> |
54 | #include <unistd.h> |
55 | #include <ifaddrs.h> |
56 | |
57 | #include "netstat.h" |
58 | |
59 | static union { |
60 | struct sockaddr u_sa; |
61 | u_int32_t u_data[64]; |
62 | int u_dummy; /* force word-alignment */ |
63 | } pt_u; |
64 | |
65 | struct rtentry rtentry; |
66 | |
67 | static struct sockaddr *kgetsa(struct sockaddr *); |
68 | static struct sockaddr *plentosa(sa_family_t, int, struct sockaddr *); |
69 | static struct art_node *getdefault(struct art_table *); |
70 | static void p_table(struct art_table *); |
71 | static void p_artnode(struct art_node *); |
72 | static void p_krtentry(struct rtentry *); |
73 | |
74 | /* |
75 | * Print routing tables. |
76 | */ |
77 | void |
78 | routepr(u_long afmap, u_long af2idx, u_long af2idx_max, u_int tableid) |
79 | { |
80 | struct art_root ar; |
81 | struct art_node *node; |
82 | struct srp *afm_head, *afm; |
83 | struct { |
84 | unsigned int limit; |
85 | void **tbl; |
86 | } map; |
87 | void **tbl; |
88 | int i; |
89 | uint8_t af2i[AF_MAX36+1]; |
90 | uint8_t af2i_max; |
91 | |
92 | printf("Routing tables\n"); |
93 | |
94 | if (afmap == 0 || af2idx == 0 || af2idx_max == 0) { |
95 | printf("symbol not in namelist\n"); |
96 | return; |
97 | } |
98 | |
99 | kread(afmap, &afm_head, sizeof(afm_head)); |
100 | kread(af2idx, af2i, sizeof(af2i)); |
101 | kread(af2idx_max, &af2i_max, sizeof(af2i_max)); |
102 | |
103 | if ((afm = calloc(af2i_max + 1, sizeof(*afm))) == NULL((void *)0)) |
104 | err(1, NULL((void *)0)); |
105 | |
106 | kread((u_long)afm_head, afm, (af2i_max + 1) * sizeof(*afm)); |
107 | |
108 | for (i = 1; i <= AF_MAX36; i++) { |
109 | if (af != AF_UNSPEC0 && af != i) |
110 | continue; |
111 | if (af2i[i] == 0 || afm[af2i[i]].ref == NULL((void *)0)) |
112 | continue; |
113 | |
114 | kread((u_long)afm[af2i[i]].ref, &map, sizeof(map)); |
115 | if (tableid >= map.limit) |
116 | continue; |
117 | |
118 | if ((tbl = calloc(map.limit, sizeof(*tbl))) == NULL((void *)0)) |
119 | err(1, NULL((void *)0)); |
120 | |
121 | kread((u_long)map.tbl, tbl, map.limit * sizeof(*tbl)); |
122 | if (tbl[tableid] == NULL((void *)0)) |
123 | continue; |
124 | |
125 | kread((u_long)tbl[tableid], &ar, sizeof(ar)); |
126 | |
127 | free(tbl); |
128 | |
129 | if (ar.ar_root.ref == NULL((void *)0)) |
130 | continue; |
131 | |
132 | pr_family(i); |
133 | pr_rthdr(i, Aflag); |
134 | |
135 | node = getdefault(ar.ar_root.ref); |
136 | if (node != NULL((void *)0)) |
137 | p_artnode(node); |
138 | |
139 | p_table(ar.ar_root.ref); |
140 | } |
141 | |
142 | free(afm); |
143 | } |
144 | |
145 | static struct sockaddr * |
146 | kgetsa(struct sockaddr *dst) |
147 | { |
148 | |
149 | kread((u_long)dst, &pt_u.u_sa, sizeof(pt_u.u_sa)); |
150 | if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) |
151 | kread((u_long)dst, pt_u.u_data, pt_u.u_sa.sa_len); |
152 | return (&pt_u.u_sa); |
153 | } |
154 | |
155 | static struct sockaddr * |
156 | plentosa(sa_family_t af, int plen, struct sockaddr *sa_mask) |
157 | { |
158 | struct sockaddr_in *sin = (struct sockaddr_in *)sa_mask; |
159 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa_mask; |
160 | uint8_t *p; |
161 | int i; |
162 | |
163 | if (plen < 0) |
164 | return (NULL((void *)0)); |
165 | |
166 | memset(sa_mask, 0, sizeof(struct sockaddr_storage)); |
167 | |
168 | switch (af) { |
169 | case AF_INET2: |
170 | if (plen > 32) |
171 | return (NULL((void *)0)); |
172 | sin->sin_family = AF_INET2; |
173 | sin->sin_len = sizeof(struct sockaddr_in); |
174 | memset(&sin->sin_addr, 0, sizeof(sin->sin_addr)); |
175 | p = (uint8_t *)&sin->sin_addr; |
176 | break; |
177 | case AF_INET624: |
178 | if (plen > 128) |
179 | return (NULL((void *)0)); |
180 | sin6->sin6_family = AF_INET624; |
181 | sin6->sin6_len = sizeof(struct sockaddr_in6); |
182 | memset(&sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 0, sizeof(sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8)); |
183 | p = sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8; |
184 | break; |
185 | default: |
186 | return (NULL((void *)0)); |
187 | } |
188 | |
189 | for (i = 0; i < plen / 8; i++) |
190 | p[i] = 0xff; |
191 | if (plen % 8) |
192 | p[i] = (0xff00 >> (plen % 8)) & 0xff; |
193 | |
194 | return (sa_mask); |
195 | } |
196 | |
197 | static struct art_node * |
198 | getdefault(struct art_table *at) |
199 | { |
200 | struct art_node *node; |
201 | struct art_table table; |
202 | union { |
203 | struct srp node; |
204 | unsigned long count; |
205 | } *heap; |
206 | |
207 | kread((u_long)at, &table, sizeof(table)); |
208 | heap = calloc(1, AT_HEAPSIZE(table.at_bits)((1 << ((table.at_bits) + 1)) * sizeof(void *))); |
Result of 'calloc' is converted to a pointer of type 'union (unnamed union at /usr/src/usr.bin/netstat/route.c:202:2)', which is incompatible with sizeof operand type 'void *' | |
209 | kread((u_long)table.at_heap, heap, AT_HEAPSIZE(table.at_bits)((1 << ((table.at_bits) + 1)) * sizeof(void *))); |
210 | |
211 | node = heap[1].node.ref; |
212 | |
213 | free(heap); |
214 | |
215 | return (node); |
216 | } |
217 | |
218 | static void |
219 | p_table(struct art_table *at) |
220 | { |
221 | struct art_node *next, *node; |
222 | struct art_table *nat, table; |
223 | union { |
224 | struct srp node; |
225 | unsigned long count; |
226 | } *heap; |
227 | int i, j; |
228 | |
229 | kread((u_long)at, &table, sizeof(table)); |
230 | heap = calloc(1, AT_HEAPSIZE(table.at_bits)((1 << ((table.at_bits) + 1)) * sizeof(void *))); |
231 | kread((u_long)table.at_heap, heap, AT_HEAPSIZE(table.at_bits)((1 << ((table.at_bits) + 1)) * sizeof(void *))); |
232 | |
233 | for (j = 1; j < table.at_minfringe; j += 2) { |
234 | for (i = (j > 2) ? j : 2; i < table.at_minfringe; i <<= 1) { |
235 | next = heap[i >> 1].node.ref; |
236 | node = heap[i].node.ref; |
237 | if (node != NULL((void *)0) && node != next) |
238 | p_artnode(node); |
239 | } |
240 | } |
241 | |
242 | for (i = table.at_minfringe; i < table.at_minfringe << 1; i++) { |
243 | next = heap[i >> 1].node.ref; |
244 | node = heap[i].node.ref; |
245 | if (!ISLEAF(node)(((unsigned long)(node) & 1) == 0)) { |
246 | nat = SUBTABLE(node)((struct art_table *)((unsigned long)(node) & ~1)); |
247 | node = getdefault(nat); |
248 | } else |
249 | nat = NULL((void *)0); |
250 | |
251 | if (node != NULL((void *)0) && node != next) |
252 | p_artnode(node); |
253 | |
254 | if (nat != NULL((void *)0)) |
255 | p_table(nat); |
256 | } |
257 | |
258 | free(heap); |
259 | } |
260 | |
261 | static void |
262 | p_artnode(struct art_node *an) |
263 | { |
264 | struct art_node node; |
265 | struct rtentry *rt; |
266 | |
267 | kread((u_long)an, &node, sizeof(node)); |
268 | rt = node.an_rtlistan_pointer.an__rtlist.sl_head.ref; |
269 | |
270 | while (rt != NULL((void *)0)) { |
271 | kread((u_long)rt, &rtentry, sizeof(rtentry)); |
272 | if (Aflag) |
273 | printf("%-16p ", rt); |
274 | p_krtentry(&rtentry); |
275 | rt = rtentry.rt_next.se_next.ref; |
276 | } |
277 | } |
278 | |
279 | static void |
280 | p_krtentry(struct rtentry *rt) |
281 | { |
282 | struct sockaddr_storage sock1, sock2; |
283 | struct sockaddr *sa = (struct sockaddr *)&sock1; |
284 | struct sockaddr *mask = (struct sockaddr *)&sock2; |
285 | |
286 | bcopy(kgetsa(rt_key(rt)((rt)->rt_dest)), sa, sizeof(struct sockaddr)); |
287 | if (sa->sa_len > sizeof(struct sockaddr)) |
288 | bcopy(kgetsa(rt_key(rt)((rt)->rt_dest)), sa, sa->sa_len); |
289 | |
290 | if (sa->sa_family == PF_KEY30) { |
291 | /* Ignore PF_KEY entries */ |
292 | return; |
293 | } |
294 | |
295 | mask = plentosa(sa->sa_family, rt_plen(rt)((rt)->rt_plen), mask); |
296 | |
297 | p_addr(sa, mask, rt->rt_flags); |
298 | p_gwaddr(kgetsa(rt->rt_gateway), sa->sa_family); |
299 | p_flags(rt->rt_flags, "%-6.6s "); |
300 | printf("%5u %8lld ", rt->rt_refcnt - 1, rt->rt_usert_rmx.rmx_pksent); |
301 | if (rt->rt_rmx.rmx_mtu) |
302 | printf("%5u ", rt->rt_rmx.rmx_mtu); |
303 | else |
304 | printf("%5s ", "-"); |
305 | putchar((rt->rt_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ')(!__isthreaded ? __sputc((rt->rt_rmx.rmx_locks & 0x1) ? 'L' : ' ', (&__sF[1])) : (putc)((rt->rt_rmx.rmx_locks & 0x1) ? 'L' : ' ', (&__sF[1]))); |
306 | printf(" %2d", rt->rt_priority & RTP_MASK0x7f); |
307 | |
308 | if (rt->rt_ifidx != 0) |
309 | printf(" if%d", rt->rt_ifidx); |
310 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); |
311 | if (vflag) |
312 | printf("\texpire %10lld%c\n", |
313 | (long long)rt->rt_rmx.rmx_expire, |
314 | (rt->rt_rmx.rmx_locks & RTV_EXPIRE0x4) ? 'L' : ' '); |
315 | } |
316 | |
317 | /* |
318 | * Print routing statistics |
319 | */ |
320 | void |
321 | rt_stats(void) |
322 | { |
323 | struct rtstat rtstat; |
324 | int mib[6]; |
325 | size_t size; |
326 | |
327 | mib[0] = CTL_NET4; |
328 | mib[1] = PF_ROUTE17; |
329 | mib[2] = 0; |
330 | mib[3] = 0; |
331 | mib[4] = NET_RT_STATS4; |
332 | mib[5] = 0; |
333 | size = sizeof (rtstat); |
334 | |
335 | if (sysctl(mib, 6, &rtstat, &size, NULL((void *)0), 0) == -1) { |
336 | perror("sysctl of routing table statistics"); |
337 | exit(1); |
338 | } |
339 | |
340 | printf("routing:\n"); |
341 | printf("\t%u bad routing redirect%s\n", |
342 | rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); |
343 | printf("\t%u dynamically created route%s\n", |
344 | rtstat.rts_dynamic, plural(rtstat.rts_dynamic)); |
345 | printf("\t%u new gateway%s due to redirects\n", |
346 | rtstat.rts_newgateway, plural(rtstat.rts_newgateway)); |
347 | printf("\t%u destination%s found unreachable\n", |
348 | rtstat.rts_unreach, plural(rtstat.rts_unreach)); |
349 | printf("\t%u use%s of a wildcard route\n", |
350 | rtstat.rts_wildcard, plural(rtstat.rts_wildcard)); |
351 | } |
352 | |
353 | /* |
354 | * Print rdomain and rtable summary |
355 | */ |
356 | |
357 | void |
358 | rdomainpr(void) |
359 | { |
360 | struct if_data *ifd; |
361 | struct ifaddrs *ifap, *ifa; |
362 | struct rt_tableinfo info; |
363 | |
364 | int rtt_dom[RT_TABLEID_MAX255+1]; |
365 | int rdom_rttcnt[RT_TABLEID_MAX255+1] = { }; |
366 | int mib[6], rdom, rtt; |
367 | size_t len; |
368 | char *old, *rdom_if[RT_TABLEID_MAX255+1] = { }; |
369 | |
370 | getifaddrs(&ifap); |
371 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { |
372 | if (ifa->ifa_addr == NULL((void *)0) || |
373 | ifa->ifa_addr->sa_family != AF_LINK18) |
374 | continue; |
375 | ifd = ifa->ifa_data; |
376 | if (rdom_if[ifd->ifi_rdomain] == NULL((void *)0)) { |
377 | if (asprintf(&rdom_if[ifd->ifi_rdomain], "%s", |
378 | ifa->ifa_name) == -1) |
379 | exit(1); |
380 | } else { |
381 | old = rdom_if[ifd->ifi_rdomain]; |
382 | if (asprintf(&rdom_if[ifd->ifi_rdomain], "%s %s", |
383 | old, ifa->ifa_name) == -1) |
384 | exit(1); |
385 | free(old); |
386 | } |
387 | } |
388 | freeifaddrs(ifap); |
389 | |
390 | mib[0] = CTL_NET4; |
391 | mib[1] = PF_ROUTE17; |
392 | mib[2] = 0; |
393 | mib[3] = 0; |
394 | mib[4] = NET_RT_TABLE5; |
395 | |
396 | len = sizeof(info); |
397 | for (rtt = 0; rtt <= RT_TABLEID_MAX255; rtt++) { |
398 | mib[5] = rtt; |
399 | if (sysctl(mib, 6, &info, &len, NULL((void *)0), 0) == -1) |
400 | rtt_dom[rtt] = -1; |
401 | else { |
402 | rtt_dom[rtt] = info.rti_domainid; |
403 | rdom_rttcnt[info.rti_domainid]++; |
404 | } |
405 | } |
406 | |
407 | for (rdom = 0; rdom <= RT_TABLEID_MAX255; rdom++) { |
408 | if (rdom_if[rdom] == NULL((void *)0)) |
409 | continue; |
410 | printf("Rdomain %i\n", rdom); |
411 | printf(" Interface%s %s\n", |
412 | (strchr(rdom_if[rdom], ' ') == NULL((void *)0)) ? ":" : "s:", |
413 | rdom_if[rdom]); |
414 | printf(" Routing table%s", |
415 | (rdom_rttcnt[rdom] == 1) ? ":" : "s:"); |
416 | for (rtt = 0; rtt <= RT_TABLEID_MAX255; rtt++) { |
417 | if (rtt_dom[rtt] == rdom) |
418 | printf(" %i", rtt); |
419 | } |
420 | printf("\n\n"); |
421 | free(rdom_if[rdom]); |
422 | } |
423 | } |