ss: remove implicit dependency on rpcinfo
Subsystems (2)
cover ss: remove implicit dependency on rpcinfo
ss uses rpcinfo to get info about rpc service sockets. However, rpcinfo is not part of iproute2 and it's an implicit dependency for ss.
This series uses libtirpc[1] API to implement the same feature of rpcinfo for ss. This makes it possible to get info about rpc sockets, provided ss is compiled with libtirpc support.
As a nice byproduct, this makes ss provide info about some ipv6 rpc sockets that are not displayed using 'rpcinfo -p'.
- patch 1 adds a configure function to check for libtirpc;
- patch 2 actually rework ss to use libtirpc.
[1] https://git.linux-nfs.org/?p=steved/libtirpc.git
Andrea Claudi (2):
configure: add check_libtirpc()
ss: remove an implicit dependency on rpcinfo
configure | 16 ++++++++++ misc/ss.c | 93 +++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 89 insertions(+), 20 deletions(-)
Signature · 1 line
2.35.1
PATCH 1/2 configure: add check_libtirpc()
This patch adds a configure function to check if libtirpc is installed on the build system. If this is the case, it makes iproute2 to compile with libtirpc support.
--- configure | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
configure +16 -0
@@ -395,6 +395,19 @@ check_selinux() fi } +check_tirpc() +{ + if ${PKG_CONFIG} libtirpc --exists; then + echo "HAVE_RPC:=y" >>$CONFIG + echo "yes" + + echo 'LDLIBS +=' `${PKG_CONFIG} --libs libtirpc` >>$CONFIG + echo 'CFLAGS += -DHAVE_RPC' `${PKG_CONFIG} --cflags libtirpc` >>$CONFIG + else + echo "no" + fi +} + check_mnl() { if ${PKG_CONFIG} libmnl --exists; then
@@ -600,6 +613,9 @@ check_name_to_handle_at echo -n "SELinux support: " check_selinux +echo -n "libtirpc support: " +check_tirpc + echo -n "libbpf support: " check_libbpf
Signature · 1 line
2.35.1
PATCH 2/2 ss: remove an implicit dependency on rpcinfo
In reply to Andrea Claudiss uses rpcinfo to get info about rpc services socket. This makes it dependent on a tool not included in iproute2, and makes it impossible to get info on rpc sockets if rpcinfo is not installed.
This reworks init_service_resolver() to use libtirpc, thus avoiding the implicity dependency on rpcinfo. Moreover, this also makes it possible to display info about ipv6 rpc socket that are not included in the rpcinfo -p output.
For example, before this patch:
$ ss -rtap
LISTEN 0 5 localhost:ipp [::]:* users:(("cupsd",pid=1600,fd=9))
LISTEN 0 64 [::]:34265 [::]:*
LISTEN 0 64 [::]:rpc.nfs_acl [::]:*
LISTEN 0 128 [::]:42253 [::]:* users:(("rpc.statd",pid=146164,fd=12))After this patch:
$ ss -rtap
LISTEN 0 5 localhost:ipp [::]:* users:(("cupsd",pid=1600,fd=9))
LISTEN 0 64 [::]:rpc.nlockmgr [::]:*
LISTEN 0 64 [::]:rpc.nfs_acl [::]:*
LISTEN 0 128 [::]:rpc.status [::]:* users:(("rpc.statd",pid=146164,fd=12))--- misc/ss.c | 93 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 20 deletions(-)
misc/ss.c +73 -20
@@ -55,6 +55,11 @@#include <linux/tls.h> #include <linux/mptcp.h> +#if HAVE_RPC +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#endif +/* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */ #ifndef PF_VSOCK #define PF_VSOCK 40
@@ -192,8 +197,12 @@ static struct { } buffer;static const char *TCP_PROTO ="tcp" ; -static const char *SCTP_PROTO ="sctp" ;static const char *UDP_PROTO ="udp" ; +#ifdef HAVE_RPC +static const char *TCP6_PROTO ="tcp6" ; +static const char *UDP6_PROTO ="udp6" ; +static const char *SCTP_PROTO ="sctp" ; +#endif static const char *RAW_PROTO ="raw" ;static const char *dg_proto;
@@ -1479,45 +1488,87 @@ struct scache {static struct scache *rlist; +#ifdef HAVE_RPC +static CLIENT *rpc_client_create (rpcprog_t prog,rpcvers_t vers) +{ +struct netbuf nbuf; +struct sockaddr_un saddr; +int sock; + +memset (&saddr,0 ,sizeof (saddr)); + sock =socket (AF_LOCAL ,SOCK_STREAM ,0 ); +if (sock <0 ) +return NULL ; + + saddr.sun_family =AF_LOCAL ; +strcpy (saddr.sun_path, _PATH_RPCBINDSOCK); + nbuf.len =SUN_LEN (&saddr); + nbuf.maxlen =sizeof (struct sockaddr_un ); + nbuf.buf = &saddr; + +return clnt_vc_create (sock, &nbuf, prog, vers,0 ,0 ); +} +static void init_service_resolver (void ) { -char buf[128 ]; -FILE *fp =popen ("/usr/sbin/rpcinfo -p 2>/dev/null" ,"r" ); +struct rpcblist *rhead =NULL ; +struct timeval timeout; +struct rpcent *rpc; +enum clnt_stat res; +CLIENT *client; -if (!fp) + timeout.tv_sec =5 ; + timeout.tv_usec =0 ; + + client =rpc_client_create (PMAPPROG ,RPCBVERS4 ); +if (!client)return ; -if (!fgets (buf,sizeof (buf), fp)) { -pclose (fp); + res =clnt_call (client,RPCBPROC_DUMP , (xdrproc_t )xdr_void,NULL , + (xdrproc_t )xdr_rpcblist_ptr, (char *)&rhead, + timeout); +if (res !=RPC_SUCCESS )return ; - } -while (fgets (buf,sizeof (buf), fp) !=NULL ) { -unsigned int progn, port; -char proto[128 ], prog[128 ] ="rpc." ; + +for (; rhead; rhead = rhead->rpcb_next) { +char prog[128 ] ="rpc." ;struct scache *c; +int hport, lport, ok; -if (sscanf (buf,"%u %*d %s %u %s" , - &progn, proto, &port, prog+4 ) !=4 ) + c =malloc (sizeof (*c)); +if (!c)continue ; -if (!(c =malloc (sizeof (*c)))) + ok =sscanf (rhead->rpcb_map.r_addr,"::.%d.%d" , &hport, &lport); +if (!ok) + ok =sscanf (rhead->rpcb_map.r_addr,"0.0.0.0.%d.%d" , + &hport, &lport); +if (!ok)continue ; + c->port = hport <<8 | lport; - c->port = port; - c->name =strdup (prog); -if (strcmp (proto,TCP_PROTO ) ==0 ) +if (strcmp (rhead->rpcb_map.r_netid,TCP_PROTO ) ==0 || +strcmp (rhead->rpcb_map.r_netid,TCP6_PROTO ) ==0 ) c->proto =TCP_PROTO ; -else if (strcmp (proto,UDP_PROTO ) ==0 ) +else if (strcmp (rhead->rpcb_map.r_netid,UDP_PROTO ) ==0 || +strcmp (rhead->rpcb_map.r_netid,UDP6_PROTO ) ==0 ) c->proto =UDP_PROTO ; -else if (strcmp (proto,SCTP_PROTO ) ==0 ) +else if (strcmp (rhead->rpcb_map.r_netid,SCTP_PROTO ) ==0 ) c->proto =SCTP_PROTO ;else - c->proto =NULL ; +continue ; + + rpc =getrpcbynumber (rhead->rpcb_map.r_prog); +if (rpc) { +strncat (prog, rpc->r_name,128 -strlen (prog)); + c->name =strdup (prog); + } + c->next = rlist; rlist = c; } -pclose (fp); } +#endif /* Even do not try default linux ephemeral port ranges: * default /etc/services contains so much of useless crap
@@ -5668,9 +5719,11 @@ int main(int argc, char *argv[])filter_states_set (¤t_filter, state_filter);filter_merge_defaults (¤t_filter); +#ifdef HAVE_RPC if (!numeric && resolve_hosts && (current_filter.dbs & (UNIX_DBM |INET_L4_DBM )))init_service_resolver (); +#endif if (current_filter.dbs ==0 ) {fprintf (stderr,"ss: no socket tables to show with such filter.\n" );
Signature · 1 line
2.35.1
This series was applied to iproute2/iproute2-next.git (main) by David Ahern <[email protected]>:
Hello:
This series was applied to iproute2/iproute2-next.git (main) by David Ahern <[email protected]>:
Quoted 8 lines · On Wed, 16 Mar 2022 19:52:12 +0100 you wrote:
ss uses rpcinfo to get info about rpc service sockets. However, rpcinfo is not part of iproute2 and it's an implicit dependency for ss.
This series uses libtirpc[1] API to implement the same feature of rpcinfo for ss. This makes it possible to get info about rpc sockets, provided ss is compiled with libtirpc support.
[...]
Here is the summary with links:
- [iproute2-next,1/2] configure: add check_libtirpc()
https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=1ee309a49aa0 - [iproute2-next,2/2] ss: remove an implicit dependency on rpcinfo https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=292509f95dd4
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html