Skip to content

Commit 8c3944e

Browse files
committed
Print associated interfaces for ::-listens
1 parent 2d7dd17 commit 8c3944e

4 files changed

Lines changed: 35 additions & 24 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ avahi-daemon (pid 655 user avahi)
3939
* Explaining wireguard and vxlan listening ports
4040

4141
More specifically
42-
* `ss` has a nice short command, but then you need a lot of arguments. But which? `-lpunt`? (Though of course, `ss` can do things `lls` can't, like printing established connections or unix sockets.)
42+
* `ss` has a nice short command, but then you need a lot of arguments. `-plut0wn` maybe? (Though of course, `ss` can do things `lls` can't, like printing established connections or unix sockets.)
4343
* `ss` output requires ~160 columns, while `lls` makes do with ~60.
4444
* `ss` output order is unfathomable.
45-
* For interpreters, `ss` will just display the command name, e.g. `python` or `node`.
45+
* `ss` will just display the command name, e.g. `python` or `node`, but not what script is running.
4646
`lls` tries to parse the command line of the interpreters and display the script name where possible.
4747
* `ss` prints almost no information for listening ports belonging to WireGuard or VXLAN interfaces, and what it prints is more confusing than helpful.

src/main.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod termtree;
77
use anyhow::Result;
88
use itertools::Itertools;
99
use netlink::{
10-
sock::{Family, SockInfo},
10+
sock::{Family, IfaceName, SockInfo},
1111
wg::wireguards,
1212
};
1313
use procfs::process::all_processes;
@@ -176,12 +176,9 @@ fn sockets_tree<'a>(
176176
}
177177
for ((port, proto), socks) in groups {
178178
let mut sout = termtree::Tree::new();
179-
if socks.iter().map(|s| s.addr).sorted().collect::<Vec<_>>()
180-
== [
181-
IpAddr::V4(Ipv4Addr::UNSPECIFIED),
182-
IpAddr::V6(Ipv6Addr::UNSPECIFIED),
183-
]
184-
{
179+
let v4all = IpAddr::V4(Ipv4Addr::UNSPECIFIED);
180+
let v6all = IpAddr::V6(Ipv6Addr::UNSPECIFIED);
181+
if socks.iter().map(|s| s.addr).sorted().collect::<Vec<_>>() == [v4all, v6all] {
185182
sout.leaf("0.0.0.0 + ::".into());
186183
} else {
187184
let socks = socks
@@ -191,9 +188,13 @@ fn sockets_tree<'a>(
191188
.collect::<BTreeSet<_>>();
192189
for (family, addr, iface) in socks {
193190
match (family, iface) {
194-
(Family::Both, _) => sout.leaf("*".into()),
195-
(_, Some(ifname)) => sout.leaf(format!("{} ({ifname})", addr)),
196-
_ => sout.leaf(format!("{}", addr)),
191+
(Family::Both, IfaceName::None) if addr == v6all => sout.leaf("*".into()),
192+
(Family::Both, IfaceName::Associated(ifnam)) if addr == v6all => {
193+
sout.leaf(format!("*%{ifnam}"))
194+
}
195+
(_, IfaceName::Associated(ifnam)) => sout.leaf(format!("{addr}%{ifnam}")),
196+
(_, IfaceName::LocalRoute(ifnam)) => sout.leaf(format!("{addr} ({ifnam})")),
197+
(_, IfaceName::None) => sout.leaf(format!("{}", addr)),
197198
};
198199
}
199200
}

src/netlink/sock.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ impl std::str::FromStr for Protocol {
152152
}
153153
}
154154

155+
#[derive(Debug, PartialEq, Eq, Clone, Ord, PartialOrd, Copy)]
156+
pub enum IfaceName<'a> {
157+
None,
158+
Associated(&'a str),
159+
LocalRoute(&'a str),
160+
}
161+
155162
#[derive(Debug, PartialEq, Eq, Clone)]
156163
pub struct SockInfo<'a> {
157164
pub family: Family,
@@ -160,7 +167,7 @@ pub struct SockInfo<'a> {
160167
pub addr: IpAddr,
161168
pub uid: u32,
162169
pub ino: Ino,
163-
pub iface: Option<&'a str>,
170+
pub iface: IfaceName<'a>,
164171
}
165172
impl<'a> SockInfo<'a> {
166173
fn new(
@@ -180,22 +187,24 @@ impl<'a> SockInfo<'a> {
180187
family
181188
};
182189
let addr = ir.header.socket_id.source_address;
183-
let iface = interfaces
184-
.get(&ir.header.socket_id.interface_id)
185-
.or_else(|| {
186-
local_routes
187-
.route(addr)
188-
.and_then(|iface| interfaces.get(&iface))
189-
})
190-
.map(|x| &**x);
190+
let iface = match ir.header.socket_id.interface_id {
191+
1.. => interfaces
192+
.get(&ir.header.socket_id.interface_id)
193+
.map(|x| IfaceName::Associated(&**x)),
194+
0 => local_routes
195+
.route(addr)
196+
.and_then(|iface| interfaces.get(&iface))
197+
.map(|x| IfaceName::LocalRoute(&**x)),
198+
};
199+
// .map(|x| &**x);
191200
Self {
192201
family,
193202
protocol,
194203
port: ir.header.socket_id.source_port,
195204
addr,
196205
uid: ir.header.uid,
197206
ino: ir.header.inode.into(),
198-
iface,
207+
iface: iface.unwrap_or(IfaceName::None),
199208
}
200209
}
201210
}

src/sockets_procfs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::Ino;
22
use crate::{
33
netlink::sock::{Family, Protocol, SockInfo},
4-
IfaceInfo,
4+
IfaceInfo, IfaceName,
55
};
66
use anyhow::{Context, Result};
77
use std::collections::HashMap;
@@ -39,7 +39,8 @@ pub fn all_sockets<'i>(
3939
iface: local_routes
4040
.route(s.local_address.ip())
4141
.and_then(|iface| interfaces.get(&iface))
42-
.map(|s| &**s),
42+
.map(|s| IfaceName::LocalRoute(&**s))
43+
.unwrap_or(IfaceName::None),
4344
},
4445
);
4546
}

0 commit comments

Comments
 (0)