]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
iproute2: add libgenl files
authorJulian Anastasov <ja@ssi.bg>
Tue, 11 Sep 2012 09:04:33 +0000 (12:04 +0300)
committerStephen Hemminger <shemminger@vyatta.com>
Tue, 11 Sep 2012 15:59:09 +0000 (08:59 -0700)
Create libgenl.h and libgenl.c. They will contain
common code for GENL users such as ipl2tp, tcp_metrics, etc.

Somewhat simplified by Stephen Hemminger

Signed-off-by: Julian Anastasov <ja@ssi.bg>
include/libgenl.h [new file with mode: 0644]
lib/Makefile
lib/libgenl.c [new file with mode: 0644]

diff --git a/include/libgenl.h b/include/libgenl.h
new file mode 100644 (file)
index 0000000..0b11a89
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __LIBGENL_H__
+#define __LIBGENL_H__
+
+#include "libnetlink.h"
+
+#define GENL_REQUEST(_req, _hdrsiz, _bufsiz)                           \
+struct {                                                               \
+       struct nlmsghdr         n;                                      \
+       struct genlmsghdr       g;                                      \
+       char                    buf[NLMSG_ALIGN(_hdrsiz) + (_bufsiz)];  \
+} _req
+
+#define GENL_INITIALIZER(_family, _hdrsiz, _ver, _cmd, _flags)         \
+       {                                                               \
+               .n = {                                                  \
+                       .nlmsg_type = (_family),                        \
+                       .nlmsg_flags = (_flags),                        \
+                       .nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN + (_hdrsiz)), \
+               },                                                      \
+               .g = {                                                  \
+                       .cmd = (_cmd),                                  \
+                       .version = (_ver),                              \
+               },                                                      \
+       }
+
+extern int genl_resolve_family(struct rtnl_handle *grth, const char *family);
+
+#endif /* __LIBGENL_H__ */
index da2f0fcbe85b0dead52e2e526bd864ed2ab1d121..bfbe67251847395eca52f2a5c4ce868d739bd688 100644 (file)
@@ -2,7 +2,7 @@ CFLAGS += -fPIC
 
 UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o
 
-NLOBJ=ll_map.o libnetlink.o
+NLOBJ=libgenl.o ll_map.o libnetlink.o
 
 all: libnetlink.a libutil.a
 
diff --git a/lib/libgenl.c b/lib/libgenl.c
new file mode 100644 (file)
index 0000000..d68e58e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * libgenl.c   GENL library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/genetlink.h>
+#include "libgenl.h"
+
+static int genl_parse_getfamily(struct nlmsghdr *nlh)
+{
+       struct rtattr *tb[CTRL_ATTR_MAX + 1];
+       struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
+       int len = nlh->nlmsg_len;
+       struct rtattr *attrs;
+
+       if (nlh->nlmsg_type != GENL_ID_CTRL) {
+               fprintf(stderr, "Not a controller message, nlmsg_len=%d "
+                       "nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
+               return -1;
+       }
+
+       len -= NLMSG_LENGTH(GENL_HDRLEN);
+
+       if (len < 0) {
+               fprintf(stderr, "wrong controller message len %d\n", len);
+               return -1;
+       }
+
+       if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
+               fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
+               return -1;
+       }
+
+       attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
+       parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
+
+       if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
+               fprintf(stderr, "Missing family id TLV\n");
+               return -1;
+       }
+
+       return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
+}
+
+int genl_resolve_family(struct rtnl_handle *grth, const char *family)
+{
+       GENL_REQUEST(req, 0, 1024)
+               = GENL_INITIALIZER(GENL_ID_CTRL, 0,
+                                  0, CTRL_CMD_GETFAMILY, NLM_F_REQUEST);
+
+       addattr_l(&req.n, 1024, CTRL_ATTR_FAMILY_NAME,
+                 family, strlen(family) + 1);
+
+       if (rtnl_talk(grth, &req.n, 0, 0, &req.n) < 0) {
+               fprintf(stderr, "Error talking to the kernel\n");
+               return -2;
+       }
+
+       return genl_parse_getfamily(&req.n);
+}
+