From nobody Wed Aug 2 16:21:16 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4RGHKn63Wmz4qhVF; Wed, 2 Aug 2023 16:21:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4RGHKS2SxYz4DY0; Wed, 2 Aug 2023 16:21:16 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1690993276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qbshhz28rnYPHKCchoSA6GXG3bpvPlpWzbh5V4eKuNI=; b=wlf3eAtdBkFHKyuLXkEv62agvE1hhsto0rBOktej/LyekAmzjFbqG0+mMpinLVT3EOj8Xw CZraaYGsxqorIElgeGhob3vdnTkg2sbq+giXiCsoK5a/IaTzrShq/r4A96IpypOPRgtsje FUbOZBB+VPTgU6o7KIW9ZzgooZFuA8oDiwS7OivSHYixSNXVDy19mHRxzZMxYiz5E62uX2 9qfWeSSS0od9KhXu1KGZfvnTr9YDxBvCGvriore5IG4Jatb7ASgSGTTNpNyEiXOCTH+YfB KBIiOMN19cFVQSzfgd84GceYqoguwx1mCBxbTR13URRl5gzYKvOOo4UYv7BD2g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1690993276; a=rsa-sha256; cv=none; b=Jfl3u8FMIrirucw89fLtoLZ6FRy+4EIsLrLTxnVPSwnwPEK1eUjW8z83A42viy1+oVAz3+ 7Wnd+CBTLjJKQ84DdW1Hn44mFkpipIdUmAntUgQqPF5pW+48X1iJntHcfkFSFc6PqG1lYL H83I8vjeEG39t+CeSN3y6vQ8IrTpXgEqhRMHZoT6jWXaYMJMoM4c21lHiSmwV2d8Dv/2jf /MZafVP2UBkQ3udoFrLNPmt2PQM8dR1ZFqOYKiWQSSiIHvelG38YKHafH5/rHORRa/KXo9 irOHA5Tnx1iaMhaw9CRtiHN3qEC9vvbtv3ja5gVcw6vPlXb3WXCLfTYcS2/r0A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1690993276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qbshhz28rnYPHKCchoSA6GXG3bpvPlpWzbh5V4eKuNI=; b=FAS7aLms6c7TqvNWQnimiRG8cQ3M1pJ2oXgzpJq6PKlSH+ixZwoWWwiZZuC8JzlHdr5MUi lBc/M+khxgv4qP07zJS6aejTo2c2Hl6KTi4JVniQgopmFUvbgPlNqutXJdfyn6Kt6nPFvB o/7alJxW+rdTihynb6YFa7AU1WsnVkGe6X93WBb/TrAKFGvZWsMmuaOJf+RUt8RNbUrnBl UHHpAsyLBOkdwhDWrTh1DWREcm+EqA6YXbVfZf3tluy2NDJ33KvNgkL+FeLnrJbRs2bFyJ +bDqMHgd94f1JTuugHjJuGwZ9YsKWyjY7XHqb9jes/kurEf7NClcUgBT3mFycw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4RGHKS0xmhzQtP; Wed, 2 Aug 2023 16:21:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 372GLGxe034442; Wed, 2 Aug 2023 16:21:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 372GLGpp034441; Wed, 2 Aug 2023 16:21:16 GMT (envelope-from git) Date: Wed, 2 Aug 2023 16:21:16 GMT Message-Id: <202308021621.372GLGpp034441@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mike Karels Subject: git: b9da47180fd6 - stable/13 - netstat -i: compute most field widths dynamically List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: karels X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: b9da47180fd6efd77489339b6559eeeb09c7b96c Auto-Submitted: auto-generated The branch stable/13 has been updated by karels: URL: https://cgit.FreeBSD.org/src/commit/?id=b9da47180fd6efd77489339b6559eeeb09c7b96c commit b9da47180fd6efd77489339b6559eeeb09c7b96c Author: Mike Karels AuthorDate: 2023-07-26 15:56:52 +0000 Commit: Mike Karels CommitDate: 2023-08-02 16:17:31 +0000 netstat -i: compute most field widths dynamically The network and address fields were sometimes truncated for netstat -i without -W, and often much too wide for netstat -i with the -W option. Fields such as normal packet counts often overflowed. As a result, columns didn't line up, and large white spaces made it harder to follow a line across the display. Change the code to compute the required field sizes for network, address, and various packet counts. Hoist the code to format network and address into a subroutine that can be called twice, once to measure the required field widths, and once to emit the values. Use separate field widths for input and output packets, byte counts, and error and drop counters. These are left at defaults (the preceding values) with the -h option, in which case the fields have a limited total width. An extra space is included between the Network and Address, which otherwise seemed too close. Change the mention of -W with -i in the man page to say that most field widths are computed dynamically in this case. Reviewed by: sjg, glebius Differential Revision: https://reviews.freebsd.org/D41160 (cherry picked from commit 372e3d561d82aba7a66fcd4ecb49a4d0a9f69345) --- usr.bin/netstat/if.c | 217 ++++++++++++++++++++++++++++++---------------- usr.bin/netstat/netstat.1 | 3 + 2 files changed, 143 insertions(+), 77 deletions(-) diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c index 5ba4f3afc67b..e08a0462d56d 100644 --- a/usr.bin/netstat/if.c +++ b/usr.bin/netstat/if.c @@ -265,6 +265,99 @@ next_ifma(struct ifmaddrs *ifma, const char *name, const sa_family_t family) return (ifma); } +enum process_op { MEASURE, EMIT }; + +static void +process_ifa_addr(enum process_op op, struct ifaddrs *ifa, int *max_net_len, + int *max_addr_len, bool *network, bool *link) +{ + int net_len, addr_len; + const char *nn, *rn; + + if (op == EMIT) { + net_len = *max_net_len; + addr_len = *max_addr_len; + } + + switch (ifa->ifa_addr->sa_family) { + case AF_UNSPEC: + if (op == MEASURE) { + net_len = strlen("none"); + addr_len = strlen("none"); + } else { + xo_emit("{:network/%-*.*s} ", net_len, net_len, + "none"); + xo_emit("{:address/%-*.*s} ", addr_len, addr_len, + "none"); + } + break; + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif /* INET6 */ + nn = netname(ifa->ifa_addr, ifa->ifa_netmask); + rn = routename(ifa->ifa_addr, numeric_addr); + if (op == MEASURE) { + net_len = strlen(nn); + addr_len = strlen(rn); + } else { + xo_emit("{t:network/%-*s} ", net_len, nn); + xo_emit("{t:address/%-*s} ", addr_len, rn); + } + + if (network != NULL) + *network = true; + break; + case AF_LINK: + { + struct sockaddr_dl *sdl; + char linknum[sizeof("")]; + + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + snprintf(linknum, sizeof(linknum), "", sdl->sdl_index); + if (op == MEASURE) { + net_len = strlen(linknum); + if (sdl->sdl_nlen == 0 && + sdl->sdl_alen == 0 && + sdl->sdl_slen == 0) + addr_len = 1; + else + addr_len = strlen(routename(ifa->ifa_addr, 1)); + } else { + xo_emit("{t:network/%-*.*s} ", net_len, net_len, + linknum); + if (sdl->sdl_nlen == 0 && + sdl->sdl_alen == 0 && + sdl->sdl_slen == 0) + xo_emit("{P:/%*s} ", addr_len, ""); + else + xo_emit("{t:address/%-*.*s} ", addr_len, + addr_len, routename(ifa->ifa_addr, 1)); + } + if (link != NULL) + *link = true; + break; + } + } + + if (op == MEASURE) { + if (net_len > *max_net_len) + *max_net_len = net_len; + if (addr_len > *max_addr_len) + *max_addr_len = addr_len; + } +} + +static int +max_num_len(int max_len, u_long num) +{ + int len = 2; /* include space */ + + for (; num > 10; len++) + num /= 10; + return (MAX(max_len, len)); +} + /* * Print a description of the network interfaces. */ @@ -274,7 +367,8 @@ intpr(void (*pfunc)(char *), int af) struct ifaddrs *ifap, *ifa; struct ifmaddrs *ifmap, *ifma; u_int ifn_len_max = 5, ifn_len; - u_int has_ipv6 = 0, net_len = 13, addr_len = 17; + u_int net_len = strlen("Network "), addr_len = strlen("Address "); + u_int npkt_len = 8, nbyte_len = 10, nerr_len = 5; if (interval) return sidewaysintpr(); @@ -294,39 +388,51 @@ intpr(void (*pfunc)(char *), int af) if ((ifa->ifa_flags & IFF_UP) == 0) ++ifn_len; ifn_len_max = MAX(ifn_len_max, ifn_len); - if (ifa->ifa_addr->sa_family == AF_INET6) - has_ipv6 = 1; - } - if (Wflag) { - if (has_ipv6) { - net_len = 24; - addr_len = 39; - } else - net_len = 18; + process_ifa_addr(MEASURE, ifa, &net_len, &addr_len, + NULL, NULL); + +#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) + if (!hflag) { + npkt_len = max_num_len(npkt_len, IFA_STAT(ipackets)); + npkt_len = max_num_len(npkt_len, IFA_STAT(opackets)); + nerr_len = max_num_len(nerr_len, IFA_STAT(ierrors)); + nerr_len = max_num_len(nerr_len, IFA_STAT(iqdrops)); + nerr_len = max_num_len(nerr_len, IFA_STAT(collisions)); + if (dflag) + nerr_len = max_num_len(nerr_len, + IFA_STAT(oqdrops)); + if (bflag) { + nbyte_len = max_num_len(nbyte_len, + IFA_STAT(ibytes)); + nbyte_len = max_num_len(nbyte_len, + IFA_STAT(obytes)); + } + } } xo_open_list("interface"); if (!pfunc) { xo_emit("{T:/%-*.*s}", ifn_len_max, ifn_len_max, "Name"); - xo_emit(" {T:/%5.5s} {T:/%-*.*s} {T:/%-*.*s} {T:/%8.8s} " - "{T:/%5.5s} {T:/%5.5s}", + xo_emit(" {T:/%5.5s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " + "{T:/%*.*s} {T:/%*.*s}", "Mtu", net_len, net_len, "Network", addr_len, addr_len, - "Address", "Ipkts", "Ierrs", "Idrop"); + "Address", npkt_len, npkt_len, "Ipkts", + nerr_len, nerr_len, "Ierrs", nerr_len, nerr_len, "Idrop"); if (bflag) - xo_emit(" {T:/%10.10s}","Ibytes"); - xo_emit(" {T:/%8.8s} {T:/%5.5s}", "Opkts", "Oerrs"); + xo_emit(" {T:/%*.*s}", nbyte_len, nbyte_len, "Ibytes"); + xo_emit(" {T:/%*.*s} {T:/%*.*s}", npkt_len, npkt_len, "Opkts", + nerr_len, nerr_len, "Oerrs"); if (bflag) - xo_emit(" {T:/%10.10s}","Obytes"); - xo_emit(" {T:/%5s}", "Coll"); + xo_emit(" {T:/%*.*s}", nbyte_len, nbyte_len, "Obytes"); + xo_emit(" {T:/%*s}", nerr_len, "Coll"); if (dflag) - xo_emit(" {T:/%5.5s}", "Drop"); + xo_emit(" {T:/%*.*s}", nerr_len, nerr_len, "Drop"); xo_emit("\n"); } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { bool network = false, link = false; char *name, *xname, buf[IFNAMSIZ+1]; - const char *nn, *rn; if (interface != NULL && strcmp(ifa->ifa_name, interface) != 0) continue; @@ -367,72 +473,29 @@ intpr(void (*pfunc)(char *), int af) show_stat("lu", 6, "mtu", IFA_MTU(ifa), IFA_MTU(ifa), 0); #undef IFA_MTU - switch (ifa->ifa_addr->sa_family) { - case AF_UNSPEC: - xo_emit("{:network/%-*.*s} ", net_len, net_len, - "none"); - xo_emit("{:address/%-*.*s} ", addr_len, addr_len, - "none"); - break; - case AF_INET: -#ifdef INET6 - case AF_INET6: -#endif /* INET6 */ - nn = netname(ifa->ifa_addr, ifa->ifa_netmask); - rn = routename(ifa->ifa_addr, numeric_addr); - if (Wflag) { - xo_emit("{t:network/%-*s} ", net_len, nn); - xo_emit("{t:address/%-*s} ", addr_len, rn); - } else { - xo_emit("{d:network/%-*.*s}{et:network} ", - net_len, net_len, nn, nn); - xo_emit("{d:address/%-*.*s}{et:address} ", - addr_len, addr_len, rn, rn); - } - - network = true; - break; - case AF_LINK: - { - struct sockaddr_dl *sdl; - char linknum[sizeof("")]; - - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - snprintf(linknum, sizeof(linknum), "", sdl->sdl_index); - xo_emit("{t:network/%-*.*s} ", net_len, net_len, - linknum); - if (sdl->sdl_nlen == 0 && - sdl->sdl_alen == 0 && - sdl->sdl_slen == 0) - xo_emit("{P:/%*s} ", addr_len, ""); - else - xo_emit("{t:address/%-*.*s} ", addr_len, - addr_len, routename(ifa->ifa_addr, 1)); - link = true; - break; - } - } + process_ifa_addr(EMIT, ifa, &net_len, &addr_len, + &network, &link); -#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) - show_stat("lu", 8, "received-packets", IFA_STAT(ipackets), - link|network, 1); - show_stat("lu", 5, "received-errors", IFA_STAT(ierrors), + show_stat("lu", npkt_len, "received-packets", + IFA_STAT(ipackets), link|network, 1); + show_stat("lu", nerr_len, "received-errors", IFA_STAT(ierrors), link, 1); - show_stat("lu", 5, "dropped-packets", IFA_STAT(iqdrops), + show_stat("lu", nerr_len, "dropped-packets", IFA_STAT(iqdrops), link, 1); if (bflag) - show_stat("lu", 10, "received-bytes", IFA_STAT(ibytes), - link|network, 0); - show_stat("lu", 8, "sent-packets", IFA_STAT(opackets), + show_stat("lu", nbyte_len, "received-bytes", + IFA_STAT(ibytes), link|network, 0); + show_stat("lu", npkt_len, "sent-packets", IFA_STAT(opackets), link|network, 1); - show_stat("lu", 5, "send-errors", IFA_STAT(oerrors), link, 1); + show_stat("lu", nerr_len, "send-errors", IFA_STAT(oerrors), + link, 1); if (bflag) - show_stat("lu", 10, "sent-bytes", IFA_STAT(obytes), - link|network, 0); - show_stat("NRSlu", 5, "collisions", IFA_STAT(collisions), + show_stat("lu", nbyte_len, "sent-bytes", + IFA_STAT(obytes), link|network, 0); + show_stat("NRSlu", nerr_len, "collisions", IFA_STAT(collisions), link, 1); if (dflag) - show_stat("LSlu", 5, "dropped-packets", + show_stat("LSlu", nerr_len, "dropped-packets", IFA_STAT(oqdrops), link, 1); xo_emit("\n"); diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1 index d2c6d2509f88..d342ec375658 100644 --- a/usr.bin/netstat/netstat.1 +++ b/usr.bin/netstat/netstat.1 @@ -317,6 +317,9 @@ See Avoid truncating addresses even if this causes some fields to overflow. See .Sx GENERAL OPTIONS . +However, in most cases field widths are determined automatically with the +.Fl i +option, and this option has little effect. .It Fl f Ar protocol_family Filter by .Ar protocol_family .