From 7aa4b6cc0b994a4af80a34d3f9872447412815e1 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 14 Mar 2013 12:02:35 +0100 Subject: doxygen: fix a variable name. Variable name in doxygen description was not correct. Signed-off-by: Eric Leblond --- src/nlmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlmsg.c b/src/nlmsg.c index 000829e..fdb7af8 100644 --- a/src/nlmsg.c +++ b/src/nlmsg.c @@ -222,7 +222,7 @@ EXPORT_SYMBOL(mnl_nlmsg_seq_ok); /** * mnl_nlmsg_portid_ok - perform portID origin check * \param nlh current netlink message that we are handling - * \param seq netlink portid that we want to check + * \param portid netlink portid that we want to check * * This functions returns true if the origin is fulfilled, otherwise * false is returned. We skip the tracking for netlink message whose portID -- cgit v1.2.3 From 3f69d23e0e4181ee91332da6060d943f82c698a0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 19 Mar 2013 13:32:04 +0100 Subject: examples: add genl-group-events Signed-off-by: Pablo Neira Ayuso --- examples/genl/Makefile.am | 6 +++- examples/genl/genl-group-events.c | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 examples/genl/genl-group-events.c diff --git a/examples/genl/Makefile.am b/examples/genl/Makefile.am index deaf18d..b4b7954 100644 --- a/examples/genl/Makefile.am +++ b/examples/genl/Makefile.am @@ -1,6 +1,10 @@ include $(top_srcdir)/Make_global.am -check_PROGRAMS = genl-family-get +check_PROGRAMS = genl-family-get \ + genl-group-events genl_family_get_SOURCES = genl-family-get.c genl_family_get_LDADD = ../../src/libmnl.la + +genl_group_events_SOURCES = genl-group-events.c +genl_group_events_LDADD = ../../src/libmnl.la diff --git a/examples/genl/genl-group-events.c b/examples/genl/genl-group-events.c new file mode 100644 index 0000000..d5f0a18 --- /dev/null +++ b/examples/genl/genl-group-events.c @@ -0,0 +1,63 @@ +/* This example is placed in the public domain. */ +#include +#include +#include +#include + +#include +#include + +static int group; + +static int data_cb(const struct nlmsghdr *nlh, void *data) +{ + printf("received event type=%d from genetlink group %d\n", + nlh->nlmsg_type, group); + return MNL_CB_OK; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret; + + if (argc != 2) { + printf("%s [group]\n", argv[0]); + exit(EXIT_FAILURE); + } + group = atoi(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); + } + + if (mnl_socket_setsockopt(nl, NETLINK_ADD_MEMBERSHIP, &group, + sizeof(int)) < 0) { + perror("mnl_socket_setsockopt"); + 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; +} -- cgit v1.2.3 From 9616a3d58e500fdd769c21d2a16c4864448768e3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 26 Mar 2013 12:51:42 +0100 Subject: examples: add kobject-event Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- examples/Makefile.am | 2 +- examples/kobject/Makefile.am | 6 +++++ examples/kobject/kobject-event.c | 49 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 examples/kobject/Makefile.am create mode 100644 examples/kobject/kobject-event.c diff --git a/configure.ac b/configure.ac index 718ab1c..7c611fa 100644 --- a/configure.ac +++ b/configure.ac @@ -27,5 +27,5 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ -Wformat=2 -pipe" AC_SUBST([regular_CPPFLAGS]) AC_SUBST([regular_CFLAGS]) -AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libmnl/Makefile include/linux/Makefile examples/Makefile examples/genl/Makefile examples/netfilter/Makefile examples/rtnl/Makefile libmnl.pc doxygen.cfg]) +AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libmnl/Makefile include/linux/Makefile examples/Makefile examples/genl/Makefile examples/kobject/Makefile examples/netfilter/Makefile examples/rtnl/Makefile libmnl.pc doxygen.cfg]) AC_OUTPUT diff --git a/examples/Makefile.am b/examples/Makefile.am index f6c2f69..e5cb052 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1 +1 @@ -SUBDIRS = genl netfilter rtnl +SUBDIRS = genl kobject netfilter rtnl diff --git a/examples/kobject/Makefile.am b/examples/kobject/Makefile.am new file mode 100644 index 0000000..9197f7a --- /dev/null +++ b/examples/kobject/Makefile.am @@ -0,0 +1,6 @@ +include $(top_srcdir)/Make_global.am + +check_PROGRAMS = kobject-event + +kobject_event_SOURCES = kobject-event.c +kobject_event_LDADD = ../../src/libmnl.la diff --git a/examples/kobject/kobject-event.c b/examples/kobject/kobject-event.c new file mode 100644 index 0000000..97debdf --- /dev/null +++ b/examples/kobject/kobject-event.c @@ -0,0 +1,49 @@ +/* This example is placed in the public domain. */ +#include +#include +#include +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret; + + nl = mnl_socket_open(NETLINK_KOBJECT_UEVENT); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + /* There is one single group in kobject over netlink */ + if (mnl_socket_bind(nl, (1<<0), MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + int i; + + /* kobject uses a string based protocol, with no initial + * netlink header. + */ + for (i=0; i Date: Tue, 26 Mar 2013 13:30:11 -0700 Subject: headers: update netlink.h to 3.9 Use sanitized kernel header from 3.9 upstream kernel. Reported-by: Nicolas Dichtel Signed-off-by: Stephen Hemminger Signed-off-by: Pablo Neira Ayuso --- include/linux/netlink.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f55ed8c..ced0e1a 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -1,14 +1,14 @@ #ifndef __LINUX_NETLINK_H #define __LINUX_NETLINK_H -#include /* for sa_family_t */ +#include /* for __kernel_sa_family_t */ #include #define NETLINK_ROUTE 0 /* Routing/device hook */ #define NETLINK_UNUSED 1 /* Unused number */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ -#define NETLINK_FIREWALL 3 /* Firewalling hook */ -#define NETLINK_INET_DIAG 4 /* INET socket monitoring */ +#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */ +#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ #define NETLINK_XFRM 6 /* ipsec */ #define NETLINK_SELINUX 7 /* SELinux event notifications */ @@ -24,11 +24,15 @@ /* leave room for NETLINK_DM (DM Events) */ #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ #define NETLINK_ECRYPTFS 19 +#define NETLINK_RDMA 20 +#define NETLINK_CRYPTO 21 /* Crypto layer */ + +#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG #define MAX_LINKS 32 struct sockaddr_nl { - sa_family_t nl_family; /* AF_NETLINK */ + __kernel_sa_family_t nl_family; /* AF_NETLINK */ unsigned short nl_pad; /* zero */ __u32 nl_pid; /* port ID */ __u32 nl_groups; /* multicast groups mask */ @@ -48,6 +52,7 @@ struct nlmsghdr { #define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ #define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ #define NLM_F_ECHO 8 /* Echo this request */ +#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ /* Modifiers to GET request */ #define NLM_F_ROOT 0x100 /* specify tree root */ @@ -145,4 +150,4 @@ struct nlattr { #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) -#endif /* __LINUX_NETLINK_H */ +#endif /* __LINUX_NETLINK_H */ -- cgit v1.2.3 From 260759dfdebe774aba6866bf49c2928b2242bb7e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 26 Mar 2013 22:15:35 +0100 Subject: callback: fix missing handling of NLM_F_DUMP_INTR Propagate the error to the user-space application, that should retry. [ I have mangled this patch to document EINTR in mnl_cb_run. --pablo ] Signed-off-by: Stephen Hemminger Acked-by: Nicolas Dichtel Signed-off-by: Pablo Neira Ayuso --- src/callback.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/callback.c b/src/callback.c index 6337acc..f023401 100644 --- a/src/callback.c +++ b/src/callback.c @@ -65,6 +65,12 @@ __mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, return -1; } + /* dump was interrupted */ + if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) { + errno = EINTR; + return -1; + } + /* netlink data message handling */ if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { if (cb_data){ @@ -117,7 +123,8 @@ out: * This function propagates the callback return value. On error, it returns * -1 and errno is explicitly set. If the portID is not the expected, errno * is set to ESRCH. If the sequence number is not the expected, errno is set - * to EPROTO. + * to EPROTO. If the dump was interrupted, errno is set to EINTR and you should + * request a new fresh dump again. */ int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq, -- cgit v1.2.3 From efcfbadb265ced5289f64c76bff777f20565a13e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 24 Apr 2013 01:03:33 +0200 Subject: examples: rtnl-route-add improvements (including IPv6 support) Now, both IPv4 and IPv6 are supported simultaneously in one single file. While at it: * I moved the declarations to the beginning of the main function. * Renamed mask by prefix, which seems more appropriate to me. * Use RTPROTO_STATIC, as the route has been added by the administrator. * Set NLM_F_ACK, so we get a report from the kernel about our query and treat reply from the kernel. * Stricter argc checking. * Use perror instead of printf for error reporting. Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/rtnl-route-add.c | 81 +++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/examples/rtnl/rtnl-route-add.c b/examples/rtnl/rtnl-route-add.c index 6d166da..dd810c9 100644 --- a/examples/rtnl/rtnl-route-add.c +++ b/examples/rtnl/rtnl-route-add.c @@ -14,63 +14,83 @@ int main(int argc, char *argv[]) { + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct rtmsg *rtm; + uint32_t prefix, seq, portid; + union { + in_addr_t ip; + struct in6_addr ip6; + } dst; + union { + in_addr_t ip; + struct in6_addr ip6; + } gw; + int iface, ret, family = AF_INET; + 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]); + printf(" %s eth0 ffff::10.0.1.12 128 fdff::1\n", argv[0]); exit(EXIT_FAILURE); } - int iface; iface = if_nametoindex(argv[1]); if (iface == 0) { - printf("Bad interface name\n"); + perror("if_nametoindex"); exit(EXIT_FAILURE); } - in_addr_t dst; if (!inet_pton(AF_INET, argv[2], &dst)) { - printf("Bad destination\n"); - exit(EXIT_FAILURE); + if (!inet_pton(AF_INET6, argv[2], &dst)) { + perror("inet_pton"); + exit(EXIT_FAILURE); + } + family = AF_INET6; } - uint32_t mask; - if (sscanf(argv[3], "%u", &mask) == 0) { - printf("Bad CIDR\n"); + if (sscanf(argv[3], "%u", &prefix) == 0) { + perror("sscanf"); exit(EXIT_FAILURE); } - in_addr_t gw; - if (argc >= 5 && !inet_pton(AF_INET, argv[4], &gw)) { - printf("Bad gateway\n"); + if (argc == 5 && !inet_pton(family, argv[4], &gw)) { + perror("inet_pton"); exit(EXIT_FAILURE); } - struct mnl_socket *nl; - char buf[MNL_SOCKET_BUFFER_SIZE]; - 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); + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; + nlh->nlmsg_seq = 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_family = family; + rtm->rtm_dst_len = prefix; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; - rtm->rtm_protocol = RTPROT_BOOT; + rtm->rtm_protocol = RTPROT_STATIC; 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); + if (family == AF_INET) + mnl_attr_put_u32(nlh, RTA_DST, dst.ip); + else + mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), &dst); + mnl_attr_put_u32(nlh, RTA_OIF, iface); - if (argc >= 5) - mnl_attr_put_u32(nlh, RTA_GATEWAY, gw); + if (argc == 5) { + if (family == AF_INET) + mnl_attr_put_u32(nlh, RTA_GATEWAY, gw.ip); + else { + mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), + &gw.ip6); + } + } nl = mnl_socket_open(NETLINK_ROUTE); if (nl == NULL) { @@ -82,12 +102,25 @@ int main(int argc, char *argv[]) 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)); + if (ret < 0) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + + ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); + if (ret < 0) { + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } + mnl_socket_close(nl); return 0; -- cgit v1.2.3 From 7a965af1cbe9a9c42935c00657af78efd29db380 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 24 Apr 2013 12:36:24 +0200 Subject: examples: rtnl-route-event: add example to listen to IPv4/IPv6 routes Derived from rtnl-route-dump.c Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/rtnl-route-event.c | 330 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 examples/rtnl/rtnl-route-event.c diff --git a/examples/rtnl/rtnl-route-event.c b/examples/rtnl/rtnl-route-event.c new file mode 100644 index 0000000..16d0563 --- /dev/null +++ b/examples/rtnl/rtnl-route-event.c @@ -0,0 +1,330 @@ +/* This example is placed in the public domain. */ +#include +#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; inlmsg_type) { + case RTM_NEWROUTE: + printf("[NEW] "); + break; + case RTM_DELROUTE: + printf("[DEL] "); + break; + } + + /* protocol family = AF_INET | AF_INET6 */ + printf("family=%u ", rm->rtm_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", rm->rtm_flags); + + switch(rm->rtm_family) { + case AF_INET: + mnl_attr_parse(nlh, sizeof(*rm), data_ipv4_attr_cb, tb); + attributes_show_ipv4(tb); + break; + case AF_INET6: + mnl_attr_parse(nlh, sizeof(*rm), data_ipv6_attr_cb, tb); + attributes_show_ipv6(tb); + break; + } + printf("\n"); + + return MNL_CB_OK; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret; + + nl = mnl_socket_open(NETLINK_ROUTE); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE, + 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 <= 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 From cf813753e8738c781e33de955f9733a27c65229f Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 24 Apr 2013 13:02:15 +0200 Subject: examples: rtnl-route-event: update Makefile.am So you can compile rtnl-route-event via `make check' Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/Makefile.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/rtnl/Makefile.am b/examples/rtnl/Makefile.am index 3cc8995..abe3e9b 100644 --- a/examples/rtnl/Makefile.am +++ b/examples/rtnl/Makefile.am @@ -4,7 +4,8 @@ check_PROGRAMS = rtnl-link-dump rtnl-link-dump2 rtnl-link-dump3 \ rtnl-link-event \ rtnl-link-set \ rtnl-route-add \ - rtnl-route-dump + rtnl-route-dump \ + rtnl-route-event rtnl_link_dump_SOURCES = rtnl-link-dump.c rtnl_link_dump_LDADD = ../../src/libmnl.la @@ -26,3 +27,6 @@ rtnl_link_set_LDADD = ../../src/libmnl.la rtnl_route_dump_SOURCES = rtnl-route-dump.c rtnl_route_dump_LDADD = ../../src/libmnl.la + +rtnl_route_event_SOURCES = rtnl-route-event.c +rtnl_route_event_LDADD = ../../src/libmnl.la -- cgit v1.2.3 From 3b8a8e462ee3ed33a95c784b6c77c33377210ca3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 25 Apr 2013 15:19:58 +0200 Subject: examples: rtnl-route-add: fix typo in IPv6 support Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/rtnl-route-add.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rtnl/rtnl-route-add.c b/examples/rtnl/rtnl-route-add.c index dd810c9..6d070b8 100644 --- a/examples/rtnl/rtnl-route-add.c +++ b/examples/rtnl/rtnl-route-add.c @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) if (family == AF_INET) mnl_attr_put_u32(nlh, RTA_GATEWAY, gw.ip); else { - mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), + mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr), &gw.ip6); } } -- cgit v1.2.3 From 050d592eee6c96ae8e08c6dfefe42f10685f0718 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 2 May 2013 17:24:57 +0200 Subject: examples: rtnl-route-dump: display also metric/priority If present in the route message, otherwise simply skip it. Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/rtnl-route-dump.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/rtnl/rtnl-route-dump.c b/examples/rtnl/rtnl-route-dump.c index a798515..59e0a9d 100644 --- a/examples/rtnl/rtnl-route-dump.c +++ b/examples/rtnl/rtnl-route-dump.c @@ -51,6 +51,9 @@ static void attributes_show_ipv4(struct nlattr *tb[]) struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]); printf("gw=%s ", inet_ntoa(*addr)); } + if (tb[RTA_PRIORITY]) { + printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY])); + } if (tb[RTA_METRICS]) { int i; struct nlattr *tbx[RTAX_MAX+1] = {}; -- cgit v1.2.3 From e2af6ce3d5f97600e8c953612608523a4ff727bd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 27 May 2013 20:30:49 +0200 Subject: examples: rtnl-link-dump: display HW address --- examples/rtnl/rtnl-link-dump.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/examples/rtnl/rtnl-link-dump.c b/examples/rtnl/rtnl-link-dump.c index 159f3b6..f717cea 100644 --- a/examples/rtnl/rtnl-link-dump.c +++ b/examples/rtnl/rtnl-link-dump.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -19,6 +20,12 @@ static int data_attr_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; switch(type) { + case IFLA_ADDRESS: + if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; case IFLA_MTU: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); @@ -55,7 +62,18 @@ static int data_cb(const struct nlmsghdr *nlh, void *data) 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("name=%s ", mnl_attr_get_str(tb[IFLA_IFNAME])); + } + if (tb[IFLA_ADDRESS]) { + uint8_t *hwaddr = mnl_attr_get_payload(tb[IFLA_ADDRESS]); + int i; + + printf("hwaddr="); + for (i=0; i Date: Mon, 27 May 2013 20:54:08 +0200 Subject: examples: add rtnl-addr-dump Signed-off-by: Pablo Neira Ayuso --- examples/rtnl/Makefile.am | 6 +- examples/rtnl/rtnl-addr-dump.c | 133 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 examples/rtnl/rtnl-addr-dump.c diff --git a/examples/rtnl/Makefile.am b/examples/rtnl/Makefile.am index abe3e9b..24769b6 100644 --- a/examples/rtnl/Makefile.am +++ b/examples/rtnl/Makefile.am @@ -1,12 +1,16 @@ include $(top_srcdir)/Make_global.am -check_PROGRAMS = rtnl-link-dump rtnl-link-dump2 rtnl-link-dump3 \ +check_PROGRAMS = rtnl-addr-dump \ + rtnl-link-dump rtnl-link-dump2 rtnl-link-dump3 \ rtnl-link-event \ rtnl-link-set \ rtnl-route-add \ rtnl-route-dump \ rtnl-route-event +rtnl_addr_dump_SOURCES = rtnl-addr-dump.c +rtnl_addr_dump_LDADD = ../../src/libmnl.la + rtnl_link_dump_SOURCES = rtnl-link-dump.c rtnl_link_dump_LDADD = ../../src/libmnl.la diff --git a/examples/rtnl/rtnl-addr-dump.c b/examples/rtnl/rtnl-addr-dump.c new file mode 100644 index 0000000..156563b --- /dev/null +++ b/examples/rtnl/rtnl-addr-dump.c @@ -0,0 +1,133 @@ +/* This example is placed in the public domain. */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static int data_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, IFA_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case IFA_ADDRESS: + if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 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[IFLA_MAX+1] = {}; + struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh); + + printf("index=%d family=%d ", ifa->ifa_index, ifa->ifa_family); + + mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb); + printf("addr="); + if (tb[IFA_ADDRESS]) { + void *addr = mnl_attr_get_payload(tb[IFA_ADDRESS]); + char out[INET6_ADDRSTRLEN]; + + if (inet_ntop(ifa->ifa_family, addr, out, sizeof(out))) + printf("%s ", out); + } + printf("scope="); + switch(ifa->ifa_scope) { + case 0: + printf("global "); + break; + case 200: + printf("site "); + break; + case 253: + printf("link "); + break; + case 254: + printf("host "); + break; + case 255: + printf("nowhere "); + break; + default: + printf("%d ", ifa->ifa_scope); + break; + } + + printf("\n"); + return MNL_CB_OK; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct rtgenmsg *rt; + int ret; + unsigned int seq, portid; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_GETADDR; + 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)); + if (strcmp(argv[1], "inet") == 0) + rt->rtgen_family = AF_INET; + else if (strcmp(argv[1], "inet6") == 0) + rt->rtgen_family = AF_INET6; + + 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 From c4f823a66a5f35dc00d37500527d6703dcd9d5a0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 31 May 2013 19:15:07 +0200 Subject: examples: netfilter: add nfct-dump Signed-off-by: Pablo Neira Ayuso --- examples/netfilter/Makefile.am | 4 + examples/netfilter/nfct-dump.c | 318 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 examples/netfilter/nfct-dump.c diff --git a/examples/netfilter/Makefile.am b/examples/netfilter/Makefile.am index 98458fd..2b295fe 100644 --- a/examples/netfilter/Makefile.am +++ b/examples/netfilter/Makefile.am @@ -2,6 +2,7 @@ include $(top_srcdir)/Make_global.am check_PROGRAMS = nf-queue \ nf-log \ + nfct-dump \ nfct-event \ nfct-create-batch @@ -11,6 +12,9 @@ nf_queue_LDADD = ../../src/libmnl.la nf_log_SOURCES = nf-log.c nf_log_LDADD = ../../src/libmnl.la +nfct_dump_SOURCES = nfct-dump.c +nfct_dump_LDADD = ../../src/libmnl.la + nfct_event_SOURCES = nfct-event.c nfct_event_LDADD = ../../src/libmnl.la diff --git a/examples/netfilter/nfct-dump.c b/examples/netfilter/nfct-dump.c new file mode 100644 index 0000000..ce05bbb --- /dev/null +++ b/examples/netfilter/nfct-dump.c @@ -0,0 +1,318 @@ +/* This example is placed in the public domain. */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int parse_counters_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_COUNTERS_PACKETS: + case CTA_COUNTERS_BYTES: + if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void print_counters(const struct nlattr *nest) +{ + struct nlattr *tb[CTA_COUNTERS_MAX+1] = {}; + + mnl_attr_parse_nested(nest, parse_counters_cb, tb); + if (tb[CTA_COUNTERS_PACKETS]) { + printf("packets=%"PRIu64" ", + be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS]))); + } + if (tb[CTA_COUNTERS_BYTES]) { + printf("bytes=%"PRIu64" ", + be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES]))); + } +} + +static int parse_ip_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = 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; + case CTA_IP_V6_SRC: + case CTA_IP_V6_DST: + if (mnl_attr_validate2(attr, MNL_TYPE_BINARY, + sizeof(struct in6_addr)) < 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)); + } + if (tb[CTA_IP_V6_SRC]) { + struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_SRC]); + char out[INET6_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET6, in, out, sizeof(out))) + printf("src=%s ", out); + } + if (tb[CTA_IP_V6_DST]) { + struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_DST]); + char out[INET6_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET6, in, out, sizeof(out))) + printf("dst=%s ", out); + } +} + +static int parse_proto_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = 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 = 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 = 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: + case CTA_COUNTERS_ORIG: + case CTA_COUNTERS_REPLY: + 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); + + 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]))); + + if (tb[CTA_COUNTERS_ORIG]) { + printf("original "); + print_counters(tb[CTA_COUNTERS_ORIG]); + } + + if (tb[CTA_COUNTERS_REPLY]) { + printf("reply "); + print_counters(tb[CTA_COUNTERS_REPLY]); + } + + printf("\n"); + return MNL_CB_OK; +} + +int main(void) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct nfgenmsg *nfh; + uint32_t seq, portid; + int ret; + + 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); + } + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET; + nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; + nlh->nlmsg_seq = seq = time(NULL); + + nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); + nfh->nfgen_family = AF_INET; + nfh->version = NFNETLINK_V0; + nfh->res_id = 0; + + ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + 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, seq, portid, data_cb, NULL); + if (ret == -1) { + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } else if (ret <= MNL_CB_STOP) + break; + } + + mnl_socket_close(nl); + + return 0; +} -- cgit v1.2.3 From 419513fb3bb8a021ade9ecda8f6b7c9bb70ad7e4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 11 Jun 2013 17:57:43 +0200 Subject: include: cache copy of nfnetlink_conntrack.h To ensure that examples compile in any installation. This header is not installed in the system. Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- include/linux/Makefile.am | 1 + include/linux/netfilter/Makefile.am | 1 + include/linux/netfilter/nfnetlink_conntrack.h | 252 ++++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 include/linux/netfilter/Makefile.am create mode 100644 include/linux/netfilter/nfnetlink_conntrack.h diff --git a/configure.ac b/configure.ac index 7c611fa..dcd3cf8 100644 --- a/configure.ac +++ b/configure.ac @@ -27,5 +27,5 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ -Wformat=2 -pipe" AC_SUBST([regular_CPPFLAGS]) AC_SUBST([regular_CFLAGS]) -AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libmnl/Makefile include/linux/Makefile examples/Makefile examples/genl/Makefile examples/kobject/Makefile examples/netfilter/Makefile examples/rtnl/Makefile libmnl.pc doxygen.cfg]) +AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/libmnl/Makefile include/linux/Makefile include/linux/netfilter/Makefile examples/Makefile examples/genl/Makefile examples/kobject/Makefile examples/netfilter/Makefile examples/rtnl/Makefile libmnl.pc doxygen.cfg]) AC_OUTPUT diff --git a/include/linux/Makefile.am b/include/linux/Makefile.am index 2d02887..95f82d2 100644 --- a/include/linux/Makefile.am +++ b/include/linux/Makefile.am @@ -1 +1,2 @@ +SUBDIRS = netfilter noinst_HEADERS = netlink.h diff --git a/include/linux/netfilter/Makefile.am b/include/linux/netfilter/Makefile.am new file mode 100644 index 0000000..64a975e --- /dev/null +++ b/include/linux/netfilter/Makefile.am @@ -0,0 +1 @@ +noinst_HEADERS = nfnetlink_conntrack.h diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h new file mode 100644 index 0000000..08fabc6 --- /dev/null +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -0,0 +1,252 @@ +#ifndef _IPCONNTRACK_NETLINK_H +#define _IPCONNTRACK_NETLINK_H +#include + +enum cntl_msg_types { + IPCTNL_MSG_CT_NEW, + IPCTNL_MSG_CT_GET, + IPCTNL_MSG_CT_DELETE, + IPCTNL_MSG_CT_GET_CTRZERO, + IPCTNL_MSG_CT_GET_STATS_CPU, + IPCTNL_MSG_CT_GET_STATS, + IPCTNL_MSG_CT_GET_DYING, + IPCTNL_MSG_CT_GET_UNCONFIRMED, + + IPCTNL_MSG_MAX +}; + +enum ctnl_exp_msg_types { + IPCTNL_MSG_EXP_NEW, + IPCTNL_MSG_EXP_GET, + IPCTNL_MSG_EXP_DELETE, + IPCTNL_MSG_EXP_GET_STATS_CPU, + + IPCTNL_MSG_EXP_MAX +}; + + +enum ctattr_type { + CTA_UNSPEC, + CTA_TUPLE_ORIG, + CTA_TUPLE_REPLY, + CTA_STATUS, + CTA_PROTOINFO, + CTA_HELP, + CTA_NAT_SRC, +#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */ + CTA_TIMEOUT, + CTA_MARK, + CTA_COUNTERS_ORIG, + CTA_COUNTERS_REPLY, + CTA_USE, + CTA_ID, + CTA_NAT_DST, + CTA_TUPLE_MASTER, + CTA_NAT_SEQ_ADJ_ORIG, + CTA_NAT_SEQ_ADJ_REPLY, + CTA_SECMARK, /* obsolete */ + CTA_ZONE, + CTA_SECCTX, + CTA_TIMESTAMP, + CTA_MARK_MASK, + CTA_LABELS, + CTA_LABELS_MASK, + __CTA_MAX +}; +#define CTA_MAX (__CTA_MAX - 1) + +enum ctattr_tuple { + CTA_TUPLE_UNSPEC, + CTA_TUPLE_IP, + CTA_TUPLE_PROTO, + __CTA_TUPLE_MAX +}; +#define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1) + +enum ctattr_ip { + CTA_IP_UNSPEC, + CTA_IP_V4_SRC, + CTA_IP_V4_DST, + CTA_IP_V6_SRC, + CTA_IP_V6_DST, + __CTA_IP_MAX +}; +#define CTA_IP_MAX (__CTA_IP_MAX - 1) + +enum ctattr_l4proto { + CTA_PROTO_UNSPEC, + CTA_PROTO_NUM, + CTA_PROTO_SRC_PORT, + CTA_PROTO_DST_PORT, + CTA_PROTO_ICMP_ID, + CTA_PROTO_ICMP_TYPE, + CTA_PROTO_ICMP_CODE, + CTA_PROTO_ICMPV6_ID, + CTA_PROTO_ICMPV6_TYPE, + CTA_PROTO_ICMPV6_CODE, + __CTA_PROTO_MAX +}; +#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1) + +enum ctattr_protoinfo { + CTA_PROTOINFO_UNSPEC, + CTA_PROTOINFO_TCP, + CTA_PROTOINFO_DCCP, + CTA_PROTOINFO_SCTP, + __CTA_PROTOINFO_MAX +}; +#define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) + +enum ctattr_protoinfo_tcp { + CTA_PROTOINFO_TCP_UNSPEC, + CTA_PROTOINFO_TCP_STATE, + CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, + CTA_PROTOINFO_TCP_WSCALE_REPLY, + CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, + CTA_PROTOINFO_TCP_FLAGS_REPLY, + __CTA_PROTOINFO_TCP_MAX +}; +#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) + +enum ctattr_protoinfo_dccp { + CTA_PROTOINFO_DCCP_UNSPEC, + CTA_PROTOINFO_DCCP_STATE, + CTA_PROTOINFO_DCCP_ROLE, + CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, + __CTA_PROTOINFO_DCCP_MAX, +}; +#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) + +enum ctattr_protoinfo_sctp { + CTA_PROTOINFO_SCTP_UNSPEC, + CTA_PROTOINFO_SCTP_STATE, + CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, + CTA_PROTOINFO_SCTP_VTAG_REPLY, + __CTA_PROTOINFO_SCTP_MAX +}; +#define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1) + +enum ctattr_counters { + CTA_COUNTERS_UNSPEC, + CTA_COUNTERS_PACKETS, /* 64bit counters */ + CTA_COUNTERS_BYTES, /* 64bit counters */ + CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */ + CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */ + __CTA_COUNTERS_MAX +}; +#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) + +enum ctattr_tstamp { + CTA_TIMESTAMP_UNSPEC, + CTA_TIMESTAMP_START, + CTA_TIMESTAMP_STOP, + __CTA_TIMESTAMP_MAX +}; +#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1) + +enum ctattr_nat { + CTA_NAT_UNSPEC, + CTA_NAT_V4_MINIP, +#define CTA_NAT_MINIP CTA_NAT_V4_MINIP + CTA_NAT_V4_MAXIP, +#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP + CTA_NAT_PROTO, + CTA_NAT_V6_MINIP, + CTA_NAT_V6_MAXIP, + __CTA_NAT_MAX +}; +#define CTA_NAT_MAX (__CTA_NAT_MAX - 1) + +enum ctattr_protonat { + CTA_PROTONAT_UNSPEC, + CTA_PROTONAT_PORT_MIN, + CTA_PROTONAT_PORT_MAX, + __CTA_PROTONAT_MAX +}; +#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) + +enum ctattr_natseq { + CTA_NAT_SEQ_UNSPEC, + CTA_NAT_SEQ_CORRECTION_POS, + CTA_NAT_SEQ_OFFSET_BEFORE, + CTA_NAT_SEQ_OFFSET_AFTER, + __CTA_NAT_SEQ_MAX +}; +#define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1) + +enum ctattr_expect { + CTA_EXPECT_UNSPEC, + CTA_EXPECT_MASTER, + CTA_EXPECT_TUPLE, + CTA_EXPECT_MASK, + CTA_EXPECT_TIMEOUT, + CTA_EXPECT_ID, + CTA_EXPECT_HELP_NAME, + CTA_EXPECT_ZONE, + CTA_EXPECT_FLAGS, + CTA_EXPECT_CLASS, + CTA_EXPECT_NAT, + CTA_EXPECT_FN, + __CTA_EXPECT_MAX +}; +#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) + +enum ctattr_expect_nat { + CTA_EXPECT_NAT_UNSPEC, + CTA_EXPECT_NAT_DIR, + CTA_EXPECT_NAT_TUPLE, + __CTA_EXPECT_NAT_MAX +}; +#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1) + +enum ctattr_help { + CTA_HELP_UNSPEC, + CTA_HELP_NAME, + CTA_HELP_INFO, + __CTA_HELP_MAX +}; +#define CTA_HELP_MAX (__CTA_HELP_MAX - 1) + +enum ctattr_secctx { + CTA_SECCTX_UNSPEC, + CTA_SECCTX_NAME, + __CTA_SECCTX_MAX +}; +#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1) + +enum ctattr_stats_cpu { + CTA_STATS_UNSPEC, + CTA_STATS_SEARCHED, + CTA_STATS_FOUND, + CTA_STATS_NEW, + CTA_STATS_INVALID, + CTA_STATS_IGNORE, + CTA_STATS_DELETE, + CTA_STATS_DELETE_LIST, + CTA_STATS_INSERT, + CTA_STATS_INSERT_FAILED, + CTA_STATS_DROP, + CTA_STATS_EARLY_DROP, + CTA_STATS_ERROR, + CTA_STATS_SEARCH_RESTART, + __CTA_STATS_MAX, +}; +#define CTA_STATS_MAX (__CTA_STATS_MAX - 1) + +enum ctattr_stats_global { + CTA_STATS_GLOBAL_UNSPEC, + CTA_STATS_GLOBAL_ENTRIES, + __CTA_STATS_GLOBAL_MAX, +}; +#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1) + +enum ctattr_expect_stats { + CTA_STATS_EXP_UNSPEC, + CTA_STATS_EXP_NEW, + CTA_STATS_EXP_CREATE, + CTA_STATS_EXP_DELETE, + __CTA_STATS_EXP_MAX, +}; +#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1) + +#endif /* _IPCONNTRACK_NETLINK_H */ -- cgit v1.2.3 From 857c683b5cabe5933650a164146fdeaecfda565b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 11 Jun 2013 17:56:37 +0200 Subject: examples: netfilter: add nfct daemon skeleton code This patch adds the skeleton code for a daemon that collects statistics via ctnetlink. Consider it a simplified version of ulogd2. It also contains some documentation on several interesting tweaks. Signed-off-by: Pablo Neira Ayuso --- examples/netfilter/Makefile.am | 6 +- examples/netfilter/nfct-daemon.c | 365 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 examples/netfilter/nfct-daemon.c diff --git a/examples/netfilter/Makefile.am b/examples/netfilter/Makefile.am index 2b295fe..4bae05f 100644 --- a/examples/netfilter/Makefile.am +++ b/examples/netfilter/Makefile.am @@ -4,7 +4,8 @@ check_PROGRAMS = nf-queue \ nf-log \ nfct-dump \ nfct-event \ - nfct-create-batch + nfct-create-batch \ + nfct-daemon nf_queue_SOURCES = nf-queue.c nf_queue_LDADD = ../../src/libmnl.la @@ -15,6 +16,9 @@ nf_log_LDADD = ../../src/libmnl.la nfct_dump_SOURCES = nfct-dump.c nfct_dump_LDADD = ../../src/libmnl.la +nfct_daemon_SOURCES = nfct-daemon.c +nfct_daemon_LDADD = ../../src/libmnl.la + nfct_event_SOURCES = nfct-event.c nfct_event_LDADD = ../../src/libmnl.la diff --git a/examples/netfilter/nfct-daemon.c b/examples/netfilter/nfct-daemon.c new file mode 100644 index 0000000..5258537 --- /dev/null +++ b/examples/netfilter/nfct-daemon.c @@ -0,0 +1,365 @@ +/* A very simple skeleton code that implements a daemon that collects + * conntrack statistics from ctnetlink. + * + * This example is placed in the public domain. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +struct nstats { + LIST_ENTRY(nstats) list; + + uint8_t family; + + union { + struct in_addr ip; + struct in6_addr ip6; + }; + uint64_t pkts, bytes; +}; + +static LIST_HEAD(nstats_head, nstats) nstats_head; + +static int parse_counters_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_COUNTERS_PACKETS: + case CTA_COUNTERS_BYTES: + if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void parse_counters(const struct nlattr *nest, struct nstats *ns) +{ + struct nlattr *tb[CTA_COUNTERS_MAX+1] = {}; + + mnl_attr_parse_nested(nest, parse_counters_cb, tb); + if (tb[CTA_COUNTERS_PACKETS]) + ns->pkts += be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS])); + + if (tb[CTA_COUNTERS_BYTES]) + ns->bytes += be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES])); +} + +static int parse_ip_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = 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; + case CTA_IP_V6_SRC: + case CTA_IP_V6_DST: + if (mnl_attr_validate2(attr, MNL_TYPE_BINARY, + sizeof(struct in6_addr)) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void parse_ip(const struct nlattr *nest, struct nstats *ns) +{ + 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]); + ns->ip = *in; + ns->family = AF_INET; + } + if (tb[CTA_IP_V6_SRC]) { + struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_SRC]); + ns->ip6 = *in; + ns->family = AF_INET6; + } +} + +static int parse_tuple_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = 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; + } + tb[type] = attr; + return MNL_CB_OK; +} + +static void parse_tuple(const struct nlattr *nest, struct nstats *ns) +{ + struct nlattr *tb[CTA_TUPLE_MAX+1] = {}; + + mnl_attr_parse_nested(nest, parse_tuple_cb, tb); + if (tb[CTA_TUPLE_IP]) + parse_ip(tb[CTA_TUPLE_IP], ns); +} + +static int data_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = 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: + case CTA_COUNTERS_ORIG: + case CTA_COUNTERS_REPLY: + 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[CTA_MAX+1] = {}; + struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); + struct nstats ns = {}, *cur, *new; + + mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb); + if (tb[CTA_TUPLE_ORIG]) + parse_tuple(tb[CTA_TUPLE_ORIG], &ns); + + if (tb[CTA_COUNTERS_ORIG]) + parse_counters(tb[CTA_COUNTERS_ORIG], &ns); + + if (tb[CTA_COUNTERS_REPLY]) + parse_counters(tb[CTA_COUNTERS_REPLY], &ns); + + /* Look up for existing statistics object ... */ + LIST_FOREACH(cur, &nstats_head, list) { + if (memcmp(&ns.ip6, &cur->ip6, sizeof(struct in6_addr)) == 0) { + /* ... and sum counters */ + cur->pkts += ns.pkts; + cur->bytes += ns.bytes; + return MNL_CB_OK; + } + } + + /* ... if it does not exist, add new stats object */ + new = calloc(1, sizeof(struct nstats)); + if (!new) + return MNL_CB_OK; + + new->family = ns.family; + new->ip6 = ns.ip6; + new->pkts = ns.pkts; + new->bytes = ns.bytes; + + LIST_INSERT_HEAD(&nstats_head, new, list); + + return MNL_CB_OK; +} + +static int handle(struct mnl_socket *nl) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + int ret; + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + if (ret == -1) { + /* It only happens if NETLINK_NO_ENOBUFS is not set, it means + * we are leaking statistics. + */ + if (errno == ENOBUFS) { + fprintf(stderr, "The daemon has hit ENOBUFS, you can " + "increase the size of your receiver " + "buffer to mitigate this or enable " + "reliable delivery.\n"); + } else { + perror("mnl_socket_recvfrom"); + } + return -1; + } + + ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL); + if (ret == -1) { + perror("mnl_cb_run"); + return -1; + } else if (ret <= MNL_CB_STOP) + return 0; + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct nfgenmsg *nfh; + struct nstats *cur; + struct timeval tv = {}; + int ret, secs, on = 1, buffersize = (1 << 22); + + if (argc != 2) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + secs = atoi(argv[1]); + + LIST_INIT(&nstats_head); + + printf("Polling every %d seconds from kernel...\n", secs); + + /* Set high priority for this process, less chances to overrun + * the netlink receiver buffer since the scheduler gives this process + * more chances to run. + */ + nice(-20); + + /* Open netlink socket to operate with netfilter */ + nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + /* Subscribe to destroy events to avoid leaking counters. The same + * socket is used to periodically atomically dump and reset counters. + */ + if (mnl_socket_bind(nl, NF_NETLINK_CONNTRACK_DESTROY, + MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + + /* Set netlink receiver buffer to 16 MBytes, to avoid packet drops */ + setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_RCVBUFFORCE, + &buffersize, sizeof(socklen_t)); + + /* The two tweaks below enable reliable event delivery, packets may + * be dropped if the netlink receiver buffer overruns. This happens ... + * + * a) if the kernel spams this user-space process until the receiver + * is filled. + * + * or: + * + * b) if the user-space process does not pull messages from the + * receiver buffer so often. + */ + setsockopt(mnl_socket_get_fd(nl), SOL_NETLINK, + NETLINK_BROADCAST_ERROR, &on, sizeof(int)); + setsockopt(mnl_socket_get_fd(nl), SOL_NETLINK, NETLINK_NO_ENOBUFS, + &on, sizeof(int)); + + nlh = mnl_nlmsg_put_header(buf); + /* Counters are atomically zeroed in each dump */ + nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | + IPCTNL_MSG_CT_GET_CTRZERO; + nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; + + nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); + nfh->nfgen_family = AF_INET; + nfh->version = NFNETLINK_V0; + nfh->res_id = 0; + + /* Filter by mark: We only want to dump entries whose mark is zero */ + mnl_attr_put_u32(nlh, CTA_MARK, htonl(0)); + mnl_attr_put_u32(nlh, CTA_MARK_MASK, htonl(0xffffffff)); + + while (1) { + int fd_max = mnl_socket_get_fd(nl); + fd_set readfds; + + /* Every N seconds ... */ + if (tv.tv_sec == 0 && tv.tv_usec == 0) { + /* ... request a fresh dump of the table from kernel */ + ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + return -1; + } + tv.tv_sec = secs; + tv.tv_usec = 0; + + /* print the content of the list */ + LIST_FOREACH(cur, &nstats_head, list) { + char out[INET6_ADDRSTRLEN]; + + if (inet_ntop(cur->family, &cur->ip, out, sizeof(out))) + printf("src=%s ", out); + + printf("counters %"PRIu64" %"PRIu64"\n", + cur->pkts, cur->bytes); + } + } + + FD_ZERO(&readfds); + FD_SET(mnl_socket_get_fd(nl), &readfds); + + ret = select(fd_max+1, &readfds, NULL, NULL, &tv); + if (ret < 0) { + if (errno == EINTR) + continue; + + perror("select"); + exit(EXIT_FAILURE); + } + + /* Handled event and periodic atomic-dump-and-reset messages */ + if (FD_ISSET(mnl_socket_get_fd(nl), &readfds)) { + if (handle(nl) < 0) + return EXIT_FAILURE; + } + } + + mnl_socket_close(nl); + + return 0; +} -- cgit v1.2.3 From 5b8a0c7479776f7781e497dd5fdacc17d9aad0ae Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 15 Jul 2013 17:45:32 +0200 Subject: include: don't force compiler to enter C++11 mode Thomas reports that g++ forces you to enable C++11 mode if you want to use . Tested with g++ (GCC) 4.4.4. He reports that this compiles fine without the special headers. So let's get rid of them. This reverts bb8c40e. Reported-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso Tested-by: Thomas Jarosch --- include/libmnl/libmnl.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h index a647fd9..223709c 100644 --- a/include/libmnl/libmnl.h +++ b/include/libmnl/libmnl.h @@ -1,14 +1,9 @@ #ifndef _LIBMNL_H_ #define _LIBMNL_H_ -#ifdef __cplusplus -# include -# include -#else -# include /* not in C++ */ -# include -# include -#endif +#include +#include +#include #include #include /* for sa_family_t */ #include -- cgit v1.2.3 From 006b3bb603ec2ba246c872c8b06ce43d2225dd63 Mon Sep 17 00:00:00 2001 From: Gustavo Zacarias Date: Tue, 10 Sep 2013 16:23:26 -0300 Subject: configure: uclinux is also linux Signed-off-by: Gustavo Zacarias Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index dcd3cf8..313a015 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ AC_DISABLE_STATIC LT_INIT CHECK_GCC_FVISIBILITY case "$host" in -*-*-linux*) ;; +*-*-linux* | *-*-uclinux*) ;; *) AC_MSG_ERROR([Linux only, dude!]);; esac -- cgit v1.2.3 From 97d1ff851f00fb7caec35f51d43b1ea53e80d9f9 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Wed, 4 Dec 2013 11:06:28 -0800 Subject: doc: mnl_socket_open returns NULL on error Signed-off-by: Florian Westphal --- src/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.c b/src/socket.c index 6d54563..676a08a 100644 --- a/src/socket.c +++ b/src/socket.c @@ -107,7 +107,7 @@ EXPORT_SYMBOL(mnl_socket_get_portid); * mnl_socket_open - open a netlink socket * \param bus the netlink socket bus ID (see NETLINK_* constants) * - * On error, it returns -1 and errno is appropriately set. Otherwise, it + * On error, it returns NULL and errno is appropriately set. Otherwise, it * returns a valid pointer to the mnl_socket structure. */ struct mnl_socket *mnl_socket_open(int bus) -- cgit v1.2.3 From c7a66dd8c1cc25889fdb91c5ef92e92d55119497 Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:21:34 +0900 Subject: examples: set attr table Florian adviced rtnl-route-event.c has same problem Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- examples/rtnl/rtnl-route-dump.c | 4 ++++ examples/rtnl/rtnl-route-event.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/examples/rtnl/rtnl-route-dump.c b/examples/rtnl/rtnl-route-dump.c index 59e0a9d..33cb2df 100644 --- a/examples/rtnl/rtnl-route-dump.c +++ b/examples/rtnl/rtnl-route-dump.c @@ -13,6 +13,8 @@ static int data_attr_cb2(const struct nlattr *attr, void *data) { + const struct nlattr **tb = data; + /* skip unsupported attribute in user-space */ if (mnl_attr_type_valid(attr, RTAX_MAX) < 0) return MNL_CB_OK; @@ -21,6 +23,8 @@ static int data_attr_cb2(const struct nlattr *attr, void *data) perror("mnl_attr_validate"); return MNL_CB_ERROR; } + + tb[mnl_attr_get_type(attr)] = attr; return MNL_CB_OK; } diff --git a/examples/rtnl/rtnl-route-event.c b/examples/rtnl/rtnl-route-event.c index 16d0563..badba2d 100644 --- a/examples/rtnl/rtnl-route-event.c +++ b/examples/rtnl/rtnl-route-event.c @@ -13,6 +13,8 @@ static int data_attr_cb2(const struct nlattr *attr, void *data) { + const struct nlattr **tb = data; + /* skip unsupported attribute in user-space */ if (mnl_attr_type_valid(attr, RTAX_MAX) < 0) return MNL_CB_OK; @@ -21,6 +23,8 @@ static int data_attr_cb2(const struct nlattr *attr, void *data) perror("mnl_attr_validate"); return MNL_CB_ERROR; } + + tb[mnl_attr_get_type(attr)] = attr; return MNL_CB_OK; } -- cgit v1.2.3 From 73b9805968e430d4328f5eca78574b6c0987f2cf Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:23:10 +0900 Subject: examples: fix trivial error message Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- examples/genl/genl-family-get.c | 2 +- examples/netfilter/nf-log.c | 12 ++++++------ examples/netfilter/nf-queue.c | 14 +++++++------- examples/netfilter/nfct-create-batch.c | 4 ++-- examples/netfilter/nfct-daemon.c | 4 ++-- examples/netfilter/nfct-dump.c | 4 ++-- examples/rtnl/rtnl-addr-dump.c | 2 +- examples/rtnl/rtnl-link-dump.c | 4 ++-- examples/rtnl/rtnl-link-dump2.c | 4 ++-- examples/rtnl/rtnl-link-dump3.c | 2 +- examples/rtnl/rtnl-link-event.c | 2 +- examples/rtnl/rtnl-link-set.c | 6 +++--- examples/rtnl/rtnl-route-add.c | 2 +- examples/rtnl/rtnl-route-dump.c | 4 ++-- examples/rtnl/rtnl-route-event.c | 2 +- 15 files changed, 34 insertions(+), 34 deletions(-) diff --git a/examples/genl/genl-family-get.c b/examples/genl/genl-family-get.c index 50f7ea3..ba8de12 100644 --- a/examples/genl/genl-family-get.c +++ b/examples/genl/genl-family-get.c @@ -219,7 +219,7 @@ int main(int argc, char *argv[]) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/netfilter/nf-log.c b/examples/netfilter/nf-log.c index a862912..901bd80 100644 --- a/examples/netfilter/nf-log.c +++ b/examples/netfilter/nf-log.c @@ -39,14 +39,14 @@ static int parse_attr_cb(const struct nlattr *attr, void *data) case NFULA_TIMESTAMP: if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(struct nfulnl_msg_packet_timestamp)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; case NFULA_HWADDR: if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(struct nfulnl_msg_packet_hw)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; @@ -174,28 +174,28 @@ int main(int argc, char *argv[]) nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_UNBIND); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_BIND); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } nlh = nflog_build_cfg_request(buf, NFULNL_CFG_CMD_BIND, qnum); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } nlh = nflog_build_cfg_params(buf, NFULNL_COPY_PACKET, 0xFFFF, qnum); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/netfilter/nf-queue.c b/examples/netfilter/nf-queue.c index c66611f..6b7c30e 100644 --- a/examples/netfilter/nf-queue.c +++ b/examples/netfilter/nf-queue.c @@ -39,14 +39,14 @@ static int parse_attr_cb(const struct nlattr *attr, void *data) case NFQA_TIMESTAMP: if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(struct nfqnl_msg_packet_timestamp)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); 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"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; @@ -188,28 +188,28 @@ int main(int argc, char *argv[]) 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"); + perror("mnl_socket_sendto"); 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"); + perror("mnl_socket_sendto"); 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"); + perror("mnl_socket_sendto"); 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"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } @@ -230,7 +230,7 @@ int main(int argc, char *argv[]) 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"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/netfilter/nfct-create-batch.c b/examples/netfilter/nfct-create-batch.c index dd6623f..40cd2f6 100644 --- a/examples/netfilter/nfct-create-batch.c +++ b/examples/netfilter/nfct-create-batch.c @@ -87,7 +87,7 @@ send_batch(struct mnl_socket *nl, struct mnl_nlmsg_batch *b, int portid) ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b), len); if (ret == -1) { - perror("mnl_socket_recvfrom"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } @@ -116,7 +116,7 @@ send_batch(struct mnl_socket *nl, struct mnl_nlmsg_batch *b, int portid) NULL, NULL, cb_ctl_array, MNL_ARRAY_SIZE(cb_ctl_array)); if (ret == -1) { - perror("mnl_cb_run"); + perror("mnl_cb_run2"); exit(EXIT_FAILURE); } diff --git a/examples/netfilter/nfct-daemon.c b/examples/netfilter/nfct-daemon.c index 5258537..a9b93db 100644 --- a/examples/netfilter/nfct-daemon.c +++ b/examples/netfilter/nfct-daemon.c @@ -87,7 +87,7 @@ static int parse_ip_cb(const struct nlattr *attr, void *data) case CTA_IP_V6_DST: if (mnl_attr_validate2(attr, MNL_TYPE_BINARY, sizeof(struct in6_addr)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; @@ -322,7 +322,7 @@ int main(int argc, char *argv[]) /* ... request a fresh dump of the table from kernel */ ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { - perror("mnl_socket_recvfrom"); + perror("mnl_socket_sendto"); return -1; } tv.tv_sec = secs; diff --git a/examples/netfilter/nfct-dump.c b/examples/netfilter/nfct-dump.c index ce05bbb..25ccf2c 100644 --- a/examples/netfilter/nfct-dump.c +++ b/examples/netfilter/nfct-dump.c @@ -66,7 +66,7 @@ static int parse_ip_cb(const struct nlattr *attr, void *data) case CTA_IP_V6_DST: if (mnl_attr_validate2(attr, MNL_TYPE_BINARY, sizeof(struct in6_addr)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; @@ -292,7 +292,7 @@ int main(void) ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { - perror("mnl_socket_recvfrom"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); diff --git a/examples/rtnl/rtnl-addr-dump.c b/examples/rtnl/rtnl-addr-dump.c index 156563b..6b4e52e 100644 --- a/examples/rtnl/rtnl-addr-dump.c +++ b/examples/rtnl/rtnl-addr-dump.c @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-link-dump.c b/examples/rtnl/rtnl-link-dump.c index f717cea..f5d6312 100644 --- a/examples/rtnl/rtnl-link-dump.c +++ b/examples/rtnl/rtnl-link-dump.c @@ -34,7 +34,7 @@ static int data_attr_cb(const struct nlattr *attr, void *data) break; case IFLA_IFNAME: if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { - perror("mnl_attr_validate2"); + perror("mnl_attr_validate"); return MNL_CB_ERROR; } break; @@ -108,7 +108,7 @@ int main(void) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-link-dump2.c b/examples/rtnl/rtnl-link-dump2.c index 78f31a8..b3ca3fa 100644 --- a/examples/rtnl/rtnl-link-dump2.c +++ b/examples/rtnl/rtnl-link-dump2.c @@ -25,7 +25,7 @@ static int data_attr_cb(const struct nlattr *attr, void *data) break; case IFLA_IFNAME: if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { - perror("mnl_attr_validate2"); + perror("mnl_attr_validate"); return MNL_CB_ERROR; } printf("name=%s ", mnl_attr_get_str(attr)); @@ -81,7 +81,7 @@ int main(void) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-link-dump3.c b/examples/rtnl/rtnl-link-dump3.c index a6dce6f..2521214 100644 --- a/examples/rtnl/rtnl-link-dump3.c +++ b/examples/rtnl/rtnl-link-dump3.c @@ -81,7 +81,7 @@ int main(void) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-link-event.c b/examples/rtnl/rtnl-link-event.c index 90bb8e5..123fb88 100644 --- a/examples/rtnl/rtnl-link-event.c +++ b/examples/rtnl/rtnl-link-event.c @@ -26,7 +26,7 @@ static int data_attr_cb(const struct nlattr *attr, void *data) break; case IFLA_IFNAME: if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { - perror("mnl_attr_validate2"); + perror("mnl_attr_validate"); return MNL_CB_ERROR; } break; diff --git a/examples/rtnl/rtnl-link-set.c b/examples/rtnl/rtnl-link-set.c index dad8856..6086c37 100644 --- a/examples/rtnl/rtnl-link-set.c +++ b/examples/rtnl/rtnl-link-set.c @@ -62,19 +62,19 @@ int main(int argc, char *argv[]) sizeof(struct ifinfomsg)); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); if (ret == -1) { - perror("read"); + perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); if (ret == -1){ - perror("callback"); + perror("mnl_cb_run"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-route-add.c b/examples/rtnl/rtnl-route-add.c index 6d070b8..97578cd 100644 --- a/examples/rtnl/rtnl-route-add.c +++ b/examples/rtnl/rtnl-route-add.c @@ -105,7 +105,7 @@ int main(int argc, char *argv[]) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-route-dump.c b/examples/rtnl/rtnl-route-dump.c index 33cb2df..9829e36 100644 --- a/examples/rtnl/rtnl-route-dump.c +++ b/examples/rtnl/rtnl-route-dump.c @@ -182,7 +182,7 @@ static int data_ipv6_attr_cb(const struct nlattr *attr, void *data) case RTA_GATEWAY: if (mnl_attr_validate2(attr, MNL_TYPE_BINARY, sizeof(struct in6_addr)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; @@ -330,7 +330,7 @@ int main(int argc, char *argv[]) portid = mnl_socket_get_portid(nl); if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); + perror("mnl_socket_sendto"); exit(EXIT_FAILURE); } diff --git a/examples/rtnl/rtnl-route-event.c b/examples/rtnl/rtnl-route-event.c index badba2d..8a836f8 100644 --- a/examples/rtnl/rtnl-route-event.c +++ b/examples/rtnl/rtnl-route-event.c @@ -178,7 +178,7 @@ static int data_ipv6_attr_cb(const struct nlattr *attr, void *data) case RTA_GATEWAY: if (mnl_attr_validate2(attr, MNL_TYPE_BINARY, sizeof(struct in6_addr)) < 0) { - perror("mnl_attr_validate"); + perror("mnl_attr_validate2"); return MNL_CB_ERROR; } break; -- cgit v1.2.3 From c766735e6937bfc0acdde29336b6d8b6a5884ec5 Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:24:40 +0900 Subject: examples: use mnl_nlmsg_get_payload() not increment (nlmsghdr) pointer Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- examples/netfilter/nfct-create-batch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/netfilter/nfct-create-batch.c b/examples/netfilter/nfct-create-batch.c index 40cd2f6..4675789 100644 --- a/examples/netfilter/nfct-create-batch.c +++ b/examples/netfilter/nfct-create-batch.c @@ -67,7 +67,7 @@ static void put_msg(char *buf, uint16_t i, int seq) static int cb_err(const struct nlmsghdr *nlh, void *data) { - struct nlmsgerr *err = (void *)(nlh + 1); + struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh); if (err->error != 0) printf("message with seq %u has failed: %s\n", nlh->nlmsg_seq, strerror(-err->error)); -- cgit v1.2.3 From 8b0c82d8bd01347874dcc9a493129082424a3649 Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:27:46 +0900 Subject: attr: validate MNL_TYPE_MSEC same as MNL_TYPE_U64 Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- src/attr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/attr.c b/src/attr.c index 1136c50..c3c57e6 100644 --- a/src/attr.c +++ b/src/attr.c @@ -200,6 +200,7 @@ static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = { [MNL_TYPE_U16] = sizeof(uint16_t), [MNL_TYPE_U32] = sizeof(uint32_t), [MNL_TYPE_U64] = sizeof(uint64_t), + [MNL_TYPE_MSECS] = sizeof(uint64_t), }; /** -- cgit v1.2.3 From 60dfea927d1c6b94239243b828ea9656a48601e9 Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:29:23 +0900 Subject: examples: made sub functions the same show entry in oneline and RTA_PRIORITY Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- examples/rtnl/rtnl-route-dump.c | 10 +++++++--- examples/rtnl/rtnl-route-event.c | 13 ++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/rtnl/rtnl-route-dump.c b/examples/rtnl/rtnl-route-dump.c index 9829e36..17da80b 100644 --- a/examples/rtnl/rtnl-route-dump.c +++ b/examples/rtnl/rtnl-route-dump.c @@ -71,7 +71,6 @@ static void attributes_show_ipv4(struct nlattr *tb[]) } } } - printf("\n"); } /* like inet_ntoa(), not reentrant */ @@ -109,6 +108,9 @@ static void attributes_show_ipv6(struct nlattr *tb[]) struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]); printf("gw=%s ", inet6_ntoa(*addr)); } + if (tb[RTA_PRIORITY]) { + printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY])); + } if (tb[RTA_METRICS]) { int i; struct nlattr *tbx[RTAX_MAX+1] = {}; @@ -122,7 +124,6 @@ static void attributes_show_ipv6(struct nlattr *tb[]) } } } - printf("\n"); } static int data_ipv4_attr_cb(const struct nlattr *attr, void *data) @@ -142,6 +143,7 @@ static int data_ipv4_attr_cb(const struct nlattr *attr, void *data) case RTA_FLOW: case RTA_PREFSRC: case RTA_GATEWAY: + case RTA_PRIORITY: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; @@ -171,6 +173,7 @@ static int data_ipv6_attr_cb(const struct nlattr *attr, void *data) case RTA_TABLE: case RTA_OIF: case RTA_FLOW: + case RTA_PRIORITY: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; @@ -276,7 +279,7 @@ static int data_cb(const struct nlmsghdr *nlh, void *data) * RTM_F_EQUALIZE = 0x400: Multipath equalizer: NI * RTM_F_PREFIX = 0x800: Prefix addresses */ - printf("flags=%x\n", rm->rtm_flags); + printf("flags=%x ", rm->rtm_flags); switch(rm->rtm_family) { case AF_INET: @@ -289,6 +292,7 @@ static int data_cb(const struct nlmsghdr *nlh, void *data) break; } + printf("\n"); return MNL_CB_OK; } diff --git a/examples/rtnl/rtnl-route-event.c b/examples/rtnl/rtnl-route-event.c index 8a836f8..6cad9f0 100644 --- a/examples/rtnl/rtnl-route-event.c +++ b/examples/rtnl/rtnl-route-event.c @@ -55,6 +55,9 @@ static void attributes_show_ipv4(struct nlattr *tb[]) struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]); printf("gw=%s ", inet_ntoa(*addr)); } + if (tb[RTA_PRIORITY]) { + printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY])); + } if (tb[RTA_METRICS]) { int i; struct nlattr *tbx[RTAX_MAX+1] = {}; @@ -105,6 +108,9 @@ static void attributes_show_ipv6(struct nlattr *tb[]) struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]); printf("gw=%s ", inet6_ntoa(*addr)); } + if (tb[RTA_PRIORITY]) { + printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY])); + } if (tb[RTA_METRICS]) { int i; struct nlattr *tbx[RTAX_MAX+1] = {}; @@ -118,7 +124,6 @@ static void attributes_show_ipv6(struct nlattr *tb[]) } } } - printf("\n"); } static int data_ipv4_attr_cb(const struct nlattr *attr, void *data) @@ -138,6 +143,7 @@ static int data_ipv4_attr_cb(const struct nlattr *attr, void *data) case RTA_FLOW: case RTA_PREFSRC: case RTA_GATEWAY: + case RTA_PRIORITY: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; @@ -167,6 +173,7 @@ static int data_ipv6_attr_cb(const struct nlattr *attr, void *data) case RTA_TABLE: case RTA_OIF: case RTA_FLOW: + case RTA_PRIORITY: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; @@ -281,7 +288,7 @@ static int data_cb(const struct nlmsghdr *nlh, void *data) * RTM_F_EQUALIZE = 0x400: Multipath equalizer: NI * RTM_F_PREFIX = 0x800: Prefix addresses */ - printf("flags=%x", rm->rtm_flags); + printf("flags=%x ", rm->rtm_flags); switch(rm->rtm_family) { case AF_INET: @@ -293,8 +300,8 @@ static int data_cb(const struct nlmsghdr *nlh, void *data) attributes_show_ipv6(tb); break; } - printf("\n"); + printf("\n"); return MNL_CB_OK; } -- cgit v1.2.3 From 7d64d7299abd2f23faffec27829986020bceadbb Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:30:47 +0900 Subject: examples: fix display condition Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- examples/netfilter/nf-queue.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/netfilter/nf-queue.c b/examples/netfilter/nf-queue.c index 6b7c30e..72779f0 100644 --- a/examples/netfilter/nf-queue.c +++ b/examples/netfilter/nf-queue.c @@ -67,9 +67,10 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) 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); } - printf("packet received (id=%u hw=0x%04x hook=%u)\n", - id, ntohs(ph->hw_protocol), ph->hook); return MNL_CB_OK + id; } -- cgit v1.2.3 From 090a8427da036a2f64785682d4a40ec2d41a5de0 Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Sat, 7 Dec 2013 20:32:29 +0900 Subject: examples: use mnl_socket_setsockopt instead of raw setsockopt() Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- examples/netfilter/nfct-daemon.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/netfilter/nfct-daemon.c b/examples/netfilter/nfct-daemon.c index a9b93db..a4ef0af 100644 --- a/examples/netfilter/nfct-daemon.c +++ b/examples/netfilter/nfct-daemon.c @@ -293,10 +293,8 @@ int main(int argc, char *argv[]) * b) if the user-space process does not pull messages from the * receiver buffer so often. */ - setsockopt(mnl_socket_get_fd(nl), SOL_NETLINK, - NETLINK_BROADCAST_ERROR, &on, sizeof(int)); - setsockopt(mnl_socket_get_fd(nl), SOL_NETLINK, NETLINK_NO_ENOBUFS, - &on, sizeof(int)); + mnl_socket_setsockopt(nl, NETLINK_BROADCAST_ERROR, &on, sizeof(int)); + mnl_socket_setsockopt(nl, NETLINK_NO_ENOBUFS, &on, sizeof(int)); nlh = mnl_nlmsg_put_header(buf); /* Counters are atomically zeroed in each dump */ -- cgit v1.2.3 From f94b2c67485009572027c6f37ba4ec09f6729910 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 13 Jun 2014 11:15:57 +0200 Subject: include: cache copy of include/linux/socket.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes compilation in Debian Squeeze: CC attr.lo In file included from ../include/libmnl/libmnl.h:9, from socket.c:10: ../include/linux/netlink.h:35: error: expected specifier-qualifier-list before ‘__kernel_sa_family_t’ In file included from ../include/libmnl/libmnl.h:9, from callback.c:11: ../include/linux/netlink.h:35: error: expected specifier-qualifier-list before ‘__kernel_sa_family_t’ socket.c: In function ‘mnl_socket_get_portid’: socket.c:102: error: ‘const struct sockaddr_nl’ has no member named ‘nl_pid’ socket.c: In function ‘mnl_socket_bind’: socket.c:146: error: ‘struct sockaddr_nl’ has no member named ‘nl_family’ socket.c:147: error: ‘struct sockaddr_nl’ has no member named ‘nl_groups’ socket.c:148: error: ‘struct sockaddr_nl’ has no member named ‘nl_pid’ socket.c:163: error: ‘struct sockaddr_nl’ has no member named ‘nl_family’ socket.c: In function ‘mnl_socket_sendto’: socket.c:184: error: unknown field ‘nl_family’ specified in initializer socket.c:185: warning: excess elements in struct initializer socket.c:185: warning: (near initialization for ‘snl’) Signed-off-by: Pablo Neira Ayuso --- include/linux/Makefile.am | 2 +- include/linux/socket.h | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 include/linux/socket.h diff --git a/include/linux/Makefile.am b/include/linux/Makefile.am index 95f82d2..08c600b 100644 --- a/include/linux/Makefile.am +++ b/include/linux/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = netfilter -noinst_HEADERS = netlink.h +noinst_HEADERS = netlink.h socket.h diff --git a/include/linux/socket.h b/include/linux/socket.h new file mode 100644 index 0000000..8c1e501 --- /dev/null +++ b/include/linux/socket.h @@ -0,0 +1,21 @@ +#ifndef _LINUX_SOCKET_H +#define _LINUX_SOCKET_H + +/* + * Desired design of maximum size and alignment (see RFC2553) + */ +#define _K_SS_MAXSIZE 128 /* Implementation specific max size */ +#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *)) + /* Implementation specific desired alignment */ + +typedef unsigned short __kernel_sa_family_t; + +struct __kernel_sockaddr_storage { + __kernel_sa_family_t ss_family; /* address family */ + /* Following field(s) are implementation specific */ + char __data[_K_SS_MAXSIZE - sizeof(unsigned short)]; + /* space to achieve desired size, */ + /* _SS_MAXSIZE value minus size of ss_family */ +} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */ + +#endif /* _LINUX_SOCKET_H */ -- cgit v1.2.3 From 2c458b2eb479cbc83c83de79dcd14bec6acc90bd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 22 Sep 2014 13:11:23 +0200 Subject: socket: calloc expects struct size as second parameter The parameters where accidentally swapped. Reported-by: Chris Rapier Signed-off-by: Pablo Neira Ayuso --- src/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.c b/src/socket.c index 676a08a..0c3cd72 100644 --- a/src/socket.c +++ b/src/socket.c @@ -114,7 +114,7 @@ struct mnl_socket *mnl_socket_open(int bus) { struct mnl_socket *nl; - nl = calloc(sizeof(struct mnl_socket), 1); + nl = calloc(1, sizeof(struct mnl_socket)); if (nl == NULL) return NULL; -- cgit v1.2.3 From e374664f48724e5b13a848bad5c5353349f0ae38 Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Thu, 25 Sep 2014 09:33:27 +0900 Subject: socket: creating a struct mnl_socket from a pre-existing socket This patch defines a new function mnl_socket_fdopen() which creates a struct mnl_socket object from a pre-existing socket like obtained from other process and different domain/type from the same prodess. Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Pablo Neira Ayuso --- include/libmnl/libmnl.h | 1 + src/libmnl.map | 4 ++++ src/socket.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h index 223709c..0de6678 100644 --- a/include/libmnl/libmnl.h +++ b/include/libmnl/libmnl.h @@ -22,6 +22,7 @@ extern "C" { struct mnl_socket; extern struct mnl_socket *mnl_socket_open(int type); +extern struct mnl_socket *mnl_socket_fdopen(int fd); extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid); extern int mnl_socket_close(struct mnl_socket *nl); extern int mnl_socket_get_fd(const struct mnl_socket *nl); diff --git a/src/libmnl.map b/src/libmnl.map index dbc332e..3c147a7 100644 --- a/src/libmnl.map +++ b/src/libmnl.map @@ -72,3 +72,7 @@ local: *; LIBMNL_1.1 { mnl_attr_parse_payload; } LIBMNL_1.0; + +LIBMNL_1.2 { + mnl_socket_fdopen; +} LIBMNL_1.1; diff --git a/src/socket.c b/src/socket.c index 0c3cd72..86657d4 100644 --- a/src/socket.c +++ b/src/socket.c @@ -128,6 +128,40 @@ struct mnl_socket *mnl_socket_open(int bus) } EXPORT_SYMBOL(mnl_socket_open); +/** + * mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket. + * \param fd pre-existing socket descriptor. + * + * On error, it returns NULL and errno is appropriately set. Otherwise, it + * returns a valid pointer to the mnl_socket structure. It also sets the portID + * if the socket fd is already bound and it is AF_NETLINK. + * + * Note that mnl_socket_get_portid() returns 0 if this function is used with + * non-netlink socket. + */ +struct mnl_socket *mnl_socket_fdopen(int fd) +{ + int ret; + struct mnl_socket *nl; + struct sockaddr_nl addr; + socklen_t addr_len = sizeof(struct sockaddr_nl); + + ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len); + if (ret == -1) + return NULL; + + nl = calloc(1, sizeof(struct mnl_socket)); + if (nl == NULL) + return NULL; + + nl->fd = fd; + if (addr.nl_family == AF_NETLINK) + nl->addr = addr; + + return nl; +} +EXPORT_SYMBOL(mnl_socket_fdopen); + /** * mnl_socket_bind - bind netlink socket * \param nl netlink socket obtained via mnl_socket_open() -- cgit v1.2.3 From 72aec11703c7fda93af77cb6356f9692f18f9e9b Mon Sep 17 00:00:00 2001 From: Ken-ichirou MATSUZAWA Date: Fri, 24 Oct 2014 14:39:28 +0900 Subject: doc: minor fix mnl_attr_ok(): fix return value type mnl_attr_put_u8(): remove unused param - len mnl_attr_put_u8_check(): remove unused param - len mnl_nlmsg_ok(): fix return value type mnl_nlmsg_batch_stop(): not return batch size, but release it Signed-off-by: Ken-ichirou MATSUZAWA Signed-off-by: Florian Westphal --- src/attr.c | 4 +--- src/nlmsg.c | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/attr.c b/src/attr.c index c3c57e6..ca2cd25 100644 --- a/src/attr.c +++ b/src/attr.c @@ -89,7 +89,7 @@ EXPORT_SYMBOL(mnl_attr_get_payload); * truncated. * * This function does not set errno in case of error since it is intended - * for iterations. Thus, it returns 1 on success and 0 on error. + * for iterations. Thus, it returns true on success and false on error. * * The len parameter may be negative in the case of malformed messages during * attribute iteration, that is why we use a signed integer. @@ -428,7 +428,6 @@ EXPORT_SYMBOL(mnl_attr_put); * mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message * \param nlh pointer to the netlink message * \param type netlink attribute type - * \param len netlink attribute payload size * \param data 8-bit unsigned integer data that is stored by the new attribute * * This function updates the length field of the Netlink message (nlmsg_len) @@ -569,7 +568,6 @@ EXPORT_SYMBOL(mnl_attr_put_check); * \param nlh pointer to the netlink message * \param buflen size of buffer which stores the message * \param type netlink attribute type - * \param len netlink attribute payload size * \param data 8-bit unsigned integer data that is stored by the new attribute * * This function first checks that the data can be added to the message diff --git a/src/nlmsg.c b/src/nlmsg.c index fdb7af8..fd2f698 100644 --- a/src/nlmsg.c +++ b/src/nlmsg.c @@ -150,7 +150,7 @@ EXPORT_SYMBOL(mnl_nlmsg_get_payload_offset); * truncated. * * This function does not set errno in case of error since it is intended - * for iterations. Thus, it returns 1 on success and 0 on error. + * for iterations. Thus, it returns true on success and false on error. * * The len parameter may become negative in malformed messages during message * iteration, that is why we use a signed integer. @@ -462,7 +462,7 @@ EXPORT_SYMBOL(mnl_nlmsg_batch_start); * mnl_nlmsg_batch_stop - release a batch * \param b pointer to batch * - * This function returns the amount of data that is part of this batch. + * This function releases the batch allocated by mnl_nlmsg_batch_start(). */ void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b) { -- cgit v1.2.3 From c9f19b98cd8e108617e825e071091df14f78c53a Mon Sep 17 00:00:00 2001 From: Hisao Tanabe Date: Sat, 10 Jan 2015 18:02:07 +0900 Subject: attr: minor doc fix in mnl_attr_next() mnl_attr_next(): remove unused param - len Signed-off-by: Hisao Tanabe Signed-off-by: Pablo Neira Ayuso --- src/attr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/attr.c b/src/attr.c index ca2cd25..c551d0b 100644 --- a/src/attr.c +++ b/src/attr.c @@ -105,7 +105,6 @@ EXPORT_SYMBOL(mnl_attr_ok); /** * mnl_attr_next - get the next attribute in the payload of a netlink message * \param attr pointer to the current attribute - * \param len length of the remaining bytes in the buffer (passed by reference). * * This function returns a pointer to the next attribute after the one passed * as parameter. You have to use mnl_attr_ok() to ensure that the next -- cgit v1.2.3 From 9ac5b6fb437e24c328a30776e30c39b906b06f66 Mon Sep 17 00:00:00 2001 From: Markus Teich Date: Thu, 26 Feb 2015 14:38:03 +0100 Subject: header: use sysconf() instead of getpagesize() The sysconf(_SC_PAGESIZE) call is more portable since it does not need _BSD_SOURCE defined. Signed-off-by: Pablo Neira Ayuso --- include/libmnl/libmnl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h index 0de6678..3a589bc 100644 --- a/include/libmnl/libmnl.h +++ b/include/libmnl/libmnl.h @@ -17,7 +17,7 @@ extern "C" { */ #define MNL_SOCKET_AUTOPID 0 -#define MNL_SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L) +#define MNL_SOCKET_BUFFER_SIZE (sysconf(_SC_PAGESIZE) < 8192L ? sysconf(_SC_PAGESIZE) : 8192L) struct mnl_socket; -- cgit v1.2.3 From b37ae85d43bd3403f1b6b1d3fa8bcf294868e56d Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 12:40:03 +0200 Subject: examples/netfilter: Include for be64toh Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- examples/netfilter/nfct-daemon.c | 1 + examples/netfilter/nfct-dump.c | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/netfilter/nfct-daemon.c b/examples/netfilter/nfct-daemon.c index a4ef0af..a97c2ec 100644 --- a/examples/netfilter/nfct-daemon.c +++ b/examples/netfilter/nfct-daemon.c @@ -3,6 +3,7 @@ * * This example is placed in the public domain. */ +#include #include #include #include diff --git a/examples/netfilter/nfct-dump.c b/examples/netfilter/nfct-dump.c index 25ccf2c..114af61 100644 --- a/examples/netfilter/nfct-dump.c +++ b/examples/netfilter/nfct-dump.c @@ -1,4 +1,5 @@ /* This example is placed in the public domain. */ +#include #include #include #include -- cgit v1.2.3 From b180a6ee27674b5060cf54a0149a9109da9d9fd1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 25 May 2015 20:51:09 +0200 Subject: example: netfilter: get rid of aligned_be64 definitions This is defined in , which is included by the nfnetlink_* header files. Thus, we can get rid of u_int64_t which causes problems to musl according to Felix Janda. Signed-off-by: Pablo Neira Ayuso --- examples/netfilter/nf-log.c | 5 ----- examples/netfilter/nf-queue.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/examples/netfilter/nf-log.c b/examples/netfilter/nf-log.c index 901bd80..4383b66 100644 --- a/examples/netfilter/nf-log.c +++ b/examples/netfilter/nf-log.c @@ -9,11 +9,6 @@ #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) diff --git a/examples/netfilter/nf-queue.c b/examples/netfilter/nf-queue.c index 72779f0..957e365 100644 --- a/examples/netfilter/nf-queue.c +++ b/examples/netfilter/nf-queue.c @@ -9,11 +9,6 @@ #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) -- cgit v1.2.3 From 1891e0e2cefced50e7bfdacd50942cefe5bf73ba Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 2 Oct 2015 22:12:33 +0200 Subject: socket: introduce mnl_socket_open2() Define mnl_socket_open2() so that user can pass a set of SOCK_* flags at socket creation time. Signed-off-by: Guillaume Nault Signed-off-by: Pablo Neira Ayuso --- include/libmnl/libmnl.h | 3 ++- src/libmnl.map | 1 + src/socket.c | 41 ++++++++++++++++++++++++++++++++--------- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/include/libmnl/libmnl.h b/include/libmnl/libmnl.h index 3a589bc..5adb13c 100644 --- a/include/libmnl/libmnl.h +++ b/include/libmnl/libmnl.h @@ -21,7 +21,8 @@ extern "C" { struct mnl_socket; -extern struct mnl_socket *mnl_socket_open(int type); +extern struct mnl_socket *mnl_socket_open(int bus); +extern struct mnl_socket *mnl_socket_open2(int bus, int flags); extern struct mnl_socket *mnl_socket_fdopen(int fd); extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid); extern int mnl_socket_close(struct mnl_socket *nl); diff --git a/src/libmnl.map b/src/libmnl.map index 3c147a7..e5920e5 100644 --- a/src/libmnl.map +++ b/src/libmnl.map @@ -74,5 +74,6 @@ LIBMNL_1.1 { } LIBMNL_1.0; LIBMNL_1.2 { + mnl_socket_open2; mnl_socket_fdopen; } LIBMNL_1.1; diff --git a/src/socket.c b/src/socket.c index 86657d4..d63ab87 100644 --- a/src/socket.c +++ b/src/socket.c @@ -103,14 +103,7 @@ unsigned int mnl_socket_get_portid(const struct mnl_socket *nl) } EXPORT_SYMBOL(mnl_socket_get_portid); -/** - * mnl_socket_open - open a netlink socket - * \param bus the netlink socket bus ID (see NETLINK_* constants) - * - * On error, it returns NULL and errno is appropriately set. Otherwise, it - * returns a valid pointer to the mnl_socket structure. - */ -struct mnl_socket *mnl_socket_open(int bus) +static struct mnl_socket *__mnl_socket_open(int bus, int flags) { struct mnl_socket *nl; @@ -118,7 +111,7 @@ struct mnl_socket *mnl_socket_open(int bus) if (nl == NULL) return NULL; - nl->fd = socket(AF_NETLINK, SOCK_RAW, bus); + nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus); if (nl->fd == -1) { free(nl); return NULL; @@ -126,8 +119,38 @@ struct mnl_socket *mnl_socket_open(int bus) return nl; } + +/** + * mnl_socket_open - open a netlink socket + * \param bus the netlink socket bus ID (see NETLINK_* constants) + * + * On error, it returns NULL and errno is appropriately set. Otherwise, it + * returns a valid pointer to the mnl_socket structure. + */ +struct mnl_socket *mnl_socket_open(int bus) +{ + return __mnl_socket_open(bus, 0); +} EXPORT_SYMBOL(mnl_socket_open); +/** + * mnl_socket_open2 - open a netlink socket with appropriate flags + * \param bus the netlink socket bus ID (see NETLINK_* constants) + * \param flags the netlink socket flags (see SOCK_* constants in socket(2)) + * + * This is similar to mnl_socket_open(), but allows to set flags like + * SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs + * performing exec calls). + * + * On error, it returns NULL and errno is appropriately set. Otherwise, it + * returns a valid pointer to the mnl_socket structure. + */ +struct mnl_socket *mnl_socket_open2(int bus, int flags) +{ + return __mnl_socket_open(bus, flags); +} +EXPORT_SYMBOL(mnl_socket_open2); + /** * mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket. * \param fd pre-existing socket descriptor. -- cgit v1.2.3