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