From 089d5e1c6a4fcd6615b02866b760f2d7b4084a08 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 8 Sep 2010 13:04:35 +0200 Subject: examples: put examples files into specific directories put examples files into specific directories according to the Netlink bus they work with. And minor update in the readme file Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/Makefile.am | 35 ++++++ examples/rtnl/rtnl-link-dump.c | 117 +++++++++++++++++++ examples/rtnl/rtnl-link-dump2.c | 108 ++++++++++++++++++ examples/rtnl/rtnl-link-dump3.c | 108 ++++++++++++++++++ examples/rtnl/rtnl-link-event.c | 100 ++++++++++++++++ examples/rtnl/rtnl-link-set.c | 88 ++++++++++++++ examples/rtnl/rtnl-route-add.c | 99 ++++++++++++++++ examples/rtnl/rtnl-route-dump.c | 247 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 902 insertions(+) create mode 100644 examples/rtnl/Makefile.am create mode 100644 examples/rtnl/rtnl-link-dump.c create mode 100644 examples/rtnl/rtnl-link-dump2.c create mode 100644 examples/rtnl/rtnl-link-dump3.c create mode 100644 examples/rtnl/rtnl-link-event.c create mode 100644 examples/rtnl/rtnl-link-set.c create mode 100644 examples/rtnl/rtnl-route-add.c create mode 100644 examples/rtnl/rtnl-route-dump.c (limited to 'examples/rtnl') diff --git a/examples/rtnl/Makefile.am b/examples/rtnl/Makefile.am new file mode 100644 index 0000000..9f0600d --- /dev/null +++ b/examples/rtnl/Makefile.am @@ -0,0 +1,35 @@ +include $(top_srcdir)/Make_global.am + +check_PROGRAMS = rtnl-link-dump rtnl-link-dump2 rtnl-link-dump3 \ + rtnl-link-event \ + rtnl-link-set \ + rtnl-route-add \ + rtnl-route-dump + +rtnl_link_dump_SOURCES = rtnl-link-dump.c +rtnl_link_dump_LDADD = ../../src/libmnl.la +rtnl_link_dump_LDFLAGS = -dynamic -ldl + +rtnl_link_dump2_SOURCES = rtnl-link-dump2.c +rtnl_link_dump2_LDADD = ../../src/libmnl.la +rtnl_link_dump2_LDFLAGS = -dynamic -ldl + +rtnl_link_dump3_SOURCES = rtnl-link-dump3.c +rtnl_link_dump3_LDADD = ../../src/libmnl.la +rtnl_link_dump3_LDFLAGS = -dynamic -ldl + +rtnl_route_add_SOURCES = rtnl-route-add.c +rtnl_route_add_LDADD = ../../src/libmnl.la +rtnl_route_add_LDFLAGS = -dynamic -ldl + +rtnl_link_event_SOURCES = rtnl-link-event.c +rtnl_link_event_LDADD = ../../src/libmnl.la +rtnl_link_event_LDFLAGS = -dynamic -ldl + +rtnl_link_set_SOURCES = rtnl-link-set.c +rtnl_link_set_LDADD = ../../src/libmnl.la +rtnl_link_set_LDFLAGS = -dynamic -ldl + +rtnl_route_dump_SOURCES = rtnl-route-dump.c +rtnl_route_dump_LDADD = ../../src/libmnl.la +rtnl_route_dump_LDFLAGS = -dynamic -ldl diff --git a/examples/rtnl/rtnl-link-dump.c b/examples/rtnl/rtnl-link-dump.c new file mode 100644 index 0000000..8bce803 --- /dev/null +++ b/examples/rtnl/rtnl-link-dump.c @@ -0,0 +1,117 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +static int data_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, IFLA_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case IFLA_MTU: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case IFLA_IFNAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate2"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[IFLA_MAX+1] = {}; + struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh); + + printf("index=%d type=%d flags=%d family=%d ", + ifm->ifi_index, ifm->ifi_type, + ifm->ifi_flags, ifm->ifi_family); + + if (ifm->ifi_flags & IFF_RUNNING) + printf("[RUNNING] "); + else + printf("[NOT RUNNING] "); + + mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, tb); + if (tb[IFLA_MTU]) { + printf("mtu=%d ", mnl_attr_get_u32(tb[IFLA_MTU])); + } + if (tb[IFLA_IFNAME]) { + printf("name=%s", mnl_attr_get_str(tb[IFLA_IFNAME])); + } + printf("\n"); + return MNL_CB_OK; +} + +int main() +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct rtgenmsg *rt; + int ret; + unsigned int seq, portid; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_GETLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + nlh->nlmsg_seq = seq = time(NULL); + rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); + rt->rtgen_family = AF_PACKET; + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); + if (ret <= MNL_CB_STOP) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/rtnl/rtnl-link-dump2.c b/examples/rtnl/rtnl-link-dump2.c new file mode 100644 index 0000000..ac3a6be --- /dev/null +++ b/examples/rtnl/rtnl-link-dump2.c @@ -0,0 +1,108 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +static int data_attr_cb(const struct nlattr *attr, void *data) +{ + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, IFLA_MAX) < 0) + return MNL_CB_OK; + + switch(mnl_attr_get_type(attr)) { + case IFLA_MTU: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + printf("mtu=%d ", mnl_attr_get_u32(attr)); + break; + case IFLA_IFNAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate2"); + return MNL_CB_ERROR; + } + printf("name=%s ", mnl_attr_get_str(attr)); + break; + } + return MNL_CB_OK; +} + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh); + + printf("index=%d type=%d flags=%d family=%d ", + ifm->ifi_index, ifm->ifi_type, + ifm->ifi_flags, ifm->ifi_family); + + if (ifm->ifi_flags & IFF_RUNNING) + printf("[RUNNING] "); + else + printf("[NOT RUNNING] "); + + mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, NULL); + printf("\n"); + return MNL_CB_OK; +} + +int main() +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct rtgenmsg *rt; + int ret; + unsigned int seq, portid; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_GETLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + nlh->nlmsg_seq = seq = time(NULL); + rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); + rt->rtgen_family = AF_PACKET; + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); + if (ret <= MNL_CB_STOP) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/rtnl/rtnl-link-dump3.c b/examples/rtnl/rtnl-link-dump3.c new file mode 100644 index 0000000..6d06d7c --- /dev/null +++ b/examples/rtnl/rtnl-link-dump3.c @@ -0,0 +1,108 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh); + struct nlattr *attr; + + printf("index=%d type=%d flags=%d family=%d ", + ifm->ifi_index, ifm->ifi_type, + ifm->ifi_flags, ifm->ifi_family); + + if (ifm->ifi_flags & IFF_RUNNING) + printf("[RUNNING] "); + else + printf("[NOT RUNNING] "); + + mnl_attr_for_each(attr, nlh, sizeof(*ifm)) { + int type = mnl_attr_get_type(attr); + + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, IFLA_MAX) < 0) + continue; + + switch(type) { + case IFLA_MTU: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + printf("mtu=%d ", mnl_attr_get_u32(attr)); + break; + case IFLA_IFNAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + printf("name=%s ", mnl_attr_get_str(attr)); + break; + } + } + printf("\n"); + + return MNL_CB_OK; +} + +int main() +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct rtgenmsg *rt; + int ret; + unsigned int seq, portid; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_GETLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + nlh->nlmsg_seq = seq = time(NULL); + rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); + rt->rtgen_family = AF_PACKET; + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); + if (ret <= MNL_CB_STOP) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/rtnl/rtnl-link-event.c b/examples/rtnl/rtnl-link-event.c new file mode 100644 index 0000000..aa51a1e --- /dev/null +++ b/examples/rtnl/rtnl-link-event.c @@ -0,0 +1,100 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include + +#include +#include +#include +#include + +static int data_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, IFLA_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case IFLA_MTU: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case IFLA_IFNAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate2"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[IFLA_MAX+1] = {}; + struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh); + + printf("index=%d type=%d flags=%d family=%d ", + ifm->ifi_index, ifm->ifi_type, + ifm->ifi_flags, ifm->ifi_family); + + if (ifm->ifi_flags & IFF_RUNNING) + printf("[RUNNING] "); + else + printf("[NOT RUNNING] "); + + mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, tb); + if (tb[IFLA_MTU]) { + printf("mtu=%d ", mnl_attr_get_u32(tb[IFLA_MTU])); + } + if (tb[IFLA_IFNAME]) { + printf("name=%s", mnl_attr_get_str(tb[IFLA_IFNAME])); + } + printf("\n"); + return MNL_CB_OK; +} + +int main() +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + int ret; + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, RTMGRP_LINK, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL); + if (ret <= 0) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/rtnl/rtnl-link-set.c b/examples/rtnl/rtnl-link-set.c new file mode 100644 index 0000000..d5cf9b1 --- /dev/null +++ b/examples/rtnl/rtnl-link-set.c @@ -0,0 +1,88 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct ifinfomsg *ifm; + int ret; + unsigned int seq, portid, change = 0, flags = 0; + + if (argc != 3) { + printf("Usage: %s [ifname] [up|down]\n", argv[0]); + exit(EXIT_FAILURE); + } + + if (strncasecmp(argv[2], "up", strlen("up")) == 0) { + change |= IFF_UP; + flags |= IFF_UP; + } else if (strncasecmp(argv[2], "down", strlen("down")) == 0) { + change |= IFF_UP; + flags &= ~IFF_UP; + } else { + fprintf(stderr, "%s is not `up' nor `down'\n", argv[2]); + exit(EXIT_FAILURE); + } + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_NEWLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nlh->nlmsg_seq = seq = time(NULL); + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + ifm->ifi_change = change; + ifm->ifi_flags = flags; + + mnl_attr_put_str(nlh, IFLA_IFNAME, argv[1]); + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + mnl_nlmsg_fprintf(stdout, nlh); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + if (ret == -1) { + perror("read"); + exit(EXIT_FAILURE); + } + + ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); + if (ret == -1){ + perror("callback"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/rtnl/rtnl-route-add.c b/examples/rtnl/rtnl-route-add.c new file mode 100644 index 0000000..1f2d1a0 --- /dev/null +++ b/examples/rtnl/rtnl-route-add.c @@ -0,0 +1,99 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + if (argc <= 3) { + printf("Usage: %s iface destination cidr [gateway]\n", argv[0]); + printf("Example: %s eth0 10.0.1.12 32 10.0.1.11\n", argv[0]); + exit(EXIT_FAILURE); + } + + int iface; + iface = if_nametoindex(argv[1]); + if (iface == 0) { + printf("Bad interface name\n"); + exit(EXIT_FAILURE); + } + + in_addr_t dst; + if (!inet_pton(AF_INET, argv[2], &dst)) { + printf("Bad destination\n"); + exit(EXIT_FAILURE); + } + + uint32_t mask; + if (sscanf(argv[3], "%u", &mask) == 0) { + printf("Bad CIDR\n"); + exit(EXIT_FAILURE); + } + + in_addr_t gw; + if (argc >= 5 && !inet_pton(AF_INET, argv[4], &gw)) { + printf("Bad gateway\n"); + exit(EXIT_FAILURE); + } + + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct rtmsg *rtm; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_NEWROUTE; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; + nlh->nlmsg_seq = time(NULL); + + rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); + rtm->rtm_family = AF_INET; + rtm->rtm_dst_len = mask; + rtm->rtm_src_len = 0; + rtm->rtm_tos = 0; + rtm->rtm_protocol = RTPROT_BOOT; + rtm->rtm_table = RT_TABLE_MAIN; + rtm->rtm_type = RTN_UNICAST; + /* is there any gateway? */ + rtm->rtm_scope = (argc == 4) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; + rtm->rtm_flags = 0; + + mnl_attr_put_u32(nlh, RTA_DST, dst); + mnl_attr_put_u32(nlh, RTA_OIF, iface); + if (argc >= 5) + mnl_attr_put_u32(nlh, RTA_GATEWAY, gw); + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/rtnl/rtnl-route-dump.c b/examples/rtnl/rtnl-route-dump.c new file mode 100644 index 0000000..34c95cf --- /dev/null +++ b/examples/rtnl/rtnl-route-dump.c @@ -0,0 +1,247 @@ +/* + * (C) 2009-2010 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static int data_attr_cb2(const struct nlattr *attr, void *data) +{ + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, RTAX_MAX) < 0) + return MNL_CB_OK; + + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + return MNL_CB_OK; +} + +static void attributes_show_ipv4(struct nlattr *tb[]) +{ + if (tb[RTA_TABLE]) { + printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE])); + } + if (tb[RTA_DST]) { + struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]); + printf("dst=%s ", inet_ntoa(*addr)); + } + if (tb[RTA_SRC]) { + struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]); + printf("src=%s ", inet_ntoa(*addr)); + } + if (tb[RTA_OIF]) { + printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF])); + } + if (tb[RTA_FLOW]) { + printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW])); + } + if (tb[RTA_PREFSRC]) { + struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]); + printf("prefsrc=%s ", inet_ntoa(*addr)); + } + if (tb[RTA_GATEWAY]) { + struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]); + printf("gw=%s ", inet_ntoa(*addr)); + } + if (tb[RTA_METRICS]) { + int i; + struct nlattr *tbx[RTAX_MAX+1] = {}; + + mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx); + + for (i=0; irtm_family); + + /* destination CIDR, eg. 24 or 32 for IPv4 */ + printf("dst_len=%u ", rm->rtm_dst_len); + + /* source CIDR */ + printf("src_len=%u ", rm->rtm_src_len); + + /* type of service (TOS), eg. 0 */ + printf("tos=%u ", rm->rtm_tos); + + /* table id: + * RT_TABLE_UNSPEC = 0 + * + * ... user defined values ... + * + * RT_TABLE_COMPAT = 252 + * RT_TABLE_DEFAULT = 253 + * RT_TABLE_MAIN = 254 + * RT_TABLE_LOCAL = 255 + * RT_TABLE_MAX = 0xFFFFFFFF + * + * Synonimous attribute: RTA_TABLE. + */ + printf("table=%u ", rm->rtm_table); + + /* type: + * RTN_UNSPEC = 0 + * RTN_UNICAST = 1 + * RTN_LOCAL = 2 + * RTN_BROADCAST = 3 + * RTN_ANYCAST = 4 + * RTN_MULTICAST = 5 + * RTN_BLACKHOLE = 6 + * RTN_UNREACHABLE = 7 + * RTN_PROHIBIT = 8 + * RTN_THROW = 9 + * RTN_NAT = 10 + * RTN_XRESOLVE = 11 + * __RTN_MAX = 12 + */ + printf("type=%u ", rm->rtm_type); + + /* scope: + * RT_SCOPE_UNIVERSE = 0 : everywhere in the universe + * + * ... user defined values ... + * + * RT_SCOPE_SITE = 200 + * RT_SCOPE_LINK = 253 : destination attached to link + * RT_SCOPE_HOST = 254 : local address + * RT_SCOPE_NOWHERE = 255 : not existing destination + */ + printf("scope=%u ", rm->rtm_scope); + + /* protocol: + * RTPROT_UNSPEC = 0 + * RTPROT_REDIRECT = 1 + * RTPROT_KERNEL = 2 : route installed by kernel + * RTPROT_BOOT = 3 : route installed during boot + * RTPROT_STATIC = 4 : route installed by administrator + * + * Values >= RTPROT_STATIC are not interpreted by kernel, they are + * just user-defined. + */ + printf("proto=%u ", rm->rtm_protocol); + + /* flags: + * RTM_F_NOTIFY = 0x100: notify user of route change + * RTM_F_CLONED = 0x200: this route is cloned + * RTM_F_EQUALIZE = 0x400: Multipath equalizer: NI + * RTM_F_PREFIX = 0x800: Prefix addresses + */ + printf("flags=%x\n", rm->rtm_flags); + + mnl_attr_parse(nlh, sizeof(*rm), data_attr_cb, tb); + + switch(rm->rtm_family) { + case AF_INET: + attributes_show_ipv4(tb); + break; + } + + return MNL_CB_OK; +} + +int main() +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct rtmsg *rtm; + int ret; + unsigned int seq, portid; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_GETROUTE; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + nlh->nlmsg_seq = seq = time(NULL); + rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); + rtm->rtm_family = AF_INET; + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL); + if (ret <= MNL_CB_STOP) + break; + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) { + perror("error"); + exit(EXIT_FAILURE); + } + + mnl_socket_close(nl); + + return 0; +} -- cgit v1.2.3