netfilter support in libnl
Subsystems (2)
There have been comments in the past on this list about using libnl for the netfilter netlink support, and since I would like to use a common library api for all the netlink interfaces, I decided to give it a go. These patches are the result of that.
Any comments welcome, particularly about whether this is still something that is desired.
Some notes about the patches:
- only tested on an ARM platform
- only conntrack and log implemented (not queue)
- only dumping and monitoring implemented (no modifications)
- monitoring ct/log events requires copying all the netlink message data into another object, which seems a bit inefficient
- I defined a cache to monitor log messages, so that it can find the parser automatically, but not sure that caching log events makes sense
- I've added 'test' operations for some ct/log fields. None of the other objects in libnl have these, but I think they are needed.
PATCH 1/3 libnl: add netfilter support
--- include/linux/netfilter/nfnetlink.h | 106 +++++++++++++++ include/netlink/netfilter/nfnl.h | 44 ++++++ include/netlink/netlink.h | 1 lib/Makefile | 2 lib/attr.c | 3 lib/netfilter/nfnl.c | 246 ++++++++++++++++++++++++++++++++++++ 6 files changed, 401 insertions(+), 1 deletion(-)
lib/Makefile +2 -0
@@ -25,6 +25,8 @@ CIN += $(wildcard route/cls/*.c) CIN += $(wildcard genl/*.c) # fib lookup CIN += $(wildcard fib_lookup/*.c) +# Netfilter +CIN += $(wildcard netfilter/*.c) DEPS := $(CIN:%.c=%.d) OBJ := $(CIN:%.c=%.o)
lib/attr.c +2 -1
@@ -261,7 +261,8 @@ int nla_parse(struct nlattr *tb[], int mmemset (tb,0 ,sizeof (struct nlattr *) * (maxtype +1 ));nla_for_each_attr (nla, head, len, rem) { -uint16_t type = nla->nla_type; +/* Ignore NFNL_NFA_NEST bit, hope nothing else uses it */ +uint16_t type = nla->nla_type &0x7fff ;if (type ==0 ) {fprintf (stderr,"Illegal nla->nla_type == 0\n" );
include/netlink/netfilter/nfnl.h new file +44 -0
44 lines not on this page · raw message
lib/netfilter/nfnl.c new file +246 -0
246 lines not on this page · raw message
include/netlink/netlink.h +1 -0
@@ -25,6 +25,7 @@#include <linux/rtnetlink.h> #include <linux/genetlink.h> #include <linux/ip_mp_alg.h> +#include <linux/netfilter/nfnetlink.h> #include <netlink/types.h> #include <netlink/handlers.h> #include <netlink/socket.h>
include/linux/netfilter/nfnetlink.h new file +106 -0
106 lines not on this page · raw message
PATCH 2/3 libnl: add netfilter conntrack support
In reply to Philip Craig--- include/linux/netfilter/nfnetlink_conntrack.h | 140 +++++ include/netlink-types.h | 44 + include/netlink/addr.h | 1 include/netlink/netfilter/ct.h | 115 ++++ include/netlink/utils.h | 4 lib/addr.c | 28 + lib/netfilter/ct.c | 422 ++++++++++++++++ lib/netfilter/ct_obj.c | 667 ++++++++++++++++++++++++++ lib/utils.c | 36 + src/Makefile | 6 src/f_ct.c | 153 +++++ src/nf-ct-dump.c | 88 +++ src/nf-monitor.c | 115 ++++ 13 files changed, 1818 insertions(+), 1 deletion(-)
include/netlink-types.h +44 -0
@@ -795,4 +795,48 @@ struct genl_familystruct nl_list_head gf_ops; }; +union nfnl_ct_proto +{ +struct { +uint16_t src; +uint16_t dst; + } port; +struct { +uint16_t id; +uint8_t type; +uint8_t code; + } icmp; +}; + +struct nfnl_ct_dir { +struct nl_addr * src; +struct nl_addr * dst; +union nfnl_ct_proto proto; +uint64_t packets; +uint64_t bytes; +}; + +union nfnl_ct_protoinfo { +struct { +uint8_t state; + } tcp; +}; + +struct nfnl_ct { +NLHDR_COMMON + + uint8_t ct_family; +uint8_t ct_proto; +union nfnl_ct_protoinfo ct_protoinfo; + +uint32_t ct_status; +uint32_t ct_timeout; +uint32_t ct_mark; +uint32_t ct_use; +uint32_t ct_id; + +struct nfnl_ct_dir ct_orig; +struct nfnl_ct_dir ct_repl; +}; +#endif
include/netlink/netfilter/ct.h new file +115 -0
115 lines not on this page · raw message
lib/netfilter/ct.c new file +422 -0
422 lines not on this page · raw message
lib/netfilter/ct_obj.c new file +667 -0
667 lines not on this page · raw message
src/Makefile +5 -1
@@ -14,7 +14,7 @@ ifeq ($(shell [ ! -r ../Makefile.opts ] endif LDFLAGS += -L../lib -lnl utils.o -CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) +CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c) TOOLS := $(CIN:%.c=%) all: $(TOOLS)
@@ -29,6 +29,10 @@ genl-%: genl-%.c @echo " LD $@"; \ $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) +nf-%: nf-%.c + @echo " LD $@"; \ + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) + clean: @echo " CLEAN src"; \ rm -f $(TOOLS) utils.o
src/f_ct.c new file +153 -0
153 lines not on this page · raw message
src/nf-ct-dump.c new file +88 -0
88 lines not on this page · raw message
src/nf-monitor.c new file +115 -0
115 lines not on this page · raw message
include/linux/netfilter/nfnetlink_conntrack.h new file +140 -0
140 lines not on this page · raw message
include/netlink/addr.h +1 -0
@@ -35,6 +35,7 @@ extern void nl_addr_put(struct nl_addrextern int nl_addr_shared (struct nl_addr *);extern int nl_addr_cmp (struct nl_addr *,struct nl_addr *); +extern int nl_addr_cmp_prefix (struct nl_addr *,struct nl_addr *);extern int nl_addr_valid (char *,int );extern int nl_addr_guess_family (struct nl_addr *); extern int nl_addr_fill_sockaddr(struct nl_addr *,
include/netlink/utils.h +4 -0
@@ -65,6 +65,10 @@ extern int nl_str2llproto(const char *);extern char *nl_ether_proto2str (int ,char *,size_t );extern int nl_str2ether_proto (const char *); +/* IP protocol translations */ +extern char *nl_ip_proto2str (int ,char *,size_t ); +extern int nl_str2ip_proto (const char *); + #ifdef __cplusplus }#endif
lib/addr.c +28 -0
@@ -501,6 +501,34 @@ int nl_addr_cmp(struct nl_addr *a, struc }/** +* Compares the prefix of two abstract address objects. +* @arg a A abstract address object. +* @arg b Another abstract address object. +* +* @return Integer less than, equal to or greather than zero if \c is found, +* respectively to be less than, to, or be greater than \c b. +*/ +int nl_addr_cmp_prefix (struct nl_addr *a,struct nl_addr *b) +{ +int d = a->a_family - b->a_family; + +if (d ==0 ) { +int len =min (a->a_prefixlen, b->a_prefixlen); +int bytes = len /8 ; + + d =memcmp (a->a_addr, b->a_addr, bytes); +if (d ==0 ) { +int mask = (1UL << (len %8 )) -1UL ; + + d = (a->a_addr[bytes] & mask) - + (b->a_addr[bytes] & mask); + } + } + +return d; +} + +/** * Check if an address matches a certain family. * @arg addr Address represented as character string. * @arg family Desired address family.
lib/utils.c +36 -0
@@ -662,4 +662,40 @@ int nl_str2ether_proto(const char *name)/** @} */ +/** +* @name IP Protocol Translations +* @{ +*/ + +char *nl_ip_proto2str (int proto,char *buf,size_t len) +{ +struct protoent *p =getprotobynumber (proto); + +if (p) { +snprintf (buf, len,"%s" , p->p_name); +return buf; + } + +snprintf (buf, len,"0x%x" , proto); +return buf; +} + +int nl_str2ip_proto (const char *name) +{ +struct protoent *p =getprotobyname (name); +unsigned long l; +char *end; + +if (p) +return p->p_proto; + + l =strtoul (name, &end,0 ); +if (l ==ULONG_MAX || *end !='\0' ) +return -1 ; + +return (int ) l; +} + +/** @} */ +/** @} */
PATCH 3/3 libnl: add netfilter log support
In reply to Philip Craig--- include/linux/netfilter/nfnetlink_log.h | 96 +++++++ include/netlink-types.h | 22 + include/netlink/netfilter/log.h | 105 +++++++ lib/netfilter/log.c | 349 ++++++++++++++++++++++++++ lib/netfilter/log_obj.c | 425 ++++++++++++++++++++++++++++++++ src/nf-log.c | 142 ++++++++++ 6 files changed, 1139 insertions(+)
include/netlink-types.h +22 -0
@@ -839,4 +839,26 @@ struct nfnl_ct {struct nfnl_ct_dir ct_repl; }; +struct nfnl_log { +NLHDR_COMMON + + uint8_t log_family; +uint8_t log_hook; +uint16_t log_hwproto; +uint32_t log_mark; +struct timeval log_timestamp; +uint32_t log_indev; +uint32_t log_outdev; +uint32_t log_physindev; +uint32_t log_physoutdev; +uint8_t log_hwaddr[8 ]; +int log_hwaddr_len; +void * log_payload; +int log_payload_len; +char * log_prefix; +uint32_t log_uid; +uint32_t log_seq; +uint32_t log_seq_global; +}; +#endif
include/netlink/netfilter/log.h new file +105 -0
105 lines not on this page · raw message
lib/netfilter/log.c new file +349 -0
349 lines not on this page · raw message
lib/netfilter/log_obj.c new file +425 -0
425 lines not on this page · raw message
src/nf-log.c new file +142 -0
142 lines not on this page · raw message
include/linux/netfilter/nfnetlink_log.h new file +96 -0
96 lines not on this page · raw message
Quoted 7 lines · Philip Craig
There have been comments in the past on this list about using libnl for the netfilter netlink support, and since I would like to use a common library api for all the netlink interfaces, I decided to give it a go. These patches are the result of that.
Any comments welcome, particularly about whether this is still something that is desired.
Very nice, I think its still desirable to avoid having to use multiple pretty similar libraries in case you also need to use other netlink subsystems.
And I think LGPL is a much better choice than GPL for stuff like this.
If you want to merge this upstream, you should probably CC Thomas.
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Philip Craiginclude/linux/netfilter/nfnetlink.h line 67
Quoted 4 lines · Philip Craig
include/linux/netfilter/nfnetlink.h new file +4
-0+#define NFA_NEST (skb, type) \ +({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ + __start; })
The latest libnetfilter_conntrack version doesn't send the NFA_NEST bit to the kernel anymore since we intend to get rid of it, at least on the receive side. Please change this to not send it here as well.
* Patrick McHardy <[email protected]> 2007-09-03 11:30
Quoted 6 lines
Quoted 5 lines · Philip Craig
There have been comments in the past on this list about using libnl for the netfilter netlink support, and since I would like to use a common library api for all the netlink interfaces, I decided to give it a go. These patches are the result of that.
Quoted 7 lines
Quoted 2 lines
Any comments welcome, particularly about whether this is still something that is desired.
Very nice, I think its still desirable to avoid having to use multiple pretty similar libraries in case you also need to use other netlink subsystems.
I agree, it would be great if we could get rid of the almost duplicate effort of nfnl attributes etc.
Quoted 2 lines
And I think LGPL is a much better choice than GPL for stuff like this.
This is my fault, I intedend to use LGPL as stated in the COPYING for some brain dead reason have been copying GPL headers from file to file. I'm fixing this up right now.
Quoted 2 lines
If you want to merge this upstream, you should probably CC Thomas.
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Patrick McHardy* Patrick McHardy <[email protected]> 2007-09-03 11:50
Quoted 11 lines
include/linux/netfilter/nfnetlink.h line 67
Quoted 4 lines · Philip Craig
include/linux/netfilter/nfnetlink.h new file +4
-0+#define NFA_NEST (skb, type) \ +({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ + __start; })The latest
libnetfilter_conntrackversion doesn't send theNFA_NESTbit to the kernel anymore since we intend to get rid of it, at least on the receive side. Please change this to not send it here as well.
Great, so basically the attribute interfaces could be merged on the sending side.
I think I can live with checking for the bit on the receiving side, the only problem it could cause is when the attribute type is used to encode information such as a port number. So if we are willing to take that risk the receiving path could be merged as well.
Quoted 9 lines · Thomas Graf
* Patrick McHardy <[email protected]> 2007-09-03 11:30
Quoted 2 lines
And I think LGPL is a much better choice than GPL for stuff like this.
This is my fault, I intedend to use LGPL as stated in the COPYING for some brain dead reason have been copying GPL headers from file to file. I'm fixing this up right now.
I was actually under the impression that it already uses LGPL :)
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Thomas GrafQuoted 16 lines · Thomas Graf
* Patrick McHardy <[email protected]> 2007-09-03 11:50
Quoted 12 lines
include/linux/netfilter/nfnetlink.h line 67
Quoted 4 lines · Philip Craig
include/linux/netfilter/nfnetlink.h new file +4
-0+#define NFA_NEST (skb, type) \ +({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ + __start; })The latest
libnetfilter_conntrackversion doesn't send theNFA_NESTbit to the kernel anymore since we intend to get rid of it, at least on the receive side. Please change this to not send it here as well.
Quoted 2 lines
Great, so basically the attribute interfaces could be merged on the sending side.
Yes, hopefully. We're using big endian for numeric values, but that shouldn't be a problem I think.
Quoted 4 lines
I think I can live with checking for the bit on the receiving side, the only problem it could cause is when the attribute type is used to encode information such as a port number. So if we are willing to take that risk the receiving path could be merged as well.
That kind of information should be stored as attribute value, no?
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Philip Craig* Philip Craig <[email protected]> 2007-09-03 15:11
lib/attr.c int nla_parse(struct nlattr *tb[], int m · line 265
Quoted 11 lines
Index:
libnl/lib/attr.c
===================================================================lib/attr.c +2
-1@@ -261,7 +261,8 @@ int nla_parse(struct nlattr *tb[], int mmemset (tb,0 ,sizeof (struct nlattr *) * (maxtype +1 ));nla_for_each_attr (nla, head, len, rem) { -uint16_t type = nla->nla_type; +/* Ignore NFNL_NFA_NEST bit, hope nothing else uses it */ +uint16_t type = nla->nla_type &0x7fff ;
I wonder if it is useful to make this behaviour conditional so that the netfilter subsystem could enable this for backwards compatibility while other subsystems won't be affected.
It will offend a few people but it's still pre 1.0 and we can break the API. I'd rather get this right now than having to life with side effects for a long time.
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Patrick McHardy* Patrick McHardy <[email protected]> 2007-09-03 12:06
Quoted 8 lines
Quoted 4 lines · Thomas Graf
I think I can live with checking for the bit on the receiving side, the only problem it could cause is when the attribute type is used to encode information such as a port number. So if we are willing to take that risk the receiving path could be merged as well.
That kind of information should be stored as attribute value, no?
Yes it should but we've already got code like this:
for (i = 0; i < cnt; i++)
nla_put(skb, i, ....);
It's only a matter of time until someone comes up with something like this:nla_put(skb, dstport, sizeof(port_info), &port_info);
Maybe we could put a WARN_ON(bit_set) in nla_put() on kernel side to make sure such behaviour is not being introduced by accident.
* Patrick McHardy <[email protected]> 2007-09-03 12:05
Quoted 7 lines
Quoted 6 lines · Thomas Graf
* Patrick McHardy <[email protected]> 2007-09-03 11:30
Quoted 2 lines
And I think LGPL is a much better choice than GPL for stuff like this.
Quoted 6 lines
Quoted 3 lines
This is my fault, I intedend to use LGPL as stated in the COPYING for some brain dead reason have been copying GPL headers from file to file. I'm fixing this up right now.
I was actually under the impression that it already uses LGPL :)
SVN head is LGPL, the latest release (very old) is still GPL :-)
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Thomas GrafQuoted 10 lines · Thomas Graf
* Patrick McHardy <[email protected]> 2007-09-03 12:06
Quoted 8 lines
Quoted 4 lines · Thomas Graf
I think I can live with checking for the bit on the receiving side, the only problem it could cause is when the attribute type is used to encode information such as a port number. So if we are willing to take that risk the receiving path could be merged as well.
Quoted 6 lines
Quoted 1 line
That kind of information should be stored as attribute value, no?
Yes it should but we've already got code like this:
for (i = 0; i < cnt; i++)nla_put(skb, i, ....);
That looks pretty much like a list of attributes, but using different attribute types. Just out of interest:
do you have a pointer to code doing this?
Quoted 6 lines
It's only a matter of time until someone comes up with something like this:
nla_put(skb, dstport, sizeof(port_info), &port_info);Maybe we could put a
WARN_ON(bit_set)innla_put()on kernel side to make sure such behaviour is not being introduced by accident.
That sounds like a good idea. Anyone doing this is looking for trouble since array-based attribute parsing would require at least 2^31 elements :)
Re: [PATCH 1/3] libnl: add netfilter support
* Patrick McHardy <[email protected]> 2007-09-03 12:53
Quoted 3 lines
That looks pretty much like a list of attributes, but using different attribute types. Just out of interest:
do you have a pointer to code doing this?
Yes, see tcf_action_dump().
OTOH, netlabel is making heavy use of attribute lists but the type is constant to allow for automatic policy validation. I think this is the proper way of generating lists.
Re: [PATCH 1/3] libnl: add netfilter support
Quoted 8 lines · Thomas Graf
* Patrick McHardy <[email protected]> 2007-09-03 12:53
Quoted 3 lines
That looks pretty much like a list of attributes, but using different attribute types. Just out of interest:
do you have a pointer to code doing this?Yes, see
tcf_action_dump().
Right, I remeber, the entire "action order" thing. Thats a horrible hack IMO, probably best to convert it to real lists if possible.
Quoted 3 lines
OTOH, netlabel is making heavy use of attribute lists but the type is constant to allow for automatic policy validation. I think this is the proper way of generating lists.
Fully agreed, thats also what I did in the 8021q netlink interface.
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Patrick McHardyQuoted 11 lines · Patrick McHardy
include/linux/netfilter/nfnetlink.h line 67
Quoted 4 lines · Philip Craig
include/linux/netfilter/nfnetlink.h new file +4
-0+#define NFA_NEST (skb, type) \ +({ struct nfattr *__start = (struct nfattr *)skb_tail_pointer(skb); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ + __start; })The latest
libnetfilter_conntrackversion doesn't send theNFA_NESTbit to the kernel anymore since we intend to get rid of it, at least on the receive side. Please change this to not send it here as well.
This is just a copy of the kernel header (maybe an old one though). I haven't added send support to libnl yet, but when I do I'll be sure not to use this.
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Thomas GrafQuoted 17 lines · Thomas Graf
* Philip Craig <[email protected]> 2007-09-03 15:11
lib/attr.c int nla_parse(struct nlattr *tb[], int m · line 265
Quoted 11 lines
Index:
libnl/lib/attr.c
===================================================================lib/attr.c +2
-1@@ -261,7 +261,8 @@ int nla_parse(struct nlattr *tb[], int mmemset (tb,0 ,sizeof (struct nlattr *) * (maxtype +1 ));nla_for_each_attr (nla, head, len, rem) { -uint16_t type = nla->nla_type; +/* Ignore NFNL_NFA_NEST bit, hope nothing else uses it */ +uint16_t type = nla->nla_type &0x7fff ;I wonder if it is useful to make this behaviour conditional so that the netfilter subsystem could enable this for backwards compatibility while other subsystems won't be affected.
Quoted 3 lines
It will offend a few people but it's still pre 1.0 and we can break the API. I'd rather get this right now than having to life with side effects for a long time.
Yes it would be nice to only do it for subsystems that need it. The only place I can see in the existing arguments for nla_parse() is to overload the meaning of the unused policy[0]. The other options are to change nla_parse() or add nla_parse_masked(). Any preference?
Re: [PATCH 1/3] libnl: add netfilter support
* Philip Craig <[email protected]> 2007-09-04 12:12
Quoted 4 lines
Yes it would be nice to only do it for subsystems that need it. The only place I can see in the existing arguments for
nla_parse()is to overload the meaning of the unused policy[0]. The other options are to changenla_parse()or addnla_parse_masked(). Any preference?
Actually after discussing this with Patrick a bit I think we can safely assume that this bit is never set in any other subsystem so just leave it as-is.
Re: [PATCH 1/3] libnl: add netfilter support
In reply to Philip Craig* Philip Craig <[email protected]> 2007-09-03 15:11
Quoted 10 lines
--- include/linux/netfilter/nfnetlink.h | 106 +++++++++++++++ include/netlink/netfilter/nfnl.h | 44 ++++++ include/netlink/netlink.h | 1 lib/Makefile | 2 lib/attr.c | 3 lib/netfilter/nfnl.c | 246 ++++++++++++++++++++++++++++++++++++ 6 files changed, 401 insertions(+), 1 deletion(-)
I've applied this patch with some minor modification which is the removal of most of the macros from include/linux/netfilter/nfnetlink.h for the purpose of making sure people use the generic alternatives.
Thanks a lot Philip!
Re: [PATCH 2/3] libnl: add netfilter conntrack support
In reply to Philip Craig* Philip Craig <[email protected]> 2007-09-03 15:11
Quoted 17 lines
--- include/linux/netfilter/nfnetlink_conntrack.h | 140 +++++ include/netlink-types.h | 44 + include/netlink/addr.h | 1 include/netlink/netfilter/ct.h | 115 ++++ include/netlink/utils.h | 4 lib/addr.c | 28 + lib/netfilter/ct.c | 422 ++++++++++++++++ lib/netfilter/ct_obj.c | 667 ++++++++++++++++++++++++++ lib/utils.c | 36 + src/Makefile | 6 src/f_ct.c | 153 +++++ src/nf-ct-dump.c | 88 +++ src/nf-monitor.c | 115 ++++ 13 files changed, 1818 insertions(+), 1 deletion(-)
Patch applied, thanks!
Re: [PATCH 3/3] libnl: add netfilter log support
In reply to Philip Craig* Philip Craig <[email protected]> 2007-09-03 15:12
Quoted 10 lines
--- include/linux/netfilter/nfnetlink_log.h | 96 +++++++ include/netlink-types.h | 22 + include/netlink/netfilter/log.h | 105 +++++++ lib/netfilter/log.c | 349 ++++++++++++++++++++++++++ lib/netfilter/log_obj.c | 425 ++++++++++++++++++++++++++++++++ src/nf-log.c | 142 ++++++++++ 6 files changed, 1139 insertions(+)
Also applied, thanks for all this great work!