找回密码
 注册
搜索
热搜: 超星 读书 找书
查看: 3534|回复: 0

[【推荐】] linux下通过netlink 获取系统路由及接口地址信息

[复制链接]
发表于 2009-8-6 14:46:19 | 显示全部楼层 |阅读模式
platform: ubuntu 8.10 server

gcc version: gcc version 4.3.2

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

  1. #include <linux/types.h>
  2. #include <asm/types.h>
  3. #include <inttypes.h>
  4. #include <sys/file.h>
  5. #include <sys/user.h>
  6. #include <sys/socket.h>
  7. #include <linux/netlink.h>
  8. #include <linux/rtnetlink.h>
  9. #include <linux/if.h>
10. #include <unistd.h>
11. #include <stdlib.h>
12. #include <string.h>
13. #include <stdio.h>
14. #include <stdbool.h>
15. #include <errno.h>
16.  
17. typedef uint32_t u32;
18. typedef uint16_t u16;
19.  
20. struct nlsock {
21.   int sock;
22.   int seq;
23.   struct sockaddr_nl snl;
24.   char *name;
25. } nl_cmd = { -1, 0, {0}, \"netlink-cmd\" };
26.  
27. static int index_oif = 0;
28. struct nl_if_info {
29.   u32 addr;
30.   char *name;
31. };
32. static int nl_socket ( struct nlsock *nl, unsigned long groups )
33. {
34.   int ret;
35.   struct sockaddr_nl snl;
36.   int sock;
37.   int namelen;
38.  
39.   sock = socket ( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
40.   if ( sock < 0 ) {
41.     fprintf ( stderr, \"Can&#39;t open %s socket: %s\", nl->name,
42.         strerror ( errno ) );
43.     return -1;
44.   }
45.  
46.   ret = fcntl ( sock, F_SETFL, O_NONBLOCK );
47.   if ( ret < 0 ) {
48.     fprintf ( stderr, \"Can&#39;t set %s socket flags: %s\", nl->name,
49.         strerror ( errno ) );
50.     close ( sock );
51.     return -1;
52.   }
53.  
54.   memset ( &snl, 0, sizeof snl );
55.   snl.nl_family = AF_NETLINK;
56.   snl.nl_groups = groups;
57.  
58.   /* Bind the socket to the netlink structure for anything. */
59.   ret = bind ( sock, ( struct sockaddr * ) &snl, sizeof snl );
60.   if ( ret < 0 ) {
61.     fprintf ( stderr, \"Can&#39;t bind %s socket to group 0x%x: %s\",
62.         nl->name, snl.nl_groups, strerror ( errno ) );
63.     close ( sock );
64.     return -1;
65.   }
66.  
67.   /* multiple netlink sockets will have different nl_pid */
68.   namelen = sizeof snl;
69.   ret = getsockname ( sock, ( struct sockaddr * ) &snl, &namelen );
70.   if ( ret < 0 || namelen != sizeof snl ) {
71.     fprintf ( stderr, \"Can&#39;t get %s socket name: %s\", nl->name,
72.         strerror ( errno ) );
73.     close ( sock );
74.     return -1;
75.   }
76.  
77.   nl->snl = snl;
78.   nl->sock = sock;
79.   return ret;
80. }
81.  
82. static int nl_request ( int family, int type, struct nlsock *nl )
83. {
84.   int ret;
85.   struct sockaddr_nl snl;
86.  
87.   struct {
88.     struct nlmsghdr nlh;
89.     struct rtgenmsg g;
90.   } req;
91.  
92.  
93.   /* Check netlink socket. */
94.   if ( nl->sock < 0 ) {
95.     fprintf ( stderr, \"%s socket isn&#39;t active.\", nl->name );
96.     return -1;
97.   }
98.  
99.   memset ( &snl, 0, sizeof snl );
100.   snl.nl_family = AF_NETLINK;
101.  
102.   req.nlh.nlmsg_len = sizeof req;
103.   req.nlh.nlmsg_type = type;
104.   req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
105.   req.nlh.nlmsg_pid = 0;
106.   req.nlh.nlmsg_seq = ++nl->seq;
107.   req.g.rtgen_family = family;
108.  
109.   ret = sendto ( nl->sock, ( void* ) &req, sizeof req, 0,
110.       ( struct sockaddr* ) &snl, sizeof snl );
111.   if ( ret < 0 ) {
112.     fprintf ( stderr, \"%s sendto failed: %s\", nl->name, strerror ( errno ) );
113.     return -1;
114.   }
115.   return 0;
116. }
117.  
118. /* Receive message from netlink interface and pass those information
119.  to the given function. */
120. static int
121. nl_parse_info ( int ( *filter ) ( struct sockaddr_nl *, struct nlmsghdr *, void * ),
122.     struct nlsock *nl, void *arg )
123. {
124.   int status;
125.   int ret = 0;
126.   int error;
127.  
128.   while ( 1 ) {
129.     char buf[4096];
130.     struct iovec iov = { buf, sizeof buf };
131.     struct sockaddr_nl snl;
132.     struct msghdr msg = { ( void* ) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
133.     struct nlmsghdr *h;
134.  
135.     status = recvmsg ( nl->sock, &msg, 0 );
136.  
137.     if ( status < 0 ) {
138.       if ( errno == EINTR )
139.         continue;
140.       if ( errno == EWOULDBLOCK || errno == EAGAIN )
141.         break;
142.       fprintf ( stderr, \"%s recvmsg overrun\", nl->name );
143.       continue;
144.     }
145.  
146.     if ( snl.nl_pid != 0 ) {
147.       fprintf ( stderr, \"Ignoring non kernel message from pid %u\",
148.           snl.nl_pid );
149.       continue;
150.     }
151.  
152.     if ( status == 0 ) {
153.       fprintf ( stderr, \"%s EOF\", nl->name );
154.       return -1;
155.     }
156.  
157.     if ( msg.msg_namelen != sizeof snl ) {
158.       fprintf ( stderr, \"%s sender address length error: length %d\",
159.           nl->name, msg.msg_namelen );
160.       return -1;
161.     }
162.  
163.     for ( h = ( struct nlmsghdr * ) buf; NLMSG_OK ( h, status );
164.         h = NLMSG_NEXT ( h, status ) ) {
165.       /* Finish of reading. */
166.       if ( h->nlmsg_type == NLMSG_DONE )
167.         return ret;
168.  
169.       /* Error handling. */
170.       if ( h->nlmsg_type == NLMSG_ERROR ) {
171.         struct nlmsgerr *err = ( struct nlmsgerr * ) NLMSG_DATA ( h );
172.  
173.         /* If the error field is zero, then this is an ACK */
174.         if ( err->error == 0 ) {
175.           /* return if not a multipart message, otherwise continue */
176.           if ( ! ( h->nlmsg_flags & NLM_F_MULTI ) ) {
177.             return 0;
178.           }
179.           continue;
180.         }
181.  
182.         if ( h->nlmsg_len < NLMSG_LENGTH ( sizeof ( struct nlmsgerr ) ) ) {
183.           fprintf ( stderr, \"%s error: message truncated\",
184.               nl->name );
185.           return -1;
186.         }
187.         fprintf ( stderr, \"%s error: %s, type=%u, seq=%u, pid=%d\",
188.             nl->name, strerror ( -err->error ),
189.             err->msg.nlmsg_type, err->msg.nlmsg_seq,
190.             err->msg.nlmsg_pid );
191.         /*
192.         ret = -1;
193.         continue;
194.         */
195.         return -1;
196.       }
197.  
198.  
199.       /* skip unsolicited messages originating from command socket */
200.       if ( nl != &nl_cmd && h->nlmsg_pid == nl_cmd.snl.nl_pid ) {
201.         continue;
202.       }
203.  
204.       error = ( *filter ) ( &snl, h, arg );
205.       if ( error < 0 ) {
206.         fprintf ( stderr, \"%s filter function error\\n\", nl->name );
207.         ret = error;
208.       }
209.     }
210.  
211.     /* After error care. */
212.     if ( msg.msg_flags & MSG_TRUNC ) {
213.       fprintf ( stderr, \"%s error: message truncated\", nl->name );
214.       continue;
215.     }
216.     if ( status ) {
217.       fprintf ( stderr, \"%s error: data remnant size %d\", nl->name,
218.           status );
219.       return -1;
220.     }
221.   }
222.   return ret;
223. }
224.  
225. static void nl_parse_rtattr ( struct rtattr **tb, int max, struct rtattr *rta, int len )
226. {
227.   while ( RTA_OK ( rta, len ) ) {
228.     if ( rta->rta_type <= max )
229.       tb[rta->rta_type] = rta;
230.     rta = RTA_NEXT ( rta,len );
231.   }
232. }
233.  
234. static int nl_get_oif ( struct sockaddr_nl *snl, struct nlmsghdr *h, void *arg )
235. {
236.   int len;
237.   struct rtmsg *rtm;
238.   struct rtattr *tb [RTA_MAX + 1];
239.   u_char flags = 0;
240.  
241.   char anyaddr[16] = {0};
242.  
243.   int index;
244.   int table;
245.   void *dest;
246.   void *gate;
247.  
248.   rtm = NLMSG_DATA ( h );
249.  
250.   if ( h->nlmsg_type != RTM_NEWROUTE )
251.     return 0;
252.   if ( rtm->rtm_type != RTN_UNICAST )
253.     return 0;
254.  
255.   table = rtm->rtm_table;
256.  
257.   len = h->nlmsg_len - NLMSG_LENGTH ( sizeof ( struct rtmsg ) );
258.   if ( len < 0 )
259.     return -1;
260.  
261.   memset ( tb, 0, sizeof tb );
262.   nl_parse_rtattr ( tb, RTA_MAX, RTM_RTA ( rtm ), len );
263.  
264.   if ( rtm->rtm_flags & RTM_F_CLONED )
265.     return 0;
266.   if ( rtm->rtm_protocol == RTPROT_REDIRECT )
267.     return 0;
268.   if ( rtm->rtm_protocol == RTPROT_KERNEL )
269.     return 0;
270.  
271.   if ( rtm->rtm_src_len != 0 )
272.     return 0;
273.  
274.  
275.  
276.   // 这里可以对所有路由进行识别
277.  
278.  
279.  
280.   // 取得out interface index
281.  
282.   if ( tb[RTA_OIF] ) {
283.     index = * ( int * ) RTA_DATA ( tb[RTA_OIF] );
284.   }
285.  
286.   if ( tb[RTA_DST] )
287.     dest = RTA_DATA ( tb[RTA_DST] );
288.   else
289.     dest = anyaddr;
290.  
291.   /* Multipath treatment is needed. */
292.   if ( tb[RTA_GATEWAY] )
293.     gate = RTA_DATA ( tb[RTA_GATEWAY] );
294.  
295.  
296.  
297.   // 判断是否为默认路由
298.  
299.   if ( dest == anyaddr && gate ) {
300.     if ( arg != NULL ) {
301.       * ( int * ) arg = index;
302.       return 0;
303.     }
304.   }
305.   return 0;
306. }
307.  
308. static int nl_get_if_addr ( struct sockaddr_nl *snl, struct nlmsghdr *h, void *arg )
309. {
310.   int len;
311.   struct ifaddrmsg *ifa;
312.   struct rtattr *tb [IFA_MAX + 1];
313.   void *addr = NULL;
314.   void *broad = NULL;
315.   u_char flags = 0;
316.   char *label = NULL;
317. u32 ifa_addr, ifa_local;
318. char ifa_label[IFNAMSIZ + 1];
319.  
320.   ifa = NLMSG_DATA ( h );
321.   if ( ifa->ifa_family != AF_INET )
322.   return 0;
323.   
324.   if ( h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR )
325.     return 0;
326.  
327.   len = h->nlmsg_len - NLMSG_LENGTH ( sizeof ( struct ifaddrmsg ) );
328.   if ( len < 0 )
329.     return -1;
330.  
331.   memset ( tb, 0, sizeof tb );
332.  
333.   nl_parse_rtattr ( tb, IFA_MAX, IFA_RTA ( ifa ), len );
334.   
335.   if (tb[IFA_ADDRESS] == NULL)
336.  tb[IFA_ADDRESS] = tb[IFA_LOCAL];
337.   
338.   if ( tb[IFA_ADDRESS] )
339.   ifa_addr = *(u32 *) RTA_DATA ( tb[IFA_ADDRESS] );
340.   
341.   if ( tb[IFA_LOCAL] )
342.   ifa_local = *(u32 *) RTA_DATA ( tb[IFA_LOCAL] );
343.   
344.   if ( tb[IFA_LABEL] )
345.   strncpy( ifa_label, RTA_DATA ( tb[IFA_LABEL] ), IFNAMSIZ );  
346.   
347.  
348.   // 打印所有地址信息
349.   printf( \"addr=%08x loal=%08x name=%s\\n\",  
350.   ifa_addr,
351.   ifa_local,
352.   ifa_label );
353.   return 0;
354. }
355.  
356. int main()
357. {
358.   int ret;
359.   char if_name[PAGE_SIZE];
360.   char *p;
361.   struct nl_if_info if_info = { -1, \"eth0\" };
362.  
363.   ret = nl_socket ( &nl_cmd, 0 );
364.   if ( ret < 0 ) {
365.     return ret;
366.   }
367.   ret = nl_request ( AF_INET, RTM_GETROUTE, &nl_cmd );
368.   if ( ret < 0 ) {
369.     return ret;
370.   }
371.   ret = nl_parse_info ( nl_get_oif, &nl_cmd, &index_oif );
372.   if ( ret < 0 )
373.     return ret;
374.  
375.   printf ( \"oif=%08x \\n\", index_oif );
376.   if ( index_oif > 0 ) {
377.   p = if_indextoname ( index_oif, if_name );
378.   if ( p ) {
379.     printf ( \"interface=%s\\n\", p );
380.   }
381. }
382.  
383.   ret = nl_request ( AF_INET, RTM_GETADDR, &nl_cmd );
384.   if ( ret < 0 )
385.     return ret;
386.  
387.   ret = nl_parse_info ( nl_get_if_addr, &nl_cmd, &if_info );
388.   if ( ret < 0 )
389.     return ret;
390.   
391.  
392.   return 0;
393. }

#include <linux/types.h> #include <asm/types.h> #include <inttypes.h> #include <sys/file.h> #include <sys/user.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <linux/if.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <errno.h> typedef uint32_t u32; typedef uint16_t u16; struct nlsock { int sock; int seq; struct sockaddr_nl snl; char *name; } nl_cmd = { -1, 0, {0}, \"netlink-cmd\" }; static int index_oif = 0; struct nl_if_info { u32 addr; char *name; }; static int nl_socket ( struct nlsock *nl, unsigned long groups ) { int ret; struct sockaddr_nl snl; int sock; int namelen; sock = socket ( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE ); if ( sock < 0 ) { fprintf ( stderr, \"Can&#39;t open %s socket: %s\", nl->name, strerror ( errno ) ); return -1; } ret = fcntl ( sock, F_SETFL, O_NONBLOCK ); if ( ret < 0 ) { fprintf ( stderr, \"Can&#39;t set %s socket flags: %s\", nl->name, strerror ( errno ) ); close ( sock ); return -1; } memset ( &snl, 0, sizeof snl ); snl.nl_family = AF_NETLINK; snl.nl_groups = groups; /* Bind the socket to the netlink structure for anything. */ ret = bind ( sock, ( struct sockaddr * ) &snl, sizeof snl ); if ( ret < 0 ) { fprintf ( stderr, \"Can&#39;t bind %s socket to group 0x%x: %s\", nl->name, snl.nl_groups, strerror ( errno ) ); close ( sock ); return -1; } /* multiple netlink sockets will have different nl_pid */ namelen = sizeof snl; ret = getsockname ( sock, ( struct sockaddr * ) &snl, &namelen ); if ( ret < 0 || namelen != sizeof snl ) { fprintf ( stderr, \"Can&#39;t get %s socket name: %s\", nl->name, strerror ( errno ) ); close ( sock ); return -1; } nl->snl = snl; nl->sock = sock; return ret; } static int nl_request ( int family, int type, struct nlsock *nl ) { int ret; struct sockaddr_nl snl; struct { struct nlmsghdr nlh; struct rtgenmsg g; } req; /* Check netlink socket. */ if ( nl->sock < 0 ) { fprintf ( stderr, \"%s socket isn&#39;t active.\", nl->name ); return -1; } memset ( &snl, 0, sizeof snl ); snl.nl_family = AF_NETLINK; req.nlh.nlmsg_len = sizeof req; req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = ++nl->seq; req.g.rtgen_family = family; ret = sendto ( nl->sock, ( void* ) &req, sizeof req, 0, ( struct sockaddr* ) &snl, sizeof snl ); if ( ret < 0 ) { fprintf ( stderr, \"%s sendto failed: %s\", nl->name, strerror ( errno ) ); return -1; } return 0; } /* Receive message from netlink interface and pass those information to the given function. */ static int nl_parse_info ( int ( *filter ) ( struct sockaddr_nl *, struct nlmsghdr *, void * ), struct nlsock *nl, void *arg ) { int status; int ret = 0; int error; while ( 1 ) { char buf[4096]; struct iovec iov = { buf, sizeof buf }; struct sockaddr_nl snl; struct msghdr msg = { ( void* ) &snl, sizeof snl, &iov, 1, NULL, 0, 0}; struct nlmsghdr *h; status = recvmsg ( nl->sock, &msg, 0 ); if ( status < 0 ) { if ( errno == EINTR ) continue; if ( errno == EWOULDBLOCK || errno == EAGAIN ) break; fprintf ( stderr, \"%s recvmsg overrun\", nl->name ); continue; } if ( snl.nl_pid != 0 ) { fprintf ( stderr, \"Ignoring non kernel message from pid %u\", snl.nl_pid ); continue; } if ( status == 0 ) { fprintf ( stderr, \"%s EOF\", nl->name ); return -1; } if ( msg.msg_namelen != sizeof snl ) { fprintf ( stderr, \"%s sender address length error: length %d\", nl->name, msg.msg_namelen ); return -1; } for ( h = ( struct nlmsghdr * ) buf; NLMSG_OK ( h, status ); h = NLMSG_NEXT ( h, status ) ) { /* Finish of reading. */ if ( h->nlmsg_type == NLMSG_DONE ) return ret; /* Error handling. */ if ( h->nlmsg_type == NLMSG_ERROR ) { struct nlmsgerr *err = ( struct nlmsgerr * ) NLMSG_DATA ( h ); /* If the error field is zero, then this is an ACK */ if ( err->error == 0 ) { /* return if not a multipart message, otherwise continue */ if ( ! ( h->nlmsg_flags & NLM_F_MULTI ) ) { return 0; } continue; } if ( h->nlmsg_len < NLMSG_LENGTH ( sizeof ( struct nlmsgerr ) ) ) { fprintf ( stderr, \"%s error: message truncated\", nl->name ); return -1; } fprintf ( stderr, \"%s error: %s, type=%u, seq=%u, pid=%d\", nl->name, strerror ( -err->error ), err->msg.nlmsg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid ); /* ret = -1; continue; */ return -1; } /* skip unsolicited messages originating from command socket */ if ( nl != &nl_cmd && h->nlmsg_pid == nl_cmd.snl.nl_pid ) { continue; } error = ( *filter ) ( &snl, h, arg ); if ( error < 0 ) { fprintf ( stderr, \"%s filter function error\\n\", nl->name ); ret = error; } } /* After error care. */ if ( msg.msg_flags & MSG_TRUNC ) { fprintf ( stderr, \"%s error: message truncated\", nl->name ); continue; } if ( status ) { fprintf ( stderr, \"%s error: data remnant size %d\", nl->name, status ); return -1; } } return ret; } static void nl_parse_rtattr ( struct rtattr **tb, int max, struct rtattr *rta, int len ) { while ( RTA_OK ( rta, len ) ) { if ( rta->rta_type <= max ) tb[rta->rta_type] = rta; rta = RTA_NEXT ( rta,len ); } } static int nl_get_oif ( struct sockaddr_nl *snl, struct nlmsghdr *h, void *arg ) { int len; struct rtmsg *rtm; struct rtattr *tb [RTA_MAX + 1]; u_char flags = 0; char anyaddr[16] = {0}; int index; int table; void *dest; void *gate; rtm = NLMSG_DATA ( h ); if ( h->nlmsg_type != RTM_NEWROUTE ) return 0; if ( rtm->rtm_type != RTN_UNICAST ) return 0; table = rtm->rtm_table; len = h->nlmsg_len - NLMSG_LENGTH ( sizeof ( struct rtmsg ) ); if ( len < 0 ) return -1; memset ( tb, 0, sizeof tb ); nl_parse_rtattr ( tb, RTA_MAX, RTM_RTA ( rtm ), len ); if ( rtm->rtm_flags & RTM_F_CLONED ) return 0; if ( rtm->rtm_protocol == RTPROT_REDIRECT ) return 0; if ( rtm->rtm_protocol == RTPROT_KERNEL ) return 0; if ( rtm->rtm_src_len != 0 ) return 0; // 这里可以对所有路由进行识别 // 取得out interface index if ( tb[RTA_OIF] ) { index = * ( int * ) RTA_DATA ( tb[RTA_OIF] ); } if ( tb[RTA_DST] ) dest = RTA_DATA ( tb[RTA_DST] ); else dest = anyaddr; /* Multipath treatment is needed. */ if ( tb[RTA_GATEWAY] ) gate = RTA_DATA ( tb[RTA_GATEWAY] ); // 判断是否为默认路由 if ( dest == anyaddr && gate ) { if ( arg != NULL ) { * ( int * ) arg = index; return 0; } } return 0; } static int nl_get_if_addr ( struct sockaddr_nl *snl, struct nlmsghdr *h, void *arg ) { int len; struct ifaddrmsg *ifa; struct rtattr *tb [IFA_MAX + 1]; void *addr = NULL; void *broad = NULL; u_char flags = 0; char *label = NULL; u32 ifa_addr, ifa_local; char ifa_label[IFNAMSIZ + 1]; ifa = NLMSG_DATA ( h ); if ( ifa->ifa_family != AF_INET ) return 0; if ( h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR ) return 0; len = h->nlmsg_len - NLMSG_LENGTH ( sizeof ( struct ifaddrmsg ) ); if ( len < 0 ) return -1; memset ( tb, 0, sizeof tb ); nl_parse_rtattr ( tb, IFA_MAX, IFA_RTA ( ifa ), len ); if (tb[IFA_ADDRESS] == NULL) tb[IFA_ADDRESS] = tb[IFA_LOCAL]; if ( tb[IFA_ADDRESS] ) ifa_addr = *(u32 *) RTA_DATA ( tb[IFA_ADDRESS] ); if ( tb[IFA_LOCAL] ) ifa_local = *(u32 *) RTA_DATA ( tb[IFA_LOCAL] ); if ( tb[IFA_LABEL] ) strncpy( ifa_label, RTA_DATA ( tb[IFA_LABEL] ), IFNAMSIZ ); // 打印所有地址信息 printf( \"addr=%08x loal=%08x name=%s\\n\", ifa_addr, ifa_local, ifa_label ); return 0; } int main() { int ret; char if_name[PAGE_SIZE]; char *p; struct nl_if_info if_info = { -1, \"eth0\" }; ret = nl_socket ( &nl_cmd, 0 ); if ( ret < 0 ) { return ret; } ret = nl_request ( AF_INET, RTM_GETROUTE, &nl_cmd ); if ( ret < 0 ) { return ret; } ret = nl_parse_info ( nl_get_oif, &nl_cmd, &index_oif ); if ( ret < 0 ) return ret; printf ( \"oif=%08x \\n\", index_oif ); if ( index_oif > 0 ) { p = if_indextoname ( index_oif, if_name ); if ( p ) { printf ( \"interface=%s\\n\", p ); } } ret = nl_request ( AF_INET, RTM_GETADDR, &nl_cmd ); if ( ret < 0 ) return ret; ret = nl_parse_info ( nl_get_if_addr, &nl_cmd, &if_info ); if ( ret < 0 ) return ret; return 0; }  

参考:

1> RFC3549 - Linux Netlink as an IP Services Protocol

2> Zebra Source code

3> netlink(7) - Linux man page
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|网上读书园地

GMT+8, 2024-11-25 20:01 , Processed in 0.131715 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表