1 /* $OpenBSD: show.c,v 1.76 2009/02/03 16:44:15 michele Exp $ */ 2 /* $NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr 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/param.h> 34 #include <sys/socket.h> 35 #include <sys/mbuf.h> 36 #include <sys/sysctl.h> 37 38 #include <net/if.h> 39 #include <net/if_dl.h> 40 #include <net/if_types.h> 41 #include <net/pfkeyv2.h> 42 #include <net/route.h> 43 #include <netinet/in.h> 44 #include <netinet/if_ether.h> 45 #include <netinet/ip_ipsp.h> 46 #include <netmpls/mpls.h> 47 #include <arpa/inet.h> 48 49 #include <err.h> 50 #include <errno.h> 51 #include <netdb.h> 52 #include <stdio.h> 53 #include <stddef.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 #include "show.h" 59 60 char *any_ntoa(const struct sockaddr *); 61 char *link_print(struct sockaddr *); 62 char *label_print_op(u_int32_t); 63 char *label_print(struct sockaddr *, struct sockaddr *); 64 65 extern int nflag; 66 extern int Fflag; 67 68 #define PLEN (LONG_BIT / 4 + 2) /* XXX this is also defined in netstat.h */ 69 70 #define ROUNDUP(a) \ 71 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 72 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 73 74 #define PFKEYV2_CHUNK sizeof(u_int64_t) 75 76 /* 77 * Definitions for showing gateway flags. 78 */ 79 struct bits { 80 int b_mask; 81 char b_val; 82 }; 83 static const struct bits bits[] = { 84 { RTF_UP, 'U' }, 85 { RTF_GATEWAY, 'G' }, 86 { RTF_HOST, 'H' }, 87 { RTF_REJECT, 'R' }, 88 { RTF_BLACKHOLE, 'B' }, 89 { RTF_DYNAMIC, 'D' }, 90 { RTF_MODIFIED, 'M' }, 91 { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ 92 { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ 93 { RTF_CLONING, 'C' }, 94 { RTF_XRESOLVE, 'X' }, 95 { RTF_LLINFO, 'L' }, 96 { RTF_STATIC, 'S' }, 97 { RTF_PROTO1, '1' }, 98 { RTF_PROTO2, '2' }, 99 { RTF_PROTO3, '3' }, 100 { RTF_CLONED, 'c' }, 101 { RTF_JUMBO, 'J' }, 102 { RTF_MPATH, 'P' }, 103 { 0 } 104 }; 105 106 void pr_rthdr(int); 107 void p_rtentry(struct rt_msghdr *); 108 void p_pfkentry(struct sadb_msg *); 109 void pr_family(int); 110 void p_encap(struct sockaddr *, struct sockaddr *, int); 111 void p_protocol(struct sadb_protocol *, struct sockaddr *, struct 112 sadb_protocol *, int); 113 void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int); 114 void p_sockaddr_mpls(struct sockaddr *, struct sockaddr *, int, int); 115 void p_flags(int, char *); 116 char *routename4(in_addr_t); 117 char *routename6(struct sockaddr_in6 *); 118 void index_pfk(struct sadb_msg *, void **); 119 120 /* 121 * Print routing tables. 122 */ 123 void 124 p_rttables(int af, u_int tableid) 125 { 126 struct rt_msghdr *rtm; 127 struct sadb_msg *msg; 128 char *buf = NULL, *next, *lim = NULL; 129 size_t needed; 130 int mib[7]; 131 struct sockaddr *sa; 132 133 mib[0] = CTL_NET; 134 mib[1] = PF_ROUTE; 135 mib[2] = 0; 136 mib[3] = af; 137 mib[4] = NET_RT_DUMP; 138 mib[5] = 0; 139 mib[6] = tableid; 140 141 if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) 142 err(1, "route-sysctl-estimate"); 143 if (needed > 0) { 144 if ((buf = malloc(needed)) == 0) 145 err(1, NULL); 146 if (sysctl(mib, 7, buf, &needed, NULL, 0) < 0) 147 err(1, "sysctl of routing table"); 148 lim = buf + needed; 149 } 150 151 printf("Routing tables\n"); 152 153 if (buf) { 154 for (next = buf; next < lim; next += rtm->rtm_msglen) { 155 rtm = (struct rt_msghdr *)next; 156 if (rtm->rtm_version != RTM_VERSION) 157 continue; 158 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 159 if (af != AF_UNSPEC && sa->sa_family != af) 160 continue; 161 p_rtentry(rtm); 162 } 163 free(buf); 164 buf = NULL; 165 } 166 167 if (af != 0 && af != PF_KEY) 168 return; 169 170 mib[0] = CTL_NET; 171 mib[1] = PF_KEY; 172 mib[2] = PF_KEY_V2; 173 mib[3] = NET_KEY_SPD_DUMP; 174 mib[4] = mib[5] = 0; 175 176 if (sysctl(mib, 4, NULL, &needed, NULL, 0) == -1) { 177 if (errno == ENOPROTOOPT) 178 return; 179 err(1, "spd-sysctl-estimate"); 180 } 181 if (needed > 0) { 182 if ((buf = malloc(needed)) == 0) 183 err(1, NULL); 184 if (sysctl(mib, 4, buf, &needed, NULL, 0) == -1) 185 err(1,"sysctl of spd"); 186 lim = buf + needed; 187 } 188 189 if (buf) { 190 printf("\nEncap:\n"); 191 192 for (next = buf; next < lim; next += msg->sadb_msg_len * 193 PFKEYV2_CHUNK) { 194 msg = (struct sadb_msg *)next; 195 if (msg->sadb_msg_len == 0) 196 break; 197 p_pfkentry(msg); 198 } 199 free(buf); 200 buf = NULL; 201 } 202 } 203 204 /* 205 * column widths; each followed by one space 206 * width of destination/gateway column 207 * strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 208 */ 209 #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18) 210 211 int 212 WID_DST(int af) 213 { 214 215 if (nflag) 216 switch (af) { 217 case AF_MPLS: 218 return 34; 219 case AF_INET6: 220 return 34; 221 default: 222 return 18; 223 } 224 else 225 switch (af) { 226 case AF_MPLS: 227 return 34; 228 default: 229 return 18; 230 } 231 } 232 233 /* 234 * Print header for routing table columns. 235 */ 236 void 237 pr_rthdr(int af) 238 { 239 switch (af) { 240 case PF_KEY: 241 printf("%-18s %-5s %-18s %-5s %-5s %-22s\n", 242 "Source", "Port", "Destination", 243 "Port", "Proto", "SA(Address/Proto/Type/Direction)"); 244 break; 245 case PF_MPLS: 246 printf("%-16s %-10s %-6s %-18s %-6.6s %5.5s %8.8s %5.5s %4.4s %s\n", 247 "In label", "Out label", "Op", "Gateway", 248 "Flags", "Refs", "Use", "Mtu", "Prio", "Interface"); 249 break; 250 default: 251 printf("%-*.*s %-*.*s %-6.6s %5.5s %8.8s %5.5s %4.4s %s\n", 252 WID_DST(af), WID_DST(af), "Destination", 253 WID_GW(af), WID_GW(af), "Gateway", 254 "Flags", "Refs", "Use", "Mtu", "Prio", "Iface"); 255 break; 256 } 257 } 258 259 static void 260 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 261 { 262 int i; 263 264 for (i = 0; i < RTAX_MAX; i++) { 265 if (addrs & (1 << i)) { 266 rti_info[i] = sa; 267 sa = (struct sockaddr *)((char *)(sa) + 268 ROUNDUP(sa->sa_len)); 269 } else 270 rti_info[i] = NULL; 271 } 272 } 273 274 /* 275 * Print a routing table entry. 276 */ 277 void 278 p_rtentry(struct rt_msghdr *rtm) 279 { 280 static int old_af = -1; 281 struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 282 struct sockaddr *mask, *rti_info[RTAX_MAX]; 283 char ifbuf[IF_NAMESIZE]; 284 285 if (sa->sa_family == AF_KEY) 286 return; 287 288 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 289 if (Fflag && rti_info[RTAX_GATEWAY]->sa_family != sa->sa_family) { 290 return; 291 } 292 if (old_af != sa->sa_family) { 293 old_af = sa->sa_family; 294 pr_family(sa->sa_family); 295 pr_rthdr(sa->sa_family); 296 } 297 298 mask = rti_info[RTAX_NETMASK]; 299 if ((sa = rti_info[RTAX_DST]) == NULL) 300 return; 301 302 p_sockaddr(sa, mask, rtm->rtm_flags, WID_DST(sa->sa_family)); 303 p_sockaddr_mpls(sa, rti_info[RTAX_SRC], rtm->rtm_mpls, 304 WID_DST(sa->sa_family)); 305 306 p_sockaddr(rti_info[RTAX_GATEWAY], NULL, RTF_HOST, 307 WID_GW(sa->sa_family)); 308 309 p_flags(rtm->rtm_flags, "%-6.6s "); 310 printf("%5u %8llu ", rtm->rtm_rmx.rmx_refcnt, 311 rtm->rtm_rmx.rmx_pksent); 312 if (rtm->rtm_rmx.rmx_mtu) 313 printf("%5u ", rtm->rtm_rmx.rmx_mtu); 314 else 315 printf("%5s ", "-"); 316 putchar((rtm->rtm_rmx.rmx_locks & RTV_MTU) ? 'L' : ' '); 317 printf(" %2d %.16s", rtm->rtm_priority & RTP_MASK, 318 if_indextoname(rtm->rtm_index, ifbuf)); 319 putchar('\n'); 320 } 321 322 /* 323 * Print a pfkey/encap entry. 324 */ 325 void 326 p_pfkentry(struct sadb_msg *msg) 327 { 328 static int old = 0; 329 struct sadb_address *saddr; 330 struct sadb_protocol *sap, *saft; 331 struct sockaddr *sa, *mask; 332 void *headers[SADB_EXT_MAX + 1]; 333 334 if (!old) { 335 pr_rthdr(PF_KEY); 336 old++; 337 } 338 339 bzero(headers, sizeof(headers)); 340 index_pfk(msg, headers); 341 342 /* These are always set */ 343 saddr = headers[SADB_X_EXT_SRC_FLOW]; 344 sa = (struct sockaddr *)(saddr + 1); 345 saddr = headers[SADB_X_EXT_SRC_MASK]; 346 mask = (struct sockaddr *)(saddr + 1); 347 p_encap(sa, mask, WID_DST(sa->sa_family)); 348 349 /* These are always set, too. */ 350 saddr = headers[SADB_X_EXT_DST_FLOW]; 351 sa = (struct sockaddr *)(saddr + 1); 352 saddr = headers[SADB_X_EXT_DST_MASK]; 353 mask = (struct sockaddr *)(saddr + 1); 354 p_encap(sa, mask, WID_DST(sa->sa_family)); 355 356 /* Bypass and deny flows do not set SADB_EXT_ADDRESS_DST! */ 357 sap = headers[SADB_X_EXT_PROTOCOL]; 358 saft = headers[SADB_X_EXT_FLOW_TYPE]; 359 saddr = headers[SADB_EXT_ADDRESS_DST]; 360 if (saddr) 361 sa = (struct sockaddr *)(saddr + 1); 362 else 363 sa = NULL; 364 p_protocol(sap, sa, saft, msg->sadb_msg_satype); 365 366 printf("\n"); 367 } 368 369 /* 370 * Print address family header before a section of the routing table. 371 */ 372 void 373 pr_family(int af) 374 { 375 char *afname; 376 377 switch (af) { 378 case AF_INET: 379 afname = "Internet"; 380 break; 381 case AF_INET6: 382 afname = "Internet6"; 383 break; 384 case PF_KEY: 385 afname = "Encap"; 386 break; 387 case AF_MPLS: 388 afname = "MPLS"; 389 break; 390 case AF_APPLETALK: 391 afname = "AppleTalk"; 392 break; 393 default: 394 afname = NULL; 395 break; 396 } 397 if (afname) 398 printf("\n%s:\n", afname); 399 else 400 printf("\nProtocol Family %d:\n", af); 401 } 402 403 void 404 p_encap(struct sockaddr *sa, struct sockaddr *mask, int width) 405 { 406 char *cp; 407 unsigned short port = 0; 408 409 if (mask) 410 cp = netname(sa, mask); 411 else 412 cp = routename(sa); 413 switch (sa->sa_family) { 414 case AF_INET: 415 port = ntohs(((struct sockaddr_in *)sa)->sin_port); 416 break; 417 case AF_INET6: 418 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 419 break; 420 } 421 if (width < 0) 422 printf("%s", cp); 423 else { 424 if (nflag) 425 printf("%-*s %-5u ", width, cp, port); 426 else 427 printf("%-*.*s %-5u ", width, width, cp, port); 428 } 429 } 430 431 void 432 p_protocol(struct sadb_protocol *sap, struct sockaddr *sa, struct sadb_protocol 433 *saft, int proto) 434 { 435 printf("%-6u", sap->sadb_protocol_proto); 436 437 if (sa) 438 p_sockaddr(sa, NULL, 0, -1); 439 else 440 printf("none"); 441 442 switch (proto) { 443 case SADB_SATYPE_ESP: 444 printf("/esp"); 445 break; 446 case SADB_SATYPE_AH: 447 printf("/ah"); 448 break; 449 case SADB_X_SATYPE_IPCOMP: 450 printf("/ipcomp"); 451 break; 452 case SADB_X_SATYPE_IPIP: 453 printf("/ipip"); 454 break; 455 default: 456 printf("/<unknown>"); 457 } 458 459 switch(saft->sadb_protocol_proto) { 460 case SADB_X_FLOW_TYPE_USE: 461 printf("/use"); 462 break; 463 case SADB_X_FLOW_TYPE_REQUIRE: 464 printf("/require"); 465 break; 466 case SADB_X_FLOW_TYPE_ACQUIRE: 467 printf("/acquire"); 468 break; 469 case SADB_X_FLOW_TYPE_DENY: 470 printf("/deny"); 471 break; 472 case SADB_X_FLOW_TYPE_BYPASS: 473 printf("/bypass"); 474 break; 475 case SADB_X_FLOW_TYPE_DONTACQ: 476 printf("/dontacq"); 477 break; 478 default: 479 printf("/<unknown type>"); 480 } 481 482 switch(saft->sadb_protocol_direction) { 483 case IPSP_DIRECTION_IN: 484 printf("/in"); 485 break; 486 case IPSP_DIRECTION_OUT: 487 printf("/out"); 488 break; 489 default: 490 printf("/<unknown>"); 491 } 492 } 493 494 void 495 p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) 496 { 497 char *cp; 498 499 switch (sa->sa_family) { 500 case AF_INET6: 501 { 502 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 503 struct in6_addr *in6 = &sa6->sin6_addr; 504 505 /* 506 * XXX: This is a special workaround for KAME kernels. 507 * sin6_scope_id field of SA should be set in the future. 508 */ 509 if (IN6_IS_ADDR_LINKLOCAL(in6) || 510 IN6_IS_ADDR_MC_LINKLOCAL(in6) || 511 IN6_IS_ADDR_MC_INTFACELOCAL(in6)) { 512 /* XXX: override is ok? */ 513 sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *) 514 &in6->s6_addr[2]); 515 *(u_short *)&in6->s6_addr[2] = 0; 516 } 517 if (flags & RTF_HOST) 518 cp = routename((struct sockaddr *)sa6); 519 else 520 cp = netname((struct sockaddr *)sa6, mask); 521 break; 522 } 523 case AF_MPLS: 524 return; 525 default: 526 if ((flags & RTF_HOST) || mask == NULL) 527 cp = routename(sa); 528 else 529 cp = netname(sa, mask); 530 break; 531 } 532 if (width < 0) 533 printf("%s", cp); 534 else { 535 if (nflag) 536 printf("%-*s ", width, cp); 537 else 538 printf("%-*.*s ", width, width, cp); 539 } 540 } 541 542 static char line[MAXHOSTNAMELEN]; 543 static char domain[MAXHOSTNAMELEN]; 544 545 void 546 p_sockaddr_mpls(struct sockaddr *in, struct sockaddr *out, int flags, int width) 547 { 548 char *cp; 549 550 if (in->sa_family != AF_MPLS) 551 return; 552 553 if (flags & MPLS_OP_POP) 554 cp = label_print(in, NULL); 555 else 556 cp = label_print(in, out); 557 558 snprintf(cp, MAXHOSTNAMELEN, "%s %s", cp, 559 label_print_op(flags)); 560 561 printf("%-*s ", width, cp); 562 } 563 564 void 565 p_flags(int f, char *format) 566 { 567 char name[33], *flags; 568 const struct bits *p = bits; 569 570 for (flags = name; p->b_mask && flags < &name[sizeof(name) - 2]; p++) 571 if (p->b_mask & f) 572 *flags++ = p->b_val; 573 *flags = '\0'; 574 printf(format, name); 575 } 576 577 char * 578 routename(struct sockaddr *sa) 579 { 580 char *cp = NULL; 581 static int first = 1; 582 583 if (first) { 584 first = 0; 585 if (gethostname(domain, sizeof(domain)) == 0 && 586 (cp = strchr(domain, '.'))) 587 (void)strlcpy(domain, cp + 1, sizeof(domain)); 588 else 589 domain[0] = '\0'; 590 cp = NULL; 591 } 592 593 if (sa->sa_len == 0) { 594 (void)strlcpy(line, "default", sizeof(line)); 595 return (line); 596 } 597 598 switch (sa->sa_family) { 599 case AF_INET: 600 return 601 (routename4(((struct sockaddr_in *)sa)->sin_addr.s_addr)); 602 603 case AF_INET6: 604 { 605 struct sockaddr_in6 sin6; 606 607 memset(&sin6, 0, sizeof(sin6)); 608 memcpy(&sin6, sa, sa->sa_len); 609 sin6.sin6_len = sizeof(struct sockaddr_in6); 610 sin6.sin6_family = AF_INET6; 611 if (sa->sa_len == sizeof(struct sockaddr_in6) && 612 (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || 613 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) || 614 IN6_IS_ADDR_MC_INTFACELOCAL(&sin6.sin6_addr)) && 615 sin6.sin6_scope_id == 0) { 616 sin6.sin6_scope_id = 617 ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 618 sin6.sin6_addr.s6_addr[2] = 0; 619 sin6.sin6_addr.s6_addr[3] = 0; 620 } 621 return (routename6(&sin6)); 622 } 623 624 case AF_LINK: 625 return (link_print(sa)); 626 case AF_MPLS: 627 return (label_print(sa, NULL)); 628 case AF_UNSPEC: 629 if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) { 630 static char name[RTLABEL_LEN]; 631 struct sockaddr_rtlabel *sr; 632 633 sr = (struct sockaddr_rtlabel *)sa; 634 (void)strlcpy(name, sr->sr_label, sizeof(name)); 635 return (name); 636 } 637 /* FALLTHROUGH */ 638 default: 639 (void)snprintf(line, sizeof(line), "(%d) %s", 640 sa->sa_family, any_ntoa(sa)); 641 break; 642 } 643 return (line); 644 } 645 646 char * 647 routename4(in_addr_t in) 648 { 649 char *cp = NULL; 650 struct in_addr ina; 651 struct hostent *hp; 652 653 if (in == INADDR_ANY) 654 cp = "default"; 655 if (!cp && !nflag) { 656 if ((hp = gethostbyaddr((char *)&in, 657 sizeof(in), AF_INET)) != NULL) { 658 if ((cp = strchr(hp->h_name, '.')) && 659 !strcmp(cp + 1, domain)) 660 *cp = '\0'; 661 cp = hp->h_name; 662 } 663 } 664 ina.s_addr = in; 665 strlcpy(line, cp ? cp : inet_ntoa(ina), sizeof(line)); 666 667 return (line); 668 } 669 670 char * 671 routename6(struct sockaddr_in6 *sin6) 672 { 673 int niflags = 0; 674 675 if (nflag) 676 niflags |= NI_NUMERICHOST; 677 else 678 niflags |= NI_NOFQDN; 679 680 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 681 line, sizeof(line), NULL, 0, niflags) != 0) 682 strncpy(line, "invalid", sizeof(line)); 683 684 return (line); 685 } 686 687 /* 688 * Return the name of the network whose address is given. 689 * The address is assumed to be that of a net or subnet, not a host. 690 */ 691 char * 692 netname4(in_addr_t in, struct sockaddr_in *maskp) 693 { 694 char *cp = NULL; 695 struct netent *np = NULL; 696 in_addr_t mask; 697 int mbits; 698 699 in = ntohl(in); 700 mask = maskp ? ntohl(maskp->sin_addr.s_addr) : 0; 701 if (!nflag && in != INADDR_ANY) { 702 if ((np = getnetbyaddr(in, AF_INET)) != NULL) 703 cp = np->n_name; 704 } 705 if (in == INADDR_ANY) 706 cp = "default"; 707 mbits = mask ? 33 - ffs(mask) : 0; 708 if (cp) 709 strlcpy(line, cp, sizeof(line)); 710 #define C(x) ((x) & 0xff) 711 else if (mbits < 9) 712 snprintf(line, sizeof(line), "%u/%d", C(in >> 24), mbits); 713 else if (mbits < 17) 714 snprintf(line, sizeof(line), "%u.%u/%d", 715 C(in >> 24) , C(in >> 16), mbits); 716 else if (mbits < 25) 717 snprintf(line, sizeof(line), "%u.%u.%u/%d", 718 C(in >> 24), C(in >> 16), C(in >> 8), mbits); 719 else 720 snprintf(line, sizeof(line), "%u.%u.%u.%u/%d", C(in >> 24), 721 C(in >> 16), C(in >> 8), C(in), mbits); 722 #undef C 723 return (line); 724 } 725 726 char * 727 netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask) 728 { 729 struct sockaddr_in6 sin6; 730 u_char *p; 731 int masklen, final = 0, illegal = 0; 732 int i, lim, flag, error; 733 char hbuf[NI_MAXHOST]; 734 735 sin6 = *sa6; 736 737 flag = 0; 738 masklen = 0; 739 if (mask) { 740 lim = mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr); 741 lim = lim < (int)sizeof(struct in6_addr) ? 742 lim : sizeof(struct in6_addr); 743 for (p = (u_char *)&mask->sin6_addr, i = 0; i < lim; p++) { 744 if (final && *p) { 745 illegal++; 746 sin6.sin6_addr.s6_addr[i++] = 0x00; 747 continue; 748 } 749 750 switch (*p & 0xff) { 751 case 0xff: 752 masklen += 8; 753 break; 754 case 0xfe: 755 masklen += 7; 756 final++; 757 break; 758 case 0xfc: 759 masklen += 6; 760 final++; 761 break; 762 case 0xf8: 763 masklen += 5; 764 final++; 765 break; 766 case 0xf0: 767 masklen += 4; 768 final++; 769 break; 770 case 0xe0: 771 masklen += 3; 772 final++; 773 break; 774 case 0xc0: 775 masklen += 2; 776 final++; 777 break; 778 case 0x80: 779 masklen += 1; 780 final++; 781 break; 782 case 0x00: 783 final++; 784 break; 785 default: 786 final++; 787 illegal++; 788 break; 789 } 790 791 if (!illegal) 792 sin6.sin6_addr.s6_addr[i++] &= *p; 793 else 794 sin6.sin6_addr.s6_addr[i++] = 0x00; 795 } 796 while (i < sizeof(struct in6_addr)) 797 sin6.sin6_addr.s6_addr[i++] = 0x00; 798 } else 799 masklen = 128; 800 801 if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) 802 return ("default"); 803 804 if (illegal) 805 warnx("illegal prefixlen"); 806 807 if (nflag) 808 flag |= NI_NUMERICHOST; 809 error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 810 hbuf, sizeof(hbuf), NULL, 0, flag); 811 if (error) 812 snprintf(hbuf, sizeof(hbuf), "invalid"); 813 814 snprintf(line, sizeof(line), "%s/%d", hbuf, masklen); 815 return (line); 816 } 817 818 /* 819 * Return the name of the network whose address is given. 820 * The address is assumed to be that of a net or subnet, not a host. 821 */ 822 char * 823 netname(struct sockaddr *sa, struct sockaddr *mask) 824 { 825 switch (sa->sa_family) { 826 case AF_INET: 827 return netname4(((struct sockaddr_in *)sa)->sin_addr.s_addr, 828 (struct sockaddr_in *)mask); 829 case AF_INET6: 830 return netname6((struct sockaddr_in6 *)sa, 831 (struct sockaddr_in6 *)mask); 832 case AF_LINK: 833 return (link_print(sa)); 834 case AF_MPLS: 835 return (label_print(sa, NULL)); 836 default: 837 snprintf(line, sizeof(line), "af %d: %s", 838 sa->sa_family, any_ntoa(sa)); 839 break; 840 } 841 return (line); 842 } 843 844 static const char hexlist[] = "0123456789abcdef"; 845 846 char * 847 any_ntoa(const struct sockaddr *sa) 848 { 849 static char obuf[240]; 850 const char *in = sa->sa_data; 851 char *out = obuf; 852 int len = sa->sa_len - offsetof(struct sockaddr, sa_data); 853 854 *out++ = 'Q'; 855 do { 856 *out++ = hexlist[(*in >> 4) & 15]; 857 *out++ = hexlist[(*in++) & 15]; 858 *out++ = '.'; 859 } while (--len > 0 && (out + 3) < &obuf[sizeof(obuf) - 1]); 860 out[-1] = '\0'; 861 return (obuf); 862 } 863 864 char * 865 link_print(struct sockaddr *sa) 866 { 867 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 868 u_char *lla = (u_char *)sdl->sdl_data + sdl->sdl_nlen; 869 870 if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && 871 sdl->sdl_slen == 0) { 872 (void)snprintf(line, sizeof(line), "link#%d", sdl->sdl_index); 873 return (line); 874 } 875 switch (sdl->sdl_type) { 876 case IFT_ETHER: 877 case IFT_CARP: 878 return (ether_ntoa((struct ether_addr *)lla)); 879 default: 880 return (link_ntoa(sdl)); 881 } 882 } 883 884 char * 885 label_print_op(u_int32_t type) 886 { 887 switch (type & (MPLS_OP_PUSH | MPLS_OP_POP | MPLS_OP_SWAP)) { 888 case MPLS_OP_POP: 889 return ("POP"); 890 case MPLS_OP_SWAP: 891 return ("SWAP"); 892 case MPLS_OP_PUSH: 893 return ("PUSH"); 894 default: 895 return ("?"); 896 } 897 } 898 899 char * 900 label_print(struct sockaddr *in, struct sockaddr *out) 901 { 902 struct sockaddr_mpls *insmpls = (struct sockaddr_mpls *)in; 903 struct sockaddr_mpls *outsmpls = (struct sockaddr_mpls *)out; 904 char ifname_in[IF_NAMESIZE]; 905 char ifname_out[IF_NAMESIZE]; 906 char *in_label; 907 char *out_label; 908 909 if (asprintf(&in_label, "%u", 910 ntohl(insmpls->smpls_label) >> MPLS_LABEL_OFFSET) == -1) 911 err(1, NULL); 912 913 if (outsmpls) { 914 if (asprintf(&out_label, "%u", 915 ntohl(outsmpls->smpls_label) >> MPLS_LABEL_OFFSET) == -1) 916 err(1, NULL); 917 } else { 918 if (asprintf(&out_label, "-") == -1) 919 err(1, NULL); 920 } 921 922 (void)snprintf(line, sizeof(line), "%-16s %-10s", in_label, 923 out_label); 924 925 free(in_label); 926 free(out_label); 927 928 return (line); 929 } 930 931 void 932 index_pfk(struct sadb_msg *msg, void **headers) 933 { 934 struct sadb_ext *ext; 935 936 for (ext = (struct sadb_ext *)(msg + 1); 937 (size_t)((u_int8_t *)ext - (u_int8_t *)msg) < 938 msg->sadb_msg_len * PFKEYV2_CHUNK && ext->sadb_ext_len > 0; 939 ext = (struct sadb_ext *)((u_int8_t *)ext + 940 ext->sadb_ext_len * PFKEYV2_CHUNK)) { 941 switch (ext->sadb_ext_type) { 942 case SADB_EXT_ADDRESS_SRC: 943 headers[SADB_EXT_ADDRESS_SRC] = (void *)ext; 944 break; 945 case SADB_EXT_ADDRESS_DST: 946 headers[SADB_EXT_ADDRESS_DST] = (void *)ext; 947 break; 948 case SADB_X_EXT_PROTOCOL: 949 headers[SADB_X_EXT_PROTOCOL] = (void *)ext; 950 break; 951 case SADB_X_EXT_SRC_FLOW: 952 headers[SADB_X_EXT_SRC_FLOW] = (void *)ext; 953 break; 954 case SADB_X_EXT_DST_FLOW: 955 headers[SADB_X_EXT_DST_FLOW] = (void *)ext; 956 break; 957 case SADB_X_EXT_SRC_MASK: 958 headers[SADB_X_EXT_SRC_MASK] = (void *)ext; 959 break; 960 case SADB_X_EXT_DST_MASK: 961 headers[SADB_X_EXT_DST_MASK] = (void *)ext; 962 break; 963 case SADB_X_EXT_FLOW_TYPE: 964 headers[SADB_X_EXT_FLOW_TYPE] = (void *)ext; 965 default: 966 /* Ignore. */ 967 break; 968 } 969 } 970 } 971