From db5bd57899affbcaf42ac0b93c5c7be8f51ca390 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Fri, 2 Jul 2010 14:06:59 +0200 Subject: [PATCH 01/15] Packet Location Interface --- Makefile.am | 3 + configure.in | 4 +- etc/pktloc | 44 +++++++++ include/netlink-local.h | 1 + include/netlink/errno.h | 3 +- include/netlink/route/pktloc.h | 44 +++++++++ lib/Makefile.am | 19 +++- lib/error.c | 1 + lib/route/pktloc.c | 168 +++++++++++++++++++++++++++++++++ lib/route/pktloc_grammar.l | 42 +++++++++ lib/route/pktloc_syntax.y | 108 +++++++++++++++++++++ src/Makefile.am | 6 +- src/nl-pktloc-lookup.c | 37 ++++++++ 13 files changed, 475 insertions(+), 5 deletions(-) create mode 100644 etc/pktloc create mode 100644 include/netlink/route/pktloc.h create mode 100644 lib/route/pktloc.c create mode 100644 lib/route/pktloc_grammar.l create mode 100644 lib/route/pktloc_syntax.y create mode 100644 src/nl-pktloc-lookup.c diff --git a/Makefile.am b/Makefile.am index 01f9879..e1c47b9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,6 +6,9 @@ SUBDIRS = include lib src doc pkgconfig_DATA = libnl-2.0.pc +sysconfdir = @sysconfdir@/libnl +sysconf_DATA = etc/pktloc + .PHONY: cscope cscope: cscope -b -q -R -Iinclude -slib -ssrc; diff --git a/configure.in b/configure.in index 02b5119..1fcdb64 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ # License as published by the Free Software Foundation version 2.1 # of the License. # -# Copyright (c) 2003-2008 Thomas Graf +# Copyright (c) 2003-2010 Thomas Graf # AC_INIT(libnl, 2.0, tgraf@suug.ch) @@ -18,6 +18,8 @@ AC_PROG_CC AM_PROG_CC_C_O AC_PROG_INSTALL AM_PROG_LIBTOOL +AM_PROG_LEX +AC_PROG_YACC AC_C_CONST AC_C_INLINE diff --git a/etc/pktloc b/etc/pktloc new file mode 100644 index 0000000..db36d40 --- /dev/null +++ b/etc/pktloc @@ -0,0 +1,44 @@ +# +# Location definitions for packet matching +# + +# name alignment offset mask +ip.version u8 net+0 0xF0 +ip.hdrlen u8 net+0 0x0F +ip.diffserv u8 net+1 +ip.length u16 net+2 +ip.id u16 net+4 +ip.df u8 net+6 0x40 +ip.mf u8 net+6 0x20 +ip.offset u16 net+6 0x1FFF +ip.ttl u8 net+8 +ip.proto u8 net+9 +ip.chksum u16 net+10 +ip.src u32 net+12 +ip.dst u32 net+16 + + +# +# Transmission Control Protocol (TCP) +# +# name alignment offset mask +tcp.sport u16 tcp+0 +tcp.dport u16 tcp+2 +tcp.seq u32 tcp+4 +tcp.ack u32 tcp+8 +tcp.off u8 tcp+12 0xF0 +tcp.reserved u8 tcp+12 0x0F +# FLAGS +tcp.win u16 tcp+14 +tcp.csum u16 tcp+16 +tcp.urg u16 tcp+18 +tcp.opts u32 tcp+20 + +# +# User Datagram Protocol (UDP) +# +# name alignment offset mask +udp.sport u16 tcp+0 +udp.dport u16 tcp+2 +udp.length u16 tcp+4 +udp.csum u16 tcp+6 diff --git a/include/netlink-local.h b/include/netlink-local.h index 1fafb51..e0c79db 100644 --- a/include/netlink-local.h +++ b/include/netlink-local.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/include/netlink/errno.h b/include/netlink/errno.h index 0b43da0..c8a376e 100644 --- a/include/netlink/errno.h +++ b/include/netlink/errno.h @@ -45,8 +45,9 @@ extern "C" { #define NLE_PROTO_MISMATCH 26 #define NLE_NOACCESS 27 #define NLE_PERM 28 +#define NLE_PKTLOC_FILE 29 -#define NLE_MAX NLE_PERM +#define NLE_MAX NLE_PKTLOC_FILE extern const char * nl_geterror(int); extern void nl_perror(int, const char *); diff --git a/include/netlink/route/pktloc.h b/include/netlink/route/pktloc.h new file mode 100644 index 0000000..28e1dc2 --- /dev/null +++ b/include/netlink/route/pktloc.h @@ -0,0 +1,44 @@ +/* + * netlink/route/pktloc.h Packet Location Aliasing + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010 Thomas Graf + */ + +#ifndef NETLINK_PKTLOC_H_ +#define NETLINK_PKTLOC_H_ + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rtnl_pktloc +{ + char * name; + uint8_t align:4; + uint8_t layer:4; + uint8_t flags; + uint16_t offset; + uint32_t mask; + + struct nl_list_head list; +}; + +extern int rtnl_pktloc_lookup(const char *, struct rtnl_pktloc **); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 1c2ae99..082408c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE +AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" lib_LTLIBRARIES = \ libnl.la libnl-genl.la libnl-route.la libnl-nf.la @@ -23,6 +23,19 @@ libnl_nf_la_SOURCES = \ netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c +BUILT_SOURCES = route/pktloc_syntax.h +CLEANFILES = \ + route/pktloc_grammar.c route/pktloc_grammar.h \ + route/pktloc_syntax.c route/pktloc_syntax.h + +# Hack to avoid using ylwrap. It does not function correctly in combination +# with --header-file= +route/pktloc_grammar.c: route/pktloc_grammar.l + $(LEX) --header-file=route/pktloc_grammar.h $(LFLAGS) -o $@ $^ + +route/pktloc_syntax.c: route/pktloc_syntax.y + $(YACC) -d $(YFLAGS) -o $@ $^ + libnl_route_la_LDFLAGS = -version-info 2:0:0 libnl_route_la_LIBADD = libnl.la libnl_route_la_SOURCES = \ @@ -40,4 +53,6 @@ libnl_route_la_SOURCES = \ route/sch/fifo.c route/sch/htb.c route/sch/netem.c route/sch/prio.c \ route/sch/red.c route/sch/sfq.c route/sch/tbf.c \ \ - fib_lookup/lookup.c fib_lookup/request.c + fib_lookup/lookup.c fib_lookup/request.c \ + \ + route/pktloc_syntax.c route/pktloc_grammar.c route/pktloc.c diff --git a/lib/error.c b/lib/error.c index b94a235..9a9fac7 100644 --- a/lib/error.c +++ b/lib/error.c @@ -42,6 +42,7 @@ static const char *errmsg[NLE_MAX+1] = { [NLE_PROTO_MISMATCH] = "Protocol mismatch", [NLE_NOACCESS] = "No Access", [NLE_PERM] = "Operation not permitted", +[NLE_PKTLOC_FILE] = "Unable to open packet location file", }; /** diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c new file mode 100644 index 0000000..f0d0155 --- /dev/null +++ b/lib/route/pktloc.c @@ -0,0 +1,168 @@ +/* + * lib/route/pktloc.c Packet Location Aliasing + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2 of the License. + * + * Copyright (c) 2008-2010 Thomas Graf + */ + +/** + * @ingroup tc + * @defgroup pktloc Packet Location Aliasing + * Packet Location Aliasing + * + * The packet location aliasing interface eases the use of offset definitions + * inside packets by allowing them to be referenced by name. Known positions + * of protocol fields are stored in a configuration file and associated with + * a name for later reference. The configuration file is distributed with the + * library and provides a well defined set of definitions for most common + * protocol fields. + * + * @subsection pktloc_examples Examples + * @par Example 1.1 Looking up a packet location + * @code + * struct rtnl_pktloc *loc; + * + * rtnl_pktloc_lookup("ip.src", &loc); + * @endcode + * @{ + */ + +#include +#include +#include +#include +#include + +#include "pktloc_syntax.h" +#include "pktloc_grammar.h" + +/** @cond */ +#define PKTLOC_NAME_HT_SIZ 256 + +static struct nl_list_head pktloc_name_ht[PKTLOC_NAME_HT_SIZ]; + +/* djb2 */ +unsigned int pktloc_hash(const char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash % PKTLOC_NAME_HT_SIZ; +} + + +void rtnl_pktloc_add(struct rtnl_pktloc *loc) +{ + nl_list_add_tail(&loc->list, &pktloc_name_ht[pktloc_hash(loc->name)]); +} + +extern int pktloc_parse(void *scanner); + +/** @endcond */ + +static void rtnl_pktloc_free(struct rtnl_pktloc *loc) +{ + if (!loc) + return; + + free(loc->name); + free(loc); +} + +static int read_pktlocs(void) +{ + YY_BUFFER_STATE buf; + yyscan_t scanner = NULL; + static time_t last_read; + struct stat st = {0}; + char *path; + int i, err; + FILE *fd; + + asprintf(&path, "%s/pktloc", SYSCONFDIR); + + /* if stat fails, just try to read the file */ + if (stat(path, &st) == 0) { + /* Don't re-read file if file is unchanged */ + if (last_read == st.st_mtime) + return 0; + } + + if (!(fd = fopen(path, "r"))) + return -NLE_PKTLOC_FILE; + + for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) { + struct rtnl_pktloc *loc, *n; + + nl_list_for_each_entry_safe(loc, n, &pktloc_name_ht[i], list) + rtnl_pktloc_free(loc); + + nl_init_list_head(&pktloc_name_ht[i]); + } + + if ((err = pktloc_lex_init(&scanner)) < 0) + return -NLE_FAILURE; + + buf = pktloc__create_buffer(fd, YY_BUF_SIZE, scanner); + pktloc__switch_to_buffer(buf, scanner); + + if ((err = pktloc_parse(scanner)) < 0) + return -NLE_FAILURE; + + if (scanner) + pktloc_lex_destroy(scanner); + + free(path); + last_read = st.st_mtime; + + return 0; +} + +/** + * Lookup packet location alias + * @arg name Name of packet location. + * + * Tries to find a matching packet location alias for the supplied + * packet location name. + * + * The file containing the packet location definitions is automatically + * re-read if its modification time has changed since the last call. + * + * @return 0 on success or a negative error code. + * @retval NLE_PKTLOC_FILE Unable to open packet location file. + * @retval NLE_OBJ_NOTFOUND No matching packet location alias found. + */ +int rtnl_pktloc_lookup(const char *name, struct rtnl_pktloc **result) +{ + struct rtnl_pktloc *loc; + int hash, err; + + if ((err = read_pktlocs()) < 0) + return err; + + hash = pktloc_hash(name); + nl_list_for_each_entry(loc, &pktloc_name_ht[hash], list) { + if (!strcasecmp(loc->name, name)) { + *result = loc; + return 0; + } + } + + return -NLE_OBJ_NOTFOUND; +} + +static int __init pktloc_init(void) +{ + int i; + + for (i = 0; i < PKTLOC_NAME_HT_SIZ; i++) + nl_init_list_head(&pktloc_name_ht[i]); + + return 0; +} diff --git a/lib/route/pktloc_grammar.l b/lib/route/pktloc_grammar.l new file mode 100644 index 0000000..f710430 --- /dev/null +++ b/lib/route/pktloc_grammar.l @@ -0,0 +1,42 @@ +%{ + #include + #include + #include + #include + #include + #include "pktloc_syntax.h" +%} + +%option 8bit +%option reentrant +%option warn +%option noyywrap +%option nounput +%option bison-bridge +%option bison-locations +%option prefix="pktloc_" + +%% + +[ \t\r\n]+ + +"#".* + +[[:digit:]]+ | +0[xX][[:xdigit:]]+ { + yylval->i = strtoul(yytext, NULL, 0); + return NUMBER; + } + +"+" { return yylval->i = yytext[0]; } + +[lL][iI][nN][kK] { yylval->i = TCF_LAYER_LINK; return LAYER; } +[nN][eE][tT] { yylval->i = TCF_LAYER_NETWORK; return LAYER; } +[tT][cC][pP] { yylval->i = TCF_LAYER_TRANSPORT; return LAYER; } + +[^ \t\r\n+]+ { + yylval->s = strdup(yytext); + if (yylval->s == NULL) + return ERROR; + return NAME; + } diff --git a/lib/route/pktloc_syntax.y b/lib/route/pktloc_syntax.y new file mode 100644 index 0000000..05d609a --- /dev/null +++ b/lib/route/pktloc_syntax.y @@ -0,0 +1,108 @@ +%{ +#include +#include +#include +#include +#include +%} + +%locations +%error-verbose +%define api.pure +%name-prefix "pktloc_" + +%parse-param {void *scanner} +%lex-param {void *scanner} + +%union { + struct rtnl_pktloc *l; + uint32_t i; + char *s; +} + +%{ +extern int pktloc_lex(YYSTYPE *, YYLTYPE *, void *); +extern void rtnl_pktloc_add(struct rtnl_pktloc *); + +static void yyerror(YYLTYPE *locp, void *scanner, const char *msg) +{ + /* FIXME */ +} +%} + +%token ERROR NUMBER LAYER +%token NAME + +%type mask layer +%type location + +%destructor { free($$); } NAME + +%start input + +%% + +input: + def + { } + ; + +def: + /* empty */ + { } + | location def + { } + ; + +location: + NAME NAME layer NUMBER mask + { + struct rtnl_pktloc *loc; + + if (!(loc = calloc(1, sizeof(*loc)))) { + /* FIXME */ + } + + if (!strcasecmp($2, "u8")) + loc->align = TCF_EM_ALIGN_U8; + else if (!strcasecmp($2, "h8")) { + loc->align = TCF_EM_ALIGN_U8; + loc->flags = TCF_EM_CMP_TRANS; + } else if (!strcasecmp($2, "u16")) + loc->align = TCF_EM_ALIGN_U16; + else if (!strcasecmp($2, "h16")) { + loc->align = TCF_EM_ALIGN_U16; + loc->flags = TCF_EM_CMP_TRANS; + } else if (!strcasecmp($2, "u32")) + loc->align = TCF_EM_ALIGN_U32; + else if (!strcasecmp($2, "h32")) { + loc->align = TCF_EM_ALIGN_U32; + loc->flags = TCF_EM_CMP_TRANS; + } + + free($2); + + loc->name = $1; + loc->layer = $3; + loc->offset = $4; + loc->mask = $5; + + rtnl_pktloc_add(loc); + + $$ = loc; + } + ; + +layer: + /* empty */ + { $$ = TCF_LAYER_NETWORK; } + | LAYER '+' + { $$ = $1; } + ; + +mask: + /* empty */ + { $$ = 0; } + | NUMBER + { $$ = $1; } + ; diff --git a/src/Makefile.am b/src/Makefile.am index ca37843..4e2b57c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,7 +20,8 @@ noinst_PROGRAMS = \ nl-route-add nl-route-delete nl-route-get nl-route-list \ nl-fib-lookup \ nl-list-caches nl-list-sockets \ - nl-util-addr + nl-util-addr \ + nl-pktloc-lookup genl_ctrl_list_SOURCES = genl-ctrl-list.c genl_ctrl_list_LDADD = -lnl-genl -lnl-route @@ -95,3 +96,6 @@ nl_list_sockets_LDADD = -lnl-route nl_util_addr_SOURCES = nl-util-addr.c nl_util_addr_LDADD = -lnl-route + +nl_pktloc_lookup_SOURCES = nl-pktloc-lookup.c +nl_pktloc_lookup_LDADD = -lnl-route diff --git a/src/nl-pktloc-lookup.c b/src/nl-pktloc-lookup.c new file mode 100644 index 0000000..09b04b2 --- /dev/null +++ b/src/nl-pktloc-lookup.c @@ -0,0 +1,37 @@ +/* + * src/nl-pktloc-lookup.c Lookup packet location alias + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2010 Thomas Graf + */ + +#include +#include + +static void print_usage(void) +{ + printf("Usage: nl-pktloc-lookup \n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct rtnl_pktloc *loc; + int err; + + if (argc < 2) + print_usage(); + + if ((err = rtnl_pktloc_lookup(argv[1], &loc)) < 0) + nl_cli_fatal(err, "Unable to lookup packet location: %s", + nl_geterror(err)); + + printf("%s: %u %u+%u 0x%x %u\n", loc->name, loc->align, + loc->layer, loc->offset, loc->mask, loc->flags); + + return 0; +} From 256d7e723c0ff402422d3501866e9301b3f64c0f Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 3 Jul 2010 15:14:13 +0200 Subject: [PATCH 02/15] Fix compile warning in nl.c --- include/netlink/netlink.h | 2 +- lib/nl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h index 34eb773..1cfe220 100644 --- a/include/netlink/netlink.h +++ b/include/netlink/netlink.h @@ -51,7 +51,7 @@ extern int nl_sendmsg(struct nl_sock *, struct nl_msg *, struct msghdr *); extern int nl_send(struct nl_sock *, struct nl_msg *); extern int nl_send_iovec(struct nl_sock *, struct nl_msg *, - const struct iovec *, unsigned); + struct iovec *, unsigned); extern void nl_auto_complete(struct nl_sock *, struct nl_msg *); extern int nl_send_auto_complete(struct nl_sock *, diff --git a/lib/nl.c b/lib/nl.c index ed501f7..c453b60 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -232,7 +232,7 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) * @see nl_sendmsg() * @return Number of characters sent on success or a negative error code. */ -int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, const struct iovec *iov, unsigned iovlen) +int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen) { struct sockaddr_nl *dst; struct ucred *creds; From 0fa04772ab1e092fce34b658d6cc4e6f6b59be1d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 3 Jul 2010 15:17:04 +0200 Subject: [PATCH 03/15] Fix compile warning in utils.c --- lib/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.c b/lib/utils.c index 4007bee..e1fdae1 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -316,7 +316,7 @@ static void __init get_psched_settings(void) uint32_t tick, us; /* the file contains 4 hexadecimals, but we just use the first two of them */ - int r = fscanf(fd, "%08x %08x", &tick, &us); + fscanf(fd, "%08x %08x", &tick, &us); ticks_per_usec = (double)tick/(double)us; fclose(fd); } From 7cf52dd94b5295b0b649f6ea8b2bf4fbf35abe33 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 3 Jul 2010 15:56:07 +0200 Subject: [PATCH 04/15] Let git ignore generated pktloc source files --- lib/route/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 lib/route/.gitignore diff --git a/lib/route/.gitignore b/lib/route/.gitignore new file mode 100644 index 0000000..debf3b7 --- /dev/null +++ b/lib/route/.gitignore @@ -0,0 +1,4 @@ +pktloc_grammar.h +pktloc_grammar.c +pktloc_syntax.h +pktloc_syntax.c From 6921b1c879e1423abe7e5ec9bd8bb4d89bb241e7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 3 Jul 2010 15:56:51 +0200 Subject: [PATCH 05/15] Ignore vim swap files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e3a31d4..17a67a0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.la *.lo *.o +*.swp Makefile /lib/stamp-h1 From 018c297274348acba1e123a3e84471c75a215efb Mon Sep 17 00:00:00 2001 From: Karl Hiramoto Date: Wed, 16 Jun 2010 16:33:51 +0200 Subject: [PATCH 06/15] libnl: optionally disable cli tools. compile and link time can reduced, most non-developers don't need these cli tools. ./configure --disable-cli time make real 0m40.485s user 0m33.784s sys 0m2.793s ./configure time make real 0m53.097s user 0m42.077s sys 0m4.396s Signed-off-by: Karl Hiramoto --- Makefile.am | 8 +++++++- configure.in | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index e1c47b9..8f9438c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,13 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include lib src doc +OPT_DIRS = + +if ENABLE_CLI +OPT_DIRS += src +endif + +SUBDIRS = include lib doc $(OPT_DIRS) pkgconfig_DATA = libnl-2.0.pc diff --git a/configure.in b/configure.in index 1fcdb64..18d2716 100644 --- a/configure.in +++ b/configure.in @@ -29,6 +29,11 @@ AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH], [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) AC_SUBST([pkgconfigdir]) +AC_ARG_ENABLE([cli], + AS_HELP_STRING([--disable-cli], [Do not build command line interface utils]), + [enable_cli="$enableval"], [enable_cli="yes"]) +AM_CONDITIONAL([ENABLE_CLI], [test "$enable_cli" = "yes"]) + AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile From 86b6f6f6291eaaec542a2f4028087fa823122082 Mon Sep 17 00:00:00 2001 From: Denys Fedorysychenko Date: Sat, 10 Jul 2010 02:48:06 +0300 Subject: [PATCH 07/15] Trivial fix for TBF memleak Without this patch, running alloc / free cache loop will lead to huge memory leaks on machine with 3000 interfaces with tbf qdiscs. Here was valgrind output: ==5580== 18,070,728 bytes in 347,514 blocks are definitely lost in loss record 32 of 32 ==5580== at 0x4025485: calloc (in /lib/valgrind/vgpreload_memcheck-x86- linux.so) ==5580== by 0x405F410: tbf_msg_parser (tbf.c:46) ==5580== by 0x405302B: qdisc_msg_parser (qdisc.c:119) ==5580== by 0x4033DC9: nl_cache_parse (cache.c:643) ==5580== by 0x4033E7C: update_msg_parser (cache.c:460) ==5580== by 0x4038A11: nl_recvmsgs (netlink-local.h:112) ==5580== by 0x4034175: __cache_pickup (cache.c:483) ==5580== by 0x40343FF: nl_cache_pickup (cache.c:516) ==5580== by 0x403447D: nl_cache_refill (cache.c:698) ==5580== by 0x4034AB7: nl_cache_alloc_and_fill (cache.c:198) ==5580== by 0x4053216: rtnl_qdisc_alloc_cache (qdisc.c:388) ==5580== by 0x80489DB: main (in /home/root/nltest) Patch complied and tested for same test case, no more leaks anymore. --- lib/route/sch/tbf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/route/sch/tbf.c b/lib/route/sch/tbf.c index 29453e3..eccaf70 100644 --- a/lib/route/sch/tbf.c +++ b/lib/route/sch/tbf.c @@ -93,6 +93,11 @@ static int tbf_msg_parser(struct rtnl_qdisc *q) return 0; } +static void tbf_free_data(struct rtnl_qdisc *qdisc) +{ + free(qdisc->q_subdata); +} + static void tbf_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p) { double r, rbit, lim; @@ -517,6 +522,7 @@ static struct rtnl_qdisc_ops tbf_qdisc_ops = { [NL_DUMP_LINE] = tbf_dump_line, [NL_DUMP_DETAILS] = tbf_dump_details, }, + .qo_free_data = tbf_free_data, .qo_get_opts = tbf_get_opts, }; From 4ab22ccd47319e7d9a972bcf018e1a03870f64f0 Mon Sep 17 00:00:00 2001 From: Andreas Fett Date: Wed, 22 Sep 2010 20:10:26 +0200 Subject: [PATCH 08/15] add user data to change_func_t for caches the patch below adds the possibility to pass user data to callbacks of type change_func_t when using the nl_cache_mngr_* family of functions. If there is any better way to do this, without duplicating the code in cache_mngr.c please let me know. --- include/netlink-types.h | 1 + include/netlink/cache.h | 9 ++++++--- lib/cache.c | 19 ++++++++++--------- lib/cache_mngr.c | 5 +++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/netlink-types.h b/include/netlink-types.h index ace5dde..ff699bb 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -83,6 +83,7 @@ struct nl_cache_assoc { struct nl_cache * ca_cache; change_func_t ca_change; + void * ca_change_data; }; struct nl_cache_mngr diff --git a/include/netlink/cache.h b/include/netlink/cache.h index f4db3b9..c752920 100644 --- a/include/netlink/cache.h +++ b/include/netlink/cache.h @@ -24,7 +24,7 @@ extern "C" { struct nl_cache; -typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int); +typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *); /* Access Functions */ extern int nl_cache_nitems(struct nl_cache *); @@ -59,10 +59,12 @@ extern int nl_cache_pickup(struct nl_sock *, struct nl_cache *); extern int nl_cache_resync(struct nl_sock *, struct nl_cache *, - change_func_t); + change_func_t, + void *); extern int nl_cache_include(struct nl_cache *, struct nl_object *, - change_func_t); + change_func_t, + void *); /* General */ extern int nl_cache_is_empty(struct nl_cache *); @@ -112,6 +114,7 @@ extern int nl_cache_mngr_alloc(struct nl_sock *, extern int nl_cache_mngr_add(struct nl_cache_mngr *, const char *, change_func_t, + void *, struct nl_cache **); extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *); extern int nl_cache_mngr_poll(struct nl_cache_mngr *, diff --git a/lib/cache.c b/lib/cache.c index 5fab32a..2b24946 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -517,7 +517,7 @@ int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache) } static int cache_include(struct nl_cache *cache, struct nl_object *obj, - struct nl_msgtype *type, change_func_t cb) + struct nl_msgtype *type, change_func_t cb, void *data) { struct nl_object *old; @@ -529,7 +529,7 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, nl_cache_remove(old); if (type->mt_act == NL_ACT_DEL) { if (cb) - cb(cache, old, NL_ACT_DEL); + cb(cache, old, NL_ACT_DEL, data); nl_object_put(old); } } @@ -537,10 +537,10 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, if (type->mt_act == NL_ACT_NEW) { nl_cache_move(cache, obj); if (old == NULL && cb) - cb(cache, obj, NL_ACT_NEW); + cb(cache, obj, NL_ACT_NEW, data); else if (old) { if (nl_object_diff(old, obj) && cb) - cb(cache, obj, NL_ACT_CHANGE); + cb(cache, obj, NL_ACT_CHANGE, data); nl_object_put(old); } @@ -555,7 +555,7 @@ static int cache_include(struct nl_cache *cache, struct nl_object *obj, } int nl_cache_include(struct nl_cache *cache, struct nl_object *obj, - change_func_t change_cb) + change_func_t change_cb, void *data) { struct nl_cache_ops *ops = cache->c_ops; int i; @@ -566,7 +566,7 @@ int nl_cache_include(struct nl_cache *cache, struct nl_object *obj, for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype) return cache_include(cache, obj, &ops->co_msgtypes[i], - change_cb); + change_cb, data); return -NLE_MSGTYPE_NOSUPPORT; } @@ -575,16 +575,17 @@ static int resync_cb(struct nl_object *c, struct nl_parser_param *p) { struct nl_cache_assoc *ca = p->pp_arg; - return nl_cache_include(ca->ca_cache, c, ca->ca_change); + return nl_cache_include(ca->ca_cache, c, ca->ca_change, ca->ca_change_data); } int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, - change_func_t change_cb) + change_func_t change_cb, void *data) { struct nl_object *obj, *next; struct nl_cache_assoc ca = { .ca_cache = cache, .ca_change = change_cb, + .ca_change_data = data, }; struct nl_parser_param p = { .pp_cb = resync_cb, @@ -610,7 +611,7 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, nl_object_get(obj); nl_cache_remove(obj); if (change_cb) - change_cb(cache, obj, NL_ACT_DEL); + change_cb(cache, obj, NL_ACT_DEL, data); nl_object_put(obj); } } diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c index 0675316..81052aa 100644 --- a/lib/cache_mngr.c +++ b/lib/cache_mngr.c @@ -95,7 +95,7 @@ static int include_cb(struct nl_object *obj, struct nl_parser_param *p) if (nl_debug >= 4) nl_object_dump(obj, &nl_debug_dp); #endif - return nl_cache_include(ca->ca_cache, obj, ca->ca_change); + return nl_cache_include(ca->ca_cache, obj, ca->ca_change, ca->ca_change_data); } static int event_input(struct nl_msg *msg, void *arg) @@ -207,7 +207,7 @@ errout: * @return 0 on success or a negative error code. */ int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, - change_func_t cb, struct nl_cache **result) + change_func_t cb, void *data, struct nl_cache **result) { struct nl_cache_ops *ops; struct nl_cache *cache; @@ -264,6 +264,7 @@ retry: mngr->cm_assocs[i].ca_cache = cache; mngr->cm_assocs[i].ca_change = cb; + mngr->cm_assocs[i].ca_change_data = data; if (mngr->cm_flags & NL_AUTO_PROVIDE) nl_cache_mngt_provide(cache); From a172e3ccf0617828a23d08c8c4a8eb4825ce0ccf Mon Sep 17 00:00:00 2001 From: "Matthew L. Creech" Date: Mon, 19 Apr 2010 11:16:30 -0400 Subject: [PATCH 09/15] Put preprocessor definitions in AM_CPPFLAGS When an alternate kernel header include directory is added in CPPFLAGS, the libnl build fails. This is because the local copy of kernel headers is added in AM_CFLAGS, which gets included after CPPFLAGS in the automake-generated makefile. Switching to AM_CPPFLAGS fixes the problems. --- lib/Makefile.am | 2 +- src/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 082408c..c2815c4 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" lib_LTLIBRARIES = \ libnl.la libnl-genl.la libnl-route.la libnl-nf.la diff --git a/src/Makefile.am b/src/Makefile.am index 4e2b57c..d72284d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS = lib -AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE AM_LDFLAGS = -L${top_builddir}/lib -L${top_builddir}/src/lib -lnl-cli noinst_PROGRAMS = \ From 706ac94ed523be847f09d04544d379d35263a930 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Oct 2010 14:30:50 +0200 Subject: [PATCH 10/15] Use CPPFLAGS --- src/lib/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 068c3a6..dd4f6cf 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -AM_CFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic AM_LDFLAGS = -L${top_builddir}/lib -ldl #nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la From cb05bbb0e2d38f41569754e1505c22929537c17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Thu, 5 Aug 2010 15:19:02 +0200 Subject: [PATCH 11/15] automake: add ${top_builddir}/include to AM_CFLAGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch enables out-of-source builds like this $ cd builddir && src_dir/configure && make Before this patch there was an error about missing netlink/version.h which is built by automake in top_builddir rather than top_srcdir which is already in include search path. Signed-off-by: Andreas Bießmann --- lib/Makefile.am | 2 +- src/Makefile.am | 2 +- src/lib/Makefile.am | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index c2815c4..b415b63 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" lib_LTLIBRARIES = \ libnl.la libnl-genl.la libnl-route.la libnl-nf.la diff --git a/src/Makefile.am b/src/Makefile.am index d72284d..dda32a7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS = lib -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE AM_LDFLAGS = -L${top_builddir}/lib -L${top_builddir}/src/lib -lnl-cli noinst_PROGRAMS = \ diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index dd4f6cf..80c217c 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,6 +1,6 @@ # -*- Makefile -*- -AM_CPPFLAGS = -Wall -I${top_srcdir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic +AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic AM_LDFLAGS = -L${top_builddir}/lib -ldl #nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la From 2b3fabab9ef2445ab1c48de0fed82514e4eb32dc Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 13 Oct 2010 15:17:33 +0200 Subject: [PATCH 12/15] route_obj: don't add empty destination to nlmsg don't try to give the kernel an empty RTA_DST attribute. this would previously happening on trying to delete the default route as returned from the kernel. the kernel doesn't add a RTA_DST atttribute, so libnl does nl_addr_alloc(0) and inserts a zero-length RTA_DST attribute into the deletion request, which the kernel then refuses with ERANGE. Signed-off-by: David Lamparter --- lib/route/route_obj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 4e14d6d..7f26bfd 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -1108,7 +1108,8 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) * required to allow more than 256 tables. */ NLA_PUT_U32(msg, RTA_TABLE, route->rt_table); - NLA_PUT_ADDR(msg, RTA_DST, route->rt_dst); + if (nl_addr_get_len(route->rt_dst)) + NLA_PUT_ADDR(msg, RTA_DST, route->rt_dst); NLA_PUT_U32(msg, RTA_PRIORITY, route->rt_prio); if (route->ce_mask & ROUTE_ATTR_SRC) From 513e45ccce5ae286fc67fde1a1bf703e9c8d83aa Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Wed, 13 Oct 2010 16:50:33 +0200 Subject: [PATCH 13/15] Don't include pktloc_syntax.h in BUILT_SOURCES --- lib/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index b415b63..92a916e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -23,7 +23,6 @@ libnl_nf_la_SOURCES = \ netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \ netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c -BUILT_SOURCES = route/pktloc_syntax.h CLEANFILES = \ route/pktloc_grammar.c route/pktloc_grammar.h \ route/pktloc_syntax.c route/pktloc_syntax.h From 2dbc1ca76c5b82c40749e609eb83877418abb006 Mon Sep 17 00:00:00 2001 From: dima Date: Wed, 13 Oct 2010 17:53:34 +0300 Subject: [PATCH 14/15] Generic Netlink multicast groups support I have a patch against commit d378220c96c3c8b6f27dca33e7d8ba03318f9c2d extending libnl with a facility to receive generic netlink messages sent to multicast groups. Essentially it add one new function genl_ctrl_resolve_grp which prototype looks like this int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, const char *grp_name) It resolves the family name and the group name to group id. Then the returned id can be used in nl_socket_add_membership to subscribe to multicast messages. Besides that it adds two more functions uint32_t nl_socket_get_peer_groups(struct nl_sock *sk) void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups) allowing to modify the socket peer groups field. So it's possible to multicast messages from the user space using the legacy interface. Looks like there is no way (or I was not able to find one?) to modify the netlink socket destination group from the user space, when the group id is greater then 32. --- include/linux/genetlink.h | 14 +++++++ include/netlink-types.h | 8 ++++ include/netlink/genl/ctrl.h | 3 ++ include/netlink/genl/family.h | 3 ++ include/netlink/genl/genl.h | 1 - include/netlink/socket.h | 3 +- lib/genl/ctrl.c | 78 +++++++++++++++++++++++++++++++++++ lib/genl/family.c | 39 ++++++++++++++++++ lib/nl.c | 2 +- lib/socket.c | 12 ++++++ 10 files changed, 160 insertions(+), 3 deletions(-) diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h index f7a9377..b834ef6 100644 --- a/include/linux/genetlink.h +++ b/include/linux/genetlink.h @@ -1,6 +1,7 @@ #ifndef __LINUX_GENERIC_NETLINK_H #define __LINUX_GENERIC_NETLINK_H +#include #include #define GENL_NAMSIZ 16 /* length of family name */ @@ -39,6 +40,9 @@ enum { CTRL_CMD_NEWOPS, CTRL_CMD_DELOPS, CTRL_CMD_GETOPS, + CTRL_CMD_NEWMCAST_GRP, + CTRL_CMD_DELMCAST_GRP, + CTRL_CMD_GETMCAST_GRP, /* unused */ __CTRL_CMD_MAX, }; @@ -52,6 +56,7 @@ enum { CTRL_ATTR_HDRSIZE, CTRL_ATTR_MAXATTR, CTRL_ATTR_OPS, + CTRL_ATTR_MCAST_GROUPS, __CTRL_ATTR_MAX, }; @@ -66,4 +71,13 @@ enum { #define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) +enum { + CTRL_ATTR_MCAST_GRP_UNSPEC, + CTRL_ATTR_MCAST_GRP_NAME, + CTRL_ATTR_MCAST_GRP_ID, + __CTRL_ATTR_MCAST_GRP_MAX, +}; + +#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) + #endif /* __LINUX_GENERIC_NETLINK_H */ diff --git a/include/netlink-types.h b/include/netlink-types.h index ff699bb..1ffb70c 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -702,6 +702,13 @@ struct genl_family_op struct nl_list_head o_list; }; +struct genl_family_grp { + struct genl_family *family; /* private */ + struct nl_list_head list; /* private */ + char name[GENL_NAMSIZ]; + u_int32_t id; +}; + struct genl_family { NLHDR_COMMON @@ -713,6 +720,7 @@ struct genl_family uint32_t gf_maxattr; struct nl_list_head gf_ops; + struct nl_list_head gf_mc_grps; }; union nfnl_ct_proto diff --git a/include/netlink/genl/ctrl.h b/include/netlink/genl/ctrl.h index 1ae62f4..26a0a99 100644 --- a/include/netlink/genl/ctrl.h +++ b/include/netlink/genl/ctrl.h @@ -29,6 +29,9 @@ extern struct genl_family * genl_ctrl_search_by_name(struct nl_cache *, const char *); extern int genl_ctrl_resolve(struct nl_sock *, const char *); +extern int genl_ctrl_resolve_grp(struct nl_sock *sk, + const char *family, + const char *grp); #ifdef __cplusplus } diff --git a/include/netlink/genl/family.h b/include/netlink/genl/family.h index 74319e5..721dc13 100644 --- a/include/netlink/genl/family.h +++ b/include/netlink/genl/family.h @@ -42,6 +42,9 @@ extern void genl_family_set_maxattr(struct genl_family *, extern int genl_family_add_op(struct genl_family *, int, int); +extern int genl_family_add_grp(struct genl_family *, + uint32_t , const char *); + #ifdef __cplusplus } diff --git a/include/netlink/genl/genl.h b/include/netlink/genl/genl.h index 3f3340c..364a471 100644 --- a/include/netlink/genl/genl.h +++ b/include/netlink/genl/genl.h @@ -21,7 +21,6 @@ extern "C" { #endif extern int genl_connect(struct nl_sock *); - extern int genl_send_simple(struct nl_sock *, int, int, int, int); diff --git a/include/netlink/socket.h b/include/netlink/socket.h index 7e71aed..31a36d3 100644 --- a/include/netlink/socket.h +++ b/include/netlink/socket.h @@ -37,7 +37,8 @@ extern void nl_join_groups(struct nl_sock *, int); extern uint32_t nl_socket_get_peer_port(struct nl_sock *); extern void nl_socket_set_peer_port(struct nl_sock *, uint32_t); - +extern uint32_t nl_socket_get_peer_groups(struct nl_sock *sk); +extern void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups); extern struct nl_cb * nl_socket_get_cb(struct nl_sock *); extern void nl_socket_set_cb(struct nl_sock *, struct nl_cb *); diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c index 1301642..3871795 100644 --- a/lib/genl/ctrl.c +++ b/lib/genl/ctrl.c @@ -45,6 +45,7 @@ static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 }, [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, [CTRL_ATTR_OPS] = { .type = NLA_NESTED }, + [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED }, }; static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { @@ -52,6 +53,11 @@ static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 }, }; +static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = { + [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING }, + [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 }, +}; + static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, struct genl_info *info, void *arg) { @@ -126,6 +132,40 @@ static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, } } + + if (info->attrs[CTRL_ATTR_MCAST_GROUPS]) { + struct nlattr *nla, *nla_grps; + int remaining; + + nla_grps = info->attrs[CTRL_ATTR_MCAST_GROUPS]; + nla_for_each_nested(nla, nla_grps, remaining) { + struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1]; + int id; + const char * name; + + err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, + family_grp_policy); + if (err < 0) + goto errout; + + if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); + + if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]); + + err = genl_family_add_grp(family, id, name); + if (err < 0) + goto errout; + } + + } err = pp->pp_cb((struct nl_object *) family, pp); errout: @@ -242,6 +282,44 @@ errout: return err; } +static int genl_ctrl_grp_by_name(const struct genl_family *family, + const char *grp_name) +{ + struct genl_family_grp *grp; + + nl_list_for_each_entry(grp, &family->gf_mc_grps, list) { + if (!strcmp(grp->name, grp_name)) { + return grp->id; + } + } + + return 0; +} + +int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, + const char *grp_name) +{ + struct nl_cache *cache; + struct genl_family *family; + int err; + + if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0) + return err; + + family = genl_ctrl_search_by_name(cache, family_name); + if (family == NULL) { + err = -NLE_OBJ_NOTFOUND; + goto errout; + } + + err = genl_ctrl_grp_by_name(family, grp_name); + genl_family_put(family); +errout: + nl_cache_free(cache); + + return err; +} + /** @} */ static struct genl_cmd genl_cmds[] = { diff --git a/lib/genl/family.c b/lib/genl/family.c index 4c6c18d..687f4b1 100644 --- a/lib/genl/family.c +++ b/lib/genl/family.c @@ -39,12 +39,14 @@ static void family_constructor(struct nl_object *c) struct genl_family *family = (struct genl_family *) c; nl_init_list_head(&family->gf_ops); + nl_init_list_head(&family->gf_mc_grps); } static void family_free_data(struct nl_object *c) { struct genl_family *family = (struct genl_family *) c; struct genl_family_op *ops, *tmp; + struct genl_family_grp *grp, *t_grp; if (family == NULL) return; @@ -53,6 +55,12 @@ static void family_free_data(struct nl_object *c) nl_list_del(&ops->o_list); free(ops); } + + nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) { + nl_list_del(&grp->list); + free(grp); + } + } static int family_clone(struct nl_object *_dst, struct nl_object *_src) @@ -60,6 +68,7 @@ static int family_clone(struct nl_object *_dst, struct nl_object *_src) struct genl_family *dst = nl_object_priv(_dst); struct genl_family *src = nl_object_priv(_src); struct genl_family_op *ops; + struct genl_family_grp *grp; int err; nl_list_for_each_entry(ops, &src->gf_ops, o_list) { @@ -67,6 +76,13 @@ static int family_clone(struct nl_object *_dst, struct nl_object *_src) if (err < 0) return err; } + + nl_list_for_each_entry(grp, &src->gf_mc_grps, list) { + err = genl_family_add_grp(dst, grp->id, grp->name); + if (err < 0) + return err; + } + return 0; } @@ -93,6 +109,7 @@ static char *ops_flags2str(int flags, char *buf, size_t len) static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p) { + struct genl_family_grp *grp; struct genl_family *family = (struct genl_family *) obj; family_dump_line(obj, p); @@ -118,6 +135,11 @@ static void family_dump_details(struct nl_object *obj, struct nl_dump_params *p) nl_dump(p, "\n"); } } + + nl_list_for_each_entry(grp, &family->gf_mc_grps, list) { + nl_dump_line(p, " grp %s (0x%02x)\n", grp->name, grp->id); + } + } static void family_dump_stats(struct nl_object *obj, struct nl_dump_params *p) @@ -255,6 +277,23 @@ int genl_family_add_op(struct genl_family *family, int id, int flags) return 0; } +int genl_family_add_grp(struct genl_family *family, uint32_t id, + const char *name) +{ + struct genl_family_grp *grp; + + grp = calloc(1, sizeof(*grp)); + if (grp == NULL) + return -NLE_NOMEM; + + grp->id = id; + strncpy(grp->name, name, GENL_NAMSIZ - 1); + + nl_list_add_tail(&grp->list, &family->gf_mc_grps); + + return 0; +} + /** @} */ /** @cond SKIP */ diff --git a/lib/nl.c b/lib/nl.c index c453b60..13c0514 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -387,7 +387,7 @@ errout: * Receives a netlink message, allocates a buffer in \c *buf and * stores the message content. The peer's netlink address is stored * in \c *nla. The caller is responsible for freeing the buffer allocated - * in \c *buf if a positive value is returned. Interruped system calls + * in \c *buf if a positive value is returned. Interrupted system calls * are handled by repeating the read. The input buffer size is determined * by peeking before the actual read is done. * diff --git a/lib/socket.c b/lib/socket.c index 8083bbb..bed53c1 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -398,6 +398,18 @@ void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port) sk->s_peer.nl_pid = port; } +uint32_t nl_socket_get_peer_groups(struct nl_sock *sk) +{ + return sk->s_peer.nl_groups; +} + +void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups) +{ + sk->s_peer.nl_groups = groups; +} + + + /** @} */ /** From 3229b32e39363c439f0d042b561417e7b48aa786 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Oct 2010 13:56:46 +0200 Subject: [PATCH 15/15] - Prepare for 2.1.x tree - Bump interface number, we will break API in the development tree --- Makefile.am | 2 +- configure.in | 4 ++-- lib/Makefile.am | 5 +---- libnl-2.0.pc.in => libnl-2.1.pc.in | 0 src/lib/Makefile.am | 4 +--- 5 files changed, 5 insertions(+), 10 deletions(-) rename libnl-2.0.pc.in => libnl-2.1.pc.in (100%) diff --git a/Makefile.am b/Makefile.am index 8f9438c..28545fd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ endif SUBDIRS = include lib doc $(OPT_DIRS) -pkgconfig_DATA = libnl-2.0.pc +pkgconfig_DATA = libnl-2.1.pc sysconfdir = @sysconfdir@/libnl sysconf_DATA = etc/pktloc diff --git a/configure.in b/configure.in index 18d2716..2d0b2dd 100644 --- a/configure.in +++ b/configure.in @@ -9,7 +9,7 @@ # Copyright (c) 2003-2010 Thomas Graf # -AC_INIT(libnl, 2.0, tgraf@suug.ch) +AC_INIT(libnl, 2.1, tgraf@suug.ch) AC_CONFIG_HEADERS([lib/defs.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) @@ -38,5 +38,5 @@ AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required])) AC_CONFIG_FILES([Makefile doc/Doxyfile doc/Makefile lib/Makefile include/Makefile src/Makefile src/lib/Makefile \ - libnl-2.0.pc include/netlink/version.h]) + libnl-2.1.pc include/netlink/version.h]) AC_OUTPUT diff --git a/lib/Makefile.am b/lib/Makefile.am index 92a916e..ba64a99 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,21 +1,19 @@ # -*- Makefile -*- AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DSYSCONFDIR=\"$(sysconfdir)/libnl\" +AM_LDFLAGS = -version-info 3:0:0 lib_LTLIBRARIES = \ libnl.la libnl-genl.la libnl-route.la libnl-nf.la -libnl_la_LDFLAGS = -version-info 2:0:0 libnl_la_SOURCES = \ addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c doc.c \ error.c handlers.c msg.c nl.c object.c socket.c utils.c -libnl_genl_la_LDFLAGS = -version-info 2:0:0 libnl_genl_la_LIBADD = libnl.la libnl_genl_la_SOURCES = \ genl/ctrl.c genl/family.c genl/genl.c genl/mngt.c -libnl_nf_la_LDFLAGS = -version-info 2:0:0 libnl_nf_la_LIBADD = libnl-route.la libnl_nf_la_SOURCES = \ netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \ @@ -35,7 +33,6 @@ route/pktloc_grammar.c: route/pktloc_grammar.l route/pktloc_syntax.c: route/pktloc_syntax.y $(YACC) -d $(YFLAGS) -o $@ $^ -libnl_route_la_LDFLAGS = -version-info 2:0:0 libnl_route_la_LIBADD = libnl.la libnl_route_la_SOURCES = \ route/addr.c route/class.c route/class_api.c route/class_obj.c \ diff --git a/libnl-2.0.pc.in b/libnl-2.1.pc.in similarity index 100% rename from libnl-2.0.pc.in rename to libnl-2.1.pc.in diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 80c217c..2b48876 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,7 +1,7 @@ # -*- Makefile -*- AM_CPPFLAGS = -Wall -I${top_srcdir}/include -I${top_builddir}/include -D_GNU_SOURCE -DPKGLIBDIR=\"$(pkglibdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -rdynamic -AM_LDFLAGS = -L${top_builddir}/lib -ldl +AM_LDFLAGS = -L${top_builddir}/lib -ldl -version-info 3:0:0 #nobase_pkglib_LTLIBRARIES = cls/basic.la cls/ematch/cmp.la #cls_basic_la_LDFLAGS = -module -version-info 2:0:0 @@ -28,8 +28,6 @@ AM_LDFLAGS = -L${top_builddir}/lib -ldl lib_LTLIBRARIES = \ libnl-cli.la -libnl_cli_la_LDFLAGS = -version-info 2:0:0 - libnl_cli_la_LIBADD = ${top_builddir}/lib/libnl.la \ ${top_builddir}/lib/libnl-route.la \ ${top_builddir}/lib/libnl-nf.la \