[systemd-devel] Filter/Parse NETLINK_KOBJECT_UEVENT Messages
Mantas Mikulėnas
grawity at gmail.com
Mon Sep 13 09:57:32 UTC 2021
On Mon, Sep 13, 2021 at 12:29 PM Ryan McClue <re.mcclue at protonmail.com>
wrote:
> Currently, I'm listening to NETLINK_KOBJECT_UEVENT messages with the
> following code:
>
> union UeventBuffer {
> struct nlmsghdr netlink_header;
> char raw[8192];
> };
> int sock = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK,
> NETLINK_KOBJECT_UEVENT);
>
> struct sockaddr_nl addr = {};
> addr.nl_family = AF_NETLINK;
> addr.nl_groups = 1 << 0;
> bind(sock, (struct sockaddr *)&addr, sizeof(addr));
>
> UeventBuffer buf = {};
> struct iovec iov = {};
> iov.iov_base = &buf;
> iov.iov_len = sizeof(buf);
>
> struct msghdr msg = {};
> struct sockaddr_nl src_addr = {};
> msg.msg_name = &src_addr;
> msg.msg_namelen = sizeof(src_addr);
> msg.msg_iov = &iov;
> msg.msg_iovlen = 1;
>
> int bytes = recvmsg(sock, &msg, 0);
> char *buf_str = buf.raw;
> // parse this buf_str ...
>
> I have a few questions to clarify my understanding and to make this more
> robust:
> 1. If I add an Xbox One controller, which evtest shows to be
> /dev/input/event14 I get a whole host of messages, e.g:
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0*
>
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38*
>
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/event14*
>
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/js0*
> *bind@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0*
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.1*
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4/1-2.4:1.2*
> *bind@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.4*
> *add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.2*
> *change@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.2*
> Why so many?
>
It represents the actual device and subsystem layering in Linux – first
there's a USB device (on hub 1-2 port 4), then USB interfaces on that
device (1.0 to 1.2), then an input-layer device (input38), then two
different /dev nodes exposed by it (generic evdev and what I *think* is
legacy joydev? Not sure if it's "legacy" or "still current".)
They are necessary; for example, the 1st event that informs systemd-udevd
about the low-level USB device is what causes the correct device driver
module to be loaded in the first place.
> Can I filter them to just get the ones ending with /input/inputXX/eventXX?
>
It seems you're supposed to use BPF filters via SO_ATTACH_FILTER; at least
that's what libudev does.
> 2. Currently this only picks up input devices. How would I listen to /snd
> devices, /hid devices, etc.? I assume some change to nl_groups, however
> what should this be and where is this documented?
>
There's just one group for all events.
(If I remember correctly, group 1 has all events straight from the kernel,
group 2 is the same events augmented and retransmitted by udev. Normally
programs want the latter. Both have the same events and include all
devices, though.)
> 3. Currently, I'm manually parsing the *buf_str* to extract the command
> and device. Are there some supplied macros that parse this information in a
> more robust way? (as is the case for RTNETLINK)
>
Well, systemd supplies a whole libudev library, so I would generally
recommend using that – *instead of* manually working with netlink... (Or
more recently sd-device, but I don't think libudev is likely to be going
*poof* anytime soon, especially if you're looking for compatibility with
older systems or eudev-using distros.)
Start with udev_monitor_new_from_netlink() and
use udev_monitor_filter_add_match_*() to filter by subsystem, devtype, or
some arbitrary property, then you'll receive events already parsed. That's
3 lines of code in comparison to your 30.
--
Mantas Mikulėnas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/systemd-devel/attachments/20210913/681f0676/attachment.htm>
More information about the systemd-devel
mailing list