diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 880f1139843c..7c73e66aba18 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -1,504 +1,506 @@ # $FreeBSD$ # # Option file for FreeBSD /usr/src builds, at least the userland and boot loader # portions of the tree. These options generally chose what parts of the tree to # include or omit and are FreeBSD source tree specific. # # Users define WITH_FOO and WITHOUT_FOO on the command line or in /etc/src.conf # and /etc/make.conf files. These translate in the build system to MK_FOO={yes,no} # with sensible (usually) defaults. # # Makefiles must include bsd.opts.mk after defining specific MK_FOO options that # are applicable for that Makefile (typically there are none, but sometimes there # are exceptions). Recursive makes usually add MK_FOO=no for options that they wish # to omit from that make. # # Makefiles must include bsd.mkopt.mk before they test the value of any MK_FOO # variable. # # Makefiles may also assume that this file is included by src.opts.mk should it # need variables defined there prior to the end of the Makefile where # bsd.{subdir,lib.bin}.mk is traditionally included. # # The old-style YES_FOO and NO_FOO are being phased out. No new instances of them # should be added. Old instances should be removed since they were just to # bridge the gap between FreeBSD 4 and FreeBSD 5. # # Makefiles should never test WITH_FOO or WITHOUT_FOO directly (although an # exception is made for _WITHOUT_SRCONF which turns off this mechanism # completely inside bsd.*.mk files). # .if !target(____) ____: .include # # Define MK_* variables (which are either "yes" or "no") for users # to set via WITH_*/WITHOUT_* in /etc/src.conf and override in the # make(1) environment. # These should be tested with `== "no"' or `!= "no"' in makefiles. # The NO_* variables should only be set by makefiles for variables # that haven't been converted over. # # These options are used by the src builds. Those listed in # __DEFAULT_YES_OPTIONS default to 'yes' and will build unless turned # off. __DEFAULT_NO_OPTIONS will default to 'no' and won't build # unless turned on. Any options listed in 'BROKEN_OPTIONS' will be # hard-wired to 'no'. "Broken" here means not working or # not-appropriate and/or not supported. It doesn't imply something is # wrong with the code. There's not a single good word for this, so # BROKEN was selected as the least imperfect one considered at the # time. Options are added to BROKEN_OPTIONS list on a per-arch basis. # At this time, there's no provision for mutually incompatible options. __DEFAULT_YES_OPTIONS = \ ACCT \ ACPI \ APM \ AT \ AUDIT \ AUTHPF \ AUTOFS \ BHYVE \ BLACKLIST \ BLUETOOTH \ BOOT \ BOOTPARAMD \ BOOTPD \ BSD_CPIO \ BSDINSTALL \ BSNMP \ BZIP2 \ CALENDAR \ CAPSICUM \ CAROOT \ CASPER \ CCD \ CDDL \ CLANG \ CLANG_BOOTSTRAP \ CLEAN \ CPP \ CROSS_COMPILER \ CRYPT \ CUSE \ CXGBETOOL \ DIALOG \ DICT \ DMAGENT \ DTRACE \ DYNAMICROOT \ EE \ EFI \ ELFTOOLCHAIN_BOOTSTRAP \ EXAMPLES \ FILE \ FINGER \ FLOPPY \ FORTH \ FP_LIBC \ FREEBSD_UPDATE \ FTP \ GAMES \ GH_BC \ GNU_DIFF \ GOOGLETEST \ GPIO \ HAST \ HTML \ HYPERV \ ICONV \ INET \ INET6 \ INETD \ IPFILTER \ IPFW \ ISCSI \ JAIL \ KDUMP \ KVM \ LDNS \ LDNS_UTILS \ LEGACY_CONSOLE \ LLD \ LLD_BOOTSTRAP \ LLD_IS_LD \ LLVM_ASSERTIONS \ LLVM_COV \ LLVM_CXXFILT \ LOADER_GELI \ LOADER_KBOOT \ LOADER_LUA \ LOADER_OFW \ LOADER_UBOOT \ LOCALES \ LOCATE \ LPR \ LS_COLORS \ MACHDEP_OPTIMIZATIONS \ MAIL \ MAILWRAPPER \ MAKE \ MLX5TOOL \ NETCAT \ NETGRAPH \ + NETLINK \ NLS_CATALOGS \ NS_CACHING \ NTP \ NVME \ OFED \ OPENSSL \ PAM \ PF \ PKGBOOTSTRAP \ PMC \ PORTSNAP \ PPP \ QUOTAS \ RADIUS_SUPPORT \ RBOOTD \ RESCUE \ ROUTED \ SENDMAIL \ SERVICESDB \ SETUID_LOGIN \ SHARED_TOOLCHAIN \ SHAREDOCS \ SOURCELESS \ SOURCELESS_HOST \ SOURCELESS_UCODE \ STATS \ SYSCONS \ SYSTEM_COMPILER \ SYSTEM_LINKER \ TALK \ TCP_WRAPPERS \ TCSH \ TELNET \ TEXTPROC \ TFTP \ UNBOUND \ USB \ UTMPX \ VI \ VT \ WIRELESS \ WPA_SUPPLICANT_EAPOL \ ZFS \ LOADER_ZFS \ ZONEINFO __DEFAULT_NO_OPTIONS = \ BEARSSL \ BHYVE_SNAPSHOT \ CLANG_EXTRAS \ CLANG_FORMAT \ DETECT_TZ_CHANGES \ DISK_IMAGE_TOOLS_BOOTSTRAP \ DTRACE_TESTS \ EXPERIMENTAL \ HESIOD \ LOADER_VERBOSE \ LOADER_VERIEXEC_PASS_MANIFEST \ LLVM_BINUTILS \ MALLOC_PRODUCTION \ OFED_EXTRA \ OPENLDAP \ REPRODUCIBLE_BUILD \ RPCBIND_WARMSTART_SUPPORT \ SORT_THREADS \ ZONEINFO_LEAPSECONDS_SUPPORT \ # LEFT/RIGHT. Left options which default to "yes" unless their corresponding # RIGHT option is disabled. __DEFAULT_DEPENDENT_OPTIONS= \ CLANG_FULL/CLANG \ LLVM_TARGET_ALL/CLANG \ LOADER_VERIEXEC/BEARSSL \ LOADER_EFI_SECUREBOOT/LOADER_VERIEXEC \ LOADER_VERIEXEC_VECTX/LOADER_VERIEXEC \ VERIEXEC/BEARSSL \ # MK_*_SUPPORT options which default to "yes" unless their corresponding # MK_* variable is set to "no". # .for var in \ BLACKLIST \ BZIP2 \ INET \ INET6 \ KERBEROS \ KVM \ NETGRAPH \ + NETLINK \ PAM \ TESTS \ WIRELESS __DEFAULT_DEPENDENT_OPTIONS+= ${var}_SUPPORT/${var} .endfor .-include # # Default behaviour of some options depends on the architecture. Unfortunately # this means that we have to test TARGET_ARCH (the buildworld case) as well # as MACHINE_ARCH (the non-buildworld case). Normally TARGET_ARCH is not # used at all in bsd.*.mk, but we have to make an exception here if we want # to allow defaults for some things like clang to vary by target architecture. # Additional, per-target behavior should be rarely added only after much # gnashing of teeth and grinding of gears. # .if defined(TARGET_ARCH) __T=${TARGET_ARCH} .else __T=${MACHINE_ARCH} .endif # All supported backends for LLVM_TARGET_XXX __LLVM_TARGETS= \ aarch64 \ arm \ powerpc \ riscv \ x86 __LLVM_TARGET_FILT= C/(amd64|i386)/x86/:C/powerpc.*/powerpc/:C/armv[67]/arm/:C/riscv.*/riscv/:C/mips.*/mips/ .for __llt in ${__LLVM_TARGETS} # Default enable the given TARGET's LLVM_TARGET support .if ${__T:${__LLVM_TARGET_FILT}} == ${__llt} __DEFAULT_YES_OPTIONS+= LLVM_TARGET_${__llt:${__LLVM_TARGET_FILT}:tu} # aarch64 needs arm for -m32 support. .elif ${__T} == "aarch64" && ${__llt:Marm*} != "" __DEFAULT_DEPENDENT_OPTIONS+= LLVM_TARGET_ARM/LLVM_TARGET_AARCH64 # Default the rest of the LLVM_TARGETs to the value of MK_LLVM_TARGET_ALL. .else __DEFAULT_DEPENDENT_OPTIONS+= LLVM_TARGET_${__llt:${__LLVM_TARGET_FILT}:tu}/LLVM_TARGET_ALL .endif .endfor __DEFAULT_NO_OPTIONS+=LLVM_TARGET_BPF LLVM_TARGET_MIPS .include .if ${__T} == "i386" || ${__T} == "amd64" __DEFAULT_NO_OPTIONS += FDT .else __DEFAULT_YES_OPTIONS += FDT .endif .if ${__T:Marm*} == "" && ${__T:Mriscv64*} == "" __DEFAULT_YES_OPTIONS+=LLDB .else __DEFAULT_NO_OPTIONS+=LLDB .endif # LIB32 is supported on amd64 and powerpc64 .if (${__T} == "amd64" || ${__T} == "powerpc64") __DEFAULT_YES_OPTIONS+=LIB32 .else BROKEN_OPTIONS+=LIB32 .endif # EFI doesn't exist on powerpc (well, officially) .if ${__T:Mpowerpc*} BROKEN_OPTIONS+=EFI .endif # OFW is only for powerpc, exclude others .if ${__T:Mpowerpc*} == "" BROKEN_OPTIONS+=LOADER_OFW .endif # KBOOT is only for powerpc64 (powerpc64le broken) amd64 and aarch64 .if ${__T} != "powerpc64" && ${__T} != "amd64" && ${__T} != "aarch64" BROKEN_OPTIONS+=LOADER_KBOOT .endif # UBOOT is only for arm, and big-endian powerpc .if (${__T:Marm*} == "" && ${__T:Mpowerpc*} == "") || ${__T} == "powerpc64le" BROKEN_OPTIONS+=LOADER_UBOOT .endif # GELI and Lua in loader currently cause boot failures on powerpc. # Further debugging is required -- probably they are just broken on big # endian systems generically (they jump to null pointers or try to read # crazy high addresses, which is typical of endianness problems). .if ${__T:Mpowerpc*} BROKEN_OPTIONS+=LOADER_GELI LOADER_LUA .endif # Kernel TLS is enabled by default on amd64, aarch64 and powerpc64* .if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T:Mpowerpc64*} != "" __DEFAULT_YES_OPTIONS+=OPENSSL_KTLS .else __DEFAULT_NO_OPTIONS+=OPENSSL_KTLS .endif .if ${__T} != "aarch64" && ${__T} != "amd64" && ${__T} != "i386" && \ ${__T:Mpowerpc64*} == "" BROKEN_OPTIONS+=CXGBETOOL BROKEN_OPTIONS+=MLX5TOOL .endif .if ${__T} != "amd64" && ${__T} != "i386" && ${__T} != "aarch64" BROKEN_OPTIONS+=HYPERV .endif # NVME is only aarch64, x86 and powerpc64* .if ${__T} != "aarch64" && ${__T} != "amd64" && ${__T} != "i386" && \ ${__T:Mpowerpc64*} == "" BROKEN_OPTIONS+=NVME .endif .if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386" || \ ${__T:Mpowerpc64*} != "" || ${__T:Mriscv64*} != "" __DEFAULT_YES_OPTIONS+=OPENMP .else __DEFAULT_NO_OPTIONS+=OPENMP .endif # Broken on 32-bit arm, kernel module compile errors .if ${__T:Marm*} != "" BROKEN_OPTIONS+= OFED .endif .include # # Force some options off if their dependencies are off. # Order is somewhat important. # .if ${MK_CAPSICUM} == "no" MK_CASPER:= no .endif .if ${MK_SOURCELESS} == "no" MK_SOURCELESS_HOST:= no MK_SOURCELESS_UCODE:= no .endif .if ${MK_CDDL} == "no" MK_CTF:= no MK_DTRACE:= no MK_LOADER_ZFS:= no MK_ZFS:= no .endif .if ${MK_CRYPT} == "no" MK_OPENSSL:= no MK_OPENSSH:= no MK_KERBEROS:= no MK_KERBEROS_SUPPORT:= no .endif .if ${MK_DIALOG} == "no" MK_BSDINSTALL:= no .endif .if ${MK_DTRACE} == "no" MK_CTF:= no .endif .if ${MK_MAIL} == "no" MK_MAILWRAPPER:= no MK_SENDMAIL:= no MK_DMAGENT:= no .endif .if ${MK_NETGRAPH} == "no" MK_BLUETOOTH:= no .endif .if ${MK_NLS} == "no" MK_NLS_CATALOGS:= no .endif .if ${MK_OPENSSL} == "no" MK_DMAGENT:= no MK_OPENSSH:= no MK_OPENSSL_KTLS:= no MK_KERBEROS:= no MK_KERBEROS_SUPPORT:= no MK_LDNS:= no MK_PKGBOOTSTRAP:= no MK_LOADER_ZFS:= no MK_ZFS:= no .endif .if ${MK_LDNS} == "no" MK_LDNS_UTILS:= no MK_UNBOUND:= no .endif .if ${MK_PF} == "no" MK_AUTHPF:= no .endif .if ${MK_OFED} == "no" MK_OFED_EXTRA:= no .endif .if ${MK_TESTS} == "no" MK_DTRACE_TESTS:= no .endif .if ${MK_TESTS_SUPPORT} == "no" MK_GOOGLETEST:= no .endif .if ${MK_ZONEINFO} == "no" MK_ZONEINFO_LEAPSECONDS_SUPPORT:= no .endif .if ${MK_CROSS_COMPILER} == "no" MK_CLANG_BOOTSTRAP:= no MK_ELFTOOLCHAIN_BOOTSTRAP:= no MK_LLD_BOOTSTRAP:= no .endif .if ${MK_TOOLCHAIN} == "no" MK_CLANG:= no MK_INCLUDES:= no MK_LLD:= no MK_LLDB:= no MK_LLVM_BINUTILS:= no .endif .if ${MK_CLANG} == "no" MK_CLANG_EXTRAS:= no MK_CLANG_FORMAT:= no MK_CLANG_FULL:= no MK_LLVM_COV:= no .endif .if ${MK_ASAN} == "yes" # In order to get sensible backtraces from ASAN we have to install # llvm-symbolizer as /usr/bin/addr2line instead of the elftoolchain version. MK_LLVM_BINUTILS:= yes .endif .if ${MK_LLVM_BINUTILS} == "yes" # MK_LLVM_CXXFILT is a subset of MK_LLVM_BINUTILS and should therefore be # enabled if MK_LLVM_BINUTILS is set. MK_LLVM_CXXFILT:= yes .endif .if ${MK_LOADER_VERIEXEC} == "no" MK_LOADER_VERIEXEC_PASS_MANIFEST := no .endif # # MK_* options whose default value depends on another option. # .for vv in \ GSSAPI/KERBEROS \ MAN_UTILS/MAN .if defined(WITH_${vv:H}) MK_${vv:H}:= yes .elif defined(WITHOUT_${vv:H}) MK_${vv:H}:= no .else MK_${vv:H}:= ${MK_${vv:T}} .endif .endfor # # Set defaults for the MK_*_SUPPORT variables. # .endif # !target(____) diff --git a/tools/build/options/WITHOUT_NETLINK_SUPPORT b/tools/build/options/WITHOUT_NETLINK_SUPPORT new file mode 100644 index 000000000000..4a72d3f1e4d1 --- /dev/null +++ b/tools/build/options/WITHOUT_NETLINK_SUPPORT @@ -0,0 +1,5 @@ +.\" $FreeBSD$ +Make libraries and programs use rtsock and +.Xr sysctl 3 +interfaces instead of +.Xr snl 3 . diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile index e2c9ca09eea5..92f8aa9c30fa 100644 --- a/usr.bin/netstat/Makefile +++ b/usr.bin/netstat/Makefile @@ -1,67 +1,72 @@ # @(#)Makefile 8.1 (Berkeley) 6/12/93 # $FreeBSD$ .include PROG= netstat SRCS= if.c inet.c main.c mbuf.c mroute.c netisr.c nl_symbols.c route.c \ unix.c mroute6.c ipsec.c bpf.c pfkey.c sctp.c common.c nhops.c nhgrp.c \ - route_netlink.c \ nl_defs.h nl_symbols.c: nlist_symbols awk '\ BEGIN { \ print "#include "; \ print "#include "; \ print "struct nlist nl[] = {"; \ } \ !/^\#/ { printf("\t{ .n_name = \"%s\" },\n", $$2); } \ END { print "\t{ .n_name = NULL },\n};" } \ ' < ${.ALLSRC} > ${.TARGET} || rm -f ${.TARGET} nl_defs.h: nlist_symbols awk '\ BEGIN { \ print "#include "; \ print "extern struct nlist nl[];"; \ i = 0; \ } \ !/^\#/ { printf("\#define\tN%s\t%s\n", toupper($$2), i++); }' \ < ${.ALLSRC} > ${.TARGET} || rm -f ${.TARGET} CLEANFILES+= nl_symbols.c nl_defs.h CFLAGS+= -I${.OBJDIR} WARNS?= 3 CFLAGS+=-fno-strict-aliasing CFLAGS+=-DIPSEC CFLAGS+=-DSCTP .if ${MK_INET_SUPPORT} != "no" CFLAGS+=-DINET .endif .if ${MK_INET6_SUPPORT} != "no" SRCS+= inet6.c CFLAGS+=-DINET6 .endif .if ${MK_OFED} != "no" CFLAGS+=-DSDP .endif .if ${MK_PF} != "no" CFLAGS+=-DPF .endif BINGRP= kmem BINMODE=2555 LIBADD= kvm memstat xo util .if ${MK_NETGRAPH_SUPPORT} != "no" SRCS+= netgraph.c LIBADD+= netgraph CFLAGS+=-DNETGRAPH .endif +.if ${MK_NETLINK_SUPPORT} != "no" +SRCS+= route_netlink.c +.else +CFLAGS+=-DWITHOUT_NETLINK +.endif + .include diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c index 5de683ebfe7a..c597f3632fa6 100644 --- a/usr.bin/netstat/route.c +++ b/usr.bin/netstat/route.c @@ -1,727 +1,736 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netstat.h" #include "common.h" #include "nl_defs.h" /* * Definitions for showing gateway flags. */ struct bits rt_bits[] = { { RTF_UP, 'U', "up" }, { RTF_GATEWAY, 'G', "gateway" }, { RTF_HOST, 'H', "host" }, { RTF_REJECT, 'R', "reject" }, { RTF_DYNAMIC, 'D', "dynamic" }, { RTF_MODIFIED, 'M', "modified" }, { RTF_DONE, 'd', "done" }, /* Completed -- for routing msgs only */ { RTF_XRESOLVE, 'X', "xresolve" }, { RTF_STATIC, 'S', "static" }, { RTF_PROTO1, '1', "proto1" }, { RTF_PROTO2, '2', "proto2" }, { RTF_PROTO3, '3', "proto3" }, { RTF_BLACKHOLE,'B', "blackhole" }, { RTF_BROADCAST,'b', "broadcast" }, #ifdef RTF_LLINFO { RTF_LLINFO, 'L', "llinfo" }, #endif { 0 , 0, NULL } }; +#ifdef WITHOUT_NETLINK static struct ifmap_entry *ifmap; static size_t ifmap_size; +#endif static struct timespec uptime; static const char *netname4(in_addr_t, in_addr_t); #ifdef INET6 static const char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); #endif +#ifdef WITHOUT_NETLINK static void p_rtable_sysctl(int, int); static void p_rtentry_sysctl(const char *name, struct rt_msghdr *); +#endif static void domask(char *, size_t, u_long); const uint32_t rt_default_weight = RT_DEFAULT_WEIGHT; /* * Print routing tables. */ void routepr(int fibnum, int af) { size_t intsize; int numfibs; if (live == 0) return; intsize = sizeof(int); if (fibnum == -1 && sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) fibnum = 0; if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) numfibs = 1; if (fibnum < 0 || fibnum > numfibs - 1) errx(EX_USAGE, "%d: invalid fib", fibnum); /* * Since kernel & userland use different timebase * (time_uptime vs time_second) and we are reading kernel memory * directly we should do rt_expire --> expire_time conversion. */ if (clock_gettime(CLOCK_UPTIME, &uptime) < 0) err(EX_OSERR, "clock_gettime() failed"); xo_open_container("route-information"); xo_emit("{T:Routing tables}"); if (fibnum) xo_emit(" ({L:fib}: {:fib/%d})", fibnum); xo_emit("\n"); - if (!p_rtable_netlink(fibnum, af)) - p_rtable_sysctl(fibnum, af); +#ifdef WITHOUT_NETLINK + p_rtable_sysctl(fibnum, af); +#else + p_rtable_netlink(fibnum, af); +#endif xo_close_container("route-information"); } /* * Print address family header before a section of the routing table. */ void pr_family(int af1) { const char *afname; switch (af1) { case AF_INET: afname = "Internet"; break; #ifdef INET6 case AF_INET6: afname = "Internet6"; break; #endif /*INET6*/ case AF_ISO: afname = "ISO"; break; case AF_CCITT: afname = "X.25"; break; case AF_NETGRAPH: afname = "Netgraph"; break; default: afname = NULL; break; } if (afname) xo_emit("\n{k:address-family/%s}:\n", afname); else xo_emit("\n{L:Protocol Family} {k:address-family/%d}:\n", af1); } /* column widths; each followed by one space */ #ifndef INET6 #define WID_DST_DEFAULT(af) 18 /* width of destination column */ #define WID_GW_DEFAULT(af) 18 /* width of gateway column */ #define WID_IF_DEFAULT(af) (Wflag ? 10 : 8) /* width of netif column */ #else #define WID_DST_DEFAULT(af) \ ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18) #define WID_GW_DEFAULT(af) \ ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18) #define WID_IF_DEFAULT(af) ((af) == AF_INET6 ? 8 : (Wflag ? 10 : 8)) #endif /*INET6*/ struct _wid wid; /* * Print header for routing table columns. */ void pr_rthdr(int af1 __unused) { if (Wflag) { xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " "{T:/%*.*s} {T:/%*.*s} {T:/%*s}\n", wid.dst, wid.dst, "Destination", wid.gw, wid.gw, "Gateway", wid.flags, wid.flags, "Flags", wid.mtu, wid.mtu, "Nhop#", wid.mtu, wid.mtu, "Mtu", wid.iface, wid.iface, "Netif", wid.expire, "Expire"); } else { xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " "{T:/%*s}\n", wid.dst, wid.dst, "Destination", wid.gw, wid.gw, "Gateway", wid.flags, wid.flags, "Flags", wid.iface, wid.iface, "Netif", wid.expire, "Expire"); } } void set_wid(int fam) { wid.dst = WID_DST_DEFAULT(fam); wid.gw = WID_GW_DEFAULT(fam); wid.flags = 6; wid.pksent = 8; wid.mtu = 6; wid.iface = WID_IF_DEFAULT(fam); wid.expire = 6; } +#ifdef WITHOUT_NETLINK static void p_rtable_sysctl(int fibnum, int af) { size_t needed; int mib[7]; char *buf, *next, *lim; struct rt_msghdr *rtm; struct sockaddr *sa; int fam = AF_UNSPEC; int need_table_close = false; ifmap = prepare_ifmap(&ifmap_size); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = af; mib[4] = NET_RT_DUMP; mib[5] = 0; mib[6] = fibnum; if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d estimate", af, fibnum); if ((buf = malloc(needed)) == NULL) errx(2, "malloc(%lu)", (unsigned long)needed); if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum); lim = buf + needed; xo_open_container("route-table"); xo_open_list("rt-family"); for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; if (rtm->rtm_version != RTM_VERSION) continue; /* * Peek inside header to determine AF */ sa = (struct sockaddr *)(rtm + 1); /* Only print family first time. */ if (fam != sa->sa_family) { if (need_table_close) { xo_close_list("rt-entry"); xo_close_instance("rt-family"); } need_table_close = true; fam = sa->sa_family; set_wid(fam); xo_open_instance("rt-family"); pr_family(fam); xo_open_list("rt-entry"); pr_rthdr(fam); } p_rtentry_sysctl("rt-entry", rtm); } if (need_table_close) { xo_close_list("rt-entry"); xo_close_instance("rt-family"); } xo_close_list("rt-family"); xo_close_container("route-table"); free(buf); } static void p_rtentry_sysctl(const char *name, struct rt_msghdr *rtm) { struct sockaddr *sa, *addr[RTAX_MAX]; char buffer[128]; char prettyname[128]; int i, protrusion; xo_open_instance(name); sa = (struct sockaddr *)(rtm + 1); for (i = 0; i < RTAX_MAX; i++) { if (rtm->rtm_addrs & (1 << i)) { addr[i] = sa; sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); } } protrusion = p_sockaddr("destination", addr[RTAX_DST], addr[RTAX_NETMASK], rtm->rtm_flags, wid.dst); protrusion = p_sockaddr("gateway", addr[RTAX_GATEWAY], NULL, RTF_HOST, wid.gw - protrusion); snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:} ", wid.flags - protrusion); p_flags(rtm->rtm_flags, buffer); /* Output path weight as non-visual property */ xo_emit("{e:weight/%u}", rtm->rtm_rmx.rmx_weight); if (Wflag) { /* XXX: use=0? */ xo_emit("{t:nhop/%*lu} ", wid.mtu, rtm->rtm_rmx.rmx_nhidx); if (rtm->rtm_rmx.rmx_mtu != 0) xo_emit("{t:mtu/%*lu} ", wid.mtu, rtm->rtm_rmx.rmx_mtu); else xo_emit("{P:/%*s} ", wid.mtu, ""); } memset(prettyname, 0, sizeof(prettyname)); if (rtm->rtm_index < ifmap_size) { strlcpy(prettyname, ifmap[rtm->rtm_index].ifname, sizeof(prettyname)); if (*prettyname == '\0') strlcpy(prettyname, "---", sizeof(prettyname)); } if (Wflag) xo_emit("{t:interface-name/%*s}", wid.iface, prettyname); else xo_emit("{t:interface-name/%*.*s}", wid.iface, wid.iface, prettyname); if (rtm->rtm_rmx.rmx_expire) { time_t expire_time; if ((expire_time = rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0) xo_emit(" {:expire-time/%*d}", wid.expire, (int)expire_time); } xo_emit("\n"); xo_close_instance(name); } +#endif int p_sockaddr(const char *name, struct sockaddr *sa, struct sockaddr *mask, int flags, int width) { const char *cp; char buf[128]; int protrusion; cp = fmt_sockaddr(sa, mask, flags); if (width < 0) { snprintf(buf, sizeof(buf), "{:%s/%%s} ", name); xo_emit(buf, cp); protrusion = 0; } else { if (Wflag != 0 || numeric_addr) { snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%s}{]:} ", -width, name); xo_emit(buf, cp); protrusion = strlen(cp) - width; if (protrusion < 0) protrusion = 0; } else { snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%-.*s}{]:} ", -width, name); xo_emit(buf, width, cp); protrusion = 0; } } return (protrusion); } const char * fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) { static char buf[128]; const char *cp; if (sa == NULL) return ("null"); switch(sa->sa_family) { #ifdef INET6 case AF_INET6: /* * The sa6->sin6_scope_id must be filled here because * this sockaddr is extracted from kmem(4) directly * and has KAME-specific embedded scope id in * sa6->sin6_addr.s6_addr[2]. */ in6_fillscopeid(satosin6(sa)); /* FALLTHROUGH */ #endif /*INET6*/ case AF_INET: if (flags & RTF_HOST) cp = routename(sa, numeric_addr); else if (mask) cp = netname(sa, mask); else cp = netname(sa, NULL); break; case AF_NETGRAPH: { strlcpy(buf, ((struct sockaddr_ng *)sa)->sg_data, sizeof(buf)); cp = buf; break; } case AF_LINK: { #if 0 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; /* Interface route. */ if (sdl->sdl_nlen) cp = sdl->sdl_data; else #endif cp = routename(sa, 1); break; } default: { u_char *s = (u_char *)sa->sa_data, *slim; char *cq, *cqlim; cq = buf; slim = sa->sa_len + (u_char *) sa; cqlim = cq + sizeof(buf) - sizeof(" ffff"); snprintf(cq, sizeof(buf), "(%d)", sa->sa_family); cq += strlen(cq); while (s < slim && cq < cqlim) { snprintf(cq, sizeof(" ff"), " %02x", *s++); cq += strlen(cq); if (s < slim) { snprintf(cq, sizeof("ff"), "%02x", *s++); cq += strlen(cq); } } cp = buf; } } return (cp); } void p_flags(int f, const char *format) { print_flags_generic(f, rt_bits, format, "flags_pretty"); } char * routename(struct sockaddr *sa, int flags) { static char line[NI_MAXHOST]; int error, f; f = (flags) ? NI_NUMERICHOST : 0; error = getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, f); if (error) { const void *src; switch (sa->sa_family) { #ifdef INET case AF_INET: src = &satosin(sa)->sin_addr; break; #endif /* INET */ #ifdef INET6 case AF_INET6: src = &satosin6(sa)->sin6_addr; break; #endif /* INET6 */ default: return(line); } inet_ntop(sa->sa_family, src, line, sizeof(line) - 1); return (line); } trimdomain(line, strlen(line)); return (line); } #define NSHIFT(m) ( \ (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \ (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \ (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \ 0) static void domask(char *dst, size_t buflen, u_long mask) { int b, i; if (mask == 0) { *dst = '\0'; return; } i = 0; for (b = 0; b < 32; b++) if (mask & (1 << b)) { int bb; i = b; for (bb = b+1; bb < 32; bb++) if (!(mask & (1 << bb))) { i = -1; /* noncontig */ break; } break; } if (i == -1) snprintf(dst, buflen, "&0x%lx", mask); else snprintf(dst, buflen, "/%d", 32-i); } /* * Return the name of the network whose address is given. */ const char * netname(struct sockaddr *sa, struct sockaddr *mask) { switch (sa->sa_family) { case AF_INET: if (mask != NULL) return (netname4(satosin(sa)->sin_addr.s_addr, satosin(mask)->sin_addr.s_addr)); else return (netname4(satosin(sa)->sin_addr.s_addr, INADDR_ANY)); break; #ifdef INET6 case AF_INET6: return (netname6(satosin6(sa), satosin6(mask))); #endif /* INET6 */ default: return (NULL); } } static const char * netname4(in_addr_t in, in_addr_t mask) { char *cp = 0; static char line[MAXHOSTNAMELEN + sizeof("&0xffffffff")]; char nline[INET_ADDRSTRLEN]; struct netent *np = 0; in_addr_t i; if (in == INADDR_ANY && mask == 0) { strlcpy(line, "default", sizeof(line)); return (line); } /* It is ok to supply host address. */ in &= mask; i = ntohl(in); if (!numeric_addr && i) { np = getnetbyaddr(i >> NSHIFT(ntohl(mask)), AF_INET); if (np != NULL) { cp = np->n_name; trimdomain(cp, strlen(cp)); } } if (cp != NULL) strlcpy(line, cp, sizeof(line)); else { inet_ntop(AF_INET, &in, nline, sizeof(nline)); strlcpy(line, nline, sizeof(line)); domask(line + strlen(line), sizeof(line) - strlen(line), ntohl(mask)); } return (line); } #undef NSHIFT #ifdef INET6 void in6_fillscopeid(struct sockaddr_in6 *sa6) { #if defined(__KAME__) /* * XXX: This is a special workaround for KAME kernels. * sin6_scope_id field of SA should be set in the future. */ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) { if (sa6->sin6_scope_id == 0) sa6->sin6_scope_id = ntohs(*(u_int16_t *)&sa6->sin6_addr.s6_addr[2]); sa6->sin6_addr.s6_addr[2] = sa6->sin6_addr.s6_addr[3] = 0; } #endif } /* Mask to length table. To check an invalid value, (length + 1) is used. */ static const u_char masktolen[256] = { [0xff] = 8 + 1, [0xfe] = 7 + 1, [0xfc] = 6 + 1, [0xf8] = 5 + 1, [0xf0] = 4 + 1, [0xe0] = 3 + 1, [0xc0] = 2 + 1, [0x80] = 1 + 1, [0x00] = 0 + 1, }; static const char * netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask) { static char line[NI_MAXHOST + sizeof("/xxx") - 1]; struct sockaddr_in6 addr; char nline[NI_MAXHOST]; char maskbuf[sizeof("/xxx")]; u_char *p, *lim; u_char masklen; int i; bool illegal = false; if (mask) { p = (u_char *)&mask->sin6_addr; for (masklen = 0, lim = p + 16; p < lim; p++) { if (masktolen[*p] > 0) { /* -1 is required. */ masklen += (masktolen[*p] - 1); } else illegal = true; } if (illegal) xo_error("illegal prefixlen\n"); memcpy(&addr, sa6, sizeof(addr)); for (i = 0; i < 16; ++i) addr.sin6_addr.s6_addr[i] &= mask->sin6_addr.s6_addr[i]; sa6 = &addr; } else masklen = 128; if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) return("default"); getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, nline, sizeof(nline), NULL, 0, NI_NUMERICHOST); if (numeric_addr) strlcpy(line, nline, sizeof(line)); else getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line), NULL, 0, 0); if (numeric_addr || strcmp(line, nline) == 0) { snprintf(maskbuf, sizeof(maskbuf), "/%d", masklen); strlcat(line, maskbuf, sizeof(line)); } return (line); } #endif /*INET6*/ /* * Print routing statistics */ void rt_stats(void) { struct rtstat rtstat; u_long rtsaddr; if ((rtsaddr = nl[N_RTSTAT].n_value) == 0) { xo_emit("{W:rtstat: symbol not in namelist}\n"); return; } kread_counters(rtsaddr, (char *)&rtstat, sizeof (rtstat)); xo_emit("{T:routing}:\n"); #define p(f, m) if (rtstat.f || sflag <= 1) \ xo_emit(m, rtstat.f, plural(rtstat.f)) p(rts_badredirect, "\t{:bad-redirects/%ju} " "{N:/bad routing redirect%s}\n"); p(rts_dynamic, "\t{:dynamically-created/%ju} " "{N:/dynamically created route%s}\n"); p(rts_newgateway, "\t{:new-gateways/%ju} " "{N:/new gateway%s due to redirects}\n"); p(rts_unreach, "\t{:unreachable-destination/%ju} " "{N:/destination%s found unreachable}\n"); p(rts_wildcard, "\t{:wildcard-uses/%ju} " "{N:/use%s of a wildcard route}\n"); #undef p }