Hey folks, A few months ago I switched away from using netlink in wireguard, preferring instead to use ioctl. I had come up against limitations in rtnetlink, and ioctl presented a straightforward hard to screw-up alternative. The very simple API is documented here: https://git.zx2c4.com/WireGuard/tree/src/uapi.h
This works well, and I'm reluctant to change it, but as I do more complicated things, and as kernel submission time looms nearer, I'm kept up at night by the notion that maybe I ought to give netlink another chance. But how? For each wireguard interface, there are three types of structures for userspace to configure. There is one wgdevice for each interface. Each wgdevice has a variable amount (up to 2^16) of wgpeers. Each wgpeer has a variable amount (up to 2^16) of wgipmasks. I'd like an interface to get and set all of these at once, atomically. Presently, with the ioctl, I just have a simple get ioctl and a simple set ioctl. The set one passes a user space pointer, which is read incrementally in kernel space. The get one will first return how much userspace should allocate, and then when called again will write incrementally into a provided userspace buffer up to a passed-in maximum number of bytes. Very basic, I'm quite happy. When I had tried to do this priorly with netlink, I did it by defining changelink and fill_info in rtnl_link_ops. For changelink, I iterated through the netlink objects, and for fill_info, I filled in the skb with netlink objects. This was a bit more complex but basically worked. Except netlink skbs have a maximum size and are buffered, which means things broke entirely when trying to read or write logs of wgpeers or lots of wgipmasks. So, the meager interfaces afforded to me by rtnl_link_ops are insufficient. Doing anything beyond this, either by registering new rtnetlink messages, or by using generic netlink, seemed overwhelmingly complex and undesirable. So I'm wondering -- is there a good way to be doing this with netlink? Or am I right to stay with ioctl? Thanks, Jason