Created
March 12, 2013 07:27
-
-
Save supermartian/5140929 to your computer and use it in GitHub Desktop.
Netlink programming demo.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <memory.h> | |
#include <linux/types.h> | |
#include <linux/netlink.h> | |
#include <linux/rtnetlink.h> | |
struct nl_req_s { | |
struct nlmsghdr hdr; | |
struct rtgenmsg gen; | |
}; | |
typedef struct nl_req_s nl_req_t; | |
int get_faces() { | |
int fd; | |
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | |
struct sockaddr_nl kernel; | |
struct msghdr rtnl_msg; | |
struct iovec io; | |
nl_req_t req; | |
memset(&rtnl_msg, 0, sizeof(rtnl_msg)); | |
memset(&kernel, 0, sizeof(kernel)); | |
memset(&req, 0, sizeof(req)); | |
kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination) */ | |
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); | |
req.hdr.nlmsg_type = RTM_GETLINK; | |
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; | |
req.hdr.nlmsg_seq = 1; | |
req.hdr.nlmsg_pid = getpid(); | |
req.gen.rtgen_family = AF_PACKET; /* no preferred AF, we will get *all* interfaces */ | |
io.iov_base = &req; | |
io.iov_len = req.hdr.nlmsg_len; | |
rtnl_msg.msg_iov = &io; | |
rtnl_msg.msg_iovlen = 1; | |
rtnl_msg.msg_name = &kernel; | |
rtnl_msg.msg_namelen = sizeof(kernel); | |
struct sockaddr_nl local; | |
memset(&local, 0, sizeof(local)); | |
local.nl_family = AF_NETLINK; | |
local.nl_pid = getpid(); /* can be obtained using getpid*/ | |
local.nl_groups = 0; | |
if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0) { | |
perror("crap..."); | |
} | |
sendmsg(fd, (struct msghdr *) &rtnl_msg, 0); | |
char reply[1024]; /* a large buffer */ | |
int len; | |
struct nlmsghdr *msg_ptr; /* pointer to current part */ | |
struct msghdr rtnl_reply; /* generic msghdr structure */ | |
struct iovec io_reply; | |
memset(&io_reply, 0, sizeof(io_reply)); | |
memset(&rtnl_reply, 0, sizeof(rtnl_reply)); | |
io.iov_base = reply; | |
io.iov_len = 1024; | |
rtnl_reply.msg_iov = &io; | |
rtnl_reply.msg_iovlen = 1; | |
rtnl_reply.msg_name = &kernel; | |
rtnl_reply.msg_namelen = sizeof(kernel); | |
len = recvmsg(fd, &rtnl_reply, 0); /* read lots of data */ | |
for (msg_ptr = (struct nlmsghdr *) reply; NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) | |
{ | |
if (msg_ptr->nlmsg_type == RTM_NEWLINK) { | |
rtnl_print_link(msg_ptr); | |
} | |
} | |
return 0; | |
} | |
void rtnl_print_link(struct nlmsghdr *h) | |
{ | |
struct ifinfomsg *iface; | |
struct rtattr *attribute; | |
int len; | |
iface = NLMSG_DATA(h); | |
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(*iface)); | |
for (attribute = IFLA_RTA(iface); RTA_OK(attribute, len); attribute = RTA_NEXT(attribute, len)) | |
{ | |
switch(attribute->rta_type) | |
{ | |
case IFLA_IFNAME: | |
printf("Interface %d : %s\n", iface->ifi_index, (char *) RTA_DATA(attribute)); | |
break; | |
} | |
} | |
} | |
int main() | |
{ | |
get_faces(); | |
return 0; | |
} |
This demo code does not use padding between header and message. It 'works', because the compiler does
the padding for struct nl_req_s.
This demo code does not use padding between header and message. It 'works', because the compiler does the padding for struct nl_req_s.
@igaw Hello, could you provide the correct way to pad nl_req_s? thank you
The raw RTNL interface is tricky. I would recomand to use libmnl & co. If you want/have to use the Kernel API check the examples in the man pages. Basically you want a buffer and use 'the position macros' (e.g. NLMSG_DATA) to place the write/read head. These macros get the alignment and padding right.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dont you have to write any kernel module for this.
Secondly, i tried executing it, and rtnl_print_link() is never called, so no output.