xref: /aosp_15_r20/external/ethtool/libmnl/examples/rtnl/rtnl-route-event.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
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