| 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 | } |