With recvfrom(2) and sendto(2), we can use a UNIX datagram socket at
server side without assigning a peer address with connect(2). Here, I
call such sockets one-way sockets.
# ss -x -p
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
...
u_dgr ESTAB 0 0 /run/systemd/notify 13465 * 0 users:(("systemd",pid=1,fd=227))
u_dgr ESTAB 0 0 * 35438 * 13465 users:(("systemd-journal",pid=1280,fd=15))
u_dgr ESTAB 0 0 * 74792 * 13465 users:(("bluetoothd",pid=13874,fd=4))
...
The socket, opened with systemd as fd 227, is an example of one-way
socket (13465). It has 0 as "Peer Address:Port". From the side of
systemd process, there is no communication peers. However, the
sockets (35438 and 74792) opened with systemd-journal and bluetoothd
have the one-way socket (13465) as their communication peers.
We expect lsfd prints these connections if user specifies
-o+ENDPOINTS. This change and subsequent changes remove limitations in
this area.
In the early stage of lsfd process, lsfd collects information about
UNIX sockets on the system via unix-diag netlink. lsfd stores the
information to the IPC table. lsfd looks up the IPC table when
printing ENDPOINTS column.
With the original code, lsfd could not fill the ENDPOINTS columns
for sockets connecting to an one-way socket because lsfd did not
store one-way sockets to the IPC table.
# ./original-lsfd -Q 'INODE == 35438 || INODE == 74792' -oCOMMAND,PID,TYPE,INODE,NAME,ENDPOINTS
COMMAND PID TYPE INODE NAME ENDPOINTS
systemd-journal 1280 UNIX 35438 state=connected type=dgram
bluetoothd 13874 UNIX 74792 state=connected type=dgram
With this change, lsfd can fill the ENDPOINTS columns for sockets
connecting to an one-way socket. The new code puts dummy entries for
the one-way sockets to the IPC table. The dummy entries help lsfd to
find the connections.
# ./new-lsfd -Q 'INODE == 35438 || INODE == 74792' -oCOMMAND,PID,TYPE,INODE,NAME,ENDPOINTS
COMMAND PID TYPE INODE NAME ENDPOINTS
systemd-journal 1280 UNIX 35438 state=connected type=dgram 1,systemd,227rw
bluetoothd 13874 UNIX 74792 state=connected type=dgram 1,systemd,227rw
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
ino_t inode;
struct sock_xinfo *xinfo;
struct unix_xinfo *unix_xinfo;
+ bool peer_added = false;
+ bool maybe_oneway = false;
if (diag->udiag_family != AF_UNIX)
return false;
switch (attr->rta_type) {
case UNIX_DIAG_NAME:
unix_refill_name(xinfo, RTA_DATA(attr), len);
+ maybe_oneway = true;
break;
case UNIX_DIAG_SHUTDOWN:
unix_xinfo->unix_ipc->inode = inode;
unix_xinfo->unix_ipc->ipeer = (ino_t)(*(uint32_t *)RTA_DATA(attr));
add_ipc(&unix_xinfo->unix_ipc->ipc, inode % UINT_MAX);
+ peer_added = true;
break;
}
}
+
+ if (!peer_added && maybe_oneway) {
+ assert(unix_xinfo->unix_ipc == NULL);
+ unix_xinfo->unix_ipc = (struct unix_ipc *)new_ipc(&unix_ipc_class);
+ unix_xinfo->unix_ipc->inode = inode;
+ unix_xinfo->unix_ipc->ipeer = 0;
+ add_ipc(&unix_xinfo->unix_ipc->ipc, inode % UINT_MAX);
+ };
return true;
}
--- /dev/null
+endpoint_c: 0
+endpoint_c == PID,test_mkfs,3rw: 0
} > "$TS_OUTPUT" 2>&1
ts_finalize_subtest
+ts_init_subtest "ENDPOINTS-column"
+if ts_is_in_docker; then
+ ts_skip_subtest "unsupported in docker environment"
+else
+ {
+ coproc MKFDS { "$TS_HELPER_MKFDS" unix-dgram $FDS $FDC \
+ path=test_mkfds-unix-dgram \
+ abstract=true ; }
+
+ if read -r -u "${MKFDS[0]}" PID; then
+ endpoint_c=$(${TS_CMD_LSFD} -n -r -Q "PID == ${PID} && FD == $FDC" -o ENDPOINTS)
+ echo endpoint_c: $?
+
+ test "$endpoint_c" = "${PID},test_mkfds,${FDS}rw"
+ echo "endpoint_c == PID,test_mkfs,${FDS}rw:" $?
+
+ echo DONE >&"${MKFDS[1]}"
+ fi
+ wait "${MKFDS_PID}"
+ } > "$TS_OUTPUT" 2>&1
+ ts_finalize_subtest
+fi
+
ts_finalize