Re: [systemd-devel] Filter/Parse NETLINK_KOBJECT_UEVENT Messages

2021-09-14 Thread Ryan McClue
Sorry, I should clarify. The code in sd-device related to BPF I don't 
understand. What is the 'input' in BPF?

Sent from ProtonMail mobile

 Original Message 
On 14 Sep. 2021, 5:24 pm, Lennart Poettering wrote:

> On Di, 14.09.21 01:08, Ryan McClue (re.mcc...@protonmail.com) wrote:
>
>> I understand this is slightly off-topic, but I'm completely new to
>> BPF. Analyzing libudev source and Internet I understand the general
>> idea. However, I don't understand how information/what information
>> is passed to the filter from the socket. For example, in my case the
>> socket payload, i.e. buf_str =
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/event14
>
>> 1. How do I pass this string to the sock_filter/sock_fprog
>> structures?
>
> You don't. The bpf filtering, and in particular the bloom filter that
> is used for that is mostly internal to udev, and not something that is
> consider official API and should be reimplemented.
>
> Use sd-device/libudev, it implements all of this, and is the only official API
> to the bpf bloom filter stuff udev does there.
>
> Lennart
>
> --
> Lennart Poettering, Berlin

Re: [systemd-devel] Filter/Parse NETLINK_KOBJECT_UEVENT Messages

2021-09-14 Thread Ryan McClue
Earlier you said that .nl_groups = 2 will get kernel uevents augmented by udev. 
So, at some stage doesn't udev have to parse the raw kernel uevents, i.e. 
.nl_groups = 1? How does it do this? Does it use BPF to achieve this or the 
string parsing?

--
Ryan McClue, Sydney

‐‐‐ Original Message ‐‐‐

On Tuesday, September 14th, 2021 at 5:24 PM, Lennart Poettering 
 wrote:

> On Di, 14.09.21 01:08, Ryan McClue (re.mcc...@protonmail.com) wrote:
>
> > I understand this is slightly off-topic, but I'm completely new to
> >
> > BPF. Analyzing libudev source and Internet I understand the general
> >
> > idea. However, I don't understand how information/what information
> >
> > is passed to the filter from the socket. For example, in my case the
> >
> > socket payload, i.e. buf_str =
> >
> > add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/event14
>
> > 1.  How do I pass this string to the sock_filter/sock_fprog
> >
> > structures?
>
> You don't. The bpf filtering, and in particular the bloom filter that
>
> is used for that is mostly internal to udev, and not something that is
>
> consider official API and should be reimplemented.
>
> Use sd-device/libudev, it implements all of this, and is the only official API
>
> to the bpf bloom filter stuff udev does there.
>
> Lennart
>
> -
>
> Lennart Poettering, Berlin


Re: [systemd-devel] Filter/Parse NETLINK_KOBJECT_UEVENT Messages

2021-09-13 Thread Ryan McClue
I understand this is slightly off-topic, but I'm completely new to BPF. 
Analyzing libudev source and Internet I understand the general idea. However, I 
don't understand how information/what information is passed to the filter from 
the socket. For example, in my case the socket payload, i.e. buf_str = 
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/event14
1. How do I pass this string to the sock_filter/sock_fprog structures?
2. Is a correct way of filtering these to implement string parsing to check for 
'/event' sub-string in EPF bytecode?
I completely agree that using libudev is the way to go (and *a lot* more sane), 
however this is for my own understanding. Just by investigating this I have 
found out more about how udev works and now BPF.
‐‐‐ Original Message ‐‐‐
On Monday, September 13th, 2021 at 7:57 PM, Mantas Mikulėnas 
 wrote:

> On Mon, Sep 13, 2021 at 12:29 PM Ryan McClue  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 *), sizeof(addr));
>>
>> UeventBuffer buf = {};
>> struct iovec iov = {};
>> iov.iov_base = 
>> iov.iov_len = sizeof(buf);
>>
>> struct msghdr msg = {};
>> struct sockaddr_nl src_addr = {};
>> msg.msg_name = _addr;
>> msg.msg_namelen = sizeof(src_addr);
>> msg.msg_iov = 
>> msg.msg_iovlen = 1;
>>
>> int bytes = recvmsg(sock, , 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/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/event14
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/js0
>> bind@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.1
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.2
>> bind@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4
>> add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.2
>> change@/devices/pci:00/: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

[systemd-devel] Filter/Parse NETLINK_KOBJECT_UEVENT Messages

2021-09-13 Thread Ryan McClue
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 *), sizeof(addr));

UeventBuffer buf = {};
struct iovec iov = {};
iov.iov_base = 
iov.iov_len = sizeof(buf);

struct msghdr msg = {};
struct sockaddr_nl src_addr = {};
msg.msg_name = _addr;
msg.msg_namelen = sizeof(src_addr);
msg.msg_iov = 
msg.msg_iovlen = 1;

int bytes = recvmsg(sock, , 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/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/event14
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input38/js0
bind@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.0
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.1
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4/1-2.4:1.2
bind@/devices/pci:00/:00:14.0/usb1/1-2/1-2.4
add@/devices/pci:00/:00:14.0/usb1/1-2/1-2.2
change@/devices/pci:00/:00:14.0/usb1/1-2/1-2.2
Why so many? Can I filter them to just get the ones ending with 
/input/inputXX/eventXX?
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?
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)

Thank you