1175061Sobrien/*- 21590Srgrimes * Copyright (c) 1983, 1988, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 30132671Scharnier#if 0 311590Srgrimes#ifndef lint 3213430Speterstatic char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95"; 33132671Scharnier#endif /* not lint */ 345811Swollman#endif 351590Srgrimes 36132671Scharnier#include <sys/cdefs.h> 37132671Scharnier__FBSDID("$FreeBSD$"); 38132671Scharnier 391590Srgrimes#include <sys/param.h> 401590Srgrimes#include <sys/protosw.h> 411590Srgrimes#include <sys/socket.h> 42171465Sjhb#include <sys/socketvar.h> 4320287Swollman#include <sys/time.h> 441590Srgrimes 4593957Sru#include <net/ethernet.h> 461590Srgrimes#include <net/if.h> 4721263Swollman#include <net/if_var.h> 481590Srgrimes#include <net/if_dl.h> 491590Srgrimes#include <net/if_types.h> 50120716Ssam#include <net/radix.h> 51263478Sglebius#define _WANT_RTENTRY 521590Srgrimes#include <net/route.h> 5316178Sjulian 541590Srgrimes#include <netinet/in.h> 5511819Sjulian#include <netipx/ipx.h> 5616178Sjulian#include <netatalk/at.h> 5752419Sjulian#include <netgraph/ng_socket.h> 5811819Sjulian 591590Srgrimes#include <sys/sysctl.h> 601590Srgrimes 6154263Sshin#include <arpa/inet.h> 62263335Sglebius#include <ifaddrs.h> 6374262Sbrian#include <libutil.h> 641590Srgrimes#include <netdb.h> 65263335Sglebius#include <nlist.h> 66160787Syar#include <stdint.h> 671590Srgrimes#include <stdio.h> 681590Srgrimes#include <stdlib.h> 691590Srgrimes#include <string.h> 70160130Soleg#include <sysexits.h> 71200462Sdelphij#include <unistd.h> 725811Swollman#include <err.h> 731590Srgrimes#include "netstat.h" 741590Srgrimes 75175061Sobrien#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) 761590Srgrimes 771590Srgrimes/* 781590Srgrimes * Definitions for showing gateway flags. 791590Srgrimes */ 801590Srgrimesstruct bits { 815103Swollman u_long b_mask; 821590Srgrimes char b_val; 831590Srgrimes} bits[] = { 841590Srgrimes { RTF_UP, 'U' }, 851590Srgrimes { RTF_GATEWAY, 'G' }, 861590Srgrimes { RTF_HOST, 'H' }, 871590Srgrimes { RTF_REJECT, 'R' }, 881590Srgrimes { RTF_DYNAMIC, 'D' }, 891590Srgrimes { RTF_MODIFIED, 'M' }, 901590Srgrimes { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ 911590Srgrimes { RTF_XRESOLVE, 'X' }, 921590Srgrimes { RTF_STATIC, 'S' }, 931590Srgrimes { RTF_PROTO1, '1' }, 941590Srgrimes { RTF_PROTO2, '2' }, 955103Swollman { RTF_PROTO3, '3' }, 9616392Speter { RTF_BLACKHOLE,'B' }, 9716392Speter { RTF_BROADCAST,'b' }, 98186119Sqingli#ifdef RTF_LLINFO 99186119Sqingli { RTF_LLINFO, 'L' }, 100186119Sqingli#endif 101102975Sdwmalone { 0 , 0 } 1021590Srgrimes}; 1031590Srgrimes 104263335Sglebius/* 105263335Sglebius * kvm(3) bindings for every needed symbol 106263335Sglebius */ 107263335Sglebiusstatic struct nlist rl[] = { 108263335Sglebius#define N_RTSTAT 0 109263335Sglebius { .n_name = "_rtstat" }, 110263335Sglebius#define N_RTREE 1 111263335Sglebius { .n_name = "_rt_tables"}, 112263335Sglebius#define N_RTTRASH 2 113263335Sglebius { .n_name = "_rttrash" }, 114263335Sglebius { .n_name = NULL }, 115263335Sglebius}; 116263335Sglebius 11735383Sphktypedef union { 11838428Sjb long dummy; /* Helps align structure. */ 1191590Srgrimes struct sockaddr u_sa; 1201590Srgrimes u_short u_data[128]; 12135383Sphk} sa_u; 1221590Srgrimes 12335383Sphkstatic sa_u pt_u; 12435383Sphk 125263335Sglebiusstruct ifmap_entry { 126263335Sglebius char ifname[IFNAMSIZ]; 127263335Sglebius}; 128263335Sglebius 129263335Sglebiusstatic struct ifmap_entry *ifmap; 130263335Sglebiusstatic int ifmap_size; 131263335Sglebius 1321590Srgrimesint do_rtent = 0; 1331590Srgrimesstruct rtentry rtentry; 1341590Srgrimesstruct radix_node rnode; 1351590Srgrimesstruct radix_mask rmask; 1361590Srgrimes 137263335Sglebiusint NewTree = 1; 1381590Srgrimes 139160130Solegstruct timespec uptime; 140160130Soleg 141175061Sobrienstatic struct sockaddr *kgetsa(struct sockaddr *); 142175061Sobrienstatic void size_cols(int ef, struct radix_node *rn); 143175061Sobrienstatic void size_cols_tree(struct radix_node *rn); 144175061Sobrienstatic void size_cols_rtentry(struct rtentry *rt); 145263335Sglebiusstatic void p_rtnode_kvm(void); 146263335Sglebiusstatic void p_rtable_sysctl(int, int); 147263335Sglebiusstatic void p_rtable_kvm(int, int ); 148263335Sglebiusstatic void p_rtree_kvm(struct radix_node *); 149263335Sglebiusstatic void p_rtentry_sysctl(struct rt_msghdr *); 150175061Sobrienstatic void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int); 151175061Sobrienstatic const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, 152182602Sobrien int flags); 153175061Sobrienstatic void p_flags(int, const char *); 15497878Skbyancstatic const char *fmt_flags(int f); 155263335Sglebiusstatic void p_rtentry_kvm(struct rtentry *); 156176194Smariusstatic void domask(char *, in_addr_t, u_long); 1571590Srgrimes 1581590Srgrimes/* 1591590Srgrimes * Print routing tables. 1601590Srgrimes */ 1611590Srgrimesvoid 162263335Sglebiusroutepr(int fibnum, int af) 1631590Srgrimes{ 164182602Sobrien size_t intsize; 165263335Sglebius int numfibs; 1661590Srgrimes 167178912Sdelphij intsize = sizeof(int); 168253275Shrs if (fibnum == -1 && 169253275Shrs sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) 170178887Sjulian fibnum = 0; 171178912Sdelphij if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) 172178887Sjulian numfibs = 1; 173253275Shrs if (fibnum < 0 || fibnum > numfibs - 1) 174253275Shrs errx(EX_USAGE, "%d: invalid fib", fibnum); 175160130Soleg /* 176160130Soleg * Since kernel & userland use different timebase 177160130Soleg * (time_uptime vs time_second) and we are reading kernel memory 178263478Sglebius * directly we should do rt_expire --> expire_time conversion. 179160130Soleg */ 180160130Soleg if (clock_gettime(CLOCK_UPTIME, &uptime) < 0) 181160130Soleg err(EX_OSERR, "clock_gettime() failed"); 182160130Soleg 183253275Shrs printf("Routing tables"); 184253275Shrs if (fibnum) 185253275Shrs printf(" (fib: %d)", fibnum); 186253275Shrs printf("\n"); 1871590Srgrimes 188263335Sglebius if (Aflag == 0 && live != 0 && NewTree) 189263335Sglebius p_rtable_sysctl(fibnum, af); 190263335Sglebius else 191263335Sglebius p_rtable_kvm(fibnum, af); 192263335Sglebius} 1931590Srgrimes 194231852Sbz 1951590Srgrimes/* 1961590Srgrimes * Print address family header before a section of the routing table. 1971590Srgrimes */ 1981590Srgrimesvoid 199102975Sdwmalonepr_family(int af1) 2001590Srgrimes{ 201102975Sdwmalone const char *afname; 2021590Srgrimes 203102975Sdwmalone switch (af1) { 2041590Srgrimes case AF_INET: 2051590Srgrimes afname = "Internet"; 2061590Srgrimes break; 20754263Sshin#ifdef INET6 20854263Sshin case AF_INET6: 20954263Sshin afname = "Internet6"; 21054263Sshin break; 21154263Sshin#endif /*INET6*/ 21211819Sjulian case AF_IPX: 21311819Sjulian afname = "IPX"; 21411819Sjulian break; 2151590Srgrimes case AF_ISO: 2161590Srgrimes afname = "ISO"; 2171590Srgrimes break; 21816178Sjulian case AF_APPLETALK: 21917254Sjulian afname = "AppleTalk"; 22016178Sjulian break; 2211590Srgrimes case AF_CCITT: 2221590Srgrimes afname = "X.25"; 2231590Srgrimes break; 22452419Sjulian case AF_NETGRAPH: 22552419Sjulian afname = "Netgraph"; 22652419Sjulian break; 2271590Srgrimes default: 2281590Srgrimes afname = NULL; 2291590Srgrimes break; 2301590Srgrimes } 2311590Srgrimes if (afname) 2321590Srgrimes printf("\n%s:\n", afname); 2331590Srgrimes else 234102975Sdwmalone printf("\nProtocol Family %d:\n", af1); 2351590Srgrimes} 2361590Srgrimes 2371590Srgrimes/* column widths; each followed by one space */ 23862584Sitojun#ifndef INET6 23997878Skbyanc#define WID_DST_DEFAULT(af) 18 /* width of destination column */ 24097878Skbyanc#define WID_GW_DEFAULT(af) 18 /* width of gateway column */ 241272846Shrs#define WID_IF_DEFAULT(af) (Wflag ? 10 : 8) /* width of netif column */ 24262584Sitojun#else 24397878Skbyanc#define WID_DST_DEFAULT(af) \ 24497878Skbyanc ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18) 24597878Skbyanc#define WID_GW_DEFAULT(af) \ 24697878Skbyanc ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18) 247272846Shrs#define WID_IF_DEFAULT(af) ((af) == AF_INET6 ? 8 : (Wflag ? 10 : 8)) 24854263Sshin#endif /*INET6*/ 2491590Srgrimes 25097878Skbyancstatic int wid_dst; 25197878Skbyancstatic int wid_gw; 25297878Skbyancstatic int wid_flags; 253263478Sglebiusstatic int wid_pksent; 25497878Skbyancstatic int wid_mtu; 25597878Skbyancstatic int wid_if; 25697878Skbyancstatic int wid_expire; 25797878Skbyanc 25897878Skbyancstatic void 259263335Sglebiussize_cols(int ef, struct radix_node *rn) 26097878Skbyanc{ 26197878Skbyanc wid_dst = WID_DST_DEFAULT(ef); 26297878Skbyanc wid_gw = WID_GW_DEFAULT(ef); 26397878Skbyanc wid_flags = 6; 264263478Sglebius wid_pksent = 8; 26597878Skbyanc wid_mtu = 6; 26697878Skbyanc wid_if = WID_IF_DEFAULT(ef); 26797878Skbyanc wid_expire = 6; 26897878Skbyanc 269263335Sglebius if (Wflag && rn != NULL) 27097878Skbyanc size_cols_tree(rn); 27197878Skbyanc} 27297878Skbyanc 27397878Skbyancstatic void 27497878Skbyancsize_cols_tree(struct radix_node *rn) 27597878Skbyanc{ 27697878Skbyancagain: 277176289Sjhb if (kget(rn, rnode) != 0) 278176289Sjhb return; 279176289Sjhb if (!(rnode.rn_flags & RNF_ACTIVE)) 280176289Sjhb return; 28197878Skbyanc if (rnode.rn_bit < 0) { 28297878Skbyanc if ((rnode.rn_flags & RNF_ROOT) == 0) { 283176289Sjhb if (kget(rn, rtentry) != 0) 284176289Sjhb return; 28597878Skbyanc size_cols_rtentry(&rtentry); 28697878Skbyanc } 28797878Skbyanc if ((rn = rnode.rn_dupedkey)) 28897878Skbyanc goto again; 28997878Skbyanc } else { 29097878Skbyanc rn = rnode.rn_right; 29197878Skbyanc size_cols_tree(rnode.rn_left); 29297878Skbyanc size_cols_tree(rn); 29397878Skbyanc } 29497878Skbyanc} 29597878Skbyanc 29697878Skbyancstatic void 29797878Skbyancsize_cols_rtentry(struct rtentry *rt) 29897878Skbyanc{ 29997878Skbyanc static struct ifnet ifnet, *lastif; 30097878Skbyanc static char buffer[100]; 30197878Skbyanc const char *bp; 30297878Skbyanc struct sockaddr *sa; 30397878Skbyanc sa_u addr, mask; 30497878Skbyanc int len; 30597878Skbyanc 30697878Skbyanc bzero(&addr, sizeof(addr)); 30797878Skbyanc if ((sa = kgetsa(rt_key(rt)))) 30897878Skbyanc bcopy(sa, &addr, sa->sa_len); 30997878Skbyanc bzero(&mask, sizeof(mask)); 31097878Skbyanc if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) 31197878Skbyanc bcopy(sa, &mask, sa->sa_len); 31297878Skbyanc bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags); 31397878Skbyanc len = strlen(bp); 31497878Skbyanc wid_dst = MAX(len, wid_dst); 31597878Skbyanc 31697878Skbyanc bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST); 31797878Skbyanc len = strlen(bp); 31897878Skbyanc wid_gw = MAX(len, wid_gw); 31997878Skbyanc 32097878Skbyanc bp = fmt_flags(rt->rt_flags); 32197878Skbyanc len = strlen(bp); 32297878Skbyanc wid_flags = MAX(len, wid_flags); 32397878Skbyanc 324263478Sglebius if (Wflag) { 325263657Sglebius len = snprintf(buffer, sizeof(buffer), "%ju", 326263657Sglebius (uintmax_t )kread_counter((u_long )rt->rt_pksent)); 327263478Sglebius wid_pksent = MAX(len, wid_pksent); 32897878Skbyanc } 32997878Skbyanc if (rt->rt_ifp) { 33097878Skbyanc if (rt->rt_ifp != lastif) { 331176289Sjhb if (kget(rt->rt_ifp, ifnet) == 0) 332176289Sjhb len = strlen(ifnet.if_xname); 333176289Sjhb else 334176289Sjhb len = strlen("---"); 33597878Skbyanc lastif = rt->rt_ifp; 33697878Skbyanc wid_if = MAX(len, wid_if); 33797878Skbyanc } 338263478Sglebius if (rt->rt_expire) { 33997878Skbyanc time_t expire_time; 34097878Skbyanc 34197878Skbyanc if ((expire_time = 342263478Sglebius rt->rt_expire - uptime.tv_sec) > 0) { 34397878Skbyanc len = snprintf(buffer, sizeof(buffer), "%d", 34497878Skbyanc (int)expire_time); 34597878Skbyanc wid_expire = MAX(len, wid_expire); 34697878Skbyanc } 34797878Skbyanc } 34897878Skbyanc } 34997878Skbyanc} 35097878Skbyanc 35197878Skbyanc 3521590Srgrimes/* 3531590Srgrimes * Print header for routing table columns. 3541590Srgrimes */ 3551590Srgrimesvoid 356102975Sdwmalonepr_rthdr(int af1) 3571590Srgrimes{ 35854946Sshin 3591590Srgrimes if (Aflag) 3601590Srgrimes printf("%-8.8s ","Address"); 361263335Sglebius if (Wflag) { 362263478Sglebius printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n", 363263335Sglebius wid_dst, wid_dst, "Destination", 364263335Sglebius wid_gw, wid_gw, "Gateway", 365263335Sglebius wid_flags, wid_flags, "Flags", 366263478Sglebius wid_pksent, wid_pksent, "Use", 367263335Sglebius wid_mtu, wid_mtu, "Mtu", 368263335Sglebius wid_if, wid_if, "Netif", 369263335Sglebius wid_expire, "Expire"); 37097878Skbyanc } else { 37197878Skbyanc printf("%-*.*s %-*.*s %-*.*s %*.*s %*s\n", 37297878Skbyanc wid_dst, wid_dst, "Destination", 37397878Skbyanc wid_gw, wid_gw, "Gateway", 37497878Skbyanc wid_flags, wid_flags, "Flags", 37597878Skbyanc wid_if, wid_if, "Netif", 37697878Skbyanc wid_expire, "Expire"); 37797878Skbyanc } 3781590Srgrimes} 3791590Srgrimes 3801590Srgrimesstatic struct sockaddr * 38178314Sassarkgetsa(struct sockaddr *dst) 3821590Srgrimes{ 3831590Srgrimes 384176289Sjhb if (kget(dst, pt_u.u_sa) != 0) 385176289Sjhb return (NULL); 3861590Srgrimes if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) 3871590Srgrimes kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len); 3881590Srgrimes return (&pt_u.u_sa); 3891590Srgrimes} 3901590Srgrimes 391263335Sglebius/* 392263335Sglebius * Print kernel routing tables for given fib 393263335Sglebius * using debugging kvm(3) interface. 394263335Sglebius */ 3951590Srgrimesstatic void 396263335Sglebiusp_rtable_kvm(int fibnum, int af) 3971590Srgrimes{ 398263335Sglebius struct radix_node_head **rnhp, *rnh, head; 399263335Sglebius struct radix_node_head **rt_tables; 400263335Sglebius u_long rtree; 401263335Sglebius int fam, af_size; 4021590Srgrimes 403263335Sglebius kresolve_list(rl); 404263335Sglebius if ((rtree = rl[N_RTREE].n_value) == 0) { 405263335Sglebius printf("rt_tables: symbol not in namelist\n"); 406263335Sglebius return; 407263335Sglebius } 408263335Sglebius 409263335Sglebius af_size = (AF_MAX + 1) * sizeof(struct radix_node_head *); 410263335Sglebius rt_tables = calloc(1, af_size); 411263335Sglebius if (rt_tables == NULL) 412263335Sglebius err(EX_OSERR, "memory allocation failed"); 413263335Sglebius 414263335Sglebius if (kread((u_long)(rtree), (char *)(rt_tables) + fibnum * af_size, 415263335Sglebius af_size) != 0) 416263335Sglebius err(EX_OSERR, "error retrieving radix pointers"); 417263335Sglebius for (fam = 0; fam <= AF_MAX; fam++) { 418263335Sglebius int tmpfib; 419263335Sglebius 420263335Sglebius switch (fam) { 421263335Sglebius case AF_INET6: 422263335Sglebius case AF_INET: 423263335Sglebius tmpfib = fibnum; 424263335Sglebius break; 425263335Sglebius default: 426263335Sglebius tmpfib = 0; 427263335Sglebius } 428263335Sglebius rnhp = (struct radix_node_head **)*rt_tables; 429263335Sglebius /* Calculate the in-kernel address. */ 430263335Sglebius rnhp += tmpfib * (AF_MAX + 1) + fam; 431263335Sglebius /* Read the in kernel rhn pointer. */ 432263335Sglebius if (kget(rnhp, rnh) != 0) 433263335Sglebius continue; 434263335Sglebius if (rnh == NULL) 435263335Sglebius continue; 436263335Sglebius /* Read the rnh data. */ 437263335Sglebius if (kget(rnh, head) != 0) 438263335Sglebius continue; 439263335Sglebius if (fam == AF_UNSPEC) { 440263335Sglebius if (Aflag && af == 0) { 441263335Sglebius printf("Netmasks:\n"); 442263335Sglebius p_rtree_kvm(head.rnh_treetop); 443263335Sglebius } 444263335Sglebius } else if (af == AF_UNSPEC || af == fam) { 445263335Sglebius size_cols(fam, head.rnh_treetop); 446263335Sglebius pr_family(fam); 447263335Sglebius do_rtent = 1; 448263335Sglebius pr_rthdr(fam); 449263335Sglebius p_rtree_kvm(head.rnh_treetop); 450263335Sglebius } 451263335Sglebius } 452263335Sglebius 453263335Sglebius free(rt_tables); 454263335Sglebius} 455263335Sglebius 456263335Sglebius/* 457263335Sglebius * Print given kernel radix tree using 458263335Sglebius * debugging kvm(3) interface. 459263335Sglebius */ 460263335Sglebiusstatic void 461263335Sglebiusp_rtree_kvm(struct radix_node *rn) 462263335Sglebius{ 463263335Sglebius 4641590Srgrimesagain: 465176289Sjhb if (kget(rn, rnode) != 0) 466176289Sjhb return; 467176289Sjhb if (!(rnode.rn_flags & RNF_ACTIVE)) 468176289Sjhb return; 46959540Smarkm if (rnode.rn_bit < 0) { 4701590Srgrimes if (Aflag) 47138428Sjb printf("%-8.8lx ", (u_long)rn); 4721590Srgrimes if (rnode.rn_flags & RNF_ROOT) { 4731590Srgrimes if (Aflag) 4741590Srgrimes printf("(root node)%s", 4751590Srgrimes rnode.rn_dupedkey ? " =>\n" : "\n"); 4761590Srgrimes } else if (do_rtent) { 477176289Sjhb if (kget(rn, rtentry) == 0) { 478263335Sglebius p_rtentry_kvm(&rtentry); 479176289Sjhb if (Aflag) 480263335Sglebius p_rtnode_kvm(); 481176289Sjhb } 4821590Srgrimes } else { 4831590Srgrimes p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), 48413430Speter NULL, 0, 44); 4851590Srgrimes putchar('\n'); 4861590Srgrimes } 48716080Salex if ((rn = rnode.rn_dupedkey)) 4881590Srgrimes goto again; 4891590Srgrimes } else { 4901590Srgrimes if (Aflag && do_rtent) { 49138428Sjb printf("%-8.8lx ", (u_long)rn); 492263335Sglebius p_rtnode_kvm(); 4931590Srgrimes } 49459540Smarkm rn = rnode.rn_right; 495263335Sglebius p_rtree_kvm(rnode.rn_left); 496263335Sglebius p_rtree_kvm(rn); 4971590Srgrimes } 4981590Srgrimes} 4991590Srgrimes 5001590Srgrimeschar nbuf[20]; 5011590Srgrimes 5021590Srgrimesstatic void 503263335Sglebiusp_rtnode_kvm(void) 5041590Srgrimes{ 5051590Srgrimes struct radix_mask *rm = rnode.rn_mklist; 5061590Srgrimes 50759540Smarkm if (rnode.rn_bit < 0) { 5081590Srgrimes if (rnode.rn_mask) { 5091590Srgrimes printf("\t mask "); 5101590Srgrimes p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), 51113430Speter NULL, 0, -1); 5121590Srgrimes } else if (rm == 0) 5131590Srgrimes return; 5141590Srgrimes } else { 51559540Smarkm sprintf(nbuf, "(%d)", rnode.rn_bit); 51659540Smarkm printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right); 5171590Srgrimes } 5181590Srgrimes while (rm) { 519176289Sjhb if (kget(rm, rmask) != 0) 520176289Sjhb break; 5211590Srgrimes sprintf(nbuf, " %d refs, ", rmask.rm_refs); 52238428Sjb printf(" mk = %8.8lx {(%d),%s", 52359540Smarkm (u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " "); 52413430Speter if (rmask.rm_flags & RNF_NORMAL) { 52513430Speter struct radix_node rnode_aux; 52613430Speter printf(" <normal>, "); 527176289Sjhb if (kget(rmask.rm_leaf, rnode_aux) == 0) 528176289Sjhb p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask), 52913430Speter NULL, 0, -1); 530176289Sjhb else 531176289Sjhb p_sockaddr(NULL, NULL, 0, -1); 53213430Speter } else 53313430Speter p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), 53413430Speter NULL, 0, -1); 5351590Srgrimes putchar('}'); 53616080Salex if ((rm = rmask.rm_mklist)) 5371590Srgrimes printf(" ->"); 5381590Srgrimes } 5391590Srgrimes putchar('\n'); 5401590Srgrimes} 5411590Srgrimes 5421590Srgrimesstatic void 543263335Sglebiusp_rtable_sysctl(int fibnum, int af) 5441590Srgrimes{ 5451590Srgrimes size_t needed; 546263335Sglebius int mib[7]; 5471590Srgrimes char *buf, *next, *lim; 548102975Sdwmalone struct rt_msghdr *rtm; 549263335Sglebius struct sockaddr *sa; 550263335Sglebius int fam = 0, ifindex = 0, size; 5511590Srgrimes 552263335Sglebius struct ifaddrs *ifap, *ifa; 553263335Sglebius struct sockaddr_dl *sdl; 554263335Sglebius 555263335Sglebius /* 556263335Sglebius * Retrieve interface list at first 557263335Sglebius * since we need #ifindex -> if_xname match 558263335Sglebius */ 559263335Sglebius if (getifaddrs(&ifap) != 0) 560263335Sglebius err(EX_OSERR, "getifaddrs"); 561263335Sglebius 562263335Sglebius for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 563263335Sglebius 564263335Sglebius if (ifa->ifa_addr->sa_family != AF_LINK) 565263335Sglebius continue; 566263335Sglebius 567263335Sglebius sdl = (struct sockaddr_dl *)ifa->ifa_addr; 568263335Sglebius ifindex = sdl->sdl_index; 569263335Sglebius 570263335Sglebius if (ifindex >= ifmap_size) { 571263335Sglebius size = roundup(ifindex + 1, 32) * 572263335Sglebius sizeof(struct ifmap_entry); 573263335Sglebius if ((ifmap = realloc(ifmap, size)) == NULL) 574263335Sglebius errx(2, "realloc(%d) failed", size); 575263335Sglebius memset(&ifmap[ifmap_size], 0, 576263335Sglebius size - ifmap_size * 577263335Sglebius sizeof(struct ifmap_entry)); 578263335Sglebius 579263335Sglebius ifmap_size = roundup(ifindex + 1, 32); 580263335Sglebius } 581263335Sglebius 582263335Sglebius if (*ifmap[ifindex].ifname != '\0') 583263335Sglebius continue; 584263335Sglebius 585263335Sglebius strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ); 586263335Sglebius } 587263335Sglebius 588263335Sglebius freeifaddrs(ifap); 589263335Sglebius 59035308Sphk mib[0] = CTL_NET; 59135308Sphk mib[1] = PF_ROUTE; 59235308Sphk mib[2] = 0; 593263335Sglebius mib[3] = af; 59435308Sphk mib[4] = NET_RT_DUMP; 59535308Sphk mib[5] = 0; 596263335Sglebius mib[6] = fibnum; 597272846Shrs if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) 598272846Shrs err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d estimate", af, 599272846Shrs fibnum); 600272846Shrs if ((buf = malloc(needed)) == NULL) 601132671Scharnier errx(2, "malloc(%lu)", (unsigned long)needed); 602272846Shrs if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) 603263335Sglebius err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum); 6041590Srgrimes lim = buf + needed; 6051590Srgrimes for (next = buf; next < lim; next += rtm->rtm_msglen) { 6061590Srgrimes rtm = (struct rt_msghdr *)next; 607272855Shrs if (rtm->rtm_version != RTM_VERSION) 608272855Shrs continue; 609263335Sglebius /* 610263335Sglebius * Peek inside header to determine AF 611263335Sglebius */ 612263335Sglebius sa = (struct sockaddr *)(rtm + 1); 613263335Sglebius if (fam != sa->sa_family) { 614263335Sglebius fam = sa->sa_family; 615263335Sglebius size_cols(fam, NULL); 616263335Sglebius pr_family(fam); 617263335Sglebius pr_rthdr(fam); 618263335Sglebius } 619263335Sglebius p_rtentry_sysctl(rtm); 6201590Srgrimes } 621272855Shrs free(buf); 6221590Srgrimes} 6231590Srgrimes 6241590Srgrimesstatic void 625263335Sglebiusp_rtentry_sysctl(struct rt_msghdr *rtm) 6261590Srgrimes{ 627102975Sdwmalone struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 628263335Sglebius char buffer[128]; 629263335Sglebius char prettyname[128]; 630263335Sglebius sa_u addr, mask, gw; 631263335Sglebius unsigned int l; 6321590Srgrimes 633263335Sglebius#define GETSA(_s, _f) { \ 634263335Sglebius bzero(&(_s), sizeof(_s)); \ 635263335Sglebius if (rtm->rtm_addrs & _f) { \ 636263335Sglebius l = roundup(sa->sa_len, sizeof(long)); \ 637263335Sglebius memcpy(&(_s), sa, (l > sizeof(_s)) ? sizeof(_s) : l); \ 638263335Sglebius sa = (struct sockaddr *)((char *)sa + l); \ 639263335Sglebius } \ 640263335Sglebius} 641263335Sglebius 642263335Sglebius GETSA(addr, RTA_DST); 643263335Sglebius GETSA(gw, RTA_GATEWAY); 644263335Sglebius GETSA(mask, RTA_NETMASK); 645263335Sglebius p_sockaddr(&addr.u_sa, &mask.u_sa, rtm->rtm_flags, wid_dst); 646263335Sglebius p_sockaddr(&gw.u_sa, NULL, RTF_HOST, wid_gw); 647263335Sglebius 648263335Sglebius snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); 649263335Sglebius p_flags(rtm->rtm_flags, buffer); 650263335Sglebius if (Wflag) { 651263478Sglebius printf("%*lu ", wid_pksent, rtm->rtm_rmx.rmx_pksent); 652263478Sglebius 653263335Sglebius if (rtm->rtm_rmx.rmx_mtu != 0) 654263335Sglebius printf("%*lu ", wid_mtu, rtm->rtm_rmx.rmx_mtu); 655263335Sglebius else 656263335Sglebius printf("%*s ", wid_mtu, ""); 6571590Srgrimes } 658263335Sglebius 659263335Sglebius memset(prettyname, 0, sizeof(prettyname)); 660263335Sglebius if (rtm->rtm_index < ifmap_size) { 661263335Sglebius strlcpy(prettyname, ifmap[rtm->rtm_index].ifname, 662263335Sglebius sizeof(prettyname)); 663263335Sglebius if (*prettyname == '\0') 664263335Sglebius strlcpy(prettyname, "---", sizeof(prettyname)); 6651590Srgrimes } 666263335Sglebius 667291381Sume if (Wflag) 668291381Sume printf("%*s", wid_if, prettyname); 669291381Sume else 670291381Sume printf("%*.*s", wid_if, wid_if, prettyname); 671263335Sglebius if (rtm->rtm_rmx.rmx_expire) { 672263335Sglebius time_t expire_time; 673263335Sglebius 674263335Sglebius if ((expire_time = 675263335Sglebius rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0) 676263335Sglebius printf(" %*d", wid_expire, (int)expire_time); 6771590Srgrimes } 678263335Sglebius 6791590Srgrimes putchar('\n'); 6801590Srgrimes} 6811590Srgrimes 6821590Srgrimesstatic void 68378314Sassarp_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) 6841590Srgrimes{ 68597878Skbyanc const char *cp; 6861590Srgrimes 68797878Skbyanc cp = fmt_sockaddr(sa, mask, flags); 68897878Skbyanc 68997878Skbyanc if (width < 0 ) 69097878Skbyanc printf("%s ", cp); 69197878Skbyanc else { 69297878Skbyanc if (numeric_addr) 69397878Skbyanc printf("%-*s ", width, cp); 69497878Skbyanc else 69597878Skbyanc printf("%-*.*s ", width, width, cp); 69697878Skbyanc } 69797878Skbyanc} 69897878Skbyanc 69997878Skbyancstatic const char * 70097878Skbyancfmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) 70197878Skbyanc{ 70297878Skbyanc static char workbuf[128]; 703102975Sdwmalone const char *cp; 70497878Skbyanc 705176289Sjhb if (sa == NULL) 706176289Sjhb return ("null"); 707176289Sjhb 7081590Srgrimes switch(sa->sa_family) { 7091590Srgrimes case AF_INET: 7101590Srgrimes { 711132671Scharnier struct sockaddr_in *sockin = (struct sockaddr_in *)sa; 7121590Srgrimes 713132671Scharnier if ((sockin->sin_addr.s_addr == INADDR_ANY) && 71455575Srgrimes mask && 71555575Srgrimes ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) 71655575Srgrimes ==0L) 71755575Srgrimes cp = "default" ; 71813430Speter else if (flags & RTF_HOST) 719132671Scharnier cp = routename(sockin->sin_addr.s_addr); 72013430Speter else if (mask) 721132671Scharnier cp = netname(sockin->sin_addr.s_addr, 722261207Sglebius ((struct sockaddr_in *)mask)->sin_addr.s_addr); 72313430Speter else 724261207Sglebius cp = netname(sockin->sin_addr.s_addr, INADDR_ANY); 7251590Srgrimes break; 7261590Srgrimes } 7271590Srgrimes 72854263Sshin#ifdef INET6 72954263Sshin case AF_INET6: 73054263Sshin { 73154263Sshin struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 73254263Sshin 733243187Shrs /* 734243187Shrs * The sa6->sin6_scope_id must be filled here because 735243187Shrs * this sockaddr is extracted from kmem(4) directly 736243187Shrs * and has KAME-specific embedded scope id in 737243187Shrs * sa6->sin6_addr.s6_addr[2]. 738243187Shrs */ 739217642Sume in6_fillscopeid(sa6); 74054263Sshin 74154263Sshin if (flags & RTF_HOST) 74254263Sshin cp = routename6(sa6); 74354263Sshin else if (mask) 74454263Sshin cp = netname6(sa6, 74554263Sshin &((struct sockaddr_in6 *)mask)->sin6_addr); 74654263Sshin else { 74754263Sshin cp = netname6(sa6, NULL); 74854263Sshin } 74954263Sshin break; 75054263Sshin } 75154263Sshin#endif /*INET6*/ 75254263Sshin 75311819Sjulian case AF_IPX: 75411819Sjulian { 75512632Sjulian struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; 75612632Sjulian if (ipx_nullnet(satoipx_addr(work))) 75711819Sjulian cp = "default"; 75811819Sjulian else 75911819Sjulian cp = ipx_print(sa); 76011819Sjulian break; 76111819Sjulian } 76216178Sjulian case AF_APPLETALK: 76316178Sjulian { 76417265Sjulian if (!(flags & RTF_HOST) && mask) 76518066Sjulian cp = atalk_print2(sa,mask,9); 76617254Sjulian else 76717254Sjulian cp = atalk_print(sa,11); 76816178Sjulian break; 76916178Sjulian } 77052419Sjulian case AF_NETGRAPH: 77152419Sjulian { 772164686Syar strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data, 773164686Syar sizeof(workbuf)); 774164686Syar cp = workbuf; 77552419Sjulian break; 77652419Sjulian } 7771590Srgrimes 7781590Srgrimes case AF_LINK: 7791590Srgrimes { 780102975Sdwmalone struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 7811590Srgrimes 7821590Srgrimes if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && 783102975Sdwmalone sdl->sdl_slen == 0) { 7841590Srgrimes (void) sprintf(workbuf, "link#%d", sdl->sdl_index); 785102975Sdwmalone cp = workbuf; 786102975Sdwmalone } else 78735308Sphk switch (sdl->sdl_type) { 7881590Srgrimes 78935308Sphk case IFT_ETHER: 790132803Sglebius case IFT_L2VLAN: 791175217Sthompsa case IFT_BRIDGE: 79293957Sru if (sdl->sdl_alen == ETHER_ADDR_LEN) { 79393957Sru cp = ether_ntoa((struct ether_addr *) 794100161Skbyanc (sdl->sdl_data + sdl->sdl_nlen)); 79593957Sru break; 79635308Sphk } 79793957Sru /* FALLTHROUGH */ 79835308Sphk default: 79935308Sphk cp = link_ntoa(sdl); 80035308Sphk break; 8011590Srgrimes } 8021590Srgrimes break; 8031590Srgrimes } 8041590Srgrimes 8051590Srgrimes default: 8061590Srgrimes { 807102975Sdwmalone u_char *s = (u_char *)sa->sa_data, *slim; 808102975Sdwmalone char *cq, *cqlim; 8091590Srgrimes 810102975Sdwmalone cq = workbuf; 8111590Srgrimes slim = sa->sa_len + (u_char *) sa; 812102975Sdwmalone cqlim = cq + sizeof(workbuf) - 6; 813102975Sdwmalone cq += sprintf(cq, "(%d)", sa->sa_family); 814102975Sdwmalone while (s < slim && cq < cqlim) { 815102975Sdwmalone cq += sprintf(cq, " %02x", *s++); 8161590Srgrimes if (s < slim) 817102975Sdwmalone cq += sprintf(cq, "%02x", *s++); 8181590Srgrimes } 8191590Srgrimes cp = workbuf; 8201590Srgrimes } 8211590Srgrimes } 82297878Skbyanc 82397878Skbyanc return (cp); 8241590Srgrimes} 8251590Srgrimes 8261590Srgrimesstatic void 827102975Sdwmalonep_flags(int f, const char *format) 8281590Srgrimes{ 82997878Skbyanc printf(format, fmt_flags(f)); 83097878Skbyanc} 8311590Srgrimes 83297878Skbyancstatic const char * 83397878Skbyancfmt_flags(int f) 83497878Skbyanc{ 83597878Skbyanc static char name[33]; 83697878Skbyanc char *flags; 83797878Skbyanc struct bits *p = bits; 83897878Skbyanc 8391590Srgrimes for (flags = name; p->b_mask; p++) 8401590Srgrimes if (p->b_mask & f) 8411590Srgrimes *flags++ = p->b_val; 8421590Srgrimes *flags = '\0'; 84397878Skbyanc return (name); 8441590Srgrimes} 8451590Srgrimes 8461590Srgrimesstatic void 847263335Sglebiusp_rtentry_kvm(struct rtentry *rt) 8481590Srgrimes{ 8491590Srgrimes static struct ifnet ifnet, *lastif; 85097878Skbyanc static char buffer[128]; 85197878Skbyanc static char prettyname[128]; 85213430Speter struct sockaddr *sa; 85335383Sphk sa_u addr, mask; 8541590Srgrimes 85537452Sbde bzero(&addr, sizeof(addr)); 85635383Sphk if ((sa = kgetsa(rt_key(rt)))) 85737452Sbde bcopy(sa, &addr, sa->sa_len); 85837452Sbde bzero(&mask, sizeof(mask)); 85935383Sphk if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) 86037452Sbde bcopy(sa, &mask, sa->sa_len); 86197878Skbyanc p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst); 86297878Skbyanc p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw); 86397878Skbyanc snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); 86497878Skbyanc p_flags(rt->rt_flags, buffer); 865263478Sglebius if (Wflag) { 866263657Sglebius printf("%*ju ", wid_pksent, 867263657Sglebius (uintmax_t )kread_counter((u_long )rt->rt_pksent)); 868263478Sglebius 869263478Sglebius if (rt->rt_mtu != 0) 870263478Sglebius printf("%*lu ", wid_mtu, rt->rt_mtu); 871263478Sglebius else 872263478Sglebius printf("%*s ", wid_mtu, ""); 87378064Sume } 8741590Srgrimes if (rt->rt_ifp) { 8751590Srgrimes if (rt->rt_ifp != lastif) { 876176289Sjhb if (kget(rt->rt_ifp, ifnet) == 0) 877176289Sjhb strlcpy(prettyname, ifnet.if_xname, 878176289Sjhb sizeof(prettyname)); 879176289Sjhb else 880176289Sjhb strlcpy(prettyname, "---", sizeof(prettyname)); 8811590Srgrimes lastif = rt->rt_ifp; 8821590Srgrimes } 88397878Skbyanc printf("%*.*s", wid_if, wid_if, prettyname); 884263478Sglebius if (rt->rt_expire) { 8857642Sjkh time_t expire_time; 8865811Swollman 88735308Sphk if ((expire_time = 888263478Sglebius rt->rt_expire - uptime.tv_sec) > 0) 88997878Skbyanc printf(" %*d", wid_expire, (int)expire_time); 89078957Sru } 89178957Sru if (rt->rt_nodes[0].rn_dupedkey) 89235308Sphk printf(" =>"); 8931590Srgrimes } 8941590Srgrimes putchar('\n'); 8951590Srgrimes} 8961590Srgrimes 8971590Srgrimeschar * 898176099Smariusroutename(in_addr_t in) 8991590Srgrimes{ 900102975Sdwmalone char *cp; 90174262Sbrian static char line[MAXHOSTNAMELEN]; 9021590Srgrimes struct hostent *hp; 9031590Srgrimes 9041590Srgrimes cp = 0; 90578238Sassar if (!numeric_addr) { 906176099Smarius hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET); 9071590Srgrimes if (hp) { 9081590Srgrimes cp = hp->h_name; 90974262Sbrian trimdomain(cp, strlen(cp)); 9101590Srgrimes } 9111590Srgrimes } 91236788Simp if (cp) { 913183988Sdelphij strlcpy(line, cp, sizeof(line)); 91436788Simp } else { 915175061Sobrien#define C(x) ((x) & 0xff) 9161590Srgrimes in = ntohl(in); 917176099Smarius sprintf(line, "%u.%u.%u.%u", 9181590Srgrimes C(in >> 24), C(in >> 16), C(in >> 8), C(in)); 9191590Srgrimes } 9201590Srgrimes return (line); 9211590Srgrimes} 9221590Srgrimes 923166711Sbms#define NSHIFT(m) ( \ 924166711Sbms (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \ 925166711Sbms (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \ 926166711Sbms (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \ 927166711Sbms 0) 92813430Speter 92913430Speterstatic void 930176194Smariusdomask(char *dst, in_addr_t addr __unused, u_long mask) 93113430Speter{ 932102975Sdwmalone int b, i; 93313430Speter 934166711Sbms if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) { 93513430Speter *dst = '\0'; 93613430Speter return; 93713430Speter } 93813430Speter i = 0; 93913430Speter for (b = 0; b < 32; b++) 94013430Speter if (mask & (1 << b)) { 941102975Sdwmalone int bb; 94213430Speter 94313430Speter i = b; 94413430Speter for (bb = b+1; bb < 32; bb++) 94513430Speter if (!(mask & (1 << bb))) { 94613430Speter i = -1; /* noncontig */ 94713430Speter break; 94813430Speter } 94913430Speter break; 95013430Speter } 95113430Speter if (i == -1) 95213430Speter sprintf(dst, "&0x%lx", mask); 95313430Speter else 95413430Speter sprintf(dst, "/%d", 32-i); 95513430Speter} 95613430Speter 9571590Srgrimes/* 9581590Srgrimes * Return the name of the network whose address is given. 9591590Srgrimes */ 9601590Srgrimeschar * 961261207Sglebiusnetname(in_addr_t in, in_addr_t mask) 9621590Srgrimes{ 9631590Srgrimes char *cp = 0; 96474262Sbrian static char line[MAXHOSTNAMELEN]; 9651590Srgrimes struct netent *np = 0; 966176194Smarius in_addr_t i; 9671590Srgrimes 968261207Sglebius /* It is ok to supply host address. */ 969261207Sglebius in &= mask; 970261207Sglebius 9711590Srgrimes i = ntohl(in); 97278238Sassar if (!numeric_addr && i) { 973261207Sglebius np = getnetbyaddr(i >> NSHIFT(ntohl(mask)), AF_INET); 97484803Sru if (np != NULL) { 9751590Srgrimes cp = np->n_name; 97674262Sbrian trimdomain(cp, strlen(cp)); 97713433Speter } 9781590Srgrimes } 97984803Sru if (cp != NULL) { 980183988Sdelphij strlcpy(line, cp, sizeof(line)); 98184803Sru } else { 982176099Smarius inet_ntop(AF_INET, &in, line, sizeof(line) - 1); 98377911Sru } 984261207Sglebius domask(line + strlen(line), i, ntohl(mask)); 9851590Srgrimes return (line); 9861590Srgrimes} 9871590Srgrimes 988166711Sbms#undef NSHIFT 989166711Sbms 99054263Sshin#ifdef INET6 991217642Sumevoid 992217642Sumein6_fillscopeid(struct sockaddr_in6 *sa6) 993217642Sume{ 994217642Sume#if defined(__KAME__) 995217642Sume /* 996217642Sume * XXX: This is a special workaround for KAME kernels. 997217642Sume * sin6_scope_id field of SA should be set in the future. 998217642Sume */ 999217642Sume if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || 1000217642Sume IN6_IS_ADDR_MC_NODELOCAL(&sa6->sin6_addr) || 1001217642Sume IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) { 1002272855Shrs if (sa6->sin6_scope_id == 0) 1003272855Shrs sa6->sin6_scope_id = 1004272855Shrs ntohs(*(u_int16_t *)&sa6->sin6_addr.s6_addr[2]); 1005217642Sume sa6->sin6_addr.s6_addr[2] = sa6->sin6_addr.s6_addr[3] = 0; 1006217642Sume } 1007217642Sume#endif 1008217642Sume} 1009217642Sume 1010102975Sdwmaloneconst char * 101178314Sassarnetname6(struct sockaddr_in6 *sa6, struct in6_addr *mask) 101254263Sshin{ 101374262Sbrian static char line[MAXHOSTNAMELEN]; 101454263Sshin u_char *p = (u_char *)mask; 101554263Sshin u_char *lim; 1016146187Sume int masklen, illegal = 0, flag = 0; 101754263Sshin 101854263Sshin if (mask) { 101954263Sshin for (masklen = 0, lim = p + 16; p < lim; p++) { 102054263Sshin switch (*p) { 102162584Sitojun case 0xff: 102262584Sitojun masklen += 8; 102362584Sitojun break; 102454263Sshin case 0xfe: 102554263Sshin masklen += 7; 102654263Sshin break; 102754263Sshin case 0xfc: 102854263Sshin masklen += 6; 102954263Sshin break; 103054263Sshin case 0xf8: 103154263Sshin masklen += 5; 103254263Sshin break; 103354263Sshin case 0xf0: 103454263Sshin masklen += 4; 103554263Sshin break; 103654263Sshin case 0xe0: 103754263Sshin masklen += 3; 103854263Sshin break; 103954263Sshin case 0xc0: 104054263Sshin masklen += 2; 104154263Sshin break; 104254263Sshin case 0x80: 104354263Sshin masklen += 1; 104454263Sshin break; 104554263Sshin case 0x00: 104654263Sshin break; 104754263Sshin default: 104854263Sshin illegal ++; 104954263Sshin break; 105054263Sshin } 105154263Sshin } 105254263Sshin if (illegal) 105354263Sshin fprintf(stderr, "illegal prefixlen\n"); 105454263Sshin } 105554263Sshin else 105654263Sshin masklen = 128; 105754263Sshin 105854263Sshin if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) 105954263Sshin return("default"); 106054263Sshin 106178238Sassar if (numeric_addr) 106254263Sshin flag |= NI_NUMERICHOST; 106354263Sshin getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line), 106454263Sshin NULL, 0, flag); 106554263Sshin 106678238Sassar if (numeric_addr) 106754263Sshin sprintf(&line[strlen(line)], "/%d", masklen); 106854263Sshin 106954263Sshin return line; 107054263Sshin} 107154263Sshin 107254263Sshinchar * 107378314Sassarroutename6(struct sockaddr_in6 *sa6) 107454263Sshin{ 107574262Sbrian static char line[MAXHOSTNAMELEN]; 1076146187Sume int flag = 0; 107762584Sitojun /* use local variable for safety */ 1078160789Syar struct sockaddr_in6 sa6_local; 107954263Sshin 1080160789Syar sa6_local.sin6_family = AF_INET6; 1081160789Syar sa6_local.sin6_len = sizeof(sa6_local); 108262584Sitojun sa6_local.sin6_addr = sa6->sin6_addr; 108362584Sitojun sa6_local.sin6_scope_id = sa6->sin6_scope_id; 108462584Sitojun 108578238Sassar if (numeric_addr) 108654263Sshin flag |= NI_NUMERICHOST; 108754263Sshin 108862584Sitojun getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len, 108962584Sitojun line, sizeof(line), NULL, 0, flag); 109054263Sshin 109154263Sshin return line; 109254263Sshin} 109354263Sshin#endif /*INET6*/ 109454263Sshin 10951590Srgrimes/* 10961590Srgrimes * Print routing statistics 10971590Srgrimes */ 10981590Srgrimesvoid 1099263335Sglebiusrt_stats(void) 11001590Srgrimes{ 11011590Srgrimes struct rtstat rtstat; 1102263335Sglebius u_long rtsaddr, rttaddr; 110378958Sru int rttrash; 11041590Srgrimes 1105263335Sglebius kresolve_list(rl); 1106263335Sglebius 1107263335Sglebius if ((rtsaddr = rl[N_RTSTAT].n_value) == 0) { 11081590Srgrimes printf("rtstat: symbol not in namelist\n"); 11091590Srgrimes return; 11101590Srgrimes } 1111263335Sglebius if ((rttaddr = rl[N_RTTRASH].n_value) == 0) { 111278958Sru printf("rttrash: symbol not in namelist\n"); 111378958Sru return; 111478958Sru } 111578958Sru kread(rtsaddr, (char *)&rtstat, sizeof (rtstat)); 111678958Sru kread(rttaddr, (char *)&rttrash, sizeof (rttrash)); 11171590Srgrimes printf("routing:\n"); 111878659Sru 111978659Sru#define p(f, m) if (rtstat.f || sflag <= 1) \ 112078659Sru printf(m, rtstat.f, plural(rtstat.f)) 112178659Sru 1122198118Srwatson p(rts_badredirect, "\t%hu bad routing redirect%s\n"); 1123198118Srwatson p(rts_dynamic, "\t%hu dynamically created route%s\n"); 1124198118Srwatson p(rts_newgateway, "\t%hu new gateway%s due to redirects\n"); 1125198118Srwatson p(rts_unreach, "\t%hu destination%s found unreachable\n"); 1126198118Srwatson p(rts_wildcard, "\t%hu use%s of a wildcard route\n"); 112778659Sru#undef p 112878958Sru 112978958Sru if (rttrash || sflag <= 1) 113078958Sru printf("\t%u route%s not in table but not freed\n", 113178958Sru rttrash, plural(rttrash)); 11321590Srgrimes} 113311819Sjulian 113411819Sjulianchar * 113578314Sassaripx_print(struct sockaddr *sa) 113611819Sjulian{ 113711819Sjulian u_short port; 113835308Sphk struct servent *sp = 0; 1139102975Sdwmalone const char *net = "", *host = ""; 1140102975Sdwmalone char *p; 1141102975Sdwmalone u_char *q; 114211819Sjulian struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; 114335308Sphk static char mybuf[50]; 114411819Sjulian char cport[10], chost[15], cnet[15]; 114511819Sjulian 114611819Sjulian port = ntohs(work.x_port); 114711819Sjulian 114811819Sjulian if (ipx_nullnet(work) && ipx_nullhost(work)) { 114911819Sjulian 115011819Sjulian if (port) { 115135308Sphk if (sp) 115235308Sphk sprintf(mybuf, "*.%s", sp->s_name); 115335308Sphk else 115435308Sphk sprintf(mybuf, "*.%x", port); 115511819Sjulian } else 115611819Sjulian sprintf(mybuf, "*.*"); 115711819Sjulian 115811819Sjulian return (mybuf); 115911819Sjulian } 116011819Sjulian 116125654Sjhay if (ipx_wildnet(work)) 116211819Sjulian net = "any"; 116311819Sjulian else if (ipx_nullnet(work)) 116411819Sjulian net = "*"; 116511819Sjulian else { 116611819Sjulian q = work.x_net.c_net; 116711819Sjulian sprintf(cnet, "%02x%02x%02x%02x", 116811819Sjulian q[0], q[1], q[2], q[3]); 116911819Sjulian for (p = cnet; *p == '0' && p < cnet + 8; p++) 117011819Sjulian continue; 117111819Sjulian net = p; 117211819Sjulian } 117311819Sjulian 117425654Sjhay if (ipx_wildhost(work)) 117511819Sjulian host = "any"; 117611819Sjulian else if (ipx_nullhost(work)) 117711819Sjulian host = "*"; 117811819Sjulian else { 117911819Sjulian q = work.x_host.c_host; 118011819Sjulian sprintf(chost, "%02x%02x%02x%02x%02x%02x", 118111819Sjulian q[0], q[1], q[2], q[3], q[4], q[5]); 118211819Sjulian for (p = chost; *p == '0' && p < chost + 12; p++) 118311819Sjulian continue; 118411819Sjulian host = p; 118511819Sjulian } 118611819Sjulian 118711819Sjulian if (port) { 118835308Sphk if (strcmp(host, "*") == 0) 118935308Sphk host = ""; 1190175061Sobrien if (sp) 119136788Simp snprintf(cport, sizeof(cport), 119236788Simp "%s%s", *host ? "." : "", sp->s_name); 1193175061Sobrien else 119436788Simp snprintf(cport, sizeof(cport), 119536788Simp "%s%x", *host ? "." : "", port); 119611819Sjulian } else 119711819Sjulian *cport = 0; 119811819Sjulian 119936788Simp snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport); 120011819Sjulian return(mybuf); 120111819Sjulian} 120211819Sjulian 120311819Sjulianchar * 120478314Sassaripx_phost(struct sockaddr *sa) 120511819Sjulian{ 1206102975Sdwmalone struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa; 120711819Sjulian struct sockaddr_ipx work; 120835308Sphk static union ipx_net ipx_zeronet; 120911819Sjulian char *p; 121011819Sjulian 121111819Sjulian work = *sipx; 121211819Sjulian 121311819Sjulian work.sipx_addr.x_port = 0; 121411819Sjulian work.sipx_addr.x_net = ipx_zeronet; 121511819Sjulian p = ipx_print((struct sockaddr *)&work); 121611819Sjulian if (strncmp("*.", p, 2) == 0) p += 2; 121711819Sjulian 121811819Sjulian return(p); 121911819Sjulian} 122011819Sjulian 12211590Srgrimesvoid 122278314SassarupHex(char *p0) 12231590Srgrimes{ 1224102975Sdwmalone char *p = p0; 12251590Srgrimes 122635308Sphk for (; *p; p++) 122735308Sphk switch (*p) { 122835308Sphk 122935308Sphk case 'a': 123035308Sphk case 'b': 123135308Sphk case 'c': 123235308Sphk case 'd': 123335308Sphk case 'e': 123435308Sphk case 'f': 123535308Sphk *p += ('A' - 'a'); 123635308Sphk break; 123735308Sphk } 12381590Srgrimes} 1239