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 --- README | 7 +- configure.in | 2 +- examples/Makefile.am | 51 +------- examples/genl-family-get.c | 241 -------------------------------------- examples/genl/Makefile.am | 7 ++ examples/genl/genl-family-get.c | 241 ++++++++++++++++++++++++++++++++++++++ examples/netfilter/Makefile.am | 12 ++ examples/netfilter/nf-queue.c | 252 ++++++++++++++++++++++++++++++++++++++++ examples/netfilter/nfct-event.c | 245 ++++++++++++++++++++++++++++++++++++++ examples/nf-queue.c | 252 ---------------------------------------- examples/nfct-event.c | 245 -------------------------------------- examples/rtnl-link-dump.c | 117 ------------------- examples/rtnl-link-dump2.c | 108 ----------------- examples/rtnl-link-dump3.c | 108 ----------------- examples/rtnl-link-event.c | 100 ---------------- examples/rtnl-link-set.c | 88 -------------- examples/rtnl-route-add.c | 99 ---------------- examples/rtnl-route-dump.c | 247 --------------------------------------- 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 +++++++++++++++++++++++++++++++++++++++ 26 files changed, 1667 insertions(+), 1657 deletions(-) delete mode 100644 examples/genl-family-get.c create mode 100644 examples/genl/Makefile.am create mode 100644 examples/genl/genl-family-get.c create mode 100644 examples/netfilter/Makefile.am create mode 100644 examples/netfilter/nf-queue.c create mode 100644 examples/netfilter/nfct-event.c delete mode 100644 examples/nf-queue.c delete mode 100644 examples/nfct-event.c delete mode 100644 examples/rtnl-link-dump.c delete mode 100644 examples/rtnl-link-dump2.c delete mode 100644 examples/rtnl-link-dump3.c delete mode 100644 examples/rtnl-link-event.c delete mode 100644 examples/rtnl-link-set.c delete mode 100644 examples/rtnl-route-add.c delete mode 100644 examples/rtnl-route-dump.c 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 diff --git a/README b/README index 689eb8a..ca7a820 100644 --- a/README +++ b/README @@ -18,6 +18,11 @@ on top of this library. is reduced, eg. the library provides many helpers but the programmer is not forced to use them. += Examples files = + +You can find several examples files under examples/ that you can compile by +invoking `make check'. + -- -08/apr/2010 +08/sep/2010 Pablo Neira Ayuso diff --git a/configure.in b/configure.in index 4a8f1a2..8969b35 100644 --- a/configure.in +++ b/configure.in @@ -15,4 +15,4 @@ case $target in *) AC_MSG_ERROR([Linux only, dude!]);; esac -AC_OUTPUT(Makefile src/Makefile include/Makefile include/libmnl/Makefile examples/Makefile libmnl.pc) +AC_OUTPUT(Makefile src/Makefile include/Makefile include/libmnl/Makefile examples/Makefile examples/genl/Makefile examples/netfilter/Makefile examples/rtnl/Makefile libmnl.pc) diff --git a/examples/Makefile.am b/examples/Makefile.am index f23a586..f6c2f69 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,50 +1 @@ -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 \ - genl-family-get \ - nf-queue \ - nfct-event - -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 - -genl_family_get_SOURCES = genl-family-get.c -genl_family_get_LDADD = ../src/libmnl.la -genl_family_get_LDFLAGS = -dynamic -ldl - -nf_queue_SOURCES = nf-queue.c -nf_queue_LDADD = ../src/libmnl.la -nf_queue_LDFLAGS = -dynamic -ldl - -nfct_event_SOURCES = nfct-event.c -nfct_event_LDADD = ../src/libmnl.la -nfct_event_LDFLAGS = -dynamic -ldl +SUBDIRS = genl netfilter rtnl diff --git a/examples/genl-family-get.c b/examples/genl-family-get.c deleted file mode 100644 index 326755e..0000000 --- a/examples/genl-family-get.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * (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 - -static int parse_mc_grps_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, CTRL_ATTR_MCAST_GRP_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTRL_ATTR_MCAST_GRP_ID: - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTRL_ATTR_MCAST_GRP_NAME: - if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static void parse_genl_mc_grps(struct nlattr *nested) -{ - struct nlattr *pos; - - mnl_attr_for_each_nested(pos, nested) { - struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {}; - - mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); - if (tb[CTRL_ATTR_MCAST_GRP_ID]) { - printf("id-0x%x ", - mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID])); - } - if (tb[CTRL_ATTR_MCAST_GRP_NAME]) { - printf("name: %s ", - mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME])); - } - printf("\n"); - } -} - -static int parse_family_ops_cb(const struct nlattr *attr, void *data) -{ - const struct nlattr **tb = (const struct nlattr **)data; - int type = mnl_attr_get_type(attr); - - if (mnl_attr_type_valid(attr, CTRL_ATTR_OP_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTRL_ATTR_OP_ID: - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTRL_ATTR_OP_MAX: - break; - default: - return MNL_CB_OK; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static void parse_genl_family_ops(struct nlattr *nested) -{ - struct nlattr *pos; - - mnl_attr_for_each_nested(pos, nested) { - struct nlattr *tb[CTRL_ATTR_OP_MAX+1] = {}; - - mnl_attr_parse_nested(pos, parse_family_ops_cb, tb); - if (tb[CTRL_ATTR_OP_ID]) { - printf("id-0x%x ", - mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID])); - } - if (tb[CTRL_ATTR_OP_MAX]) { - printf("flags "); - } - printf("\n"); - } -} - -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); - - if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTRL_ATTR_FAMILY_NAME: - if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTRL_ATTR_FAMILY_ID: - if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTRL_ATTR_VERSION: - case CTRL_ATTR_HDRSIZE: - case CTRL_ATTR_MAXATTR: - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTRL_ATTR_OPS: - case CTRL_ATTR_MCAST_GROUPS: - if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { - perror("mnl_attr_validate"); - 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[CTRL_ATTR_MAX+1] = {}; - struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); - - mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb); - if (tb[CTRL_ATTR_FAMILY_NAME]) { - printf("name=%s\t", - mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME])); - } - if (tb[CTRL_ATTR_FAMILY_ID]) { - printf("id=%u\t", - mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID])); - } - if (tb[CTRL_ATTR_VERSION]) { - printf("version=%u\t", - mnl_attr_get_u32(tb[CTRL_ATTR_VERSION])); - } - if (tb[CTRL_ATTR_HDRSIZE]) { - printf("hdrsize=%u\t", - mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE])); - } - if (tb[CTRL_ATTR_MAXATTR]) { - printf("maxattr=%u\t", - mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR])); - } - if (tb[CTRL_ATTR_OPS]) { - printf("\nops:\n"); - parse_genl_family_ops(tb[CTRL_ATTR_OPS]); - } - if (tb[CTRL_ATTR_MCAST_GROUPS]) { - printf("\ngrps:\n"); - parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]); - } - return MNL_CB_OK; -} - -int main(int argc, char *argv[]) -{ - struct mnl_socket *nl; - char buf[getpagesize()]; - struct nlmsghdr *nlh; - struct genlmsghdr *genl; - int ret; - unsigned int seq, portid; - - if (argc != 2) { - printf("%s [family name]\n", argv[0]); - exit(EXIT_FAILURE); - } - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = GENL_ID_CTRL; - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - - genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); - genl->cmd = CTRL_CMD_GETFAMILY; - genl->version = 1; - - mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL); - mnl_attr_put_str_null(nlh, CTRL_ATTR_FAMILY_NAME, argv[1]); - - nl = mnl_socket_open(NETLINK_GENERIC); - 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 <= 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/genl/Makefile.am b/examples/genl/Makefile.am new file mode 100644 index 0000000..a2df116 --- /dev/null +++ b/examples/genl/Makefile.am @@ -0,0 +1,7 @@ +include $(top_srcdir)/Make_global.am + +check_PROGRAMS = genl-family-get + +genl_family_get_SOURCES = genl-family-get.c +genl_family_get_LDADD = ../../src/libmnl.la +genl_family_get_LDFLAGS = -dynamic -ldl diff --git a/examples/genl/genl-family-get.c b/examples/genl/genl-family-get.c new file mode 100644 index 0000000..326755e --- /dev/null +++ b/examples/genl/genl-family-get.c @@ -0,0 +1,241 @@ +/* + * (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 + +static int parse_mc_grps_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, CTRL_ATTR_MCAST_GRP_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTRL_ATTR_MCAST_GRP_ID: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTRL_ATTR_MCAST_GRP_NAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void parse_genl_mc_grps(struct nlattr *nested) +{ + struct nlattr *pos; + + mnl_attr_for_each_nested(pos, nested) { + struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {}; + + mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); + if (tb[CTRL_ATTR_MCAST_GRP_ID]) { + printf("id-0x%x ", + mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID])); + } + if (tb[CTRL_ATTR_MCAST_GRP_NAME]) { + printf("name: %s ", + mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME])); + } + printf("\n"); + } +} + +static int parse_family_ops_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTRL_ATTR_OP_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTRL_ATTR_OP_ID: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTRL_ATTR_OP_MAX: + break; + default: + return MNL_CB_OK; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void parse_genl_family_ops(struct nlattr *nested) +{ + struct nlattr *pos; + + mnl_attr_for_each_nested(pos, nested) { + struct nlattr *tb[CTRL_ATTR_OP_MAX+1] = {}; + + mnl_attr_parse_nested(pos, parse_family_ops_cb, tb); + if (tb[CTRL_ATTR_OP_ID]) { + printf("id-0x%x ", + mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID])); + } + if (tb[CTRL_ATTR_OP_MAX]) { + printf("flags "); + } + printf("\n"); + } +} + +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); + + if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTRL_ATTR_FAMILY_NAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTRL_ATTR_FAMILY_ID: + if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTRL_ATTR_VERSION: + case CTRL_ATTR_HDRSIZE: + case CTRL_ATTR_MAXATTR: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTRL_ATTR_OPS: + case CTRL_ATTR_MCAST_GROUPS: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + 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[CTRL_ATTR_MAX+1] = {}; + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + + mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb); + if (tb[CTRL_ATTR_FAMILY_NAME]) { + printf("name=%s\t", + mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME])); + } + if (tb[CTRL_ATTR_FAMILY_ID]) { + printf("id=%u\t", + mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID])); + } + if (tb[CTRL_ATTR_VERSION]) { + printf("version=%u\t", + mnl_attr_get_u32(tb[CTRL_ATTR_VERSION])); + } + if (tb[CTRL_ATTR_HDRSIZE]) { + printf("hdrsize=%u\t", + mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE])); + } + if (tb[CTRL_ATTR_MAXATTR]) { + printf("maxattr=%u\t", + mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR])); + } + if (tb[CTRL_ATTR_OPS]) { + printf("\nops:\n"); + parse_genl_family_ops(tb[CTRL_ATTR_OPS]); + } + if (tb[CTRL_ATTR_MCAST_GROUPS]) { + printf("\ngrps:\n"); + parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]); + } + return MNL_CB_OK; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + struct genlmsghdr *genl; + int ret; + unsigned int seq, portid; + + if (argc != 2) { + printf("%s [family name]\n", argv[0]); + exit(EXIT_FAILURE); + } + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = GENL_ID_CTRL; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nlh->nlmsg_seq = seq = time(NULL); + + genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); + genl->cmd = CTRL_CMD_GETFAMILY; + genl->version = 1; + + mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL); + mnl_attr_put_str_null(nlh, CTRL_ATTR_FAMILY_NAME, argv[1]); + + nl = mnl_socket_open(NETLINK_GENERIC); + 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 <= 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/netfilter/Makefile.am b/examples/netfilter/Makefile.am new file mode 100644 index 0000000..ef2f10c --- /dev/null +++ b/examples/netfilter/Makefile.am @@ -0,0 +1,12 @@ +include $(top_srcdir)/Make_global.am + +check_PROGRAMS = nf-queue \ + nfct-event + +nf_queue_SOURCES = nf-queue.c +nf_queue_LDADD = ../../src/libmnl.la +nf_queue_LDFLAGS = -dynamic -ldl + +nfct_event_SOURCES = nfct-event.c +nfct_event_LDADD = ../../src/libmnl.la +nfct_event_LDFLAGS = -dynamic -ldl diff --git a/examples/netfilter/nf-queue.c b/examples/netfilter/nf-queue.c new file mode 100644 index 0000000..1df004a --- /dev/null +++ b/examples/netfilter/nf-queue.c @@ -0,0 +1,252 @@ +/* + * (C) 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 + +#ifndef aligned_be64 +#define aligned_be64 u_int64_t __attribute__((aligned(8))) +#endif + +#include + +static int parse_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, NFQA_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFQA_MARK: + case NFQA_IFINDEX_INDEV: + case NFQA_IFINDEX_OUTDEV: + case NFQA_IFINDEX_PHYSINDEV: + case NFQA_IFINDEX_PHYSOUTDEV: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case NFQA_TIMESTAMP: + if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, + sizeof(struct nfqnl_msg_packet_timestamp)) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case NFQA_HWADDR: + if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, + sizeof(struct nfqnl_msg_packet_hw)) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case NFQA_PAYLOAD: + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static int queue_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[NFQA_MAX+1] = {}; + struct nfqnl_msg_packet_hdr *ph = NULL; + uint32_t id = 0; + + mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb); + if (tb[NFQA_PACKET_HDR]) { + ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]); + id = ntohl(ph->packet_id); + } + printf("packet received (id=%u hw=0x%04x hook=%u)\n", + id, ntohs(ph->hw_protocol), ph->hook); + + return MNL_CB_OK + id; +} + +static struct nlmsghdr * +nfq_build_cfg_pf_request(char *buf, uint8_t command) +{ + struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; + nlh->nlmsg_flags = NLM_F_REQUEST; + + struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); + nfg->nfgen_family = AF_UNSPEC; + nfg->version = NFNETLINK_V0; + + struct nfqnl_msg_config_cmd cmd = { + .command = command, + .pf = htons(AF_INET), + }; + mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd); + + return nlh; +} + +static struct nlmsghdr * +nfq_build_cfg_request(char *buf, uint8_t command, int queue_num) +{ + struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; + nlh->nlmsg_flags = NLM_F_REQUEST; + + struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); + nfg->nfgen_family = AF_UNSPEC; + nfg->version = NFNETLINK_V0; + nfg->res_id = htons(queue_num); + + struct nfqnl_msg_config_cmd cmd = { + .command = command, + .pf = htons(AF_INET), + }; + mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd); + + return nlh; +} + +static struct nlmsghdr * +nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num) +{ + struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; + nlh->nlmsg_flags = NLM_F_REQUEST; + + struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); + nfg->nfgen_family = AF_UNSPEC; + nfg->version = NFNETLINK_V0; + nfg->res_id = htons(queue_num); + + struct nfqnl_msg_config_params params = { + .copy_range = htonl(range), + .copy_mode = mode, + }; + mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), ¶ms); + + return nlh; +} + +static struct nlmsghdr * +nfq_build_verdict(char *buf, int id, int queue_num, int verd) +{ + struct nlmsghdr *nlh; + struct nfgenmsg *nfg; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT; + nlh->nlmsg_flags = NLM_F_REQUEST; + nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); + nfg->nfgen_family = AF_UNSPEC; + nfg->version = NFNETLINK_V0; + nfg->res_id = htons(queue_num); + + struct nfqnl_msg_verdict_hdr vh = { + .verdict = htonl(verd), + .id = htonl(id), + }; + mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh); + + return nlh; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + struct nlmsghdr *nlh; + int ret; + unsigned int portid, queue_num; + + if (argc != 2) { + printf("Usage: %s [queue_num]\n", argv[0]); + exit(EXIT_FAILURE); + } + queue_num = atoi(argv[1]); + + nl = mnl_socket_open(NETLINK_NETFILTER); + 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); + + nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_UNBIND); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_BIND); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num); + + 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("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + while (ret > 0) { + uint32_t id; + + ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL); + if (ret < 0){ + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } + + id = ret - MNL_CB_OK; + nlh = nfq_build_verdict(buf, id, queue_num, NF_ACCEPT); + 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("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/netfilter/nfct-event.c b/examples/netfilter/nfct-event.c new file mode 100644 index 0000000..9dcf6cc --- /dev/null +++ b/examples/netfilter/nfct-event.c @@ -0,0 +1,245 @@ +/* + * (C) 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 parse_ip_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_IP_V4_SRC: + case CTA_IP_V4_DST: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void print_ip(const struct nlattr *nest) +{ + struct nlattr *tb[CTA_IP_MAX+1] = {}; + + mnl_attr_parse_nested(nest, parse_ip_cb, tb); + if (tb[CTA_IP_V4_SRC]) { + struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]); + printf("src=%s ", inet_ntoa(*in)); + } + if (tb[CTA_IP_V4_DST]) { + struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]); + printf("dst=%s ", inet_ntoa(*in)); + } +} + +static int parse_proto_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_PROTO_NUM: + case CTA_PROTO_ICMP_TYPE: + case CTA_PROTO_ICMP_CODE: + if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTA_PROTO_SRC_PORT: + case CTA_PROTO_DST_PORT: + case CTA_PROTO_ICMP_ID: + if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void print_proto(const struct nlattr *nest) +{ + struct nlattr *tb[CTA_PROTO_MAX+1] = {}; + + mnl_attr_parse_nested(nest, parse_proto_cb, tb); + if (tb[CTA_PROTO_NUM]) { + printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM])); + } + if (tb[CTA_PROTO_SRC_PORT]) { + printf("sport=%u ", + ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]))); + } + if (tb[CTA_PROTO_DST_PORT]) { + printf("dport=%u ", + ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]))); + } + if (tb[CTA_PROTO_ICMP_ID]) { + printf("id=%u ", + ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]))); + } + if (tb[CTA_PROTO_ICMP_TYPE]) { + printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE])); + } + if (tb[CTA_PROTO_ICMP_CODE]) { + printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE])); + } +} + +static int parse_tuple_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = (const struct nlattr **)data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_TUPLE_IP: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTA_TUPLE_PROTO: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void print_tuple(const struct nlattr *nest) +{ + struct nlattr *tb[CTA_TUPLE_MAX+1] = {}; + + mnl_attr_parse_nested(nest, parse_tuple_cb, tb); + if (tb[CTA_TUPLE_IP]) { + print_ip(tb[CTA_TUPLE_IP]); + } + if (tb[CTA_TUPLE_PROTO]) { + print_proto(tb[CTA_TUPLE_PROTO]); + } +} + +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); + + if (mnl_attr_type_valid(attr, CTA_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_TUPLE_ORIG: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + case CTA_TIMEOUT: + case CTA_MARK: + case CTA_SECMARK: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + 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[CTA_MAX+1] = {}; + struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); + + switch(nlh->nlmsg_type & 0xFF) { + case IPCTNL_MSG_CT_NEW: + if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) + printf("%9s ", "[NEW] "); + else + printf("%9s ", "[UPDATE] "); + break; + case IPCTNL_MSG_CT_DELETE: + printf("%9s ", "[DESTROY] "); + break; + } + + mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb); + if (tb[CTA_TUPLE_ORIG]) { + print_tuple(tb[CTA_TUPLE_ORIG]); + } + if (tb[CTA_MARK]) { + printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK]))); + } + if (tb[CTA_SECMARK]) { + printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK]))); + } + printf("\n"); + return MNL_CB_OK; +} + +int main() +{ + struct mnl_socket *nl; + char buf[getpagesize()]; + int ret; + + nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, NFNLGRP_CONNTRACK_NEW | + NFNLGRP_CONNTRACK_UPDATE | + NFNLGRP_CONNTRACK_DESTROY, + MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + + while (1) { + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + + ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL); + if (ret == -1) { + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/examples/nf-queue.c b/examples/nf-queue.c deleted file mode 100644 index 1df004a..0000000 --- a/examples/nf-queue.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * (C) 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 - -#ifndef aligned_be64 -#define aligned_be64 u_int64_t __attribute__((aligned(8))) -#endif - -#include - -static int parse_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, NFQA_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case NFQA_MARK: - case NFQA_IFINDEX_INDEV: - case NFQA_IFINDEX_OUTDEV: - case NFQA_IFINDEX_PHYSINDEV: - case NFQA_IFINDEX_PHYSOUTDEV: - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case NFQA_TIMESTAMP: - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, - sizeof(struct nfqnl_msg_packet_timestamp)) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case NFQA_HWADDR: - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, - sizeof(struct nfqnl_msg_packet_hw)) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case NFQA_PAYLOAD: - break; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static int queue_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nlattr *tb[NFQA_MAX+1] = {}; - struct nfqnl_msg_packet_hdr *ph = NULL; - uint32_t id = 0; - - mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb); - if (tb[NFQA_PACKET_HDR]) { - ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]); - id = ntohl(ph->packet_id); - } - printf("packet received (id=%u hw=0x%04x hook=%u)\n", - id, ntohs(ph->hw_protocol), ph->hook); - - return MNL_CB_OK + id; -} - -static struct nlmsghdr * -nfq_build_cfg_pf_request(char *buf, uint8_t command) -{ - struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; - nlh->nlmsg_flags = NLM_F_REQUEST; - - struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); - nfg->nfgen_family = AF_UNSPEC; - nfg->version = NFNETLINK_V0; - - struct nfqnl_msg_config_cmd cmd = { - .command = command, - .pf = htons(AF_INET), - }; - mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd); - - return nlh; -} - -static struct nlmsghdr * -nfq_build_cfg_request(char *buf, uint8_t command, int queue_num) -{ - struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; - nlh->nlmsg_flags = NLM_F_REQUEST; - - struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); - nfg->nfgen_family = AF_UNSPEC; - nfg->version = NFNETLINK_V0; - nfg->res_id = htons(queue_num); - - struct nfqnl_msg_config_cmd cmd = { - .command = command, - .pf = htons(AF_INET), - }; - mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd); - - return nlh; -} - -static struct nlmsghdr * -nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num) -{ - struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG; - nlh->nlmsg_flags = NLM_F_REQUEST; - - struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); - nfg->nfgen_family = AF_UNSPEC; - nfg->version = NFNETLINK_V0; - nfg->res_id = htons(queue_num); - - struct nfqnl_msg_config_params params = { - .copy_range = htonl(range), - .copy_mode = mode, - }; - mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), ¶ms); - - return nlh; -} - -static struct nlmsghdr * -nfq_build_verdict(char *buf, int id, int queue_num, int verd) -{ - struct nlmsghdr *nlh; - struct nfgenmsg *nfg; - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT; - nlh->nlmsg_flags = NLM_F_REQUEST; - nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); - nfg->nfgen_family = AF_UNSPEC; - nfg->version = NFNETLINK_V0; - nfg->res_id = htons(queue_num); - - struct nfqnl_msg_verdict_hdr vh = { - .verdict = htonl(verd), - .id = htonl(id), - }; - mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh); - - return nlh; -} - -int main(int argc, char *argv[]) -{ - struct mnl_socket *nl; - char buf[getpagesize()]; - struct nlmsghdr *nlh; - int ret; - unsigned int portid, queue_num; - - if (argc != 2) { - printf("Usage: %s [queue_num]\n", argv[0]); - exit(EXIT_FAILURE); - } - queue_num = atoi(argv[1]); - - nl = mnl_socket_open(NETLINK_NETFILTER); - 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); - - nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_UNBIND); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); - exit(EXIT_FAILURE); - } - - nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_BIND); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); - exit(EXIT_FAILURE); - } - - nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); - exit(EXIT_FAILURE); - } - - nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num); - - 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("mnl_socket_recvfrom"); - exit(EXIT_FAILURE); - } - while (ret > 0) { - uint32_t id; - - ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL); - if (ret < 0){ - perror("mnl_cb_run"); - exit(EXIT_FAILURE); - } - - id = ret - MNL_CB_OK; - nlh = nfq_build_verdict(buf, id, queue_num, NF_ACCEPT); - 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("mnl_socket_recvfrom"); - exit(EXIT_FAILURE); - } - } - - mnl_socket_close(nl); - - return 0; -} diff --git a/examples/nfct-event.c b/examples/nfct-event.c deleted file mode 100644 index 9dcf6cc..0000000 --- a/examples/nfct-event.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * (C) 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 parse_ip_cb(const struct nlattr *attr, void *data) -{ - const struct nlattr **tb = (const struct nlattr **)data; - int type = mnl_attr_get_type(attr); - - if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTA_IP_V4_SRC: - case CTA_IP_V4_DST: - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static void print_ip(const struct nlattr *nest) -{ - struct nlattr *tb[CTA_IP_MAX+1] = {}; - - mnl_attr_parse_nested(nest, parse_ip_cb, tb); - if (tb[CTA_IP_V4_SRC]) { - struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]); - printf("src=%s ", inet_ntoa(*in)); - } - if (tb[CTA_IP_V4_DST]) { - struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]); - printf("dst=%s ", inet_ntoa(*in)); - } -} - -static int parse_proto_cb(const struct nlattr *attr, void *data) -{ - const struct nlattr **tb = (const struct nlattr **)data; - int type = mnl_attr_get_type(attr); - - if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTA_PROTO_NUM: - case CTA_PROTO_ICMP_TYPE: - case CTA_PROTO_ICMP_CODE: - if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTA_PROTO_SRC_PORT: - case CTA_PROTO_DST_PORT: - case CTA_PROTO_ICMP_ID: - if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static void print_proto(const struct nlattr *nest) -{ - struct nlattr *tb[CTA_PROTO_MAX+1] = {}; - - mnl_attr_parse_nested(nest, parse_proto_cb, tb); - if (tb[CTA_PROTO_NUM]) { - printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM])); - } - if (tb[CTA_PROTO_SRC_PORT]) { - printf("sport=%u ", - ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]))); - } - if (tb[CTA_PROTO_DST_PORT]) { - printf("dport=%u ", - ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]))); - } - if (tb[CTA_PROTO_ICMP_ID]) { - printf("id=%u ", - ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]))); - } - if (tb[CTA_PROTO_ICMP_TYPE]) { - printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE])); - } - if (tb[CTA_PROTO_ICMP_CODE]) { - printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE])); - } -} - -static int parse_tuple_cb(const struct nlattr *attr, void *data) -{ - const struct nlattr **tb = (const struct nlattr **)data; - int type = mnl_attr_get_type(attr); - - if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTA_TUPLE_IP: - if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTA_TUPLE_PROTO: - if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static void print_tuple(const struct nlattr *nest) -{ - struct nlattr *tb[CTA_TUPLE_MAX+1] = {}; - - mnl_attr_parse_nested(nest, parse_tuple_cb, tb); - if (tb[CTA_TUPLE_IP]) { - print_ip(tb[CTA_TUPLE_IP]); - } - if (tb[CTA_TUPLE_PROTO]) { - print_proto(tb[CTA_TUPLE_PROTO]); - } -} - -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); - - if (mnl_attr_type_valid(attr, CTA_MAX) < 0) - return MNL_CB_OK; - - switch(type) { - case CTA_TUPLE_ORIG: - if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) { - perror("mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - case CTA_TIMEOUT: - case CTA_MARK: - case CTA_SECMARK: - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - perror("mnl_attr_validate"); - 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[CTA_MAX+1] = {}; - struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); - - switch(nlh->nlmsg_type & 0xFF) { - case IPCTNL_MSG_CT_NEW: - if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) - printf("%9s ", "[NEW] "); - else - printf("%9s ", "[UPDATE] "); - break; - case IPCTNL_MSG_CT_DELETE: - printf("%9s ", "[DESTROY] "); - break; - } - - mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb); - if (tb[CTA_TUPLE_ORIG]) { - print_tuple(tb[CTA_TUPLE_ORIG]); - } - if (tb[CTA_MARK]) { - printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK]))); - } - if (tb[CTA_SECMARK]) { - printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK]))); - } - printf("\n"); - return MNL_CB_OK; -} - -int main() -{ - struct mnl_socket *nl; - char buf[getpagesize()]; - int ret; - - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - perror("mnl_socket_open"); - exit(EXIT_FAILURE); - } - - if (mnl_socket_bind(nl, NFNLGRP_CONNTRACK_NEW | - NFNLGRP_CONNTRACK_UPDATE | - NFNLGRP_CONNTRACK_DESTROY, - MNL_SOCKET_AUTOPID) < 0) { - perror("mnl_socket_bind"); - exit(EXIT_FAILURE); - } - - while (1) { - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - if (ret == -1) { - perror("mnl_socket_recvfrom"); - exit(EXIT_FAILURE); - } - - ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL); - if (ret == -1) { - perror("mnl_cb_run"); - exit(EXIT_FAILURE); - } - } - - mnl_socket_close(nl); - - return 0; -} diff --git a/examples/rtnl-link-dump.c b/examples/rtnl-link-dump.c deleted file mode 100644 index 8bce803..0000000 --- a/examples/rtnl-link-dump.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * (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-link-dump2.c b/examples/rtnl-link-dump2.c deleted file mode 100644 index ac3a6be..0000000 --- a/examples/rtnl-link-dump2.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * (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-link-dump3.c b/examples/rtnl-link-dump3.c deleted file mode 100644 index 6d06d7c..0000000 --- a/examples/rtnl-link-dump3.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * (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-link-event.c b/examples/rtnl-link-event.c deleted file mode 100644 index aa51a1e..0000000 --- a/examples/rtnl-link-event.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * (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-link-set.c b/examples/rtnl-link-set.c deleted file mode 100644 index d5cf9b1..0000000 --- a/examples/rtnl-link-set.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * (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-route-add.c b/examples/rtnl-route-add.c deleted file mode 100644 index 1f2d1a0..0000000 --- a/examples/rtnl-route-add.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * (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-route-dump.c b/examples/rtnl-route-dump.c deleted file mode 100644 index 34c95cf..0000000 --- a/examples/rtnl-route-dump.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * (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; -} 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