From owner-svn-src-stable@freebsd.org Mon Oct 28 21:51:46 2019 Return-Path: Delivered-To: svn-src-stable@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 7095A15DE83; Mon, 28 Oct 2019 21:51:46 +0000 (UTC) (envelope-from jlh@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) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4727hy2Nzfz4Xmb; Mon, 28 Oct 2019 21:51:46 +0000 (UTC) (envelope-from jlh@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 36BA8FEC5; Mon, 28 Oct 2019 21:51:46 +0000 (UTC) (envelope-from jlh@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x9SLpkLw017175; Mon, 28 Oct 2019 21:51:46 GMT (envelope-from jlh@FreeBSD.org) Received: (from jlh@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x9SLpjs4017173; Mon, 28 Oct 2019 21:51:45 GMT (envelope-from jlh@FreeBSD.org) Message-Id: <201910282151.x9SLpjs4017173@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jlh set sender to jlh@FreeBSD.org using -f From: Jeremie Le Hen Date: Mon, 28 Oct 2019 21:51:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r354141 - stable/12/usr.bin/fstat X-SVN-Group: stable-12 X-SVN-Commit-Author: jlh X-SVN-Commit-Paths: stable/12/usr.bin/fstat X-SVN-Commit-Revision: 354141 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Oct 2019 21:51:46 -0000 Author: jlh Date: Mon Oct 28 21:51:45 2019 New Revision: 354141 URL: https://svnweb.freebsd.org/changeset/base/354141 Log: MFC r353769, r354140: Add the fstat -s option to display socket information. Grammar fix. Modified: stable/12/usr.bin/fstat/fstat.1 stable/12/usr.bin/fstat/fstat.c Directory Properties: stable/12/ (props changed) Modified: stable/12/usr.bin/fstat/fstat.1 ============================================================================== --- stable/12/usr.bin/fstat/fstat.1 Mon Oct 28 21:48:20 2019 (r354140) +++ stable/12/usr.bin/fstat/fstat.1 Mon Oct 28 21:51:45 2019 (r354141) @@ -28,7 +28,7 @@ .\" @(#)fstat.1 8.3 (Berkeley) 2/25/94 .\" $FreeBSD$ .\" -.Dd September 28, 2011 +.Dd October 19, 2019 .Dt FSTAT 1 .Os .Sh NAME @@ -36,7 +36,7 @@ .Nd identify active files .Sh SYNOPSIS .Nm -.Op Fl fmnv +.Op Fl fmnsv .Op Fl M Ar core .Op Fl N Ar system .Op Fl p Ar pid @@ -85,6 +85,8 @@ in and print the mode of the file in octal instead of symbolic form. .It Fl p Report all files open by the specified process. +.It Fl s +Print socket endpoint information. .It Fl u Report all files open by the specified user. .It Fl v @@ -199,9 +201,6 @@ For tcp, it is the address of the tcpcb, and for udp, For unix domain sockets, its the address of the socket pcb and the address of the connected pcb (if connected). Otherwise the protocol number and address of the socket itself are printed. -The attempt is to make enough information available to -permit further analysis without duplicating -.Xr netstat 1 . .Pp For example, the addresses mentioned above are the addresses which the .Dq Li netstat -A @@ -211,6 +210,15 @@ connected unix domain stream socket. A unidirectional unix domain socket indicates the direction of flow with an arrow (``<-'' or ``->''), and a full duplex socket shows a double arrow (``<->''). +.Pp +When the +.Fl s +flag is used, socket endpoint information is shown after the address of the +socket. +For internet sockets the local and remote addresses are shown, separated with +a double arrow (``<->''). +For unix/local sockets either the local or remote address is shown, depending +on which one is available. .Sh SEE ALSO .Xr netstat 1 , .Xr nfsstat 1 , Modified: stable/12/usr.bin/fstat/fstat.c ============================================================================== --- stable/12/usr.bin/fstat/fstat.c Mon Oct 28 21:48:20 2019 (r354140) +++ stable/12/usr.bin/fstat/fstat.c Mon Oct 28 21:51:45 2019 (r354141) @@ -40,9 +40,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include + #include #include #include @@ -61,6 +64,7 @@ __FBSDID("$FreeBSD$"); static int fsflg, /* show files on same filesystem as file(s) argument */ pflg, /* show files open by a particular pid */ + sflg, /* show socket details */ uflg; /* show files open by a particular (effective) user */ static int checkfile; /* restrict to particular files or filesystems */ static int nflg; /* (numerical) display f.s. and rdev as dev_t */ @@ -108,7 +112,7 @@ do_fstat(int argc, char **argv) arg = 0; what = KERN_PROC_PROC; nlistf = memf = NULL; - while ((ch = getopt(argc, argv, "fmnp:u:vN:M:")) != -1) + while ((ch = getopt(argc, argv, "fmnp:su:vN:M:")) != -1) switch((char)ch) { case 'f': fsflg = 1; @@ -135,6 +139,9 @@ do_fstat(int argc, char **argv) what = KERN_PROC_PID; arg = atoi(optarg); break; + case 's': + sflg = 1; + break; case 'u': if (uflg++) usage(); @@ -314,6 +321,55 @@ print_file_info(struct procstat *procstat, struct file putchar('\n'); } +static char * +addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen) +{ + char buffer2[INET6_ADDRSTRLEN]; + struct sockaddr_in6 *sin6; + struct sockaddr_in *sin; + struct sockaddr_un *sun; + + switch (ss->ss_family) { + case AF_LOCAL: + sun = (struct sockaddr_un *)ss; + if (strlen(sun->sun_path) == 0) + strlcpy(buffer, "-", buflen); + else + strlcpy(buffer, sun->sun_path, buflen); + break; + + case AF_INET: + sin = (struct sockaddr_in *)ss; + if (sin->sin_addr.s_addr == INADDR_ANY) + snprintf(buffer, buflen, "%s:%d", "*", + ntohs(sin->sin_port)); + else if (inet_ntop(AF_INET, &sin->sin_addr, buffer2, + sizeof(buffer2)) != NULL) + snprintf(buffer, buflen, "%s:%d", buffer2, + ntohs(sin->sin_port)); + break; + + case AF_INET6: + sin6 = (struct sockaddr_in6 *)ss; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) + snprintf(buffer, buflen, "%s.%d", "*", + ntohs(sin6->sin6_port)); + else if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2, + sizeof(buffer2)) != NULL) + snprintf(buffer, buflen, "%s.%d", buffer2, + ntohs(sin6->sin6_port)); + else + strlcpy(buffer, "-", buflen); + break; + + default: + strlcpy(buffer, "", buflen); + break; + } + return buffer; +} + + static void print_socket_info(struct procstat *procstat, struct filestat *fst) { @@ -329,6 +385,8 @@ print_socket_info(struct procstat *procstat, struct fi struct sockstat sock; struct protoent *pe; char errbuf[_POSIX2_LINE_MAX]; + char src_addr[PATH_MAX], dst_addr[PATH_MAX]; + struct sockaddr_un *sun; int error; static int isopen; @@ -368,6 +426,11 @@ print_socket_info(struct procstat *procstat, struct fi } else if (sock.so_pcb != 0) printf(" %lx", (u_long)sock.so_pcb); + if (!sflg) + break; + printf(" %s <-> %s", + addr_to_string(&sock.sa_local, src_addr, sizeof(src_addr)), + addr_to_string(&sock.sa_peer, dst_addr, sizeof(dst_addr))); break; case AF_UNIX: /* print address of pcb and connected pcb */ @@ -385,8 +448,25 @@ print_socket_info(struct procstat *procstat, struct fi *cp = '\0'; printf(" %s %lx", shoconn, (u_long)sock.unp_conn); - } + } } + if (!sflg) + break; + sun = (struct sockaddr_un *)&sock.sa_local; + /* + * While generally we like to print two addresses, + * local and peer, for sockets, it turns out to be + * more useful to print the first non-null address for + * local sockets, as typically they aren't bound and + * connected, and the path strings can get long. + */ + if (sun->sun_path[0] != 0) + addr_to_string(&sock.sa_local, + src_addr, sizeof(src_addr)); + else + addr_to_string(&sock.sa_peer, + src_addr, sizeof(src_addr)); + printf(" %s", src_addr); break; default: /* print protocol number and socket address */