From: Stephen Hemminger <stephen@networkplumber.org>
To: netdev@vger.kernel.org
Cc: dsahern@kernel.org, Stephen Hemminger <stephen@networkplumber.org>
Subject: [PATCH iproute2 02/11] ss: drop /proc fallback for socket listing
Date: Thu, 12 Nov 2026 11:59:15 -0800 [thread overview]
Message-ID: <20261112200046.2164391-3-stephen@networkplumber.org> (raw)
In-Reply-To: <20261112200046.2164391-1-stephen@networkplumber.org>
All socket families ss lists from /proc (tcp, udp, raw, unix, packet,
netlink) have had sock_diag support since well before the oldest
supported LTS kernel. The /proc parsers are rarely used, untested,
and trust file contents that unprivileged users can partly control;
a unix socket name containing a newline can forge a /proc/net/unix
line with an out of range state and crash ss.
Remove the fallback and print an error if the kernel can not dump a
socket family. The TCPDIAG_GETSOCK retry goes with it; that request
is only needed for kernels older than 3.3. /proc is still used for
-s and process info.
Reported-by: Anthropic OSS scanner (ANT-2026-TNFMK5ZB)
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
misc/ss.c | 626 +++---------------------------------------------------
1 file changed, 28 insertions(+), 598 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index 674ed8e8..b93df60f 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -473,17 +473,6 @@ static void filter_merge_defaults(struct filter *f)
}
}
-#define net_tcp_open() generic_proc_open("PROC_NET_TCP", "net/tcp")
-#define net_tcp6_open() generic_proc_open("PROC_NET_TCP6", "net/tcp6")
-#define net_udp_open() generic_proc_open("PROC_NET_UDP", "net/udp")
-#define net_udp6_open() generic_proc_open("PROC_NET_UDP6", "net/udp6")
-#define net_raw_open() generic_proc_open("PROC_NET_RAW", "net/raw")
-#define net_raw6_open() generic_proc_open("PROC_NET_RAW6", "net/raw6")
-#define net_unix_open() generic_proc_open("PROC_NET_UNIX", "net/unix")
-#define net_packet_open() generic_proc_open("PROC_NET_PACKET", \
- "net/packet")
-#define net_netlink_open() generic_proc_open("PROC_NET_NETLINK", \
- "net/netlink")
#define net_sockstat_open() generic_proc_open("PROC_NET_SOCKSTAT", \
"net/sockstat")
#define net_sockstat6_open() generic_proc_open("PROC_NET_SOCKSTAT6", \
@@ -2477,55 +2466,6 @@ static void inet_stats_print(struct sockstat *s, bool v6only)
proc_ctx_print(s);
}
-static int proc_parse_inet_addr(char *loc, char *rem, int family, struct
- sockstat * s)
-{
- s->local.family = s->remote.family = family;
- if (family == AF_INET) {
- sscanf(loc, "%x:%lx", s->local.data, (unsigned long *)&s->lport);
- sscanf(rem, "%x:%lx", s->remote.data, (unsigned long *)&s->rport);
- s->local.bytelen = s->remote.bytelen = 4;
- return 0;
- } else {
- sscanf(loc, "%08x%08x%08x%08x:%lx",
- s->local.data,
- s->local.data + 1,
- s->local.data + 2,
- s->local.data + 3,
- (unsigned long *)&s->lport);
- sscanf(rem, "%08x%08x%08x%08x:%lx",
- s->remote.data,
- s->remote.data + 1,
- s->remote.data + 2,
- s->remote.data + 3,
- (unsigned long *)&s->rport);
- s->local.bytelen = s->remote.bytelen = 16;
- return 0;
- }
- return -1;
-}
-
-static int proc_inet_split_line(char *line, char **loc, char **rem, char **data)
-{
- char *p;
-
- if ((p = strchr(line, ':')) == NULL)
- return -1;
-
- *loc = p+2;
- if ((p = strchr(*loc, ':')) == NULL)
- return -1;
-
- p[5] = 0;
- *rem = p+6;
- if ((p = strchr(*rem, ':')) == NULL)
- return -1;
-
- p[5] = 0;
- *data = p+6;
- return 0;
-}
-
/*
* Display bandwidth in standard units
* See: https://en.wikipedia.org/wiki/Data-rate_units
@@ -2794,98 +2734,6 @@ static void sctp_timer_print(struct tcpstat *s)
print_ms_timer(s->timeout), s->retrans);
}
-static int tcp_show_line(char *line, const struct filter *f, int family)
-{
- int rto = 0, ato = 0;
- struct tcpstat s = {};
- char *loc, *rem, *data;
- char opt[256];
- int n;
- int hz = get_user_hz();
-
- if (proc_inet_split_line(line, &loc, &rem, &data))
- return -1;
-
- int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
-
- if (!(f->states & (1 << state)))
- return 0;
-
- proc_parse_inet_addr(loc, rem, family, &s.ss);
-
- if (f->f && run_ssfilter(f->f, &s.ss) == 0)
- return 0;
-
- opt[0] = 0;
- n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %u %d %[^\n]\n",
- &s.ss.state, &s.ss.wq, &s.ss.rq,
- &s.timer, &s.timeout, &s.retrans, &s.ss.uid, &s.probes,
- &s.ss.ino, &s.ss.refcnt, &s.ss.sk, &rto, &ato, &s.qack, &s.cwnd,
- &s.ssthresh, opt);
-
- if (n < 17)
- opt[0] = 0;
-
- if (n < 12) {
- rto = 0;
- s.cwnd = 2;
- s.ssthresh = -1;
- ato = s.qack = 0;
- }
-
- s.retrans = s.timer != 1 ? s.probes : s.retrans;
- s.timeout = (s.timeout * 1000 + hz - 1) / hz;
- s.ato = (double)ato / hz;
- s.qack /= 2;
- s.rto = (double)rto;
- s.ssthresh = s.ssthresh == -1 ? 0 : s.ssthresh;
- s.rto = s.rto != 3 * hz ? s.rto / hz : 0;
- s.ss.type = IPPROTO_TCP;
-
- inet_stats_print(&s.ss, false);
-
- if (show_options)
- tcp_timer_print(&s);
-
- if (show_details) {
- sock_details_print(&s.ss);
- if (opt[0])
- out(" opt:\"%s\"", opt);
- }
-
- if (show_tcpinfo)
- tcp_stats_print(&s);
-
- return 0;
-}
-
-static int generic_record_read(FILE *fp,
- int (*worker)(char*, const struct filter *, int),
- const struct filter *f, int fam)
-{
- char line[256];
-
- /* skip header */
- if (fgets(line, sizeof(line), fp) == NULL)
- goto outerr;
-
- while (fgets(line, sizeof(line), fp) != NULL) {
- int n = strlen(line);
-
- if (n == 0 || line[n-1] != '\n') {
- errno = -EINVAL;
- return -1;
- }
- line[n-1] = 0;
-
- if (worker(line, f, fam) < 0)
- return 0;
- }
-outerr:
-
- return ferror(fp) ? -1 : 0;
-}
-
static void print_skmeminfo(struct rtattr *tb[], int attrtype)
{
const __u32 *skmeminfo;
@@ -3867,76 +3715,6 @@ static int inet_show_sock(struct nlmsghdr *nlh,
return 0;
}
-static int tcpdiag_send(int fd, int protocol, struct filter *f)
-{
- struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
- struct {
- struct nlmsghdr nlh;
- struct inet_diag_req r;
- } req = {
- .nlh.nlmsg_len = sizeof(req),
- .nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
- .nlh.nlmsg_seq = MAGIC_SEQ,
- .r.idiag_family = AF_INET,
- .r.idiag_states = f->states,
- };
- char *bc = NULL;
- int bclen;
- struct msghdr msg;
- struct rtattr rta;
- struct iovec iov[3];
- int iovlen = 1;
-
- if (protocol == IPPROTO_TCP)
- req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
- else
- return -1;
-
- if (show_mem) {
- req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
- req.r.idiag_ext |= (1<<(INET_DIAG_SKMEMINFO-1));
- }
-
- if (show_tcpinfo) {
- req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
- req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1));
- req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
- }
-
- if (show_tos) {
- req.r.idiag_ext |= (1<<(INET_DIAG_TOS-1));
- req.r.idiag_ext |= (1<<(INET_DIAG_TCLASS-1));
- }
-
- iov[0] = (struct iovec){
- .iov_base = &req,
- .iov_len = sizeof(req)
- };
- if (f->f) {
- bclen = ssfilter_bytecompile(f->f, &bc);
- if (bclen) {
- rta.rta_type = INET_DIAG_REQ_BYTECODE;
- rta.rta_len = RTA_LENGTH(bclen);
- iov[1] = (struct iovec){ &rta, sizeof(rta) };
- iov[2] = (struct iovec){ bc, bclen };
- req.nlh.nlmsg_len += RTA_LENGTH(bclen);
- iovlen = 3;
- }
- }
-
- msg = (struct msghdr) {
- .msg_name = (void *)&nladdr,
- .msg_namelen = sizeof(nladdr),
- .msg_iov = iov,
- .msg_iovlen = iovlen,
- };
-
- if (sendmsg(fd, &msg, 0) < 0)
- return -1;
-
- return 0;
-}
-
static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
{
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
@@ -3951,9 +3729,6 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
struct iovec iov[6];
int iovlen = 1;
- if (family == PF_UNSPEC)
- return tcpdiag_send(fd, protocol, f);
-
memset(&req.r, 0, sizeof(req.r));
req.r.sdiag_family = family;
req.r.sdiag_protocol = protocol;
@@ -4131,13 +3906,8 @@ again:
if ((err = sockdiag_send(family, rth.fd, protocol, f)))
goto Exit;
- if ((err = rtnl_dump_filter(&rth, show_one_inet_sock, &arg))) {
- if (family != PF_UNSPEC) {
- family = PF_UNSPEC;
- goto again;
- }
+ if ((err = rtnl_dump_filter(&rth, show_one_inet_sock, &arg)))
goto Exit;
- }
if (family == PF_INET && preferred_family != PF_INET) {
family = PF_INET6;
goto again;
@@ -4222,12 +3992,20 @@ static int tcp_show_netlink_file(struct filter *f)
return err;
}
-static int tcp_show(struct filter *f)
+static int sock_diag_error(const char *what)
{
- FILE *fp = NULL;
- char *buf = NULL;
- int bufsize = 1024*1024;
+ if (errno == ENOENT || errno == EOPNOTSUPP)
+ fprintf(stderr,
+ "Cannot dump %s sockets: kernel lacks sock_diag support\n",
+ what);
+ else
+ fprintf(stderr, "Cannot dump %s sockets: %s\n",
+ what, strerror(errno));
+ return -1;
+}
+static int tcp_show(struct filter *f)
+{
if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
return 0;
@@ -4236,52 +4014,9 @@ static int tcp_show(struct filter *f)
if (getenv("TCPDIAG_FILE"))
return tcp_show_netlink_file(f);
- if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT")
- && inet_show_netlink(f, NULL, IPPROTO_TCP) == 0)
- return 0;
-
- /* Sigh... We have to parse /proc/net/tcp... */
- while (bufsize >= 64*1024) {
- if ((buf = malloc(bufsize)) != NULL)
- break;
- bufsize /= 2;
- }
- if (buf == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- if (f->families & FAMILY_MASK(AF_INET)) {
- if ((fp = net_tcp_open()) == NULL)
- goto outerr;
-
- setbuffer(fp, buf, bufsize);
- if (generic_record_read(fp, tcp_show_line, f, AF_INET))
- goto outerr;
- fclose(fp);
- }
-
- if ((f->families & FAMILY_MASK(AF_INET6)) &&
- (fp = net_tcp6_open()) != NULL) {
- setbuffer(fp, buf, bufsize);
- if (generic_record_read(fp, tcp_show_line, f, AF_INET6))
- goto outerr;
- fclose(fp);
- }
-
- free(buf);
+ if (inet_show_netlink(f, NULL, IPPROTO_TCP))
+ return sock_diag_error("TCP");
return 0;
-
-outerr:
- do {
- int saved_errno = errno;
-
- free(buf);
- if (fp)
- fclose(fp);
- errno = saved_errno;
- return -1;
- } while (0);
}
static int mptcp_show(struct filter *f)
@@ -4289,10 +4024,7 @@ static int mptcp_show(struct filter *f)
if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
return 0;
- if (!getenv("PROC_NET_MPTCP") && !getenv("PROC_ROOT")
- && inet_show_netlink(f, NULL, IPPROTO_MPTCP) == 0)
- return 0;
-
+ inet_show_netlink(f, NULL, IPPROTO_MPTCP);
return 0;
}
@@ -4301,140 +4033,32 @@ static int sctp_show(struct filter *f)
if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
return 0;
- if (!getenv("PROC_NET_SCTP") && !getenv("PROC_ROOT")
- && inet_show_netlink(f, NULL, IPPROTO_SCTP) == 0)
- return 0;
-
- return 0;
-}
-
-static int dgram_show_line(char *line, const struct filter *f, int family)
-{
- struct sockstat s = {};
- char *loc, *rem, *data;
- char opt[256];
- int n;
-
- if (proc_inet_split_line(line, &loc, &rem, &data))
- return -1;
-
- int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
-
- if (!(f->states & (1 << state)))
- return 0;
-
- proc_parse_inet_addr(loc, rem, family, &s);
-
- if (f->f && run_ssfilter(f->f, &s) == 0)
- return 0;
-
- opt[0] = 0;
- n = sscanf(data, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n",
- &s.state, &s.wq, &s.rq,
- &s.uid, &s.ino,
- &s.refcnt, &s.sk, opt);
-
- if (n < 9)
- opt[0] = 0;
-
- s.type = dg_proto == UDP_PROTO ? IPPROTO_UDP : 0;
- inet_stats_print(&s, false);
-
- if (show_details && opt[0])
- out(" opt:\"%s\"", opt);
-
+ inet_show_netlink(f, NULL, IPPROTO_SCTP);
return 0;
}
static int udp_show(struct filter *f)
{
- FILE *fp = NULL;
-
if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
return 0;
dg_proto = UDP_PROTO;
- if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT")
- && inet_show_netlink(f, NULL, IPPROTO_UDP) == 0)
- return 0;
-
- if (f->families&FAMILY_MASK(AF_INET)) {
- if ((fp = net_udp_open()) == NULL)
- goto outerr;
- if (generic_record_read(fp, dgram_show_line, f, AF_INET))
- goto outerr;
- fclose(fp);
- }
-
- if ((f->families&FAMILY_MASK(AF_INET6)) &&
- (fp = net_udp6_open()) != NULL) {
- if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
- goto outerr;
- fclose(fp);
- }
+ if (inet_show_netlink(f, NULL, IPPROTO_UDP))
+ return sock_diag_error("UDP");
return 0;
-
-outerr:
- do {
- int saved_errno = errno;
-
- if (fp)
- fclose(fp);
- errno = saved_errno;
- return -1;
- } while (0);
}
static int raw_show(struct filter *f)
{
- FILE *fp = NULL;
-
if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6))
return 0;
dg_proto = RAW_PROTO;
- if (!getenv("PROC_NET_RAW") && !getenv("PROC_ROOT") &&
- inet_show_netlink(f, NULL, IPPROTO_RAW) == 0)
- return 0;
-
- if (f->families&FAMILY_MASK(AF_INET)) {
- if ((fp = net_raw_open()) == NULL)
- goto outerr;
- if (generic_record_read(fp, dgram_show_line, f, AF_INET))
- goto outerr;
- fclose(fp);
- }
-
- if ((f->families&FAMILY_MASK(AF_INET6)) &&
- (fp = net_raw6_open()) != NULL) {
- if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
- goto outerr;
- fclose(fp);
- }
+ if (inet_show_netlink(f, NULL, IPPROTO_RAW))
+ return sock_diag_error("RAW");
return 0;
-
-outerr:
- do {
- int saved_errno = errno;
-
- if (fp)
- fclose(fp);
- errno = saved_errno;
- return -1;
- } while (0);
-}
-
-#define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct sockstat))
-
-static void unix_list_drop_first(struct sockstat **list)
-{
- struct sockstat *s = *list;
-
- (*list) = (*list)->next;
- free(s->name);
- free(s);
}
static bool unix_type_skip(struct sockstat *s, struct filter *f)
@@ -4579,134 +4203,11 @@ static int unix_show_netlink(struct filter *f)
static int unix_show(struct filter *f)
{
- FILE *fp;
- char buf[256];
- char name[128];
- int newformat = 0;
- int cnt;
- struct sockstat *list = NULL;
- const int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT,
- SS_ESTABLISHED, SS_CLOSING };
-
if (!filter_af_get(f, AF_UNIX))
return 0;
- if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
- && unix_show_netlink(f) == 0)
- return 0;
-
- if ((fp = net_unix_open()) == NULL)
- return -1;
- if (!fgets(buf, sizeof(buf), fp)) {
- fclose(fp);
- return -1;
- }
-
- if (memcmp(buf, "Peer", 4) == 0)
- newformat = 1;
- cnt = 0;
-
- while (fgets(buf, sizeof(buf), fp)) {
- struct sockstat *u, **insp;
- int flags;
-
- if (!(u = calloc(1, sizeof(*u))))
- break;
-
- if (sscanf(buf, "%lx: %x %x %x %x %x %d %s",
- (unsigned long *)&u->rport, &u->rq, &u->wq, &flags, &u->type,
- &u->state, &u->ino, name) < 8)
- name[0] = 0;
-
- u->lport = u->ino;
- u->local.family = u->remote.family = AF_UNIX;
-
- if (flags & (1 << 16)) {
- u->state = SS_LISTEN;
- } else if (u->state > 0 &&
- u->state <= ARRAY_SIZE(unix_state_map)) {
- u->state = unix_state_map[u->state-1];
- if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport)
- u->state = SS_ESTABLISHED;
- }
- if (unix_type_skip(u, f) ||
- !(f->states & (1 << u->state))) {
- free(u);
- continue;
- }
-
- if (!newformat) {
- u->rport = 0;
- u->rq = 0;
- u->wq = 0;
- }
-
- if (name[0]) {
- u->name = strdup(name);
- if (!u->name) {
- free(u);
- break;
- }
- }
-
- if (u->rport) {
- struct sockstat *p;
-
- for (p = list; p; p = p->next) {
- if (u->rport == p->lport)
- break;
- }
- if (!p)
- u->peer_name = "?";
- else
- u->peer_name = p->name ? : "*";
- }
-
- if (f->f) {
- struct sockstat st = {
- .local.family = AF_UNIX,
- .remote.family = AF_UNIX,
- };
-
- memcpy(st.local.data, &u->name, sizeof(u->name));
- /* when parsing the old format rport is set to 0 and
- * therefore peer_name remains NULL
- */
- if (u->peer_name && strcmp(u->peer_name, "*"))
- memcpy(st.remote.data, &u->peer_name,
- sizeof(u->peer_name));
- if (run_ssfilter(f->f, &st) == 0) {
- free(u->name);
- free(u);
- continue;
- }
- }
-
- insp = &list;
- while (*insp) {
- if (u->type < (*insp)->type ||
- (u->type == (*insp)->type &&
- u->ino < (*insp)->ino))
- break;
- insp = &(*insp)->next;
- }
- u->next = *insp;
- *insp = u;
-
- if (++cnt > MAX_UNIX_REMEMBER) {
- while (list) {
- unix_stats_print(list, f);
- unix_list_drop_first(&list);
- }
- cnt = 0;
- }
- }
- fclose(fp);
- while (list) {
- unix_stats_print(list, f);
- unix_list_drop_first(&list);
- }
-
+ if (unix_show_netlink(f))
+ return sock_diag_error("UNIX");
return 0;
}
@@ -4770,10 +4271,6 @@ static int packet_show_sock(struct nlmsghdr *nlh, void *arg)
parse_rtattr(tb, PACKET_DIAG_MAX, (struct rtattr *)(r+1),
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
- /* use /proc/net/packet if all info are not available */
- if (!tb[PACKET_DIAG_MEMINFO])
- return -1;
-
stat.type = r->pdiag_type;
stat.prot = r->pdiag_num;
stat.ino = r->pdiag_ino;
@@ -4909,56 +4406,14 @@ static int packet_show_netlink(struct filter *f)
return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock);
}
-static int packet_show_line(char *buf, const struct filter *f, int fam)
-{
- unsigned long long sk;
- struct sockstat stat = {};
- int type, prot, iface, state, rq, uid, ino;
-
- sscanf(buf, "%llx %*d %d %x %d %d %u %u %u",
- &sk,
- &type, &prot, &iface, &state,
- &rq, &uid, &ino);
-
- if (type == SOCK_RAW && !(f->dbs & (1<<PACKET_R_DB)))
- return 0;
- if (type == SOCK_DGRAM && !(f->dbs & (1<<PACKET_DG_DB)))
- return 0;
-
- stat.type = type;
- stat.prot = prot;
- stat.lport = stat.iface = iface;
- stat.state = state;
- stat.rq = rq;
- stat.uid = uid;
- stat.ino = ino;
- stat.state = SS_CLOSE;
-
- if (packet_stats_print(&stat, f))
- return 0;
-
- return 0;
-}
-
static int packet_show(struct filter *f)
{
- FILE *fp;
- int rc = 0;
-
if (!filter_af_get(f, AF_PACKET) || !(f->states & (1 << SS_CLOSE)))
return 0;
- if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") &&
- packet_show_netlink(f) == 0)
- return 0;
-
- if ((fp = net_packet_open()) == NULL)
- return -1;
- if (generic_record_read(fp, packet_show_line, f, AF_PACKET))
- rc = -1;
-
- fclose(fp);
- return rc;
+ if (packet_show_netlink(f))
+ return sock_diag_error("PACKET");
+ return 0;
}
static int xdp_stats_print(struct sockstat *s, const struct filter *f)
@@ -5263,36 +4718,11 @@ static int netlink_show_netlink(struct filter *f)
static int netlink_show(struct filter *f)
{
- FILE *fp;
- char buf[256];
- int prot, pid;
- unsigned int groups;
- int rq, wq, rc;
- unsigned long long sk, cb;
-
if (!filter_af_get(f, AF_NETLINK) || !(f->states & (1 << SS_CLOSE)))
return 0;
- if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") &&
- netlink_show_netlink(f) == 0)
- return 0;
-
- if ((fp = net_netlink_open()) == NULL)
- return -1;
- if (!fgets(buf, sizeof(buf), fp)) {
- fclose(fp);
- return -1;
- }
-
- while (fgets(buf, sizeof(buf), fp)) {
- sscanf(buf, "%llx %d %d %x %d %d %llx %d",
- &sk,
- &prot, &pid, &groups, &rq, &wq, &cb, &rc);
-
- netlink_show_one(f, prot, pid, groups, 0, 0, 0, rq, wq, sk, cb);
- }
-
- fclose(fp);
+ if (netlink_show_netlink(f))
+ return sock_diag_error("NETLINK");
return 0;
}
--
2.53.0
next prev parent reply other threads:[~2026-11-12 20:00 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 19:59 [PATCH iproute2 00/11] ss fixes from an OSS scan Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 01/11] ss: fix double close on sock_diag send failure Stephen Hemminger
2026-11-12 19:59 ` Stephen Hemminger [this message]
2026-11-12 19:59 ` [PATCH iproute2 03/11] ss: escape names chosen by the socket owner Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 04/11] ss: size the TCPDIAG_FILE buffer to the record Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 05/11] ss: replay all dumps in TCPDIAG_FILE Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 06/11] ss: bound state and type name lookups Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 07/11] ss: fix rpcbind service cache Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 08/11] ss: read socket SELinux context only for -z Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 09/11] ss: check owner before naming a netlink socket Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 10/11] ss: keep following events after ENOBUFS Stephen Hemminger
2026-11-12 19:59 ` [PATCH iproute2 11/11] ss: report a failed SCTP or MPTCP dump Stephen Hemminger
-- strict thread matches above, loose matches on Subject: below --
2026-11-09 21:25 [PATCH iproute2 00/11] ss fixes from an OSS scan Stephen Hemminger
2026-11-09 21:25 ` [PATCH iproute2 02/11] ss: drop /proc fallback for socket listing Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261112200046.2164391-3-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=dsahern@kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox