9 #include <libmnl/libmnl.h>
11 #include <linux/if_link.h>
12 #include <linux/rtnetlink.h>
14 static int data_attr_cb2(
const struct nlattr *attr,
void *data)
16 const struct nlattr **tb = data;
19 if (mnl_attr_type_valid(attr, RTAX_MAX) < 0)
22 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
23 perror(
"mnl_attr_validate");
27 tb[mnl_attr_get_type(attr)] = attr;
31 static void attributes_show_ipv4(
struct nlattr *tb[])
34 printf(
"table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
37 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
38 printf(
"dst=%s ", inet_ntoa(*addr));
41 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
42 printf(
"src=%s ", inet_ntoa(*addr));
45 printf(
"oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
48 printf(
"flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
50 if (tb[RTA_PREFSRC]) {
51 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
52 printf(
"prefsrc=%s ", inet_ntoa(*addr));
54 if (tb[RTA_GATEWAY]) {
55 struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
56 printf(
"gw=%s ", inet_ntoa(*addr));
58 if (tb[RTA_PRIORITY]) {
59 printf(
"prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
61 if (tb[RTA_METRICS]) {
63 struct nlattr *tbx[RTAX_MAX+1] = {};
65 mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
67 for (i=0; i<RTAX_MAX; i++) {
69 printf(
"metrics[%d]=%u ",
70 i, mnl_attr_get_u32(tbx[i]));
77 static const char *inet6_ntoa(
struct in6_addr in6)
79 static char buf[INET6_ADDRSTRLEN];
81 return inet_ntop(AF_INET6, &in6.s6_addr, buf,
sizeof(buf));
84 static void attributes_show_ipv6(
struct nlattr *tb[])
87 printf(
"table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
90 struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
91 printf(
"dst=%s ", inet6_ntoa(*addr));
94 struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
95 printf(
"src=%s ", inet6_ntoa(*addr));
98 printf(
"oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
101 printf(
"flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
103 if (tb[RTA_PREFSRC]) {
104 struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
105 printf(
"prefsrc=%s ", inet6_ntoa(*addr));
107 if (tb[RTA_GATEWAY]) {
108 struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
109 printf(
"gw=%s ", inet6_ntoa(*addr));
111 if (tb[RTA_PRIORITY]) {
112 printf(
"prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
114 if (tb[RTA_METRICS]) {
116 struct nlattr *tbx[RTAX_MAX+1] = {};
118 mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
120 for (i=0; i<RTAX_MAX; i++) {
122 printf(
"metrics[%d]=%u ",
123 i, mnl_attr_get_u32(tbx[i]));
129 static int data_ipv4_attr_cb(
const struct nlattr *attr,
void *data)
131 const struct nlattr **tb = data;
132 int type = mnl_attr_get_type(attr);
135 if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
147 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
148 perror(
"mnl_attr_validate");
153 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
154 perror(
"mnl_attr_validate");
163 static int data_ipv6_attr_cb(
const struct nlattr *attr,
void *data)
165 const struct nlattr **tb = data;
166 int type = mnl_attr_get_type(attr);
169 if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
177 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
178 perror(
"mnl_attr_validate");
186 if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
187 sizeof(
struct in6_addr)) < 0) {
188 perror(
"mnl_attr_validate2");
193 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
194 perror(
"mnl_attr_validate");
203 static int data_cb(
const struct nlmsghdr *nlh,
void *data)
205 struct nlattr *tb[RTA_MAX+1] = {};
206 struct rtmsg *rm = mnl_nlmsg_get_payload(nlh);
209 printf(
"family=%u ", rm->rtm_family);
212 printf(
"dst_len=%u ", rm->rtm_dst_len);
215 printf(
"src_len=%u ", rm->rtm_src_len);
218 printf(
"tos=%u ", rm->rtm_tos);
233 printf(
"table=%u ", rm->rtm_table);
250 printf(
"type=%u ", rm->rtm_type);
262 printf(
"scope=%u ", rm->rtm_scope);
274 printf(
"proto=%u ", rm->rtm_protocol);
282 printf(
"flags=%x ", rm->rtm_flags);
284 switch(rm->rtm_family) {
286 mnl_attr_parse(nlh,
sizeof(*rm), data_ipv4_attr_cb, tb);
287 attributes_show_ipv4(tb);
290 mnl_attr_parse(nlh,
sizeof(*rm), data_ipv6_attr_cb, tb);
291 attributes_show_ipv6(tb);
299 int main(
int argc,
char *argv[])
302 char buf[MNL_SOCKET_BUFFER_SIZE];
303 struct nlmsghdr *nlh;
306 unsigned int seq, portid;
309 fprintf(stderr,
"Usage: %s <inet|inet6>\n", argv[0]);
313 nlh = mnl_nlmsg_put_header(buf);
314 nlh->nlmsg_type = RTM_GETROUTE;
315 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
316 nlh->nlmsg_seq = seq = time(NULL);
317 rtm = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct rtmsg));
319 if (strcmp(argv[1],
"inet") == 0)
320 rtm->rtm_family = AF_INET;
321 else if (strcmp(argv[1],
"inet6") == 0)
322 rtm->rtm_family = AF_INET6;
324 nl = mnl_socket_open(NETLINK_ROUTE);
326 perror(
"mnl_socket_open");
330 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
331 perror(
"mnl_socket_bind");
334 portid = mnl_socket_get_portid(nl);
336 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
337 perror(
"mnl_socket_sendto");
341 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
343 ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
344 if (ret <= MNL_CB_STOP)
346 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
353 mnl_socket_close(nl);