1 1.11 christos /* $NetBSD: rtutil.c,v 1.11 2020/08/29 19:27:40 christos Exp $ */ 2 1.1 christos /* $OpenBSD: show.c,v 1.1 2006/05/27 19:16:37 claudio Exp $ */ 3 1.1 christos 4 1.1 christos /* 5 1.1 christos * Copyright (c) 1983, 1988, 1993 6 1.1 christos * The Regents of the University of California. All rights reserved. 7 1.1 christos * 8 1.1 christos * Redistribution and use in source and binary forms, with or without 9 1.1 christos * modification, are permitted provided that the following conditions 10 1.1 christos * are met: 11 1.1 christos * 1. Redistributions of source code must retain the above copyright 12 1.1 christos * notice, this list of conditions and the following disclaimer. 13 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 christos * notice, this list of conditions and the following disclaimer in the 15 1.1 christos * documentation and/or other materials provided with the distribution. 16 1.1 christos * 3. Neither the name of the University nor the names of its contributors 17 1.1 christos * may be used to endorse or promote products derived from this software 18 1.1 christos * without specific prior written permission. 19 1.1 christos * 20 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.1 christos * SUCH DAMAGE. 31 1.1 christos */ 32 1.1 christos 33 1.1 christos #include <sys/param.h> 34 1.1 christos #include <sys/protosw.h> 35 1.1 christos #include <sys/socket.h> 36 1.1 christos #include <sys/sysctl.h> 37 1.1 christos 38 1.1 christos #include <net/if.h> 39 1.1 christos #include <net/if_dl.h> 40 1.1 christos #include <net/if_types.h> 41 1.1 christos #include <net/pfvar.h> 42 1.1 christos #include <net/pfkeyv2.h> 43 1.1 christos #include <net/route.h> 44 1.1 christos #include <netinet/in.h> 45 1.1 christos #include <netinet/if_ether.h> 46 1.1 christos #include <netatalk/at.h> 47 1.1 christos #include <netmpls/mpls.h> 48 1.1 christos #include <arpa/inet.h> 49 1.1 christos 50 1.1 christos #include <err.h> 51 1.1 christos #include <errno.h> 52 1.1 christos #include <netdb.h> 53 1.1 christos #include <stdio.h> 54 1.1 christos #include <stddef.h> 55 1.1 christos #include <stdlib.h> 56 1.1 christos #include <string.h> 57 1.1 christos #include <unistd.h> 58 1.1 christos 59 1.1 christos #include "prog_ops.h" 60 1.1 christos #include "rtutil.h" 61 1.1 christos 62 1.1 christos #define PLEN (LONG_BIT / 4 + 2) 63 1.1 christos #define PFKEYV2_CHUNK sizeof(u_int64_t) 64 1.1 christos static char *link_print(const struct sockaddr *); 65 1.1 christos 66 1.1 christos /* 67 1.1 christos * Definitions for showing gateway flags. 68 1.1 christos */ 69 1.1 christos struct bits { 70 1.1 christos int b_mask; 71 1.1 christos char b_val; 72 1.1 christos }; 73 1.1 christos static const struct bits bits[] = { 74 1.1 christos { RTF_UP, 'U' }, 75 1.1 christos { RTF_GATEWAY, 'G' }, 76 1.1 christos { RTF_HOST, 'H' }, 77 1.1 christos { RTF_REJECT, 'R' }, 78 1.1 christos { RTF_BLACKHOLE, 'B' }, 79 1.1 christos { RTF_DYNAMIC, 'D' }, 80 1.1 christos { RTF_MODIFIED, 'M' }, 81 1.1 christos { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ 82 1.1 christos { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ 83 1.8 ozaki /* { RTF_CLONING, 'C' }, */ 84 1.8 ozaki { RTF_CONNECTED, 'C' }, 85 1.8 ozaki /* { RTF_XRESOLVE, 'X' }, */ 86 1.11 christos { RTF_LLDATA, 'L' }, 87 1.1 christos { RTF_STATIC, 'S' }, 88 1.1 christos { RTF_PROTO1, '1' }, 89 1.1 christos { RTF_PROTO2, '2' }, 90 1.1 christos /* { RTF_PROTO3, '3' }, */ 91 1.8 ozaki /* { RTF_CLONED, 'c' }, */ 92 1.1 christos /* { RTF_JUMBO, 'J' }, */ 93 1.1 christos { RTF_ANNOUNCE, 'p' }, 94 1.5 roy { RTF_LOCAL, 'l'}, 95 1.6 roy { RTF_BROADCAST, 'b'}, 96 1.1 christos { 0, 0 } 97 1.1 christos }; 98 1.1 christos 99 1.1 christos #ifndef SMALL 100 1.1 christos static void p_tag(const struct sockaddr *sa); 101 1.1 christos #endif 102 1.1 christos static void p_rtentry(struct rt_msghdr *, int, int); 103 1.1 christos 104 1.1 christos /* 105 1.1 christos * Print routing tables. 106 1.1 christos */ 107 1.1 christos void 108 1.1 christos p_rttables(int paf, int flags, int pflags, int interesting) 109 1.1 christos { 110 1.1 christos struct rt_msghdr *rtm; 111 1.1 christos char *buf = NULL, *next, *lim = NULL; 112 1.1 christos size_t needed; 113 1.1 christos int mib[6]; 114 1.1 christos struct sockaddr *sa; 115 1.1 christos 116 1.1 christos mib[0] = CTL_NET; 117 1.1 christos mib[1] = PF_ROUTE; 118 1.1 christos mib[2] = 0; 119 1.1 christos mib[3] = paf; 120 1.1 christos mib[4] = NET_RT_DUMP; 121 1.1 christos mib[5] = 0; 122 1.1 christos if (prog_sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 123 1.1 christos err(1, "route-sysctl-estimate"); 124 1.1 christos if (needed > 0) { 125 1.1 christos if ((buf = malloc(needed)) == 0) 126 1.1 christos err(1, NULL); 127 1.1 christos if (prog_sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 128 1.1 christos err(1, "sysctl of routing table"); 129 1.1 christos lim = buf + needed; 130 1.1 christos } 131 1.1 christos 132 1.1 christos printf("Routing tables\n"); 133 1.1 christos 134 1.1 christos if (buf) { 135 1.1 christos for (next = buf; next < lim; next += rtm->rtm_msglen) { 136 1.1 christos rtm = (struct rt_msghdr *)next; 137 1.1 christos sa = (struct sockaddr *)(rtm + 1); 138 1.1 christos if ((rtm->rtm_flags & pflags) != pflags) 139 1.1 christos continue; 140 1.1 christos if (paf != AF_UNSPEC && sa->sa_family != paf) 141 1.1 christos continue; 142 1.1 christos p_rtentry(rtm, flags, interesting); 143 1.1 christos } 144 1.1 christos free(buf); 145 1.1 christos buf = NULL; 146 1.1 christos } 147 1.1 christos 148 1.1 christos if (paf != 0 && paf != PF_KEY) 149 1.1 christos return; 150 1.1 christos 151 1.1 christos #if 0 /* XXX-elad */ 152 1.1 christos mib[0] = CTL_NET; 153 1.1 christos mib[1] = PF_KEY; 154 1.1 christos mib[2] = PF_KEY_V2; 155 1.1 christos mib[3] = NET_KEY_SPD_DUMP; 156 1.1 christos mib[4] = mib[5] = 0; 157 1.1 christos 158 1.1 christos if (prog_sysctl(mib, 4, NULL, &needed, NULL, 0) == -1) { 159 1.1 christos if (errno == ENOPROTOOPT) 160 1.1 christos return; 161 1.1 christos err(1, "spd-sysctl-estimate"); 162 1.1 christos } 163 1.1 christos if (needed > 0) { 164 1.1 christos if ((buf = malloc(needed)) == 0) 165 1.1 christos err(1, NULL); 166 1.1 christos if (prog_sysctl(mib, 4, buf, &needed, NULL, 0) == -1) 167 1.1 christos err(1,"sysctl of spd"); 168 1.1 christos lim = buf + needed; 169 1.1 christos } 170 1.1 christos 171 1.1 christos if (buf) { 172 1.1 christos printf("\nEncap:\n"); 173 1.1 christos 174 1.1 christos for (next = buf; next < lim; next += msg->sadb_msg_len * 175 1.1 christos PFKEYV2_CHUNK) { 176 1.1 christos msg = (struct sadb_msg *)next; 177 1.1 christos if (msg->sadb_msg_len == 0) 178 1.1 christos break; 179 1.1 christos p_pfkentry(msg); 180 1.1 christos } 181 1.1 christos free(buf); 182 1.1 christos buf = NULL; 183 1.1 christos } 184 1.1 christos #endif /* 0 */ 185 1.1 christos } 186 1.1 christos 187 1.1 christos /* 188 1.1 christos * column widths; each followed by one space 189 1.1 christos * width of destination/gateway column 190 1.2 christos * strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 = 34 191 1.2 christos * strlen("aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh") == 39 192 1.1 christos */ 193 1.1 christos #ifndef INET6 194 1.1 christos #define WID_DST(af) 18 /* width of destination column */ 195 1.1 christos #define WID_GW(af) 18 /* width of gateway column */ 196 1.1 christos #else 197 1.2 christos #define WID_DST(af) ((af) == AF_INET6 ? ((flags & RT_NFLAG) ? 39 : 18) : 18) 198 1.1 christos #define WID_GW(af) ((af) == AF_INET6 ? ((flags & RT_NFLAG) ? 30 : 18) : 18) 199 1.1 christos #endif 200 1.1 christos 201 1.1 christos /* 202 1.1 christos * Print header for routing table columns. 203 1.1 christos */ 204 1.1 christos void 205 1.1 christos p_rthdr(int paf, int flags) 206 1.1 christos { 207 1.1 christos #ifndef SMALL 208 1.1 christos if (flags & RT_AFLAG) 209 1.1 christos printf("%-*.*s ", PLEN, PLEN, "Address"); 210 1.1 christos if (paf == PF_KEY) { 211 1.1 christos printf("%-18s %-5s %-18s %-5s %-5s %-22s\n", 212 1.1 christos "Source", "Port", "Destination", 213 1.1 christos "Port", "Proto", "SA(Address/Proto/Type/Direction)"); 214 1.1 christos return; 215 1.1 christos } 216 1.1 christos if (flags & RT_TFLAG) { 217 1.1 christos printf("%-*.*s %-*.*s %-6.6s %6.6s %8.8s %6.6s %7.7s" 218 1.1 christos " %s\n", WID_DST(paf), WID_DST(paf), "Destination", 219 1.1 christos WID_GW(paf), WID_GW(paf), "Gateway", 220 1.1 christos "Flags", "Refs", "Use", "Mtu", "Tag", "Interface"); 221 1.1 christos return; 222 1.1 christos } 223 1.1 christos #endif 224 1.1 christos #ifndef SMALL 225 1.1 christos printf("%-*.*s %-*.*s %-6.6s %6.6s %8.8s %6.6s %s\n", 226 1.1 christos WID_DST(paf), WID_DST(paf), "Destination", 227 1.1 christos WID_GW(paf), WID_GW(paf), "Gateway", 228 1.1 christos "Flags", "Refs", "Use", "Mtu", "Interface"); 229 1.1 christos #else 230 1.1 christos printf("%-*.*s %-*.*s %-6.6s\n", 231 1.1 christos WID_DST(paf), WID_DST(paf), "Destination", 232 1.1 christos WID_GW(paf), WID_GW(paf), "Gateway", 233 1.1 christos "Flags"); 234 1.1 christos #endif 235 1.1 christos } 236 1.1 christos 237 1.1 christos static void 238 1.1 christos get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 239 1.1 christos { 240 1.1 christos int i; 241 1.1 christos 242 1.1 christos for (i = 0; i < RTAX_MAX; i++) { 243 1.1 christos if (addrs & (1 << i)) { 244 1.1 christos rti_info[i] = sa; 245 1.1 christos sa = (struct sockaddr *)((char *)(sa) + 246 1.1 christos RT_ROUNDUP(sa->sa_len)); 247 1.1 christos } else 248 1.1 christos rti_info[i] = NULL; 249 1.1 christos } 250 1.1 christos } 251 1.1 christos 252 1.1 christos /* 253 1.1 christos * Print a routing table entry. 254 1.1 christos */ 255 1.1 christos static void 256 1.1 christos p_rtentry(struct rt_msghdr *rtm, int flags, int interesting) 257 1.1 christos { 258 1.1 christos static int old_af = -1; 259 1.1 christos struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 260 1.1 christos struct sockaddr *mask, *rti_info[RTAX_MAX]; 261 1.1 christos #ifndef SMALL 262 1.1 christos char ifbuf[IF_NAMESIZE]; 263 1.1 christos #endif 264 1.1 christos 265 1.11 christos if ((flags & RT_LFLAG) && (rtm->rtm_flags & RTF_LLDATA)) 266 1.9 ozaki return; 267 1.9 ozaki 268 1.1 christos if (old_af != sa->sa_family) { 269 1.1 christos old_af = sa->sa_family; 270 1.1 christos p_family(sa->sa_family); 271 1.1 christos p_rthdr(sa->sa_family, flags); 272 1.1 christos } 273 1.1 christos get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 274 1.1 christos 275 1.1 christos mask = rti_info[RTAX_NETMASK]; 276 1.1 christos if ((sa = rti_info[RTAX_DST]) == NULL) 277 1.1 christos return; 278 1.1 christos 279 1.1 christos p_sockaddr(sa, mask, rtm->rtm_flags, WID_DST(sa->sa_family), flags); 280 1.1 christos p_sockaddr(rti_info[RTAX_GATEWAY], NULL, RTF_HOST, 281 1.1 christos WID_GW(sa->sa_family), flags); 282 1.1 christos p_flags(rtm->rtm_flags & interesting); 283 1.1 christos #if 0 /* XXX-elad */ 284 1.1 christos printf("%6d %8"PRId64" ", (int)rtm->rtm_rmx.rmx_refcnt, 285 1.1 christos rtm->rtm_rmx.rmx_pksent); 286 1.1 christos #else 287 1.1 christos printf("%6s %8s ", "-", "-"); 288 1.1 christos #endif 289 1.1 christos #ifndef SMALL 290 1.1 christos if (rtm->rtm_rmx.rmx_mtu) 291 1.1 christos printf("%6"PRId64, rtm->rtm_rmx.rmx_mtu); 292 1.1 christos else 293 1.1 christos printf("%6s", "-"); 294 1.1 christos putchar((rtm->rtm_rmx.rmx_locks & RTV_MTU) ? 'L' : ' '); 295 1.1 christos if (flags & RT_TFLAG) 296 1.1 christos p_tag(rti_info[RTAX_TAG]); 297 1.1 christos printf(" %.16s", if_indextoname(rtm->rtm_index, ifbuf)); 298 1.1 christos putchar('\n'); 299 1.1 christos if (flags & RT_VFLAG) 300 1.1 christos p_rtrmx(&rtm->rtm_rmx); 301 1.10 manu #else 302 1.10 manu putchar('\n'); 303 1.1 christos #endif 304 1.1 christos } 305 1.1 christos 306 1.1 christos /* 307 1.1 christos * Print address family header before a section of the routing table. 308 1.1 christos */ 309 1.1 christos void 310 1.1 christos p_family(int paf) 311 1.1 christos { 312 1.1 christos const char *afname; 313 1.1 christos 314 1.1 christos switch (paf) { 315 1.1 christos case AF_INET: 316 1.1 christos afname = "Internet"; 317 1.1 christos break; 318 1.1 christos #ifdef INET6 319 1.1 christos case AF_INET6: 320 1.1 christos afname = "Internet6"; 321 1.1 christos break; 322 1.1 christos #endif 323 1.1 christos case PF_KEY: 324 1.1 christos afname = "Encap"; 325 1.1 christos break; 326 1.1 christos case AF_APPLETALK: 327 1.1 christos afname = "AppleTalk"; 328 1.1 christos break; 329 1.1 christos #ifndef SMALL 330 1.1 christos case AF_MPLS: 331 1.1 christos afname = "MPLS"; 332 1.1 christos break; 333 1.1 christos #endif 334 1.1 christos default: 335 1.1 christos afname = NULL; 336 1.1 christos break; 337 1.1 christos } 338 1.1 christos if (afname) 339 1.1 christos printf("\n%s:\n", afname); 340 1.1 christos else 341 1.1 christos printf("\nProtocol Family %d:\n", paf); 342 1.1 christos } 343 1.1 christos 344 1.1 christos void 345 1.1 christos p_sockaddr(const struct sockaddr *sa, const struct sockaddr *mask, int rflags, 346 1.1 christos int width, int flags) 347 1.1 christos { 348 1.1 christos char *cp; 349 1.1 christos 350 1.1 christos switch (sa->sa_family) { 351 1.1 christos #ifdef INET6 352 1.1 christos case AF_INET6: 353 1.1 christos { 354 1.1 christos struct sockaddr_in6 sa6 = *(const struct sockaddr_in6 *)sa; 355 1.1 christos 356 1.1 christos inet6_getscopeid(&sa6, INET6_IS_ADDR_LINKLOCAL| 357 1.1 christos INET6_IS_ADDR_MC_LINKLOCAL); 358 1.1 christos if (rflags & RTF_HOST) 359 1.1 christos cp = routename((const struct sockaddr *)&sa6, flags); 360 1.1 christos else 361 1.1 christos cp = netname((const struct sockaddr *)&sa6, mask, flags); 362 1.1 christos break; 363 1.1 christos } 364 1.1 christos #endif 365 1.1 christos default: 366 1.1 christos if ((rflags & RTF_HOST) || mask == NULL) 367 1.1 christos cp = routename(sa, flags); 368 1.1 christos else 369 1.1 christos cp = netname(sa, mask, flags); 370 1.1 christos break; 371 1.1 christos } 372 1.1 christos if (width < 0) 373 1.1 christos printf("%s", cp); 374 1.1 christos else { 375 1.1 christos if (flags & RT_NFLAG) 376 1.1 christos printf("%-*s ", width, cp); 377 1.1 christos else 378 1.1 christos printf("%-*.*s ", width, width, cp); 379 1.1 christos } 380 1.1 christos } 381 1.1 christos 382 1.1 christos void 383 1.1 christos p_flags(int f) 384 1.1 christos { 385 1.1 christos char name[33], *flags; 386 1.1 christos const struct bits *p = bits; 387 1.1 christos 388 1.1 christos for (flags = name; p->b_mask && flags < &name[sizeof(name) - 2]; p++) 389 1.1 christos if (p->b_mask & f) 390 1.1 christos *flags++ = p->b_val; 391 1.1 christos *flags = '\0'; 392 1.1 christos printf("%-6.6s ", name); 393 1.1 christos } 394 1.1 christos 395 1.1 christos #ifndef SMALL 396 1.1 christos void 397 1.1 christos p_rtrmx(const struct rt_metrics *rmx) 398 1.1 christos { 399 1.1 christos printf("\texpire %10"PRId64"%c recvpipe %10"PRIu64"%c " 400 1.1 christos "sendpipe %10"PRIu64"%c\n", 401 1.1 christos (int64_t)rmx->rmx_expire, 402 1.1 christos (rmx->rmx_locks & RTV_EXPIRE) ? 'L' : ' ', rmx->rmx_recvpipe, 403 1.1 christos (rmx->rmx_locks & RTV_RPIPE) ? 'L' : ' ', rmx->rmx_sendpipe, 404 1.1 christos (rmx->rmx_locks & RTV_SPIPE) ? 'L' : ' '); 405 1.1 christos printf("\tssthresh %10"PRIu64"%c rtt %10"PRIu64"%c " 406 1.1 christos "rttvar %10"PRIu64"%c\n", rmx->rmx_ssthresh, 407 1.1 christos (rmx->rmx_locks & RTV_SSTHRESH) ? 'L' : ' ', 408 1.1 christos rmx->rmx_rtt, (rmx->rmx_locks & RTV_RTT) ? 'L' : ' ', 409 1.1 christos rmx->rmx_rttvar, (rmx->rmx_locks & RTV_RTTVAR) ? 'L' : ' '); 410 1.1 christos printf("\thopcount %10"PRIu64"%c\n", 411 1.1 christos rmx->rmx_hopcount, (rmx->rmx_locks & RTV_HOPCOUNT) ? 'L' : ' '); 412 1.1 christos } 413 1.1 christos 414 1.1 christos static void 415 1.1 christos p_tag(const struct sockaddr *sa) 416 1.1 christos { 417 1.1 christos char *line; 418 1.1 christos 419 1.1 christos if (sa == NULL || sa->sa_family != AF_MPLS) { 420 1.1 christos printf("%7s", "-"); 421 1.1 christos return; 422 1.1 christos } 423 1.1 christos line = mpls_ntoa(sa); 424 1.1 christos if (strlen(line) < 7) 425 1.1 christos printf("%7s", line); 426 1.1 christos else 427 1.1 christos printf("%s", line); 428 1.1 christos } 429 1.1 christos #endif 430 1.1 christos 431 1.1 christos static char line[MAXHOSTNAMELEN]; 432 1.1 christos static char domain[MAXHOSTNAMELEN]; 433 1.1 christos 434 1.1 christos char * 435 1.1 christos routename(const struct sockaddr *sa, int flags) 436 1.1 christos { 437 1.1 christos char *cp = NULL; 438 1.1 christos static int first = 1; 439 1.1 christos 440 1.1 christos if (first) { 441 1.1 christos first = 0; 442 1.1 christos if (gethostname(domain, sizeof(domain)) == 0 && 443 1.1 christos (cp = strchr(domain, '.'))) 444 1.1 christos (void)strlcpy(domain, cp + 1, sizeof(domain)); 445 1.1 christos else 446 1.1 christos domain[0] = '\0'; 447 1.1 christos cp = NULL; 448 1.1 christos } 449 1.1 christos 450 1.1 christos if (sa->sa_len == 0) { 451 1.1 christos (void)strlcpy(line, "default", sizeof(line)); 452 1.1 christos return (line); 453 1.1 christos } 454 1.1 christos 455 1.1 christos switch (sa->sa_family) { 456 1.1 christos case AF_INET: 457 1.1 christos return routename4( 458 1.1 christos ((const struct sockaddr_in *)sa)->sin_addr.s_addr, 459 1.1 christos flags); 460 1.1 christos #ifdef INET6 461 1.1 christos case AF_INET6: 462 1.1 christos { 463 1.1 christos struct sockaddr_in6 sin6; 464 1.1 christos 465 1.1 christos memset(&sin6, 0, sizeof(sin6)); 466 1.1 christos memcpy(&sin6, sa, sa->sa_len); 467 1.1 christos sin6.sin6_len = sizeof(struct sockaddr_in6); 468 1.1 christos sin6.sin6_family = AF_INET6; 469 1.1 christos if (sa->sa_len == sizeof(struct sockaddr_in6)) 470 1.1 christos inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL| 471 1.1 christos INET6_IS_ADDR_MC_LINKLOCAL); 472 1.1 christos return routename6(&sin6, flags); 473 1.1 christos } 474 1.1 christos #endif 475 1.1 christos case AF_LINK: 476 1.1 christos return link_print(sa); 477 1.1 christos 478 1.1 christos #ifndef SMALL 479 1.1 christos case AF_MPLS: 480 1.1 christos return mpls_ntoa(sa); 481 1.1 christos 482 1.1 christos case AF_APPLETALK: 483 1.1 christos (void)snprintf(line, sizeof(line), "atalk %d.%d", 484 1.1 christos ((const struct sockaddr_at *)sa)->sat_addr.s_net, 485 1.1 christos ((const struct sockaddr_at *)sa)->sat_addr.s_node); 486 1.1 christos break; 487 1.1 christos #endif 488 1.1 christos 489 1.1 christos #if 0 /* XXX-elad */ 490 1.1 christos case AF_UNSPEC: 491 1.1 christos if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) { 492 1.1 christos static char name[RTLABEL_LEN]; 493 1.1 christos struct sockaddr_rtlabel *sr; 494 1.1 christos 495 1.1 christos sr = (struct sockaddr_rtlabel *)sa; 496 1.1 christos strlcpy(name, sr->sr_label, sizeof(name)); 497 1.1 christos return (name); 498 1.1 christos } 499 1.1 christos /* FALLTHROUGH */ 500 1.1 christos #endif 501 1.1 christos default: 502 1.1 christos (void)snprintf(line, sizeof(line), "(%d) %s", 503 1.1 christos sa->sa_family, any_ntoa(sa)); 504 1.1 christos break; 505 1.1 christos } 506 1.1 christos return (line); 507 1.1 christos } 508 1.1 christos 509 1.1 christos char * 510 1.1 christos routename4(in_addr_t in, int flags) 511 1.1 christos { 512 1.1 christos const char *cp = NULL; 513 1.1 christos struct in_addr ina; 514 1.1 christos struct hostent *hp; 515 1.1 christos 516 1.1 christos if (in == INADDR_ANY) 517 1.1 christos cp = "default"; 518 1.1 christos if (!cp && (flags & RT_NFLAG) == 0) { 519 1.1 christos if ((hp = gethostbyaddr((char *)&in, 520 1.1 christos sizeof(in), AF_INET)) != NULL) { 521 1.1 christos char *p; 522 1.1 christos if ((p = strchr(hp->h_name, '.')) && 523 1.1 christos !strcmp(p + 1, domain)) 524 1.1 christos *p = '\0'; 525 1.1 christos cp = hp->h_name; 526 1.1 christos } 527 1.1 christos } 528 1.1 christos ina.s_addr = in; 529 1.1 christos strlcpy(line, cp ? cp : inet_ntoa(ina), sizeof(line)); 530 1.1 christos 531 1.1 christos return (line); 532 1.1 christos } 533 1.1 christos 534 1.1 christos #ifdef INET6 535 1.1 christos char * 536 1.1 christos routename6(const struct sockaddr_in6 *sin6, int flags) 537 1.1 christos { 538 1.1 christos int niflags = 0; 539 1.1 christos 540 1.1 christos if ((flags & RT_NFLAG)) 541 1.1 christos niflags |= NI_NUMERICHOST; 542 1.1 christos else 543 1.1 christos niflags |= NI_NOFQDN; 544 1.1 christos 545 1.1 christos if (getnameinfo((const struct sockaddr *)sin6, sin6->sin6_len, 546 1.1 christos line, sizeof(line), NULL, 0, niflags) != 0) 547 1.1 christos strncpy(line, "invalid", sizeof(line)); 548 1.1 christos 549 1.1 christos return (line); 550 1.1 christos } 551 1.1 christos #endif 552 1.1 christos 553 1.1 christos /* 554 1.1 christos * Return the name of the network whose address is given. 555 1.1 christos * The address is assumed to be that of a net or subnet, not a host. 556 1.1 christos */ 557 1.1 christos char * 558 1.4 christos netname4(const struct sockaddr_in* sa4, const struct sockaddr_in *mask, int flags) 559 1.1 christos { 560 1.1 christos const char *cp = NULL; 561 1.1 christos struct netent *np = NULL; 562 1.1 christos int mbits; 563 1.4 christos in_addr_t in = sa4->sin_addr.s_addr; 564 1.4 christos 565 1.4 christos if (mask) { 566 1.4 christos in_addr_t m = mask->sin_addr.s_addr ; 567 1.4 christos m = ntohl(m); 568 1.4 christos mbits = m ? 33 - ffs(m) : 0; 569 1.4 christos } else 570 1.4 christos mbits = 0; 571 1.1 christos 572 1.1 christos in = ntohl(in); 573 1.4 christos if (in == INADDR_ANY && !mbits) 574 1.4 christos cp = "default"; 575 1.4 christos else if (!(flags & RT_NFLAG) && in != INADDR_ANY) { 576 1.1 christos if ((np = getnetbyaddr(in, AF_INET)) != NULL) 577 1.1 christos cp = np->n_name; 578 1.1 christos } 579 1.1 christos if (cp) 580 1.1 christos strlcpy(line, cp, sizeof(line)); 581 1.1 christos #define C(x) ((x) & 0xff) 582 1.1 christos else if (mbits < 9) 583 1.1 christos snprintf(line, sizeof(line), "%u/%d", C(in >> 24), mbits); 584 1.1 christos else if (mbits < 17) 585 1.1 christos snprintf(line, sizeof(line), "%u.%u/%d", 586 1.1 christos C(in >> 24) , C(in >> 16), mbits); 587 1.1 christos else if (mbits < 25) 588 1.1 christos snprintf(line, sizeof(line), "%u.%u.%u/%d", 589 1.1 christos C(in >> 24), C(in >> 16), C(in >> 8), mbits); 590 1.1 christos else 591 1.1 christos snprintf(line, sizeof(line), "%u.%u.%u.%u/%d", C(in >> 24), 592 1.1 christos C(in >> 16), C(in >> 8), C(in), mbits); 593 1.1 christos #undef C 594 1.4 christos return line; 595 1.1 christos } 596 1.1 christos 597 1.1 christos #ifdef INET6 598 1.1 christos char * 599 1.1 christos netname6(const struct sockaddr_in6 *sa6, const struct sockaddr_in6 *mask, int flags) 600 1.1 christos { 601 1.1 christos struct sockaddr_in6 sin6; 602 1.1 christos const u_char *p; 603 1.1 christos int masklen, final = 0, illegal = 0; 604 1.1 christos int i, lim, flag, error; 605 1.1 christos char hbuf[NI_MAXHOST]; 606 1.1 christos 607 1.1 christos sin6 = *sa6; 608 1.1 christos 609 1.1 christos flag = 0; 610 1.1 christos masklen = 0; 611 1.1 christos if (mask) { 612 1.1 christos lim = mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr); 613 1.1 christos if (lim < 0) 614 1.1 christos lim = 0; 615 1.1 christos else if (lim > (int)sizeof(struct in6_addr)) 616 1.1 christos lim = sizeof(struct in6_addr); 617 1.1 christos for (p = (const u_char *)&mask->sin6_addr, i = 0; i < lim; p++) { 618 1.1 christos if (final && *p) { 619 1.1 christos illegal++; 620 1.1 christos sin6.sin6_addr.s6_addr[i++] = 0x00; 621 1.1 christos continue; 622 1.1 christos } 623 1.1 christos 624 1.1 christos switch (*p & 0xff) { 625 1.1 christos case 0xff: 626 1.1 christos masklen += 8; 627 1.1 christos break; 628 1.1 christos case 0xfe: 629 1.1 christos masklen += 7; 630 1.1 christos final++; 631 1.1 christos break; 632 1.1 christos case 0xfc: 633 1.1 christos masklen += 6; 634 1.1 christos final++; 635 1.1 christos break; 636 1.1 christos case 0xf8: 637 1.1 christos masklen += 5; 638 1.1 christos final++; 639 1.1 christos break; 640 1.1 christos case 0xf0: 641 1.1 christos masklen += 4; 642 1.1 christos final++; 643 1.1 christos break; 644 1.1 christos case 0xe0: 645 1.1 christos masklen += 3; 646 1.1 christos final++; 647 1.1 christos break; 648 1.1 christos case 0xc0: 649 1.1 christos masklen += 2; 650 1.1 christos final++; 651 1.1 christos break; 652 1.1 christos case 0x80: 653 1.1 christos masklen += 1; 654 1.1 christos final++; 655 1.1 christos break; 656 1.1 christos case 0x00: 657 1.1 christos final++; 658 1.1 christos break; 659 1.1 christos default: 660 1.1 christos final++; 661 1.1 christos illegal++; 662 1.1 christos break; 663 1.1 christos } 664 1.1 christos 665 1.1 christos if (!illegal) 666 1.1 christos sin6.sin6_addr.s6_addr[i++] &= *p; 667 1.1 christos else 668 1.1 christos sin6.sin6_addr.s6_addr[i++] = 0x00; 669 1.1 christos } 670 1.1 christos while (i < (int)sizeof(struct in6_addr)) 671 1.1 christos sin6.sin6_addr.s6_addr[i++] = 0x00; 672 1.1 christos } else 673 1.1 christos masklen = 128; 674 1.1 christos 675 1.1 christos if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) { 676 1.1 christos snprintf(line, sizeof(line), "default"); 677 1.1 christos return (line); 678 1.1 christos } 679 1.1 christos 680 1.1 christos if (illegal) 681 1.1 christos warnx("illegal prefixlen"); 682 1.1 christos 683 1.1 christos if (flags & RT_NFLAG) 684 1.1 christos flag |= NI_NUMERICHOST; 685 1.1 christos error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 686 1.1 christos hbuf, sizeof(hbuf), NULL, 0, flag); 687 1.1 christos if (error) 688 1.1 christos snprintf(hbuf, sizeof(hbuf), "invalid"); 689 1.1 christos 690 1.1 christos snprintf(line, sizeof(line), "%s/%d", hbuf, masklen); 691 1.1 christos return (line); 692 1.1 christos } 693 1.1 christos #endif 694 1.1 christos 695 1.1 christos /* 696 1.1 christos * Return the name of the network whose address is given. 697 1.1 christos * The address is assumed to be that of a net or subnet, not a host. 698 1.1 christos */ 699 1.1 christos char * 700 1.1 christos netname(const struct sockaddr *sa, const struct sockaddr *mask, int flags) 701 1.1 christos { 702 1.1 christos switch (sa->sa_family) { 703 1.1 christos 704 1.1 christos case AF_INET: 705 1.4 christos return netname4((const struct sockaddr_in *)sa, 706 1.4 christos (const struct sockaddr_in *)mask, flags); 707 1.1 christos #ifdef INET6 708 1.1 christos case AF_INET6: 709 1.1 christos return netname6((const struct sockaddr_in6 *)sa, 710 1.1 christos (const struct sockaddr_in6 *)mask, flags); 711 1.1 christos #endif 712 1.1 christos case AF_LINK: 713 1.1 christos return link_print(sa); 714 1.1 christos default: 715 1.1 christos snprintf(line, sizeof(line), "af %d: %s", 716 1.1 christos sa->sa_family, any_ntoa(sa)); 717 1.1 christos break; 718 1.1 christos } 719 1.1 christos return (line); 720 1.1 christos } 721 1.1 christos 722 1.1 christos static const char hexlist[] = "0123456789abcdef"; 723 1.1 christos 724 1.1 christos char * 725 1.1 christos any_ntoa(const struct sockaddr *sa) 726 1.1 christos { 727 1.1 christos static char obuf[240]; 728 1.1 christos const char *in = sa->sa_data; 729 1.1 christos char *out = obuf; 730 1.1 christos int len = sa->sa_len - offsetof(struct sockaddr, sa_data); 731 1.1 christos 732 1.1 christos *out++ = 'Q'; 733 1.1 christos do { 734 1.1 christos *out++ = hexlist[(*in >> 4) & 15]; 735 1.1 christos *out++ = hexlist[(*in++) & 15]; 736 1.1 christos *out++ = '.'; 737 1.1 christos } while (--len > 0 && (out + 3) < &obuf[sizeof(obuf) - 1]); 738 1.1 christos out[-1] = '\0'; 739 1.1 christos return (obuf); 740 1.1 christos } 741 1.1 christos 742 1.1 christos static char * 743 1.1 christos link_print(const struct sockaddr *sa) 744 1.1 christos { 745 1.1 christos const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)sa; 746 1.1 christos const u_char *lla = (const u_char *)sdl->sdl_data + sdl->sdl_nlen; 747 1.1 christos 748 1.1 christos if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && 749 1.1 christos sdl->sdl_slen == 0) { 750 1.1 christos (void)snprintf(line, sizeof(line), "link#%d", sdl->sdl_index); 751 1.1 christos return (line); 752 1.1 christos } 753 1.1 christos switch (sdl->sdl_type) { 754 1.1 christos case IFT_ETHER: 755 1.1 christos case IFT_CARP: 756 1.1 christos return ether_ntoa((const struct ether_addr *)lla); 757 1.1 christos default: 758 1.1 christos return link_ntoa(sdl); 759 1.1 christos } 760 1.1 christos } 761 1.1 christos 762 1.1 christos #ifndef SMALL 763 1.1 christos char * 764 1.1 christos mpls_ntoa(const struct sockaddr *sa) 765 1.1 christos { 766 1.1 christos static char obuf[16]; 767 1.1 christos size_t olen; 768 1.1 christos const union mpls_shim *pms; 769 1.1 christos union mpls_shim ms; 770 1.1 christos int psize = sizeof(struct sockaddr_mpls); 771 1.1 christos 772 1.1 christos pms = &((const struct sockaddr_mpls*)sa)->smpls_addr; 773 1.1 christos ms.s_addr = ntohl(pms->s_addr); 774 1.1 christos 775 1.1 christos snprintf(obuf, sizeof(obuf), "%u", ms.shim.label); 776 1.1 christos 777 1.1 christos while(psize < sa->sa_len) { 778 1.1 christos pms++; 779 1.1 christos ms.s_addr = ntohl(pms->s_addr); 780 1.1 christos olen = strlen(obuf); 781 1.1 christos snprintf(obuf + olen, sizeof(obuf) - olen, ",%u", 782 1.1 christos ms.shim.label); 783 1.1 christos psize+=sizeof(ms); 784 1.1 christos } 785 1.1 christos return obuf; 786 1.1 christos } 787 1.1 christos #endif 788 1.1 christos 789 1.1 christos void 790 1.1 christos p_addr(const struct sockaddr *sa, const struct sockaddr *mask, int rflags, int flags) 791 1.1 christos { 792 1.1 christos p_sockaddr(sa, mask, rflags, WID_DST(sa->sa_family), flags); 793 1.1 christos } 794 1.1 christos 795 1.1 christos void 796 1.1 christos p_gwaddr(const struct sockaddr *sa, int gwaf, int flags) 797 1.1 christos { 798 1.1 christos p_sockaddr(sa, 0, RTF_HOST, WID_GW(gwaf), flags); 799 1.1 christos } 800