Penguin
Blame: LinuxNetlinkSocketExample
EditPageHistoryDiffInfoLikePages
Annotated edit history of LinuxNetlinkSocketExample version 7, including all changes. View license author blame.
Rev Author # Line
1 PerryLorier 1 This is a sample program that uses a netlink socket to listen to route change events and prints out some rudimentary information about them. It's very simple and boring, but hopefully useful.
2
3 IanMcDonald 3 This being a wiki, I also expect everyone to hack on this code and make it nicer, this is pretty hideous, but I want to get on with my real program now. So if you're reading this page your mission (if you choose to accept it) is to clean up the below code a little bit (doesn't need to be much).
2 AdrianKitto 4
5 See LinuxNetlinkSockets
6
1 PerryLorier 7 ----
8 <verbatim>
4 CamiloMesias 9 #include <asm/types.h>
10
1 PerryLorier 11 #include <sys/socket.h>
12 #include <unistd.h>
13 #include <err.h>
14 #include <stdio.h>
7 ThomasHisch 15 #include <string.h>
1 PerryLorier 16 #include <netinet/in.h>
17
18 #include <linux/netlink.h>
19 #include <linux/rtnetlink.h>
20
21 #if 0
5 CamiloMesias 22 //#define MYPROTO NETLINK_ARPD
4 CamiloMesias 23 #define MYMGRP RTMGRP_NEIGH
5 CamiloMesias 24 // if you want the above you'll find that the kernel must be compiled with CONFIG_ARPD, and
25 // that you need MYPROTO=NETLINK_ROUTE, since the kernel arp code {re,ab}uses rtnl (NETLINK_ROUTE)
26
1 PerryLorier 27 #else
4 CamiloMesias 28 #define MYPROTO NETLINK_ROUTE
29 #define MYMGRP RTMGRP_IPV4_ROUTE
1 PerryLorier 30 #endif
31
32 struct msgnames_t {
33 int id;
34 char *msg;
35 } typenames[] = {
36 #define MSG(x) { x, #x }
37 MSG(RTM_NEWROUTE),
38 MSG(RTM_DELROUTE),
39 MSG(RTM_GETROUTE),
40 #undef MSG
41 {0,0}
42 };
43
44 char *lookup_name(struct msgnames_t *db,int id)
45 {
46 static char name[512];
47 struct msgnames_t *msgnamesiter;
48 for(msgnamesiter=db;msgnamesiter->msg;++msgnamesiter) {
49 if (msgnamesiter->id == id)
50 break;
51 }
52 if (msgnamesiter->msg) {
53 return msgnamesiter->msg;
54 }
55 snprintf(name,sizeof(name),"#%i",id);
56 return name;
57 }
58
59 int open_netlink()
60 {
5 CamiloMesias 61 int sock = socket(AF_NETLINK,SOCK_RAW,MYPROTO);
1 PerryLorier 62 struct sockaddr_nl addr;
5 CamiloMesias 63
64 memset((void *)&addr, 0, sizeof(addr));
65
1 PerryLorier 66 if (sock<0)
67 return sock;
68 addr.nl_family = AF_NETLINK;
69 addr.nl_pid = getpid();
4 CamiloMesias 70 addr.nl_groups = MYMGRP;
1 PerryLorier 71 if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
72 return -1;
73 return sock;
74 }
75
76 int read_event(int sock)
77 {
78 struct sockaddr_nl nladdr;
79 struct msghdr msg;
80 struct iovec iov[2];
81 struct nlmsghdr nlh;
82 char buffer[65536];
83 int ret;
84 iov[0].iov_base = (void *)&nlh;
85 iov[0].iov_len = sizeof(nlh);
86 iov[1].iov_base = (void *)buffer;
87 iov[1].iov_len = sizeof(buffer);
88 msg.msg_name = (void *)&(nladdr);
89 msg.msg_namelen = sizeof(nladdr);
90 msg.msg_iov = iov;
91 msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
92 ret=recvmsg(sock, &msg, 0);
93 if (ret<0) {
94 return ret;
95 }
96 printf("Type: %i (%s)\n",(nlh.nlmsg_type),lookup_name(typenames,nlh.nlmsg_type));
97 printf("Flag:");
6 MarcoPolci 98 #define FLAG(x) if (nlh.nlmsg_flags & x) printf(" %s",#x)
1 PerryLorier 99 FLAG(NLM_F_REQUEST);
100 FLAG(NLM_F_MULTI);
101 FLAG(NLM_F_ACK);
102 FLAG(NLM_F_ECHO);
103 FLAG(NLM_F_REPLACE);
104 FLAG(NLM_F_EXCL);
105 FLAG(NLM_F_CREATE);
106 FLAG(NLM_F_APPEND);
107 #undef FLAG
108 printf("\n");
109 printf("Seq : %i\n",nlh.nlmsg_seq);
110 printf("Pid : %i\n",nlh.nlmsg_pid);
111 printf("\n");
112 return 0;
113 }
114
115 int main(int argc, char *argv[])
7 ThomasHisch 116 {
117 int nls = open_netlink();
1 PerryLorier 118 if (nls<0) {
119 err(1,"netlink");
120 }
7 ThomasHisch 121
1 PerryLorier 122 while (1)
123 read_event(nls);
124 return 0;
125 }
126 </verbatim>