Last active
August 4, 2019 13:57
-
-
Save luohao-brian/7535fa346f37450137e5db45cd793ace to your computer and use it in GitHub Desktop.
netlink-examples
This file contains hidden or 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
// Netlink 是内核与用户空间进程通信的一种机制,采用与 UDP socket 非常类似的编程风格。( | |
// 与 UDP 类似,Netlink 通信也有服务器端和客户端。例如,Linux 内核作为服务器端,已经运行在那里。我们则编写 Netlink 客户端,给内核发消息,并获得我们想要的信息。 | |
/* | |
* Display all IPv4 addresses | |
*/ | |
#include <stdio.h> //printf, perror | |
#include <string.h> //memset, strlen | |
#include <stdlib.h> //exit | |
#include <unistd.h> //close | |
#include <sys/socket.h> //msghdr | |
#include <arpa/inet.h> //inet_ntop | |
#include <linux/netlink.h> //sockaddr_nl | |
#include <linux/rtnetlink.h> //rtgenmsg,ifinfomsg | |
#define BUFSIZE 8192 | |
struct nl_req_s { | |
struct nlmsghdr hdr; | |
struct rtgenmsg gen; | |
}; | |
void die(char *s) | |
{ | |
perror(s); | |
exit(1); | |
} | |
void rtnl_print_addr(struct nlmsghdr * h) | |
{ | |
struct ifaddrmsg * addr; | |
struct rtattr * attr; | |
int len; | |
addr = NLMSG_DATA(h); | |
len = RTM_PAYLOAD(h); | |
/* loop over all attributes for the NEWLINK message */ | |
for (attr = IFLA_RTA(addr); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) | |
{ | |
switch (attr->rta_type) | |
{ | |
case IFA_LABEL: | |
printf("Interface : %s\n", (char *)RTA_DATA(attr)); | |
break; | |
case IFA_LOCAL: | |
{ | |
int ip = *(int*)RTA_DATA(attr); | |
unsigned char bytes[4]; | |
bytes[0] = ip & 0xFF; | |
bytes[1] = (ip >> 8) & 0xFF; | |
bytes[2] = (ip >> 16) & 0xFF; | |
bytes[3] = (ip >> 24) & 0xFF; | |
printf("IP Address : %d.%d.%d.%d\n", bytes[0], bytes[1], bytes[2], bytes[3]); | |
break; | |
} | |
default: | |
break; | |
} | |
} | |
} | |
int main(void) | |
{ | |
struct sockaddr_nl kernel; | |
int s, end=0, len; | |
struct msghdr msg; | |
struct nl_req_s req; | |
struct iovec io; | |
char buf[BUFSIZE]; | |
//build kernel netlink address | |
memset(&kernel, 0, sizeof(kernel)); | |
kernel.nl_family = AF_NETLINK; | |
kernel.nl_groups = 0; | |
//create a Netlink socket | |
if ((s=socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) | |
{ | |
die("socket"); | |
} | |
//build netlink message | |
memset(&req, 0, sizeof(req)); | |
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); | |
req.hdr.nlmsg_type = RTM_GETADDR; | |
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_INET; | |
memset(&io, 0, sizeof(io)); | |
io.iov_base = &req; | |
io.iov_len = req.hdr.nlmsg_len; | |
memset(&msg, 0, sizeof(msg)); | |
msg.msg_iov = &io; | |
msg.msg_iovlen = 1; | |
msg.msg_name = &kernel; | |
msg.msg_namelen = sizeof(kernel); | |
//send the message | |
if (sendmsg(s, &msg, 0) < 0) | |
{ | |
die("sendmsg"); | |
} | |
//parse reply | |
while (!end) | |
{ | |
memset(buf, 0, BUFSIZE); | |
msg.msg_iov->iov_base = buf; | |
msg.msg_iov->iov_len = BUFSIZE; | |
if ((len=recvmsg(s, &msg, 0)) < 0) | |
{ | |
die("recvmsg"); | |
} | |
for (struct nlmsghdr * msg_ptr = (struct nlmsghdr *)buf; | |
NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) | |
{ | |
switch (msg_ptr->nlmsg_type) | |
{ | |
case NLMSG_DONE: | |
end++; | |
break; | |
case RTM_NEWADDR: | |
rtnl_print_addr(msg_ptr); | |
break; | |
default: | |
printf("Ignored msg: type=%d, len=%d\n", msg_ptr->nlmsg_type, msg_ptr->nlmsg_len); | |
break; | |
} | |
} | |
} | |
close(s); | |
return 0; | |
} |
This file contains hidden or 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
/* | |
* Display all network interface names | |
*/ | |
#include <stdio.h> //printf, perror | |
#include <string.h> //memset, strlen | |
#include <stdlib.h> //exit | |
#include <unistd.h> //close | |
#include <sys/socket.h> //msghdr | |
#include <arpa/inet.h> //inet_ntop | |
#include <linux/netlink.h> //sockaddr_nl | |
#include <linux/rtnetlink.h> //rtgenmsg,ifinfomsg | |
#define BUFSIZE 8192 | |
struct nl_req_s { | |
struct nlmsghdr hdr; | |
struct rtgenmsg gen; | |
}; | |
void die(char *s) | |
{ | |
perror(s); | |
exit(1); | |
} | |
void rtnl_print_link(struct nlmsghdr * h) | |
{ | |
struct ifinfomsg * iface; | |
struct rtattr * attr; | |
int len; | |
iface = NLMSG_DATA(h); | |
len = RTM_PAYLOAD(h); | |
/* loop over all attributes for the NEWLINK message */ | |
for (attr = IFLA_RTA(iface); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) | |
{ | |
switch (attr->rta_type) | |
{ | |
case IFLA_IFNAME: | |
printf("Interface %d : %s\n", iface->ifi_index, (char *)RTA_DATA(attr)); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
int main(void) | |
{ | |
struct sockaddr_nl kernel; | |
int s, end=0, len; | |
struct msghdr msg; | |
struct nl_req_s req; | |
struct iovec io; | |
char buf[BUFSIZE]; | |
//build kernel netlink address | |
memset(&kernel, 0, sizeof(kernel)); | |
kernel.nl_family = AF_NETLINK; | |
kernel.nl_groups = 0; | |
//create a Netlink socket | |
if ((s=socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) | |
{ | |
die("socket"); | |
} | |
//build netlink message | |
memset(&req, 0, sizeof(req)); | |
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_INET; | |
memset(&io, 0, sizeof(io)); | |
io.iov_base = &req; | |
io.iov_len = req.hdr.nlmsg_len; | |
memset(&msg, 0, sizeof(msg)); | |
msg.msg_iov = &io; | |
msg.msg_iovlen = 1; | |
msg.msg_name = &kernel; | |
msg.msg_namelen = sizeof(kernel); | |
//send the message | |
if (sendmsg(s, &msg, 0) < 0) | |
{ | |
die("sendmsg"); | |
} | |
//parse reply | |
while (!end) | |
{ | |
memset(buf, 0, BUFSIZE); | |
msg.msg_iov->iov_base = buf; | |
msg.msg_iov->iov_len = BUFSIZE; | |
if ((len=recvmsg(s, &msg, 0)) < 0) | |
{ | |
die("recvmsg"); | |
} | |
for (struct nlmsghdr * msg_ptr = (struct nlmsghdr *)buf; | |
NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) | |
{ | |
switch (msg_ptr->nlmsg_type) | |
{ | |
case NLMSG_DONE: | |
end++; | |
break; | |
case RTM_NEWLINK: | |
rtnl_print_link(msg_ptr); | |
break; | |
default: | |
printf("Ignored msg: type=%d, len=%d\n", msg_ptr->nlmsg_type, msg_ptr->nlmsg_len); | |
break; | |
} | |
} | |
} | |
close(s); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment