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 */ 241273188Shrs#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) 247273188Shrs#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; 597273188Shrs if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) 598273188Shrs err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d estimate", af, 599273188Shrs fibnum); 600273188Shrs if ((buf = malloc(needed)) == NULL) 601132671Scharnier errx(2, "malloc(%lu)", (unsigned long)needed); 602273188Shrs 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; 607273188Shrs if (rtm->rtm_version != RTM_VERSION) 608273188Shrs 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 } 621273188Shrs 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 667263335Sglebius printf("%*.*s", wid_if, wid_if, prettyname); 668263335Sglebius if (rtm->rtm_rmx.rmx_expire) { 669263335Sglebius time_t expire_time; 670263335Sglebius 671263335Sglebius if ((expire_time = 672263335Sglebius rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0) 673263335Sglebius printf(" %*d", wid_expire, (int)expire_time); 6741590Srgrimes } 675263335Sglebius 6761590Srgrimes putchar('\n'); 6771590Srgrimes} 6781590Srgrimes 6791590Srgrimesstatic void 68078314Sassarp_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) 6811590Srgrimes{ 68297878Skbyanc const char *cp; 6831590Srgrimes 68497878Skbyanc cp = fmt_sockaddr(sa, mask, flags); 68597878Skbyanc 68697878Skbyanc if (width < 0 ) 68797878Skbyanc printf("%s ", cp); 68897878Skbyanc else { 68997878Skbyanc if (numeric_addr) 69097878Skbyanc printf("%-*s ", width, cp); 69197878Skbyanc else 69297878Skbyanc printf("%-*.*s ", width, width, cp); 69397878Skbyanc } 69497878Skbyanc} 69597878Skbyanc 69697878Skbyancstatic const char * 69797878Skbyancfmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) 69897878Skbyanc{ 69997878Skbyanc static char workbuf[128]; 700102975Sdwmalone const char *cp; 70197878Skbyanc 702176289Sjhb if (sa == NULL) 703176289Sjhb return ("null"); 704176289Sjhb 7051590Srgrimes switch(sa->sa_family) { 7061590Srgrimes case AF_INET: 7071590Srgrimes { 708132671Scharnier struct sockaddr_in *sockin = (struct sockaddr_in *)sa; 7091590Srgrimes 710132671Scharnier if ((sockin->sin_addr.s_addr == INADDR_ANY) && 71155575Srgrimes mask && 71255575Srgrimes ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) 71355575Srgrimes ==0L) 71455575Srgrimes cp = "default" ; 71513430Speter else if (flags & RTF_HOST) 716132671Scharnier cp = routename(sockin->sin_addr.s_addr); 71713430Speter else if (mask) 718132671Scharnier cp = netname(sockin->sin_addr.s_addr, 719261207Sglebius ((struct sockaddr_in *)mask)->sin_addr.s_addr); 72013430Speter else 721261207Sglebius cp = netname(sockin->sin_addr.s_addr, INADDR_ANY); 7221590Srgrimes break; 7231590Srgrimes } 7241590Srgrimes 72554263Sshin#ifdef INET6 72654263Sshin case AF_INET6: 72754263Sshin { 72854263Sshin struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 72954263Sshin 730243187Shrs /* 731243187Shrs * The sa6->sin6_scope_id must be filled here because 732243187Shrs * this sockaddr is extracted from kmem(4) directly 733243187Shrs * and has KAME-specific embedded scope id in 734243187Shrs * sa6->sin6_addr.s6_addr[2]. 735243187Shrs */ 736217642Sume in6_fillscopeid(sa6); 73754263Sshin 73854263Sshin if (flags & RTF_HOST) 73954263Sshin cp = routename6(sa6); 74054263Sshin else if (mask) 74154263Sshin cp = netname6(sa6, 74254263Sshin &((struct sockaddr_in6 *)mask)->sin6_addr); 74354263Sshin else { 74454263Sshin cp = netname6(sa6, NULL); 74554263Sshin } 74654263Sshin break; 74754263Sshin } 74854263Sshin#endif /*INET6*/ 74954263Sshin 75011819Sjulian case AF_IPX: 75111819Sjulian { 75212632Sjulian struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; 75312632Sjulian if (ipx_nullnet(satoipx_addr(work))) 75411819Sjulian cp = "default"; 75511819Sjulian else 75611819Sjulian cp = ipx_print(sa); 75711819Sjulian break; 75811819Sjulian } 75916178Sjulian case AF_APPLETALK: 76016178Sjulian { 76117265Sjulian if (!(flags & RTF_HOST) && mask) 76218066Sjulian cp = atalk_print2(sa,mask,9); 76317254Sjulian else 76417254Sjulian cp = atalk_print(sa,11); 76516178Sjulian break; 76616178Sjulian } 76752419Sjulian case AF_NETGRAPH: 76852419Sjulian { 769164686Syar strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data, 770164686Syar sizeof(workbuf)); 771164686Syar cp = workbuf; 77252419Sjulian break; 77352419Sjulian } 7741590Srgrimes 7751590Srgrimes case AF_LINK: 7761590Srgrimes { 777102975Sdwmalone struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 7781590Srgrimes 7791590Srgrimes if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && 780102975Sdwmalone sdl->sdl_slen == 0) { 7811590Srgrimes (void) sprintf(workbuf, "link#%d", sdl->sdl_index); 782102975Sdwmalone cp = workbuf; 783102975Sdwmalone } else 78435308Sphk switch (sdl->sdl_type) { 7851590Srgrimes 78635308Sphk case IFT_ETHER: 787132803Sglebius case IFT_L2VLAN: 788175217Sthompsa case IFT_BRIDGE: 78993957Sru if (sdl->sdl_alen == ETHER_ADDR_LEN) { 79093957Sru cp = ether_ntoa((struct ether_addr *) 791100161Skbyanc (sdl->sdl_data + sdl->sdl_nlen)); 79293957Sru break; 79335308Sphk } 79493957Sru /* FALLTHROUGH */ 79535308Sphk default: 79635308Sphk cp = link_ntoa(sdl); 79735308Sphk break; 7981590Srgrimes } 7991590Srgrimes break; 8001590Srgrimes } 8011590Srgrimes 8021590Srgrimes default: 8031590Srgrimes { 804102975Sdwmalone u_char *s = (u_char *)sa->sa_data, *slim; 805102975Sdwmalone char *cq, *cqlim; 8061590Srgrimes 807102975Sdwmalone cq = workbuf; 8081590Srgrimes slim = sa->sa_len + (u_char *) sa; 809102975Sdwmalone cqlim = cq + sizeof(workbuf) - 6; 810102975Sdwmalone cq += sprintf(cq, "(%d)", sa->sa_family); 811102975Sdwmalone while (s < slim && cq < cqlim) { 812102975Sdwmalone cq += sprintf(cq, " %02x", *s++); 8131590Srgrimes if (s < slim) 814102975Sdwmalone cq += sprintf(cq, "%02x", *s++); 8151590Srgrimes } 8161590Srgrimes cp = workbuf; 8171590Srgrimes } 8181590Srgrimes } 81997878Skbyanc 82097878Skbyanc return (cp); 8211590Srgrimes} 8221590Srgrimes 8231590Srgrimesstatic void 824102975Sdwmalonep_flags(int f, const char *format) 8251590Srgrimes{ 82697878Skbyanc printf(format, fmt_flags(f)); 82797878Skbyanc} 8281590Srgrimes 82997878Skbyancstatic const char * 83097878Skbyancfmt_flags(int f) 83197878Skbyanc{ 83297878Skbyanc static char name[33]; 83397878Skbyanc char *flags; 83497878Skbyanc struct bits *p = bits; 83597878Skbyanc 8361590Srgrimes for (flags = name; p->b_mask; p++) 8371590Srgrimes if (p->b_mask & f) 8381590Srgrimes *flags++ = p->b_val; 8391590Srgrimes *flags = '\0'; 84097878Skbyanc return (name); 8411590Srgrimes} 8421590Srgrimes 8431590Srgrimesstatic void 844263335Sglebiusp_rtentry_kvm(struct rtentry *rt) 8451590Srgrimes{ 8461590Srgrimes static struct ifnet ifnet, *lastif; 84797878Skbyanc static char buffer[128]; 84897878Skbyanc static char prettyname[128]; 84913430Speter struct sockaddr *sa; 85035383Sphk sa_u addr, mask; 8511590Srgrimes 85237452Sbde bzero(&addr, sizeof(addr)); 85335383Sphk if ((sa = kgetsa(rt_key(rt)))) 85437452Sbde bcopy(sa, &addr, sa->sa_len); 85537452Sbde bzero(&mask, sizeof(mask)); 85635383Sphk if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) 85737452Sbde bcopy(sa, &mask, sa->sa_len); 85897878Skbyanc p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst); 85997878Skbyanc p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw); 86097878Skbyanc snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); 86197878Skbyanc p_flags(rt->rt_flags, buffer); 862263478Sglebius if (Wflag) { 863263657Sglebius printf("%*ju ", wid_pksent, 864263657Sglebius (uintmax_t )kread_counter((u_long )rt->rt_pksent)); 865263478Sglebius 866263478Sglebius if (rt->rt_mtu != 0) 867263478Sglebius printf("%*lu ", wid_mtu, rt->rt_mtu); 868263478Sglebius else 869263478Sglebius printf("%*s ", wid_mtu, ""); 87078064Sume } 8711590Srgrimes if (rt->rt_ifp) { 8721590Srgrimes if (rt->rt_ifp != lastif) { 873176289Sjhb if (kget(rt->rt_ifp, ifnet) == 0) 874176289Sjhb strlcpy(prettyname, ifnet.if_xname, 875176289Sjhb sizeof(prettyname)); 876176289Sjhb else 877176289Sjhb strlcpy(prettyname, "---", sizeof(prettyname)); 8781590Srgrimes lastif = rt->rt_ifp; 8791590Srgrimes } 88097878Skbyanc printf("%*.*s", wid_if, wid_if, prettyname); 881263478Sglebius if (rt->rt_expire) { 8827642Sjkh time_t expire_time; 8835811Swollman 88435308Sphk if ((expire_time = 885263478Sglebius rt->rt_expire - uptime.tv_sec) > 0) 88697878Skbyanc printf(" %*d", wid_expire, (int)expire_time); 88778957Sru } 88878957Sru if (rt->rt_nodes[0].rn_dupedkey) 88935308Sphk printf(" =>"); 8901590Srgrimes } 8911590Srgrimes putchar('\n'); 8921590Srgrimes} 8931590Srgrimes 8941590Srgrimeschar * 895176099Smariusroutename(in_addr_t in) 8961590Srgrimes{ 897102975Sdwmalone char *cp; 89874262Sbrian static char line[MAXHOSTNAMELEN]; 8991590Srgrimes struct hostent *hp; 9001590Srgrimes 9011590Srgrimes cp = 0; 90278238Sassar if (!numeric_addr) { 903176099Smarius hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET); 9041590Srgrimes if (hp) { 9051590Srgrimes cp = hp->h_name; 90674262Sbrian trimdomain(cp, strlen(cp)); 9071590Srgrimes } 9081590Srgrimes } 90936788Simp if (cp) { 910183988Sdelphij strlcpy(line, cp, sizeof(line)); 91136788Simp } else { 912175061Sobrien#define C(x) ((x) & 0xff) 9131590Srgrimes in = ntohl(in); 914176099Smarius sprintf(line, "%u.%u.%u.%u", 9151590Srgrimes C(in >> 24), C(in >> 16), C(in >> 8), C(in)); 9161590Srgrimes } 9171590Srgrimes return (line); 9181590Srgrimes} 9191590Srgrimes 920166711Sbms#define NSHIFT(m) ( \ 921166711Sbms (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \ 922166711Sbms (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \ 923166711Sbms (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \ 924166711Sbms 0) 92513430Speter 92613430Speterstatic void 927176194Smariusdomask(char *dst, in_addr_t addr __unused, u_long mask) 92813430Speter{ 929102975Sdwmalone int b, i; 93013430Speter 931166711Sbms if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) { 93213430Speter *dst = '\0'; 93313430Speter return; 93413430Speter } 93513430Speter i = 0; 93613430Speter for (b = 0; b < 32; b++) 93713430Speter if (mask & (1 << b)) { 938102975Sdwmalone int bb; 93913430Speter 94013430Speter i = b; 94113430Speter for (bb = b+1; bb < 32; bb++) 94213430Speter if (!(mask & (1 << bb))) { 94313430Speter i = -1; /* noncontig */ 94413430Speter break; 94513430Speter } 94613430Speter break; 94713430Speter } 94813430Speter if (i == -1) 94913430Speter sprintf(dst, "&0x%lx", mask); 95013430Speter else 95113430Speter sprintf(dst, "/%d", 32-i); 95213430Speter} 95313430Speter 9541590Srgrimes/* 9551590Srgrimes * Return the name of the network whose address is given. 9561590Srgrimes */ 9571590Srgrimeschar * 958261207Sglebiusnetname(in_addr_t in, in_addr_t mask) 9591590Srgrimes{ 9601590Srgrimes char *cp = 0; 96174262Sbrian static char line[MAXHOSTNAMELEN]; 9621590Srgrimes struct netent *np = 0; 963176194Smarius in_addr_t i; 9641590Srgrimes 965261207Sglebius /* It is ok to supply host address. */ 966261207Sglebius in &= mask; 967261207Sglebius 9681590Srgrimes i = ntohl(in); 96978238Sassar if (!numeric_addr && i) { 970261207Sglebius np = getnetbyaddr(i >> NSHIFT(ntohl(mask)), AF_INET); 97184803Sru if (np != NULL) { 9721590Srgrimes cp = np->n_name; 97374262Sbrian trimdomain(cp, strlen(cp)); 97413433Speter } 9751590Srgrimes } 97684803Sru if (cp != NULL) { 977183988Sdelphij strlcpy(line, cp, sizeof(line)); 97884803Sru } else { 979176099Smarius inet_ntop(AF_INET, &in, line, sizeof(line) - 1); 98077911Sru } 981261207Sglebius domask(line + strlen(line), i, ntohl(mask)); 9821590Srgrimes return (line); 9831590Srgrimes} 9841590Srgrimes 985166711Sbms#undef NSHIFT 986166711Sbms 98754263Sshin#ifdef INET6 988217642Sumevoid 989217642Sumein6_fillscopeid(struct sockaddr_in6 *sa6) 990217642Sume{ 991217642Sume#if defined(__KAME__) 992217642Sume /* 993217642Sume * XXX: This is a special workaround for KAME kernels. 994217642Sume * sin6_scope_id field of SA should be set in the future. 995217642Sume */ 996217642Sume if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || 997217642Sume IN6_IS_ADDR_MC_NODELOCAL(&sa6->sin6_addr) || 998217642Sume IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) { 999273188Shrs if (sa6->sin6_scope_id == 0) 1000273188Shrs sa6->sin6_scope_id = 1001273188Shrs ntohs(*(u_int16_t *)&sa6->sin6_addr.s6_addr[2]); 1002217642Sume sa6->sin6_addr.s6_addr[2] = sa6->sin6_addr.s6_addr[3] = 0; 1003217642Sume } 1004217642Sume#endif 1005217642Sume} 1006217642Sume 1007102975Sdwmaloneconst char * 100878314Sassarnetname6(struct sockaddr_in6 *sa6, struct in6_addr *mask) 100954263Sshin{ 101074262Sbrian static char line[MAXHOSTNAMELEN]; 101154263Sshin u_char *p = (u_char *)mask; 101254263Sshin u_char *lim; 1013146187Sume int masklen, illegal = 0, flag = 0; 101454263Sshin 101554263Sshin if (mask) { 101654263Sshin for (masklen = 0, lim = p + 16; p < lim; p++) { 101754263Sshin switch (*p) { 101862584Sitojun case 0xff: 101962584Sitojun masklen += 8; 102062584Sitojun break; 102154263Sshin case 0xfe: 102254263Sshin masklen += 7; 102354263Sshin break; 102454263Sshin case 0xfc: 102554263Sshin masklen += 6; 102654263Sshin break; 102754263Sshin case 0xf8: 102854263Sshin masklen += 5; 102954263Sshin break; 103054263Sshin case 0xf0: 103154263Sshin masklen += 4; 103254263Sshin break; 103354263Sshin case 0xe0: 103454263Sshin masklen += 3; 103554263Sshin break; 103654263Sshin case 0xc0: 103754263Sshin masklen += 2; 103854263Sshin break; 103954263Sshin case 0x80: 104054263Sshin masklen += 1; 104154263Sshin break; 104254263Sshin case 0x00: 104354263Sshin break; 104454263Sshin default: 104554263Sshin illegal ++; 104654263Sshin break; 104754263Sshin } 104854263Sshin } 104954263Sshin if (illegal) 105054263Sshin fprintf(stderr, "illegal prefixlen\n"); 105154263Sshin } 105254263Sshin else 105354263Sshin masklen = 128; 105454263Sshin 105554263Sshin if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) 105654263Sshin return("default"); 105754263Sshin 105878238Sassar if (numeric_addr) 105954263Sshin flag |= NI_NUMERICHOST; 106054263Sshin getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line), 106154263Sshin NULL, 0, flag); 106254263Sshin 106378238Sassar if (numeric_addr) 106454263Sshin sprintf(&line[strlen(line)], "/%d", masklen); 106554263Sshin 106654263Sshin return line; 106754263Sshin} 106854263Sshin 106954263Sshinchar * 107078314Sassarroutename6(struct sockaddr_in6 *sa6) 107154263Sshin{ 107274262Sbrian static char line[MAXHOSTNAMELEN]; 1073146187Sume int flag = 0; 107462584Sitojun /* use local variable for safety */ 1075160789Syar struct sockaddr_in6 sa6_local; 107654263Sshin 1077160789Syar sa6_local.sin6_family = AF_INET6; 1078160789Syar sa6_local.sin6_len = sizeof(sa6_local); 107962584Sitojun sa6_local.sin6_addr = sa6->sin6_addr; 108062584Sitojun sa6_local.sin6_scope_id = sa6->sin6_scope_id; 108162584Sitojun 108278238Sassar if (numeric_addr) 108354263Sshin flag |= NI_NUMERICHOST; 108454263Sshin 108562584Sitojun getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len, 108662584Sitojun line, sizeof(line), NULL, 0, flag); 108754263Sshin 108854263Sshin return line; 108954263Sshin} 109054263Sshin#endif /*INET6*/ 109154263Sshin 10921590Srgrimes/* 10931590Srgrimes * Print routing statistics 10941590Srgrimes */ 10951590Srgrimesvoid 1096263335Sglebiusrt_stats(void) 10971590Srgrimes{ 10981590Srgrimes struct rtstat rtstat; 1099263335Sglebius u_long rtsaddr, rttaddr; 110078958Sru int rttrash; 11011590Srgrimes 1102263335Sglebius kresolve_list(rl); 1103263335Sglebius 1104263335Sglebius if ((rtsaddr = rl[N_RTSTAT].n_value) == 0) { 11051590Srgrimes printf("rtstat: symbol not in namelist\n"); 11061590Srgrimes return; 11071590Srgrimes } 1108263335Sglebius if ((rttaddr = rl[N_RTTRASH].n_value) == 0) { 110978958Sru printf("rttrash: symbol not in namelist\n"); 111078958Sru return; 111178958Sru } 111278958Sru kread(rtsaddr, (char *)&rtstat, sizeof (rtstat)); 111378958Sru kread(rttaddr, (char *)&rttrash, sizeof (rttrash)); 11141590Srgrimes printf("routing:\n"); 111578659Sru 111678659Sru#define p(f, m) if (rtstat.f || sflag <= 1) \ 111778659Sru printf(m, rtstat.f, plural(rtstat.f)) 111878659Sru 1119198118Srwatson p(rts_badredirect, "\t%hu bad routing redirect%s\n"); 1120198118Srwatson p(rts_dynamic, "\t%hu dynamically created route%s\n"); 1121198118Srwatson p(rts_newgateway, "\t%hu new gateway%s due to redirects\n"); 1122198118Srwatson p(rts_unreach, "\t%hu destination%s found unreachable\n"); 1123198118Srwatson p(rts_wildcard, "\t%hu use%s of a wildcard route\n"); 112478659Sru#undef p 112578958Sru 112678958Sru if (rttrash || sflag <= 1) 112778958Sru printf("\t%u route%s not in table but not freed\n", 112878958Sru rttrash, plural(rttrash)); 11291590Srgrimes} 113011819Sjulian 113111819Sjulianchar * 113278314Sassaripx_print(struct sockaddr *sa) 113311819Sjulian{ 113411819Sjulian u_short port; 113535308Sphk struct servent *sp = 0; 1136102975Sdwmalone const char *net = "", *host = ""; 1137102975Sdwmalone char *p; 1138102975Sdwmalone u_char *q; 113911819Sjulian struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; 114035308Sphk static char mybuf[50]; 114111819Sjulian char cport[10], chost[15], cnet[15]; 114211819Sjulian 114311819Sjulian port = ntohs(work.x_port); 114411819Sjulian 114511819Sjulian if (ipx_nullnet(work) && ipx_nullhost(work)) { 114611819Sjulian 114711819Sjulian if (port) { 114835308Sphk if (sp) 114935308Sphk sprintf(mybuf, "*.%s", sp->s_name); 115035308Sphk else 115135308Sphk sprintf(mybuf, "*.%x", port); 115211819Sjulian } else 115311819Sjulian sprintf(mybuf, "*.*"); 115411819Sjulian 115511819Sjulian return (mybuf); 115611819Sjulian } 115711819Sjulian 115825654Sjhay if (ipx_wildnet(work)) 115911819Sjulian net = "any"; 116011819Sjulian else if (ipx_nullnet(work)) 116111819Sjulian net = "*"; 116211819Sjulian else { 116311819Sjulian q = work.x_net.c_net; 116411819Sjulian sprintf(cnet, "%02x%02x%02x%02x", 116511819Sjulian q[0], q[1], q[2], q[3]); 116611819Sjulian for (p = cnet; *p == '0' && p < cnet + 8; p++) 116711819Sjulian continue; 116811819Sjulian net = p; 116911819Sjulian } 117011819Sjulian 117125654Sjhay if (ipx_wildhost(work)) 117211819Sjulian host = "any"; 117311819Sjulian else if (ipx_nullhost(work)) 117411819Sjulian host = "*"; 117511819Sjulian else { 117611819Sjulian q = work.x_host.c_host; 117711819Sjulian sprintf(chost, "%02x%02x%02x%02x%02x%02x", 117811819Sjulian q[0], q[1], q[2], q[3], q[4], q[5]); 117911819Sjulian for (p = chost; *p == '0' && p < chost + 12; p++) 118011819Sjulian continue; 118111819Sjulian host = p; 118211819Sjulian } 118311819Sjulian 118411819Sjulian if (port) { 118535308Sphk if (strcmp(host, "*") == 0) 118635308Sphk host = ""; 1187175061Sobrien if (sp) 118836788Simp snprintf(cport, sizeof(cport), 118936788Simp "%s%s", *host ? "." : "", sp->s_name); 1190175061Sobrien else 119136788Simp snprintf(cport, sizeof(cport), 119236788Simp "%s%x", *host ? "." : "", port); 119311819Sjulian } else 119411819Sjulian *cport = 0; 119511819Sjulian 119636788Simp snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport); 119711819Sjulian return(mybuf); 119811819Sjulian} 119911819Sjulian 120011819Sjulianchar * 120178314Sassaripx_phost(struct sockaddr *sa) 120211819Sjulian{ 1203102975Sdwmalone struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa; 120411819Sjulian struct sockaddr_ipx work; 120535308Sphk static union ipx_net ipx_zeronet; 120611819Sjulian char *p; 120711819Sjulian 120811819Sjulian work = *sipx; 120911819Sjulian 121011819Sjulian work.sipx_addr.x_port = 0; 121111819Sjulian work.sipx_addr.x_net = ipx_zeronet; 121211819Sjulian p = ipx_print((struct sockaddr *)&work); 121311819Sjulian if (strncmp("*.", p, 2) == 0) p += 2; 121411819Sjulian 121511819Sjulian return(p); 121611819Sjulian} 121711819Sjulian 12181590Srgrimesvoid 121978314SassarupHex(char *p0) 12201590Srgrimes{ 1221102975Sdwmalone char *p = p0; 12221590Srgrimes 122335308Sphk for (; *p; p++) 122435308Sphk switch (*p) { 122535308Sphk 122635308Sphk case 'a': 122735308Sphk case 'b': 122835308Sphk case 'c': 122935308Sphk case 'd': 123035308Sphk case 'e': 123135308Sphk case 'f': 123235308Sphk *p += ('A' - 'a'); 123335308Sphk break; 123435308Sphk } 12351590Srgrimes} 1236