Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
netlink: minimal Linux rtnetlink support
This 1st of the 10 patches brings support of the minimal subset of the rtnetlink (Linux routing socket) interface as described here - https://man7.org/linux/man-pages/man7/rtnetlink.7.html. The rtnetlink is actually a subset of even richer netlink interface described here - https://man7.org/linux/man-pages/man7/netlink.7.html. In other words, rtnetlink covers a NETLINK_ROUTE family of the broader netlink interface. We need rtnetlink in order to support the implemetation of if_nameindex() and getifaddrs() in modern musl 1.1.24. In addition Golang uses the netlink interface to discover the interfaces and IP address as well. Please note this is an original copy of the Charles Myers' two commits: f1cd48e except of the modifications to bsd/net.cc that are part of the last commit and subset of the 64a0c1a that adds lltable_foreach() and lltable_foreach_lle(). The next 8 much smaller patches fix various small bugs and enhance slightly this implementation. The last one enables the netlink support and adds a unit test. The netlink interface is pretty rich and not very precisely documented. I have actually used a unit test to discover in more details how the netlink responses should look like. In general, the application would use standard socket API to open a socket with the domain and protocol equal to AF_NETLINK and NETLINK_ROUTE respectively and typically use SOCK_RAW as type. Then it would optionally bind the socket and build a request sent using standard sendmsg(). Finally it would receive all replies from kernel using recvmsg(). To illustrate, the incomplete code might look like this: //////////////////////////////////////////////////////// //step 1 int s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); //step 2 src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = pid; // if 0 kernel will assign unique id bind(s, (struct sockaddr*) &src_addr, sizeof(src_addr)) // step 3 dst_addr.nl_family = AF_NETLINK; dst_addr.nl_pid = 0; // should be 0 if destination is kernel iov[0].iov_base = req; iov[0].iov_len = req->nlmsg_len; snd_msg.msg_iov = iov; snd_msg.msg_iovlen = 1; snd_msg.msg_name = &dst_addr; snd_msg.msg_namelen = sizeof(dst_addr); sendmsg(s, &snd_msg, 0) //step 4 rcv_msg.msg_iov[0].iov_base = buf; rcv_msg.msg_iov[0].iov_len = BUFSIZE; recvmsg(s, &rcv_msg, 0) //process replies received in buf //////////////////////////////////////////////////////// This patch implements support of only 3 rtnetlink types of requests: - RTM_GETLINK - RTM_GETADDR - RTM_GETNEIGH The bulk of the implementation is in the linux_netlink.cc and mostly centers around following functions: - netlink_attach() - netlink_bind() - netlink_output() - netlink_process_msg() - netlink_process_getlink_msg() - netlink_process_getaddr_msg() - netlink_process_getneigh_msg() Most other pru_* functions delegate to raw_usrreqs as is. Authored-by: Charles Myers <[email protected]> Signed-off-by: Waldemar Kozaczuk <[email protected]>
- Loading branch information