mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	add libnl-tiny as a small replacement for libnl with only genl support included
SVN-Revision: 15507
This commit is contained in:
		
							parent
							
								
									4e12c9d210
								
							
						
					
					
						commit
						938553bd69
					
				
							
								
								
									
										49
									
								
								package/libnl-tiny/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								package/libnl-tiny/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (C) 2006-2009 OpenWrt.org
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is free software, licensed under the GNU General Public License v2.
 | 
				
			||||||
 | 
					# See /LICENSE for more information.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(TOPDIR)/rules.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PKG_NAME:=libnl-tiny
 | 
				
			||||||
 | 
					PKG_VERSION:=0.1
 | 
				
			||||||
 | 
					PKG_RELEASE:=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(INCLUDE_DIR)/package.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Package/libnl-tiny
 | 
				
			||||||
 | 
					  SECTION:=libs
 | 
				
			||||||
 | 
					  CATEGORY:=Libraries
 | 
				
			||||||
 | 
					  TITLE:=netlink socket library
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Package/libnl-tiny/description
 | 
				
			||||||
 | 
					 This package contains a stripped down version of libnl
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Build/Prepare
 | 
				
			||||||
 | 
						mkdir -p $(PKG_BUILD_DIR)
 | 
				
			||||||
 | 
						$(CP) ./src/* $(PKG_BUILD_DIR)/
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Build/Compile
 | 
				
			||||||
 | 
						$(MAKE) -C $(PKG_BUILD_DIR) \
 | 
				
			||||||
 | 
							$(TARGET_CONFIGURE_OPTS) \
 | 
				
			||||||
 | 
							CFLAGS="$(TARGET_CFLAGS)" \
 | 
				
			||||||
 | 
							all
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Build/InstallDev
 | 
				
			||||||
 | 
						$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include/libnl-tiny
 | 
				
			||||||
 | 
						$(CP) $(PKG_BUILD_DIR)/include/* $(1)/usr/include/libnl-tiny
 | 
				
			||||||
 | 
						$(CP) $(PKG_BUILD_DIR)/libnl-tiny.so $(1)/usr/lib/
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Package/libnl-tiny/install
 | 
				
			||||||
 | 
						$(INSTALL_DIR) $(1)/usr/lib
 | 
				
			||||||
 | 
						$(CP) $(PKG_BUILD_DIR)/libnl-tiny.so $(1)/usr/lib/
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(eval $(call BuildPackage,libnl-tiny))
 | 
				
			||||||
							
								
								
									
										17
									
								
								package/libnl-tiny/src/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								package/libnl-tiny/src/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					CC=gcc
 | 
				
			||||||
 | 
					WFLAGS=-Wall
 | 
				
			||||||
 | 
					CFLAGS=-O2
 | 
				
			||||||
 | 
					INCLUDES=-Iinclude
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIBNAME=libnl-tiny.so
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: $(LIBNAME)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%.o: %.c
 | 
				
			||||||
 | 
						$(CC) $(WFLAGS) -c -o $@ $(INCLUDES) $(CFLAGS) $<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIBNL_OBJ=nl.o handlers.o msg.o attr.o cache.o cache_mngt.o object.o socket.o error.o
 | 
				
			||||||
 | 
					GENL_OBJ=genl.o genl_family.o genl_ctrl.o genl_mngt.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(LIBNAME): $(LIBNL_OBJ) $(GENL_OBJ)
 | 
				
			||||||
 | 
						$(CC) -shared -o $@ $^
 | 
				
			||||||
							
								
								
									
										668
									
								
								package/libnl-tiny/src/attr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										668
									
								
								package/libnl-tiny/src/attr.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,668 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/attr.c		Netlink Attributes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/addr.h>
 | 
				
			||||||
 | 
					#include <netlink/attr.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <linux/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 * @defgroup attr Attributes
 | 
				
			||||||
 | 
					 * Netlink Attributes Construction/Parsing Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \section attr_sec Netlink Attributes
 | 
				
			||||||
 | 
					 * Netlink attributes allow for data chunks of arbitary length to be
 | 
				
			||||||
 | 
					 * attached to a netlink message. Each attribute is encoded with a
 | 
				
			||||||
 | 
					 * type and length field, both 16 bits, stored in the attribute header
 | 
				
			||||||
 | 
					 * preceding the attribute data. The main advantage of using attributes
 | 
				
			||||||
 | 
					 * over packing everything into the family header is that the interface
 | 
				
			||||||
 | 
					 * stays extendable as new attributes can supersede old attributes while
 | 
				
			||||||
 | 
					 * remaining backwards compatible. Also attributes can be defined optional
 | 
				
			||||||
 | 
					 * thus avoiding the transmission of unnecessary empty data blocks.
 | 
				
			||||||
 | 
					 * Special nested attributes allow for more complex data structures to
 | 
				
			||||||
 | 
					 * be transmitted, e.g. trees, lists, etc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * While not required, netlink attributes typically follow the family
 | 
				
			||||||
 | 
					 * header of a netlink message and must be properly aligned to NLA_ALIGNTO:
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *   +----------------+- - -+---------------+- - -+------------+- - -+
 | 
				
			||||||
 | 
					 *   | Netlink Header | Pad | Family Header | Pad | Attributes | Pad |
 | 
				
			||||||
 | 
					 *   +----------------+- - -+---------------+- - -+------------+- - -+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The actual attributes are chained together each separately aligned to
 | 
				
			||||||
 | 
					 * NLA_ALIGNTO. The position of an attribute is defined based on the
 | 
				
			||||||
 | 
					 * length field of the preceding attributes:
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *   +-------------+- - -+-------------+- - -+------
 | 
				
			||||||
 | 
					 *   | Attribute 1 | Pad | Attribute 2 | Pad | ...
 | 
				
			||||||
 | 
					 *   +-------------+- - -+-------------+- - -+------
 | 
				
			||||||
 | 
					 *   nla_next(attr1)------^
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The attribute itself consists of the attribute header followed by
 | 
				
			||||||
 | 
					 * the actual payload also aligned to NLA_ALIGNTO. The function nla_data()
 | 
				
			||||||
 | 
					 * returns a pointer to the start of the payload while nla_len() returns
 | 
				
			||||||
 | 
					 * the length of the payload in bytes.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \b Note: Be aware, NLA_ALIGNTO equals to 4 bytes, therefore it is not
 | 
				
			||||||
 | 
					 * safe to dereference any 64 bit data types directly.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *    <----------- nla_total_size(payload) ----------->
 | 
				
			||||||
 | 
					 *    <-------- nla_attr_size(payload) --------->
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 *   | Attribute Header | Pad |     Payload      | Pad |
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 *   nla_data(nla)-------------^
 | 
				
			||||||
 | 
					 *                             <- nla_len(nla) ->
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @subsection attr_datatypes Attribute Data Types
 | 
				
			||||||
 | 
					 * A number of basic data types are supported to simplify access and
 | 
				
			||||||
 | 
					 * validation of netlink attributes. This data type information is
 | 
				
			||||||
 | 
					 * not encoded in the attribute, both the kernel and userspace part
 | 
				
			||||||
 | 
					 * are required to share this information on their own.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * One of the major advantages of these basic types is the automatic
 | 
				
			||||||
 | 
					 * validation of each attribute based on an attribute policy. The
 | 
				
			||||||
 | 
					 * validation covers most of the checks required to safely use
 | 
				
			||||||
 | 
					 * attributes and thus keeps the individual sanity check to a minimum.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Never access attribute payload without ensuring basic validation
 | 
				
			||||||
 | 
					 * first, attributes may:
 | 
				
			||||||
 | 
					 * - not be present even though required
 | 
				
			||||||
 | 
					 * - contain less actual payload than expected
 | 
				
			||||||
 | 
					 * - fake a attribute length which exceeds the end of the message
 | 
				
			||||||
 | 
					 * - contain unterminated character strings
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Policies are defined as array of the struct nla_policy. The array is
 | 
				
			||||||
 | 
					 * indexed with the attribute type, therefore the array must be sized
 | 
				
			||||||
 | 
					 * accordingly.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * static struct nla_policy my_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 * 	[ATTR_FOO] = { .type = ..., .minlen = ..., .maxlen = ... },
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * err = nla_validate(attrs, attrlen, ATTR_MAX, &my_policy);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Some basic validations are performed on every attribute, regardless of type.
 | 
				
			||||||
 | 
					 * - If the attribute type exceeds the maximum attribute type specified or
 | 
				
			||||||
 | 
					 *   the attribute type is lesser-or-equal than zero, the attribute will
 | 
				
			||||||
 | 
					 *   be silently ignored.
 | 
				
			||||||
 | 
					 * - If the payload length falls below the \a minlen value the attribute
 | 
				
			||||||
 | 
					 *   will be rejected.
 | 
				
			||||||
 | 
					 * - If \a maxlen is non-zero and the payload length exceeds the \a maxlen
 | 
				
			||||||
 | 
					 *   value the attribute will be rejected.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Unspecific Attribute (NLA_UNSPEC)
 | 
				
			||||||
 | 
					 * This is the standard type if no type is specified. It is used for
 | 
				
			||||||
 | 
					 * binary data of arbitary length. Typically this attribute carries
 | 
				
			||||||
 | 
					 * a binary structure or a stream of bytes.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // In this example, we will assume a binary structure requires to
 | 
				
			||||||
 | 
					 * // be transmitted. The definition of the structure will typically
 | 
				
			||||||
 | 
					 * // go into a header file available to both the kernel and userspace
 | 
				
			||||||
 | 
					 * // side.
 | 
				
			||||||
 | 
					 * //
 | 
				
			||||||
 | 
					 * // Note: Be careful when putting 64 bit data types into a structure.
 | 
				
			||||||
 | 
					 * // The attribute payload is only aligned to 4 bytes, dereferencing
 | 
				
			||||||
 | 
					 * // the member may fail.
 | 
				
			||||||
 | 
					 * struct my_struct {
 | 
				
			||||||
 | 
					 *     int a;
 | 
				
			||||||
 | 
					 *     int b;
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // The validation function will not enforce an exact length match to
 | 
				
			||||||
 | 
					 * // allow structures to grow as required. Note: While it is allowed
 | 
				
			||||||
 | 
					 * // to add members to the end of the structure, changing the order or
 | 
				
			||||||
 | 
					 * // inserting members in the middle of the structure will break your
 | 
				
			||||||
 | 
					 * // binary interface.
 | 
				
			||||||
 | 
					 * static struct nla_policy my_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 *     [ATTR_MY_STRICT] = { .type = NLA_UNSPEC,
 | 
				
			||||||
 | 
					 *                          .minlen = sizeof(struct my_struct) },
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // The binary structure is appened to the message using nla_put()
 | 
				
			||||||
 | 
					 * struct my_struct foo = { .a = 1, .b = 2 };
 | 
				
			||||||
 | 
					 * nla_put(msg, ATTR_MY_STRUCT, sizeof(foo), &foo);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // On the receiving side, a pointer to the structure pointing inside
 | 
				
			||||||
 | 
					 * // the message payload is returned by nla_get().
 | 
				
			||||||
 | 
					 * if (attrs[ATTR_MY_STRUCT])
 | 
				
			||||||
 | 
					 *     struct my_struct *foo = nla_get(attrs[ATTR_MY_STRUCT]);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Integers (NLA_U8, NLA_U16, NLA_U32, NLA_U64)
 | 
				
			||||||
 | 
					 * Integers come in different sizes from 8 bit to 64 bit. However, since the
 | 
				
			||||||
 | 
					 * payload length is aligned to 4 bytes, integers smaller than 32 bit are
 | 
				
			||||||
 | 
					 * only useful to enforce the maximum range of values.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * \b Note: There is no difference made between signed and unsigned integers.
 | 
				
			||||||
 | 
					 * The validation only enforces the minimal payload length required to store
 | 
				
			||||||
 | 
					 * an integer of specified type.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Even though possible, it does not make sense to specify .minlen or
 | 
				
			||||||
 | 
					 * // .maxlen for integer types. The data types implies the corresponding
 | 
				
			||||||
 | 
					 * // minimal payload length.
 | 
				
			||||||
 | 
					 * static struct nla_policy my_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 *     [ATTR_FOO] = { .type = NLA_U32 },
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Numeric values can be appended directly using the respective
 | 
				
			||||||
 | 
					 * // nla_put_uxxx() function
 | 
				
			||||||
 | 
					 * nla_put_u32(msg, ATTR_FOO, 123);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Same for the receiving side.
 | 
				
			||||||
 | 
					 * if (attrs[ATTR_FOO])
 | 
				
			||||||
 | 
					 *     uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Character string (NLA_STRING)
 | 
				
			||||||
 | 
					 * This data type represents a NUL terminated character string of variable
 | 
				
			||||||
 | 
					 * length. For binary data streams the type NLA_UNSPEC is recommended.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Enforce a NUL terminated character string of at most 4 characters
 | 
				
			||||||
 | 
					 * // including the NUL termination.
 | 
				
			||||||
 | 
					 * static struct nla_policy my_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 *     [ATTR_BAR] = { .type = NLA_STRING, maxlen = 4 },
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // nla_put_string() creates a string attribute of the necessary length
 | 
				
			||||||
 | 
					 * // and appends it to the message including the NUL termination.
 | 
				
			||||||
 | 
					 * nla_put_string(msg, ATTR_BAR, "some text");
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // It is safe to use the returned character string directly if the
 | 
				
			||||||
 | 
					 * // attribute has been validated as the validation enforces the proper
 | 
				
			||||||
 | 
					 * // termination of the string.
 | 
				
			||||||
 | 
					 * if (attrs[ATTR_BAR])
 | 
				
			||||||
 | 
					 *     char *text = nla_get_string(attrs[ATTR_BAR]);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Flag (NLA_FLAG)
 | 
				
			||||||
 | 
					 * This attribute type may be used to indicate the presence of a flag. The
 | 
				
			||||||
 | 
					 * attribute is only valid if the payload length is zero. The presence of
 | 
				
			||||||
 | 
					 * the attribute header indicates the presence of the flag.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // This attribute type is special as .minlen and .maxlen have no effect.
 | 
				
			||||||
 | 
					 * static struct nla_policy my_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 *     [ATTR_FLAG] = { .type = NLA_FLAG },
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // nla_put_flag() appends a zero sized attribute to the message.
 | 
				
			||||||
 | 
					 * nla_put_flag(msg, ATTR_FLAG);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // There is no need for a receival function, the presence is the value.
 | 
				
			||||||
 | 
					 * if (attrs[ATTR_FLAG])
 | 
				
			||||||
 | 
					 *     // flag is present
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Micro Seconds (NLA_MSECS)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Nested Attribute (NLA_NESTED)
 | 
				
			||||||
 | 
					 * Attributes can be nested and put into a container to create groups, lists
 | 
				
			||||||
 | 
					 * or to construct trees of attributes. Nested attributes are often used to
 | 
				
			||||||
 | 
					 * pass attributes to a subsystem where the top layer has no knowledge of the
 | 
				
			||||||
 | 
					 * configuration possibilities of each subsystem.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * \b Note: When validating the attributes using nlmsg_validate() or
 | 
				
			||||||
 | 
					 * nlmsg_parse() it will only affect the top level attributes. Each
 | 
				
			||||||
 | 
					 * level of nested attributes must be validated seperately using
 | 
				
			||||||
 | 
					 * nla_parse_nested() or nla_validate().
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // The minimal length policy may be used to enforce the presence of at
 | 
				
			||||||
 | 
					 * // least one attribute.
 | 
				
			||||||
 | 
					 * static struct nla_policy my_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 *     [ATTR_OPTS] = { .type = NLA_NESTED, minlen = NLA_HDRLEN },
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Nested attributes are constructed by enclosing the attributes
 | 
				
			||||||
 | 
					 * // to be nested with calls to nla_nest_start() respetively nla_nest_end().
 | 
				
			||||||
 | 
					 * struct nlattr *opts = nla_nest_start(msg, ATTR_OPTS);
 | 
				
			||||||
 | 
					 * nla_put_u32(msg, ATTR_FOO, 123);
 | 
				
			||||||
 | 
					 * nla_put_string(msg, ATTR_BAR, "some text");
 | 
				
			||||||
 | 
					 * nla_nest_end(msg, opts);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Various methods exist to parse nested attributes, the easiest being
 | 
				
			||||||
 | 
					 * // nla_parse_nested() which also allows validation in the same step.
 | 
				
			||||||
 | 
					 * if (attrs[ATTR_OPTS]) {
 | 
				
			||||||
 | 
					 *     struct nlattr *nested[ATTR_MAX+1];
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     nla_parse_nested(nested, ATTR_MAX, attrs[ATTR_OPTS], &policy);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     if (nested[ATTR_FOO])
 | 
				
			||||||
 | 
					 *         uint32_t foo = nla_get_u32(nested[ATTR_FOO]);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @subsection attr_exceptions Exception Based Attribute Construction
 | 
				
			||||||
 | 
					 * Often a large number of attributes are added to a message in a single
 | 
				
			||||||
 | 
					 * function. In order to simplify error handling, a second set of
 | 
				
			||||||
 | 
					 * construction functions exist which jump to a error label when they
 | 
				
			||||||
 | 
					 * fail instead of returning an error code. This second set consists
 | 
				
			||||||
 | 
					 * of macros which are named after their error code based counterpart
 | 
				
			||||||
 | 
					 * except that the name is written all uppercase.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All of the macros jump to the target \c nla_put_failure if they fail.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * void my_func(struct nl_msg *msg)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 *     NLA_PUT_U32(msg, ATTR_FOO, 10);
 | 
				
			||||||
 | 
					 *     NLA_PUT_STRING(msg, ATTR_BAR, "bar");
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     return 0;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * nla_put_failure:
 | 
				
			||||||
 | 
					 *     return -NLE_NOMEM;
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @subsection attr_examples Examples
 | 
				
			||||||
 | 
					 * @par Example 1.1 Constructing a netlink message with attributes.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 *     struct nl_msg *msg;
 | 
				
			||||||
 | 
					 *     struct nlattr *info, *vlan;
 | 
				
			||||||
 | 
					 *     struct ifinfomsg ifi = {
 | 
				
			||||||
 | 
					 *         .ifi_family = AF_INET,
 | 
				
			||||||
 | 
					 *         .ifi_index = ifindex,
 | 
				
			||||||
 | 
					 *     };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Allocate a new netlink message, type=RTM_SETLINK, flags=NLM_F_ECHO
 | 
				
			||||||
 | 
					 *     if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_ECHO)))
 | 
				
			||||||
 | 
					 *         return NULL;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Append the family specific header (struct ifinfomsg)
 | 
				
			||||||
 | 
					 *     if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
 | 
				
			||||||
 | 
					 *         goto nla_put_failure
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Append a 32 bit integer attribute to carry the MTU
 | 
				
			||||||
 | 
					 *     NLA_PUT_U32(msg, IFLA_MTU, mtu);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Append a unspecific attribute to carry the link layer address
 | 
				
			||||||
 | 
					 *     NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Append a container for nested attributes to carry link information
 | 
				
			||||||
 | 
					 *     if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
 | 
				
			||||||
 | 
					 *         goto nla_put_failure;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Put a string attribute into the container
 | 
				
			||||||
 | 
					 *     NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan");
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Append another container inside the open container to carry
 | 
				
			||||||
 | 
					 *     // vlan specific attributes
 | 
				
			||||||
 | 
					 *     if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA)))
 | 
				
			||||||
 | 
					 *         goto nla_put_failure;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // add vlan specific info attributes here...
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Finish nesting the vlan attributes and close the second container.
 | 
				
			||||||
 | 
					 *     nla_nest_end(msg, vlan);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Finish nesting the link info attribute and close the first container.
 | 
				
			||||||
 | 
					 *     nla_nest_end(msg, info);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     return msg;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // If any of the construction macros fails, we end up here.
 | 
				
			||||||
 | 
					 * nla_put_failure:
 | 
				
			||||||
 | 
					 *     nlmsg_free(msg);
 | 
				
			||||||
 | 
					 *     return NULL;
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Example 2.1 Parsing a netlink message with attributes.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * int parse_message(struct nl_msg *msg)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 *     // The policy defines two attributes: a 32 bit integer and a container
 | 
				
			||||||
 | 
					 *     // for nested attributes.
 | 
				
			||||||
 | 
					 *     struct nla_policy attr_policy[ATTR_MAX+1] = {
 | 
				
			||||||
 | 
					 *         [ATTR_FOO] = { .type = NLA_U32 },
 | 
				
			||||||
 | 
					 *         [ATTR_BAR] = { .type = NLA_NESTED },
 | 
				
			||||||
 | 
					 *     };
 | 
				
			||||||
 | 
					 *     struct nlattr *attrs[ATTR_MAX+1];
 | 
				
			||||||
 | 
					 *     int err;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // The nlmsg_parse() function will make sure that the message contains
 | 
				
			||||||
 | 
					 *     // enough payload to hold the header (struct my_hdr), validates any
 | 
				
			||||||
 | 
					 *     // attributes attached to the messages and stores a pointer to each
 | 
				
			||||||
 | 
					 *     // attribute in the attrs[] array accessable by attribute type.
 | 
				
			||||||
 | 
					 *     if ((err = nlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs,
 | 
				
			||||||
 | 
					 *                            ATTR_MAX, attr_policy)) < 0)
 | 
				
			||||||
 | 
					 *         goto errout;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     if (attrs[ATTR_FOO]) {
 | 
				
			||||||
 | 
					 *         // It is safe to directly access the attribute payload without
 | 
				
			||||||
 | 
					 *         // any further checks since nlmsg_parse() enforced the policy.
 | 
				
			||||||
 | 
					 *         uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
 | 
				
			||||||
 | 
					 *     }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     if (attrs[ATTR_BAR]) {
 | 
				
			||||||
 | 
					 *         struct nlattr *nested[NESTED_MAX+1];
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *         // Attributes nested in a container can be parsed the same way
 | 
				
			||||||
 | 
					 *         // as top level attributes.
 | 
				
			||||||
 | 
					 *         if ((err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR],
 | 
				
			||||||
 | 
					 *                                     nested_policy)) < 0)
 | 
				
			||||||
 | 
					 *             goto errout;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *         // Process nested attributes here.
 | 
				
			||||||
 | 
					 *     }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     err = 0;
 | 
				
			||||||
 | 
					 * errout:
 | 
				
			||||||
 | 
					 *     return err;
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Attribute Size Calculation
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Parsing Attributes
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if the attribute header and payload can be accessed safely.
 | 
				
			||||||
 | 
					 * @arg nla		Attribute of any kind.
 | 
				
			||||||
 | 
					 * @arg remaining	Number of bytes remaining in attribute stream.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Verifies that the header and payload do not exceed the number of
 | 
				
			||||||
 | 
					 * bytes left in the attribute stream. This function must be called
 | 
				
			||||||
 | 
					 * before access the attribute header or payload when iterating over
 | 
				
			||||||
 | 
					 * the attribute stream using nla_next().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return True if the attribute can be accessed safely, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nla_ok(const struct nlattr *nla, int remaining)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return remaining >= sizeof(*nla) &&
 | 
				
			||||||
 | 
						       nla->nla_len >= sizeof(*nla) &&
 | 
				
			||||||
 | 
						       nla->nla_len <= remaining;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return next attribute in a stream of attributes.
 | 
				
			||||||
 | 
					 * @arg nla		Attribute of any kind.
 | 
				
			||||||
 | 
					 * @arg remaining	Variable to count remaining bytes in stream.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Calculates the offset to the next attribute based on the attribute
 | 
				
			||||||
 | 
					 * given. The attribute provided is assumed to be accessible, the
 | 
				
			||||||
 | 
					 * caller is responsible to use nla_ok() beforehand. The offset (length
 | 
				
			||||||
 | 
					 * of specified attribute including padding) is then subtracted from
 | 
				
			||||||
 | 
					 * the remaining bytes variable and a pointer to the next attribute is
 | 
				
			||||||
 | 
					 * returned.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * nla_next() can be called as long as remainig is >0.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to next attribute.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int totlen = NLA_ALIGN(nla->nla_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*remaining -= totlen;
 | 
				
			||||||
 | 
						return (struct nlattr *) ((char *) nla + totlen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
 | 
				
			||||||
 | 
						[NLA_U8]	= sizeof(uint8_t),
 | 
				
			||||||
 | 
						[NLA_U16]	= sizeof(uint16_t),
 | 
				
			||||||
 | 
						[NLA_U32]	= sizeof(uint32_t),
 | 
				
			||||||
 | 
						[NLA_U64]	= sizeof(uint64_t),
 | 
				
			||||||
 | 
						[NLA_STRING]	= 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int validate_nla(struct nlattr *nla, int maxtype,
 | 
				
			||||||
 | 
								struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nla_policy *pt;
 | 
				
			||||||
 | 
						int minlen = 0, type = nla_type(nla);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (type <= 0 || type > maxtype)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pt = &policy[type];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pt->type > NLA_TYPE_MAX)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pt->minlen)
 | 
				
			||||||
 | 
							minlen = pt->minlen;
 | 
				
			||||||
 | 
						else if (pt->type != NLA_UNSPEC)
 | 
				
			||||||
 | 
							minlen = nla_attr_minlen[pt->type];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pt->type == NLA_FLAG && nla_len(nla) > 0)
 | 
				
			||||||
 | 
							return -NLE_RANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nla_len(nla) < minlen)
 | 
				
			||||||
 | 
							return -NLE_RANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pt->maxlen && nla_len(nla) > pt->maxlen)
 | 
				
			||||||
 | 
							return -NLE_RANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pt->type == NLA_STRING) {
 | 
				
			||||||
 | 
							char *data = nla_data(nla);
 | 
				
			||||||
 | 
							if (data[nla_len(nla) - 1] != '\0')
 | 
				
			||||||
 | 
								return -NLE_INVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Create attribute index based on a stream of attributes.
 | 
				
			||||||
 | 
					 * @arg tb		Index array to be filled (maxtype+1 elements).
 | 
				
			||||||
 | 
					 * @arg maxtype		Maximum attribute type expected and accepted.
 | 
				
			||||||
 | 
					 * @arg head		Head of attribute stream.
 | 
				
			||||||
 | 
					 * @arg len		Length of attribute stream.
 | 
				
			||||||
 | 
					 * @arg policy		Attribute validation policy.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Iterates over the stream of attributes and stores a pointer to each
 | 
				
			||||||
 | 
					 * attribute in the index array using the attribute type as index to
 | 
				
			||||||
 | 
					 * the array. Attribute with a type greater than the maximum type
 | 
				
			||||||
 | 
					 * specified will be silently ignored in order to maintain backwards
 | 
				
			||||||
 | 
					 * compatibility. If \a policy is not NULL, the attribute will be
 | 
				
			||||||
 | 
					 * validated using the specified policy.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_validate
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
 | 
				
			||||||
 | 
						      struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *nla;
 | 
				
			||||||
 | 
						int rem, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla_for_each_attr(nla, head, len, rem) {
 | 
				
			||||||
 | 
							int type = nla_type(nla);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type == 0) {
 | 
				
			||||||
 | 
								fprintf(stderr, "Illegal nla->nla_type == 0\n");
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type <= maxtype) {
 | 
				
			||||||
 | 
								if (policy) {
 | 
				
			||||||
 | 
									err = validate_nla(nla, maxtype, policy);
 | 
				
			||||||
 | 
									if (err < 0)
 | 
				
			||||||
 | 
										goto errout;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								tb[type] = nla;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rem > 0)
 | 
				
			||||||
 | 
							fprintf(stderr, "netlink: %d bytes leftover after parsing "
 | 
				
			||||||
 | 
							       "attributes.\n", rem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = 0;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Validate a stream of attributes.
 | 
				
			||||||
 | 
					 * @arg head		Head of attributes stream.
 | 
				
			||||||
 | 
					 * @arg len		Length of attributes stream.
 | 
				
			||||||
 | 
					 * @arg maxtype		Maximum attribute type expected and accepted.
 | 
				
			||||||
 | 
					 * @arg policy		Validation policy.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Iterates over the stream of attributes and validates each attribute
 | 
				
			||||||
 | 
					 * one by one using the specified policy. Attributes with a type greater
 | 
				
			||||||
 | 
					 * than the maximum type specified will be silently ignored in order to
 | 
				
			||||||
 | 
					 * maintain backwards compatibility.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See \ref attr_datatypes for more details on what kind of validation
 | 
				
			||||||
 | 
					 * checks are performed on each attribute data type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nla_validate(struct nlattr *head, int len, int maxtype,
 | 
				
			||||||
 | 
							 struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *nla;
 | 
				
			||||||
 | 
						int rem, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla_for_each_attr(nla, head, len, rem) {
 | 
				
			||||||
 | 
							err = validate_nla(nla, maxtype, policy);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = 0;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Find a single attribute in a stream of attributes.
 | 
				
			||||||
 | 
					 * @arg head		Head of attributes stream.
 | 
				
			||||||
 | 
					 * @arg len		Length of attributes stream.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type to look for.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Iterates over the stream of attributes and compares each type with
 | 
				
			||||||
 | 
					 * the type specified. Returns the first attribute which matches the
 | 
				
			||||||
 | 
					 * type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to attribute found or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *nla;
 | 
				
			||||||
 | 
						int rem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla_for_each_attr(nla, head, len, rem)
 | 
				
			||||||
 | 
							if (nla_type(nla) == attrtype)
 | 
				
			||||||
 | 
								return nla;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Unspecific Attribute
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reserve space for a attribute.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink Message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute Type.
 | 
				
			||||||
 | 
					 * @arg attrlen		Length of payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reserves room for a attribute in the specified netlink message and
 | 
				
			||||||
 | 
					 * fills in the attribute header (type, length). Returns NULL if there
 | 
				
			||||||
 | 
					 * is unsuficient space for the attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Any padding between payload and the start of the next attribute is
 | 
				
			||||||
 | 
					 * zeroed out.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to start of attribute or NULL on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *nla;
 | 
				
			||||||
 | 
						int tlen;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((tlen + msg->nm_nlh->nlmsg_len) > msg->nm_size)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
 | 
				
			||||||
 | 
						nla->nla_type = attrtype;
 | 
				
			||||||
 | 
						nla->nla_len = nla_attr_size(attrlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
 | 
				
			||||||
 | 
						msg->nm_nlh->nlmsg_len = tlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d "
 | 
				
			||||||
 | 
							  "nlmsg_len=%d\n", msg, attrlen,
 | 
				
			||||||
 | 
							  (void *) nla - nlmsg_data(msg->nm_nlh),
 | 
				
			||||||
 | 
							  attrtype, msg->nm_nlh->nlmsg_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nla;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add a unspecific attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg datalen		Length of data to be used as payload.
 | 
				
			||||||
 | 
					 * @arg data		Pointer to data to be used as attribute payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reserves room for a unspecific attribute and copies the provided data
 | 
				
			||||||
 | 
					 * into the message as payload of the attribute. Returns an error if there
 | 
				
			||||||
 | 
					 * is insufficient space for the attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_reserve
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *nla;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla = nla_reserve(msg, attrtype, datalen);
 | 
				
			||||||
 | 
						if (!nla)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(nla_data(nla), data, datalen);
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n",
 | 
				
			||||||
 | 
						       msg, datalen, (void *) nla - nlmsg_data(msg->nm_nlh), attrtype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										841
									
								
								package/libnl-tiny/src/cache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										841
									
								
								package/libnl-tiny/src/cache.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,841 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/cache.c		Caching Module
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup cache_mngt
 | 
				
			||||||
 | 
					 * @defgroup cache Cache
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *   Cache Management             |    | Type Specific Cache Operations
 | 
				
			||||||
 | 
					 *                                      
 | 
				
			||||||
 | 
					 *                                |    | +----------------+ +------------+
 | 
				
			||||||
 | 
					 *                                       | request update | | msg_parser |
 | 
				
			||||||
 | 
					 *                                |    | +----------------+ +------------+
 | 
				
			||||||
 | 
					 *                                     +- - - - -^- - - - - - - -^- -|- - - -
 | 
				
			||||||
 | 
					 *    nl_cache_update:            |              |               |   |
 | 
				
			||||||
 | 
					 *          1) --------- co_request_update ------+               |   |
 | 
				
			||||||
 | 
					 *                                |                              |   |
 | 
				
			||||||
 | 
					 *          2) destroy old cache     +----------- pp_cb ---------|---+
 | 
				
			||||||
 | 
					 *                                |  |                           |
 | 
				
			||||||
 | 
					 *          3) ---------- nl_recvmsgs ----------+   +- cb_valid -+
 | 
				
			||||||
 | 
					 *             +--------------+   |  |          |   |
 | 
				
			||||||
 | 
					 *             | nl_cache_add |<-----+   + - - -v- -|- - - - - - - - - - -
 | 
				
			||||||
 | 
					 *             +--------------+   |      | +-------------+
 | 
				
			||||||
 | 
					 *                                         | nl_recvmsgs |
 | 
				
			||||||
 | 
					 *                                |      | +-----|-^-----+
 | 
				
			||||||
 | 
					 *                                           +---v-|---+
 | 
				
			||||||
 | 
					 *                                |      |   | nl_recv |
 | 
				
			||||||
 | 
					 *                                           +---------+
 | 
				
			||||||
 | 
					 *                                |      |                 Core Netlink
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					#include <netlink/object.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Access Functions
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the number of items in the cache
 | 
				
			||||||
 | 
					 * @arg cache		cache handle
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_nitems(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cache->c_nitems;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the number of items matching a filter in the cache
 | 
				
			||||||
 | 
					 * @arg cache		Cache object.
 | 
				
			||||||
 | 
					 * @arg filter		Filter object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_nitems_filter(struct nl_cache *cache, struct nl_object *filter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object_ops *ops;
 | 
				
			||||||
 | 
						struct nl_object *obj;
 | 
				
			||||||
 | 
						int nitems = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops == NULL)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = cache->c_ops->co_obj_ops;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (filter && !nl_object_match_filter(obj, filter))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nitems++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nitems;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns \b true if the cache is empty.
 | 
				
			||||||
 | 
					 * @arg cache		Cache to check
 | 
				
			||||||
 | 
					 * @return \a true if the cache is empty, otherwise \b false is returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_is_empty(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_list_empty(&cache->c_items);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the operations set of the cache
 | 
				
			||||||
 | 
					 * @arg cache		cache handle
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache_ops *nl_cache_get_ops(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cache->c_ops;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the first element in the cache
 | 
				
			||||||
 | 
					 * @arg cache		cache handle
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_cache_get_first(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nl_list_empty(&cache->c_items))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_list_entry(cache->c_items.next,
 | 
				
			||||||
 | 
								     struct nl_object, ce_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the last element in the cache
 | 
				
			||||||
 | 
					 * @arg cache		cache handle
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_cache_get_last(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nl_list_empty(&cache->c_items))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_list_entry(cache->c_items.prev,
 | 
				
			||||||
 | 
								     struct nl_object, ce_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the next element in the cache
 | 
				
			||||||
 | 
					 * @arg obj		current object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_cache_get_next(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nl_list_at_tail(obj, &obj->ce_cache->c_items, ce_list))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return nl_list_entry(obj->ce_list.next,
 | 
				
			||||||
 | 
									     struct nl_object, ce_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the previous element in the cache
 | 
				
			||||||
 | 
					 * @arg obj		current object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_cache_get_prev(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nl_list_at_head(obj, &obj->ce_cache->c_items, ce_list))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return nl_list_entry(obj->ce_list.prev,
 | 
				
			||||||
 | 
									     struct nl_object, ce_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Cache Creation/Deletion
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate an empty cache
 | 
				
			||||||
 | 
					 * @arg ops		cache operations to base the cache on
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @return A newly allocated and initialized cache.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cache = calloc(1, sizeof(*cache));
 | 
				
			||||||
 | 
						if (!cache)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_init_list_head(&cache->c_items);
 | 
				
			||||||
 | 
						cache->c_ops = ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock,
 | 
				
			||||||
 | 
								    struct nl_cache **result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *cache;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (!(cache = nl_cache_alloc(ops)))
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
 | 
				
			||||||
 | 
							nl_cache_free(cache);
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*result = cache;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate an empty cache based on type name
 | 
				
			||||||
 | 
					 * @arg kind		Name of cache type
 | 
				
			||||||
 | 
					 * @return A newly allocated and initialized cache.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_alloc_name(const char *kind, struct nl_cache **result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
						struct nl_cache *cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = nl_cache_ops_lookup(kind);
 | 
				
			||||||
 | 
						if (!ops)
 | 
				
			||||||
 | 
							return -NLE_NOCACHE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(cache = nl_cache_alloc(ops)))
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*result = cache;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new cache containing a subset of a cache
 | 
				
			||||||
 | 
					 * @arg orig		Original cache to be based on
 | 
				
			||||||
 | 
					 * @arg filter		Filter defining the subset to be filled into new cache
 | 
				
			||||||
 | 
					 * @return A newly allocated cache or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache *nl_cache_subset(struct nl_cache *orig,
 | 
				
			||||||
 | 
									 struct nl_object *filter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *cache;
 | 
				
			||||||
 | 
						struct nl_object_ops *ops;
 | 
				
			||||||
 | 
						struct nl_object *obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!filter)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cache = nl_cache_alloc(orig->c_ops);
 | 
				
			||||||
 | 
						if (!cache)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = orig->c_ops->co_obj_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(obj, &orig->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (!nl_object_match_filter(obj, filter))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nl_cache_add(cache, obj);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Clear a cache.
 | 
				
			||||||
 | 
					 * @arg cache		cache to clear
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Removes all elements of a cache.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_clear(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *obj, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Clearing cache %p <%s>...\n", cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list)
 | 
				
			||||||
 | 
							nl_cache_remove(obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Free a cache.
 | 
				
			||||||
 | 
					 * @arg cache		Cache to free.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Removes all elements of a cache and frees all memory.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note Use this function if you are working with allocated caches.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_free(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!cache)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cache_clear(cache);
 | 
				
			||||||
 | 
						NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
						free(cache);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Cache Modifications
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						obj->ce_cache = cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_add_tail(&obj->ce_list, &cache->c_items);
 | 
				
			||||||
 | 
						cache->c_nitems++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Added %p to cache %p <%s>.\n",
 | 
				
			||||||
 | 
						       obj, cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add object to a cache.
 | 
				
			||||||
 | 
					 * @arg cache		Cache to add object to
 | 
				
			||||||
 | 
					 * @arg obj		Object to be added to the cache
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Adds the given object to the specified cache. The object is cloned
 | 
				
			||||||
 | 
					 * if it has been added to another cache already.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *new;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops->co_obj_ops != obj->ce_ops)
 | 
				
			||||||
 | 
							return -NLE_OBJ_MISMATCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!nl_list_empty(&obj->ce_list)) {
 | 
				
			||||||
 | 
							new = nl_object_clone(obj);
 | 
				
			||||||
 | 
							if (!new)
 | 
				
			||||||
 | 
								return -NLE_NOMEM;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							nl_object_get(obj);
 | 
				
			||||||
 | 
							new = obj;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return __cache_add(cache, new);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Move object from one cache to another
 | 
				
			||||||
 | 
					 * @arg cache		Cache to move object to.
 | 
				
			||||||
 | 
					 * @arg obj		Object subject to be moved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Removes the given object from its associated cache if needed
 | 
				
			||||||
 | 
					 * and adds it to the new cache.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_move(struct nl_cache *cache, struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (cache->c_ops->co_obj_ops != obj->ce_ops)
 | 
				
			||||||
 | 
							return -NLE_OBJ_MISMATCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(3, "Moving object %p to cache %p\n", obj, cache);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/* Acquire reference, if already in a cache this will be
 | 
				
			||||||
 | 
						 * reverted during removal */
 | 
				
			||||||
 | 
						nl_object_get(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!nl_list_empty(&obj->ce_list))
 | 
				
			||||||
 | 
							nl_cache_remove(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return __cache_add(cache, obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Removes an object from a cache.
 | 
				
			||||||
 | 
					 * @arg obj		Object to remove from its cache
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Removes the object \c obj from the cache it is assigned to, since
 | 
				
			||||||
 | 
					 * an object can only be assigned to one cache at a time, the cache
 | 
				
			||||||
 | 
					 * must ne be passed along with it.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_remove(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *cache = obj->ce_cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_del(&obj->ce_list);
 | 
				
			||||||
 | 
						obj->ce_cache = NULL;
 | 
				
			||||||
 | 
						nl_object_put(obj);
 | 
				
			||||||
 | 
						cache->c_nitems--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Deleted %p from cache %p <%s>.\n",
 | 
				
			||||||
 | 
						       obj, cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Search for an object in a cache
 | 
				
			||||||
 | 
					 * @arg cache		Cache to search in.
 | 
				
			||||||
 | 
					 * @arg needle		Object to look for.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Iterates over the cache and looks for an object with identical
 | 
				
			||||||
 | 
					 * identifiers as the needle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Reference to object or NULL if not found.
 | 
				
			||||||
 | 
					 * @note The returned object must be returned via nl_object_put().
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_cache_search(struct nl_cache *cache,
 | 
				
			||||||
 | 
									  struct nl_object *needle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (nl_object_identical(obj, needle)) {
 | 
				
			||||||
 | 
								nl_object_get(obj);
 | 
				
			||||||
 | 
								return obj;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Synchronization
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Request a full dump from the kernel to fill a cache
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg cache		Cache subjected to be filled.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Send a dumping request to the kernel causing it to dump all objects
 | 
				
			||||||
 | 
					 * related to the specified cache to the netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Use nl_cache_pickup() to read the objects from the socket and fill them
 | 
				
			||||||
 | 
					 * into a cache.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_request_full_dump(struct nl_sock *sk, struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NL_DBG(2, "Requesting dump from kernel for cache %p <%s>...\n",
 | 
				
			||||||
 | 
						          cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops->co_request_update == NULL)
 | 
				
			||||||
 | 
							return -NLE_OPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache->c_ops->co_request_update(cache, sk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					struct update_xdata {
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
						struct nl_parser_param *params;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int update_msg_parser(struct nl_msg *msg, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct update_xdata *x = arg;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache,
 | 
				
			||||||
 | 
							   struct nl_parser_param *param)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct nl_cb *cb;
 | 
				
			||||||
 | 
						struct update_xdata x = {
 | 
				
			||||||
 | 
							.ops = cache->c_ops,
 | 
				
			||||||
 | 
							.params = param,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Picking up answer for cache %p <%s>...\n",
 | 
				
			||||||
 | 
							  cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cb = nl_cb_clone(sk->s_cb);
 | 
				
			||||||
 | 
						if (cb == NULL)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, update_msg_parser, &x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = nl_recvmsgs(sk, cb);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							NL_DBG(2, "While picking up for %p <%s>, recvmsgs() returned " \
 | 
				
			||||||
 | 
							       "%d: %s", cache, nl_cache_name(cache),
 | 
				
			||||||
 | 
							       err, nl_geterror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cb_put(cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pickup_cb(struct nl_object *c, struct nl_parser_param *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_cache_add((struct nl_cache *) p->pp_arg, c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Pickup a netlink dump response and put it into a cache.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg cache		Cache to put items into.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Waits for netlink messages to arrive, parses them and puts them into
 | 
				
			||||||
 | 
					 * the specified cache.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_parser_param p = {
 | 
				
			||||||
 | 
							.pp_cb = pickup_cb,
 | 
				
			||||||
 | 
							.pp_arg = cache,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return __cache_pickup(sk, cache, &p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					static int cache_include(struct nl_cache *cache, struct nl_object *obj,
 | 
				
			||||||
 | 
								 struct nl_msgtype *type, change_func_t cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *old;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (type->mt_act) {
 | 
				
			||||||
 | 
						case NL_ACT_NEW:
 | 
				
			||||||
 | 
						case NL_ACT_DEL:
 | 
				
			||||||
 | 
							old = nl_cache_search(cache, obj);
 | 
				
			||||||
 | 
							if (old) {
 | 
				
			||||||
 | 
								nl_cache_remove(old);
 | 
				
			||||||
 | 
								if (type->mt_act == NL_ACT_DEL) {
 | 
				
			||||||
 | 
									if (cb)
 | 
				
			||||||
 | 
										cb(cache, old, NL_ACT_DEL);
 | 
				
			||||||
 | 
									nl_object_put(old);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type->mt_act == NL_ACT_NEW) {
 | 
				
			||||||
 | 
								nl_cache_move(cache, obj);
 | 
				
			||||||
 | 
								if (old == NULL && cb)
 | 
				
			||||||
 | 
									cb(cache, obj, NL_ACT_NEW);
 | 
				
			||||||
 | 
								else if (old) {
 | 
				
			||||||
 | 
									if (nl_object_diff(old, obj) && cb)
 | 
				
			||||||
 | 
										cb(cache, obj, NL_ACT_CHANGE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									nl_object_put(old);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							NL_DBG(2, "Unknown action associated to object %p\n", obj);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
 | 
				
			||||||
 | 
							     change_func_t change_cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops = cache->c_ops;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->co_obj_ops != obj->ce_ops)
 | 
				
			||||||
 | 
							return -NLE_OBJ_MISMATCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -NLE_MSGTYPE_NOSUPPORT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
 | 
				
			||||||
 | 
							    change_func_t change_cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *obj, *next;
 | 
				
			||||||
 | 
						struct nl_cache_assoc ca = {
 | 
				
			||||||
 | 
							.ca_cache = cache,
 | 
				
			||||||
 | 
							.ca_change = change_cb,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct nl_parser_param p = {
 | 
				
			||||||
 | 
							.pp_cb = resync_cb,
 | 
				
			||||||
 | 
							.pp_arg = &ca,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Mark all objects so we can see if some of them are obsolete */
 | 
				
			||||||
 | 
						nl_cache_mark_all(cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = nl_cache_request_full_dump(sk, cache);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = __cache_pickup(sk, cache, &p);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list)
 | 
				
			||||||
 | 
							if (nl_object_is_marked(obj))
 | 
				
			||||||
 | 
								nl_cache_remove(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Finished resyncing %p <%s>\n", cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = 0;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Parsing
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					int nl_cache_parse(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 | 
				
			||||||
 | 
							   struct nlmsghdr *nlh, struct nl_parser_param *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!nlmsg_valid_hdr(nlh, ops->co_hdrsize))
 | 
				
			||||||
 | 
							return -NLE_MSG_TOOSHORT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
 | 
				
			||||||
 | 
							if (ops->co_msgtypes[i].mt_id == nlh->nlmsg_type) {
 | 
				
			||||||
 | 
								err = ops->co_msg_parser(ops, who, nlh, params);
 | 
				
			||||||
 | 
								if (err != -NLE_OPNOTSUPP)
 | 
				
			||||||
 | 
									goto errout;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = -NLE_MSGTYPE_NOSUPPORT;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Parse a netlink message and add it to the cache.
 | 
				
			||||||
 | 
					 * @arg cache		cache to add element to
 | 
				
			||||||
 | 
					 * @arg msg		netlink message
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Parses a netlink message by calling the cache specific message parser
 | 
				
			||||||
 | 
					 * and adds the new element to the cache.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_parse_and_add(struct nl_cache *cache, struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_parser_param p = {
 | 
				
			||||||
 | 
							.pp_cb = pickup_cb,
 | 
				
			||||||
 | 
							.pp_arg = cache,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_cache_parse(cache->c_ops, NULL, nlmsg_hdr(msg), &p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * (Re)fill a cache with the contents in the kernel.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg cache		cache to update
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Clears the specified cache and fills it with the current state in
 | 
				
			||||||
 | 
					 * the kernel.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = nl_cache_request_full_dump(sk, cache);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "Upading cache %p <%s>, request sent, waiting for dump...\n",
 | 
				
			||||||
 | 
						       cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
						nl_cache_clear(cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_cache_pickup(sk, cache);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Utillities
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Mark all objects in a cache
 | 
				
			||||||
 | 
					 * @arg cache		Cache to mark all objects in
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_mark_all(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "Marking all objects in cache %p <%s>...\n",
 | 
				
			||||||
 | 
						          cache, nl_cache_name(cache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(obj, &cache->c_items, ce_list)
 | 
				
			||||||
 | 
							nl_object_mark(obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Dumping
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dump all elements of a cache.
 | 
				
			||||||
 | 
					 * @arg cache		cache to dump
 | 
				
			||||||
 | 
					 * @arg params		dumping parameters
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Dumps all elements of the \a cache to the file descriptor \a fd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_dump(struct nl_cache *cache, struct nl_dump_params *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_cache_dump_filter(cache, params, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dump all elements of a cache (filtered).
 | 
				
			||||||
 | 
					 * @arg cache		cache to dump
 | 
				
			||||||
 | 
					 * @arg params		dumping parameters (optional)
 | 
				
			||||||
 | 
					 * @arg filter		filter object
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Dumps all elements of the \a cache to the file descriptor \a fd
 | 
				
			||||||
 | 
					 * given they match the given filter \a filter.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_dump_filter(struct nl_cache *cache,
 | 
				
			||||||
 | 
								  struct nl_dump_params *params,
 | 
				
			||||||
 | 
								  struct nl_object *filter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int type = params ? params->dp_type : NL_DUMP_DETAILS;
 | 
				
			||||||
 | 
						struct nl_object_ops *ops;
 | 
				
			||||||
 | 
						struct nl_object *obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "Dumping cache %p <%s> filter %p\n",
 | 
				
			||||||
 | 
						       cache, nl_cache_name(cache), filter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (type > NL_DUMP_MAX || type < 0)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops == NULL)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = cache->c_ops->co_obj_ops;
 | 
				
			||||||
 | 
						if (!ops->oo_dump[type])
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (filter && !nl_object_match_filter(obj, filter))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NL_DBG(4, "Dumping object %p...\n", obj);
 | 
				
			||||||
 | 
							dump_from_ops(obj, params);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Iterators
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Call a callback on each element of the cache.
 | 
				
			||||||
 | 
					 * @arg cache		cache to iterate on
 | 
				
			||||||
 | 
					 * @arg cb		callback function
 | 
				
			||||||
 | 
					 * @arg arg		argument passed to callback function
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Calls a callback function \a cb on each element of the \a cache.
 | 
				
			||||||
 | 
					 * The argument \a arg is passed on the callback function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_foreach(struct nl_cache *cache,
 | 
				
			||||||
 | 
							      void (*cb)(struct nl_object *, void *), void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_cache_foreach_filter(cache, NULL, cb, arg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Call a callback on each element of the cache (filtered).
 | 
				
			||||||
 | 
					 * @arg cache		cache to iterate on
 | 
				
			||||||
 | 
					 * @arg filter		filter object
 | 
				
			||||||
 | 
					 * @arg cb		callback function
 | 
				
			||||||
 | 
					 * @arg arg		argument passed to callback function
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Calls a callback function \a cb on each element of the \a cache
 | 
				
			||||||
 | 
					 * that matches the \a filter. The argument \a arg is passed on
 | 
				
			||||||
 | 
					 * to the callback function.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter,
 | 
				
			||||||
 | 
								     void (*cb)(struct nl_object *, void *), void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *obj, *tmp;
 | 
				
			||||||
 | 
						struct nl_object_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops == NULL)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = cache->c_ops->co_obj_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (filter && !nl_object_match_filter(obj, filter))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cb(obj, arg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										249
									
								
								package/libnl-tiny/src/cache_mngt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								package/libnl-tiny/src/cache_mngt.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,249 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/cache_mngt.c	Cache Management
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup core
 | 
				
			||||||
 | 
					 * @defgroup cache_mngt Caching
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nl_cache_ops *cache_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Cache Operations Sets
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Lookup the set cache operations of a certain cache type
 | 
				
			||||||
 | 
					 * @arg name		name of the cache type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return The cache operations or NULL if no operations
 | 
				
			||||||
 | 
					 *         have been registered under the specified name.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (ops = cache_ops; ops; ops = ops->co_next)
 | 
				
			||||||
 | 
							if (!strcmp(ops->co_name, name))
 | 
				
			||||||
 | 
								return ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Associate a message type to a set of cache operations
 | 
				
			||||||
 | 
					 * @arg protocol		netlink protocol
 | 
				
			||||||
 | 
					 * @arg msgtype			netlink message type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Associates the specified netlink message type with
 | 
				
			||||||
 | 
					 * a registered set of cache operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return The cache operations or NULL if no association
 | 
				
			||||||
 | 
					 *         could be made.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (ops = cache_ops; ops; ops = ops->co_next) {
 | 
				
			||||||
 | 
							if (ops->co_protocol != protocol)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
 | 
				
			||||||
 | 
								if (ops->co_msgtypes[i].mt_id == msgtype)
 | 
				
			||||||
 | 
									return ops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Lookup message type cache association
 | 
				
			||||||
 | 
					 * @arg ops			cache operations
 | 
				
			||||||
 | 
					 * @arg msgtype			netlink message type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Searches for a matching message type association ing the specified
 | 
				
			||||||
 | 
					 * cache operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return A message type association or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
 | 
				
			||||||
 | 
							if (ops->co_msgtypes[i].mt_id == msgtype)
 | 
				
			||||||
 | 
								return &ops->co_msgtypes[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (ops = cache_ops; ops; ops = ops->co_next)
 | 
				
			||||||
 | 
							if (ops->co_obj_ops == obj_ops)
 | 
				
			||||||
 | 
								return ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Call a function for each registered cache operation
 | 
				
			||||||
 | 
					 * @arg cb		Callback function to be called
 | 
				
			||||||
 | 
					 * @arg arg		User specific argument.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (ops = cache_ops; ops; ops = ops->co_next)
 | 
				
			||||||
 | 
							cb(ops, arg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Register a set of cache operations
 | 
				
			||||||
 | 
					 * @arg ops		cache operations
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Called by users of caches to announce the avaibility of
 | 
				
			||||||
 | 
					 * a certain cache type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_mngt_register(struct nl_cache_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!ops->co_name || !ops->co_obj_ops)
 | 
				
			||||||
 | 
							return -NLE_INVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nl_cache_ops_lookup(ops->co_name))
 | 
				
			||||||
 | 
							return -NLE_EXIST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops->co_next = cache_ops;
 | 
				
			||||||
 | 
						cache_ops = ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Registered cache operations %s\n", ops->co_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unregister a set of cache operations
 | 
				
			||||||
 | 
					 * @arg ops		cache operations
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Called by users of caches to announce a set of
 | 
				
			||||||
 | 
					 * cache operations is no longer available. The
 | 
				
			||||||
 | 
					 * specified cache operations must have been registered
 | 
				
			||||||
 | 
					 * previously using nl_cache_mngt_register()
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *t, **tp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
 | 
				
			||||||
 | 
							if (t == ops)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!t)
 | 
				
			||||||
 | 
							return -NLE_NOCACHE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*tp = t->co_next;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Global Cache Provisioning/Requiring
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Provide a cache for global use
 | 
				
			||||||
 | 
					 * @arg cache		cache to provide
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Offers the specified cache to be used by other modules.
 | 
				
			||||||
 | 
					 * Only one cache per type may be shared at a time,
 | 
				
			||||||
 | 
					 * a previsouly provided caches will be overwritten.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_mngt_provide(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
 | 
				
			||||||
 | 
						if (!ops)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ops->co_major_cache = cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unprovide a cache for global use
 | 
				
			||||||
 | 
					 * @arg cache		cache to unprovide
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Cancels the offer to use a cache globally. The
 | 
				
			||||||
 | 
					 * cache will no longer be returned via lookups but
 | 
				
			||||||
 | 
					 * may still be in use.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_cache_mngt_unprovide(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
 | 
				
			||||||
 | 
						if (!ops)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
						else if (ops->co_major_cache == cache)
 | 
				
			||||||
 | 
							ops->co_major_cache = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Demand the use of a global cache
 | 
				
			||||||
 | 
					 * @arg name		name of the required object type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Trys to find a cache of the specified type for global
 | 
				
			||||||
 | 
					 * use.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return A cache provided by another subsystem of the
 | 
				
			||||||
 | 
					 *         specified type marked to be available.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache *nl_cache_mngt_require(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = nl_cache_ops_lookup(name);
 | 
				
			||||||
 | 
						if (!ops || !ops->co_major_cache) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Application BUG: Your application must "
 | 
				
			||||||
 | 
								"call nl_cache_mngt_provide() and\nprovide a valid "
 | 
				
			||||||
 | 
								"%s cache to be used for internal lookups.\nSee the "
 | 
				
			||||||
 | 
								" API documentation for more details.\n", name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return ops->co_major_cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										108
									
								
								package/libnl-tiny/src/error.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								package/libnl-tiny/src/error.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/error.c		Error Handling
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *errmsg[NLE_MAX+1] = {
 | 
				
			||||||
 | 
					[NLE_SUCCESS]		= "Success",
 | 
				
			||||||
 | 
					[NLE_FAILURE]		= "Unspecific failure",
 | 
				
			||||||
 | 
					[NLE_INTR]		= "Interrupted system call",
 | 
				
			||||||
 | 
					[NLE_BAD_SOCK]		= "Bad socket",
 | 
				
			||||||
 | 
					[NLE_AGAIN]		= "Try again",
 | 
				
			||||||
 | 
					[NLE_NOMEM]		= "Out of memory",
 | 
				
			||||||
 | 
					[NLE_EXIST]		= "Object exists",
 | 
				
			||||||
 | 
					[NLE_INVAL]		= "Invalid input data or parameter",
 | 
				
			||||||
 | 
					[NLE_RANGE]		= "Input data out of range",
 | 
				
			||||||
 | 
					[NLE_MSGSIZE]		= "Message size not sufficient",
 | 
				
			||||||
 | 
					[NLE_OPNOTSUPP]		= "Operation not supported",
 | 
				
			||||||
 | 
					[NLE_AF_NOSUPPORT]	= "Address family not supported",
 | 
				
			||||||
 | 
					[NLE_OBJ_NOTFOUND]	= "Object not found",
 | 
				
			||||||
 | 
					[NLE_NOATTR]		= "Attribute not available",
 | 
				
			||||||
 | 
					[NLE_MISSING_ATTR]	= "Missing attribute",
 | 
				
			||||||
 | 
					[NLE_AF_MISMATCH]	= "Address family mismatch",
 | 
				
			||||||
 | 
					[NLE_SEQ_MISMATCH]	= "Message sequence number mismatch",
 | 
				
			||||||
 | 
					[NLE_MSG_OVERFLOW]	= "Kernel reported message overflow",
 | 
				
			||||||
 | 
					[NLE_MSG_TRUNC]		= "Kernel reported truncated message",
 | 
				
			||||||
 | 
					[NLE_NOADDR]		= "Invalid address for specified address family",
 | 
				
			||||||
 | 
					[NLE_SRCRT_NOSUPPORT]	= "Source based routing not supported",
 | 
				
			||||||
 | 
					[NLE_MSG_TOOSHORT]	= "Netlink message is too short",
 | 
				
			||||||
 | 
					[NLE_MSGTYPE_NOSUPPORT]	= "Netlink message type is not supported",
 | 
				
			||||||
 | 
					[NLE_OBJ_MISMATCH]	= "Object type does not match cache",
 | 
				
			||||||
 | 
					[NLE_NOCACHE]		= "Unknown or invalid cache type",
 | 
				
			||||||
 | 
					[NLE_BUSY]		= "Object busy",
 | 
				
			||||||
 | 
					[NLE_PROTO_MISMATCH]	= "Protocol mismatch",
 | 
				
			||||||
 | 
					[NLE_NOACCESS]		= "No Access",
 | 
				
			||||||
 | 
					[NLE_PERM]		= "Operation not permitted",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return error message for an error code
 | 
				
			||||||
 | 
					 * @return error message
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const char *nl_geterror(int error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						error = abs(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (error > NLE_MAX)
 | 
				
			||||||
 | 
							error = NLE_FAILURE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return errmsg[error];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Print a libnl error message
 | 
				
			||||||
 | 
					 * @arg s		error message prefix
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Prints the error message of the call that failed last.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If s is not NULL and *s is not a null byte the argument
 | 
				
			||||||
 | 
					 * string is printed, followed by a colon and a blank. Then
 | 
				
			||||||
 | 
					 * the error message and a new-line.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_perror(int error, const char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (s && *s)
 | 
				
			||||||
 | 
							fprintf(stderr, "%s: %s\n", s, nl_geterror(error));
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							fprintf(stderr, "%s\n", nl_geterror(error));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int nl_syserr2nlerr(int error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						error = abs(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (error) {
 | 
				
			||||||
 | 
						case EBADF:		return NLE_BAD_SOCK;
 | 
				
			||||||
 | 
						case EADDRINUSE:	return NLE_EXIST;
 | 
				
			||||||
 | 
						case EEXIST:		return NLE_EXIST;
 | 
				
			||||||
 | 
						case EADDRNOTAVAIL:	return NLE_NOADDR;
 | 
				
			||||||
 | 
						case ENOENT:		return NLE_OBJ_NOTFOUND;
 | 
				
			||||||
 | 
						case EINTR:		return NLE_INTR;
 | 
				
			||||||
 | 
						case EAGAIN:		return NLE_AGAIN;
 | 
				
			||||||
 | 
						case ENOTSOCK:		return NLE_BAD_SOCK;
 | 
				
			||||||
 | 
						case ENOPROTOOPT:	return NLE_INVAL;
 | 
				
			||||||
 | 
						case EFAULT:		return NLE_INVAL;
 | 
				
			||||||
 | 
						case EACCES:		return NLE_NOACCESS;
 | 
				
			||||||
 | 
						case EINVAL:		return NLE_INVAL;
 | 
				
			||||||
 | 
						case ENOBUFS:		return NLE_NOMEM;
 | 
				
			||||||
 | 
						case ENOMEM:		return NLE_NOMEM;
 | 
				
			||||||
 | 
						case EAFNOSUPPORT:	return NLE_AF_NOSUPPORT;
 | 
				
			||||||
 | 
						case EPROTONOSUPPORT:	return NLE_PROTO_MISMATCH;
 | 
				
			||||||
 | 
						case EOPNOTSUPP:	return NLE_OPNOTSUPP;
 | 
				
			||||||
 | 
						case EPERM:		return NLE_PERM;
 | 
				
			||||||
 | 
						case EBUSY:		return NLE_BUSY;
 | 
				
			||||||
 | 
						default:		return NLE_FAILURE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										268
									
								
								package/libnl-tiny/src/genl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								package/libnl-tiny/src/genl.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,268 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/genl/genl.c		Generic Netlink
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @defgroup genl Generic Netlink
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Message Format
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *  <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
 | 
				
			||||||
 | 
					 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
 | 
				
			||||||
 | 
					 * |           Header           | Pad |       Payload       | Pad |
 | 
				
			||||||
 | 
					 * |      struct nlmsghdr       |     |                     |     |
 | 
				
			||||||
 | 
					 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *  <-------- GENL_HDRLEN -------> <--- hdrlen -->
 | 
				
			||||||
 | 
					 *                                 <------- genlmsg_len(ghdr) ------>
 | 
				
			||||||
 | 
					 * +------------------------+- - -+---------------+- - -+------------+
 | 
				
			||||||
 | 
					 * | Generic Netlink Header | Pad | Family Header | Pad | Attributes |
 | 
				
			||||||
 | 
					 * |    struct genlmsghdr   |     |               |     |            |
 | 
				
			||||||
 | 
					 * +------------------------+- - -+---------------+- - -+------------+
 | 
				
			||||||
 | 
					 * genlmsg_data(ghdr)--------------^                     ^
 | 
				
			||||||
 | 
					 * genlmsg_attrdata(ghdr, hdrlen)-------------------------
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Example
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * #include <netlink/netlink.h>
 | 
				
			||||||
 | 
					 * #include <netlink/genl/genl.h>
 | 
				
			||||||
 | 
					 * #include <netlink/genl/ctrl.h>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * struct nl_sock *sock;
 | 
				
			||||||
 | 
					 * struct nl_msg *msg;
 | 
				
			||||||
 | 
					 * int family;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Allocate a new netlink socket
 | 
				
			||||||
 | 
					 * sock = nl_socket_alloc();
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Connect to generic netlink socket on kernel side
 | 
				
			||||||
 | 
					 * genl_connect(sock);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Ask kernel to resolve family name to family id
 | 
				
			||||||
 | 
					 * family = genl_ctrl_resolve(sock, "generic_netlink_family_name");
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Construct a generic netlink by allocating a new message, fill in
 | 
				
			||||||
 | 
					 * // the header and append a simple integer attribute.
 | 
				
			||||||
 | 
					 * msg = nlmsg_alloc();
 | 
				
			||||||
 | 
					 * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO,
 | 
				
			||||||
 | 
					 *             CMD_FOO_GET, FOO_VERSION);
 | 
				
			||||||
 | 
					 * nla_put_u32(msg, ATTR_FOO, 123);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Send message over netlink socket
 | 
				
			||||||
 | 
					 * nl_send_auto_complete(sock, msg);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Free message
 | 
				
			||||||
 | 
					 * nlmsg_free(msg);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Prepare socket to receive the answer by specifying the callback
 | 
				
			||||||
 | 
					 * // function to be called for valid messages.
 | 
				
			||||||
 | 
					 * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Wait for the answer and receive it
 | 
				
			||||||
 | 
					 * nl_recvmsgs_default(sock);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * static int parse_cb(struct nl_msg *msg, void *arg)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 *     struct nlmsghdr *nlh = nlmsg_hdr(msg);
 | 
				
			||||||
 | 
					 *     struct nlattr *attrs[ATTR_MAX+1];
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     // Validate message and parse attributes
 | 
				
			||||||
 | 
					 *     genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     if (attrs[ATTR_FOO]) {
 | 
				
			||||||
 | 
					 *         uint32_t value = nla_get_u32(attrs[ATTR_FOO]);
 | 
				
			||||||
 | 
					 *         ...
 | 
				
			||||||
 | 
					 *     }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     return 0;
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-generic.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/genl.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Socket Creating
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genl_connect(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_connect(sk, NETLINK_GENERIC);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Sending
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Send trivial generic netlink message
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg family		Generic netlink family
 | 
				
			||||||
 | 
					 * @arg cmd		Command
 | 
				
			||||||
 | 
					 * @arg version		Version
 | 
				
			||||||
 | 
					 * @arg flags		Additional netlink message flags.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Fills out a routing netlink request message and sends it out
 | 
				
			||||||
 | 
					 * using nl_send_simple().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int genl_send_simple(struct nl_sock *sk, int family, int cmd,
 | 
				
			||||||
 | 
							     int version, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genlmsghdr hdr = {
 | 
				
			||||||
 | 
							.cmd = cmd,
 | 
				
			||||||
 | 
							.version = version,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Message Parsing
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genlmsghdr *ghdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ghdr = nlmsg_data(nlh);
 | 
				
			||||||
 | 
						if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
 | 
				
			||||||
 | 
							   struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genlmsghdr *ghdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!genlmsg_valid_hdr(nlh, hdrlen))
 | 
				
			||||||
 | 
							return -NLE_MSG_TOOSHORT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ghdr = nlmsg_data(nlh);
 | 
				
			||||||
 | 
						return nla_validate(genlmsg_attrdata(ghdr, hdrlen),
 | 
				
			||||||
 | 
								    genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
 | 
				
			||||||
 | 
							  int maxtype, struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genlmsghdr *ghdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!genlmsg_valid_hdr(nlh, hdrlen))
 | 
				
			||||||
 | 
							return -NLE_MSG_TOOSHORT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ghdr = nlmsg_data(nlh);
 | 
				
			||||||
 | 
						return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
 | 
				
			||||||
 | 
								 genlmsg_attrlen(ghdr, hdrlen), policy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get head of message payload
 | 
				
			||||||
 | 
					 * @arg gnlh	genetlink messsage header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void *genlmsg_data(const struct genlmsghdr *gnlh)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ((unsigned char *) gnlh + GENL_HDRLEN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get lenght of message payload
 | 
				
			||||||
 | 
					 * @arg gnlh	genetlink message header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int genlmsg_len(const struct genlmsghdr *gnlh)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
 | 
				
			||||||
 | 
												NLMSG_HDRLEN);
 | 
				
			||||||
 | 
						return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get head of attribute data
 | 
				
			||||||
 | 
					 * @arg gnlh	generic netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen	length of family specific header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get length of attribute data
 | 
				
			||||||
 | 
					 * @arg gnlh	generic netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen	length of family specific header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Message Building
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add generic netlink header to netlink message
 | 
				
			||||||
 | 
					 * @arg msg		netlink message
 | 
				
			||||||
 | 
					 * @arg pid		netlink process id or NL_AUTO_PID
 | 
				
			||||||
 | 
					 * @arg seq		sequence number of message or NL_AUTO_SEQ
 | 
				
			||||||
 | 
					 * @arg family		generic netlink family
 | 
				
			||||||
 | 
					 * @arg hdrlen		length of user specific header
 | 
				
			||||||
 | 
					 * @arg flags		message flags
 | 
				
			||||||
 | 
					 * @arg cmd		generic netlink command
 | 
				
			||||||
 | 
					 * @arg version		protocol version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns pointer to user specific header.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
 | 
				
			||||||
 | 
							  int hdrlen, int flags, uint8_t cmd, uint8_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlmsghdr *nlh;
 | 
				
			||||||
 | 
						struct genlmsghdr hdr = {
 | 
				
			||||||
 | 
							.cmd = cmd,
 | 
				
			||||||
 | 
							.version = version,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags);
 | 
				
			||||||
 | 
						if (nlh == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr));
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n",
 | 
				
			||||||
 | 
						       msg, cmd, version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nlmsg_data(nlh) + GENL_HDRLEN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										302
									
								
								package/libnl-tiny/src/genl_ctrl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								package/libnl-tiny/src/genl_ctrl.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,302 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/genl/ctrl.c		Generic Netlink Controller
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup genl_mngt
 | 
				
			||||||
 | 
					 * @defgroup ctrl Controller
 | 
				
			||||||
 | 
					 * @brief
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-generic.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/genl.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/family.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/mngt.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/ctrl.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					#define CTRL_VERSION		0x0001
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nl_cache_ops genl_ctrl_ops;
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
 | 
				
			||||||
 | 
									CTRL_VERSION, NLM_F_DUMP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
 | 
				
			||||||
 | 
						[CTRL_ATTR_FAMILY_ID]	= { .type = NLA_U16 },
 | 
				
			||||||
 | 
						[CTRL_ATTR_FAMILY_NAME]	= { .type = NLA_STRING,
 | 
				
			||||||
 | 
									    .maxlen = GENL_NAMSIZ },
 | 
				
			||||||
 | 
						[CTRL_ATTR_VERSION]	= { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[CTRL_ATTR_HDRSIZE]	= { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[CTRL_ATTR_MAXATTR]	= { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[CTRL_ATTR_OPS]		= { .type = NLA_NESTED },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
 | 
				
			||||||
 | 
						[CTRL_ATTR_OP_ID]	= { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[CTRL_ATTR_OP_FLAGS]	= { .type = NLA_U32 },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd,
 | 
				
			||||||
 | 
								   struct genl_info *info, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *family;
 | 
				
			||||||
 | 
						struct nl_parser_param *pp = arg;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						family = genl_family_alloc();
 | 
				
			||||||
 | 
						if (family == NULL) {
 | 
				
			||||||
 | 
							err = -NLE_NOMEM;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
 | 
				
			||||||
 | 
							err = -NLE_MISSING_ATTR;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
 | 
				
			||||||
 | 
							err = -NLE_MISSING_ATTR;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						family->ce_msgtype = info->nlh->nlmsg_type;
 | 
				
			||||||
 | 
						genl_family_set_id(family,
 | 
				
			||||||
 | 
								   nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]));
 | 
				
			||||||
 | 
						genl_family_set_name(family,
 | 
				
			||||||
 | 
							     nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[CTRL_ATTR_VERSION]) {
 | 
				
			||||||
 | 
							uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
 | 
				
			||||||
 | 
							genl_family_set_version(family, version);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[CTRL_ATTR_HDRSIZE]) {
 | 
				
			||||||
 | 
							uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
 | 
				
			||||||
 | 
							genl_family_set_hdrsize(family, hdrsize);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[CTRL_ATTR_MAXATTR]) {
 | 
				
			||||||
 | 
							uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
 | 
				
			||||||
 | 
							genl_family_set_maxattr(family, maxattr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[CTRL_ATTR_OPS]) {
 | 
				
			||||||
 | 
							struct nlattr *nla, *nla_ops;
 | 
				
			||||||
 | 
							int remaining;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nla_ops = info->attrs[CTRL_ATTR_OPS];
 | 
				
			||||||
 | 
							nla_for_each_nested(nla, nla_ops, remaining) {
 | 
				
			||||||
 | 
								struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
 | 
				
			||||||
 | 
								int flags = 0, id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla,
 | 
				
			||||||
 | 
										       family_op_policy);
 | 
				
			||||||
 | 
								if (err < 0)
 | 
				
			||||||
 | 
									goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (tb[CTRL_ATTR_OP_ID] == NULL) {
 | 
				
			||||||
 | 
									err = -NLE_MISSING_ATTR;
 | 
				
			||||||
 | 
									goto errout;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								id = nla_get_u32(tb[CTRL_ATTR_OP_ID]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (tb[CTRL_ATTR_OP_FLAGS])
 | 
				
			||||||
 | 
									flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = genl_family_add_op(family, id, flags);
 | 
				
			||||||
 | 
								if (err < 0)
 | 
				
			||||||
 | 
									goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = pp->pp_cb((struct nl_object *) family, pp);
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						genl_family_put(family);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Cache Management
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_cache_alloc_and_fill(&genl_ctrl_ops, sock, result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Look up generic netlink family by id in the provided cache.
 | 
				
			||||||
 | 
					 * @arg cache		Generic netlink family cache.
 | 
				
			||||||
 | 
					 * @arg id		Family identifier.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Searches through the cache looking for a registered family
 | 
				
			||||||
 | 
					 * matching the specified identifier. The caller will own a
 | 
				
			||||||
 | 
					 * reference on the returned object which needs to be given
 | 
				
			||||||
 | 
					 * back after usage using genl_family_put().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Generic netlink family object or NULL if no match was found.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *fam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops != &genl_ctrl_ops)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (fam->gf_id == id) {
 | 
				
			||||||
 | 
								nl_object_get((struct nl_object *) fam);
 | 
				
			||||||
 | 
								return fam;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Resolver
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Look up generic netlink family by family name in the provided cache.
 | 
				
			||||||
 | 
					 * @arg cache		Generic netlink family cache.
 | 
				
			||||||
 | 
					 * @arg name		Family name.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Searches through the cache looking for a registered family
 | 
				
			||||||
 | 
					 * matching the specified name. The caller will own a reference
 | 
				
			||||||
 | 
					 * on the returned object which needs to be given back after
 | 
				
			||||||
 | 
					 * usage using genl_family_put().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Generic netlink family object or NULL if no match was found.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
 | 
				
			||||||
 | 
										    const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *fam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cache->c_ops != &genl_ctrl_ops)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
 | 
				
			||||||
 | 
							if (!strcmp(name, fam->gf_name)) {
 | 
				
			||||||
 | 
								nl_object_get((struct nl_object *) fam);
 | 
				
			||||||
 | 
								return fam;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Resolve generic netlink family name to its identifier
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg name		Name of generic netlink family
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Resolves the generic netlink family name to its identifer and returns
 | 
				
			||||||
 | 
					 * it.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return A positive identifier or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int genl_ctrl_resolve(struct nl_sock *sk, const char *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, name);
 | 
				
			||||||
 | 
						if (family == NULL) {
 | 
				
			||||||
 | 
							err = -NLE_OBJ_NOTFOUND;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = genl_family_get_id(family);
 | 
				
			||||||
 | 
						genl_family_put(family);
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						nl_cache_free(cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct genl_cmd genl_cmds[] = {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.c_id		= CTRL_CMD_NEWFAMILY,
 | 
				
			||||||
 | 
							.c_name		= "NEWFAMILY" ,
 | 
				
			||||||
 | 
							.c_maxattr	= CTRL_ATTR_MAX,
 | 
				
			||||||
 | 
							.c_attr_policy	= ctrl_policy,
 | 
				
			||||||
 | 
							.c_msg_parser	= ctrl_msg_parser,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.c_id		= CTRL_CMD_DELFAMILY,
 | 
				
			||||||
 | 
							.c_name		= "DELFAMILY" ,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.c_id		= CTRL_CMD_GETFAMILY,
 | 
				
			||||||
 | 
							.c_name		= "GETFAMILY" ,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.c_id		= CTRL_CMD_NEWOPS,
 | 
				
			||||||
 | 
							.c_name		= "NEWOPS" ,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.c_id		= CTRL_CMD_DELOPS,
 | 
				
			||||||
 | 
							.c_name		= "DELOPS" ,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct genl_ops genl_ops = {
 | 
				
			||||||
 | 
						.o_cmds			= genl_cmds,
 | 
				
			||||||
 | 
						.o_ncmds		= ARRAY_SIZE(genl_cmds),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					extern struct nl_object_ops genl_family_ops;
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nl_cache_ops genl_ctrl_ops = {
 | 
				
			||||||
 | 
						.co_name		= "genl/family",
 | 
				
			||||||
 | 
						.co_hdrsize		= GENL_HDRSIZE(0),
 | 
				
			||||||
 | 
						.co_msgtypes		= GENL_FAMILY(GENL_ID_CTRL, "nlctrl"),
 | 
				
			||||||
 | 
						.co_genl		= &genl_ops,
 | 
				
			||||||
 | 
						.co_protocol		= NETLINK_GENERIC,
 | 
				
			||||||
 | 
						.co_request_update      = ctrl_request_update,
 | 
				
			||||||
 | 
						.co_obj_ops		= &genl_family_ops,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __init ctrl_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						genl_register(&genl_ctrl_ops);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __exit ctrl_exit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						genl_unregister(&genl_ctrl_ops);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										136
									
								
								package/libnl-tiny/src/genl_family.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								package/libnl-tiny/src/genl_family.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,136 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/genl/family.c		Generic Netlink Family
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup genl
 | 
				
			||||||
 | 
					 * @defgroup genl_family Generic Netlink Family
 | 
				
			||||||
 | 
					 * @brief
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-generic.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/genl.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/family.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_object_ops genl_family_ops;
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void family_constructor(struct nl_object *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *family = (struct genl_family *) c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_init_list_head(&family->gf_ops);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void family_free_data(struct nl_object *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *family = (struct genl_family *) c;
 | 
				
			||||||
 | 
						struct genl_family_op *ops, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (family == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
 | 
				
			||||||
 | 
							nl_list_del(&ops->o_list);
 | 
				
			||||||
 | 
							free(ops);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
 | 
				
			||||||
 | 
							err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int family_compare(struct nl_object *_a, struct nl_object *_b,
 | 
				
			||||||
 | 
								  uint32_t attrs, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *a = (struct genl_family *) _a;
 | 
				
			||||||
 | 
						struct genl_family *b = (struct genl_family *) _b;
 | 
				
			||||||
 | 
						int diff = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						diff |= FAM_DIFF(ID,		a->gf_id != b->gf_id);
 | 
				
			||||||
 | 
						diff |= FAM_DIFF(VERSION,	a->gf_version != b->gf_version);
 | 
				
			||||||
 | 
						diff |= FAM_DIFF(HDRSIZE,	a->gf_hdrsize != b->gf_hdrsize);
 | 
				
			||||||
 | 
						diff |= FAM_DIFF(MAXATTR,	a->gf_maxattr != b->gf_maxattr);
 | 
				
			||||||
 | 
						diff |= FAM_DIFF(NAME,		strcmp(a->gf_name, b->gf_name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef FAM_DIFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return diff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Family Object
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct genl_family *genl_family_alloc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (struct genl_family *) nl_object_alloc(&genl_family_ops);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void genl_family_put(struct genl_family *family)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_object_put((struct nl_object *) family);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genl_family_add_op(struct genl_family *family, int id, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family_op *op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						op = calloc(1, sizeof(*op));
 | 
				
			||||||
 | 
						if (op == NULL)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						op->o_id = id;
 | 
				
			||||||
 | 
						op->o_flags = flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_add_tail(&op->o_list, &family->gf_ops);
 | 
				
			||||||
 | 
						family->ce_mask |= FAMILY_ATTR_OPS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					struct nl_object_ops genl_family_ops = {
 | 
				
			||||||
 | 
						.oo_name		= "genl/family",
 | 
				
			||||||
 | 
						.oo_size		= sizeof(struct genl_family),
 | 
				
			||||||
 | 
						.oo_constructor		= family_constructor,
 | 
				
			||||||
 | 
						.oo_free_data		= family_free_data,
 | 
				
			||||||
 | 
						.oo_clone		= family_clone,
 | 
				
			||||||
 | 
						.oo_compare		= family_compare,
 | 
				
			||||||
 | 
						.oo_id_attrs		= FAMILY_ATTR_ID,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										273
									
								
								package/libnl-tiny/src/genl_mngt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								package/libnl-tiny/src/genl_mngt.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,273 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/genl/mngt.c		Generic Netlink Management
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup genl
 | 
				
			||||||
 | 
					 * @defgroup genl_mngt Management
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 1) Registering a generic netlink module
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * #include <netlink/genl/mngt.h>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // First step is to define all the commands being used in
 | 
				
			||||||
 | 
					 * // particular generic netlink family. The ID and name are
 | 
				
			||||||
 | 
					 * // mandatory to be filled out. A callback function and
 | 
				
			||||||
 | 
					 * // most the attribute policy that comes with it must be
 | 
				
			||||||
 | 
					 * // defined for commands expected to be issued towards
 | 
				
			||||||
 | 
					 * // userspace.
 | 
				
			||||||
 | 
					 * static struct genl_cmd foo_cmds[] = {
 | 
				
			||||||
 | 
					 * 	{
 | 
				
			||||||
 | 
					 * 		.c_id		= FOO_CMD_NEW,
 | 
				
			||||||
 | 
					 * 		.c_name		= "NEWFOO" ,
 | 
				
			||||||
 | 
					 * 		.c_maxattr	= FOO_ATTR_MAX,
 | 
				
			||||||
 | 
					 * 		.c_attr_policy	= foo_policy,
 | 
				
			||||||
 | 
					 * 		.c_msg_parser	= foo_msg_parser,
 | 
				
			||||||
 | 
					 * 	},
 | 
				
			||||||
 | 
					 * 	{
 | 
				
			||||||
 | 
					 * 		.c_id		= FOO_CMD_DEL,
 | 
				
			||||||
 | 
					 * 		.c_name		= "DELFOO" ,
 | 
				
			||||||
 | 
					 * 	},
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // The list of commands must then be integrated into a
 | 
				
			||||||
 | 
					 * // struct genl_ops serving as handle for this particular
 | 
				
			||||||
 | 
					 * // family.
 | 
				
			||||||
 | 
					 * static struct genl_ops my_genl_ops = {
 | 
				
			||||||
 | 
					 * 	.o_cmds			= foo_cmds,
 | 
				
			||||||
 | 
					 * 	.o_ncmds		= ARRAY_SIZE(foo_cmds),
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Using the above struct genl_ops an arbitary number of
 | 
				
			||||||
 | 
					 * // cache handles can be associated to it.
 | 
				
			||||||
 | 
					 * //
 | 
				
			||||||
 | 
					 * // The macro GENL_HDRSIZE() must be used to specify the
 | 
				
			||||||
 | 
					 * // length of the header to automatically take headers on
 | 
				
			||||||
 | 
					 * // generic layers into account.
 | 
				
			||||||
 | 
					 * //
 | 
				
			||||||
 | 
					 * // The macro GENL_FAMILY() is used to represent the generic
 | 
				
			||||||
 | 
					 * // netlink family id.
 | 
				
			||||||
 | 
					 * static struct nl_cache_ops genl_foo_ops = {
 | 
				
			||||||
 | 
					 * 	.co_name		= "genl/foo",
 | 
				
			||||||
 | 
					 * 	.co_hdrsize		= GENL_HDRSIZE(sizeof(struct my_hdr)),
 | 
				
			||||||
 | 
					 * 	.co_msgtypes		= GENL_FAMILY(GENL_ID_GENERATE, "foo"),
 | 
				
			||||||
 | 
					 * 	.co_genl		= &my_genl_ops,
 | 
				
			||||||
 | 
					 * 	.co_protocol		= NETLINK_GENERIC,
 | 
				
			||||||
 | 
					 * 	.co_request_update      = foo_request_update,
 | 
				
			||||||
 | 
					 * 	.co_obj_ops		= &genl_foo_ops,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Finally each cache handle for a generic netlink family
 | 
				
			||||||
 | 
					 * // must be registered using genl_register().
 | 
				
			||||||
 | 
					 * static void __init foo_init(void)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	genl_register(&genl_foo_ops);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // ... respectively unregsted again.
 | 
				
			||||||
 | 
					 * static void __exit foo_exit(void)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	genl_unregister(&genl_foo_ops);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-generic.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/genl.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/mngt.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/family.h>
 | 
				
			||||||
 | 
					#include <netlink/genl/ctrl.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static NL_LIST_HEAD(genl_ops_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 | 
				
			||||||
 | 
								   struct nlmsghdr *nlh, struct nl_parser_param *pp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, err;
 | 
				
			||||||
 | 
						struct genlmsghdr *ghdr;
 | 
				
			||||||
 | 
						struct genl_cmd *cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ghdr = nlmsg_data(nlh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->co_genl == NULL)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ops->co_genl->o_ncmds; i++) {
 | 
				
			||||||
 | 
							cmd = &ops->co_genl->o_cmds[i];
 | 
				
			||||||
 | 
							if (cmd->c_id == ghdr->cmd)
 | 
				
			||||||
 | 
								goto found;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = -NLE_MSGTYPE_NOSUPPORT;
 | 
				
			||||||
 | 
						goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					found:
 | 
				
			||||||
 | 
						if (cmd->c_msg_parser == NULL)
 | 
				
			||||||
 | 
							err = -NLE_OPNOTSUPP;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							struct nlattr *tb[cmd->c_maxattr + 1];
 | 
				
			||||||
 | 
							struct genl_info info = {
 | 
				
			||||||
 | 
								.who = who,
 | 
				
			||||||
 | 
								.nlh = nlh,
 | 
				
			||||||
 | 
								.genlhdr = ghdr,
 | 
				
			||||||
 | 
								.userhdr = genlmsg_data(ghdr),
 | 
				
			||||||
 | 
								.attrs = tb,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = nlmsg_parse(nlh, ops->co_hdrsize, tb, cmd->c_maxattr,
 | 
				
			||||||
 | 
									  cmd->c_attr_policy);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = cmd->c_msg_parser(ops, cmd, &info, pp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *genl_op2name(int family, int op, char *buf, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_ops *ops;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
 | 
				
			||||||
 | 
							if (ops->o_family == family) {
 | 
				
			||||||
 | 
								for (i = 0; i < ops->o_ncmds; i++) {
 | 
				
			||||||
 | 
									struct genl_cmd *cmd;
 | 
				
			||||||
 | 
									cmd = &ops->o_cmds[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (cmd->c_id == op) {
 | 
				
			||||||
 | 
										strncpy(buf, cmd->c_name, len - 1);
 | 
				
			||||||
 | 
										return buf;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strncpy(buf, "unknown", len - 1);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Register/Unregister
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Register generic netlink operations
 | 
				
			||||||
 | 
					 * @arg ops		cache operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int genl_register(struct nl_cache_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->co_protocol != NETLINK_GENERIC) {
 | 
				
			||||||
 | 
							err = -NLE_PROTO_MISMATCH;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->co_hdrsize < GENL_HDRSIZE(0)) {
 | 
				
			||||||
 | 
							err = -NLE_INVAL;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->co_genl == NULL) {
 | 
				
			||||||
 | 
							err = -NLE_INVAL;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops->co_genl->o_cache_ops = ops;
 | 
				
			||||||
 | 
						ops->co_genl->o_name = ops->co_msgtypes[0].mt_name;
 | 
				
			||||||
 | 
						ops->co_genl->o_family = ops->co_msgtypes[0].mt_id;
 | 
				
			||||||
 | 
						ops->co_msg_parser = genl_msg_parser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* FIXME: check for dup */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_add_tail(&ops->co_genl->o_list, &genl_ops_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = nl_cache_mngt_register(ops);
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unregister generic netlink operations
 | 
				
			||||||
 | 
					 * @arg ops		cache operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void genl_unregister(struct nl_cache_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_cache_mngt_unregister(ops);
 | 
				
			||||||
 | 
						nl_list_del(&ops->co_genl->o_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Resolving ID/Name
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct genl_family *family;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						family = genl_ctrl_search_by_name(ctrl, ops->o_name);
 | 
				
			||||||
 | 
						if (family != NULL) {
 | 
				
			||||||
 | 
							ops->o_id = genl_family_get_id(family);
 | 
				
			||||||
 | 
							genl_family_put(family);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -NLE_OBJ_NOTFOUND;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *ctrl;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = __genl_ops_resolve(ctrl, ops);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cache_free(ctrl);
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int genl_mngt_resolve(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *ctrl;
 | 
				
			||||||
 | 
						struct genl_ops *ops;
 | 
				
			||||||
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
 | 
				
			||||||
 | 
							err = __genl_ops_resolve(ctrl, ops);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cache_free(ctrl);
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										162
									
								
								package/libnl-tiny/src/handlers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								package/libnl-tiny/src/handlers.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/handlers.c	default netlink message handlers
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup core
 | 
				
			||||||
 | 
					 * @defgroup cb Callbacks/Customization
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @details
 | 
				
			||||||
 | 
					 * @par 1) Setting up a callback set
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Allocate a callback set and initialize it to the verbose default set
 | 
				
			||||||
 | 
					 * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Modify the set to call my_func() for all valid messages
 | 
				
			||||||
 | 
					 * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Set the error message handler to the verbose default implementation
 | 
				
			||||||
 | 
					 * // and direct it to print all errors to the given file descriptor.
 | 
				
			||||||
 | 
					 * FILE *file = fopen(...);
 | 
				
			||||||
 | 
					 * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <netlink/handlers.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Callback Handle Management
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new callback handle
 | 
				
			||||||
 | 
					 * @arg kind		callback kind to be used for initialization
 | 
				
			||||||
 | 
					 * @return Newly allocated callback handle or NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						struct nl_cb *cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (kind < 0 || kind > NL_CB_KIND_MAX)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cb = calloc(1, sizeof(*cb));
 | 
				
			||||||
 | 
						if (!cb)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cb->cb_refcnt = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i <= NL_CB_TYPE_MAX; i++)
 | 
				
			||||||
 | 
							nl_cb_set(cb, i, kind, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cb_err(cb, kind, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Clone an existing callback handle
 | 
				
			||||||
 | 
					 * @arg orig		original callback handle
 | 
				
			||||||
 | 
					 * @return Newly allocated callback handle being a duplicate of
 | 
				
			||||||
 | 
					 *         orig or NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cb *nl_cb_clone(struct nl_cb *orig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cb *cb;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						cb = nl_cb_alloc(NL_CB_DEFAULT);
 | 
				
			||||||
 | 
						if (!cb)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(cb, orig, sizeof(*orig));
 | 
				
			||||||
 | 
						cb->cb_refcnt = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nl_cb_put(struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!cb)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cb->cb_refcnt--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cb->cb_refcnt < 0)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cb->cb_refcnt <= 0)
 | 
				
			||||||
 | 
							free(cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Callback Setup
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set up a callback 
 | 
				
			||||||
 | 
					 * @arg cb		callback set
 | 
				
			||||||
 | 
					 * @arg type		callback to modify
 | 
				
			||||||
 | 
					 * @arg kind		kind of implementation
 | 
				
			||||||
 | 
					 * @arg func		callback function (NL_CB_CUSTOM)
 | 
				
			||||||
 | 
					 * @arg arg		argument passed to callback
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
 | 
				
			||||||
 | 
						      nl_recvmsg_msg_cb_t func, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (type < 0 || type > NL_CB_TYPE_MAX)
 | 
				
			||||||
 | 
							return -NLE_RANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (kind < 0 || kind > NL_CB_KIND_MAX)
 | 
				
			||||||
 | 
							return -NLE_RANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (kind == NL_CB_CUSTOM) {
 | 
				
			||||||
 | 
							cb->cb_set[type] = func;
 | 
				
			||||||
 | 
							cb->cb_args[type] = arg;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set up an error callback
 | 
				
			||||||
 | 
					 * @arg cb		callback set
 | 
				
			||||||
 | 
					 * @arg kind		kind of callback
 | 
				
			||||||
 | 
					 * @arg func		callback function
 | 
				
			||||||
 | 
					 * @arg arg		argument to be passed to callback function
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
 | 
				
			||||||
 | 
						      nl_recvmsg_err_cb_t func, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (kind < 0 || kind > NL_CB_KIND_MAX)
 | 
				
			||||||
 | 
							return -NLE_RANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (kind == NL_CB_CUSTOM) {
 | 
				
			||||||
 | 
							cb->cb_err = func;
 | 
				
			||||||
 | 
							cb->cb_err_arg = arg;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										69
									
								
								package/libnl-tiny/src/include/linux/genetlink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								package/libnl-tiny/src/include/linux/genetlink.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					#ifndef __LINUX_GENERIC_NETLINK_H
 | 
				
			||||||
 | 
					#define __LINUX_GENERIC_NETLINK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_NAMSIZ	16	/* length of family name */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_MIN_ID	NLMSG_MIN_TYPE
 | 
				
			||||||
 | 
					#define GENL_MAX_ID	1023
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct genlmsghdr {
 | 
				
			||||||
 | 
						__u8	cmd;
 | 
				
			||||||
 | 
						__u8	version;
 | 
				
			||||||
 | 
						__u16	reserved;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_HDRLEN	NLMSG_ALIGN(sizeof(struct genlmsghdr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_ADMIN_PERM		0x01
 | 
				
			||||||
 | 
					#define GENL_CMD_CAP_DO		0x02
 | 
				
			||||||
 | 
					#define GENL_CMD_CAP_DUMP	0x04
 | 
				
			||||||
 | 
					#define GENL_CMD_CAP_HASPOL	0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * List of reserved static generic netlink identifiers:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define GENL_ID_GENERATE	0
 | 
				
			||||||
 | 
					#define GENL_ID_CTRL		NLMSG_MIN_TYPE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**************************************************************************
 | 
				
			||||||
 | 
					 * Controller
 | 
				
			||||||
 | 
					 **************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						CTRL_CMD_UNSPEC,
 | 
				
			||||||
 | 
						CTRL_CMD_NEWFAMILY,
 | 
				
			||||||
 | 
						CTRL_CMD_DELFAMILY,
 | 
				
			||||||
 | 
						CTRL_CMD_GETFAMILY,
 | 
				
			||||||
 | 
						CTRL_CMD_NEWOPS,
 | 
				
			||||||
 | 
						CTRL_CMD_DELOPS,
 | 
				
			||||||
 | 
						CTRL_CMD_GETOPS,
 | 
				
			||||||
 | 
						__CTRL_CMD_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						CTRL_ATTR_UNSPEC,
 | 
				
			||||||
 | 
						CTRL_ATTR_FAMILY_ID,
 | 
				
			||||||
 | 
						CTRL_ATTR_FAMILY_NAME,
 | 
				
			||||||
 | 
						CTRL_ATTR_VERSION,
 | 
				
			||||||
 | 
						CTRL_ATTR_HDRSIZE,
 | 
				
			||||||
 | 
						CTRL_ATTR_MAXATTR,
 | 
				
			||||||
 | 
						CTRL_ATTR_OPS,
 | 
				
			||||||
 | 
						__CTRL_ATTR_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						CTRL_ATTR_OP_UNSPEC,
 | 
				
			||||||
 | 
						CTRL_ATTR_OP_ID,
 | 
				
			||||||
 | 
						CTRL_ATTR_OP_FLAGS,
 | 
				
			||||||
 | 
						__CTRL_ATTR_OP_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif	/* __LINUX_GENERIC_NETLINK_H */
 | 
				
			||||||
							
								
								
									
										131
									
								
								package/libnl-tiny/src/include/linux/if.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								package/libnl-tiny/src/include/linux/if.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * INET		An implementation of the TCP/IP protocol suite for the LINUX
 | 
				
			||||||
 | 
					 *		operating system.  INET is implemented using the  BSD Socket
 | 
				
			||||||
 | 
					 *		interface as the means of communication with the user level.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		Global definitions for the INET interface module.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Version:	@(#)if.h	1.0.2	04/18/93
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Authors:	Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
 | 
				
			||||||
 | 
					 *		Ross Biro
 | 
				
			||||||
 | 
					 *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		This program 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; either version
 | 
				
			||||||
 | 
					 *		2 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _LINUX_IF_H
 | 
				
			||||||
 | 
					#define _LINUX_IF_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/types.h>		/* for "__kernel_caddr_t" et al	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	IFNAMSIZ	16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Standard interface flags (netdevice->flags). */
 | 
				
			||||||
 | 
					#define	IFF_UP		0x1		/* interface is up		*/
 | 
				
			||||||
 | 
					#define	IFF_BROADCAST	0x2		/* broadcast address valid	*/
 | 
				
			||||||
 | 
					#define	IFF_DEBUG	0x4		/* turn on debugging		*/
 | 
				
			||||||
 | 
					#define	IFF_LOOPBACK	0x8		/* is a loopback net		*/
 | 
				
			||||||
 | 
					#define	IFF_POINTOPOINT	0x10		/* interface is has p-p link	*/
 | 
				
			||||||
 | 
					#define	IFF_NOTRAILERS	0x20		/* avoid use of trailers	*/
 | 
				
			||||||
 | 
					#define	IFF_RUNNING	0x40		/* interface RFC2863 OPER_UP	*/
 | 
				
			||||||
 | 
					#define	IFF_NOARP	0x80		/* no ARP protocol		*/
 | 
				
			||||||
 | 
					#define	IFF_PROMISC	0x100		/* receive all packets		*/
 | 
				
			||||||
 | 
					#define	IFF_ALLMULTI	0x200		/* receive all multicast packets*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFF_MASTER	0x400		/* master of a load balancer 	*/
 | 
				
			||||||
 | 
					#define IFF_SLAVE	0x800		/* slave of a load balancer	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFF_MULTICAST	0x1000		/* Supports multicast		*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFF_PORTSEL	0x2000          /* can set media type		*/
 | 
				
			||||||
 | 
					#define IFF_AUTOMEDIA	0x4000		/* auto media select active	*/
 | 
				
			||||||
 | 
					#define IFF_DYNAMIC	0x8000		/* dialup device with changing addresses*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFF_LOWER_UP	0x10000		/* driver signals L1 up		*/
 | 
				
			||||||
 | 
					#define IFF_DORMANT	0x20000		/* driver signals dormant	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFF_ECHO	0x40000		/* echo sent packets		*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
 | 
				
			||||||
 | 
							IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Private (from user) interface flags (netdevice->priv_flags). */
 | 
				
			||||||
 | 
					#define IFF_802_1Q_VLAN 0x1             /* 802.1Q VLAN device.          */
 | 
				
			||||||
 | 
					#define IFF_EBRIDGE	0x2		/* Ethernet bridging device.	*/
 | 
				
			||||||
 | 
					#define IFF_SLAVE_INACTIVE	0x4	/* bonding slave not the curr. active */
 | 
				
			||||||
 | 
					#define IFF_MASTER_8023AD	0x8	/* bonding master, 802.3ad. 	*/
 | 
				
			||||||
 | 
					#define IFF_MASTER_ALB	0x10		/* bonding master, balance-alb.	*/
 | 
				
			||||||
 | 
					#define IFF_BONDING	0x20		/* bonding master or slave	*/
 | 
				
			||||||
 | 
					#define IFF_SLAVE_NEEDARP 0x40		/* need ARPs for validation	*/
 | 
				
			||||||
 | 
					#define IFF_ISATAP	0x80		/* ISATAP interface (RFC4214)	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IF_GET_IFACE	0x0001		/* for querying only */
 | 
				
			||||||
 | 
					#define IF_GET_PROTO	0x0002
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* For definitions see hdlc.h */
 | 
				
			||||||
 | 
					#define IF_IFACE_V35	0x1000		/* V.35 serial interface	*/
 | 
				
			||||||
 | 
					#define IF_IFACE_V24	0x1001		/* V.24 serial interface	*/
 | 
				
			||||||
 | 
					#define IF_IFACE_X21	0x1002		/* X.21 serial interface	*/
 | 
				
			||||||
 | 
					#define IF_IFACE_T1	0x1003		/* T1 telco serial interface	*/
 | 
				
			||||||
 | 
					#define IF_IFACE_E1	0x1004		/* E1 telco serial interface	*/
 | 
				
			||||||
 | 
					#define IF_IFACE_SYNC_SERIAL 0x1005	/* can't be set by software	*/
 | 
				
			||||||
 | 
					#define IF_IFACE_X21D   0x1006          /* X.21 Dual Clocking (FarSite) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* For definitions see hdlc.h */
 | 
				
			||||||
 | 
					#define IF_PROTO_HDLC	0x2000		/* raw HDLC protocol		*/
 | 
				
			||||||
 | 
					#define IF_PROTO_PPP	0x2001		/* PPP protocol			*/
 | 
				
			||||||
 | 
					#define IF_PROTO_CISCO	0x2002		/* Cisco HDLC protocol		*/
 | 
				
			||||||
 | 
					#define IF_PROTO_FR	0x2003		/* Frame Relay protocol		*/
 | 
				
			||||||
 | 
					#define IF_PROTO_FR_ADD_PVC 0x2004	/*    Create FR PVC		*/
 | 
				
			||||||
 | 
					#define IF_PROTO_FR_DEL_PVC 0x2005	/*    Delete FR PVC		*/
 | 
				
			||||||
 | 
					#define IF_PROTO_X25	0x2006		/* X.25				*/
 | 
				
			||||||
 | 
					#define IF_PROTO_HDLC_ETH 0x2007	/* raw HDLC, Ethernet emulation	*/
 | 
				
			||||||
 | 
					#define IF_PROTO_FR_ADD_ETH_PVC 0x2008	/*  Create FR Ethernet-bridged PVC */
 | 
				
			||||||
 | 
					#define IF_PROTO_FR_DEL_ETH_PVC 0x2009	/*  Delete FR Ethernet-bridged PVC */
 | 
				
			||||||
 | 
					#define IF_PROTO_FR_PVC	0x200A		/* for reading PVC status	*/
 | 
				
			||||||
 | 
					#define IF_PROTO_FR_ETH_PVC 0x200B
 | 
				
			||||||
 | 
					#define IF_PROTO_RAW    0x200C          /* RAW Socket                   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 2863 operational status */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						IF_OPER_UNKNOWN,
 | 
				
			||||||
 | 
						IF_OPER_NOTPRESENT,
 | 
				
			||||||
 | 
						IF_OPER_DOWN,
 | 
				
			||||||
 | 
						IF_OPER_LOWERLAYERDOWN,
 | 
				
			||||||
 | 
						IF_OPER_TESTING,
 | 
				
			||||||
 | 
						IF_OPER_DORMANT,
 | 
				
			||||||
 | 
						IF_OPER_UP,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* link modes */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						IF_LINK_MODE_DEFAULT,
 | 
				
			||||||
 | 
						IF_LINK_MODE_DORMANT,	/* limit upward transition to dormant */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *	Device mapping structure. I'd just gone off and designed a 
 | 
				
			||||||
 | 
					 *	beautiful scheme using only loadable modules with arguments
 | 
				
			||||||
 | 
					 *	for driver options and along come the PCMCIA people 8)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Ah well. The get() side of this is good for WDSETUP, and it'll
 | 
				
			||||||
 | 
					 *	be handy for debugging things. The set side is fine for now and
 | 
				
			||||||
 | 
					 *	being very small might be worth keeping for clean configuration.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ifmap 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long mem_start;
 | 
				
			||||||
 | 
						unsigned long mem_end;
 | 
				
			||||||
 | 
						unsigned short base_addr; 
 | 
				
			||||||
 | 
						unsigned char irq;
 | 
				
			||||||
 | 
						unsigned char dma;
 | 
				
			||||||
 | 
						unsigned char port;
 | 
				
			||||||
 | 
						/* 3 bytes spare */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _LINUX_IF_H */
 | 
				
			||||||
							
								
								
									
										62
									
								
								package/libnl-tiny/src/include/linux/if_addr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								package/libnl-tiny/src/include/linux/if_addr.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					#ifndef __LINUX_IF_ADDR_H
 | 
				
			||||||
 | 
					#define __LINUX_IF_ADDR_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ifaddrmsg
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u8		ifa_family;
 | 
				
			||||||
 | 
						__u8		ifa_prefixlen;	/* The prefix length		*/
 | 
				
			||||||
 | 
						__u8		ifa_flags;	/* Flags			*/
 | 
				
			||||||
 | 
						__u8		ifa_scope;	/* Address scope		*/
 | 
				
			||||||
 | 
						__u32		ifa_index;	/* Link index			*/
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Important comment:
 | 
				
			||||||
 | 
					 * IFA_ADDRESS is prefix address, rather than local interface address.
 | 
				
			||||||
 | 
					 * It makes no difference for normally configured broadcast interfaces,
 | 
				
			||||||
 | 
					 * but for point-to-point IFA_ADDRESS is DESTINATION address,
 | 
				
			||||||
 | 
					 * local address is supplied in IFA_LOCAL attribute.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						IFA_UNSPEC,
 | 
				
			||||||
 | 
						IFA_ADDRESS,
 | 
				
			||||||
 | 
						IFA_LOCAL,
 | 
				
			||||||
 | 
						IFA_LABEL,
 | 
				
			||||||
 | 
						IFA_BROADCAST,
 | 
				
			||||||
 | 
						IFA_ANYCAST,
 | 
				
			||||||
 | 
						IFA_CACHEINFO,
 | 
				
			||||||
 | 
						IFA_MULTICAST,
 | 
				
			||||||
 | 
						__IFA_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFA_MAX (__IFA_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ifa_flags */
 | 
				
			||||||
 | 
					#define IFA_F_SECONDARY		0x01
 | 
				
			||||||
 | 
					#define IFA_F_TEMPORARY		IFA_F_SECONDARY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	IFA_F_NODAD		0x02
 | 
				
			||||||
 | 
					#define IFA_F_OPTIMISTIC	0x04
 | 
				
			||||||
 | 
					#define	IFA_F_HOMEADDRESS	0x10
 | 
				
			||||||
 | 
					#define IFA_F_DEPRECATED	0x20
 | 
				
			||||||
 | 
					#define IFA_F_TENTATIVE		0x40
 | 
				
			||||||
 | 
					#define IFA_F_PERMANENT		0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ifa_cacheinfo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u32	ifa_prefered;
 | 
				
			||||||
 | 
						__u32	ifa_valid;
 | 
				
			||||||
 | 
						__u32	cstamp; /* created timestamp, hundredths of seconds */
 | 
				
			||||||
 | 
						__u32	tstamp; /* updated timestamp, hundredths of seconds */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* backwards compatibility for userspace */
 | 
				
			||||||
 | 
					#ifndef __KERNEL__
 | 
				
			||||||
 | 
					#define IFA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
 | 
				
			||||||
 | 
					#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										150
									
								
								package/libnl-tiny/src/include/linux/netlink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								package/libnl-tiny/src/include/linux/netlink.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					#ifndef __LINUX_NETLINK_H
 | 
				
			||||||
 | 
					#define __LINUX_NETLINK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/socket.h> /* for sa_family_t */
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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_NFLOG		5	/* netfilter/iptables ULOG */
 | 
				
			||||||
 | 
					#define NETLINK_XFRM		6	/* ipsec */
 | 
				
			||||||
 | 
					#define NETLINK_SELINUX		7	/* SELinux event notifications */
 | 
				
			||||||
 | 
					#define NETLINK_ISCSI		8	/* Open-iSCSI */
 | 
				
			||||||
 | 
					#define NETLINK_AUDIT		9	/* auditing */
 | 
				
			||||||
 | 
					#define NETLINK_FIB_LOOKUP	10	
 | 
				
			||||||
 | 
					#define NETLINK_CONNECTOR	11
 | 
				
			||||||
 | 
					#define NETLINK_NETFILTER	12	/* netfilter subsystem */
 | 
				
			||||||
 | 
					#define NETLINK_IP6_FW		13
 | 
				
			||||||
 | 
					#define NETLINK_DNRTMSG		14	/* DECnet routing messages */
 | 
				
			||||||
 | 
					#define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
 | 
				
			||||||
 | 
					#define NETLINK_GENERIC		16
 | 
				
			||||||
 | 
					/* leave room for NETLINK_DM (DM Events) */
 | 
				
			||||||
 | 
					#define NETLINK_SCSITRANSPORT	18	/* SCSI Transports */
 | 
				
			||||||
 | 
					#define NETLINK_ECRYPTFS	19
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_LINKS 32		
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sockaddr_nl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sa_family_t	nl_family;	/* AF_NETLINK	*/
 | 
				
			||||||
 | 
						unsigned short	nl_pad;		/* zero		*/
 | 
				
			||||||
 | 
						__u32		nl_pid;		/* port ID	*/
 | 
				
			||||||
 | 
					       	__u32		nl_groups;	/* multicast groups mask */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nlmsghdr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u32		nlmsg_len;	/* Length of message including header */
 | 
				
			||||||
 | 
						__u16		nlmsg_type;	/* Message content */
 | 
				
			||||||
 | 
						__u16		nlmsg_flags;	/* Additional flags */
 | 
				
			||||||
 | 
						__u32		nlmsg_seq;	/* Sequence number */
 | 
				
			||||||
 | 
						__u32		nlmsg_pid;	/* Sending process port ID */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Flags values */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLM_F_REQUEST		1	/* It is request message. 	*/
 | 
				
			||||||
 | 
					#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 		*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Modifiers to GET request */
 | 
				
			||||||
 | 
					#define NLM_F_ROOT	0x100	/* specify tree	root	*/
 | 
				
			||||||
 | 
					#define NLM_F_MATCH	0x200	/* return all matching	*/
 | 
				
			||||||
 | 
					#define NLM_F_ATOMIC	0x400	/* atomic GET		*/
 | 
				
			||||||
 | 
					#define NLM_F_DUMP	(NLM_F_ROOT|NLM_F_MATCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Modifiers to NEW request */
 | 
				
			||||||
 | 
					#define NLM_F_REPLACE	0x100	/* Override existing		*/
 | 
				
			||||||
 | 
					#define NLM_F_EXCL	0x200	/* Do not touch, if it exists	*/
 | 
				
			||||||
 | 
					#define NLM_F_CREATE	0x400	/* Create, if it does not exist	*/
 | 
				
			||||||
 | 
					#define NLM_F_APPEND	0x800	/* Add to end of list		*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   4.4BSD ADD		NLM_F_CREATE|NLM_F_EXCL
 | 
				
			||||||
 | 
					   4.4BSD CHANGE	NLM_F_REPLACE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   True CHANGE		NLM_F_CREATE|NLM_F_REPLACE
 | 
				
			||||||
 | 
					   Append		NLM_F_CREATE
 | 
				
			||||||
 | 
					   Check		NLM_F_EXCL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLMSG_ALIGNTO	4
 | 
				
			||||||
 | 
					#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
 | 
				
			||||||
 | 
					#define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
 | 
				
			||||||
 | 
					#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
 | 
				
			||||||
 | 
					#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
 | 
				
			||||||
 | 
					#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
 | 
				
			||||||
 | 
					#define NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
 | 
				
			||||||
 | 
									  (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
 | 
				
			||||||
 | 
					#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
 | 
				
			||||||
 | 
								   (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
 | 
				
			||||||
 | 
								   (nlh)->nlmsg_len <= (len))
 | 
				
			||||||
 | 
					#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLMSG_NOOP		0x1	/* Nothing.		*/
 | 
				
			||||||
 | 
					#define NLMSG_ERROR		0x2	/* Error		*/
 | 
				
			||||||
 | 
					#define NLMSG_DONE		0x3	/* End of a dump	*/
 | 
				
			||||||
 | 
					#define NLMSG_OVERRUN		0x4	/* Data lost		*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLMSG_MIN_TYPE		0x10	/* < 0x10: reserved control messages */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nlmsgerr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int		error;
 | 
				
			||||||
 | 
						struct nlmsghdr msg;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NETLINK_ADD_MEMBERSHIP	1
 | 
				
			||||||
 | 
					#define NETLINK_DROP_MEMBERSHIP	2
 | 
				
			||||||
 | 
					#define NETLINK_PKTINFO		3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_pktinfo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u32	group;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NET_MAJOR 36		/* Major 36 is reserved for networking 						*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						NETLINK_UNCONNECTED = 0,
 | 
				
			||||||
 | 
						NETLINK_CONNECTED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
 | 
				
			||||||
 | 
					 * +---------------------+- - -+- - - - - - - - - -+- - -+
 | 
				
			||||||
 | 
					 * |        Header       | Pad |     Payload       | Pad |
 | 
				
			||||||
 | 
					 * |   (struct nlattr)   | ing |                   | ing |
 | 
				
			||||||
 | 
					 * +---------------------+- - -+- - - - - - - - - -+- - -+
 | 
				
			||||||
 | 
					 *  <-------------- nlattr->nla_len -------------->
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nlattr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u16           nla_len;
 | 
				
			||||||
 | 
						__u16           nla_type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * nla_type (16 bits)
 | 
				
			||||||
 | 
					 * +---+---+-------------------------------+
 | 
				
			||||||
 | 
					 * | N | O | Attribute Type                |
 | 
				
			||||||
 | 
					 * +---+---+-------------------------------+
 | 
				
			||||||
 | 
					 * N := Carries nested attributes
 | 
				
			||||||
 | 
					 * O := Payload stored in network byte order
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note: The N and O flag are mutually exclusive.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_F_NESTED		(1 << 15)
 | 
				
			||||||
 | 
					#define NLA_F_NET_BYTEORDER	(1 << 14)
 | 
				
			||||||
 | 
					#define NLA_TYPE_MASK		~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLA_ALIGNTO		4
 | 
				
			||||||
 | 
					#define NLA_ALIGN(len)		(((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
 | 
				
			||||||
 | 
					#define NLA_HDRLEN		((int) NLA_ALIGN(sizeof(struct nlattr)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif	/* __LINUX_NETLINK_H */
 | 
				
			||||||
							
								
								
									
										20
									
								
								package/libnl-tiny/src/include/netlink-generic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								package/libnl-tiny/src/include/netlink-generic.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink-generic.h	Local Generic Netlink Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_GENL_PRIV_H_
 | 
				
			||||||
 | 
					#define NETLINK_GENL_PRIV_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										153
									
								
								package/libnl-tiny/src/include/netlink-local.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								package/libnl-tiny/src/include/netlink-local.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink-local.h		Local Netlink Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_LOCAL_H_
 | 
				
			||||||
 | 
					#define NETLINK_LOCAL_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SOL_NETLINK
 | 
				
			||||||
 | 
					#define SOL_NETLINK 270
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* local header copies */
 | 
				
			||||||
 | 
					#include <linux/if.h>
 | 
				
			||||||
 | 
					#include <linux/if_arp.h>
 | 
				
			||||||
 | 
					#include <linux/if_ether.h>
 | 
				
			||||||
 | 
					#include <linux/pkt_sched.h>
 | 
				
			||||||
 | 
					#include <linux/pkt_cls.h>
 | 
				
			||||||
 | 
					#include <linux/gen_stats.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/handlers.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					#include <netlink/object-api.h>
 | 
				
			||||||
 | 
					#include <netlink/cache-api.h>
 | 
				
			||||||
 | 
					#include <netlink-types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct trans_tbl {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						const char *a;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __ADD(id, name) { .i = id, .a = #name },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct trans_list {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						char *a;
 | 
				
			||||||
 | 
						struct nl_list_head list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_DEBUG	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_DBG(LVL,FMT,ARG...) \
 | 
				
			||||||
 | 
						do {} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BUG()                            \
 | 
				
			||||||
 | 
						do {                                 \
 | 
				
			||||||
 | 
							fprintf(stderr, "BUG: %s:%d\n",  \
 | 
				
			||||||
 | 
								__FILE__, __LINE__);         \
 | 
				
			||||||
 | 
							assert(0);	\
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int __nl_read_num_str_file(const char *path,
 | 
				
			||||||
 | 
									  int (*cb)(long, const char *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int __trans_list_add(int, const char *, struct nl_list_head *);
 | 
				
			||||||
 | 
					extern void __trans_list_clear(struct nl_list_head *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char *__type2str(int, char *, size_t, struct trans_tbl *, size_t);
 | 
				
			||||||
 | 
					extern int __str2type(const char *, struct trans_tbl *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char *__list_type2str(int, char *, size_t, struct nl_list_head *);
 | 
				
			||||||
 | 
					extern int __list_str2type(const char *, struct nl_list_head *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char *__flags2str(int, char *, size_t, struct trans_tbl *, size_t);
 | 
				
			||||||
 | 
					extern int __str2flags(const char *, struct trans_tbl *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void dump_from_ops(struct nl_object *, struct nl_dump_params *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct nl_cache *dp_cache(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (obj->ce_cache == NULL)
 | 
				
			||||||
 | 
							return nl_cache_mngt_require(obj->ce_ops->oo_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return obj->ce_cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cb->cb_set[type](msg, cb->cb_args[type]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
 | 
				
			||||||
 | 
					#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __init __attribute__ ((constructor))
 | 
				
			||||||
 | 
					#define __exit __attribute__ ((destructor))
 | 
				
			||||||
 | 
					#undef __deprecated
 | 
				
			||||||
 | 
					#define __deprecated __attribute__ ((deprecated))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define min(x,y) ({ \
 | 
				
			||||||
 | 
						typeof(x) _x = (x);	\
 | 
				
			||||||
 | 
						typeof(y) _y = (y);	\
 | 
				
			||||||
 | 
						(void) (&_x == &_y);		\
 | 
				
			||||||
 | 
						_x < _y ? _x : _y; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define max(x,y) ({ \
 | 
				
			||||||
 | 
						typeof(x) _x = (x);	\
 | 
				
			||||||
 | 
						typeof(y) _y = (y);	\
 | 
				
			||||||
 | 
						(void) (&_x == &_y);		\
 | 
				
			||||||
 | 
						_x > _y ? _x : _y; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
 | 
				
			||||||
 | 
								  struct nlmsghdr *, struct nl_parser_param *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline char *nl_cache_name(struct nl_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cache->c_ops ? cache->c_ops->co_name : "unknown";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_FAMILY(id, name) \
 | 
				
			||||||
 | 
						{ \
 | 
				
			||||||
 | 
							{ id, NL_ACT_UNSPEC, name }, \
 | 
				
			||||||
 | 
							END_OF_MSGTYPES_LIST, \
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int wait_for_ack(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (sk->s_flags & NL_NO_AUTO_ACK)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return nl_wait_for_ack(sk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										81
									
								
								package/libnl-tiny/src/include/netlink-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								package/libnl-tiny/src/include/netlink-types.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink-types.h	Netlink Types (Private)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_LOCAL_TYPES_H_
 | 
				
			||||||
 | 
					#define NETLINK_LOCAL_TYPES_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/list.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache_ops;
 | 
				
			||||||
 | 
					struct nl_sock;
 | 
				
			||||||
 | 
					struct nl_object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_list_head	c_items;
 | 
				
			||||||
 | 
						int			c_nitems;
 | 
				
			||||||
 | 
						int                     c_iarg1;
 | 
				
			||||||
 | 
						int                     c_iarg2;
 | 
				
			||||||
 | 
						struct nl_cache_ops *   c_ops;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache_assoc
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache *	ca_cache;
 | 
				
			||||||
 | 
						change_func_t		ca_change;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache_mngr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int			cm_protocol;
 | 
				
			||||||
 | 
						int			cm_flags;
 | 
				
			||||||
 | 
						int			cm_nassocs;
 | 
				
			||||||
 | 
						struct nl_sock *	cm_handle;
 | 
				
			||||||
 | 
						struct nl_cache_assoc *	cm_assocs;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_parser_param;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOOSE_COMPARISON	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_data
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t			d_size;
 | 
				
			||||||
 | 
						void *			d_data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_addr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int			a_family;
 | 
				
			||||||
 | 
						unsigned int		a_maxsize;
 | 
				
			||||||
 | 
						unsigned int		a_len;
 | 
				
			||||||
 | 
						int			a_prefixlen;
 | 
				
			||||||
 | 
						int			a_refcnt;
 | 
				
			||||||
 | 
						char			a_addr[0];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IFQDISCSIZ	32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENL_OP_HAS_POLICY	1
 | 
				
			||||||
 | 
					#define GENL_OP_HAS_DOIT	2
 | 
				
			||||||
 | 
					#define GENL_OP_HAS_DUMPIT	4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct genl_family_op
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t		o_id;
 | 
				
			||||||
 | 
						uint32_t		o_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct nl_list_head	o_list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										69
									
								
								package/libnl-tiny/src/include/netlink/addr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								package/libnl-tiny/src/include/netlink/addr.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/addr.h		Abstract Address
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_ADDR_H_
 | 
				
			||||||
 | 
					#define NETLINK_ADDR_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Creation */
 | 
				
			||||||
 | 
					extern struct nl_addr *	nl_addr_alloc(size_t);
 | 
				
			||||||
 | 
					extern struct nl_addr *	nl_addr_alloc_attr(struct nlattr *, int);
 | 
				
			||||||
 | 
					extern struct nl_addr *	nl_addr_build(int, void *, size_t);
 | 
				
			||||||
 | 
					extern int		nl_addr_parse(const char *, int, struct nl_addr **);
 | 
				
			||||||
 | 
					extern struct nl_addr *	nl_addr_clone(struct nl_addr *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Destroyage */
 | 
				
			||||||
 | 
					extern void		nl_addr_destroy(struct nl_addr *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Usage Management */
 | 
				
			||||||
 | 
					extern struct nl_addr *	nl_addr_get(struct nl_addr *);
 | 
				
			||||||
 | 
					extern void		nl_addr_put(struct nl_addr *);
 | 
				
			||||||
 | 
					extern 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_iszero(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 *,
 | 
				
			||||||
 | 
										      struct sockaddr *, socklen_t *);
 | 
				
			||||||
 | 
					extern int		nl_addr_info(struct nl_addr *, struct addrinfo **);
 | 
				
			||||||
 | 
					extern int		nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Access Functions */
 | 
				
			||||||
 | 
					extern void		nl_addr_set_family(struct nl_addr *, int);
 | 
				
			||||||
 | 
					extern int		nl_addr_get_family(struct nl_addr *);
 | 
				
			||||||
 | 
					extern int		nl_addr_set_binary_addr(struct nl_addr *, void *,
 | 
				
			||||||
 | 
											size_t);
 | 
				
			||||||
 | 
					extern void *		nl_addr_get_binary_addr(struct nl_addr *);
 | 
				
			||||||
 | 
					extern unsigned int	nl_addr_get_len(struct nl_addr *);
 | 
				
			||||||
 | 
					extern void		nl_addr_set_prefixlen(struct nl_addr *, int);
 | 
				
			||||||
 | 
					extern unsigned int	nl_addr_get_prefixlen(struct nl_addr *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Address Family Translations */
 | 
				
			||||||
 | 
					extern char *		nl_af2str(int, char *, size_t);
 | 
				
			||||||
 | 
					extern int		nl_str2af(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Translations to Strings */
 | 
				
			||||||
 | 
					extern char *		nl_addr2str(struct nl_addr *, char *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										726
									
								
								package/libnl-tiny/src/include/netlink/attr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										726
									
								
								package/libnl-tiny/src/include/netlink/attr.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,726 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/attr.h		Netlink Attributes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_ATTR_H_
 | 
				
			||||||
 | 
					#define NETLINK_ATTR_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/object.h>
 | 
				
			||||||
 | 
					#include <netlink/addr.h>
 | 
				
			||||||
 | 
					#include <netlink/data.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Basic Attribute Data Types
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * @ingroup attr
 | 
				
			||||||
 | 
					  * Basic attribute data types
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * See \ref attr_datatypes for more details.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						NLA_UNSPEC,	/**< Unspecified type, binary data chunk */
 | 
				
			||||||
 | 
						NLA_U8,		/**< 8 bit integer */
 | 
				
			||||||
 | 
						NLA_U16,	/**< 16 bit integer */
 | 
				
			||||||
 | 
						NLA_U32,	/**< 32 bit integer */
 | 
				
			||||||
 | 
						NLA_U64,	/**< 64 bit integer */
 | 
				
			||||||
 | 
						NLA_STRING,	/**< NUL terminated character string */
 | 
				
			||||||
 | 
						NLA_FLAG,	/**< Flag */
 | 
				
			||||||
 | 
						NLA_MSECS,	/**< Micro seconds (64bit) */
 | 
				
			||||||
 | 
						NLA_NESTED,	/**< Nested attributes */
 | 
				
			||||||
 | 
						__NLA_TYPE_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup attr
 | 
				
			||||||
 | 
					 * Attribute validation policy.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See \ref attr_datatypes for more details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nla_policy {
 | 
				
			||||||
 | 
						/** Type of attribute or NLA_UNSPEC */
 | 
				
			||||||
 | 
						uint16_t	type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Minimal length of payload required */
 | 
				
			||||||
 | 
						uint16_t	minlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Maximal length of payload allowed */
 | 
				
			||||||
 | 
						uint16_t	maxlen;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Attribute parsing */
 | 
				
			||||||
 | 
					extern int		nla_ok(const struct nlattr *, int);
 | 
				
			||||||
 | 
					extern struct nlattr *	nla_next(const struct nlattr *, int *);
 | 
				
			||||||
 | 
					extern int		nla_parse(struct nlattr **, int, struct nlattr *,
 | 
				
			||||||
 | 
									  int, struct nla_policy *);
 | 
				
			||||||
 | 
					extern int		nla_validate(struct nlattr *, int, int,
 | 
				
			||||||
 | 
									     struct nla_policy *);
 | 
				
			||||||
 | 
					extern struct nlattr *	nla_find(struct nlattr *, int, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Unspecific attribute */
 | 
				
			||||||
 | 
					extern struct nlattr *	nla_reserve(struct nl_msg *, int, int);
 | 
				
			||||||
 | 
					extern int		nla_put(struct nl_msg *, int, int, const void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nlmsg_find_attr - find a specific attribute in a netlink message
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen		length of familiy specific header
 | 
				
			||||||
 | 
					 * @arg attrtype	type of attribute to look for
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns the first attribute which matches the specified type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_find(nlmsg_attrdata(nlh, hdrlen),
 | 
				
			||||||
 | 
								nlmsg_attrlen(nlh, hdrlen), attrtype);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return size of attribute whithout padding.
 | 
				
			||||||
 | 
					 * @arg payload		Payload length of attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *    <-------- nla_attr_size(payload) --------->
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 *   | Attribute Header | Pad |     Payload      | Pad |
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Size of attribute in bytes without padding.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_attr_size(int payload)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NLA_HDRLEN + payload;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return size of attribute including padding.
 | 
				
			||||||
 | 
					 * @arg payload		Payload length of attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *    <----------- nla_total_size(payload) ----------->
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 *   | Attribute Header | Pad |     Payload      | Pad |
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Size of attribute in bytes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_total_size(int payload)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NLA_ALIGN(nla_attr_size(payload));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return length of padding at the tail of the attribute.
 | 
				
			||||||
 | 
					 * @arg payload		Payload length of attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 *   | Attribute Header | Pad |     Payload      | Pad |
 | 
				
			||||||
 | 
					 *   +------------------+- - -+- - - - - - - - - +- - -+
 | 
				
			||||||
 | 
					 *                                                <--->  
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Length of padding in bytes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_padlen(int payload)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_total_size(payload) - nla_attr_size(payload);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return type of the attribute.
 | 
				
			||||||
 | 
					 * @arg nla		Attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Type of attribute.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_type(const struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla->nla_type & NLA_TYPE_MASK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return pointer to the payload section.
 | 
				
			||||||
 | 
					 * @arg nla		Attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to start of payload section.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void *nla_data(const struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (char *) nla + NLA_HDRLEN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return length of the payload .
 | 
				
			||||||
 | 
					 * @arg nla		Attribute
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Length of payload in bytes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_len(const struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla->nla_len - NLA_HDRLEN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Copy attribute payload to another memory area.
 | 
				
			||||||
 | 
					 * @arg dest		Pointer to destination memory area.
 | 
				
			||||||
 | 
					 * @arg src		Attribute
 | 
				
			||||||
 | 
					 * @arg count		Number of bytes to copy at most.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note: The number of bytes copied is limited by the length of
 | 
				
			||||||
 | 
					 *       the attribute payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return The number of bytes copied to dest.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_memcpy(void *dest, struct nlattr *src, int count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int minlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!src)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						minlen = min_t(int, count, nla_len(src));
 | 
				
			||||||
 | 
						memcpy(dest, nla_data(src), minlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return minlen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add abstract data as unspecific attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg data		Abstract data object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Equivalent to nla_put() except that the length of the payload is
 | 
				
			||||||
 | 
					 * derived from the abstract data object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, nl_data_get_size(data),
 | 
				
			||||||
 | 
							       nl_data_get(data));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add abstract address as unspecific attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg addr		Abstract address object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, nl_addr_get_len(addr),
 | 
				
			||||||
 | 
							       nl_addr_get_binary_addr(addr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Integer Attributes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 8 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value to store as payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, sizeof(uint8_t), &value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return value of 8 bit integer attribute.
 | 
				
			||||||
 | 
					 * @arg nla		8 bit integer attribute
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Payload as 8 bit integer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint8_t nla_get_u8(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return *(uint8_t *) nla_data(nla);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 16 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value to store as payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, sizeof(uint16_t), &value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return payload of 16 bit integer attribute.
 | 
				
			||||||
 | 
					 * @arg nla		16 bit integer attribute
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Payload as 16 bit integer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint16_t nla_get_u16(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return *(uint16_t *) nla_data(nla);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 32 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value to store as payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, sizeof(uint32_t), &value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return payload of 32 bit integer attribute.
 | 
				
			||||||
 | 
					 * @arg nla		32 bit integer attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Payload as 32 bit integer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint32_t nla_get_u32(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return *(uint32_t *) nla_data(nla);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 64 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value to store as payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, sizeof(uint64_t), &value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return payload of u64 attribute
 | 
				
			||||||
 | 
					 * @arg nla		u64 netlink attribute
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Payload as 64 bit integer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint64_t nla_get_u64(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint64_t tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nla_memcpy(&tmp, nla, sizeof(tmp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tmp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add string attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg str		NUL terminated string.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, strlen(str) + 1, str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return payload of string attribute.
 | 
				
			||||||
 | 
					 * @arg nla		String attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to attribute payload.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline char *nla_get_string(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (char *) nla_data(nla);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline char *nla_strdup(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return strdup(nla_get_string(nla));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Flag Attribute
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add flag netlink attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_flag(struct nl_msg *msg, int attrtype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, 0, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return true if flag attribute is set.
 | 
				
			||||||
 | 
					 * @arg nla		Flag netlink attribute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return True if flag is set, otherwise false.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_get_flag(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return !!nla;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Microseconds Attribute
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add a msecs netlink attribute to a netlink message
 | 
				
			||||||
 | 
					 * @arg n		netlink message
 | 
				
			||||||
 | 
					 * @arg attrtype	attribute type
 | 
				
			||||||
 | 
					 * @arg msecs 		number of msecs
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put_u64(n, attrtype, msecs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return payload of msecs attribute
 | 
				
			||||||
 | 
					 * @arg nla		msecs netlink attribute
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return the number of milliseconds.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline unsigned long nla_get_msecs(struct nlattr *nla)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_get_u64(nla);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add nested attributes to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg nested		Message containing attributes to be nested.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Takes the attributes found in the \a nested message and appends them
 | 
				
			||||||
 | 
					 * to the message \a msg nested in a container of the type \a attrtype.
 | 
				
			||||||
 | 
					 * The \a nested message may not have a family specific header.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_put
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_put(msg, attrtype, nlmsg_len(nested->nm_nlh),
 | 
				
			||||||
 | 
							       nlmsg_data(nested->nm_nlh));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Start a new level of nested attributes.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type of container.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to container attribute.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nla_put(msg, attrtype, 0, NULL) < 0)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return start;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Finalize nesting of attributes.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg start		Container attribute as returned from nla_nest_start().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Corrects the container attribute header to include the appeneded attributes.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) -
 | 
				
			||||||
 | 
									(unsigned char *) start;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Create attribute index based on nested attribute
 | 
				
			||||||
 | 
					 * @arg tb		Index array to be filled (maxtype+1 elements).
 | 
				
			||||||
 | 
					 * @arg maxtype		Maximum attribute type expected and accepted.
 | 
				
			||||||
 | 
					 * @arg nla		Nested Attribute.
 | 
				
			||||||
 | 
					 * @arg policy		Attribute validation policy.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Feeds the stream of attributes nested into the specified attribute
 | 
				
			||||||
 | 
					 * to nla_parse().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nla_parse
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
 | 
				
			||||||
 | 
							     struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compare attribute payload with memory area.
 | 
				
			||||||
 | 
					 * @arg nla		Attribute.
 | 
				
			||||||
 | 
					 * @arg data		Memory area to compare to.
 | 
				
			||||||
 | 
					 * @arg size		Number of bytes to compare.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see memcmp(3)
 | 
				
			||||||
 | 
					 * @return An integer less than, equal to, or greater than zero.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int d = nla_len(nla) - size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (d == 0)
 | 
				
			||||||
 | 
							d = memcmp(nla_data(nla), data, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return d;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compare string attribute payload with string
 | 
				
			||||||
 | 
					 * @arg nla		Attribute of type NLA_STRING.
 | 
				
			||||||
 | 
					 * @arg str		NUL terminated string.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see strcmp(3)
 | 
				
			||||||
 | 
					 * @return An integer less than, equal to, or greater than zero.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nla_strcmp(const struct nlattr *nla, const char *str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len = strlen(str) + 1;
 | 
				
			||||||
 | 
						int d = nla_len(nla) - len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (d == 0)
 | 
				
			||||||
 | 
							d = memcmp(nla_data(nla), str, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return d;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Copy string attribute payload to a buffer.
 | 
				
			||||||
 | 
					 * @arg dst		Pointer to destination buffer.
 | 
				
			||||||
 | 
					 * @arg nla		Attribute of type NLA_STRING.
 | 
				
			||||||
 | 
					 * @arg dstsize		Size of destination buffer in bytes.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copies at most dstsize - 1 bytes to the destination buffer.
 | 
				
			||||||
 | 
					 * The result is always a valid NUL terminated string. Unlike
 | 
				
			||||||
 | 
					 * strlcpy the destination buffer is always padded out.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return The length of string attribute without the terminating NUL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t srclen = nla_len(nla);
 | 
				
			||||||
 | 
						char *src = nla_data(nla);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (srclen > 0 && src[srclen - 1] == '\0')
 | 
				
			||||||
 | 
							srclen--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dstsize > 0) {
 | 
				
			||||||
 | 
							size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							memset(dst, 0, dstsize);
 | 
				
			||||||
 | 
							memcpy(dst, src, len);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return srclen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Attribute Construction (Exception Based)
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup attr
 | 
				
			||||||
 | 
					 * Add unspecific attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg attrlen		Length of attribute payload.
 | 
				
			||||||
 | 
					 * @arg data		Head of attribute payload.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT(msg, attrtype, attrlen, data) \
 | 
				
			||||||
 | 
						do { \
 | 
				
			||||||
 | 
							if (nla_put(msg, attrtype, attrlen, data) < 0) \
 | 
				
			||||||
 | 
								goto nla_put_failure; \
 | 
				
			||||||
 | 
						} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup attr
 | 
				
			||||||
 | 
					 * Add atomic type attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg type		Atomic type.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Head of attribute payload.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_TYPE(msg, type, attrtype, value) \
 | 
				
			||||||
 | 
						do { \
 | 
				
			||||||
 | 
							type __tmp = value; \
 | 
				
			||||||
 | 
							NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \
 | 
				
			||||||
 | 
						} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 8 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_U8(msg, attrtype, value) \
 | 
				
			||||||
 | 
						NLA_PUT_TYPE(msg, uint8_t, attrtype, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 16 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_U16(msg, attrtype, value) \
 | 
				
			||||||
 | 
						NLA_PUT_TYPE(msg, uint16_t, attrtype, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 32 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_U32(msg, attrtype, value) \
 | 
				
			||||||
 | 
						NLA_PUT_TYPE(msg, uint32_t, attrtype, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add 64 bit integer attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		Numeric value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_U64(msg, attrtype, value) \
 | 
				
			||||||
 | 
						NLA_PUT_TYPE(msg, uint64_t, attrtype, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add string attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg value		NUL terminated character string.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_STRING(msg, attrtype, value) \
 | 
				
			||||||
 | 
						NLA_PUT(msg, attrtype, strlen(value) + 1, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add flag attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_FLAG(msg, attrtype) \
 | 
				
			||||||
 | 
						NLA_PUT(msg, attrtype, 0, NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add msecs attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg msecs		Numeric value in micro seconds.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_MSECS(msg, attrtype, msecs) \
 | 
				
			||||||
 | 
						NLA_PUT_U64(msg, attrtype, msecs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add address attribute to netlink message.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message.
 | 
				
			||||||
 | 
					 * @arg attrtype	Attribute type.
 | 
				
			||||||
 | 
					 * @arg addr		Abstract address object.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLA_PUT_ADDR(msg, attrtype, addr) \
 | 
				
			||||||
 | 
						NLA_PUT(msg, attrtype, nl_addr_get_len(addr), \
 | 
				
			||||||
 | 
							nl_addr_get_binary_addr(addr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Iterators
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup attr
 | 
				
			||||||
 | 
					 * Iterate over a stream of attributes
 | 
				
			||||||
 | 
					 * @arg pos	loop counter, set to current attribute
 | 
				
			||||||
 | 
					 * @arg head	head of attribute stream
 | 
				
			||||||
 | 
					 * @arg len	length of attribute stream
 | 
				
			||||||
 | 
					 * @arg rem	initialized to len, holds bytes currently remaining in stream
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define nla_for_each_attr(pos, head, len, rem) \
 | 
				
			||||||
 | 
						for (pos = head, rem = len; \
 | 
				
			||||||
 | 
						     nla_ok(pos, rem); \
 | 
				
			||||||
 | 
						     pos = nla_next(pos, &(rem)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup attr
 | 
				
			||||||
 | 
					 * Iterate over a stream of nested attributes
 | 
				
			||||||
 | 
					 * @arg pos	loop counter, set to current attribute
 | 
				
			||||||
 | 
					 * @arg nla	attribute containing the nested attributes
 | 
				
			||||||
 | 
					 * @arg rem	initialized to len, holds bytes currently remaining in stream
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define nla_for_each_nested(pos, nla, rem) \
 | 
				
			||||||
 | 
						for (pos = nla_data(nla), rem = nla_len(nla); \
 | 
				
			||||||
 | 
						     nla_ok(pos, rem); \
 | 
				
			||||||
 | 
						     pos = nla_next(pos, &(rem)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										199
									
								
								package/libnl-tiny/src/include/netlink/cache-api.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								package/libnl-tiny/src/include/netlink/cache-api.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/cache-api.h		Caching API
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_CACHE_API_H_
 | 
				
			||||||
 | 
					#define NETLINK_CACHE_API_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup cache
 | 
				
			||||||
 | 
					 * @defgroup cache_api Cache Implementation
 | 
				
			||||||
 | 
					 * @brief
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 1) Cache Definition
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * struct nl_cache_ops my_cache_ops = {
 | 
				
			||||||
 | 
					 * 	.co_name		= "route/link",
 | 
				
			||||||
 | 
					 * 	.co_protocol		= NETLINK_ROUTE,
 | 
				
			||||||
 | 
					 * 	.co_hdrsize		= sizeof(struct ifinfomsg),
 | 
				
			||||||
 | 
					 * 	.co_obj_ops		= &my_obj_ops,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 2) 
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // The simplest way to fill a cache is by providing a request-update
 | 
				
			||||||
 | 
					 * // function which must trigger a complete dump on the kernel-side of
 | 
				
			||||||
 | 
					 * // whatever the cache covers.
 | 
				
			||||||
 | 
					 * static int my_request_update(struct nl_cache *cache,
 | 
				
			||||||
 | 
					 * 				struct nl_sock *socket)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	// In this example, we request a full dump of the interface table
 | 
				
			||||||
 | 
					 * 	return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // The resulting netlink messages sent back will be fed into a message
 | 
				
			||||||
 | 
					 * // parser one at a time. The message parser has to extract all relevant
 | 
				
			||||||
 | 
					 * // information from the message and create an object reflecting the
 | 
				
			||||||
 | 
					 * // contents of the message and pass it on to the parser callback function
 | 
				
			||||||
 | 
					 * // provide which will add the object to the cache.
 | 
				
			||||||
 | 
					 * static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 | 
				
			||||||
 | 
					 * 			    struct nlmsghdr *nlh, struct nl_parser_param *pp)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	struct my_obj *obj;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	obj = my_obj_alloc();
 | 
				
			||||||
 | 
					 * 	obj->ce_msgtype = nlh->nlmsg_type;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	// Parse the netlink message and continue creating the object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	err = pp->pp_cb((struct nl_object *) obj, pp);
 | 
				
			||||||
 | 
					 * 	if (err < 0)
 | 
				
			||||||
 | 
					 * 		goto errout;
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * struct nl_cache_ops my_cache_ops = {
 | 
				
			||||||
 | 
					 * 	...
 | 
				
			||||||
 | 
					 * 	.co_request_update	= my_request_update,
 | 
				
			||||||
 | 
					 * 	.co_msg_parser		= my_msg_parser,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 3) Notification based Updates
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Caches can be kept up-to-date based on notifications if the kernel
 | 
				
			||||||
 | 
					 * // sends out notifications whenever an object is added/removed/changed.
 | 
				
			||||||
 | 
					 * //
 | 
				
			||||||
 | 
					 * // It is trivial to support this, first a list of groups needs to be
 | 
				
			||||||
 | 
					 * // defined which are required to join in order to receive all necessary
 | 
				
			||||||
 | 
					 * // notifications. The groups are separated by address family to support
 | 
				
			||||||
 | 
					 * // the common situation where a separate group is used for each address
 | 
				
			||||||
 | 
					 * // family. If there is only one group, simply specify AF_UNSPEC.
 | 
				
			||||||
 | 
					 * static struct nl_af_group addr_groups[] = {
 | 
				
			||||||
 | 
					 * 	{ AF_INET,	RTNLGRP_IPV4_IFADDR },
 | 
				
			||||||
 | 
					 * 	{ AF_INET6,	RTNLGRP_IPV6_IFADDR },
 | 
				
			||||||
 | 
					 * 	{ END_OF_GROUP_LIST },
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // In order for the caching system to know the meaning of each message
 | 
				
			||||||
 | 
					 * // type it requires a table which maps each supported message type to
 | 
				
			||||||
 | 
					 * // a cache action, e.g. RTM_NEWADDR means address has been added or
 | 
				
			||||||
 | 
					 * // updated, RTM_DELADDR means address has been removed.
 | 
				
			||||||
 | 
					 * static struct nl_cache_ops rtnl_addr_ops = {
 | 
				
			||||||
 | 
					 * 	...
 | 
				
			||||||
 | 
					 * 	.co_msgtypes		= {
 | 
				
			||||||
 | 
					 * 					{ RTM_NEWADDR, NL_ACT_NEW, "new" },
 | 
				
			||||||
 | 
					 * 					{ RTM_DELADDR, NL_ACT_DEL, "del" },
 | 
				
			||||||
 | 
					 * 					{ RTM_GETADDR, NL_ACT_GET, "get" },
 | 
				
			||||||
 | 
					 * 					END_OF_MSGTYPES_LIST,
 | 
				
			||||||
 | 
					 * 				},
 | 
				
			||||||
 | 
					 * 	.co_groups		= addr_groups,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // It is now possible to keep the cache up-to-date using the cache manager.
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						NL_ACT_UNSPEC,
 | 
				
			||||||
 | 
						NL_ACT_NEW,
 | 
				
			||||||
 | 
						NL_ACT_DEL,
 | 
				
			||||||
 | 
						NL_ACT_GET,
 | 
				
			||||||
 | 
						NL_ACT_SET,
 | 
				
			||||||
 | 
						NL_ACT_CHANGE,
 | 
				
			||||||
 | 
						__NL_ACT_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_ACT_MAX (__NL_ACT_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define END_OF_MSGTYPES_LIST	{ -1, -1, NULL }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Message type to cache action association
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msgtype
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/** Netlink message type */
 | 
				
			||||||
 | 
						int			mt_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Cache action to take */
 | 
				
			||||||
 | 
						int			mt_act;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Name of operation for human-readable printing */
 | 
				
			||||||
 | 
						char *			mt_name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Address family to netlink group association
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_af_group
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/** Address family */
 | 
				
			||||||
 | 
						int			ag_family;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Netlink group identifier */
 | 
				
			||||||
 | 
						int			ag_group;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define END_OF_GROUP_LIST AF_UNSPEC, 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_parser_param
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int             (*pp_cb)(struct nl_object *, struct nl_parser_param *);
 | 
				
			||||||
 | 
						void *            pp_arg;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Cache Operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_cache_ops
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char  *			co_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int			co_hdrsize;
 | 
				
			||||||
 | 
						int			co_protocol;
 | 
				
			||||||
 | 
						struct nl_af_group *	co_groups;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Called whenever an update of the cache is required. Must send
 | 
				
			||||||
 | 
						 * a request message to the kernel requesting a complete dump.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int   (*co_request_update)(struct nl_cache *, struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Called whenever a message was received that needs to be parsed.
 | 
				
			||||||
 | 
						 * Must parse the message and call the paser callback function
 | 
				
			||||||
 | 
						 * (nl_parser_param) provided via the argument.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int   (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *,
 | 
				
			||||||
 | 
								       struct nlmsghdr *, struct nl_parser_param *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct nl_object_ops *	co_obj_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct nl_cache_ops *co_next;
 | 
				
			||||||
 | 
						struct nl_cache *co_major_cache;
 | 
				
			||||||
 | 
						struct genl_ops *	co_genl;
 | 
				
			||||||
 | 
						struct nl_msgtype	co_msgtypes[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										126
									
								
								package/libnl-tiny/src/include/netlink/cache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								package/libnl-tiny/src/include/netlink/cache.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,126 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/cache.h		Caching Module
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_CACHE_H_
 | 
				
			||||||
 | 
					#define NETLINK_CACHE_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/object.h>
 | 
				
			||||||
 | 
					#include <netlink/cache-api.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Access Functions */
 | 
				
			||||||
 | 
					extern int			nl_cache_nitems(struct nl_cache *);
 | 
				
			||||||
 | 
					extern int			nl_cache_nitems_filter(struct nl_cache *,
 | 
				
			||||||
 | 
											       struct nl_object *);
 | 
				
			||||||
 | 
					extern struct nl_cache_ops *	nl_cache_get_ops(struct nl_cache *);
 | 
				
			||||||
 | 
					extern struct nl_object *	nl_cache_get_first(struct nl_cache *);
 | 
				
			||||||
 | 
					extern struct nl_object *	nl_cache_get_last(struct nl_cache *);
 | 
				
			||||||
 | 
					extern struct nl_object *	nl_cache_get_next(struct nl_object *);
 | 
				
			||||||
 | 
					extern struct nl_object *	nl_cache_get_prev(struct nl_object *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct nl_cache *	nl_cache_alloc(struct nl_cache_ops *);
 | 
				
			||||||
 | 
					extern int			nl_cache_alloc_and_fill(struct nl_cache_ops *,
 | 
				
			||||||
 | 
												struct nl_sock *,
 | 
				
			||||||
 | 
												struct nl_cache **);
 | 
				
			||||||
 | 
					extern int			nl_cache_alloc_name(const char *,
 | 
				
			||||||
 | 
											    struct nl_cache **);
 | 
				
			||||||
 | 
					extern struct nl_cache *	nl_cache_subset(struct nl_cache *,
 | 
				
			||||||
 | 
											struct nl_object *);
 | 
				
			||||||
 | 
					extern void			nl_cache_clear(struct nl_cache *);
 | 
				
			||||||
 | 
					extern void			nl_cache_free(struct nl_cache *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Cache modification */
 | 
				
			||||||
 | 
					extern int			nl_cache_add(struct nl_cache *,
 | 
				
			||||||
 | 
										     struct nl_object *);
 | 
				
			||||||
 | 
					extern int			nl_cache_parse_and_add(struct nl_cache *,
 | 
				
			||||||
 | 
											       struct nl_msg *);
 | 
				
			||||||
 | 
					extern void			nl_cache_remove(struct nl_object *);
 | 
				
			||||||
 | 
					extern int			nl_cache_refill(struct nl_sock *,
 | 
				
			||||||
 | 
											struct nl_cache *);
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					extern int			nl_cache_include(struct nl_cache *,
 | 
				
			||||||
 | 
											 struct nl_object *,
 | 
				
			||||||
 | 
											 change_func_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* General */
 | 
				
			||||||
 | 
					extern int			nl_cache_is_empty(struct nl_cache *);
 | 
				
			||||||
 | 
					extern void			nl_cache_mark_all(struct nl_cache *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Dumping */
 | 
				
			||||||
 | 
					extern void			nl_cache_dump(struct nl_cache *,
 | 
				
			||||||
 | 
										      struct nl_dump_params *);
 | 
				
			||||||
 | 
					extern void			nl_cache_dump_filter(struct nl_cache *,
 | 
				
			||||||
 | 
											     struct nl_dump_params *,
 | 
				
			||||||
 | 
											     struct nl_object *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Iterators */
 | 
				
			||||||
 | 
					extern void			nl_cache_foreach(struct nl_cache *,
 | 
				
			||||||
 | 
											 void (*cb)(struct nl_object *,
 | 
				
			||||||
 | 
												    void *),
 | 
				
			||||||
 | 
											 void *arg);
 | 
				
			||||||
 | 
					extern void			nl_cache_foreach_filter(struct nl_cache *,
 | 
				
			||||||
 | 
												struct nl_object *,
 | 
				
			||||||
 | 
												void (*cb)(struct
 | 
				
			||||||
 | 
													   nl_object *,
 | 
				
			||||||
 | 
													   void *),
 | 
				
			||||||
 | 
												void *arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* --- cache management --- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Cache type management */
 | 
				
			||||||
 | 
					extern struct nl_cache_ops *	nl_cache_ops_lookup(const char *);
 | 
				
			||||||
 | 
					extern struct nl_cache_ops *	nl_cache_ops_associate(int, int);
 | 
				
			||||||
 | 
					extern struct nl_msgtype *	nl_msgtype_lookup(struct nl_cache_ops *, int);
 | 
				
			||||||
 | 
					extern void			nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
 | 
				
			||||||
 | 
					extern int			nl_cache_mngt_register(struct nl_cache_ops *);
 | 
				
			||||||
 | 
					extern int			nl_cache_mngt_unregister(struct nl_cache_ops *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Global cache provisioning/requiring */
 | 
				
			||||||
 | 
					extern void			nl_cache_mngt_provide(struct nl_cache *);
 | 
				
			||||||
 | 
					extern void			nl_cache_mngt_unprovide(struct nl_cache *);
 | 
				
			||||||
 | 
					extern struct nl_cache *	nl_cache_mngt_require(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache_mngr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_AUTO_PROVIDE		1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int			nl_cache_mngr_alloc(struct nl_sock *,
 | 
				
			||||||
 | 
											    int, int,
 | 
				
			||||||
 | 
											    struct nl_cache_mngr **);
 | 
				
			||||||
 | 
					extern int			nl_cache_mngr_add(struct nl_cache_mngr *,
 | 
				
			||||||
 | 
											  const char *,
 | 
				
			||||||
 | 
											  change_func_t,
 | 
				
			||||||
 | 
											  struct nl_cache **);
 | 
				
			||||||
 | 
					extern int			nl_cache_mngr_get_fd(struct nl_cache_mngr *);
 | 
				
			||||||
 | 
					extern int			nl_cache_mngr_poll(struct nl_cache_mngr *,
 | 
				
			||||||
 | 
											   int);
 | 
				
			||||||
 | 
					extern int			nl_cache_mngr_data_ready(struct nl_cache_mngr *);
 | 
				
			||||||
 | 
					extern void			nl_cache_mngr_free(struct nl_cache_mngr *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										41
									
								
								package/libnl-tiny/src/include/netlink/data.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								package/libnl-tiny/src/include/netlink/data.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/data.h	Abstract Data
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_DATA_H_
 | 
				
			||||||
 | 
					#define NETLINK_DATA_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* General */
 | 
				
			||||||
 | 
					extern struct nl_data *	nl_data_alloc(void *, size_t);
 | 
				
			||||||
 | 
					extern struct nl_data * nl_data_alloc_attr(struct nlattr *);
 | 
				
			||||||
 | 
					extern struct nl_data *	nl_data_clone(struct nl_data *);
 | 
				
			||||||
 | 
					extern int		nl_data_append(struct nl_data *, void *, size_t);
 | 
				
			||||||
 | 
					extern void		nl_data_free(struct nl_data *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Access Functions */
 | 
				
			||||||
 | 
					extern void *		nl_data_get(struct nl_data *);
 | 
				
			||||||
 | 
					extern size_t		nl_data_get_size(struct nl_data *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Misc */
 | 
				
			||||||
 | 
					extern int		nl_data_cmp(struct nl_data *, struct nl_data *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										59
									
								
								package/libnl-tiny/src/include/netlink/errno.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								package/libnl-tiny/src/include/netlink/errno.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/errno.h		Error Numbers
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_ERRNO_H_
 | 
				
			||||||
 | 
					#define NETLINK_ERRNO_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLE_SUCCESS		0
 | 
				
			||||||
 | 
					#define NLE_FAILURE		1
 | 
				
			||||||
 | 
					#define NLE_INTR		2
 | 
				
			||||||
 | 
					#define NLE_BAD_SOCK		3
 | 
				
			||||||
 | 
					#define NLE_AGAIN		4
 | 
				
			||||||
 | 
					#define NLE_NOMEM		5
 | 
				
			||||||
 | 
					#define NLE_EXIST		6
 | 
				
			||||||
 | 
					#define NLE_INVAL		7
 | 
				
			||||||
 | 
					#define NLE_RANGE		8
 | 
				
			||||||
 | 
					#define NLE_MSGSIZE		9
 | 
				
			||||||
 | 
					#define NLE_OPNOTSUPP		10
 | 
				
			||||||
 | 
					#define NLE_AF_NOSUPPORT	11
 | 
				
			||||||
 | 
					#define NLE_OBJ_NOTFOUND	12
 | 
				
			||||||
 | 
					#define NLE_NOATTR		13
 | 
				
			||||||
 | 
					#define NLE_MISSING_ATTR	14
 | 
				
			||||||
 | 
					#define NLE_AF_MISMATCH		15
 | 
				
			||||||
 | 
					#define NLE_SEQ_MISMATCH	16
 | 
				
			||||||
 | 
					#define NLE_MSG_OVERFLOW	17
 | 
				
			||||||
 | 
					#define NLE_MSG_TRUNC		18
 | 
				
			||||||
 | 
					#define NLE_NOADDR		19
 | 
				
			||||||
 | 
					#define NLE_SRCRT_NOSUPPORT	20
 | 
				
			||||||
 | 
					#define NLE_MSG_TOOSHORT	21
 | 
				
			||||||
 | 
					#define NLE_MSGTYPE_NOSUPPORT	22
 | 
				
			||||||
 | 
					#define NLE_OBJ_MISMATCH	23
 | 
				
			||||||
 | 
					#define NLE_NOCACHE		24
 | 
				
			||||||
 | 
					#define NLE_BUSY		25
 | 
				
			||||||
 | 
					#define NLE_PROTO_MISMATCH	26
 | 
				
			||||||
 | 
					#define NLE_NOACCESS		27
 | 
				
			||||||
 | 
					#define NLE_PERM		28
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NLE_MAX			NLE_PERM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const char *	nl_geterror(int);
 | 
				
			||||||
 | 
					extern void		nl_perror(int, const char *);
 | 
				
			||||||
 | 
					extern int		nl_syserr2nlerr(int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										37
									
								
								package/libnl-tiny/src/include/netlink/genl/ctrl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								package/libnl-tiny/src/include/netlink/genl/ctrl.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/genl/ctrl.h		Generic Netlink Controller
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_GENL_CTRL_H_
 | 
				
			||||||
 | 
					#define NETLINK_GENL_CTRL_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					#include <netlink/addr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct genl_family;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int			genl_ctrl_alloc_cache(struct nl_sock *,
 | 
				
			||||||
 | 
											      struct nl_cache **);
 | 
				
			||||||
 | 
					extern struct genl_family *	genl_ctrl_search(struct nl_cache *, int);
 | 
				
			||||||
 | 
					extern struct genl_family *	genl_ctrl_search_by_name(struct nl_cache *,
 | 
				
			||||||
 | 
												 const char *);
 | 
				
			||||||
 | 
					extern int			genl_ctrl_resolve(struct nl_sock *,
 | 
				
			||||||
 | 
											  const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										130
									
								
								package/libnl-tiny/src/include/netlink/genl/family.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								package/libnl-tiny/src/include/netlink/genl/family.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,130 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/genl/family.h	Generic Netlink Family
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_GENL_FAMILY_H_
 | 
				
			||||||
 | 
					#define NETLINK_GENL_FAMILY_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					#define FAMILY_ATTR_ID		0x01
 | 
				
			||||||
 | 
					#define FAMILY_ATTR_NAME	0x02
 | 
				
			||||||
 | 
					#define FAMILY_ATTR_VERSION	0x04
 | 
				
			||||||
 | 
					#define FAMILY_ATTR_HDRSIZE	0x08
 | 
				
			||||||
 | 
					#define FAMILY_ATTR_MAXATTR	0x10
 | 
				
			||||||
 | 
					#define FAMILY_ATTR_OPS		0x20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct genl_family
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NLHDR_COMMON
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint16_t		gf_id;
 | 
				
			||||||
 | 
						char 			gf_name[GENL_NAMSIZ];
 | 
				
			||||||
 | 
						uint32_t		gf_version;
 | 
				
			||||||
 | 
						uint32_t		gf_hdrsize;
 | 
				
			||||||
 | 
						uint32_t		gf_maxattr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct nl_list_head	gf_ops;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct genl_family *	genl_family_alloc(void);
 | 
				
			||||||
 | 
					extern void			genl_family_put(struct genl_family *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int			genl_family_add_op(struct genl_family *,
 | 
				
			||||||
 | 
											   int, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Attributes
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int genl_family_get_id(struct genl_family *family)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (family->ce_mask & FAMILY_ATTR_ID)
 | 
				
			||||||
 | 
							return family->gf_id;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return GENL_ID_GENERATE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void genl_family_set_id(struct genl_family *family, unsigned int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						family->gf_id = id;
 | 
				
			||||||
 | 
						family->ce_mask |= FAMILY_ATTR_ID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline char *genl_family_get_name(struct genl_family *family)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (family->ce_mask & FAMILY_ATTR_NAME)
 | 
				
			||||||
 | 
							return family->gf_name;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void genl_family_set_name(struct genl_family *family, const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						strncpy(family->gf_name, name, GENL_NAMSIZ-1);
 | 
				
			||||||
 | 
						family->ce_mask |= FAMILY_ATTR_NAME;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint8_t genl_family_get_version(struct genl_family *family)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (family->ce_mask & FAMILY_ATTR_VERSION)
 | 
				
			||||||
 | 
							return family->gf_version;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void genl_family_set_version(struct genl_family *family, uint8_t version)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						family->gf_version = version;
 | 
				
			||||||
 | 
						family->ce_mask |= FAMILY_ATTR_VERSION;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t genl_family_get_hdrsize(struct genl_family *family)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
 | 
				
			||||||
 | 
							return family->gf_hdrsize;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						family->gf_hdrsize = hdrsize;
 | 
				
			||||||
 | 
						family->ce_mask |= FAMILY_ATTR_HDRSIZE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t genl_family_get_maxattr(struct genl_family *family)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (family->ce_mask & FAMILY_ATTR_MAXATTR)
 | 
				
			||||||
 | 
							return family->gf_maxattr;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return family->gf_maxattr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						family->gf_maxattr = maxattr;
 | 
				
			||||||
 | 
						family->ce_mask |= FAMILY_ATTR_MAXATTR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										47
									
								
								package/libnl-tiny/src/include/netlink/genl/genl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								package/libnl-tiny/src/include/netlink/genl/genl.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/genl/genl.h		Generic Netlink
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_GENL_H_
 | 
				
			||||||
 | 
					#define NETLINK_GENL_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <netlink/attr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		genl_connect(struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		genl_send_simple(struct nl_sock *, int, int,
 | 
				
			||||||
 | 
										 int, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void *		genlmsg_put(struct nl_msg *, uint32_t, uint32_t,
 | 
				
			||||||
 | 
									    int, int, int, uint8_t, uint8_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		genlmsg_valid_hdr(struct nlmsghdr *, int);
 | 
				
			||||||
 | 
					extern int		genlmsg_validate(struct nlmsghdr *, int, int,
 | 
				
			||||||
 | 
										 struct nla_policy *);
 | 
				
			||||||
 | 
					extern int		genlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
 | 
				
			||||||
 | 
									      int, struct nla_policy *);
 | 
				
			||||||
 | 
					extern void *		genlmsg_data(const struct genlmsghdr *);
 | 
				
			||||||
 | 
					extern int		genlmsg_len(const struct genlmsghdr *);
 | 
				
			||||||
 | 
					extern struct nlattr *	genlmsg_attrdata(const struct genlmsghdr *, int);
 | 
				
			||||||
 | 
					extern int		genlmsg_attrlen(const struct genlmsghdr *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char *		genl_op2name(int, int, char *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										87
									
								
								package/libnl-tiny/src/include/netlink/genl/mngt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								package/libnl-tiny/src/include/netlink/genl/mngt.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/genl/mngt.h		Generic Netlink Management
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_GENL_MNGT_H_
 | 
				
			||||||
 | 
					#define NETLINK_GENL_MNGT_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/attr.h>
 | 
				
			||||||
 | 
					#include <netlink/list.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct genl_info
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sockaddr_nl *    who;
 | 
				
			||||||
 | 
						struct nlmsghdr *       nlh;
 | 
				
			||||||
 | 
						struct genlmsghdr *     genlhdr;
 | 
				
			||||||
 | 
						void *                  userhdr;
 | 
				
			||||||
 | 
						struct nlattr **        attrs;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup genl_mngt
 | 
				
			||||||
 | 
					 * Generic Netlink Command
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct genl_cmd
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/** Unique command identifier */
 | 
				
			||||||
 | 
						int			c_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Name/description of command */
 | 
				
			||||||
 | 
						char *			c_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Maximum attribute identifier, must be provided if
 | 
				
			||||||
 | 
						 * a message parser is available.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int			c_maxattr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int		      (*c_msg_parser)(struct nl_cache_ops *,
 | 
				
			||||||
 | 
										      struct genl_cmd *,
 | 
				
			||||||
 | 
										      struct genl_info *, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Attribute validation policy (optional)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						struct nla_policy *	c_attr_policy;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup genl_mngt
 | 
				
			||||||
 | 
					 * Generic Netlink Operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct genl_ops
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int			o_family;
 | 
				
			||||||
 | 
						int			o_id;
 | 
				
			||||||
 | 
						char *			o_name;
 | 
				
			||||||
 | 
						struct nl_cache_ops *	o_cache_ops;
 | 
				
			||||||
 | 
						struct genl_cmd	*	o_cmds;
 | 
				
			||||||
 | 
						int			o_ncmds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* linked list of all genl cache operations */
 | 
				
			||||||
 | 
						struct nl_list_head	o_list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		genl_register(struct nl_cache_ops *);
 | 
				
			||||||
 | 
					extern void		genl_unregister(struct nl_cache_ops *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										230
									
								
								package/libnl-tiny/src/include/netlink/handlers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								package/libnl-tiny/src/include/netlink/handlers.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,230 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/handlers.c	default netlink message handlers
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_HANDLERS_H_
 | 
				
			||||||
 | 
					#define NETLINK_HANDLERS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink-compat.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink-kernel.h>
 | 
				
			||||||
 | 
					#include <netlink/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_sock;
 | 
				
			||||||
 | 
					struct nl_msg;
 | 
				
			||||||
 | 
					struct nl_cb;
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Callback Typedefs
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nl_recvmsgs() callback for message processing customization
 | 
				
			||||||
 | 
					 * @ingroup cb
 | 
				
			||||||
 | 
					 * @arg msg		netlink message being processed
 | 
				
			||||||
 | 
					 * @arg arg		argument passwd on through caller
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nl_recvmsgs() callback for error message processing customization
 | 
				
			||||||
 | 
					 * @ingroup cb
 | 
				
			||||||
 | 
					 * @arg nla		netlink address of the peer
 | 
				
			||||||
 | 
					 * @arg nlerr		netlink error message being processed
 | 
				
			||||||
 | 
					 * @arg arg		argument passed on through caller
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla,
 | 
				
			||||||
 | 
									   struct nlmsgerr *nlerr, void *arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback actions
 | 
				
			||||||
 | 
					 * @ingroup cb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl_cb_action {
 | 
				
			||||||
 | 
						/** Proceed with wathever would come next */
 | 
				
			||||||
 | 
						NL_OK,
 | 
				
			||||||
 | 
						/** Skip this message */
 | 
				
			||||||
 | 
						NL_SKIP,
 | 
				
			||||||
 | 
						/** Stop parsing altogether and discard remaining messages */
 | 
				
			||||||
 | 
						NL_STOP,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback kinds
 | 
				
			||||||
 | 
					 * @ingroup cb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl_cb_kind {
 | 
				
			||||||
 | 
						/** Default handlers (quiet) */
 | 
				
			||||||
 | 
						NL_CB_DEFAULT,
 | 
				
			||||||
 | 
						/** Verbose default handlers (error messages printed) */
 | 
				
			||||||
 | 
						NL_CB_VERBOSE,
 | 
				
			||||||
 | 
						/** Debug handlers for debugging */
 | 
				
			||||||
 | 
						NL_CB_DEBUG,
 | 
				
			||||||
 | 
						/** Customized handler specified by the user */
 | 
				
			||||||
 | 
						NL_CB_CUSTOM,
 | 
				
			||||||
 | 
						__NL_CB_KIND_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback types
 | 
				
			||||||
 | 
					 * @ingroup cb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl_cb_type {
 | 
				
			||||||
 | 
						/** Message is valid */
 | 
				
			||||||
 | 
						NL_CB_VALID,
 | 
				
			||||||
 | 
						/** Last message in a series of multi part messages received */
 | 
				
			||||||
 | 
						NL_CB_FINISH,
 | 
				
			||||||
 | 
						/** Report received that data was lost */
 | 
				
			||||||
 | 
						NL_CB_OVERRUN,
 | 
				
			||||||
 | 
						/** Message wants to be skipped */
 | 
				
			||||||
 | 
						NL_CB_SKIPPED,
 | 
				
			||||||
 | 
						/** Message is an acknowledge */
 | 
				
			||||||
 | 
						NL_CB_ACK,
 | 
				
			||||||
 | 
						/** Called for every message received */
 | 
				
			||||||
 | 
						NL_CB_MSG_IN,
 | 
				
			||||||
 | 
						/** Called for every message sent out except for nl_sendto() */
 | 
				
			||||||
 | 
						NL_CB_MSG_OUT,
 | 
				
			||||||
 | 
						/** Message is malformed and invalid */
 | 
				
			||||||
 | 
						NL_CB_INVALID,
 | 
				
			||||||
 | 
						/** Called instead of internal sequence number checking */
 | 
				
			||||||
 | 
						NL_CB_SEQ_CHECK,
 | 
				
			||||||
 | 
						/** Sending of an acknowledge message has been requested */
 | 
				
			||||||
 | 
						NL_CB_SEND_ACK,
 | 
				
			||||||
 | 
						__NL_CB_TYPE_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cb
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_recvmsg_msg_cb_t	cb_set[NL_CB_TYPE_MAX+1];
 | 
				
			||||||
 | 
						void *			cb_args[NL_CB_TYPE_MAX+1];
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						nl_recvmsg_err_cb_t	cb_err;
 | 
				
			||||||
 | 
						void *			cb_err_arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** May be used to replace nl_recvmsgs with your own implementation
 | 
				
			||||||
 | 
						 * in all internal calls to nl_recvmsgs. */
 | 
				
			||||||
 | 
						int			(*cb_recvmsgs_ow)(struct nl_sock *,
 | 
				
			||||||
 | 
											  struct nl_cb *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Overwrite internal calls to nl_recv, must return the number of
 | 
				
			||||||
 | 
						 * octets read and allocate a buffer for the received data. */
 | 
				
			||||||
 | 
						int			(*cb_recv_ow)(struct nl_sock *,
 | 
				
			||||||
 | 
										      struct sockaddr_nl *,
 | 
				
			||||||
 | 
										      unsigned char **,
 | 
				
			||||||
 | 
										      struct ucred **);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Overwrites internal calls to nl_send, must send the netlink
 | 
				
			||||||
 | 
						 * message. */
 | 
				
			||||||
 | 
						int			(*cb_send_ow)(struct nl_sock *,
 | 
				
			||||||
 | 
										      struct nl_msg *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int			cb_refcnt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct nl_cb *	nl_cb_alloc(enum nl_cb_kind);
 | 
				
			||||||
 | 
					extern struct nl_cb *	nl_cb_clone(struct nl_cb *);
 | 
				
			||||||
 | 
					extern void		nl_cb_put(struct nl_cb *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int  nl_cb_set(struct nl_cb *, enum nl_cb_type, enum nl_cb_kind,
 | 
				
			||||||
 | 
							      nl_recvmsg_msg_cb_t, void *);
 | 
				
			||||||
 | 
					extern int  nl_cb_err(struct nl_cb *, enum nl_cb_kind, nl_recvmsg_err_cb_t,
 | 
				
			||||||
 | 
							      void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct nl_cb *nl_cb_get(struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cb->cb_refcnt++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set up a all callbacks
 | 
				
			||||||
 | 
					 * @arg cb		callback set
 | 
				
			||||||
 | 
					 * @arg kind		kind of callback
 | 
				
			||||||
 | 
					 * @arg func		callback function
 | 
				
			||||||
 | 
					 * @arg arg		argument to be passwd to callback function
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
 | 
				
			||||||
 | 
							  nl_recvmsg_msg_cb_t func, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
 | 
				
			||||||
 | 
							err = nl_cb_set(cb, i, kind, func, arg);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Overwriting
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Overwrite internal calls to nl_recvmsgs()
 | 
				
			||||||
 | 
					 * @arg cb		callback set
 | 
				
			||||||
 | 
					 * @arg func		replacement callback for nl_recvmsgs()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
 | 
				
			||||||
 | 
								      int (*func)(struct nl_sock *, struct nl_cb *))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cb->cb_recvmsgs_ow = func;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Overwrite internal calls to nl_recv()
 | 
				
			||||||
 | 
					 * @arg cb		callback set
 | 
				
			||||||
 | 
					 * @arg func		replacement callback for nl_recv()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_cb_overwrite_recv(struct nl_cb *cb,
 | 
				
			||||||
 | 
								  int (*func)(struct nl_sock *, struct sockaddr_nl *,
 | 
				
			||||||
 | 
									      unsigned char **, struct ucred **))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cb->cb_recv_ow = func;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Overwrite internal calls to nl_send()
 | 
				
			||||||
 | 
					 * @arg cb		callback set
 | 
				
			||||||
 | 
					 * @arg func		replacement callback for nl_send()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_cb_overwrite_send(struct nl_cb *cb,
 | 
				
			||||||
 | 
								  int (*func)(struct nl_sock *, struct nl_msg *))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cb->cb_send_ow = func;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										88
									
								
								package/libnl-tiny/src/include/netlink/list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								package/libnl-tiny/src/include/netlink/list.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/list.h	Netlink List Utilities
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_LIST_H_
 | 
				
			||||||
 | 
					#define NETLINK_LIST_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_list_head
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_list_head *	next;
 | 
				
			||||||
 | 
						struct nl_list_head *	prev;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void __nl_list_add(struct nl_list_head *obj,
 | 
				
			||||||
 | 
									 struct nl_list_head *prev,
 | 
				
			||||||
 | 
									 struct nl_list_head *next)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						prev->next = obj;
 | 
				
			||||||
 | 
						obj->prev = prev;
 | 
				
			||||||
 | 
						next->prev = obj;
 | 
				
			||||||
 | 
						obj->next = next;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nl_list_add_tail(struct nl_list_head *obj,
 | 
				
			||||||
 | 
									    struct nl_list_head *head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__nl_list_add(obj, head->prev, head);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nl_list_add_head(struct nl_list_head *obj,
 | 
				
			||||||
 | 
									    struct nl_list_head *head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__nl_list_add(obj, head, head->next);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nl_list_del(struct nl_list_head *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						obj->next->prev = obj->prev;
 | 
				
			||||||
 | 
						obj->prev->next = obj->next;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nl_list_empty(struct nl_list_head *head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return head->next == head;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_container_of(ptr, type, member) ({			\
 | 
				
			||||||
 | 
					        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
 | 
				
			||||||
 | 
					        (type *)( (char *)__mptr - ((size_t) &((type *)0)->member));})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_list_entry(ptr, type, member) \
 | 
				
			||||||
 | 
						nl_container_of(ptr, type, member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_list_at_tail(pos, head, member) \
 | 
				
			||||||
 | 
						((pos)->member.next == (head))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_list_at_head(pos, head, member) \
 | 
				
			||||||
 | 
						((pos)->member.prev == (head))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_LIST_HEAD(name) \
 | 
				
			||||||
 | 
						struct nl_list_head name = { &(name), &(name) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_list_first_entry(head, type, member)			\
 | 
				
			||||||
 | 
						nl_list_entry((head)->next, type, member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_list_for_each_entry(pos, head, member)				\
 | 
				
			||||||
 | 
						for (pos = nl_list_entry((head)->next, typeof(*pos), member);	\
 | 
				
			||||||
 | 
						     &(pos)->member != (head); 	\
 | 
				
			||||||
 | 
						     (pos) = nl_list_entry((pos)->member.next, typeof(*(pos)), member))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_list_for_each_entry_safe(pos, n, head, member)			\
 | 
				
			||||||
 | 
						for (pos = nl_list_entry((head)->next, typeof(*pos), member),	\
 | 
				
			||||||
 | 
							n = nl_list_entry(pos->member.next, typeof(*pos), member);	\
 | 
				
			||||||
 | 
						     &(pos)->member != (head); 					\
 | 
				
			||||||
 | 
						     pos = n, n = nl_list_entry(n->member.next, typeof(*n), member))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define nl_init_list_head(head) \
 | 
				
			||||||
 | 
						do { (head)->next = (head); (head)->prev = (head); } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										308
									
								
								package/libnl-tiny/src/include/netlink/msg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								package/libnl-tiny/src/include/netlink/msg.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,308 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/msg.c		Netlink Messages Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_MSG_H_
 | 
				
			||||||
 | 
					#define NETLINK_MSG_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/object.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nla_policy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_DONTPAD	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 * @brief
 | 
				
			||||||
 | 
					 * Will cause the netlink pid to be set to the pid assigned to
 | 
				
			||||||
 | 
					 * the netlink handle (socket) just before sending the message off.
 | 
				
			||||||
 | 
					 * @note Requires the use of nl_send_auto_complete()!
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NL_AUTO_PID	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 * @brief
 | 
				
			||||||
 | 
					 * May be used to refer to a sequence number which should be
 | 
				
			||||||
 | 
					 * automatically set just before sending the message off.
 | 
				
			||||||
 | 
					 * @note Requires the use of nl_send_auto_complete()!
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NL_AUTO_SEQ	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_MSG_CRED_PRESENT 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_msg
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int			nm_protocol;
 | 
				
			||||||
 | 
						int			nm_flags;
 | 
				
			||||||
 | 
						struct sockaddr_nl	nm_src;
 | 
				
			||||||
 | 
						struct sockaddr_nl	nm_dst;
 | 
				
			||||||
 | 
						struct ucred		nm_creds;
 | 
				
			||||||
 | 
						struct nlmsghdr *	nm_nlh;
 | 
				
			||||||
 | 
						size_t			nm_size;
 | 
				
			||||||
 | 
						int			nm_refcnt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_msg;
 | 
				
			||||||
 | 
					struct nl_tree;
 | 
				
			||||||
 | 
					struct ucred;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* message parsing */
 | 
				
			||||||
 | 
					extern int		  nlmsg_ok(const struct nlmsghdr *, int);
 | 
				
			||||||
 | 
					extern struct nlmsghdr *  nlmsg_next(struct nlmsghdr *, int *);
 | 
				
			||||||
 | 
					extern int		  nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
 | 
				
			||||||
 | 
									      int, struct nla_policy *);
 | 
				
			||||||
 | 
					extern int		  nlmsg_validate(struct nlmsghdr *, int, int,
 | 
				
			||||||
 | 
										 struct nla_policy *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct nl_msg *	  nlmsg_alloc(void);
 | 
				
			||||||
 | 
					extern struct nl_msg *	  nlmsg_alloc_size(size_t);
 | 
				
			||||||
 | 
					extern struct nl_msg *	  nlmsg_alloc_simple(int, int);
 | 
				
			||||||
 | 
					extern void		  nlmsg_set_default_size(size_t);
 | 
				
			||||||
 | 
					extern struct nl_msg *	  nlmsg_inherit(struct nlmsghdr *);
 | 
				
			||||||
 | 
					extern struct nl_msg *	  nlmsg_convert(struct nlmsghdr *);
 | 
				
			||||||
 | 
					extern void *		  nlmsg_reserve(struct nl_msg *, size_t, int);
 | 
				
			||||||
 | 
					extern int		  nlmsg_append(struct nl_msg *, void *, size_t, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct nlmsghdr *  nlmsg_put(struct nl_msg *, uint32_t, uint32_t,
 | 
				
			||||||
 | 
									    int, int, int);
 | 
				
			||||||
 | 
					extern void		  nlmsg_free(struct nl_msg *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		  nl_msg_parse(struct nl_msg *,
 | 
				
			||||||
 | 
									       void (*cb)(struct nl_object *, void *),
 | 
				
			||||||
 | 
									       void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void		nl_msg_dump(struct nl_msg *, FILE *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * length of netlink message not including padding
 | 
				
			||||||
 | 
					 * @arg payload		length of message payload
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nlmsg_msg_size(int payload)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NLMSG_HDRLEN + payload;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * length of netlink message including padding
 | 
				
			||||||
 | 
					 * @arg payload		length of message payload
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nlmsg_total_size(int payload)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NLMSG_ALIGN(nlmsg_msg_size(payload));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * length of padding at the message's tail
 | 
				
			||||||
 | 
					 * @arg payload		length of message payload
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nlmsg_padlen(int payload)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nlmsg_total_size(payload) - nlmsg_msg_size(payload);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * head of message payload
 | 
				
			||||||
 | 
					 * @arg nlh		netlink messsage header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void *nlmsg_data(const struct nlmsghdr *nlh)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (unsigned char *) nlh + NLMSG_HDRLEN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void *nlmsg_tail(const struct nlmsghdr *nlh)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * length of message payload
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nlmsg_len(const struct nlmsghdr *nlh)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nlh->nlmsg_len - NLMSG_HDRLEN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * head of attributes data
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen		length of family specific header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char *data = nlmsg_data(nlh);
 | 
				
			||||||
 | 
						return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * length of attributes data
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen		length of family specific header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nlmsg_set_proto(struct nl_msg *msg, int protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						msg->nm_protocol = protocol;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nlmsg_get_proto(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return msg->nm_protocol;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline size_t nlmsg_get_max_size(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return msg->nm_size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memcpy(&msg->nm_src, addr, sizeof(*addr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct sockaddr_nl *nlmsg_get_src(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return &msg->nm_src;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nlmsg_set_dst(struct nl_msg *msg, struct sockaddr_nl *addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memcpy(&msg->nm_dst, addr, sizeof(*addr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return &msg->nm_dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memcpy(&msg->nm_creds, creds, sizeof(*creds));
 | 
				
			||||||
 | 
						msg->nm_flags |= NL_MSG_CRED_PRESENT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct ucred *nlmsg_get_creds(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (msg->nm_flags & NL_MSG_CRED_PRESENT)
 | 
				
			||||||
 | 
							return &msg->nm_creds;
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return actual netlink message
 | 
				
			||||||
 | 
					 * @arg n		netlink message
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Returns the actual netlink message casted to the type of the netlink
 | 
				
			||||||
 | 
					 * message header.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @return A pointer to the netlink message.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline struct nlmsghdr *nlmsg_hdr(struct nl_msg *n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return n->nm_nlh;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Acquire a reference on a netlink message
 | 
				
			||||||
 | 
					 * @arg msg		message to acquire reference from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nlmsg_get(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						msg->nm_refcnt++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Expand maximum payload size of a netlink message
 | 
				
			||||||
 | 
					 * @arg n		Netlink message.
 | 
				
			||||||
 | 
					 * @arg newlen		New maximum payload size.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reallocates the payload section of a netlink message and increases
 | 
				
			||||||
 | 
					 * the maximum payload size of the message.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note Any pointers pointing to old payload block will be stale and
 | 
				
			||||||
 | 
					 *       need to be refetched. Therfore, do not expand while constructing
 | 
				
			||||||
 | 
					 *       nested attributes or while reserved data blocks are held.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nlmsg_expand(struct nl_msg *n, size_t newlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (newlen <= n->nm_size)
 | 
				
			||||||
 | 
							return -NLE_INVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmp = realloc(n->nm_nlh, newlen);
 | 
				
			||||||
 | 
						if (tmp == NULL)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->nm_nlh = tmp;
 | 
				
			||||||
 | 
						n->nm_size = newlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Iterators
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 * Iterate over a stream of attributes in a message
 | 
				
			||||||
 | 
					 * @arg pos	loop counter, set to current attribute
 | 
				
			||||||
 | 
					 * @arg nlh	netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen	length of family header
 | 
				
			||||||
 | 
					 * @arg rem	initialized to len, holds bytes currently remaining in stream
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
 | 
				
			||||||
 | 
						nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
 | 
				
			||||||
 | 
								  nlmsg_attrlen(nlh, hdrlen), rem)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Iterate over a stream of messages
 | 
				
			||||||
 | 
					 * @arg pos	loop counter, set to current message
 | 
				
			||||||
 | 
					 * @arg head	head of message stream
 | 
				
			||||||
 | 
					 * @arg len	length of message stream
 | 
				
			||||||
 | 
					 * @arg rem	initialized to len, holds bytes currently remaining in stream
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define nlmsg_for_each_msg(pos, head, len, rem) \
 | 
				
			||||||
 | 
						for (pos = head, rem = len; \
 | 
				
			||||||
 | 
						     nlmsg_ok(pos, rem); \
 | 
				
			||||||
 | 
						     pos = nlmsg_next(pos, &(rem)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										50
									
								
								package/libnl-tiny/src/include/netlink/netlink-compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								package/libnl-tiny/src/include/netlink/netlink-compat.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/netlink-compat.h	Netlink Compatability
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_COMPAT_H_
 | 
				
			||||||
 | 
					#define NETLINK_COMPAT_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined _LINUX_SOCKET_H && !defined _BITS_SOCKADDR_H
 | 
				
			||||||
 | 
					typedef unsigned short  sa_family_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef IFNAMSIZ 
 | 
				
			||||||
 | 
					/** Maximum length of a interface name */
 | 
				
			||||||
 | 
					#define IFNAMSIZ 16
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* patch 2.4.x if_arp */
 | 
				
			||||||
 | 
					#ifndef ARPHRD_INFINIBAND
 | 
				
			||||||
 | 
					#define ARPHRD_INFINIBAND 32
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* patch 2.4.x eth header file */
 | 
				
			||||||
 | 
					#ifndef ETH_P_MPLS_UC
 | 
				
			||||||
 | 
					#define ETH_P_MPLS_UC  0x8847 
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ETH_P_MPLS_MC
 | 
				
			||||||
 | 
					#define ETH_P_MPLS_MC   0x8848
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef  ETH_P_EDP2
 | 
				
			||||||
 | 
					#define ETH_P_EDP2      0x88A2
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ETH_P_HDLC
 | 
				
			||||||
 | 
					#define ETH_P_HDLC      0x0019 
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef AF_LLC
 | 
				
			||||||
 | 
					#define AF_LLC		26
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										196
									
								
								package/libnl-tiny/src/include/netlink/netlink-kernel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								package/libnl-tiny/src/include/netlink/netlink-kernel.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,196 @@
 | 
				
			|||||||
 | 
					#ifndef __LINUX_NETLINK_H
 | 
				
			||||||
 | 
					#define __LINUX_NETLINK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Netlink socket address
 | 
				
			||||||
 | 
					 * @ingroup nl
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sockaddr_nl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/** socket family (AF_NETLINK) */
 | 
				
			||||||
 | 
						sa_family_t     nl_family;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Padding (unused) */
 | 
				
			||||||
 | 
						unsigned short  nl_pad;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Unique process ID  */
 | 
				
			||||||
 | 
						uint32_t        nl_pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Multicast group subscriptions */
 | 
				
			||||||
 | 
						uint32_t        nl_groups;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Netlink message header
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlmsghdr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Length of message including header.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint32_t	nlmsg_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Message type (content type)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint16_t	nlmsg_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Message flags
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint16_t	nlmsg_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Sequence number
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint32_t	nlmsg_seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Netlink PID of the proccess sending the message.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint32_t	nlmsg_pid;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Standard message flags
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Must be set on all request messages (typically from user space to
 | 
				
			||||||
 | 
					 * kernel space).
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_REQUEST		1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Indicates the message is part of a multipart message terminated
 | 
				
			||||||
 | 
					 * by NLMSG_DONE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_MULTI		2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Request for an acknowledgment on success.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_ACK		4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Echo this request
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_ECHO		8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Additional message flags for GET requests
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the complete table instead of a single entry.
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_ROOT	0x100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return all entries matching criteria passed in message content.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_MATCH	0x200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return an atomic snapshot of the table being referenced. This
 | 
				
			||||||
 | 
					 * may require special privileges because it has the potential to
 | 
				
			||||||
 | 
					 * interrupt service in the FE for a longer time.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_ATOMIC	0x400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dump all entries
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_DUMP	(NLM_F_ROOT|NLM_F_MATCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Additional messsage flags for NEW requests
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Replace existing matching config object with this request.
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_REPLACE	0x100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Don't replace the config object if it already exists.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_EXCL	0x200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Create config object if it doesn't already exist.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_CREATE	0x400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add to the end of the object list.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLM_F_APPEND	0x800
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Standard Message types
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * No operation, message must be ignored
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLMSG_NOOP		0x1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The message signals an error and the payload contains a nlmsgerr
 | 
				
			||||||
 | 
					 * structure. This can be looked at as a NACK and typically it is
 | 
				
			||||||
 | 
					 * from FEC to CPC.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLMSG_ERROR		0x2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Message terminates a multipart message.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLMSG_DONE		0x3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The message signals that data got lost
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLMSG_OVERRUN		0x4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Lower limit of reserved message types
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLMSG_MIN_TYPE		0x10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Netlink error message
 | 
				
			||||||
 | 
					 * @ingroup msg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlmsgerr
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/** Error code (errno number) */
 | 
				
			||||||
 | 
						int		error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Original netlink message causing the error */
 | 
				
			||||||
 | 
						struct nlmsghdr	msg;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_pktinfo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u32	group;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif	/* __LINUX_NETLINK_H */
 | 
				
			||||||
							
								
								
									
										82
									
								
								package/libnl-tiny/src/include/netlink/netlink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								package/libnl-tiny/src/include/netlink/netlink.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/netlink.h		Netlink Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_NETLINK_H_
 | 
				
			||||||
 | 
					#define NETLINK_NETLINK_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <sys/poll.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink-compat.h>
 | 
				
			||||||
 | 
					#include <linux/netlink.h>
 | 
				
			||||||
 | 
					#include <linux/genetlink.h>
 | 
				
			||||||
 | 
					#include <netlink/version.h>
 | 
				
			||||||
 | 
					#include <netlink/errno.h>
 | 
				
			||||||
 | 
					#include <netlink/types.h>
 | 
				
			||||||
 | 
					#include <netlink/handlers.h>
 | 
				
			||||||
 | 
					#include <netlink/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int nl_debug;
 | 
				
			||||||
 | 
					extern struct nl_dump_params nl_debug_dp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Connection Management */
 | 
				
			||||||
 | 
					extern int			nl_connect(struct nl_sock *, int);
 | 
				
			||||||
 | 
					extern void			nl_close(struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Send */
 | 
				
			||||||
 | 
					extern int			nl_sendto(struct nl_sock *, void *, size_t);
 | 
				
			||||||
 | 
					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_auto_complete(struct nl_sock *,
 | 
				
			||||||
 | 
											      struct nl_msg *);
 | 
				
			||||||
 | 
					extern int			nl_send_simple(struct nl_sock *, int, int,
 | 
				
			||||||
 | 
										       void *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Receive */
 | 
				
			||||||
 | 
					extern int			nl_recv(struct nl_sock *,
 | 
				
			||||||
 | 
										struct sockaddr_nl *, unsigned char **,
 | 
				
			||||||
 | 
										struct ucred **);
 | 
				
			||||||
 | 
					extern int			nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int			nl_wait_for_ack(struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Netlink Family Translations */
 | 
				
			||||||
 | 
					extern char *			nl_nlfamily2str(int, char *, size_t);
 | 
				
			||||||
 | 
					extern int			nl_str2nlfamily(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Receive a set of message from a netlink socket using handlers in nl_sock.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Calls nl_recvmsgs() with the handlers configured in the netlink socket.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nl_recvmsgs_default(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_recvmsgs(sk, sk->s_cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										331
									
								
								package/libnl-tiny/src/include/netlink/object-api.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								package/libnl-tiny/src/include/netlink/object-api.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,331 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/object-api.c		Object API
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2007 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_OBJECT_API_H_
 | 
				
			||||||
 | 
					#define NETLINK_OBJECT_API_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup object
 | 
				
			||||||
 | 
					 * @defgroup object_api Object API
 | 
				
			||||||
 | 
					 * @brief
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 1) Object Definition
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Define your object starting with the common object header
 | 
				
			||||||
 | 
					 * struct my_obj {
 | 
				
			||||||
 | 
					 * 	NLHDR_COMMON
 | 
				
			||||||
 | 
					 * 	int		my_data;
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Fill out the object operations structure
 | 
				
			||||||
 | 
					 * struct nl_object_ops my_ops = {
 | 
				
			||||||
 | 
					 * 	.oo_name	= "my_obj",
 | 
				
			||||||
 | 
					 * 	.oo_size	= sizeof(struct my_obj),
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // At this point the object can be allocated, you may want to provide a
 | 
				
			||||||
 | 
					 * // separate _alloc() function to ease allocting objects of this kind.
 | 
				
			||||||
 | 
					 * struct nl_object *obj = nl_object_alloc(&my_ops);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // And release it again...
 | 
				
			||||||
 | 
					 * nl_object_put(obj);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 2) Allocating additional data
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // You may require to allocate additional data and store it inside
 | 
				
			||||||
 | 
					 * // object, f.e. assuming there is a field `ptr'.
 | 
				
			||||||
 | 
					 * struct my_obj {
 | 
				
			||||||
 | 
					 * 	NLHDR_COMMON
 | 
				
			||||||
 | 
					 * 	void *		ptr;
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // And at some point you may assign allocated data to this field:
 | 
				
			||||||
 | 
					 * my_obj->ptr = calloc(1, ...);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // In order to not introduce any memory leaks you have to release
 | 
				
			||||||
 | 
					 * // this data again when the last reference is given back.
 | 
				
			||||||
 | 
					 * static void my_obj_free_data(struct nl_object *obj)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	struct my_obj *my_obj = nl_object_priv(obj);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	free(my_obj->ptr);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Also when the object is cloned, you must ensure for your pointer
 | 
				
			||||||
 | 
					 * // stay valid even if one of the clones is freed by either making
 | 
				
			||||||
 | 
					 * // a clone as well or increase the reference count.
 | 
				
			||||||
 | 
					 * static int my_obj_clone(struct nl_object *src, struct nl_object *dst)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	struct my_obj *my_src = nl_object_priv(src);
 | 
				
			||||||
 | 
					 * 	struct my_obj *my_dst = nl_object_priv(dst);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	if (src->ptr) {
 | 
				
			||||||
 | 
					 * 		dst->ptr = calloc(1, ...);
 | 
				
			||||||
 | 
					 * 		memcpy(dst->ptr, src->ptr, ...);
 | 
				
			||||||
 | 
					 * 	}
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * struct nl_object_ops my_ops = {
 | 
				
			||||||
 | 
					 * 	...
 | 
				
			||||||
 | 
					 * 	.oo_free_data	= my_obj_free_data,
 | 
				
			||||||
 | 
					 * 	.oo_clone	= my_obj_clone,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 3) Object Dumping
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * static int my_obj_dump_detailed(struct nl_object *obj,
 | 
				
			||||||
 | 
					 * 				   struct nl_dump_params *params)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	struct my_obj *my_obj = nl_object_priv(obj);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	// It is absolutely essential to use nl_dump() when printing
 | 
				
			||||||
 | 
					 *	// any text to make sure the dumping parameters are respected.
 | 
				
			||||||
 | 
					 * 	nl_dump(params, "Obj Integer: %d\n", my_obj->my_int);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	// Before we can dump the next line, make sure to prefix
 | 
				
			||||||
 | 
					 *	// this line correctly.
 | 
				
			||||||
 | 
					 * 	nl_new_line(params);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	// You may also split a line into multiple nl_dump() calls.
 | 
				
			||||||
 | 
					 * 	nl_dump(params, "String: %s ", my_obj->my_string);
 | 
				
			||||||
 | 
					 * 	nl_dump(params, "String-2: %s\n", my_obj->another_string);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * struct nl_object_ops my_ops = {
 | 
				
			||||||
 | 
					 * 	...
 | 
				
			||||||
 | 
					 * 	.oo_dump[NL_DUMP_FULL]	= my_obj_dump_detailed,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 4) Object Attributes
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // The concept of object attributes is optional but can ease the typical
 | 
				
			||||||
 | 
					 * // case of objects that have optional attributes, e.g. a route may have a
 | 
				
			||||||
 | 
					 * // nexthop assigned but it is not required to.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // The first step to define your object specific bitmask listing all
 | 
				
			||||||
 | 
					 * // attributes
 | 
				
			||||||
 | 
					 * #define MY_ATTR_FOO		(1<<0)
 | 
				
			||||||
 | 
					 * #define MY_ATTR_BAR		(1<<1)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // When assigning an optional attribute to the object, make sure
 | 
				
			||||||
 | 
					 * // to mark its availability.
 | 
				
			||||||
 | 
					 * my_obj->foo = 123123;
 | 
				
			||||||
 | 
					 * my_obj->ce_mask |= MY_ATTR_FOO;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // At any time you may use this mask to check for the availability
 | 
				
			||||||
 | 
					 * // of the attribute, e.g. while dumping
 | 
				
			||||||
 | 
					 * if (my_obj->ce_mask & MY_ATTR_FOO)
 | 
				
			||||||
 | 
					 * 	nl_dump(params, "foo %d ", my_obj->foo);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // One of the big advantages of this concept is that it allows for
 | 
				
			||||||
 | 
					 * // standardized comparisons which make it trivial for caches to
 | 
				
			||||||
 | 
					 * // identify unique objects by use of unified comparison functions.
 | 
				
			||||||
 | 
					 * // In order for it to work, your object implementation must provide
 | 
				
			||||||
 | 
					 * // a comparison function and define a list of attributes which
 | 
				
			||||||
 | 
					 * // combined together make an object unique.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
 | 
				
			||||||
 | 
					 * 			     uint32_t attrs, int flags)
 | 
				
			||||||
 | 
					 * {
 | 
				
			||||||
 | 
					 * 	struct my_obj *a = nl_object_priv(_a):
 | 
				
			||||||
 | 
					 * 	struct my_obj *b = nl_object_priv(_b):
 | 
				
			||||||
 | 
					 * 	int diff = 0;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	// We help ourselves in defining our own DIFF macro which will
 | 
				
			||||||
 | 
					 *	// call ATTR_DIFF() on both objects which will make sure to only
 | 
				
			||||||
 | 
					 *	// compare the attributes if required.
 | 
				
			||||||
 | 
					 * 	#define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	// Call our own diff macro for each attribute to build a bitmask
 | 
				
			||||||
 | 
					 *	// representing the attributes which mismatch.
 | 
				
			||||||
 | 
					 * 	diff |= MY_DIFF(FOO, a->foo != b->foo)
 | 
				
			||||||
 | 
					 * 	diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 	return diff;
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // In order to identify identical objects with differing attributes
 | 
				
			||||||
 | 
					 * // you must specify the attributes required to uniquely identify
 | 
				
			||||||
 | 
					 * // your object. Make sure to not include too many attributes, this
 | 
				
			||||||
 | 
					 * // list is used when caches look for an old version of an object.
 | 
				
			||||||
 | 
					 * struct nl_object_ops my_ops = {
 | 
				
			||||||
 | 
					 * 	...
 | 
				
			||||||
 | 
					 * 	.oo_id_attrs		= MY_ATTR_FOO,
 | 
				
			||||||
 | 
					 * 	.oo_compare		= my_obj_compare,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Common Object Header
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This macro must be included as first member in every object
 | 
				
			||||||
 | 
					 * definition to allow objects to be cached.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NLHDR_COMMON				\
 | 
				
			||||||
 | 
						int			ce_refcnt;	\
 | 
				
			||||||
 | 
						struct nl_object_ops *	ce_ops;		\
 | 
				
			||||||
 | 
						struct nl_cache *	ce_cache;	\
 | 
				
			||||||
 | 
						struct nl_list_head	ce_list;	\
 | 
				
			||||||
 | 
						int			ce_msgtype;	\
 | 
				
			||||||
 | 
						int			ce_flags;	\
 | 
				
			||||||
 | 
						uint32_t		ce_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return true if attribute is available in both objects
 | 
				
			||||||
 | 
					 * @arg A		an object
 | 
				
			||||||
 | 
					 * @arg B		another object
 | 
				
			||||||
 | 
					 * @arg ATTR		attribute bit
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return True if the attribute is available, otherwise false is returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define AVAILABLE(A, B, ATTR)	(((A)->ce_mask & (B)->ce_mask) & (ATTR))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return true if attributes mismatch
 | 
				
			||||||
 | 
					 * @arg A		an object
 | 
				
			||||||
 | 
					 * @arg B		another object
 | 
				
			||||||
 | 
					 * @arg ATTR		attribute bit
 | 
				
			||||||
 | 
					 * @arg EXPR		Comparison expression
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function will check if the attribute in question is available
 | 
				
			||||||
 | 
					 * in both objects, if not this will count as a mismatch.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If available the function will execute the expression which must
 | 
				
			||||||
 | 
					 * return true if the attributes mismatch.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return True if the attribute mismatch, or false if they match.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ATTR_MISMATCH(A, B, ATTR, EXPR)	(!AVAILABLE(A, B, ATTR) || (EXPR))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return attribute bit if attribute does not match
 | 
				
			||||||
 | 
					 * @arg LIST		list of attributes to be compared
 | 
				
			||||||
 | 
					 * @arg ATTR		attribute bit
 | 
				
			||||||
 | 
					 * @arg A		an object
 | 
				
			||||||
 | 
					 * @arg B		another object
 | 
				
			||||||
 | 
					 * @arg EXPR		Comparison expression
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function will check if the attribute in question is available
 | 
				
			||||||
 | 
					 * in both objects, if not this will count as a mismatch.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If available the function will execute the expression which must
 | 
				
			||||||
 | 
					 * return true if the attributes mismatch.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * In case the attributes mismatch, the attribute is returned, otherwise
 | 
				
			||||||
 | 
					 * 0 is returned.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
 | 
				
			||||||
 | 
					({	int diff = 0; \
 | 
				
			||||||
 | 
						if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
 | 
				
			||||||
 | 
							diff = ATTR; \
 | 
				
			||||||
 | 
						diff; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Object Operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object;
 | 
				
			||||||
 | 
					struct nl_object_ops
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Unique name of object type
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Must be in the form family/name, e.g. "route/addr"
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						char *		oo_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Size of object including its header */
 | 
				
			||||||
 | 
						size_t		oo_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* List of attributes needed to uniquely identify the object */
 | 
				
			||||||
 | 
						uint32_t	oo_id_attrs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Constructor function
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Will be called when a new object of this type is allocated.
 | 
				
			||||||
 | 
						 * Can be used to initialize members such as lists etc.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void  (*oo_constructor)(struct nl_object *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Destructor function
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Will be called when an object is freed. Must free all
 | 
				
			||||||
 | 
						 * resources which may have been allocated as part of this
 | 
				
			||||||
 | 
						 * object.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void  (*oo_free_data)(struct nl_object *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Cloning function
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Will be called when an object needs to be cloned. Please
 | 
				
			||||||
 | 
						 * note that the generic object code will make an exact
 | 
				
			||||||
 | 
						 * copy of the object first, therefore you only need to take
 | 
				
			||||||
 | 
						 * care of members which require reference counting etc.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * May return a negative error code to abort cloning.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int  (*oo_clone)(struct nl_object *, struct nl_object *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Dumping functions
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Will be called when an object is dumped. The implementations
 | 
				
			||||||
 | 
						 * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
 | 
				
			||||||
 | 
						 * dump objects.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * The functions must return the number of lines printed.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
 | 
				
			||||||
 | 
									       struct nl_dump_params *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Comparison function
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Will be called when two objects of the same type are
 | 
				
			||||||
 | 
						 * compared. It takes the two objects in question, an object
 | 
				
			||||||
 | 
						 * specific bitmask defining which attributes should be
 | 
				
			||||||
 | 
						 * compared and flags to control the behaviour.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * The function must return a bitmask with the relevant bit
 | 
				
			||||||
 | 
						 * set for each attribute that mismatches.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int   (*oo_compare)(struct nl_object *, struct nl_object *,
 | 
				
			||||||
 | 
								    uint32_t, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *(*oo_attrs2str)(int, char *, size_t);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										144
									
								
								package/libnl-tiny/src/include/netlink/object.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								package/libnl-tiny/src/include/netlink/object.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/object.c	Generic Cacheable Object
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_OBJECT_H_
 | 
				
			||||||
 | 
					#define NETLINK_OBJECT_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/object-api.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_OBJ_MARK		1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cache;
 | 
				
			||||||
 | 
					struct nl_object;
 | 
				
			||||||
 | 
					struct nl_object_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_object
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NLHDR_COMMON
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OBJ_CAST(ptr)		((struct nl_object *) (ptr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* General */
 | 
				
			||||||
 | 
					extern struct nl_object *	nl_object_alloc(struct nl_object_ops *);
 | 
				
			||||||
 | 
					extern int			nl_object_alloc_name(const char *,
 | 
				
			||||||
 | 
											     struct nl_object **);
 | 
				
			||||||
 | 
					extern void			nl_object_free(struct nl_object *);
 | 
				
			||||||
 | 
					extern struct nl_object *	nl_object_clone(struct nl_object *obj);
 | 
				
			||||||
 | 
					extern void			nl_object_get(struct nl_object *);
 | 
				
			||||||
 | 
					extern void			nl_object_put(struct nl_object *);
 | 
				
			||||||
 | 
					extern void			nl_object_dump(struct nl_object *,
 | 
				
			||||||
 | 
										       struct nl_dump_params *);
 | 
				
			||||||
 | 
					extern int			nl_object_identical(struct nl_object *,
 | 
				
			||||||
 | 
											    struct nl_object *);
 | 
				
			||||||
 | 
					extern uint32_t			nl_object_diff(struct nl_object *,
 | 
				
			||||||
 | 
										       struct nl_object *);
 | 
				
			||||||
 | 
					extern int			nl_object_match_filter(struct nl_object *,
 | 
				
			||||||
 | 
											       struct nl_object *);
 | 
				
			||||||
 | 
					extern char *			nl_object_attrs2str(struct nl_object *,
 | 
				
			||||||
 | 
											    uint32_t attrs, char *buf,
 | 
				
			||||||
 | 
											    size_t);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check whether this object is used by multiple users
 | 
				
			||||||
 | 
					 * @arg obj		object to check
 | 
				
			||||||
 | 
					 * @return true or false
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nl_object_shared(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return obj->ce_refcnt > 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Marks
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add mark to object
 | 
				
			||||||
 | 
					 * @arg obj		Object to mark
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_object_mark(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						obj->ce_flags |= NL_OBJ_MARK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Remove mark from object
 | 
				
			||||||
 | 
					 * @arg obj		Object to unmark
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_object_unmark(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						obj->ce_flags &= ~NL_OBJ_MARK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return true if object is marked
 | 
				
			||||||
 | 
					 * @arg obj		Object to check
 | 
				
			||||||
 | 
					 * @return true if object is marked, otherwise false
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nl_object_is_marked(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (obj->ce_flags & NL_OBJ_MARK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return list of attributes present in an object
 | 
				
			||||||
 | 
					 * @arg obj		an object
 | 
				
			||||||
 | 
					 * @arg buf		destination buffer
 | 
				
			||||||
 | 
					 * @arg len		length of destination buffer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return destination buffer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Attributes
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nl_object_get_refcnt(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return obj->ce_refcnt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct nl_cache *nl_object_get_cache(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return obj->ce_cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void *		nl_object_priv(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return obj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										221
									
								
								package/libnl-tiny/src/include/netlink/socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								package/libnl-tiny/src/include/netlink/socket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,221 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/socket.h		Netlink Socket
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_SOCKET_H_
 | 
				
			||||||
 | 
					#define NETLINK_SOCKET_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/types.h>
 | 
				
			||||||
 | 
					#include <netlink/handlers.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_SOCK_BUFSIZE_SET	(1<<0)
 | 
				
			||||||
 | 
					#define NL_SOCK_PASSCRED	(1<<1)
 | 
				
			||||||
 | 
					#define NL_OWN_PORT		(1<<2)
 | 
				
			||||||
 | 
					#define NL_MSG_PEEK		(1<<3)
 | 
				
			||||||
 | 
					#define NL_NO_AUTO_ACK		(1<<4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_cb;
 | 
				
			||||||
 | 
					struct nl_sock
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sockaddr_nl	s_local;
 | 
				
			||||||
 | 
						struct sockaddr_nl	s_peer;
 | 
				
			||||||
 | 
						int			s_fd;
 | 
				
			||||||
 | 
						int			s_proto;
 | 
				
			||||||
 | 
						unsigned int		s_seq_next;
 | 
				
			||||||
 | 
						unsigned int		s_seq_expect;
 | 
				
			||||||
 | 
						int			s_flags;
 | 
				
			||||||
 | 
						struct nl_cb *		s_cb;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct nl_sock *	nl_socket_alloc(void);
 | 
				
			||||||
 | 
					extern struct nl_sock *	nl_socket_alloc_cb(struct nl_cb *);
 | 
				
			||||||
 | 
					extern void		nl_socket_free(struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void		nl_socket_set_local_port(struct nl_sock *, uint32_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		nl_socket_add_memberships(struct nl_sock *, int, ...);
 | 
				
			||||||
 | 
					extern int		nl_socket_drop_memberships(struct nl_sock *, int, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		nl_socket_set_buffer_size(struct nl_sock *, int, int);
 | 
				
			||||||
 | 
					extern int		nl_socket_set_passcred(struct nl_sock *, int);
 | 
				
			||||||
 | 
					extern int		nl_socket_recv_pktinfo(struct nl_sock *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void		nl_socket_disable_seq_check(struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int		nl_socket_set_nonblocking(struct nl_sock *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Use next sequence number
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Uses the next available sequence number and increases the counter
 | 
				
			||||||
 | 
					 * by one for subsequent calls.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Unique serial sequence number
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline unsigned int nl_socket_use_seq(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sk->s_seq_next++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Disable automatic request for ACK
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The default behaviour of a socket is to request an ACK for
 | 
				
			||||||
 | 
					 * each message sent to allow for the caller to synchronize to
 | 
				
			||||||
 | 
					 * the completion of the netlink operation. This function
 | 
				
			||||||
 | 
					 * disables this behaviour and will result in requests being
 | 
				
			||||||
 | 
					 * sent which will not have the NLM_F_ACK flag set automatically.
 | 
				
			||||||
 | 
					 * However, it is still possible for the caller to set the
 | 
				
			||||||
 | 
					 * NLM_F_ACK flag explicitely.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_socket_disable_auto_ack(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk->s_flags |= NL_NO_AUTO_ACK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Enable automatic request for ACK (default)
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @see nl_socket_disable_auto_ack
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_socket_enable_auto_ack(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk->s_flags &= ~NL_NO_AUTO_ACK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Source Idenficiation
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t nl_socket_get_local_port(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sk->s_local.nl_pid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Join multicast groups (deprecated)
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg groups		Bitmask of groups to join.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function defines the old way of joining multicast group which
 | 
				
			||||||
 | 
					 * has to be done prior to calling nl_connect(). It works on any kernel
 | 
				
			||||||
 | 
					 * version but is very limited as only 32 groups can be joined.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_join_groups(struct nl_sock *sk, int groups)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk->s_local.nl_groups |= groups;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Peer Identfication
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t nl_socket_get_peer_port(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sk->s_peer.nl_pid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk->s_peer.nl_pid = port;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name File Descriptor
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nl_socket_get_fd(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sk->s_fd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Enable use of MSG_PEEK when reading from socket
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_socket_enable_msg_peek(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk->s_flags |= NL_MSG_PEEK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Disable use of MSG_PEEK when reading from socket
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void nl_socket_disable_msg_peek(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sk->s_flags &= ~NL_MSG_PEEK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Callback Handler
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct nl_cb *nl_socket_get_cb(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_cb_get(sk->s_cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_cb_put(sk->s_cb);
 | 
				
			||||||
 | 
						sk->s_cb = nl_cb_get(cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Modify the callback handler associated to the socket
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg type		which type callback to set
 | 
				
			||||||
 | 
					 * @arg kind		kind of callback
 | 
				
			||||||
 | 
					 * @arg func		callback function
 | 
				
			||||||
 | 
					 * @arg arg		argument to be passwd to callback function
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nl_cb_set
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
 | 
				
			||||||
 | 
								enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
 | 
				
			||||||
 | 
								void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_cb_set(sk->s_cb, type, kind, func, arg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nl_socket_add_membership(struct nl_sock *sk, int group)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_socket_add_memberships(sk, group, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int nl_socket_drop_membership(struct nl_sock *sk, int group)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nl_socket_drop_memberships(sk, group, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										117
									
								
								package/libnl-tiny/src/include/netlink/types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								package/libnl-tiny/src/include/netlink/types.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/netlink-types.h	Netlink Types
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2006 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __NETLINK_TYPES_H_
 | 
				
			||||||
 | 
					#define __NETLINK_TYPES_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dumping types (dp_type)
 | 
				
			||||||
 | 
					 * @ingroup utils
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl_dump_type {
 | 
				
			||||||
 | 
						NL_DUMP_LINE,		/**< Dump object briefly on one line */
 | 
				
			||||||
 | 
						NL_DUMP_DETAILS,	/**< Dump all attributes but no statistics */
 | 
				
			||||||
 | 
						NL_DUMP_STATS,		/**< Dump all attributes including statistics */
 | 
				
			||||||
 | 
						NL_DUMP_ENV,		/**< Dump all attribtues as env variables */
 | 
				
			||||||
 | 
						__NL_DUMP_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#define NL_DUMP_MAX (__NL_DUMP_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dumping parameters
 | 
				
			||||||
 | 
					 * @ingroup utils
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_dump_params
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Specifies the type of dump that is requested.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						enum nl_dump_type	dp_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Specifies the number of whitespaces to be put in front
 | 
				
			||||||
 | 
						 * of every new line (indentation).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int			dp_prefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Causes the cache index to be printed for each element.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int			dp_print_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Causes each element to be prefixed with the message type.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int			dp_dump_msgtype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * A callback invoked for output
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Passed arguments are:
 | 
				
			||||||
 | 
						 *  - dumping parameters
 | 
				
			||||||
 | 
						 *  - string to append to the output
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void			(*dp_cb)(struct nl_dump_params *, char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * A callback invoked for every new line, can be used to
 | 
				
			||||||
 | 
						 * customize the indentation.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Passed arguments are:
 | 
				
			||||||
 | 
						 *  - dumping parameters
 | 
				
			||||||
 | 
						 *  - line number starting from 0
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void			(*dp_nl_cb)(struct nl_dump_params *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * User data pointer, can be used to pass data to callbacks.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void			*dp_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * File descriptor the dumping output should go to
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						FILE *			dp_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Alternatively the output may be redirected into a buffer
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						char *			dp_buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Length of the buffer dp_buf
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						size_t			dp_buflen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * PRIVATE
 | 
				
			||||||
 | 
						 * Set if a dump was performed prior to the actual dump handler.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int			dp_pre_dump;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * PRIVATE
 | 
				
			||||||
 | 
						 * Owned by the current caller
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int			dp_ivar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int		dp_line;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define min_t(type,x,y) \
 | 
				
			||||||
 | 
						({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
 | 
				
			||||||
 | 
					#define max_t(type,x,y) \
 | 
				
			||||||
 | 
						({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										78
									
								
								package/libnl-tiny/src/include/netlink/utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								package/libnl-tiny/src/include/netlink/utils.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/utils.h		Utility Functions
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_UTILS_H_
 | 
				
			||||||
 | 
					#define NETLINK_UTILS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/list.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Probability Constants
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Lower probability limit
 | 
				
			||||||
 | 
					 * @ingroup utils
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NL_PROB_MIN 0x0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Upper probability limit
 | 
				
			||||||
 | 
					 * @ingroup utils
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define NL_PROB_MAX 0xffffffff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* unit pretty-printing */
 | 
				
			||||||
 | 
					extern double	nl_cancel_down_bytes(unsigned long long, char **);
 | 
				
			||||||
 | 
					extern double	nl_cancel_down_bits(unsigned long long, char **);
 | 
				
			||||||
 | 
					extern double	nl_cancel_down_us(uint32_t, char **);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* generic unit translations */
 | 
				
			||||||
 | 
					extern long	nl_size2int(const char *);
 | 
				
			||||||
 | 
					extern long	nl_prob2int(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* time translations */
 | 
				
			||||||
 | 
					extern int	nl_get_hz(void);
 | 
				
			||||||
 | 
					extern uint32_t	nl_us2ticks(uint32_t);
 | 
				
			||||||
 | 
					extern uint32_t	nl_ticks2us(uint32_t);
 | 
				
			||||||
 | 
					extern int	nl_str2msec(const char *, uint64_t *);
 | 
				
			||||||
 | 
					extern char *	nl_msec2str(uint64_t, char *, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* link layer protocol translations */
 | 
				
			||||||
 | 
					extern char *	nl_llproto2str(int, char *, size_t);
 | 
				
			||||||
 | 
					extern int	nl_str2llproto(const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ethernet protocol translations */
 | 
				
			||||||
 | 
					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 *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Dumping helpers */
 | 
				
			||||||
 | 
					extern void	nl_new_line(struct nl_dump_params *);
 | 
				
			||||||
 | 
					extern void	nl_dump(struct nl_dump_params *, const char *, ...);
 | 
				
			||||||
 | 
					extern void	nl_dump_line(struct nl_dump_params *, const char *, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										18
									
								
								package/libnl-tiny/src/include/netlink/version.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								package/libnl-tiny/src/include/netlink/version.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * netlink/version.h	Compile Time Versioning Information
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NETLINK_VERSION_H_
 | 
				
			||||||
 | 
					#define NETLINK_VERSION_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LIBNL_STRING "libnl"
 | 
				
			||||||
 | 
					#define LIBNL_VERSION "2.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										566
									
								
								package/libnl-tiny/src/msg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								package/libnl-tiny/src/msg.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,566 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/msg.c		Netlink Messages Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup core
 | 
				
			||||||
 | 
					 * @defgroup msg Messages
 | 
				
			||||||
 | 
					 * Netlink Message Construction/Parsing Interface
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * The following information is partly extracted from RFC3549
 | 
				
			||||||
 | 
					 * (ftp://ftp.rfc-editor.org/in-notes/rfc3549.txt)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Message Format
 | 
				
			||||||
 | 
					 * Netlink messages consist of a byte stream with one or multiple
 | 
				
			||||||
 | 
					 * Netlink headers and an associated payload.  If the payload is too big
 | 
				
			||||||
 | 
					 * to fit into a single message it, can be split over multiple Netlink
 | 
				
			||||||
 | 
					 * messages, collectively called a multipart message.  For multipart
 | 
				
			||||||
 | 
					 * messages, the first and all following headers have the \c NLM_F_MULTI
 | 
				
			||||||
 | 
					 * Netlink header flag set, except for the last header which has the
 | 
				
			||||||
 | 
					 * Netlink header type \c NLMSG_DONE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * The Netlink message header (\link nlmsghdr struct nlmsghdr\endlink) is shown below.
 | 
				
			||||||
 | 
					 * @code   
 | 
				
			||||||
 | 
					 * 0                   1                   2                   3
 | 
				
			||||||
 | 
					 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |                          Length                             |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |            Type              |           Flags              |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |                      Sequence Number                        |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |                      Process ID (PID)                       |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * The netlink message header and payload must be aligned properly:
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *  <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
 | 
				
			||||||
 | 
					 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
 | 
				
			||||||
 | 
					 * |           Header           | Pad |       Payload       | Pad |
 | 
				
			||||||
 | 
					 * |      struct nlmsghdr       |     |                     |     |
 | 
				
			||||||
 | 
					 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * Message Format:
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *    <--- nlmsg_total_size(payload)  --->
 | 
				
			||||||
 | 
					 *    <-- nlmsg_msg_size(payload) ->
 | 
				
			||||||
 | 
					 *   +----------+- - -+-------------+- - -+-------- - -
 | 
				
			||||||
 | 
					 *   | nlmsghdr | Pad |   Payload   | Pad | nlmsghdr
 | 
				
			||||||
 | 
					 *   +----------+- - -+-------------+- - -+-------- - -
 | 
				
			||||||
 | 
					 *   nlmsg_data(nlh)---^                   ^
 | 
				
			||||||
 | 
					 *   nlmsg_next(nlh)-----------------------+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * The payload may consist of arbitary data but may have strict
 | 
				
			||||||
 | 
					 * alignment and formatting rules depening on the specific netlink
 | 
				
			||||||
 | 
					 * families.
 | 
				
			||||||
 | 
					 * @par
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *    <---------------------- nlmsg_len(nlh) --------------------->
 | 
				
			||||||
 | 
					 *    <------ hdrlen ------>       <- nlmsg_attrlen(nlh, hdrlen) ->
 | 
				
			||||||
 | 
					 *   +----------------------+- - -+--------------------------------+
 | 
				
			||||||
 | 
					 *   |     Family Header    | Pad |           Attributes           |
 | 
				
			||||||
 | 
					 *   +----------------------+- - -+--------------------------------+
 | 
				
			||||||
 | 
					 *   nlmsg_attrdata(nlh, hdrlen)---^
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @par The ACK Netlink Message
 | 
				
			||||||
 | 
					 * This message is actually used to denote both an ACK and a NACK.
 | 
				
			||||||
 | 
					 * Typically, the direction is from FEC to CPC (in response to an ACK
 | 
				
			||||||
 | 
					 * request message).  However, the CPC should be able to send ACKs back
 | 
				
			||||||
 | 
					 * to FEC when requested.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *  0                   1                   2                   3
 | 
				
			||||||
 | 
					 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |                       Netlink message header                  |
 | 
				
			||||||
 | 
					 * |                       type = NLMSG_ERROR                      |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |                          Error code                           |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * |                       OLD Netlink message header              |
 | 
				
			||||||
 | 
					 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par Example
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Various methods exist to create/allocate a new netlink
 | 
				
			||||||
 | 
					 * // message. 
 | 
				
			||||||
 | 
					 * //
 | 
				
			||||||
 | 
					 * // nlmsg_alloc() will allocate an empty netlink message with
 | 
				
			||||||
 | 
					 * // a maximum payload size which defaults to the page size of
 | 
				
			||||||
 | 
					 * // the system. This default size can be modified using the
 | 
				
			||||||
 | 
					 * // function nlmsg_set_default_size().
 | 
				
			||||||
 | 
					 * struct nl_msg *msg = nlmsg_alloc();
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Very often, the message type and message flags are known
 | 
				
			||||||
 | 
					 * // at allocation time while the other fields are auto generated:
 | 
				
			||||||
 | 
					 * struct nl_msg *msg = nlmsg_alloc_simple(MY_TYPE, MY_FLAGS);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Alternatively an existing netlink message header can be used
 | 
				
			||||||
 | 
					 * // to inherit the header values:
 | 
				
			||||||
 | 
					 * struct nlmsghdr hdr = {
 | 
				
			||||||
 | 
					 * 	.nlmsg_type = MY_TYPE,
 | 
				
			||||||
 | 
					 * 	.nlmsg_flags = MY_FLAGS,
 | 
				
			||||||
 | 
					 * };
 | 
				
			||||||
 | 
					 * struct nl_msg *msg = nlmsg_inherit(&hdr);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Last but not least, netlink messages received from netlink sockets
 | 
				
			||||||
 | 
					 * // can be converted into nl_msg objects using nlmsg_convert(). This
 | 
				
			||||||
 | 
					 * // will create a message with a maximum payload size which equals the
 | 
				
			||||||
 | 
					 * // length of the existing netlink message, therefore no more data can
 | 
				
			||||||
 | 
					 * // be appened without calling nlmsg_expand() first.
 | 
				
			||||||
 | 
					 * struct nl_msg *msg = nlmsg_convert(nlh_from_nl_sock);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Payload may be added to the message via nlmsg_append(). The fourth
 | 
				
			||||||
 | 
					 * // parameter specifies the number of alignment bytes the data should
 | 
				
			||||||
 | 
					 * // be padding with at the end. Common values are 0 to disable it or
 | 
				
			||||||
 | 
					 * // NLMSG_ALIGNTO to ensure proper netlink message padding.
 | 
				
			||||||
 | 
					 * nlmsg_append(msg, &mydata, sizeof(mydata), 0);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Sometimes it may be necessary to reserve room for data but defer
 | 
				
			||||||
 | 
					 * // the actual copying to a later point, nlmsg_reserve() can be used
 | 
				
			||||||
 | 
					 * // for this purpose:
 | 
				
			||||||
 | 
					 * void *data = nlmsg_reserve(msg, sizeof(mydata), NLMSG_ALIGNTO);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Attributes may be added using the attributes interface.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // After successful use of the message, the memory must be freed
 | 
				
			||||||
 | 
					 * // using nlmsg_free()
 | 
				
			||||||
 | 
					 * nlmsg_free(msg);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @par 4) Parsing messages
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * int n;
 | 
				
			||||||
 | 
					 * unsigned char *buf;
 | 
				
			||||||
 | 
					 * struct nlmsghdr *hdr;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * n = nl_recv(handle, NULL, &buf);
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * hdr = (struct nlmsghdr *) buf;
 | 
				
			||||||
 | 
					 * while (nlmsg_ok(hdr, n)) {
 | 
				
			||||||
 | 
					 * 	// Process message here...
 | 
				
			||||||
 | 
					 * 	hdr = nlmsg_next(hdr, &n);
 | 
				
			||||||
 | 
					 * }
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					#include <netlink/attr.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <linux/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t default_msg_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __init init_msg_size(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						default_msg_size = getpagesize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Attribute Access
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Message Parsing
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * check if the netlink message fits into the remaining bytes
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 * @arg remaining	number of bytes remaining in message stream
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (remaining >= sizeof(struct nlmsghdr) &&
 | 
				
			||||||
 | 
							nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
 | 
				
			||||||
 | 
							nlh->nlmsg_len <= remaining);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * next netlink message in message stream
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 * @arg remaining	number of bytes remaining in message stream
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @returns the next netlink message in the message stream and
 | 
				
			||||||
 | 
					 * decrements remaining by the size of the current message.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*remaining -= totlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (struct nlmsghdr *) ((unsigned char *) nlh + totlen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * parse attributes of a netlink message
 | 
				
			||||||
 | 
					 * @arg nlh		netlink message header
 | 
				
			||||||
 | 
					 * @arg hdrlen		length of family specific header
 | 
				
			||||||
 | 
					 * @arg tb		destination array with maxtype+1 elements
 | 
				
			||||||
 | 
					 * @arg maxtype		maximum attribute type to be expected
 | 
				
			||||||
 | 
					 * @arg policy		validation policy
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See nla_parse()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
 | 
				
			||||||
 | 
							int maxtype, struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!nlmsg_valid_hdr(nlh, hdrlen))
 | 
				
			||||||
 | 
							return -NLE_MSG_TOOSHORT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
 | 
				
			||||||
 | 
								 nlmsg_attrlen(nlh, hdrlen), policy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nlmsg_validate - validate a netlink message including attributes
 | 
				
			||||||
 | 
					 * @arg nlh		netlinket message header
 | 
				
			||||||
 | 
					 * @arg hdrlen		length of familiy specific header
 | 
				
			||||||
 | 
					 * @arg maxtype		maximum attribute type to be expected
 | 
				
			||||||
 | 
					 * @arg policy		validation policy
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
 | 
				
			||||||
 | 
							   struct nla_policy *policy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!nlmsg_valid_hdr(nlh, hdrlen))
 | 
				
			||||||
 | 
							return -NLE_MSG_TOOSHORT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nla_validate(nlmsg_attrdata(nlh, hdrlen),
 | 
				
			||||||
 | 
								    nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Message Building/Access
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nl_msg *__nlmsg_alloc(size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_msg *nm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nm = calloc(1, sizeof(*nm));
 | 
				
			||||||
 | 
						if (!nm)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nm->nm_refcnt = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nm->nm_nlh = malloc(len);
 | 
				
			||||||
 | 
						if (!nm->nm_nlh)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(nm->nm_nlh, 0, sizeof(struct nlmsghdr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nm->nm_protocol = -1;
 | 
				
			||||||
 | 
						nm->nm_size = len;
 | 
				
			||||||
 | 
						nm->nm_nlh->nlmsg_len = nlmsg_total_size(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Allocated new message, maxlen=%zu\n", nm, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nm;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						free(nm);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new netlink message with the default maximum payload size.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Allocates a new netlink message without any further payload. The
 | 
				
			||||||
 | 
					 * maximum payload size defaults to PAGESIZE or as otherwise specified
 | 
				
			||||||
 | 
					 * with nlmsg_set_default_size().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Newly allocated netlink message or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msg *nlmsg_alloc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return __nlmsg_alloc(default_msg_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new netlink message with maximum payload size specified.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msg *nlmsg_alloc_size(size_t max)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return __nlmsg_alloc(max);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new netlink message and inherit netlink message header
 | 
				
			||||||
 | 
					 * @arg hdr		Netlink message header template
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Allocates a new netlink message and inherits the original message
 | 
				
			||||||
 | 
					 * header. If \a hdr is not NULL it will be used as a template for
 | 
				
			||||||
 | 
					 * the netlink message header, otherwise the header is left blank.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @return Newly allocated netlink message or NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msg *nlmsg_inherit(struct nlmsghdr *hdr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_msg *nm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nm = nlmsg_alloc();
 | 
				
			||||||
 | 
						if (nm && hdr) {
 | 
				
			||||||
 | 
							struct nlmsghdr *new = nm->nm_nlh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							new->nlmsg_type = hdr->nlmsg_type;
 | 
				
			||||||
 | 
							new->nlmsg_flags = hdr->nlmsg_flags;
 | 
				
			||||||
 | 
							new->nlmsg_seq = hdr->nlmsg_seq;
 | 
				
			||||||
 | 
							new->nlmsg_pid = hdr->nlmsg_pid;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nm;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new netlink message
 | 
				
			||||||
 | 
					 * @arg nlmsgtype	Netlink message type
 | 
				
			||||||
 | 
					 * @arg flags		Message flags.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Newly allocated netlink message or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_msg *msg;
 | 
				
			||||||
 | 
						struct nlmsghdr nlh = {
 | 
				
			||||||
 | 
							.nlmsg_type = nlmsgtype,
 | 
				
			||||||
 | 
							.nlmsg_flags = flags,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg = nlmsg_inherit(&nlh);
 | 
				
			||||||
 | 
						if (msg)
 | 
				
			||||||
 | 
							NL_DBG(2, "msg %p: Allocated new simple message\n", msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return msg;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set the default maximum message payload size for allocated messages
 | 
				
			||||||
 | 
					 * @arg max		Size of payload in bytes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nlmsg_set_default_size(size_t max)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (max < nlmsg_total_size(0))
 | 
				
			||||||
 | 
							max = nlmsg_total_size(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default_msg_size = max;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert a netlink message received from a netlink socket to a nl_msg
 | 
				
			||||||
 | 
					 * @arg hdr		Netlink message received from netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Allocates a new netlink message and copies all of the data pointed to
 | 
				
			||||||
 | 
					 * by \a hdr into the new message object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Newly allocated netlink message or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_msg *nlmsg_convert(struct nlmsghdr *hdr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_msg *nm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len));
 | 
				
			||||||
 | 
						if (!nm)
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nm;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						nlmsg_free(nm);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reserve room for additional data in a netlink message
 | 
				
			||||||
 | 
					 * @arg n		netlink message
 | 
				
			||||||
 | 
					 * @arg len		length of additional data to reserve room for
 | 
				
			||||||
 | 
					 * @arg pad		number of bytes to align data to
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reserves room for additional data at the tail of the an
 | 
				
			||||||
 | 
					 * existing netlink message. Eventual padding required will
 | 
				
			||||||
 | 
					 * be zeroed out.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Pointer to start of additional data tailroom or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *buf = n->nm_nlh;
 | 
				
			||||||
 | 
						size_t nlmsg_len = n->nm_nlh->nlmsg_len;
 | 
				
			||||||
 | 
						size_t tlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((tlen + nlmsg_len) > n->nm_size)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf += nlmsg_len;
 | 
				
			||||||
 | 
						n->nm_nlh->nlmsg_len += tlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tlen > len)
 | 
				
			||||||
 | 
							memset(buf + len, 0, tlen - len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Reserved %zu bytes, pad=%d, nlmsg_len=%d\n",
 | 
				
			||||||
 | 
							  n, len, pad, n->nm_nlh->nlmsg_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buf;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Append data to tail of a netlink message
 | 
				
			||||||
 | 
					 * @arg n		netlink message
 | 
				
			||||||
 | 
					 * @arg data		data to add
 | 
				
			||||||
 | 
					 * @arg len		length of data
 | 
				
			||||||
 | 
					 * @arg pad		Number of bytes to align data to.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Extends the netlink message as needed and appends the data of given
 | 
				
			||||||
 | 
					 * length to the message. 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmp = nlmsg_reserve(n, len, pad);
 | 
				
			||||||
 | 
						if (tmp == NULL)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(tmp, data, len);
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add a netlink message header to a netlink message
 | 
				
			||||||
 | 
					 * @arg n		netlink message
 | 
				
			||||||
 | 
					 * @arg pid		netlink process id or NL_AUTO_PID
 | 
				
			||||||
 | 
					 * @arg seq		sequence number of message or NL_AUTO_SEQ
 | 
				
			||||||
 | 
					 * @arg type		message type
 | 
				
			||||||
 | 
					 * @arg payload		length of message payload
 | 
				
			||||||
 | 
					 * @arg flags		message flags
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Adds or overwrites the netlink message header in an existing message
 | 
				
			||||||
 | 
					 * object. If \a payload is greater-than zero additional room will be
 | 
				
			||||||
 | 
					 * reserved, f.e. for family specific headers. It can be accesed via
 | 
				
			||||||
 | 
					 * nlmsg_data().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return A pointer to the netlink message header or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nlmsghdr *nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq,
 | 
				
			||||||
 | 
								   int type, int payload, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlmsghdr *nlh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nlh = (struct nlmsghdr *) n->nm_nlh;
 | 
				
			||||||
 | 
						nlh->nlmsg_type = type;
 | 
				
			||||||
 | 
						nlh->nlmsg_flags = flags;
 | 
				
			||||||
 | 
						nlh->nlmsg_pid = pid;
 | 
				
			||||||
 | 
						nlh->nlmsg_seq = seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(2, "msg %p: Added netlink header type=%d, flags=%d, pid=%d, "
 | 
				
			||||||
 | 
							  "seq=%d\n", n, type, flags, pid, seq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (payload > 0 &&
 | 
				
			||||||
 | 
						    nlmsg_reserve(n, payload, NLMSG_ALIGNTO) == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nlh;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Release a reference from an netlink message
 | 
				
			||||||
 | 
					 * @arg msg		message to release reference from
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Frees memory after the last reference has been released.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nlmsg_free(struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!msg)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg->nm_refcnt--;
 | 
				
			||||||
 | 
						NL_DBG(4, "Returned message reference %p, %d remaining\n",
 | 
				
			||||||
 | 
						       msg, msg->nm_refcnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msg->nm_refcnt < 0)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msg->nm_refcnt <= 0) {
 | 
				
			||||||
 | 
							free(msg->nm_nlh);
 | 
				
			||||||
 | 
							free(msg);
 | 
				
			||||||
 | 
							NL_DBG(2, "msg %p: Freed\n", msg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Direct Parsing
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond SKIP */
 | 
				
			||||||
 | 
					struct dp_xdata {
 | 
				
			||||||
 | 
						void (*cb)(struct nl_object *, void *);
 | 
				
			||||||
 | 
						void *arg;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int parse_cb(struct nl_object *obj, struct nl_parser_param *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dp_xdata *x = p->pp_arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x->cb(obj, x->arg);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int nl_msg_parse(struct nl_msg *msg, void (*cb)(struct nl_object *, void *),
 | 
				
			||||||
 | 
							 void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
						struct nl_parser_param p = {
 | 
				
			||||||
 | 
							.pp_cb = parse_cb
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct dp_xdata x = {
 | 
				
			||||||
 | 
							.cb = cb,
 | 
				
			||||||
 | 
							.arg = arg,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = nl_cache_ops_associate(nlmsg_get_proto(msg),
 | 
				
			||||||
 | 
									     nlmsg_hdr(msg)->nlmsg_type);
 | 
				
			||||||
 | 
						if (ops == NULL)
 | 
				
			||||||
 | 
							return -NLE_MSGTYPE_NOSUPPORT;
 | 
				
			||||||
 | 
						p.pp_arg = &x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										720
									
								
								package/libnl-tiny/src/nl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										720
									
								
								package/libnl-tiny/src/nl.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,720 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/nl.c		Core Netlink Interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @defgroup core Core
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @details
 | 
				
			||||||
 | 
					 * @par 1) Connecting the socket
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Bind and connect the socket to a protocol, NETLINK_ROUTE in this example.
 | 
				
			||||||
 | 
					 * nl_connect(sk, NETLINK_ROUTE);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 2) Sending data
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // The most rudimentary method is to use nl_sendto() simply pushing
 | 
				
			||||||
 | 
					 * // a piece of data to the other netlink peer. This method is not
 | 
				
			||||||
 | 
					 * // recommended.
 | 
				
			||||||
 | 
					 * const char buf[] = { 0x01, 0x02, 0x03, 0x04 };
 | 
				
			||||||
 | 
					 * nl_sendto(sk, buf, sizeof(buf));
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // A more comfortable interface is nl_send() taking a pointer to
 | 
				
			||||||
 | 
					 * // a netlink message.
 | 
				
			||||||
 | 
					 * struct nl_msg *msg = my_msg_builder();
 | 
				
			||||||
 | 
					 * nl_send(sk, nlmsg_hdr(msg));
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // nl_sendmsg() provides additional control over the sendmsg() message
 | 
				
			||||||
 | 
					 * // header in order to allow more specific addressing of multiple peers etc.
 | 
				
			||||||
 | 
					 * struct msghdr hdr = { ... };
 | 
				
			||||||
 | 
					 * nl_sendmsg(sk, nlmsg_hdr(msg), &hdr);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // You're probably too lazy to fill out the netlink pid, sequence number
 | 
				
			||||||
 | 
					 * // and message flags all the time. nl_send_auto_complete() automatically
 | 
				
			||||||
 | 
					 * // extends your message header as needed with an appropriate sequence
 | 
				
			||||||
 | 
					 * // number, the netlink pid stored in the netlink socket and the message
 | 
				
			||||||
 | 
					 * // flags NLM_F_REQUEST and NLM_F_ACK (if not disabled in the socket)
 | 
				
			||||||
 | 
					 * nl_send_auto_complete(sk, nlmsg_hdr(msg));
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // Simple protocols don't require the complex message construction interface
 | 
				
			||||||
 | 
					 * // and may favour nl_send_simple() to easly send a bunch of payload
 | 
				
			||||||
 | 
					 * // encapsulated in a netlink message header.
 | 
				
			||||||
 | 
					 * nl_send_simple(sk, MY_MSG_TYPE, 0, buf, sizeof(buf));
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 3) Receiving data
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // nl_recv() receives a single message allocating a buffer for the message
 | 
				
			||||||
 | 
					 * // content and gives back the pointer to you.
 | 
				
			||||||
 | 
					 * struct sockaddr_nl peer;
 | 
				
			||||||
 | 
					 * unsigned char *msg;
 | 
				
			||||||
 | 
					 * nl_recv(sk, &peer, &msg);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // nl_recvmsgs() receives a bunch of messages until the callback system
 | 
				
			||||||
 | 
					 * // orders it to state, usually after receving a compolete multi part
 | 
				
			||||||
 | 
					 * // message series.
 | 
				
			||||||
 | 
					 * nl_recvmsgs(sk, my_callback_configuration);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // nl_recvmsgs_default() acts just like nl_recvmsg() but uses the callback
 | 
				
			||||||
 | 
					 * // configuration stored in the socket.
 | 
				
			||||||
 | 
					 * nl_recvmsgs_default(sk);
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // In case you want to wait for the ACK to be recieved that you requested
 | 
				
			||||||
 | 
					 * // with your latest message, you can call nl_wait_for_ack()
 | 
				
			||||||
 | 
					 * nl_wait_for_ack(sk);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @par 4) Closing
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * // Close the socket first to release kernel memory
 | 
				
			||||||
 | 
					 * nl_close(sk);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/handlers.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <netlink/attr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Connection Management
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Create and connect netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg protocol	Netlink protocol to use.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Creates a netlink socket using the specified protocol, binds the socket
 | 
				
			||||||
 | 
					 * and issues a connection attempt.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_connect(struct nl_sock *sk, int protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						socklen_t addrlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk->s_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
 | 
				
			||||||
 | 
						if (sk->s_fd < 0) {
 | 
				
			||||||
 | 
							err = -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(sk->s_flags & NL_SOCK_BUFSIZE_SET)) {
 | 
				
			||||||
 | 
							err = nl_socket_set_buffer_size(sk, 0, 0);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local,
 | 
				
			||||||
 | 
							   sizeof(sk->s_local));
 | 
				
			||||||
 | 
						if (err < 0) {
 | 
				
			||||||
 | 
							err = -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addrlen = sizeof(sk->s_local);
 | 
				
			||||||
 | 
						err = getsockname(sk->s_fd, (struct sockaddr *) &sk->s_local,
 | 
				
			||||||
 | 
								  &addrlen);
 | 
				
			||||||
 | 
						if (err < 0) {
 | 
				
			||||||
 | 
							err = -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (addrlen != sizeof(sk->s_local)) {
 | 
				
			||||||
 | 
							err = -NLE_NOADDR;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_local.nl_family != AF_NETLINK) {
 | 
				
			||||||
 | 
							err = -NLE_AF_NOSUPPORT;
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk->s_proto = protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						close(sk->s_fd);
 | 
				
			||||||
 | 
						sk->s_fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Close/Disconnect netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_close(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (sk->s_fd >= 0) {
 | 
				
			||||||
 | 
							close(sk->s_fd);
 | 
				
			||||||
 | 
							sk->s_fd = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk->s_proto = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Send
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Send raw data over netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg buf		Data buffer.
 | 
				
			||||||
 | 
					 * @arg size		Size of data buffer.
 | 
				
			||||||
 | 
					 * @return Number of characters written on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_sendto(struct nl_sock *sk, void *buf, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *)
 | 
				
			||||||
 | 
							     &sk->s_peer, sizeof(sk->s_peer));
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Send netlink message with control over sendmsg() message header.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message to be sent.
 | 
				
			||||||
 | 
					 * @arg hdr		Sendmsg() message header.
 | 
				
			||||||
 | 
					 * @return Number of characters sent on sucess or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cb *cb;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct iovec iov = {
 | 
				
			||||||
 | 
							.iov_base = (void *) nlmsg_hdr(msg),
 | 
				
			||||||
 | 
							.iov_len = nlmsg_hdr(msg)->nlmsg_len,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hdr->msg_iov = &iov;
 | 
				
			||||||
 | 
						hdr->msg_iovlen = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nlmsg_set_src(msg, &sk->s_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cb = sk->s_cb;
 | 
				
			||||||
 | 
						if (cb->cb_set[NL_CB_MSG_OUT])
 | 
				
			||||||
 | 
							if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = sendmsg(sk->s_fd, hdr, 0);
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Send netlink message.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message to be sent.
 | 
				
			||||||
 | 
					 * @see nl_sendmsg()
 | 
				
			||||||
 | 
					 * @return Number of characters sent on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_send(struct nl_sock *sk, struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sockaddr_nl *dst;
 | 
				
			||||||
 | 
						struct ucred *creds;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						struct msghdr hdr = {
 | 
				
			||||||
 | 
							.msg_name = (void *) &sk->s_peer,
 | 
				
			||||||
 | 
							.msg_namelen = sizeof(struct sockaddr_nl),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Overwrite destination if specified in the message itself, defaults
 | 
				
			||||||
 | 
						 * to the peer address of the socket.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						dst = nlmsg_get_dst(msg);
 | 
				
			||||||
 | 
						if (dst->nl_family == AF_NETLINK)
 | 
				
			||||||
 | 
							hdr.msg_name = dst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Add credentials if present. */
 | 
				
			||||||
 | 
						creds = nlmsg_get_creds(msg);
 | 
				
			||||||
 | 
						if (creds != NULL) {
 | 
				
			||||||
 | 
							char buf[CMSG_SPACE(sizeof(struct ucred))];
 | 
				
			||||||
 | 
							struct cmsghdr *cmsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							hdr.msg_control = buf;
 | 
				
			||||||
 | 
							hdr.msg_controllen = sizeof(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cmsg = CMSG_FIRSTHDR(&hdr);
 | 
				
			||||||
 | 
							cmsg->cmsg_level = SOL_SOCKET;
 | 
				
			||||||
 | 
							cmsg->cmsg_type = SCM_CREDENTIALS;
 | 
				
			||||||
 | 
							cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
 | 
				
			||||||
 | 
							memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nl_sendmsg(sk, msg, &hdr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Send netlink message and check & extend header values as needed.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg msg		Netlink message to be sent.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Checks the netlink message \c nlh for completness and extends it
 | 
				
			||||||
 | 
					 * as required before sending it out. Checked fields include pid,
 | 
				
			||||||
 | 
					 * sequence nr, and flags.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nl_send()
 | 
				
			||||||
 | 
					 * @return Number of characters sent or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlmsghdr *nlh;
 | 
				
			||||||
 | 
						struct nl_cb *cb = sk->s_cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nlh = nlmsg_hdr(msg);
 | 
				
			||||||
 | 
						if (nlh->nlmsg_pid == 0)
 | 
				
			||||||
 | 
							nlh->nlmsg_pid = sk->s_local.nl_pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nlh->nlmsg_seq == 0)
 | 
				
			||||||
 | 
							nlh->nlmsg_seq = sk->s_seq_next++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msg->nm_protocol == -1)
 | 
				
			||||||
 | 
							msg->nm_protocol = sk->s_proto;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						nlh->nlmsg_flags |= NLM_F_REQUEST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(sk->s_flags & NL_NO_AUTO_ACK))
 | 
				
			||||||
 | 
							nlh->nlmsg_flags |= NLM_F_ACK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cb->cb_send_ow)
 | 
				
			||||||
 | 
							return cb->cb_send_ow(sk, msg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return nl_send(sk, msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Send simple netlink message using nl_send_auto_complete()
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg type		Netlink message type.
 | 
				
			||||||
 | 
					 * @arg flags		Netlink message flags.
 | 
				
			||||||
 | 
					 * @arg buf		Data buffer.
 | 
				
			||||||
 | 
					 * @arg size		Size of data buffer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Builds a netlink message with the specified type and flags and
 | 
				
			||||||
 | 
					 * appends the specified data as payload to the message.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nl_send_auto_complete()
 | 
				
			||||||
 | 
					 * @return Number of characters sent on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf,
 | 
				
			||||||
 | 
							   size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct nl_msg *msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg = nlmsg_alloc_simple(type, flags);
 | 
				
			||||||
 | 
						if (!msg)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buf && size) {
 | 
				
			||||||
 | 
							err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								goto errout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = nl_send_auto_complete(sk, msg);
 | 
				
			||||||
 | 
					errout:
 | 
				
			||||||
 | 
						nlmsg_free(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Receive
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Receive data from netlink socket
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg nla		Destination pointer for peer's netlink address.
 | 
				
			||||||
 | 
					 * @arg buf		Destination pointer for message content.
 | 
				
			||||||
 | 
					 * @arg creds		Destination pointer for credentials.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
 | 
					 * are handled by repeating the read. The input buffer size is determined
 | 
				
			||||||
 | 
					 * by peeking before the actual read is done.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A non-blocking sockets causes the function to return immediately with
 | 
				
			||||||
 | 
					 * a return value of 0 if no data is available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Number of octets read, 0 on EOF or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
 | 
				
			||||||
 | 
						    unsigned char **buf, struct ucred **creds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int n;
 | 
				
			||||||
 | 
						int flags = 0;
 | 
				
			||||||
 | 
						static int page_size = 0;
 | 
				
			||||||
 | 
						struct iovec iov;
 | 
				
			||||||
 | 
						struct msghdr msg = {
 | 
				
			||||||
 | 
							.msg_name = (void *) nla,
 | 
				
			||||||
 | 
							.msg_namelen = sizeof(struct sockaddr_nl),
 | 
				
			||||||
 | 
							.msg_iov = &iov,
 | 
				
			||||||
 | 
							.msg_iovlen = 1,
 | 
				
			||||||
 | 
							.msg_control = NULL,
 | 
				
			||||||
 | 
							.msg_controllen = 0,
 | 
				
			||||||
 | 
							.msg_flags = 0,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct cmsghdr *cmsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_flags & NL_MSG_PEEK)
 | 
				
			||||||
 | 
							flags |= MSG_PEEK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (page_size == 0)
 | 
				
			||||||
 | 
							page_size = getpagesize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iov.iov_len = page_size;
 | 
				
			||||||
 | 
						iov.iov_base = *buf = malloc(iov.iov_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_flags & NL_SOCK_PASSCRED) {
 | 
				
			||||||
 | 
							msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
 | 
				
			||||||
 | 
							msg.msg_control = calloc(1, msg.msg_controllen);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					retry:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n = recvmsg(sk->s_fd, &msg, flags);
 | 
				
			||||||
 | 
						if (!n)
 | 
				
			||||||
 | 
							goto abort;
 | 
				
			||||||
 | 
						else if (n < 0) {
 | 
				
			||||||
 | 
							if (errno == EINTR) {
 | 
				
			||||||
 | 
								NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
 | 
				
			||||||
 | 
								goto retry;
 | 
				
			||||||
 | 
							} else if (errno == EAGAIN) {
 | 
				
			||||||
 | 
								NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
 | 
				
			||||||
 | 
								goto abort;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								free(msg.msg_control);
 | 
				
			||||||
 | 
								free(*buf);
 | 
				
			||||||
 | 
								return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (iov.iov_len < n ||
 | 
				
			||||||
 | 
						    msg.msg_flags & MSG_TRUNC) {
 | 
				
			||||||
 | 
							/* Provided buffer is not long enough, enlarge it
 | 
				
			||||||
 | 
							 * and try again. */
 | 
				
			||||||
 | 
							iov.iov_len *= 2;
 | 
				
			||||||
 | 
							iov.iov_base = *buf = realloc(*buf, iov.iov_len);
 | 
				
			||||||
 | 
							goto retry;
 | 
				
			||||||
 | 
						} else if (msg.msg_flags & MSG_CTRUNC) {
 | 
				
			||||||
 | 
							msg.msg_controllen *= 2;
 | 
				
			||||||
 | 
							msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
 | 
				
			||||||
 | 
							goto retry;
 | 
				
			||||||
 | 
						} else if (flags != 0) {
 | 
				
			||||||
 | 
							/* Buffer is big enough, do the actual reading */
 | 
				
			||||||
 | 
							flags = 0;
 | 
				
			||||||
 | 
							goto retry;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
 | 
				
			||||||
 | 
							free(msg.msg_control);
 | 
				
			||||||
 | 
							free(*buf);
 | 
				
			||||||
 | 
							return -NLE_NOADDR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
 | 
				
			||||||
 | 
							if (cmsg->cmsg_level == SOL_SOCKET &&
 | 
				
			||||||
 | 
							    cmsg->cmsg_type == SCM_CREDENTIALS) {
 | 
				
			||||||
 | 
								*creds = calloc(1, sizeof(struct ucred));
 | 
				
			||||||
 | 
								memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(msg.msg_control);
 | 
				
			||||||
 | 
						return n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abort:
 | 
				
			||||||
 | 
						free(msg.msg_control);
 | 
				
			||||||
 | 
						free(*buf);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NL_CB_CALL(cb, type, msg) \
 | 
				
			||||||
 | 
					do { \
 | 
				
			||||||
 | 
						err = nl_cb_call(cb, type, msg); \
 | 
				
			||||||
 | 
						switch (err) { \
 | 
				
			||||||
 | 
						case NL_OK: \
 | 
				
			||||||
 | 
							err = 0; \
 | 
				
			||||||
 | 
							break; \
 | 
				
			||||||
 | 
						case NL_SKIP: \
 | 
				
			||||||
 | 
							goto skip; \
 | 
				
			||||||
 | 
						case NL_STOP: \
 | 
				
			||||||
 | 
							goto stop; \
 | 
				
			||||||
 | 
						default: \
 | 
				
			||||||
 | 
							goto out; \
 | 
				
			||||||
 | 
						} \
 | 
				
			||||||
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int n, err = 0, multipart = 0;
 | 
				
			||||||
 | 
						unsigned char *buf = NULL;
 | 
				
			||||||
 | 
						struct nlmsghdr *hdr;
 | 
				
			||||||
 | 
						struct sockaddr_nl nla = {0};
 | 
				
			||||||
 | 
						struct nl_msg *msg = NULL;
 | 
				
			||||||
 | 
						struct ucred *creds = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					continue_reading:
 | 
				
			||||||
 | 
						NL_DBG(3, "Attempting to read from %p\n", sk);
 | 
				
			||||||
 | 
						if (cb->cb_recv_ow)
 | 
				
			||||||
 | 
							n = cb->cb_recv_ow(sk, &nla, &buf, &creds);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							n = nl_recv(sk, &nla, &buf, &creds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (n <= 0)
 | 
				
			||||||
 | 
							return n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hdr = (struct nlmsghdr *) buf;
 | 
				
			||||||
 | 
						while (nlmsg_ok(hdr, n)) {
 | 
				
			||||||
 | 
							NL_DBG(3, "recgmsgs(%p): Processing valid message...\n", sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nlmsg_free(msg);
 | 
				
			||||||
 | 
							msg = nlmsg_convert(hdr);
 | 
				
			||||||
 | 
							if (!msg) {
 | 
				
			||||||
 | 
								err = -NLE_NOMEM;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nlmsg_set_proto(msg, sk->s_proto);
 | 
				
			||||||
 | 
							nlmsg_set_src(msg, &nla);
 | 
				
			||||||
 | 
							if (creds)
 | 
				
			||||||
 | 
								nlmsg_set_creds(msg, creds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Raw callback is the first, it gives the most control
 | 
				
			||||||
 | 
							 * to the user and he can do his very own parsing. */
 | 
				
			||||||
 | 
							if (cb->cb_set[NL_CB_MSG_IN])
 | 
				
			||||||
 | 
								NL_CB_CALL(cb, NL_CB_MSG_IN, msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Sequence number checking. The check may be done by
 | 
				
			||||||
 | 
							 * the user, otherwise a very simple check is applied
 | 
				
			||||||
 | 
							 * enforcing strict ordering */
 | 
				
			||||||
 | 
							if (cb->cb_set[NL_CB_SEQ_CHECK])
 | 
				
			||||||
 | 
								NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg);
 | 
				
			||||||
 | 
							else if (hdr->nlmsg_seq != sk->s_seq_expect) {
 | 
				
			||||||
 | 
								if (cb->cb_set[NL_CB_INVALID])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_INVALID, msg);
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									err = -NLE_SEQ_MISMATCH;
 | 
				
			||||||
 | 
									goto out;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (hdr->nlmsg_type == NLMSG_DONE ||
 | 
				
			||||||
 | 
							    hdr->nlmsg_type == NLMSG_ERROR ||
 | 
				
			||||||
 | 
							    hdr->nlmsg_type == NLMSG_NOOP ||
 | 
				
			||||||
 | 
							    hdr->nlmsg_type == NLMSG_OVERRUN) {
 | 
				
			||||||
 | 
								/* We can't check for !NLM_F_MULTI since some netlink
 | 
				
			||||||
 | 
								 * users in the kernel are broken. */
 | 
				
			||||||
 | 
								sk->s_seq_expect++;
 | 
				
			||||||
 | 
								NL_DBG(3, "recvmsgs(%p): Increased expected " \
 | 
				
			||||||
 | 
								       "sequence number to %d\n",
 | 
				
			||||||
 | 
								       sk, sk->s_seq_expect);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (hdr->nlmsg_flags & NLM_F_MULTI)
 | 
				
			||||||
 | 
								multipart = 1;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							/* Other side wishes to see an ack for this message */
 | 
				
			||||||
 | 
							if (hdr->nlmsg_flags & NLM_F_ACK) {
 | 
				
			||||||
 | 
								if (cb->cb_set[NL_CB_SEND_ACK])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_SEND_ACK, msg);
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									/* FIXME: implement */
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* messages terminates a multpart message, this is
 | 
				
			||||||
 | 
							 * usually the end of a message and therefore we slip
 | 
				
			||||||
 | 
							 * out of the loop by default. the user may overrule
 | 
				
			||||||
 | 
							 * this action by skipping this packet. */
 | 
				
			||||||
 | 
							if (hdr->nlmsg_type == NLMSG_DONE) {
 | 
				
			||||||
 | 
								multipart = 0;
 | 
				
			||||||
 | 
								if (cb->cb_set[NL_CB_FINISH])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_FINISH, msg);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Message to be ignored, the default action is to
 | 
				
			||||||
 | 
							 * skip this message if no callback is specified. The
 | 
				
			||||||
 | 
							 * user may overrule this action by returning
 | 
				
			||||||
 | 
							 * NL_PROCEED. */
 | 
				
			||||||
 | 
							else if (hdr->nlmsg_type == NLMSG_NOOP) {
 | 
				
			||||||
 | 
								if (cb->cb_set[NL_CB_SKIPPED])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_SKIPPED, msg);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									goto skip;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Data got lost, report back to user. The default action is to
 | 
				
			||||||
 | 
							 * quit parsing. The user may overrule this action by retuning
 | 
				
			||||||
 | 
							 * NL_SKIP or NL_PROCEED (dangerous) */
 | 
				
			||||||
 | 
							else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
 | 
				
			||||||
 | 
								if (cb->cb_set[NL_CB_OVERRUN])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_OVERRUN, msg);
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									err = -NLE_MSG_OVERFLOW;
 | 
				
			||||||
 | 
									goto out;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Message carries a nlmsgerr */
 | 
				
			||||||
 | 
							else if (hdr->nlmsg_type == NLMSG_ERROR) {
 | 
				
			||||||
 | 
								struct nlmsgerr *e = nlmsg_data(hdr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) {
 | 
				
			||||||
 | 
									/* Truncated error message, the default action
 | 
				
			||||||
 | 
									 * is to stop parsing. The user may overrule
 | 
				
			||||||
 | 
									 * this action by returning NL_SKIP or
 | 
				
			||||||
 | 
									 * NL_PROCEED (dangerous) */
 | 
				
			||||||
 | 
									if (cb->cb_set[NL_CB_INVALID])
 | 
				
			||||||
 | 
										NL_CB_CALL(cb, NL_CB_INVALID, msg);
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										err = -NLE_MSG_TRUNC;
 | 
				
			||||||
 | 
										goto out;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if (e->error) {
 | 
				
			||||||
 | 
									/* Error message reported back from kernel. */
 | 
				
			||||||
 | 
									if (cb->cb_err) {
 | 
				
			||||||
 | 
										err = cb->cb_err(&nla, e,
 | 
				
			||||||
 | 
												   cb->cb_err_arg);
 | 
				
			||||||
 | 
										if (err < 0)
 | 
				
			||||||
 | 
											goto out;
 | 
				
			||||||
 | 
										else if (err == NL_SKIP)
 | 
				
			||||||
 | 
											goto skip;
 | 
				
			||||||
 | 
										else if (err == NL_STOP) {
 | 
				
			||||||
 | 
											err = -nl_syserr2nlerr(e->error);
 | 
				
			||||||
 | 
											goto out;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										err = -nl_syserr2nlerr(e->error);
 | 
				
			||||||
 | 
										goto out;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if (cb->cb_set[NL_CB_ACK])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_ACK, msg);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Valid message (not checking for MULTIPART bit to
 | 
				
			||||||
 | 
								 * get along with broken kernels. NL_SKIP has no
 | 
				
			||||||
 | 
								 * effect on this.  */
 | 
				
			||||||
 | 
								if (cb->cb_set[NL_CB_VALID])
 | 
				
			||||||
 | 
									NL_CB_CALL(cb, NL_CB_VALID, msg);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					skip:
 | 
				
			||||||
 | 
							err = 0;
 | 
				
			||||||
 | 
							hdr = nlmsg_next(hdr, &n);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						nlmsg_free(msg);
 | 
				
			||||||
 | 
						free(buf);
 | 
				
			||||||
 | 
						free(creds);
 | 
				
			||||||
 | 
						buf = NULL;
 | 
				
			||||||
 | 
						msg = NULL;
 | 
				
			||||||
 | 
						creds = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (multipart) {
 | 
				
			||||||
 | 
							/* Multipart message not yet complete, continue reading */
 | 
				
			||||||
 | 
							goto continue_reading;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					stop:
 | 
				
			||||||
 | 
						err = 0;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						nlmsg_free(msg);
 | 
				
			||||||
 | 
						free(buf);
 | 
				
			||||||
 | 
						free(creds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Receive a set of messages from a netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg cb		set of callbacks to control behaviour.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Repeatedly calls nl_recv() or the respective replacement if provided
 | 
				
			||||||
 | 
					 * by the application (see nl_cb_overwrite_recv()) and parses the
 | 
				
			||||||
 | 
					 * received data as netlink messages. Stops reading if one of the
 | 
				
			||||||
 | 
					 * callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A non-blocking sockets causes the function to return immediately if
 | 
				
			||||||
 | 
					 * no data is available.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code from nl_recv().
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (cb->cb_recvmsgs_ow)
 | 
				
			||||||
 | 
							return cb->cb_recvmsgs_ow(sk, cb);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return recvmsgs(sk, cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ack_wait_handler(struct nl_msg *msg, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NL_STOP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Wait for ACK.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @pre The netlink socket must be in blocking state.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Waits until an ACK is received for the latest not yet acknowledged
 | 
				
			||||||
 | 
					 * netlink message.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_wait_for_ack(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct nl_cb *cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cb = nl_cb_clone(sk->s_cb);
 | 
				
			||||||
 | 
						if (cb == NULL)
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
 | 
				
			||||||
 | 
						err = nl_recvmsgs(sk, cb);
 | 
				
			||||||
 | 
						nl_cb_put(cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										309
									
								
								package/libnl-tiny/src/object.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								package/libnl-tiny/src/object.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,309 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/object.c		Generic Cacheable Object
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup cache
 | 
				
			||||||
 | 
					 * @defgroup object Object
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/cache.h>
 | 
				
			||||||
 | 
					#include <netlink/object.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!obj->ce_ops)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return obj->ce_ops;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Object Creation/Deletion
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new object of kind specified by the operations handle
 | 
				
			||||||
 | 
					 * @arg ops		cache operations handle
 | 
				
			||||||
 | 
					 * @return The new object or NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *new;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->oo_size < sizeof(*new))
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new = calloc(1, ops->oo_size);
 | 
				
			||||||
 | 
						if (!new)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new->ce_refcnt = 1;
 | 
				
			||||||
 | 
						nl_init_list_head(&new->ce_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new->ce_ops = ops;
 | 
				
			||||||
 | 
						if (ops->oo_constructor)
 | 
				
			||||||
 | 
							ops->oo_constructor(new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(4, "Allocated new object %p\n", new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return new;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new object of kind specified by the name
 | 
				
			||||||
 | 
					 * @arg kind		name of object type
 | 
				
			||||||
 | 
					 * @return The new object or nULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_object_alloc_name(const char *kind, struct nl_object **result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cache_ops *ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops = nl_cache_ops_lookup(kind);
 | 
				
			||||||
 | 
						if (!ops)
 | 
				
			||||||
 | 
							return -NLE_OPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(*result = nl_object_alloc(ops->co_obj_ops)))
 | 
				
			||||||
 | 
							return -NLE_NOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nl_derived_object {
 | 
				
			||||||
 | 
						NLHDR_COMMON
 | 
				
			||||||
 | 
						char data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate a new object and copy all data from an existing object
 | 
				
			||||||
 | 
					 * @arg obj		object to inherite data from
 | 
				
			||||||
 | 
					 * @return The new object or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_object *nl_object_clone(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object *new;
 | 
				
			||||||
 | 
						struct nl_object_ops *ops = obj_ops(obj);
 | 
				
			||||||
 | 
						int doff = offsetof(struct nl_derived_object, data);
 | 
				
			||||||
 | 
						int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new = nl_object_alloc(ops);
 | 
				
			||||||
 | 
						if (!new)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size = ops->oo_size - doff;
 | 
				
			||||||
 | 
						if (size < 0)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new->ce_ops = obj->ce_ops;
 | 
				
			||||||
 | 
						new->ce_msgtype = obj->ce_msgtype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (size)
 | 
				
			||||||
 | 
							memcpy((void *)new + doff, (void *)obj + doff, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->oo_clone) {
 | 
				
			||||||
 | 
							if (ops->oo_clone(new, obj) < 0) {
 | 
				
			||||||
 | 
								nl_object_free(new);
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (size && ops->oo_free_data)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return new;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Free a cacheable object
 | 
				
			||||||
 | 
					 * @arg obj		object to free
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_object_free(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object_ops *ops = obj_ops(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (obj->ce_refcnt > 0)
 | 
				
			||||||
 | 
							NL_DBG(1, "Warning: Freeing object in use...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (obj->ce_cache)
 | 
				
			||||||
 | 
							nl_cache_remove(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->oo_free_data)
 | 
				
			||||||
 | 
							ops->oo_free_data(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL_DBG(4, "Freed object %p\n", obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Reference Management
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Acquire a reference on a object
 | 
				
			||||||
 | 
					 * @arg obj		object to acquire reference from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_object_get(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						obj->ce_refcnt++;
 | 
				
			||||||
 | 
						NL_DBG(4, "New reference to object %p, total %d\n",
 | 
				
			||||||
 | 
						       obj, obj->ce_refcnt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Release a reference from an object
 | 
				
			||||||
 | 
					 * @arg obj		object to release reference from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_object_put(struct nl_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!obj)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj->ce_refcnt--;
 | 
				
			||||||
 | 
						NL_DBG(4, "Returned object reference %p, %d remaining\n",
 | 
				
			||||||
 | 
						       obj, obj->ce_refcnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (obj->ce_refcnt < 0)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (obj->ce_refcnt <= 0)
 | 
				
			||||||
 | 
							nl_object_free(obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Utillities
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef disabled
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dump this object according to the specified parameters
 | 
				
			||||||
 | 
					 * @arg obj		object to dump
 | 
				
			||||||
 | 
					 * @arg params		dumping parameters
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dump_from_ops(obj, params);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check if the identifiers of two objects are identical 
 | 
				
			||||||
 | 
					 * @arg a		an object
 | 
				
			||||||
 | 
					 * @arg b		another object of same type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true if both objects have equal identifiers, otherwise false.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_object_identical(struct nl_object *a, struct nl_object *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object_ops *ops = obj_ops(a);
 | 
				
			||||||
 | 
						int req_attrs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Both objects must be of same type */
 | 
				
			||||||
 | 
						if (ops != obj_ops(b))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req_attrs = ops->oo_id_attrs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Both objects must provide all required attributes to uniquely
 | 
				
			||||||
 | 
						 * identify an object */
 | 
				
			||||||
 | 
						if ((a->ce_mask & req_attrs) != req_attrs ||
 | 
				
			||||||
 | 
						    (b->ce_mask & req_attrs) != req_attrs)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Can't judge unless we can compare */
 | 
				
			||||||
 | 
						if (ops->oo_compare == NULL)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return !(ops->oo_compare(a, b, req_attrs, 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compute bitmask representing difference in attribute values
 | 
				
			||||||
 | 
					 * @arg a		an object
 | 
				
			||||||
 | 
					 * @arg b		another object of same type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The bitmask returned is specific to an object type, each bit set represents
 | 
				
			||||||
 | 
					 * an attribute which mismatches in either of the two objects. Unavailability
 | 
				
			||||||
 | 
					 * of an attribute in one object and presence in the other is regarded a
 | 
				
			||||||
 | 
					 * mismatch as well.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Bitmask describing differences or 0 if they are completely identical.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object_ops *ops = obj_ops(a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops != obj_ops(b) || ops->oo_compare == NULL)
 | 
				
			||||||
 | 
							return UINT_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ops->oo_compare(a, b, ~0, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Match a filter against an object
 | 
				
			||||||
 | 
					 * @arg obj		object to check
 | 
				
			||||||
 | 
					 * @arg filter		object of same type acting as filter
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 1 if the object matches the filter or 0
 | 
				
			||||||
 | 
					 *           if no filter procedure is available or if the
 | 
				
			||||||
 | 
					 *           filter does not match.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object_ops *ops = obj_ops(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops != obj_ops(filter) || ops->oo_compare == NULL)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return !(ops->oo_compare(obj, filter, filter->ce_mask,
 | 
				
			||||||
 | 
									 LOOSE_COMPARISON));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert bitmask of attributes to a character string
 | 
				
			||||||
 | 
					 * @arg obj		object of same type as attribute bitmask
 | 
				
			||||||
 | 
					 * @arg attrs		bitmask of attribute types
 | 
				
			||||||
 | 
					 * @arg buf		destination buffer
 | 
				
			||||||
 | 
					 * @arg len		length of destination buffer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Converts the bitmask of attribute types into a list of attribute
 | 
				
			||||||
 | 
					 * names separated by comas.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return destination buffer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
 | 
				
			||||||
 | 
								  char *buf, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_object_ops *ops = obj_ops(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops->oo_attrs2str != NULL)
 | 
				
			||||||
 | 
							return ops->oo_attrs2str(attrs, buf, len);
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							memset(buf, 0, len);
 | 
				
			||||||
 | 
							return buf;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
							
								
								
									
										406
									
								
								package/libnl-tiny/src/socket.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								package/libnl-tiny/src/socket.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,406 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * lib/socket.c		Netlink Socket
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	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) 2003-2008 Thomas Graf <tgraf@suug.ch>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup core
 | 
				
			||||||
 | 
					 * @defgroup socket Socket
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netlink-local.h>
 | 
				
			||||||
 | 
					#include <netlink/netlink.h>
 | 
				
			||||||
 | 
					#include <netlink/utils.h>
 | 
				
			||||||
 | 
					#include <netlink/handlers.h>
 | 
				
			||||||
 | 
					#include <netlink/msg.h>
 | 
				
			||||||
 | 
					#include <netlink/attr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t used_ports_map[32];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t generate_local_port(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, n;
 | 
				
			||||||
 | 
						uint32_t pid = getpid() & 0x3FFFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
 | 
							if (used_ports_map[i] == 0xFFFFFFFF)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (n = 0; n < 32; n++) {
 | 
				
			||||||
 | 
								if (1UL & (used_ports_map[i] >> n))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								used_ports_map[i] |= (1UL << n);
 | 
				
			||||||
 | 
								n += (i * 32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
 | 
				
			||||||
 | 
								 * to, i.e. 1024 unique ports per application. */
 | 
				
			||||||
 | 
								return pid + (n << 22);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Out of sockets in our own PID namespace, what to do? FIXME */
 | 
				
			||||||
 | 
						return UINT_MAX;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void release_local_port(uint32_t port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (port == UINT_MAX)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						nr = port >> 22;
 | 
				
			||||||
 | 
						used_ports_map[nr / 32] &= ~((nr % 32) + 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Allocation
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct nl_sock *__alloc_socket(struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_sock *sk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk = calloc(1, sizeof(*sk));
 | 
				
			||||||
 | 
						if (!sk)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk->s_fd = -1;
 | 
				
			||||||
 | 
						sk->s_cb = cb;
 | 
				
			||||||
 | 
						sk->s_local.nl_family = AF_NETLINK;
 | 
				
			||||||
 | 
						sk->s_peer.nl_family = AF_NETLINK;
 | 
				
			||||||
 | 
						sk->s_seq_expect = sk->s_seq_next = time(0);
 | 
				
			||||||
 | 
						sk->s_local.nl_pid = generate_local_port();
 | 
				
			||||||
 | 
						if (sk->s_local.nl_pid == UINT_MAX) {
 | 
				
			||||||
 | 
							nl_socket_free(sk);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sk;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate new netlink socket
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Newly allocated netlink socket or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_sock *nl_socket_alloc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nl_cb *cb;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						cb = nl_cb_alloc(NL_CB_DEFAULT);
 | 
				
			||||||
 | 
						if (!cb)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return __alloc_socket(cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allocate new socket with custom callbacks
 | 
				
			||||||
 | 
					 * @arg cb		Callback handler
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The reference to the callback handler is taken into account
 | 
				
			||||||
 | 
					 * automatically, it is released again upon calling nl_socket_free().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *@return Newly allocted socket handle or NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (cb == NULL)
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return __alloc_socket(nl_cb_get(cb));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Free a netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_socket_free(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!sk)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_fd >= 0)
 | 
				
			||||||
 | 
							close(sk->s_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(sk->s_flags & NL_OWN_PORT))
 | 
				
			||||||
 | 
							release_local_port(sk->s_local.nl_pid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nl_cb_put(sk->s_cb);
 | 
				
			||||||
 | 
						free(sk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Sequence Numbers
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int noop_seq_check(struct nl_msg *msg, void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NL_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Disable sequence number checking.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Disables checking of sequence numbers on the netlink socket This is
 | 
				
			||||||
 | 
					 * required to allow messages to be processed which were not requested by
 | 
				
			||||||
 | 
					 * a preceding request message, e.g. netlink events.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note This function modifies the NL_CB_SEQ_CHECK configuration in
 | 
				
			||||||
 | 
					 * the callback handle associated with the socket.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_socket_disable_seq_check(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
 | 
				
			||||||
 | 
							  NL_CB_CUSTOM, noop_seq_check, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set local port of socket
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg port		Local port identifier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Assigns a local port identifier to the socket. If port is 0
 | 
				
			||||||
 | 
					 * a unique port identifier will be generated automatically.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (port == 0) {
 | 
				
			||||||
 | 
							port = generate_local_port(); 
 | 
				
			||||||
 | 
							sk->s_flags &= ~NL_OWN_PORT;
 | 
				
			||||||
 | 
						} else  {
 | 
				
			||||||
 | 
							if (!(sk->s_flags & NL_OWN_PORT))
 | 
				
			||||||
 | 
								release_local_port(sk->s_local.nl_pid);
 | 
				
			||||||
 | 
							sk->s_flags |= NL_OWN_PORT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk->s_local.nl_pid = port;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Group Subscriptions
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Join groups
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket
 | 
				
			||||||
 | 
					 * @arg group		Group identifier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Joins the specified groups using the modern socket option which
 | 
				
			||||||
 | 
					 * is available since kernel version 2.6.14. It allows joining an
 | 
				
			||||||
 | 
					 * almost arbitary number of groups without limitation.  The list
 | 
				
			||||||
 | 
					 * of groups has to be terminated by 0 (%NFNLGRP_NONE).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Make sure to use the correct group definitions as the older
 | 
				
			||||||
 | 
					 * bitmask definitions for nl_join_groups() are likely to still
 | 
				
			||||||
 | 
					 * be present for backward compatibility reasons.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on sucess or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						va_list ap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_fd == -1)
 | 
				
			||||||
 | 
							return -NLE_BAD_SOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, group);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (group != 0) {
 | 
				
			||||||
 | 
							if (group < 0)
 | 
				
			||||||
 | 
								return -NLE_INVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
 | 
				
			||||||
 | 
											 &group, sizeof(group));
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group = va_arg(ap, int);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Leave groups
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket
 | 
				
			||||||
 | 
					 * @arg group		Group identifier
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Leaves the specified groups using the modern socket option
 | 
				
			||||||
 | 
					 * which is available since kernel version 2.6.14. The list of groups
 | 
				
			||||||
 | 
					 * has to terminated by 0 (%NFNLGRP_NONE).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see nl_socket_add_membership
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						va_list ap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_fd == -1)
 | 
				
			||||||
 | 
							return -NLE_BAD_SOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, group);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (group != 0) {
 | 
				
			||||||
 | 
							if (group < 0)
 | 
				
			||||||
 | 
								return -NLE_INVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
 | 
				
			||||||
 | 
											 &group, sizeof(group));
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group = va_arg(ap, int);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set file descriptor of socket to non-blocking state
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_socket_set_nonblocking(struct nl_sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (sk->s_fd == -1)
 | 
				
			||||||
 | 
							return -NLE_BAD_SOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @name Utilities
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set socket buffer size of netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg rxbuf		New receive socket buffer size in bytes.
 | 
				
			||||||
 | 
					 * @arg txbuf		New transmit socket buffer size in bytes.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Sets the socket buffer size of a netlink socket to the specified
 | 
				
			||||||
 | 
					 * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
 | 
				
			||||||
 | 
					 * good default value.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note It is not required to call this function prior to nl_connect().
 | 
				
			||||||
 | 
					 * @return 0 on sucess or a negative error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rxbuf <= 0)
 | 
				
			||||||
 | 
							rxbuf = 32768;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (txbuf <= 0)
 | 
				
			||||||
 | 
							txbuf = 32768;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_fd == -1)
 | 
				
			||||||
 | 
							return -NLE_BAD_SOCK;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
 | 
				
			||||||
 | 
								 &txbuf, sizeof(txbuf));
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
 | 
				
			||||||
 | 
								 &rxbuf, sizeof(rxbuf));
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk->s_flags |= NL_SOCK_BUFSIZE_SET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Enable/disable credential passing on netlink socket.
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg state		New state (0 - disabled, 1 - enabled)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_socket_set_passcred(struct nl_sock *sk, int state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_fd == -1)
 | 
				
			||||||
 | 
							return -NLE_BAD_SOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
 | 
				
			||||||
 | 
								 &state, sizeof(state));
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state)
 | 
				
			||||||
 | 
							sk->s_flags |= NL_SOCK_PASSCRED;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							sk->s_flags &= ~NL_SOCK_PASSCRED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Enable/disable receival of additional packet information
 | 
				
			||||||
 | 
					 * @arg sk		Netlink socket.
 | 
				
			||||||
 | 
					 * @arg state		New state (0 - disabled, 1 - enabled)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success or a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sk->s_fd == -1)
 | 
				
			||||||
 | 
							return -NLE_BAD_SOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
 | 
				
			||||||
 | 
								 &state, sizeof(state));
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return -nl_syserr2nlerr(errno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user