1*1b481fc3SMaciej Żenczykowski /* This example is placed in the public domain. */
2*1b481fc3SMaciej Żenczykowski #include <stdio.h>
3*1b481fc3SMaciej Żenczykowski #include <stdlib.h>
4*1b481fc3SMaciej Żenczykowski #include <string.h>
5*1b481fc3SMaciej Żenczykowski #include <unistd.h>
6*1b481fc3SMaciej Żenczykowski #include <time.h>
7*1b481fc3SMaciej Żenczykowski #include <arpa/inet.h>
8*1b481fc3SMaciej Żenczykowski
9*1b481fc3SMaciej Żenczykowski #include <libmnl/libmnl.h>
10*1b481fc3SMaciej Żenczykowski #include <linux/if.h>
11*1b481fc3SMaciej Żenczykowski #include <linux/if_link.h>
12*1b481fc3SMaciej Żenczykowski #include <linux/rtnetlink.h>
13*1b481fc3SMaciej Żenczykowski
data_attr_cb2(const struct nlattr * attr,void * data)14*1b481fc3SMaciej Żenczykowski static int data_attr_cb2(const struct nlattr *attr, void *data)
15*1b481fc3SMaciej Żenczykowski {
16*1b481fc3SMaciej Żenczykowski const struct nlattr **tb = data;
17*1b481fc3SMaciej Żenczykowski
18*1b481fc3SMaciej Żenczykowski /* skip unsupported attribute in user-space */
19*1b481fc3SMaciej Żenczykowski if (mnl_attr_type_valid(attr, RTAX_MAX) < 0)
20*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
21*1b481fc3SMaciej Żenczykowski
22*1b481fc3SMaciej Żenczykowski if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
23*1b481fc3SMaciej Żenczykowski perror("mnl_attr_validate");
24*1b481fc3SMaciej Żenczykowski return MNL_CB_ERROR;
25*1b481fc3SMaciej Żenczykowski }
26*1b481fc3SMaciej Żenczykowski
27*1b481fc3SMaciej Żenczykowski tb[mnl_attr_get_type(attr)] = attr;
28*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
29*1b481fc3SMaciej Żenczykowski }
30*1b481fc3SMaciej Żenczykowski
attributes_show_ipv4(struct nlattr * tb[])31*1b481fc3SMaciej Żenczykowski static void attributes_show_ipv4(struct nlattr *tb[])
32*1b481fc3SMaciej Żenczykowski {
33*1b481fc3SMaciej Żenczykowski if (tb[RTA_TABLE]) {
34*1b481fc3SMaciej Żenczykowski printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
35*1b481fc3SMaciej Żenczykowski }
36*1b481fc3SMaciej Żenczykowski if (tb[RTA_DST]) {
37*1b481fc3SMaciej Żenczykowski struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
38*1b481fc3SMaciej Żenczykowski printf("dst=%s ", inet_ntoa(*addr));
39*1b481fc3SMaciej Żenczykowski }
40*1b481fc3SMaciej Żenczykowski if (tb[RTA_SRC]) {
41*1b481fc3SMaciej Żenczykowski struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
42*1b481fc3SMaciej Żenczykowski printf("src=%s ", inet_ntoa(*addr));
43*1b481fc3SMaciej Żenczykowski }
44*1b481fc3SMaciej Żenczykowski if (tb[RTA_OIF]) {
45*1b481fc3SMaciej Żenczykowski printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
46*1b481fc3SMaciej Żenczykowski }
47*1b481fc3SMaciej Żenczykowski if (tb[RTA_FLOW]) {
48*1b481fc3SMaciej Żenczykowski printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
49*1b481fc3SMaciej Żenczykowski }
50*1b481fc3SMaciej Żenczykowski if (tb[RTA_PREFSRC]) {
51*1b481fc3SMaciej Żenczykowski struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
52*1b481fc3SMaciej Żenczykowski printf("prefsrc=%s ", inet_ntoa(*addr));
53*1b481fc3SMaciej Żenczykowski }
54*1b481fc3SMaciej Żenczykowski if (tb[RTA_GATEWAY]) {
55*1b481fc3SMaciej Żenczykowski struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
56*1b481fc3SMaciej Żenczykowski printf("gw=%s ", inet_ntoa(*addr));
57*1b481fc3SMaciej Żenczykowski }
58*1b481fc3SMaciej Żenczykowski if (tb[RTA_PRIORITY]) {
59*1b481fc3SMaciej Żenczykowski printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
60*1b481fc3SMaciej Żenczykowski }
61*1b481fc3SMaciej Żenczykowski if (tb[RTA_METRICS]) {
62*1b481fc3SMaciej Żenczykowski int i;
63*1b481fc3SMaciej Żenczykowski struct nlattr *tbx[RTAX_MAX+1] = {};
64*1b481fc3SMaciej Żenczykowski
65*1b481fc3SMaciej Żenczykowski mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
66*1b481fc3SMaciej Żenczykowski
67*1b481fc3SMaciej Żenczykowski for (i=0; i<RTAX_MAX; i++) {
68*1b481fc3SMaciej Żenczykowski if (tbx[i]) {
69*1b481fc3SMaciej Żenczykowski printf("metrics[%d]=%u ",
70*1b481fc3SMaciej Żenczykowski i, mnl_attr_get_u32(tbx[i]));
71*1b481fc3SMaciej Żenczykowski }
72*1b481fc3SMaciej Żenczykowski }
73*1b481fc3SMaciej Żenczykowski }
74*1b481fc3SMaciej Żenczykowski }
75*1b481fc3SMaciej Żenczykowski
76*1b481fc3SMaciej Żenczykowski /* like inet_ntoa(), not reentrant */
inet6_ntoa(struct in6_addr in6)77*1b481fc3SMaciej Żenczykowski static const char *inet6_ntoa(struct in6_addr in6)
78*1b481fc3SMaciej Żenczykowski {
79*1b481fc3SMaciej Żenczykowski static char buf[INET6_ADDRSTRLEN];
80*1b481fc3SMaciej Żenczykowski
81*1b481fc3SMaciej Żenczykowski return inet_ntop(AF_INET6, &in6.s6_addr, buf, sizeof(buf));
82*1b481fc3SMaciej Żenczykowski }
83*1b481fc3SMaciej Żenczykowski
attributes_show_ipv6(struct nlattr * tb[])84*1b481fc3SMaciej Żenczykowski static void attributes_show_ipv6(struct nlattr *tb[])
85*1b481fc3SMaciej Żenczykowski {
86*1b481fc3SMaciej Żenczykowski if (tb[RTA_TABLE]) {
87*1b481fc3SMaciej Żenczykowski printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
88*1b481fc3SMaciej Żenczykowski }
89*1b481fc3SMaciej Żenczykowski if (tb[RTA_DST]) {
90*1b481fc3SMaciej Żenczykowski struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
91*1b481fc3SMaciej Żenczykowski printf("dst=%s ", inet6_ntoa(*addr));
92*1b481fc3SMaciej Żenczykowski }
93*1b481fc3SMaciej Żenczykowski if (tb[RTA_SRC]) {
94*1b481fc3SMaciej Żenczykowski struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
95*1b481fc3SMaciej Żenczykowski printf("src=%s ", inet6_ntoa(*addr));
96*1b481fc3SMaciej Żenczykowski }
97*1b481fc3SMaciej Żenczykowski if (tb[RTA_OIF]) {
98*1b481fc3SMaciej Żenczykowski printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
99*1b481fc3SMaciej Żenczykowski }
100*1b481fc3SMaciej Żenczykowski if (tb[RTA_FLOW]) {
101*1b481fc3SMaciej Żenczykowski printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
102*1b481fc3SMaciej Żenczykowski }
103*1b481fc3SMaciej Żenczykowski if (tb[RTA_PREFSRC]) {
104*1b481fc3SMaciej Żenczykowski struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
105*1b481fc3SMaciej Żenczykowski printf("prefsrc=%s ", inet6_ntoa(*addr));
106*1b481fc3SMaciej Żenczykowski }
107*1b481fc3SMaciej Żenczykowski if (tb[RTA_GATEWAY]) {
108*1b481fc3SMaciej Żenczykowski struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
109*1b481fc3SMaciej Żenczykowski printf("gw=%s ", inet6_ntoa(*addr));
110*1b481fc3SMaciej Żenczykowski }
111*1b481fc3SMaciej Żenczykowski if (tb[RTA_PRIORITY]) {
112*1b481fc3SMaciej Żenczykowski printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
113*1b481fc3SMaciej Żenczykowski }
114*1b481fc3SMaciej Żenczykowski if (tb[RTA_METRICS]) {
115*1b481fc3SMaciej Żenczykowski int i;
116*1b481fc3SMaciej Żenczykowski struct nlattr *tbx[RTAX_MAX+1] = {};
117*1b481fc3SMaciej Żenczykowski
118*1b481fc3SMaciej Żenczykowski mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
119*1b481fc3SMaciej Żenczykowski
120*1b481fc3SMaciej Żenczykowski for (i=0; i<RTAX_MAX; i++) {
121*1b481fc3SMaciej Żenczykowski if (tbx[i]) {
122*1b481fc3SMaciej Żenczykowski printf("metrics[%d]=%u ",
123*1b481fc3SMaciej Żenczykowski i, mnl_attr_get_u32(tbx[i]));
124*1b481fc3SMaciej Żenczykowski }
125*1b481fc3SMaciej Żenczykowski }
126*1b481fc3SMaciej Żenczykowski }
127*1b481fc3SMaciej Żenczykowski }
128*1b481fc3SMaciej Żenczykowski
data_ipv4_attr_cb(const struct nlattr * attr,void * data)129*1b481fc3SMaciej Żenczykowski static int data_ipv4_attr_cb(const struct nlattr *attr, void *data)
130*1b481fc3SMaciej Żenczykowski {
131*1b481fc3SMaciej Żenczykowski const struct nlattr **tb = data;
132*1b481fc3SMaciej Żenczykowski int type = mnl_attr_get_type(attr);
133*1b481fc3SMaciej Żenczykowski
134*1b481fc3SMaciej Żenczykowski /* skip unsupported attribute in user-space */
135*1b481fc3SMaciej Żenczykowski if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
136*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
137*1b481fc3SMaciej Żenczykowski
138*1b481fc3SMaciej Żenczykowski switch(type) {
139*1b481fc3SMaciej Żenczykowski case RTA_TABLE:
140*1b481fc3SMaciej Żenczykowski case RTA_DST:
141*1b481fc3SMaciej Żenczykowski case RTA_SRC:
142*1b481fc3SMaciej Żenczykowski case RTA_OIF:
143*1b481fc3SMaciej Żenczykowski case RTA_FLOW:
144*1b481fc3SMaciej Żenczykowski case RTA_PREFSRC:
145*1b481fc3SMaciej Żenczykowski case RTA_GATEWAY:
146*1b481fc3SMaciej Żenczykowski case RTA_PRIORITY:
147*1b481fc3SMaciej Żenczykowski if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
148*1b481fc3SMaciej Żenczykowski perror("mnl_attr_validate");
149*1b481fc3SMaciej Żenczykowski return MNL_CB_ERROR;
150*1b481fc3SMaciej Żenczykowski }
151*1b481fc3SMaciej Żenczykowski break;
152*1b481fc3SMaciej Żenczykowski case RTA_METRICS:
153*1b481fc3SMaciej Żenczykowski if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
154*1b481fc3SMaciej Żenczykowski perror("mnl_attr_validate");
155*1b481fc3SMaciej Żenczykowski return MNL_CB_ERROR;
156*1b481fc3SMaciej Żenczykowski }
157*1b481fc3SMaciej Żenczykowski break;
158*1b481fc3SMaciej Żenczykowski }
159*1b481fc3SMaciej Żenczykowski tb[type] = attr;
160*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
161*1b481fc3SMaciej Żenczykowski }
162*1b481fc3SMaciej Żenczykowski
data_ipv6_attr_cb(const struct nlattr * attr,void * data)163*1b481fc3SMaciej Żenczykowski static int data_ipv6_attr_cb(const struct nlattr *attr, void *data)
164*1b481fc3SMaciej Żenczykowski {
165*1b481fc3SMaciej Żenczykowski const struct nlattr **tb = data;
166*1b481fc3SMaciej Żenczykowski int type = mnl_attr_get_type(attr);
167*1b481fc3SMaciej Żenczykowski
168*1b481fc3SMaciej Żenczykowski /* skip unsupported attribute in user-space */
169*1b481fc3SMaciej Żenczykowski if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
170*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
171*1b481fc3SMaciej Żenczykowski
172*1b481fc3SMaciej Żenczykowski switch(type) {
173*1b481fc3SMaciej Żenczykowski case RTA_TABLE:
174*1b481fc3SMaciej Żenczykowski case RTA_OIF:
175*1b481fc3SMaciej Żenczykowski case RTA_FLOW:
176*1b481fc3SMaciej Żenczykowski case RTA_PRIORITY:
177*1b481fc3SMaciej Żenczykowski if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
178*1b481fc3SMaciej Żenczykowski perror("mnl_attr_validate");
179*1b481fc3SMaciej Żenczykowski return MNL_CB_ERROR;
180*1b481fc3SMaciej Żenczykowski }
181*1b481fc3SMaciej Żenczykowski break;
182*1b481fc3SMaciej Żenczykowski case RTA_DST:
183*1b481fc3SMaciej Żenczykowski case RTA_SRC:
184*1b481fc3SMaciej Żenczykowski case RTA_PREFSRC:
185*1b481fc3SMaciej Żenczykowski case RTA_GATEWAY:
186*1b481fc3SMaciej Żenczykowski if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
187*1b481fc3SMaciej Żenczykowski sizeof(struct in6_addr)) < 0) {
188*1b481fc3SMaciej Żenczykowski perror("mnl_attr_validate2");
189*1b481fc3SMaciej Żenczykowski return MNL_CB_ERROR;
190*1b481fc3SMaciej Żenczykowski }
191*1b481fc3SMaciej Żenczykowski break;
192*1b481fc3SMaciej Żenczykowski case RTA_METRICS:
193*1b481fc3SMaciej Żenczykowski if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
194*1b481fc3SMaciej Żenczykowski perror("mnl_attr_validate");
195*1b481fc3SMaciej Żenczykowski return MNL_CB_ERROR;
196*1b481fc3SMaciej Żenczykowski }
197*1b481fc3SMaciej Żenczykowski break;
198*1b481fc3SMaciej Żenczykowski }
199*1b481fc3SMaciej Żenczykowski tb[type] = attr;
200*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
201*1b481fc3SMaciej Żenczykowski }
202*1b481fc3SMaciej Żenczykowski
data_cb(const struct nlmsghdr * nlh,void * data)203*1b481fc3SMaciej Żenczykowski static int data_cb(const struct nlmsghdr *nlh, void *data)
204*1b481fc3SMaciej Żenczykowski {
205*1b481fc3SMaciej Żenczykowski struct nlattr *tb[RTA_MAX+1] = {};
206*1b481fc3SMaciej Żenczykowski struct rtmsg *rm = mnl_nlmsg_get_payload(nlh);
207*1b481fc3SMaciej Żenczykowski
208*1b481fc3SMaciej Żenczykowski switch(nlh->nlmsg_type) {
209*1b481fc3SMaciej Żenczykowski case RTM_NEWROUTE:
210*1b481fc3SMaciej Żenczykowski printf("[NEW] ");
211*1b481fc3SMaciej Żenczykowski break;
212*1b481fc3SMaciej Żenczykowski case RTM_DELROUTE:
213*1b481fc3SMaciej Żenczykowski printf("[DEL] ");
214*1b481fc3SMaciej Żenczykowski break;
215*1b481fc3SMaciej Żenczykowski }
216*1b481fc3SMaciej Żenczykowski
217*1b481fc3SMaciej Żenczykowski /* protocol family = AF_INET | AF_INET6 */
218*1b481fc3SMaciej Żenczykowski printf("family=%u ", rm->rtm_family);
219*1b481fc3SMaciej Żenczykowski
220*1b481fc3SMaciej Żenczykowski /* destination CIDR, eg. 24 or 32 for IPv4 */
221*1b481fc3SMaciej Żenczykowski printf("dst_len=%u ", rm->rtm_dst_len);
222*1b481fc3SMaciej Żenczykowski
223*1b481fc3SMaciej Żenczykowski /* source CIDR */
224*1b481fc3SMaciej Żenczykowski printf("src_len=%u ", rm->rtm_src_len);
225*1b481fc3SMaciej Żenczykowski
226*1b481fc3SMaciej Żenczykowski /* type of service (TOS), eg. 0 */
227*1b481fc3SMaciej Żenczykowski printf("tos=%u ", rm->rtm_tos);
228*1b481fc3SMaciej Żenczykowski
229*1b481fc3SMaciej Żenczykowski /* table id:
230*1b481fc3SMaciej Żenczykowski * RT_TABLE_UNSPEC = 0
231*1b481fc3SMaciej Żenczykowski *
232*1b481fc3SMaciej Żenczykowski * ... user defined values ...
233*1b481fc3SMaciej Żenczykowski *
234*1b481fc3SMaciej Żenczykowski * RT_TABLE_COMPAT = 252
235*1b481fc3SMaciej Żenczykowski * RT_TABLE_DEFAULT = 253
236*1b481fc3SMaciej Żenczykowski * RT_TABLE_MAIN = 254
237*1b481fc3SMaciej Żenczykowski * RT_TABLE_LOCAL = 255
238*1b481fc3SMaciej Żenczykowski * RT_TABLE_MAX = 0xFFFFFFFF
239*1b481fc3SMaciej Żenczykowski *
240*1b481fc3SMaciej Żenczykowski * Synonimous attribute: RTA_TABLE.
241*1b481fc3SMaciej Żenczykowski */
242*1b481fc3SMaciej Żenczykowski printf("table=%u ", rm->rtm_table);
243*1b481fc3SMaciej Żenczykowski
244*1b481fc3SMaciej Żenczykowski /* type:
245*1b481fc3SMaciej Żenczykowski * RTN_UNSPEC = 0
246*1b481fc3SMaciej Żenczykowski * RTN_UNICAST = 1
247*1b481fc3SMaciej Żenczykowski * RTN_LOCAL = 2
248*1b481fc3SMaciej Żenczykowski * RTN_BROADCAST = 3
249*1b481fc3SMaciej Żenczykowski * RTN_ANYCAST = 4
250*1b481fc3SMaciej Żenczykowski * RTN_MULTICAST = 5
251*1b481fc3SMaciej Żenczykowski * RTN_BLACKHOLE = 6
252*1b481fc3SMaciej Żenczykowski * RTN_UNREACHABLE = 7
253*1b481fc3SMaciej Żenczykowski * RTN_PROHIBIT = 8
254*1b481fc3SMaciej Żenczykowski * RTN_THROW = 9
255*1b481fc3SMaciej Żenczykowski * RTN_NAT = 10
256*1b481fc3SMaciej Żenczykowski * RTN_XRESOLVE = 11
257*1b481fc3SMaciej Żenczykowski * __RTN_MAX = 12
258*1b481fc3SMaciej Żenczykowski */
259*1b481fc3SMaciej Żenczykowski printf("type=%u ", rm->rtm_type);
260*1b481fc3SMaciej Żenczykowski
261*1b481fc3SMaciej Żenczykowski /* scope:
262*1b481fc3SMaciej Żenczykowski * RT_SCOPE_UNIVERSE = 0 : everywhere in the universe
263*1b481fc3SMaciej Żenczykowski *
264*1b481fc3SMaciej Żenczykowski * ... user defined values ...
265*1b481fc3SMaciej Żenczykowski *
266*1b481fc3SMaciej Żenczykowski * RT_SCOPE_SITE = 200
267*1b481fc3SMaciej Żenczykowski * RT_SCOPE_LINK = 253 : destination attached to link
268*1b481fc3SMaciej Żenczykowski * RT_SCOPE_HOST = 254 : local address
269*1b481fc3SMaciej Żenczykowski * RT_SCOPE_NOWHERE = 255 : not existing destination
270*1b481fc3SMaciej Żenczykowski */
271*1b481fc3SMaciej Żenczykowski printf("scope=%u ", rm->rtm_scope);
272*1b481fc3SMaciej Żenczykowski
273*1b481fc3SMaciej Żenczykowski /* protocol:
274*1b481fc3SMaciej Żenczykowski * RTPROT_UNSPEC = 0
275*1b481fc3SMaciej Żenczykowski * RTPROT_REDIRECT = 1
276*1b481fc3SMaciej Żenczykowski * RTPROT_KERNEL = 2 : route installed by kernel
277*1b481fc3SMaciej Żenczykowski * RTPROT_BOOT = 3 : route installed during boot
278*1b481fc3SMaciej Żenczykowski * RTPROT_STATIC = 4 : route installed by administrator
279*1b481fc3SMaciej Żenczykowski *
280*1b481fc3SMaciej Żenczykowski * Values >= RTPROT_STATIC are not interpreted by kernel, they are
281*1b481fc3SMaciej Żenczykowski * just user-defined.
282*1b481fc3SMaciej Żenczykowski */
283*1b481fc3SMaciej Żenczykowski printf("proto=%u ", rm->rtm_protocol);
284*1b481fc3SMaciej Żenczykowski
285*1b481fc3SMaciej Żenczykowski /* flags:
286*1b481fc3SMaciej Żenczykowski * RTM_F_NOTIFY = 0x100: notify user of route change
287*1b481fc3SMaciej Żenczykowski * RTM_F_CLONED = 0x200: this route is cloned
288*1b481fc3SMaciej Żenczykowski * RTM_F_EQUALIZE = 0x400: Multipath equalizer: NI
289*1b481fc3SMaciej Żenczykowski * RTM_F_PREFIX = 0x800: Prefix addresses
290*1b481fc3SMaciej Żenczykowski */
291*1b481fc3SMaciej Żenczykowski printf("flags=%x ", rm->rtm_flags);
292*1b481fc3SMaciej Żenczykowski
293*1b481fc3SMaciej Żenczykowski switch(rm->rtm_family) {
294*1b481fc3SMaciej Żenczykowski case AF_INET:
295*1b481fc3SMaciej Żenczykowski mnl_attr_parse(nlh, sizeof(*rm), data_ipv4_attr_cb, tb);
296*1b481fc3SMaciej Żenczykowski attributes_show_ipv4(tb);
297*1b481fc3SMaciej Żenczykowski break;
298*1b481fc3SMaciej Żenczykowski case AF_INET6:
299*1b481fc3SMaciej Żenczykowski mnl_attr_parse(nlh, sizeof(*rm), data_ipv6_attr_cb, tb);
300*1b481fc3SMaciej Żenczykowski attributes_show_ipv6(tb);
301*1b481fc3SMaciej Żenczykowski break;
302*1b481fc3SMaciej Żenczykowski }
303*1b481fc3SMaciej Żenczykowski
304*1b481fc3SMaciej Żenczykowski printf("\n");
305*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
306*1b481fc3SMaciej Żenczykowski }
307*1b481fc3SMaciej Żenczykowski
main(int argc,char * argv[])308*1b481fc3SMaciej Żenczykowski int main(int argc, char *argv[])
309*1b481fc3SMaciej Żenczykowski {
310*1b481fc3SMaciej Żenczykowski struct mnl_socket *nl;
311*1b481fc3SMaciej Żenczykowski char buf[MNL_SOCKET_BUFFER_SIZE];
312*1b481fc3SMaciej Żenczykowski int ret;
313*1b481fc3SMaciej Żenczykowski
314*1b481fc3SMaciej Żenczykowski nl = mnl_socket_open(NETLINK_ROUTE);
315*1b481fc3SMaciej Żenczykowski if (nl == NULL) {
316*1b481fc3SMaciej Żenczykowski perror("mnl_socket_open");
317*1b481fc3SMaciej Żenczykowski exit(EXIT_FAILURE);
318*1b481fc3SMaciej Żenczykowski }
319*1b481fc3SMaciej Żenczykowski
320*1b481fc3SMaciej Żenczykowski if (mnl_socket_bind(nl, RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE,
321*1b481fc3SMaciej Żenczykowski MNL_SOCKET_AUTOPID) < 0) {
322*1b481fc3SMaciej Żenczykowski perror("mnl_socket_bind");
323*1b481fc3SMaciej Żenczykowski exit(EXIT_FAILURE);
324*1b481fc3SMaciej Żenczykowski }
325*1b481fc3SMaciej Żenczykowski
326*1b481fc3SMaciej Żenczykowski ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
327*1b481fc3SMaciej Żenczykowski while (ret > 0) {
328*1b481fc3SMaciej Żenczykowski ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
329*1b481fc3SMaciej Żenczykowski if (ret <= MNL_CB_STOP)
330*1b481fc3SMaciej Żenczykowski break;
331*1b481fc3SMaciej Żenczykowski ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
332*1b481fc3SMaciej Żenczykowski }
333*1b481fc3SMaciej Żenczykowski if (ret == -1) {
334*1b481fc3SMaciej Żenczykowski perror("error");
335*1b481fc3SMaciej Żenczykowski exit(EXIT_FAILURE);
336*1b481fc3SMaciej Żenczykowski }
337*1b481fc3SMaciej Żenczykowski
338*1b481fc3SMaciej Żenczykowski mnl_socket_close(nl);
339*1b481fc3SMaciej Żenczykowski
340*1b481fc3SMaciej Żenczykowski return 0;
341*1b481fc3SMaciej Żenczykowski }
342