Compare commits
134 Commits
libnl3_2_1
...
master
Author | SHA1 | Date |
---|---|---|
Patrick McHardy | 6ae22c1b39 | |
Thomas Graf | 01cfa9c1db | |
Holger Eitzenberger | d612180cda | |
Holger Eitzenberger | 34a96ba5c2 | |
Andrew Collins | 53ac502a2b | |
Andrew Collins | 87bbfb6b12 | |
Thomas Graf | c1de0f3129 | |
Michael Braun | c76393e203 | |
Thomas Graf | c4d846f239 | |
Thomas Graf | 807fddc4cd | |
Nathan Lynch | 8983fa9914 | |
Thomas Graf | 183052d047 | |
Thomas Graf | ed1f4cba2c | |
Thomas Graf | 4e9aa6a9a6 | |
Thomas Graf | ffc0ee3540 | |
Emmanuel Thierry | 979ea335b0 | |
Thomas Graf | 3a6d256da5 | |
Thomas Graf | 37f788f391 | |
Thomas Graf | c07a6a30c2 | |
Коренберг Марк (дома) | 33396faca5 | |
Thomas Graf | ead4cdeb99 | |
Коренберг Марк (дома) | 59db7fb35b | |
Thomas Graf | d505165f2b | |
Thomas Graf | d3cf89ea94 | |
Emmanuel Roullit | ea436445ad | |
Thomas Graf | 56eb22fa74 | |
Thomas Graf | 375a6294a4 | |
Thomas Graf | df66b0f267 | |
Holger Eitzenberger | 18152ca916 | |
Thomas Graf | ff567100d6 | |
Thomas Graf | f9241d57fe | |
Patrick McHardy | d2b5cbd88a | |
Thomas Graf | ad545f2854 | |
Thomas Graf | aad041c46f | |
roopa | 6c9be5a316 | |
Tony Cheneau | 23e26e9e05 | |
Tony Cheneau | 4db11517fd | |
Thomas Graf | b39c9f7a53 | |
Thomas Graf | 549d26dc87 | |
Thomas Graf | e09e7f1035 | |
Thomas Graf | 780a0423dc | |
Thomas Graf | 88527534ba | |
Thomas Graf | f0f33c394b | |
Thomas Graf | f72bfc7220 | |
Thomas Graf | c608b4d151 | |
Thomas Graf | 1395c69901 | |
Thomas Graf | 64315f731c | |
Thomas Graf | 60b370de8c | |
Thomas Graf | 9e6cdbf6fc | |
Thomas Graf | 4d7680c19c | |
roopa | ded20487fd | |
roopa | 8f151fadda | |
Thomas Graf | 1ecf98a23e | |
Thomas Graf | ee4122a12e | |
Thomas Graf | bb9911b5a3 | |
Thomas Graf | 5a5aa73158 | |
Thomas Graf | fd19dae352 | |
Thomas Graf | 9f8548b551 | |
Thomas Graf | 8026fe2e3a | |
Thomas Graf | 4a793a4235 | |
Thomas Graf | e5767684a6 | |
Thomas Graf | 2d36371aa1 | |
Thomas Graf | 8b8e26b333 | |
Holger Dengler | 506020ae99 | |
Thomas Graf | 1c24480180 | |
Thomas Graf | 8571f58f23 | |
Thomas Graf | 2005c2ecac | |
Thomas Graf | 87458abbd0 | |
Thomas Graf | 73cb5f57ba | |
roopa | b06c23a9dd | |
Rich Fought | 4f088d38ae | |
Benedikt Spranger | 6cc5fdc0e9 | |
Thomas Graf | 4cb375a812 | |
Rich Fought | 87244f739c | |
Thomas Graf | 83c762d7cf | |
Thomas Graf | b6afd0bf1a | |
Thomas Graf | 776cde0a10 | |
Thomas Graf | c4f803366e | |
Thomas Graf | c6abb44e38 | |
Thomas Graf | 1b9de9a49d | |
Thomas Graf | 9680f910f4 | |
Rich Fought | 56352ab9f6 | |
Jiri Pirko | 1419851eb4 | |
Thomas Graf | 26e22d887e | |
roopa | 1481f97d36 | |
Thomas Graf | 2b96c3381d | |
Thomas Graf | f20bbe1f07 | |
Thomas Graf | 7559157f2d | |
Thomas Graf | 5291af6fb5 | |
roopa | 5c3f2f015a | |
roopa | 99399ca9c0 | |
Thomas Graf | 6b4a2cb634 | |
roopa | 310ec86b39 | |
roopa | 09213ee5ee | |
roopa | b1ebda9241 | |
Flavio Leitner | 3540e44b15 | |
Patrick McHardy | 94cd080452 | |
Patrick McHardy | c2fdebea42 | |
Patrick McHardy | 4cec8d361c | |
Patrick McHardy | 68915b1292 | |
Patrick McHardy | 450d03b24b | |
Patrick McHardy | 29abe5d86f | |
Patrick McHardy | 93a9e4dc6a | |
Erik Tews | 3c6622aeb8 | |
Patrick McHardy | 2a591b7b2b | |
Patrick McHardy | 56a447dffd | |
Patrick McHardy | ac50c84f8c | |
Patrick McHardy | 2dc8bc1921 | |
Patrick McHardy | 432a1a31f2 | |
Patrick McHardy | edaf9cac24 | |
Patrick McHardy | 2080dce45e | |
Patrick McHardy | ac263675d1 | |
Patrick McHardy | a9886abe70 | |
Patrick McHardy | 6ff91c4799 | |
Patrick McHardy | 47a4c5a4c0 | |
Patrick McHardy | c17d47977e | |
Patrick McHardy | 44fde8fcbb | |
Patrick McHardy | 2826c89a77 | |
Patrick McHardy | 17e2ac82ca | |
Patrick McHardy | d9c446dd4f | |
Patrick McHardy | ff81f73c8a | |
Patrick McHardy | accc75c463 | |
Patrick McHardy | 71f3690295 | |
Patrick McHardy | f5b6c85296 | |
Patrick McHardy | c335c58b68 | |
Patrick McHardy | 464d806d27 | |
Patrick McHardy | 9a8cbfdf5a | |
Patrick McHardy | c60e16afd0 | |
Patrick McHardy | d9cf87a0bc | |
Patrick McHardy | 1d25939936 | |
Patrick McHardy | 598dcf6c52 | |
Patrick McHardy | 85e8099cc4 | |
Patrick McHardy | be93d3d46c | |
Patrick McHardy | b24d4fa5db |
62
configure.ac
62
configure.ac
|
@ -6,37 +6,37 @@
|
|||
# License as published by the Free Software Foundation version 2.1
|
||||
# of the License.
|
||||
#
|
||||
# Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
|
||||
# Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
#
|
||||
|
||||
|
||||
# copied from glib
|
||||
m4_define([libnl_major_version], [3])
|
||||
m4_define([libnl_minor_version], [2])
|
||||
m4_define([libnl_micro_version], [18])
|
||||
m4_define([libnl_micro_version], [22])
|
||||
|
||||
|
||||
# If either revision or age are omitted, they default to 0. Also note that age
|
||||
# must be less than or equal to the current interface number.
|
||||
# The following explanation may help to understand the above rules a bit
|
||||
# better: consider that there are three possible kinds of reactions from
|
||||
# users of your library to changes in a shared library:
|
||||
#
|
||||
# Here are a set of rules to help you update your library version information:
|
||||
# 1. Programs using the previous version may use the new version as drop-in
|
||||
# replacement, and programs using the new version can also work with the
|
||||
# previous one. In other words, no recompiling nor relinking is needed.
|
||||
# In this case, bump revision only, don't touch current nor age.
|
||||
#
|
||||
# 1. Start with version information of `0:0:0' for each libtool library.
|
||||
# 2. Update the version information only immediately before a public release
|
||||
# of your software. More frequent updates are unnecessary, and only
|
||||
# guarantee that the current interface number gets larger faster.
|
||||
# 3. If the library source code has changed at all since the last update, then
|
||||
# increment revision (`c:r:a' becomes `c:r+1:a').
|
||||
# 4. If any interfaces have been added, removed, or changed since the last
|
||||
# update, increment current, and set revision to 0.
|
||||
# 5. If any interfaces have been added since the last public release, then
|
||||
# increment age.
|
||||
# 6. If any interfaces have been removed since the last public release, then
|
||||
# set age to 0.
|
||||
# 2. Programs using the previous version may use the new version as drop-in
|
||||
# replacement, but programs using the new version may use APIs not
|
||||
# present in the previous one. In other words, a program linking against
|
||||
# the new version may fail with “unresolved symbols” if linking against
|
||||
# the old version at runtime: set revision to 0, bump current and age.
|
||||
#
|
||||
# 3. Programs may need to be changed, recompiled, relinked in order to use
|
||||
# the new version. Bump current, set revision and age to 0.
|
||||
|
||||
m4_define([libnl_lt_current], [214])
|
||||
m4_define([libnl_lt_revision], [1])
|
||||
m4_define([libnl_lt_age], [13])
|
||||
m4_define([libnl_lt_current], [217])
|
||||
m4_define([libnl_lt_revision], [0])
|
||||
m4_define([libnl_lt_age], [17])
|
||||
|
||||
m4_define([libnl_version],
|
||||
[libnl_major_version.libnl_minor_version.libnl_micro_version])
|
||||
|
@ -75,6 +75,13 @@ AC_CHECK_PROGS(YACC, 'bison -y')
|
|||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
|
||||
PKG_CHECK_MODULES([CHECK], [check >= 0.9.0],
|
||||
[enable_unit_tests="yes"],
|
||||
[AC_MSG_WARN([*** Disabling building of unit tests])
|
||||
enable_unit_tests="no"])
|
||||
|
||||
AM_CONDITIONAL([ENABLE_UNIT_TESTS], [test "$enable_unit_tests" = "yes"])
|
||||
|
||||
AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH],
|
||||
[Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]),
|
||||
[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
|
||||
|
@ -90,6 +97,11 @@ AC_ARG_ENABLE([pthreads],
|
|||
[enable_pthreads="$enableval"], [enable_pthreads="yes"])
|
||||
AM_CONDITIONAL([DISABLE_PTHREADS], [test "$enable_pthreads" = "no"])
|
||||
|
||||
AC_ARG_ENABLE([debug],
|
||||
AS_HELP_STRING([--disable-debug], [Do not include debugging statements]),
|
||||
[enable_debug="$enableval"], [enable_debug="yes"])
|
||||
AM_CONDITIONAL([ENABLE_DEBUG], [test "$enable_debug" = "no" ])
|
||||
|
||||
AC_CHECK_LIB([m], [pow], [], AC_MSG_ERROR([libm is required]))
|
||||
|
||||
if test "x$enable_pthreads" = "xno"; then
|
||||
|
@ -98,6 +110,10 @@ else
|
|||
AC_CHECK_LIB([pthread], [pthread_mutex_lock], [], AC_MSG_ERROR([libpthread is required]))
|
||||
fi
|
||||
|
||||
if test "x$enable_debug" = "xyes"; then
|
||||
AC_DEFINE([NL_DEBUG], [1], [Define to 1 to enable debugging])
|
||||
fi
|
||||
|
||||
AC_CONFIG_SUBDIRS([doc])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
|
@ -106,6 +122,7 @@ libnl-3.0.pc
|
|||
libnl-route-3.0.pc
|
||||
libnl-genl-3.0.pc
|
||||
libnl-nf-3.0.pc
|
||||
libnl-dect-3.0.pc
|
||||
libnl-cli-3.0.pc
|
||||
lib/Makefile
|
||||
include/Makefile
|
||||
|
@ -149,10 +166,7 @@ echo " - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the S
|
|||
echo " libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc."
|
||||
echo ""
|
||||
echo " - libtool versioning was assumed, to ease detection of compatible library"
|
||||
echo " versions. libnl-${MAJ_VERSION}.so.CURRENT.REVISION.AGE where."
|
||||
echo " CURRENT := 100 * \$MINOR_VERSION + \$MICRO_VERSION"
|
||||
echo " REVISION := nth revision if API was unchanged"
|
||||
echo " AGE := nth revision that is backwards compatible."
|
||||
echo " versions."
|
||||
echo ""
|
||||
echo " If you are using pkg-config for detecting and linking against the library "
|
||||
echo " things will continue magically as if nothing every happened. If you are "
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
# License as published by the Free Software Foundation version 2.1
|
||||
# of the License.
|
||||
#
|
||||
# Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
|
||||
# Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
#
|
||||
|
||||
AC_INIT(libnl-doc, [3.2.18], [http://www.infradead.org/~tgr/libnl/])
|
||||
AC_INIT(libnl-doc, [3.2.22], [http://www.infradead.org/~tgr/libnl/])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
|
|
@ -2316,6 +2316,7 @@ int put_opts(struct nl_msg *msg)
|
|||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(msg, opts);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
--------
|
||||
|
|
|
@ -645,9 +645,8 @@ This attribute is unused and obsoleted in all recent kernels.
|
|||
|
||||
struct rtnl_link *link;
|
||||
|
||||
link = rtnl_link_alloc();
|
||||
link = rtnl_link_bond_alloc();
|
||||
rtnl_link_set_name(link, "my_bond");
|
||||
rtnl_link_set_type(link, "bond");
|
||||
|
||||
/* requires admin privileges */
|
||||
if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0)
|
||||
|
@ -693,16 +692,70 @@ int master_index;
|
|||
if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
|
||||
/* error */
|
||||
|
||||
/* allocate new link object to configure the vlan device */
|
||||
link = rtnl_link_alloc();
|
||||
/* allocate new link object of type vlan */
|
||||
link = rtnl_link_vlan_alloc();
|
||||
|
||||
/* set eth0 to be our master device */
|
||||
rtnl_link_set_link(link, master_index);
|
||||
|
||||
if ((err = rtnl_link_set_type(link, "vlan")) < 0)
|
||||
rtnl_link_vlan_set_id(link, 10);
|
||||
|
||||
if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
|
||||
/* error */
|
||||
|
||||
rtnl_link_vlan_set_id(link, 10);
|
||||
rtnl_link_put(link);
|
||||
-----
|
||||
|
||||
[[link_macvlan]]
|
||||
==== MACVLAN
|
||||
|
||||
[source,c]
|
||||
-----
|
||||
extern struct rtnl_link *rtnl_link_macvlan_alloc(void);
|
||||
|
||||
extern int rtnl_link_is_macvlan(struct rtnl_link *);
|
||||
|
||||
extern char * rtnl_link_macvlan_mode2str(int, char *, size_t);
|
||||
extern int rtnl_link_macvlan_str2mode(const char *);
|
||||
|
||||
extern char * rtnl_link_macvlan_flags2str(int, char *, size_t);
|
||||
extern int rtnl_link_macvlan_str2flags(const char *);
|
||||
|
||||
extern int rtnl_link_macvlan_set_mode(struct rtnl_link *,
|
||||
uint32_t);
|
||||
extern uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *);
|
||||
|
||||
extern int rtnl_link_macvlan_set_flags(struct rtnl_link *,
|
||||
uint16_t);
|
||||
extern int rtnl_link_macvlan_unset_flags(struct rtnl_link *,
|
||||
uint16_t);
|
||||
extern uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *);
|
||||
-----
|
||||
|
||||
.Example: Add a MACVLAN device
|
||||
[source,c]
|
||||
-----
|
||||
struct rtnl_link *link;
|
||||
int master_index;
|
||||
struct nl_addr* addr;
|
||||
|
||||
/* lookup interface index of eth0 */
|
||||
if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
|
||||
/* error */
|
||||
|
||||
/* allocate new link object of type macvlan */
|
||||
link = rtnl_link_macvlan_alloc();
|
||||
|
||||
/* set eth0 to be our master device */
|
||||
rtnl_link_set_link(link, master_index);
|
||||
|
||||
/* set address of virtual interface */
|
||||
addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN);
|
||||
rtnl_link_set_addr(link, addr);
|
||||
nl_addr_put(addr);
|
||||
|
||||
/* set mode of virtual interface */
|
||||
rtnl_link_macvlan_set_mode(link, rtnl_link_macvlan_str2mode("bridge"));
|
||||
|
||||
if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
|
||||
/* error */
|
||||
|
|
|
@ -17,9 +17,14 @@ nobase_libnlinclude_HEADERS = \
|
|||
netlink/netfilter/nfnl.h \
|
||||
netlink/netfilter/queue.h \
|
||||
netlink/netfilter/queue_msg.h \
|
||||
netlink/dect/ari.h \
|
||||
netlink/dect/cell.h \
|
||||
netlink/dect/cluster.h \
|
||||
netlink/dect/dect.h \
|
||||
netlink/dect/llme.h \
|
||||
netlink/dect/transceiver.h \
|
||||
netlink/addr.h \
|
||||
netlink/attr.h \
|
||||
netlink/cache-api.h \
|
||||
netlink/cache.h \
|
||||
netlink/data.h \
|
||||
netlink/errno.h \
|
||||
|
@ -31,7 +36,6 @@ nobase_libnlinclude_HEADERS = \
|
|||
netlink/netlink-compat.h \
|
||||
netlink/netlink-kernel.h \
|
||||
netlink/netlink.h \
|
||||
netlink/object-api.h \
|
||||
netlink/object.h \
|
||||
netlink/route/cls/ematch/cmp.h \
|
||||
netlink/route/cls/ematch/meta.h \
|
||||
|
@ -43,12 +47,12 @@ nobase_libnlinclude_HEADERS = \
|
|||
netlink/route/cls/fw.h \
|
||||
netlink/route/cls/police.h \
|
||||
netlink/route/cls/u32.h \
|
||||
netlink/route/link/api.h \
|
||||
netlink/route/link/bonding.h \
|
||||
netlink/route/link/bridge.h \
|
||||
netlink/route/link/can.h \
|
||||
netlink/route/link/info-api.h \
|
||||
netlink/route/link/inet.h \
|
||||
netlink/route/link/vlan.h \
|
||||
netlink/route/link/macvlan.h \
|
||||
netlink/route/qdisc/cbq.h \
|
||||
netlink/route/qdisc/dsmark.h \
|
||||
netlink/route/qdisc/fifo.h \
|
||||
|
@ -72,11 +76,16 @@ nobase_libnlinclude_HEADERS = \
|
|||
netlink/route/rtnl.h \
|
||||
netlink/route/rule.h \
|
||||
netlink/route/tc.h \
|
||||
netlink/route/tc-api.h \
|
||||
netlink/socket.h \
|
||||
netlink/types.h \
|
||||
netlink/utils.h \
|
||||
netlink/version.h
|
||||
netlink/version.h \
|
||||
netlink/cache-api.h \
|
||||
netlink/object-api.h \
|
||||
netlink/route/link/api.h \
|
||||
netlink/route/link/info-api.h \
|
||||
netlink/route/tc-api.h
|
||||
|
||||
|
||||
if ENABLE_CLI
|
||||
nobase_libnlinclude_HEADERS += \
|
||||
|
@ -102,11 +111,13 @@ noinst_HEADERS = \
|
|||
linux/if_arp.h \
|
||||
linux/if_ether.h \
|
||||
linux/if.h \
|
||||
linux/if_bridge.h \
|
||||
linux/if_link.h \
|
||||
linux/if_vlan.h \
|
||||
linux/inetdevice.h \
|
||||
linux/ip_mp_alg.h \
|
||||
linux/ipv6.h \
|
||||
linux/can/netlink.h \
|
||||
linux/neighbour.h \
|
||||
linux/netfilter.h \
|
||||
linux/netfilter/nf_conntrack_common.h \
|
||||
|
@ -121,7 +132,11 @@ noinst_HEADERS = \
|
|||
linux/rtnetlink.h \
|
||||
linux/snmp.h \
|
||||
linux/tc_ematch/tc_em_meta.h \
|
||||
netlink-generic.h \
|
||||
netlink-local.h \
|
||||
netlink-tc.h \
|
||||
netlink-types.h
|
||||
netlink-private/genl.h \
|
||||
netlink-private/netlink.h \
|
||||
netlink-private/tc.h \
|
||||
netlink-private/types.h \
|
||||
netlink-private/cache-api.h \
|
||||
netlink-private/object-api.h \
|
||||
netlink-private/route/link/api.h \
|
||||
netlink-private/route/tc-api.h
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
#ifndef _LINUX_DECT_H
|
||||
#define _LINUX_DECT_H
|
||||
|
||||
#define DECTNAMSIZ 16
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/socket.h>
|
||||
|
||||
/* these have to be macros in order to be usable for module aliases */
|
||||
#define DECT_RAW 0 /* raw frames */
|
||||
#define DECT_B_SAP 1 /* DLC Broadcast Service */
|
||||
#define DECT_S_SAP 2 /* DLC Data Link Service */
|
||||
#define DECT_LU1_SAP 3 /* LU1 sockets */
|
||||
#define DECT_PROTO_NUM 4
|
||||
|
||||
/**
|
||||
* struct sockaddr_dect
|
||||
*
|
||||
* @dect_family: address family (AF_DECT)
|
||||
* @dect_index: cluster index
|
||||
*/
|
||||
struct sockaddr_dect {
|
||||
sa_family_t dect_family;
|
||||
int dect_index;
|
||||
};
|
||||
|
||||
/* raw sockets */
|
||||
|
||||
#define DECT_RAW_AUXDATA 0
|
||||
|
||||
/**
|
||||
* struct dect_raw_auxdata - raw socket auxiliary frame data
|
||||
*
|
||||
* @mfn: multi-frame number
|
||||
* @frame: frame number
|
||||
* @slot: slot numer
|
||||
* @rssi: receive signal strength indicator
|
||||
*/
|
||||
struct dect_raw_auxdata {
|
||||
__u32 mfn;
|
||||
__u8 frame;
|
||||
__u8 slot;
|
||||
__u8 rssi;
|
||||
};
|
||||
|
||||
#define DECT_BSAP_AUXDATA 0
|
||||
|
||||
/**
|
||||
* struct dect_bsap_auxdata
|
||||
*
|
||||
* @long_page: message contains a long page
|
||||
*/
|
||||
struct dect_bsap_auxdata {
|
||||
__u8 long_page;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dect_sapis - S SAP Identifier
|
||||
*
|
||||
* @DECT_SAPI_CO_SIGNALLING: connection oriented signalling
|
||||
* @DECT_SAPI_CL_SIGNALLING: connectionless signalling
|
||||
* @DECT_SAPI_ANY: wildcard
|
||||
*/
|
||||
enum dect_sapis {
|
||||
DECT_SAPI_CO_SIGNALLING = 0,
|
||||
DECT_SAPI_CL_SIGNALLING = 3,
|
||||
DECT_SAPI_ANY = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dect_llns - Logical Link Numbers
|
||||
*
|
||||
* @DECT_LLN_CLASS_U: Class U operation
|
||||
* @DECT_LLN_CLASS_A: Class A operation
|
||||
* @DECT_LLN_ASSIGNABLE*: Assignable LLN (class B operation)
|
||||
* @DECT_LLN_UNASSIGNED: LLN unassigned (class B operation
|
||||
* @DECT_LLN_ANY: wildcard
|
||||
*/
|
||||
enum dect_llns {
|
||||
DECT_LLN_CLASS_U = 0,
|
||||
DECT_LLN_CLASS_A = 1,
|
||||
DECT_LLN_ASSIGNABLE_MIN = 2,
|
||||
DECT_LLN_ASSIGNABLE_MAX = 6,
|
||||
DECT_LLN_UNASSIGNED = 7,
|
||||
DECT_LLN_ANY = 15,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sockaddr_dect_ssap
|
||||
*
|
||||
* @dect_family: family (AF_DECT)
|
||||
* @dect_lln: logical link number
|
||||
* @dect_sapi: service access point identifier
|
||||
* @dect_class: class A/B
|
||||
* @dect_index: cluster index
|
||||
* @dect_ari: ARI
|
||||
* @dect_pmid: PMID
|
||||
* @dect_lcn: logical connection number
|
||||
*/
|
||||
struct sockaddr_dect_ssap {
|
||||
sa_family_t dect_family;
|
||||
__u8 dect_lln:4,
|
||||
dect_sapi:3;
|
||||
__u8 dect_class;
|
||||
int dect_index;
|
||||
__u64 dect_ari:40,
|
||||
dect_pmid:20,
|
||||
dect_lcn:3;
|
||||
};
|
||||
|
||||
/* S-SAP primitives */
|
||||
#define DECT_DL_ENC_KEY 1
|
||||
#define DECT_DL_ENCRYPT 2
|
||||
#define DECT_DL_MAC_CONN_PARAMS 3
|
||||
|
||||
enum dect_cipher_states {
|
||||
DECT_CIPHER_DISABLED,
|
||||
DECT_CIPHER_ENABLED,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dect_mac_connection_types - MAC Connection types
|
||||
*
|
||||
* @DECT_MAC_CONN_BASIC: Basic connection, always I_N_min_delay service
|
||||
* @DECT_MAC_CONN_ADVANCED: Advanced connection
|
||||
* @DECT_MAC_CONN_COMPLEMENT: Complementary connection
|
||||
*/
|
||||
enum dect_mac_connection_types {
|
||||
DECT_MAC_CONN_BASIC,
|
||||
DECT_MAC_CONN_ADVANCED,
|
||||
DECT_MAC_CONN_COMPLEMENT,
|
||||
};
|
||||
|
||||
enum dect_mac_service_types {
|
||||
DECT_SERVICE_IN_MIN_DELAY = 0x0,
|
||||
DECT_SERVICE_IPX_ENCODED_PROTECTED = 0x1,
|
||||
DECT_SERVICE_IN_NORMAL_DELAY = 0x2,
|
||||
DECT_SERVICE_UNKNOWN = 0x4,
|
||||
DECT_SERVICE_C_CHANNEL_ONLY = 0x5,
|
||||
DECT_SERVICE_IP_ERROR_DETECTION = 0x10,
|
||||
DECT_SERVICE_IPQ_ERROR_DETECTION = 0x14,
|
||||
/* Lifetime encoded in low three bits */
|
||||
DECT_SERVICE_IP_ERROR_CORRECTION = 0x18,
|
||||
DECT_SERVICE_IPQ_ERROR_CORRECTION = 0x38,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dect_slot_types - DECT slot types
|
||||
*
|
||||
* @DECT_FULL_SLOT: Full-slot format (480 bits)
|
||||
* @DECT_HALF_SLOT: Half-slot format (240 bits)
|
||||
* @DECT_DOUBLE_SLOT: Double-slot format (960 bits)
|
||||
* @DECT_LONG_SLOT_j640: Long slot format j=640 (800 bits)
|
||||
* @DECT_LONG_SLOT_j672: Long slot format j=672 (832 bits)
|
||||
*
|
||||
* The numeric values must match the MAC-layer attributes-T coding.
|
||||
*/
|
||||
enum dect_slot_types {
|
||||
DECT_FULL_SLOT = 0x0,
|
||||
DECT_HALF_SLOT = 0x1,
|
||||
DECT_DOUBLE_SLOT = 0x2,
|
||||
DECT_LONG_SLOT_640 = 0x3,
|
||||
DECT_LONG_SLOT_672 = 0x4,
|
||||
};
|
||||
|
||||
struct dect_mac_conn_params {
|
||||
enum dect_mac_connection_types type;
|
||||
enum dect_mac_service_types service;
|
||||
enum dect_slot_types slot;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dect_dl_encrypt - DL_ENCRYPT primitive arguments
|
||||
*
|
||||
* @status: desired/achieved encryption status
|
||||
*/
|
||||
struct dect_dl_encrypt {
|
||||
enum dect_cipher_states status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sockaddr_dect_lu - DLC U-plane LUx service instance address
|
||||
*
|
||||
* @dect_family: address family (AF_DECT)
|
||||
* @dect_mci: MAC Connection Identifier
|
||||
*/
|
||||
struct sockaddr_dect_lu {
|
||||
sa_family_t dect_family;
|
||||
int dect_index;
|
||||
__u64 dect_ari:40,
|
||||
dect_pmid:20,
|
||||
dect_lcn:3;
|
||||
};
|
||||
|
||||
/* LU1 SAP */
|
||||
|
||||
#define DECT_LU1_QUEUE_STATS 0
|
||||
|
||||
struct dect_lu1_queue_stats {
|
||||
__u32 rx_bytes;
|
||||
__u32 rx_underflow;
|
||||
__u32 tx_bytes;
|
||||
__u32 tx_underflow;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_DECT_H */
|
|
@ -0,0 +1,397 @@
|
|||
#ifndef _LINUX_DECT_NETLINK_H
|
||||
#define _LINUX_DECT_NETLINK_H
|
||||
|
||||
struct dectmsg {
|
||||
int dm_index;
|
||||
};
|
||||
|
||||
enum dect_nlgroups {
|
||||
DECTNLGRP_NONE,
|
||||
DECTNLGRP_TRANSCEIVER,
|
||||
DECTNLGRP_CELL,
|
||||
DECTNLGRP_CLUSTER,
|
||||
DECTNLGRP_LLME,
|
||||
__DECTNLGRP_MAX
|
||||
};
|
||||
#define DECTNLGRP_MAX (__DECTNLGRP_MAX - 1)
|
||||
|
||||
enum dect_netlink_msg_types {
|
||||
DECT_MSG_BASE = 0x10,
|
||||
DECT_NEW_TRANSCEIVER,
|
||||
DECT_DEL_TRANSCEIVER,
|
||||
DECT_GET_TRANSCEIVER,
|
||||
DECT_NEW_CELL,
|
||||
DECT_DEL_CELL,
|
||||
DECT_GET_CELL,
|
||||
DECT_NEW_CLUSTER,
|
||||
DECT_DEL_CLUSTER,
|
||||
DECT_GET_CLUSTER,
|
||||
DECT_LLME_MSG,
|
||||
__DECT_MSG_MAX
|
||||
};
|
||||
#define DECT_MSG_MAX (__DECT_MSG_MAX - 1)
|
||||
|
||||
#define DECT_NR_MSGTYPES (DECT_MSG_MAX + 1 - DECT_MSG_BASE)
|
||||
|
||||
enum dect_list_attrs {
|
||||
DECTA_LIST_UNSPEC,
|
||||
DECTA_LIST_ELEM,
|
||||
__DECTA_LIST_MAX
|
||||
};
|
||||
#define DECTA_LIST_MAX (__DECTA_LIST_MAX - 1)
|
||||
|
||||
enum dect_slot_states {
|
||||
DECT_SLOT_IDLE,
|
||||
DECT_SLOT_SCANNING,
|
||||
DECT_SLOT_RX,
|
||||
DECT_SLOT_TX,
|
||||
};
|
||||
|
||||
enum dect_slot_flags {
|
||||
DECT_SLOT_SYNC = 0x1,
|
||||
DECT_SLOT_CIPHER = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dect_packet_types - DECT Physical Packet Types
|
||||
*
|
||||
* @DECT_PACKET_P00: short physical packet P00, 96 bits, A-field only
|
||||
* @DECT_PACKET_P08: low capacity physical packet P08j, 180 bits
|
||||
* @DECT_PACKET_P32: basic physical packet P32, 420 bits
|
||||
* @DECT_PACKET_P80: high capacity physical packet P80, 900 bits
|
||||
* @DECT_PACKET_P640j: variable capacity packet P640j, 712 bits
|
||||
* @DECT_PACKET_P672j: variable capacity packet P640j, 744 bits
|
||||
*/
|
||||
enum dect_packet_types {
|
||||
DECT_PACKET_P00,
|
||||
DECT_PACKET_P08,
|
||||
DECT_PACKET_P32,
|
||||
DECT_PACKET_P80,
|
||||
DECT_PACKET_P640j,
|
||||
DECT_PACKET_P672j,
|
||||
__DECT_PACKET_MAX
|
||||
};
|
||||
#define DECT_PACKET_MAX (__DECT_PACKET_MAX - 1)
|
||||
|
||||
#define DECT_PHASE_OFFSET_SCALE 1024
|
||||
|
||||
enum dect_slot_attrs {
|
||||
DECTA_SLOT_UNSPEC,
|
||||
DECTA_SLOT_NUM,
|
||||
DECTA_SLOT_STATE,
|
||||
DECTA_SLOT_FLAGS,
|
||||
DECTA_SLOT_PACKET,
|
||||
DECTA_SLOT_CARRIER,
|
||||
DECTA_SLOT_FREQUENCY,
|
||||
DECTA_SLOT_PHASEOFF,
|
||||
DECTA_SLOT_RSSI,
|
||||
DECTA_SLOT_RX_PACKETS,
|
||||
DECTA_SLOT_RX_BYTES,
|
||||
DECTA_SLOT_RX_A_CRC_ERRORS,
|
||||
DECTA_SLOT_RX_X_CRC_ERRORS,
|
||||
DECTA_SLOT_RX_Z_CRC_ERRORS,
|
||||
DECTA_SLOT_TX_PACKETS,
|
||||
DECTA_SLOT_TX_BYTES,
|
||||
__DECTA_SLOT_MAX
|
||||
};
|
||||
#define DECTA_SLOT_MAX (__DECTA_SLOT_MAX - 1)
|
||||
|
||||
enum dect_transceiver_stats_attrs {
|
||||
DECTA_TRANSCEIVER_STATS_UNSPEC,
|
||||
DECTA_TRANSCEIVER_STATS_EVENT_BUSY,
|
||||
DECTA_TRANSCEIVER_STATS_EVENT_LATE,
|
||||
__DECTA_TRANSCEIVER_STATS_MAX
|
||||
};
|
||||
#define DECTA_TRANSCEIVER_STATS_MAX (__DECTA_TRANSCEIVER_STATS_MAX - 1)
|
||||
|
||||
/**
|
||||
* @DECT_TRANSCEIVER_SLOW_HOPPING: transceiver has slow hopping radio
|
||||
* @DECT_TRANSCEIVER_PACKET_P64: transceiver supports packet P640j
|
||||
*/
|
||||
enum dect_transceiver_features {
|
||||
DECT_TRANSCEIVER_SLOW_HOPPING = 0x1,
|
||||
DECT_TRANSCEIVER_PACKET_P64 = 0x2,
|
||||
};
|
||||
|
||||
enum dect_transceiver_attrs {
|
||||
DECTA_TRANSCEIVER_UNSPEC,
|
||||
DECTA_TRANSCEIVER_NAME,
|
||||
DECTA_TRANSCEIVER_TYPE,
|
||||
DECTA_TRANSCEIVER_FEATURES,
|
||||
DECTA_TRANSCEIVER_LINK,
|
||||
DECTA_TRANSCEIVER_STATS,
|
||||
DECTA_TRANSCEIVER_BAND,
|
||||
DECTA_TRANSCEIVER_SLOTS,
|
||||
__DECTA_TRANSCEIVER_MAX
|
||||
};
|
||||
#define DECTA_TRANSCEIVER_MAX (__DECTA_TRANSCEIVER_MAX - 1)
|
||||
|
||||
enum dect_cell_flags {
|
||||
DECT_CELL_CCP = (1 << 0),
|
||||
DECT_CELL_SLAVE = (1 << 1),
|
||||
DECT_CELL_MONITOR = (1 << 2),
|
||||
};
|
||||
|
||||
enum dect_cell_attrs {
|
||||
DECTA_CELL_UNSPEC,
|
||||
DECTA_CELL_NAME,
|
||||
DECTA_CELL_FLAGS,
|
||||
DECTA_CELL_TRANSCEIVERS,
|
||||
DECTA_CELL_CLUSTER,
|
||||
__DECTA_CELL_MAX
|
||||
};
|
||||
#define DECTA_CELL_MAX (__DECTA_CELL_MAX - 1)
|
||||
|
||||
enum dect_mbc_state {
|
||||
DECT_MBC_NONE,
|
||||
DECT_MBC_INITIATED,
|
||||
DECT_MBC_ESTABLISHED,
|
||||
DECT_MBC_RELEASED,
|
||||
};
|
||||
|
||||
enum dect_mbc_tb_attrs {
|
||||
DECTA_MBC_TB_UNSPEC,
|
||||
DECTA_MBC_TB_LBN,
|
||||
DECTA_MBC_TB_ECN,
|
||||
DECTA_MBC_TB_CELL,
|
||||
DECTA_MBC_TB_RX_SLOT,
|
||||
DECTA_MBC_TB_TX_SLOT,
|
||||
__DECTA_MBC_TB_MAX,
|
||||
};
|
||||
#define DECTA_MBC_TB_MAX (__DECTA_MBC_TB_MAX - 1)
|
||||
|
||||
enum dect_mbc_stats_attrs {
|
||||
DECTA_MBC_STATS_UNSPEC,
|
||||
DECTA_MBC_STATS_CS_RX_BYTES,
|
||||
DECTA_MBC_STATS_CS_TX_BYTES,
|
||||
DECTA_MBC_STATS_I_RX_BYTES,
|
||||
DECTA_MBC_STATS_I_TX_BYTES,
|
||||
DECTA_MBC_STATS_HANDOVERS,
|
||||
__DECTA_MBC_STATS_MAX,
|
||||
};
|
||||
#define DECTA_MBC_STATS_MAX (__DECTA_MBC_STATS_MAX - 1)
|
||||
|
||||
enum dect_mbc_attrs {
|
||||
DECTA_MBC_UNSPEC,
|
||||
DECTA_MBC_MCEI,
|
||||
DECTA_MBC_SERVICE,
|
||||
DECTA_MBC_STATE,
|
||||
DECTA_MBC_CIPHER_STATE,
|
||||
DECTA_MBC_STATS,
|
||||
DECTA_MBC_TBS,
|
||||
__DECTA_MBC_MAX,
|
||||
};
|
||||
#define DECTA_MBC_MAX (__DECTA_MBC_MAX - 1)
|
||||
|
||||
enum dect_cluster_attrs {
|
||||
DECTA_CLUSTER_UNSPEC,
|
||||
DECTA_CLUSTER_NAME,
|
||||
DECTA_CLUSTER_MODE,
|
||||
DECTA_CLUSTER_PARI,
|
||||
DECTA_CLUSTER_CELLS,
|
||||
DECTA_CLUSTER_MBCS,
|
||||
__DECTA_CLUSTER_MAX
|
||||
};
|
||||
#define DECTA_CLUSTER_MAX (__DECTA_CLUSTER_MAX - 1)
|
||||
|
||||
enum dect_cluster_modes {
|
||||
DECT_MODE_FP,
|
||||
DECT_MODE_PP,
|
||||
};
|
||||
|
||||
/**
|
||||
* DECT ARI classes
|
||||
*
|
||||
* @DECT_ARC_A: Residential and private (PBX) single- and small multiple cell systems
|
||||
* @DECT_ARC_B: Private (PABXs) multiple cell
|
||||
* @DECT_ARC_C: Public single and multiple cell systems
|
||||
* @DECT_ARC_D: Public DECT access to a GSM network
|
||||
* @DECT_ARC_E: PP to PP direct communication (private)
|
||||
*/
|
||||
enum dect_ari_classes {
|
||||
DECT_ARC_A,
|
||||
DECT_ARC_B,
|
||||
DECT_ARC_C,
|
||||
DECT_ARC_D,
|
||||
DECT_ARC_E,
|
||||
};
|
||||
|
||||
enum dect_ari_attrs {
|
||||
DECTA_ARI_UNSPEC,
|
||||
DECTA_ARI_CLASS,
|
||||
DECTA_ARI_FPN,
|
||||
DECTA_ARI_FPS,
|
||||
DECTA_ARI_EMC,
|
||||
DECTA_ARI_EIC,
|
||||
DECTA_ARI_POC,
|
||||
DECTA_ARI_GOP,
|
||||
DECTA_ARI_FIL,
|
||||
__DECTA_ARI_MAX
|
||||
};
|
||||
#define DECTA_ARI_MAX (__DECTA_ARI_MAX - 1)
|
||||
|
||||
enum decta_sari_attrs {
|
||||
DECTA_SARI_UNSPEC,
|
||||
DECTA_SARI_ARI,
|
||||
DECTA_SARI_BLACK,
|
||||
DECTA_SARI_TARI,
|
||||
__DECTA_SARI_MAX
|
||||
};
|
||||
#define DECTA_SARI_MAX (__DECTA_SARI_MAX - 1)
|
||||
|
||||
enum dect_fixed_part_capabilities {
|
||||
DECT_FPC_EXTENDED_FP_INFO = 0x80000,
|
||||
DECT_FPC_DOUBLE_DUPLEX_BEARER_CONNECTION= 0x40000,
|
||||
DECT_FPC_RESERVED = 0x20000,
|
||||
DECT_FPC_DOUBLE_SLOT = 0x10000,
|
||||
DECT_FPC_HALF_SLOT = 0x08000,
|
||||
DECT_FPC_FULL_SLOT = 0x04000,
|
||||
DECT_FPC_FREQ_CONTROL = 0x02000,
|
||||
DECT_FPC_PAGE_REPETITION = 0x01000,
|
||||
DECT_FPC_CO_SETUP_ON_DUMMY = 0x00800,
|
||||
DECT_FPC_CL_UPLINK = 0x00400,
|
||||
DECT_FPC_CL_DOWNLINK = 0x00200,
|
||||
DECT_FPC_BASIC_A_FIELD_SETUP = 0x00100,
|
||||
DECT_FPC_ADV_A_FIELD_SETUP = 0x00080,
|
||||
DECT_FPC_B_FIELD_SETUP = 0x00040,
|
||||
DECT_FPC_CF_MESSAGES = 0x00020,
|
||||
DECT_FPC_IN_MIN_DELAY = 0x00010,
|
||||
DECT_FPC_IN_NORM_DELAY = 0x00008,
|
||||
DECT_FPC_IP_ERROR_DETECTION = 0x00004,
|
||||
DECT_FPC_IP_ERROR_CORRECTION = 0x00002,
|
||||
DECT_FPC_MULTIBEARER_CONNECTIONS = 0x00001,
|
||||
};
|
||||
|
||||
enum dect_higher_layer_capabilities {
|
||||
DECT_HLC_ADPCM_G721_VOICE = 0x8000,
|
||||
DECT_HLC_GAP_PAP_BASIC_SPEECH = 0x4000,
|
||||
DECT_HLC_NON_VOICE_CIRCUIT_SWITCHED = 0x2000,
|
||||
DECT_HLC_NON_VOICE_PACKET_SWITCHED = 0x1000,
|
||||
DECT_HLC_STANDARD_AUTHENTICATION = 0x0800,
|
||||
DECT_HLC_STANDARD_CIPHERING = 0x0400,
|
||||
DECT_HLC_LOCATION_REGISTRATION = 0x0200,
|
||||
DECT_HLC_SIM_SERVICES = 0x0100,
|
||||
DECT_HLC_NON_STATIC_FIXED_PART = 0x0080,
|
||||
DECT_HLC_CISS_SERVICE = 0x0040,
|
||||
DECT_HLC_CLMS_SERVICE = 0x0020,
|
||||
DECT_HLC_COMS_SERVICE = 0x0010,
|
||||
DECT_HLC_ACCESS_RIGHTS_REQUESTS = 0x0008,
|
||||
DECT_HLC_EXTERNAL_HANDOVER = 0x0004,
|
||||
DECT_HLC_CONNECTION_HANDOVER = 0x0002,
|
||||
DECT_HLC_RESERVED = 0x0001,
|
||||
};
|
||||
|
||||
enum dect_extended_fixed_part_capabilities {
|
||||
DECT_EFPC_WRS_MASK = 0x1f80,
|
||||
DECT_EFPC_WRS_CRFP_HOPS_MASK = 0x1800,
|
||||
DECT_EFPC_WRS_CRFP_HOPS_1 = 0x0000,
|
||||
DECT_EFPC_WRS_CRFP_HOPS_2 = 0x0800,
|
||||
DECT_EFPC_WRS_CRFP_HOPS_3 = 0x1000,
|
||||
DECT_EFPC_WRS_CRFP_HOPS_NONE = 0x1800,
|
||||
DECT_EFPC_WRS_CRFP_ENCRYPTION = 0x0400,
|
||||
DECT_EFPC_WRS_REP_HOPS_MASK = 0x0300,
|
||||
DECT_EFPC_WRS_REP_HOPS_NONE = 0x0000,
|
||||
DECT_EFPC_WRS_REP_HOPS_1 = 0x0100,
|
||||
DECT_EFPC_WRS_REP_HOPS_2 = 0x0200,
|
||||
DECT_EFPC_WRS_REP_HOPS_3 = 0x0300,
|
||||
DECT_EFPC_WRS_REP_INTERLACING = 0x0080,
|
||||
DECT_EFPC_SYNC_MASK = 0x0060,
|
||||
DECT_EFPC_SYNC_PROLONGED_PREAMBLE = 0x0020,
|
||||
DECT_EFPC_SYNC_RESERVED1 = 0x0010,
|
||||
DECT_EFPC_MAC_SUSPEND_RESUME = 0x0008,
|
||||
DECT_EFPC_MAC_IP_Q_SERVICE = 0x0004,
|
||||
DECT_EFPC_EXTENDED_FP_INFO2 = 0x0002,
|
||||
DECT_EFPC_RESERVED2 = 0x0001,
|
||||
};
|
||||
|
||||
enum dect_extended_higher_layer_capabilities {
|
||||
DECT_EHLC_ISDN_DATA_SERVICE = 0x000001,
|
||||
DECT_EHLC_DPRS_FREL = 0x000002,
|
||||
DECT_EHLC_DPRS_STREAM = 0x000004,
|
||||
DECT_EHLC_DATA_SERVICE_PROFILE_D = 0x000008,
|
||||
DECT_EHLC_LRMS = 0x000010,
|
||||
DECT_EHLC_ASYMETRIC_BEARERS = 0x000040,
|
||||
DECT_EHLC_EMERGENCY_CALLS = 0x000080,
|
||||
DECT_EHLC_TPUI_LOCATION_REGISTRATION = 0x000100,
|
||||
DECT_EHLC_GPS_SYNCHRONIZED = 0x000200,
|
||||
DECT_EHLC_ISDN_INTERMEDIATE_SYSTEM = 0x000400,
|
||||
DECT_EHLC_RAP_PART_1_PROFILE = 0x000800,
|
||||
DECT_EHLC_V_24 = 0x004000,
|
||||
DECT_EHLC_PPP = 0x008000,
|
||||
DECT_EHLC_IP = 0x010000,
|
||||
DECT_EHLC_TOKEN_RING = 0x020000,
|
||||
DECT_EHLC_ETHERNET = 0x040000,
|
||||
DECT_EHLC_IP_ROAMING = 0x080000,
|
||||
DECT_EHLC_GENERIC_MEDIA_ENCAPSULATION = 0x100000,
|
||||
DECT_EHLC_BASIC_ODAP = 0x200000,
|
||||
DECT_EHLC_F_MMS_INTERWORKING_PROFILE = 0x400000,
|
||||
};
|
||||
|
||||
enum dect_extended_fixed_part_capabilities2 {
|
||||
DECT_EFPC2_LONG_SLOT_J640 = 0x800,
|
||||
DECT_EFPC2_LONG_SLOT_J672 = 0x400,
|
||||
DECT_EFPC2_IP_F = 0x200,
|
||||
DECT_EFPC2_SI_PF = 0x100,
|
||||
DECT_EFPC2_GF = 0x080,
|
||||
DECT_EFPC2_NO_EMISSION_CARRIER = 0x001,
|
||||
};
|
||||
|
||||
enum dect_extended_higher_layer_capabilities2 {
|
||||
DECT_EHLC2_NG_DECT_PERMANENT_CLIR = 0x000100,
|
||||
DECT_EHLC2_NG_DECT_MULTIPLE_CALLS = 0x000200,
|
||||
DECT_EHLC2_NG_DECT_MULTIPLE_LINES = 0x000400,
|
||||
DECT_EHLC2_EASY_PAIRING = 0x000800,
|
||||
DECT_EHLC2_LIST_ACCESS_FEATURES = 0x001000,
|
||||
DECT_EHLC2_NO_EMISSION_MODE = 0x002000,
|
||||
DECT_EHLC2_NG_DECT_CALL_DEFLECTION = 0x004000,
|
||||
DECT_EHLC2_NG_DECT_INTRUSION_CALL = 0x008000,
|
||||
DECT_EHLC2_NG_DECT_CONFERENCE_CALL = 0x010000,
|
||||
DECT_EHLC2_NG_DECT_PARALLEL_CALLS = 0x020000,
|
||||
DECT_EHLC2_NG_DECT_CALL_TRANSFER = 0x040000,
|
||||
DECT_EHLC2_NG_DECT_EXTENDED_WIDEBAND = 0x080000,
|
||||
DECT_EHLC2_PACKET_DATA_CATEGORY_MASK = 0x700000,
|
||||
DECT_EHLC2_NG_DECT_WIDEBAND = 0x800000,
|
||||
};
|
||||
|
||||
enum dect_mac_info_attrs {
|
||||
DECTA_MAC_INFO_UNSPEC,
|
||||
DECTA_MAC_INFO_PARI,
|
||||
DECTA_MAC_INFO_RPN,
|
||||
DECTA_MAC_INFO_RSSI,
|
||||
DECTA_MAC_INFO_SARI_LIST,
|
||||
DECTA_MAC_INFO_FPC,
|
||||
DECTA_MAC_INFO_HLC,
|
||||
DECTA_MAC_INFO_EFPC,
|
||||
DECTA_MAC_INFO_EHLC,
|
||||
DECTA_MAC_INFO_EFPC2,
|
||||
DECTA_MAC_INFO_EHLC2,
|
||||
DECTA_MAC_INFO_MFN,
|
||||
__DECTA_MAC_INFO_MAX
|
||||
};
|
||||
#define DECTA_MAC_INFO_MAX (__DECTA_MAC_INFO_MAX - 1)
|
||||
|
||||
enum dect_llme_ops {
|
||||
DECT_LLME_REQUEST,
|
||||
DECT_LLME_INDICATE,
|
||||
DECT_LLME_RESPONSE,
|
||||
DECT_LLME_CONFIRM,
|
||||
};
|
||||
|
||||
enum dect_llme_msg_types {
|
||||
DECT_LLME_SCAN,
|
||||
DECT_LLME_MAC_INFO,
|
||||
DECT_LLME_MAC_RFP_PRELOAD,
|
||||
__DECT_LLME_MAX
|
||||
};
|
||||
#define DECT_LLME_MAX (__DECT_LLME_MAX - 1)
|
||||
|
||||
enum dect_llme_msg_attrs {
|
||||
DECTA_LLME_UNSPEC,
|
||||
DECTA_LLME_OP,
|
||||
DECTA_LLME_TYPE,
|
||||
DECTA_LLME_DATA,
|
||||
__DECTA_LLME_MAX
|
||||
};
|
||||
#define DECTA_LLME_MAX (__DECTA_LLME_MAX - 1)
|
||||
|
||||
#endif /* _LINUX_DECT_NETLINK_H */
|
|
@ -117,6 +117,12 @@ enum {
|
|||
IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
|
||||
};
|
||||
|
||||
/* carrier state */
|
||||
enum {
|
||||
IF_CARRIER_DOWN,
|
||||
IF_CARRIER_UP
|
||||
};
|
||||
|
||||
/*
|
||||
* Device mapping structure. I'd just gone off and designed a
|
||||
* beautiful scheme using only loadable modules with arguments
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Linux ethernet bridge
|
||||
*
|
||||
* Authors:
|
||||
* Lennert Buytenhek <buytenh@gnu.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 _UAPI_LINUX_IF_BRIDGE_H
|
||||
#define _UAPI_LINUX_IF_BRIDGE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define SYSFS_BRIDGE_ATTR "bridge"
|
||||
#define SYSFS_BRIDGE_FDB "brforward"
|
||||
#define SYSFS_BRIDGE_PORT_SUBDIR "brif"
|
||||
#define SYSFS_BRIDGE_PORT_ATTR "brport"
|
||||
#define SYSFS_BRIDGE_PORT_LINK "bridge"
|
||||
|
||||
#define BRCTL_VERSION 1
|
||||
|
||||
#define BRCTL_GET_VERSION 0
|
||||
#define BRCTL_GET_BRIDGES 1
|
||||
#define BRCTL_ADD_BRIDGE 2
|
||||
#define BRCTL_DEL_BRIDGE 3
|
||||
#define BRCTL_ADD_IF 4
|
||||
#define BRCTL_DEL_IF 5
|
||||
#define BRCTL_GET_BRIDGE_INFO 6
|
||||
#define BRCTL_GET_PORT_LIST 7
|
||||
#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8
|
||||
#define BRCTL_SET_BRIDGE_HELLO_TIME 9
|
||||
#define BRCTL_SET_BRIDGE_MAX_AGE 10
|
||||
#define BRCTL_SET_AGEING_TIME 11
|
||||
#define BRCTL_SET_GC_INTERVAL 12
|
||||
#define BRCTL_GET_PORT_INFO 13
|
||||
#define BRCTL_SET_BRIDGE_STP_STATE 14
|
||||
#define BRCTL_SET_BRIDGE_PRIORITY 15
|
||||
#define BRCTL_SET_PORT_PRIORITY 16
|
||||
#define BRCTL_SET_PATH_COST 17
|
||||
#define BRCTL_GET_FDB_ENTRIES 18
|
||||
|
||||
#define BR_STATE_DISABLED 0
|
||||
#define BR_STATE_LISTENING 1
|
||||
#define BR_STATE_LEARNING 2
|
||||
#define BR_STATE_FORWARDING 3
|
||||
#define BR_STATE_BLOCKING 4
|
||||
|
||||
struct __bridge_info {
|
||||
__u64 designated_root;
|
||||
__u64 bridge_id;
|
||||
__u32 root_path_cost;
|
||||
__u32 max_age;
|
||||
__u32 hello_time;
|
||||
__u32 forward_delay;
|
||||
__u32 bridge_max_age;
|
||||
__u32 bridge_hello_time;
|
||||
__u32 bridge_forward_delay;
|
||||
__u8 topology_change;
|
||||
__u8 topology_change_detected;
|
||||
__u8 root_port;
|
||||
__u8 stp_enabled;
|
||||
__u32 ageing_time;
|
||||
__u32 gc_interval;
|
||||
__u32 hello_timer_value;
|
||||
__u32 tcn_timer_value;
|
||||
__u32 topology_change_timer_value;
|
||||
__u32 gc_timer_value;
|
||||
};
|
||||
|
||||
struct __port_info {
|
||||
__u64 designated_root;
|
||||
__u64 designated_bridge;
|
||||
__u16 port_id;
|
||||
__u16 designated_port;
|
||||
__u32 path_cost;
|
||||
__u32 designated_cost;
|
||||
__u8 state;
|
||||
__u8 top_change_ack;
|
||||
__u8 config_pending;
|
||||
__u8 unused0;
|
||||
__u32 message_age_timer_value;
|
||||
__u32 forward_delay_timer_value;
|
||||
__u32 hold_timer_value;
|
||||
};
|
||||
|
||||
struct __fdb_entry {
|
||||
__u8 mac_addr[6];
|
||||
__u8 port_no;
|
||||
__u8 is_local;
|
||||
__u32 ageing_timer_value;
|
||||
__u8 port_hi;
|
||||
__u8 pad0;
|
||||
__u16 unused;
|
||||
};
|
||||
|
||||
/* Bridge Flags */
|
||||
#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */
|
||||
#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */
|
||||
|
||||
#define BRIDGE_MODE_VEB 0 /* Default loopback mode */
|
||||
#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */
|
||||
|
||||
/* Bridge management nested attributes
|
||||
* [IFLA_AF_SPEC] = {
|
||||
* [IFLA_BRIDGE_FLAGS]
|
||||
* [IFLA_BRIDGE_MODE]
|
||||
* }
|
||||
*/
|
||||
enum {
|
||||
IFLA_BRIDGE_FLAGS,
|
||||
IFLA_BRIDGE_MODE,
|
||||
__IFLA_BRIDGE_MAX,
|
||||
};
|
||||
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
|
||||
|
||||
/* Bridge multicast database attributes
|
||||
* [MDBA_MDB] = {
|
||||
* [MDBA_MDB_ENTRY] = {
|
||||
* [MDBA_MDB_ENTRY_INFO]
|
||||
* }
|
||||
* }
|
||||
* [MDBA_ROUTER] = {
|
||||
* [MDBA_ROUTER_PORT]
|
||||
* }
|
||||
*/
|
||||
enum {
|
||||
MDBA_UNSPEC,
|
||||
MDBA_MDB,
|
||||
MDBA_ROUTER,
|
||||
__MDBA_MAX,
|
||||
};
|
||||
#define MDBA_MAX (__MDBA_MAX - 1)
|
||||
|
||||
enum {
|
||||
MDBA_MDB_UNSPEC,
|
||||
MDBA_MDB_ENTRY,
|
||||
__MDBA_MDB_MAX,
|
||||
};
|
||||
#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1)
|
||||
|
||||
enum {
|
||||
MDBA_MDB_ENTRY_UNSPEC,
|
||||
MDBA_MDB_ENTRY_INFO,
|
||||
__MDBA_MDB_ENTRY_MAX,
|
||||
};
|
||||
#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1)
|
||||
|
||||
enum {
|
||||
MDBA_ROUTER_UNSPEC,
|
||||
MDBA_ROUTER_PORT,
|
||||
__MDBA_ROUTER_MAX,
|
||||
};
|
||||
#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1)
|
||||
|
||||
struct br_port_msg {
|
||||
__u8 family;
|
||||
__u32 ifindex;
|
||||
};
|
||||
|
||||
struct br_mdb_entry {
|
||||
__u32 ifindex;
|
||||
#define MDB_TEMPORARY 0
|
||||
#define MDB_PERMANENT 1
|
||||
__u8 state;
|
||||
struct {
|
||||
union {
|
||||
__be32 ip4;
|
||||
struct in6_addr ip6;
|
||||
} u;
|
||||
__be16 proto;
|
||||
} addr;
|
||||
};
|
||||
|
||||
enum {
|
||||
MDBA_SET_ENTRY_UNSPEC,
|
||||
MDBA_SET_ENTRY,
|
||||
__MDBA_SET_ENTRY_MAX,
|
||||
};
|
||||
#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1)
|
||||
|
||||
#endif /* _UAPI_LINUX_IF_BRIDGE_H */
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _LINUX_IF_LINK_H
|
||||
#define _LINUX_IF_LINK_H
|
||||
#ifndef _UAPI_LINUX_IF_LINK_H
|
||||
#define _UAPI_LINUX_IF_LINK_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
|
@ -142,6 +142,7 @@ enum {
|
|||
#define IFLA_PROMISCUITY IFLA_PROMISCUITY
|
||||
IFLA_NUM_TX_QUEUES,
|
||||
IFLA_NUM_RX_QUEUES,
|
||||
IFLA_CARRIER,
|
||||
__IFLA_MAX
|
||||
};
|
||||
|
||||
|
@ -199,6 +200,24 @@ enum {
|
|||
|
||||
#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
|
||||
|
||||
enum {
|
||||
BRIDGE_MODE_UNSPEC,
|
||||
BRIDGE_MODE_HAIRPIN,
|
||||
};
|
||||
|
||||
enum {
|
||||
IFLA_BRPORT_UNSPEC,
|
||||
IFLA_BRPORT_STATE, /* Spanning tree state */
|
||||
IFLA_BRPORT_PRIORITY, /* " priority */
|
||||
IFLA_BRPORT_COST, /* " cost */
|
||||
IFLA_BRPORT_MODE, /* mode (hairpin) */
|
||||
IFLA_BRPORT_GUARD, /* bpdu guard */
|
||||
IFLA_BRPORT_PROTECT, /* root port protection */
|
||||
IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */
|
||||
__IFLA_BRPORT_MAX
|
||||
};
|
||||
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
|
||||
|
||||
struct ifla_cacheinfo {
|
||||
__u32 max_reasm_len;
|
||||
__u32 tstamp; /* ipv6InterfaceTable updated timestamp */
|
||||
|
@ -266,6 +285,32 @@ enum macvlan_mode {
|
|||
|
||||
#define MACVLAN_FLAG_NOPROMISC 1
|
||||
|
||||
/* VXLAN section */
|
||||
enum {
|
||||
IFLA_VXLAN_UNSPEC,
|
||||
IFLA_VXLAN_ID,
|
||||
IFLA_VXLAN_GROUP,
|
||||
IFLA_VXLAN_LINK,
|
||||
IFLA_VXLAN_LOCAL,
|
||||
IFLA_VXLAN_TTL,
|
||||
IFLA_VXLAN_TOS,
|
||||
IFLA_VXLAN_LEARNING,
|
||||
IFLA_VXLAN_AGEING,
|
||||
IFLA_VXLAN_LIMIT,
|
||||
IFLA_VXLAN_PORT_RANGE,
|
||||
IFLA_VXLAN_PROXY,
|
||||
IFLA_VXLAN_RSC,
|
||||
IFLA_VXLAN_L2MISS,
|
||||
IFLA_VXLAN_L3MISS,
|
||||
__IFLA_VXLAN_MAX
|
||||
};
|
||||
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
|
||||
|
||||
struct ifla_vxlan_port_range {
|
||||
__be16 low;
|
||||
__be16 high;
|
||||
};
|
||||
|
||||
/* SR-IOV virtual function management section */
|
||||
|
||||
enum {
|
||||
|
@ -307,18 +352,6 @@ struct ifla_vf_spoofchk {
|
|||
__u32 vf;
|
||||
__u32 setting;
|
||||
};
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* We don't want this structure exposed to user space */
|
||||
struct ifla_vf_info {
|
||||
__u32 vf;
|
||||
__u8 mac[32];
|
||||
__u32 vlan;
|
||||
__u32 qos;
|
||||
__u32 tx_rate;
|
||||
__u32 spoofchk;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* VF ports management section
|
||||
*
|
||||
|
@ -392,4 +425,22 @@ struct ifla_port_vsi {
|
|||
__u8 pad[3];
|
||||
};
|
||||
|
||||
#endif /* _LINUX_IF_LINK_H */
|
||||
|
||||
/* IPoIB section */
|
||||
|
||||
enum {
|
||||
IFLA_IPOIB_UNSPEC,
|
||||
IFLA_IPOIB_PKEY,
|
||||
IFLA_IPOIB_MODE,
|
||||
IFLA_IPOIB_UMCAST,
|
||||
__IFLA_IPOIB_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */
|
||||
IPOIB_MODE_CONNECTED = 1, /* using connected QPs */
|
||||
};
|
||||
|
||||
#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
|
||||
|
||||
#endif /* _UAPI_LINUX_IF_LINK_H */
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
|
||||
#define NETLINK_ECRYPTFS 19
|
||||
#define NETLINK_RDMA 20
|
||||
#define NETLINK_CRYPTO 21 /* Crypto layer */
|
||||
#define NETLINK_DECT 22 /* DECT */
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* netlink-private/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-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_CACHE_API_H_
|
||||
#define NETLINK_CACHE_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.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
|
||||
* @{
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
/**
|
||||
* Parser parameters
|
||||
*
|
||||
* This structure is used to configure what kind of parser to use
|
||||
* when parsing netlink messages to create objects.
|
||||
*/
|
||||
struct nl_parser_param
|
||||
{
|
||||
/** Function to parse netlink messages into objects */
|
||||
int (*pp_cb)(struct nl_object *, struct nl_parser_param *);
|
||||
|
||||
/** Arbitary argument to be passed to the parser */
|
||||
void * pp_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache Operations
|
||||
*
|
||||
* This structure defines the characterstics of a cache type. It contains
|
||||
* pointers to functions which implement the specifics of the object type
|
||||
* the cache can hold.
|
||||
*/
|
||||
struct nl_cache_ops
|
||||
{
|
||||
/** Name of cache type (must be unique) */
|
||||
char * co_name;
|
||||
|
||||
/** Size of family specific netlink header */
|
||||
int co_hdrsize;
|
||||
|
||||
/** Netlink protocol */
|
||||
int co_protocol;
|
||||
|
||||
/** cache object hash size **/
|
||||
int co_hash_size;
|
||||
|
||||
/** cache flags */
|
||||
unsigned int co_flags;
|
||||
|
||||
/** Reference counter */
|
||||
unsigned int co_refcnt;
|
||||
|
||||
/** Group definition */
|
||||
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 *);
|
||||
|
||||
/**
|
||||
* The function registered under this callback is called after a
|
||||
* netlink notification associated with this cache type has been
|
||||
* parsed into an object and is being considered for inclusio into
|
||||
* the specified cache.
|
||||
*
|
||||
* The purpose of this function is to filter out notifications
|
||||
* which should be ignored when updating caches.
|
||||
*
|
||||
* The function must return NL_SKIP to prevent the object from
|
||||
* being included, or NL_OK to include it.
|
||||
*
|
||||
* @code
|
||||
* int my_filter(struct nl_cache *cache, struct nl_object *obj)
|
||||
* {
|
||||
* if (reason_to_not_include_obj(obj))
|
||||
* return NL_SKIP;
|
||||
*
|
||||
* return NL_OK;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
int (*co_event_filter)(struct nl_cache *, struct nl_object *obj);
|
||||
|
||||
/**
|
||||
* The function registered under this callback is called when an
|
||||
* object formed from a notification event needs to be included in
|
||||
* a cache.
|
||||
*
|
||||
* For each modified object, the change callback \c change_cb must
|
||||
* be called with the \c data argument provided.
|
||||
*
|
||||
* If no function is registered, the function nl_cache_include()
|
||||
* will be used for this purpose.
|
||||
*
|
||||
* @see nl_cache_include()
|
||||
*/
|
||||
int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj,
|
||||
change_func_t change_cb, void *data);
|
||||
|
||||
void (*reserved_1)(void);
|
||||
void (*reserved_2)(void);
|
||||
void (*reserved_3)(void);
|
||||
void (*reserved_4)(void);
|
||||
void (*reserved_5)(void);
|
||||
void (*reserved_6)(void);
|
||||
void (*reserved_7)(void);
|
||||
void (*reserved_8)(void);
|
||||
|
||||
/** Object operations */
|
||||
struct nl_object_ops * co_obj_ops;
|
||||
|
||||
/** Internal, do not touch! */
|
||||
struct nl_cache_ops *co_next;
|
||||
|
||||
struct nl_cache *co_major_cache;
|
||||
struct genl_ops * co_genl;
|
||||
|
||||
/* Message type definition */
|
||||
struct nl_msgtype co_msgtypes[];
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,20 +1,22 @@
|
|||
/*
|
||||
* netlink-generic.h Local Generic Netlink Interface
|
||||
* netlink-private/genl.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>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_GENL_PRIV_H_
|
||||
#define NETLINK_GENL_PRIV_H_
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
|
||||
#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen))
|
||||
|
||||
extern int genl_resolve_id(struct genl_ops *ops);
|
||||
|
||||
#endif
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* netlink-local.h Local Netlink Interface
|
||||
* netlink-private/netlink.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-2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LOCAL_H_
|
||||
|
@ -63,9 +63,9 @@
|
|||
#include <netlink/handlers.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/route/tc.h>
|
||||
#include <netlink/object-api.h>
|
||||
#include <netlink/cache-api.h>
|
||||
#include <netlink-types.h>
|
||||
#include <netlink-private/object-api.h>
|
||||
#include <netlink-private/cache-api.h>
|
||||
#include <netlink-private/types.h>
|
||||
|
||||
struct trans_tbl {
|
||||
int i;
|
||||
|
@ -80,24 +80,29 @@ struct trans_list {
|
|||
struct nl_list_head list;
|
||||
};
|
||||
|
||||
#define NL_DEBUG 1
|
||||
|
||||
#define NL_DBG(LVL,FMT,ARG...) \
|
||||
do { \
|
||||
if (LVL <= nl_debug) \
|
||||
fprintf(stderr, "DBG<" #LVL ">: " FMT, ##ARG); \
|
||||
#ifdef NL_DEBUG
|
||||
#define NL_DBG(LVL,FMT,ARG...) \
|
||||
do { \
|
||||
if (LVL <= nl_debug) \
|
||||
fprintf(stderr, \
|
||||
"DBG<" #LVL ">%20s:%-4u %s: " FMT, \
|
||||
__FILE__, __LINE__, \
|
||||
__PRETTY_FUNCTION__, ##ARG); \
|
||||
} while (0)
|
||||
#else /* NL_DEBUG */
|
||||
#define NL_DBG(LVL,FMT,ARG...) do { } while(0)
|
||||
#endif /* NL_DEBUG */
|
||||
|
||||
#define BUG() \
|
||||
do { \
|
||||
NL_DBG(1, "BUG: %s:%d\n", \
|
||||
__FILE__, __LINE__); \
|
||||
fprintf(stderr, "BUG at file position %s:%d:%s\n", \
|
||||
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
|
||||
assert(0); \
|
||||
} while (0)
|
||||
|
||||
#define APPBUG(msg) \
|
||||
do { \
|
||||
NL_DBG(1, "APPLICATION BUG: %s:%d:%s: %s\n", \
|
||||
fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", \
|
||||
__FILE__, __LINE__, __PRETTY_FUNCTION__, msg); \
|
||||
assert(0); \
|
||||
} while(0)
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* netlink-private/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-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_OBJECT_API_H_
|
||||
#define NETLINK_OBJECT_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/object.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;
|
||||
|
||||
struct nl_object
|
||||
{
|
||||
NLHDR_COMMON
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 attribute is available in only one of both objects
|
||||
* @arg A an object
|
||||
* @arg B another object
|
||||
* @arg ATTR attribute bit
|
||||
*
|
||||
* @return True if the attribute is available in only one of both objects,
|
||||
* otherwise false is returned.
|
||||
*/
|
||||
#define AVAILABLE_MISMATCH(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_MISMATCH(A, B, ATTR) || \
|
||||
(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_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);
|
||||
|
||||
|
||||
/**
|
||||
* update function
|
||||
*
|
||||
* Will be called when the object given by first argument
|
||||
* needs to be updated with the contents of the second object
|
||||
*
|
||||
* The function must return 0 for success and error for failure
|
||||
* to update. In case of failure its assumed that the original
|
||||
* object is not touched
|
||||
*/
|
||||
int (*oo_update)(struct nl_object *, struct nl_object *);
|
||||
|
||||
/**
|
||||
* Hash Key generator function
|
||||
*
|
||||
* When called returns a hash key for the object being
|
||||
* referenced. This key will be used by higher level hash functions
|
||||
* to build association lists. Each object type gets to specify
|
||||
* it's own key formulation
|
||||
*/
|
||||
void (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t);
|
||||
|
||||
char *(*oo_attrs2str)(int, char *, size_t);
|
||||
|
||||
/**
|
||||
* Get key attributes by family function
|
||||
*/
|
||||
uint32_t (*oo_id_attrs_get)(struct nl_object *);
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* netlink-private/route/link/api.h Link Modules 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-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_API_H_
|
||||
#define NETLINK_LINK_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup link_api
|
||||
*
|
||||
* Available operations to modules implementing a link info type.
|
||||
*/
|
||||
struct rtnl_link_info_ops
|
||||
{
|
||||
/** Name of link info type, must match name on kernel side */
|
||||
char * io_name;
|
||||
|
||||
/** Reference count, DO NOT MODIFY */
|
||||
int io_refcnt;
|
||||
|
||||
/** Called to assign an info type to a link.
|
||||
* Has to allocate enough resources to hold attributes. Can
|
||||
* use link->l_info to store a pointer. */
|
||||
int (*io_alloc)(struct rtnl_link *);
|
||||
|
||||
/** Called to parse the link info attribute.
|
||||
* Must parse the attribute and assign all values to the link.
|
||||
*/
|
||||
int (*io_parse)(struct rtnl_link *,
|
||||
struct nlattr *,
|
||||
struct nlattr *);
|
||||
|
||||
/** Called when the link object is dumped.
|
||||
* Must dump the info type specific attributes. */
|
||||
void (*io_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
|
||||
struct nl_dump_params *);
|
||||
|
||||
/** Called when a link object is cloned.
|
||||
* Must clone all info type specific attributes. */
|
||||
int (*io_clone)(struct rtnl_link *, struct rtnl_link *);
|
||||
|
||||
/** Called when construction a link netlink message.
|
||||
* Must append all info type specific attributes to the message. */
|
||||
int (*io_put_attrs)(struct nl_msg *, struct rtnl_link *);
|
||||
|
||||
/** Called to release all resources previously allocated
|
||||
* in either io_alloc() or io_parse(). */
|
||||
void (*io_free)(struct rtnl_link *);
|
||||
|
||||
struct nl_list_head io_list;
|
||||
};
|
||||
|
||||
extern struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *);
|
||||
extern void rtnl_link_info_ops_put(struct rtnl_link_info_ops *);
|
||||
extern int rtnl_link_register_info(struct rtnl_link_info_ops *);
|
||||
extern int rtnl_link_unregister_info(struct rtnl_link_info_ops *);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup link_api
|
||||
*
|
||||
* Available operations to modules implementing a link address family.
|
||||
*/
|
||||
struct rtnl_link_af_ops
|
||||
{
|
||||
/** The address family this operations set implements */
|
||||
const unsigned int ao_family;
|
||||
|
||||
/** Number of users of this operations, DO NOT MODIFY. */
|
||||
int ao_refcnt;
|
||||
|
||||
/** Validation policy for IFLA_PROTINFO attribute. This pointer
|
||||
* can be set to a nla_policy structure describing the minimal
|
||||
* requirements the attribute must meet. Failure of meeting these
|
||||
* requirements will result in a parsing error. */
|
||||
const struct nla_policy *ao_protinfo_policy;
|
||||
|
||||
/** Called after address family has been assigned to link. Must
|
||||
* allocate data buffer to hold address family specific data and
|
||||
* store it in link->l_af_data. */
|
||||
void * (*ao_alloc)(struct rtnl_link *);
|
||||
|
||||
/** Called when the link is cloned, must allocate a clone of the
|
||||
* address family specific buffer and return it. */
|
||||
void * (*ao_clone)(struct rtnl_link *, void *);
|
||||
|
||||
/** Called when the link gets freed. Must free all allocated data */
|
||||
void (*ao_free)(struct rtnl_link *, void *);
|
||||
|
||||
/** Called if a IFLA_PROTINFO attribute needs to be parsed. Typically
|
||||
* stores the parsed data in the address family specific buffer. */
|
||||
int (*ao_parse_protinfo)(struct rtnl_link *,
|
||||
struct nlattr *, void *);
|
||||
|
||||
/** Called if a IFLA_AF_SPEC attribute needs to be parsed. Typically
|
||||
* stores the parsed data in the address family specific buffer. */
|
||||
int (*ao_parse_af)(struct rtnl_link *,
|
||||
struct nlattr *, void *);
|
||||
|
||||
/** Called if a link message is sent to the kernel. Must append the
|
||||
* link address family specific attributes to the message. */
|
||||
int (*ao_fill_af)(struct rtnl_link *,
|
||||
struct nl_msg *msg, void *);
|
||||
|
||||
/** Dump address family specific link attributes */
|
||||
void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
|
||||
struct nl_dump_params *,
|
||||
void *);
|
||||
|
||||
/** Comparison function
|
||||
*
|
||||
* Will be called when two links are compared for their af data. It
|
||||
* takes two link 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 (*ao_compare)(struct rtnl_link *,
|
||||
struct rtnl_link *, int, uint32_t, int);
|
||||
};
|
||||
|
||||
extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int);
|
||||
extern void rtnl_link_af_ops_put(struct rtnl_link_af_ops *);
|
||||
extern void * rtnl_link_af_alloc(struct rtnl_link *,
|
||||
const struct rtnl_link_af_ops *);
|
||||
extern void * rtnl_link_af_data(const struct rtnl_link *,
|
||||
const struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_register(struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_data_compare(struct rtnl_link *a,
|
||||
struct rtnl_link *b,
|
||||
int family);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* netlink-private/route/tc-api.h Traffic Control 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) 2011-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_TC_API_H_
|
||||
#define NETLINK_TC_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/msg.h>
|
||||
#include <netlink/route/tc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Traffic control object operations
|
||||
* @ingroup tc
|
||||
*
|
||||
* This structure holds function pointers and settings implementing
|
||||
* the features of each traffic control object implementation.
|
||||
*/
|
||||
struct rtnl_tc_ops
|
||||
{
|
||||
/**
|
||||
* Name of traffic control module
|
||||
*/
|
||||
char *to_kind;
|
||||
|
||||
/**
|
||||
* Type of traffic control object
|
||||
*/
|
||||
enum rtnl_tc_type to_type;
|
||||
|
||||
|
||||
/**
|
||||
* Size of private data
|
||||
*/
|
||||
size_t to_size;
|
||||
|
||||
/**
|
||||
* Dump callbacks
|
||||
*/
|
||||
void (*to_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, void *,
|
||||
struct nl_dump_params *);
|
||||
/**
|
||||
* Used to fill the contents of TCA_OPTIONS
|
||||
*/
|
||||
int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *);
|
||||
|
||||
/**
|
||||
* Uesd to to fill tc related messages, unlike with to_msg_fill,
|
||||
* the contents is not encapsulated with a TCA_OPTIONS nested
|
||||
* attribute.
|
||||
*/
|
||||
int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *);
|
||||
|
||||
/**
|
||||
* TCA_OPTIONS message parser
|
||||
*/
|
||||
int (*to_msg_parser)(struct rtnl_tc *, void *);
|
||||
|
||||
/**
|
||||
* Called before a tc object is destroyed
|
||||
*/
|
||||
void (*to_free_data)(struct rtnl_tc *, void *);
|
||||
|
||||
/**
|
||||
* Called whenever a classifier object needs to be cloned
|
||||
*/
|
||||
int (*to_clone)(void *, void *);
|
||||
|
||||
/**
|
||||
* Internal, don't touch
|
||||
*/
|
||||
struct nl_list_head to_list;
|
||||
};
|
||||
|
||||
struct rtnl_tc_type_ops
|
||||
{
|
||||
enum rtnl_tc_type tt_type;
|
||||
|
||||
char *tt_dump_prefix;
|
||||
|
||||
/**
|
||||
* Dump callbacks
|
||||
*/
|
||||
void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *,
|
||||
struct nl_dump_params *);
|
||||
};
|
||||
|
||||
extern int rtnl_tc_msg_parse(struct nlmsghdr *,
|
||||
struct rtnl_tc *);
|
||||
extern int rtnl_tc_msg_build(struct rtnl_tc *, int,
|
||||
int, struct nl_msg **);
|
||||
|
||||
extern void rtnl_tc_free_data(struct nl_object *);
|
||||
extern int rtnl_tc_clone(struct nl_object *,
|
||||
struct nl_object *);
|
||||
extern void rtnl_tc_dump_line(struct nl_object *,
|
||||
struct nl_dump_params *);
|
||||
extern void rtnl_tc_dump_details(struct nl_object *,
|
||||
struct nl_dump_params *);
|
||||
extern void rtnl_tc_dump_stats(struct nl_object *,
|
||||
struct nl_dump_params *);
|
||||
extern int rtnl_tc_compare(struct nl_object *,
|
||||
struct nl_object *,
|
||||
uint32_t, int);
|
||||
|
||||
extern void * rtnl_tc_data(struct rtnl_tc *);
|
||||
extern void * rtnl_tc_data_check(struct rtnl_tc *,
|
||||
struct rtnl_tc_ops *);
|
||||
|
||||
extern struct rtnl_tc_ops * rtnl_tc_lookup_ops(enum rtnl_tc_type,
|
||||
const char *);
|
||||
extern struct rtnl_tc_ops * rtnl_tc_get_ops(struct rtnl_tc *);
|
||||
extern int rtnl_tc_register(struct rtnl_tc_ops *);
|
||||
extern void rtnl_tc_unregister(struct rtnl_tc_ops *);
|
||||
|
||||
extern void rtnl_tc_type_register(struct rtnl_tc_type_ops *);
|
||||
extern void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
* netlink-tc.h Local Traffic Control Interface
|
||||
* netlink-private/tc.h Local Traffic Control 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-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_TC_PRIV_H_
|
||||
#define NETLINK_TC_PRIV_H_
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* netlink-types.h Netlink Types (Private)
|
||||
* netlink-private/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-2012 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LOCAL_TYPES_H_
|
||||
|
@ -17,7 +17,7 @@
|
|||
#include <netlink/route/qdisc.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/route.h>
|
||||
#include <netlink/route/tc-api.h>
|
||||
#include <netlink-private/route/tc-api.h>
|
||||
|
||||
#define NL_SOCK_BUFSIZE_SET (1<<0)
|
||||
#define NL_SOCK_PASSCRED (1<<1)
|
||||
|
@ -182,6 +182,9 @@ struct rtnl_link
|
|||
uint32_t l_num_tx_queues;
|
||||
uint32_t l_num_rx_queues;
|
||||
uint32_t l_group;
|
||||
uint8_t l_carrier;
|
||||
/* 3 byte hole */
|
||||
struct rtnl_link_af_ops * l_af_ops;
|
||||
};
|
||||
|
||||
struct rtnl_ncacheinfo
|
||||
|
@ -900,6 +903,140 @@ struct nfnl_queue_msg {
|
|||
uint32_t queue_msg_verdict;
|
||||
};
|
||||
|
||||
struct nl_dect_transceiver_slot {
|
||||
uint8_t dts_valid;
|
||||
uint8_t dts_state;
|
||||
uint32_t dts_flags;
|
||||
uint8_t dts_packet;
|
||||
uint8_t dts_carrier;
|
||||
uint8_t dts_rssi;
|
||||
uint32_t dts_frequency;
|
||||
int32_t dts_phaseoff;
|
||||
uint32_t dts_rx_bytes;
|
||||
uint32_t dts_rx_packets;
|
||||
uint32_t dts_rx_a_crc_errors;
|
||||
uint32_t dts_rx_x_crc_errors;
|
||||
uint32_t dts_rx_z_crc_errors;
|
||||
uint32_t dts_tx_bytes;
|
||||
uint32_t dts_tx_packets;
|
||||
};
|
||||
|
||||
struct nl_dect_transceiver_stats {
|
||||
uint32_t trx_event_busy;
|
||||
uint32_t trx_event_late;
|
||||
};
|
||||
|
||||
struct nl_dect_transceiver {
|
||||
NLHDR_COMMON
|
||||
|
||||
char *trx_name;
|
||||
char *trx_type;
|
||||
uint32_t trx_features;
|
||||
uint8_t trx_index;
|
||||
uint8_t trx_link;
|
||||
uint8_t trx_band;
|
||||
struct nl_dect_transceiver_stats trx_stats;
|
||||
struct nl_dect_transceiver_slot trx_slots[24];
|
||||
};
|
||||
|
||||
struct nl_dect_ari {
|
||||
uint32_t ari_flags;
|
||||
|
||||
uint8_t ari_class;
|
||||
uint32_t ari_fpn;
|
||||
uint32_t ari_fps;
|
||||
union {
|
||||
uint16_t emc;
|
||||
uint16_t eic;
|
||||
uint16_t poc;
|
||||
uint32_t gop;
|
||||
uint16_t fil;
|
||||
} ari_u;
|
||||
};
|
||||
|
||||
struct nl_dect_mbc_tb {
|
||||
uint8_t mtb_lbn;
|
||||
uint8_t mtb_ecn;
|
||||
uint8_t mtb_cell;
|
||||
uint8_t mtb_rx_slot;
|
||||
uint8_t mtb_tx_slot;
|
||||
};
|
||||
|
||||
struct nl_dect_mbc {
|
||||
uint32_t mbc_mcei;
|
||||
uint8_t mbc_state;
|
||||
uint8_t mbc_service;
|
||||
uint8_t mbc_cipher_state;
|
||||
uint8_t mbc_ntbs;
|
||||
struct nl_dect_mbc_tb mbc_tbs[8];
|
||||
|
||||
uint32_t mbc_cs_rx_bytes;
|
||||
uint32_t mbc_cs_tx_bytes;
|
||||
uint32_t mbc_i_rx_bytes;
|
||||
uint32_t mbc_i_tx_bytes;
|
||||
uint32_t mbc_handovers;
|
||||
};
|
||||
|
||||
struct nl_dect_cluster {
|
||||
NLHDR_COMMON
|
||||
|
||||
int cl_index;
|
||||
char *cl_name;
|
||||
uint8_t cl_mode;
|
||||
struct nl_dect_ari cl_pari;
|
||||
uint8_t cells[8];
|
||||
struct nl_dect_mbc cl_mbcs[8];
|
||||
uint8_t cl_nmbcs;
|
||||
};
|
||||
|
||||
struct nl_dect_cell {
|
||||
NLHDR_COMMON
|
||||
|
||||
int c_index;
|
||||
char * c_name;
|
||||
uint32_t c_flags;
|
||||
char *c_transceiver[16];
|
||||
int c_link;
|
||||
};
|
||||
|
||||
struct nl_dect_llme_mac_info {
|
||||
NLHDR_COMMON
|
||||
|
||||
struct nl_dect_ari mi_pari;
|
||||
uint8_t mi_rpn;
|
||||
uint8_t mi_rssi;
|
||||
uint32_t mi_fpc;
|
||||
uint16_t mi_hlc;
|
||||
uint16_t mi_efpc;
|
||||
uint32_t mi_ehlc;
|
||||
uint16_t mi_efpc2;
|
||||
uint32_t mi_ehlc2;
|
||||
uint32_t mi_mfn;
|
||||
};
|
||||
|
||||
struct nl_dect_llme_mac_con {
|
||||
NLHDR_COMMON
|
||||
|
||||
uint32_t mc_mcei;
|
||||
struct nl_dect_ari mc_ari;
|
||||
uint32_t mc_pmid;
|
||||
uint8_t mc_type;
|
||||
uint8_t mc_ecn;
|
||||
uint8_t mc_service;
|
||||
};
|
||||
|
||||
struct nl_dect_llme_msg {
|
||||
NLHDR_COMMON
|
||||
|
||||
int lm_index;
|
||||
uint8_t lm_type;
|
||||
uint8_t lm_op;
|
||||
union {
|
||||
struct nl_dect_llme_mac_info lm_mi;
|
||||
struct nl_dect_llme_mac_con lm_mc;
|
||||
};
|
||||
};
|
||||
|
||||
struct ematch_quoted {
|
||||
char * data;
|
||||
size_t len;
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_ADDR_H_
|
||||
|
@ -40,7 +40,7 @@ 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);
|
||||
extern int nl_addr_resolve(struct nl_addr *, char *, size_t);
|
||||
|
||||
/* Access Functions */
|
||||
extern void nl_addr_set_family(struct nl_addr *, int);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_ATTR_H_
|
||||
|
@ -124,8 +124,10 @@ extern int nla_put_msecs(struct nl_msg *, int, unsigned long);
|
|||
extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *);
|
||||
extern struct nlattr * nla_nest_start(struct nl_msg *, int);
|
||||
extern int nla_nest_end(struct nl_msg *, struct nlattr *);
|
||||
extern void nla_nest_cancel(struct nl_msg *, struct nlattr *);
|
||||
extern int nla_parse_nested(struct nlattr **, int, struct nlattr *,
|
||||
struct nla_policy *);
|
||||
extern int nla_is_nested(struct nlattr *);
|
||||
|
||||
/**
|
||||
* @name Attribute Construction (Exception Based)
|
||||
|
|
|
@ -6,281 +6,15 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_CACHE_API_H_
|
||||
#define NETLINK_CACHE_API_H_
|
||||
#ifndef NETLINK_DUMMY_CACHE_API_H_
|
||||
#define NETLINK_DUMMY_CACHE_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *);
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
/**
|
||||
* Parser parameters
|
||||
*
|
||||
* This structure is used to configure what kind of parser to use
|
||||
* when parsing netlink messages to create objects.
|
||||
*/
|
||||
struct nl_parser_param
|
||||
{
|
||||
/** Function to parse netlink messages into objects */
|
||||
int (*pp_cb)(struct nl_object *, struct nl_parser_param *);
|
||||
|
||||
/** Arbitary argument to be passed to the parser */
|
||||
void * pp_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache Operations
|
||||
*
|
||||
* This structure defines the characterstics of a cache type. It contains
|
||||
* pointers to functions which implement the specifics of the object type
|
||||
* the cache can hold.
|
||||
*/
|
||||
struct nl_cache_ops
|
||||
{
|
||||
/** Name of cache type (must be unique) */
|
||||
char * co_name;
|
||||
|
||||
/** Size of family specific netlink header */
|
||||
int co_hdrsize;
|
||||
|
||||
/** Netlink protocol */
|
||||
int co_protocol;
|
||||
|
||||
/** cache object hash size **/
|
||||
int co_hash_size;
|
||||
|
||||
/** cache flags */
|
||||
unsigned int co_flags;
|
||||
|
||||
/** Reference counter */
|
||||
unsigned int co_refcnt;
|
||||
|
||||
/** Group definition */
|
||||
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 *);
|
||||
|
||||
/**
|
||||
* The function registered under this callback is called after a
|
||||
* netlink notification associated with this cache type has been
|
||||
* parsed into an object and is being considered for inclusio into
|
||||
* the specified cache.
|
||||
*
|
||||
* The purpose of this function is to filter out notifications
|
||||
* which should be ignored when updating caches.
|
||||
*
|
||||
* The function must return NL_SKIP to prevent the object from
|
||||
* being included, or NL_OK to include it.
|
||||
*
|
||||
* @code
|
||||
* int my_filter(struct nl_cache *cache, struct nl_object *obj)
|
||||
* {
|
||||
* if (reason_to_not_include_obj(obj))
|
||||
* return NL_SKIP;
|
||||
*
|
||||
* return NL_OK;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
int (*co_event_filter)(struct nl_cache *, struct nl_object *obj);
|
||||
|
||||
/**
|
||||
* The function registered under this callback is called when an
|
||||
* object formed from a notification event needs to be included in
|
||||
* a cache.
|
||||
*
|
||||
* For each modified object, the change callback \c change_cb must
|
||||
* be called with the \c data argument provided.
|
||||
*
|
||||
* If no function is registered, the function nl_cache_include()
|
||||
* will be used for this purpose.
|
||||
*
|
||||
* @see nl_cache_include()
|
||||
*/
|
||||
int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj,
|
||||
change_func_t change_cb, void *data);
|
||||
|
||||
void (*reserved_1)(void);
|
||||
void (*reserved_2)(void);
|
||||
void (*reserved_3)(void);
|
||||
void (*reserved_4)(void);
|
||||
void (*reserved_5)(void);
|
||||
void (*reserved_6)(void);
|
||||
void (*reserved_7)(void);
|
||||
void (*reserved_8)(void);
|
||||
|
||||
/** Object operations */
|
||||
struct nl_object_ops * co_obj_ops;
|
||||
|
||||
/** Internal, do not touch! */
|
||||
struct nl_cache_ops *co_next;
|
||||
|
||||
struct nl_cache *co_major_cache;
|
||||
struct genl_ops * co_genl;
|
||||
|
||||
/* Message type definition */
|
||||
struct nl_msgtype co_msgtypes[];
|
||||
};
|
||||
|
||||
extern void nl_cache_ops_get(struct nl_cache_ops *);
|
||||
extern void nl_cache_ops_put(struct nl_cache_ops *);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#warning "You are including a deprecated header file, include <netlink/cache.h>."
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,13 +16,25 @@
|
|||
#include <netlink/msg.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/object.h>
|
||||
#include <netlink/cache-api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
||||
struct nl_cache;
|
||||
typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int, void *);
|
||||
|
||||
/**
|
||||
* @ingroup cache
|
||||
|
@ -146,6 +158,9 @@ extern void nl_cache_mngr_info(struct nl_cache_mngr *,
|
|||
struct nl_dump_params *);
|
||||
extern void nl_cache_mngr_free(struct nl_cache_mngr *);
|
||||
|
||||
extern void nl_cache_ops_get(struct nl_cache_ops *);
|
||||
extern void nl_cache_ops_put(struct nl_cache_ops *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#ifndef __NETLINK_CLI_TC_H_
|
||||
#define __NETLINK_CLI_TC_H_
|
||||
|
||||
#include <netlink/route/tc-api.h>
|
||||
#include <netlink/route/tc.h>
|
||||
|
||||
struct rtnl_tc_ops;
|
||||
|
||||
extern void nl_cli_tc_parse_dev(struct rtnl_tc *, struct nl_cache *, char *);
|
||||
extern void nl_cli_tc_parse_parent(struct rtnl_tc *, char *);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -47,6 +48,11 @@
|
|||
#include <netlink/genl/ctrl.h>
|
||||
#include <netlink/genl/mngt.h>
|
||||
#include <netlink/netfilter/ct.h>
|
||||
#include <netlink/dect/transceiver.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/llme.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef NETLINK_DECT_ARI_H
|
||||
#define NETLINK_DECT_ARI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern int nl_dect_parse_ari(struct nl_dect_ari *,
|
||||
struct nlattr *);
|
||||
extern int nl_dect_fill_ari(struct nl_msg *,
|
||||
const struct nl_dect_ari *,
|
||||
int);
|
||||
extern void nl_dect_dump_ari(const struct nl_dect_ari *,
|
||||
struct nl_dump_params *);
|
||||
|
||||
extern const char * nl_dect_ari_class2str(enum dect_ari_classes,
|
||||
char *buf, size_t len);
|
||||
extern enum dect_ari_classes nl_dect_ari_str2class(const char *);
|
||||
|
||||
extern void nl_dect_ari_set_class(struct nl_dect_ari *,
|
||||
enum dect_ari_classes);
|
||||
extern enum dect_ari_classes nl_dect_ari_get_class(const struct nl_dect_ari *);
|
||||
|
||||
extern void nl_dect_ari_set_fpn(struct nl_dect_ari *, uint32_t);
|
||||
extern uint32_t nl_dect_ari_get_fpn(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_fps(struct nl_dect_ari *, uint32_t);
|
||||
extern uint32_t nl_dect_ari_get_fps(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_emc(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_emc(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_eic(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_eic(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_poc(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_poc(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_gop(struct nl_dect_ari *, uint32_t);
|
||||
extern uint32_t nl_dect_ari_get_gop(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_fil(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_fil(const struct nl_dect_ari *);
|
||||
|
||||
#endif /* NETLINK_DECT_ARI_H */
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef NETLINK_DECT_CELL_H
|
||||
#define NETLINK_DECT_CELL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_cell;
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern struct nl_object_ops nl_dect_cell_obj_ops;
|
||||
|
||||
extern struct nl_dect_cell * nl_dect_cell_alloc(void);
|
||||
extern void nl_dect_cell_get(struct nl_dect_cell *);
|
||||
extern void nl_dect_cell_put(struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_index(struct nl_dect_cell *, int);
|
||||
extern bool nl_dect_cell_test_index(const struct nl_dect_cell *);
|
||||
extern int nl_dect_cell_get_index(const struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_name(struct nl_dect_cell *, const char *);
|
||||
extern bool nl_dect_cell_test_name(const struct nl_dect_cell *);
|
||||
extern const char * nl_dect_cell_get_name(const struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_flags(struct nl_dect_cell *, uint32_t);
|
||||
extern bool nl_dect_cell_test_flags(const struct nl_dect_cell *);
|
||||
extern uint32_t nl_dect_cell_get_flags(const struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_transceiver(struct nl_dect_cell *,
|
||||
unsigned int,
|
||||
const char *);
|
||||
extern bool nl_dect_cell_test_transceiver(const struct nl_dect_cell *);
|
||||
extern const char * nl_dect_cell_get_transceiver(const struct nl_dect_cell *,
|
||||
unsigned int);
|
||||
|
||||
extern void nl_dect_cell_set_link(struct nl_dect_cell *, int);
|
||||
extern bool nl_dect_cell_test_link(const struct nl_dect_cell *);
|
||||
extern int nl_dect_cell_get_link(const struct nl_dect_cell *);
|
||||
|
||||
extern int nl_dect_cell_alloc_cache(struct nl_sock *,
|
||||
struct nl_cache **);
|
||||
|
||||
extern int nl_dect_cell_build_msg(struct nl_msg *,
|
||||
struct nl_dect_cell *);
|
||||
|
||||
extern int nl_dect_cell_build_add_request(struct nl_dect_cell *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cell_add(struct nl_sock *,
|
||||
struct nl_dect_cell *, int);
|
||||
|
||||
extern int nl_dect_cell_build_del_request(struct nl_dect_cell *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cell_delete(struct nl_sock *,
|
||||
struct nl_dect_cell *, int);
|
||||
|
||||
extern char * nl_dect_cell_i2name(struct nl_cache *, int, char *,
|
||||
size_t);
|
||||
extern int nl_dect_cell_name2i(struct nl_cache *, const char *);
|
||||
|
||||
extern char * nl_dect_cell_flags2str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_cell_str2flags(const char *);
|
||||
|
||||
#endif /* NETLINK_DECT_CELL_H */
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef NETLINK_DECT_CLUSTER_H
|
||||
#define NETLINK_DECT_CLUSTER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_cluster;
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern struct nl_object_ops nl_dect_cluster_obj_ops;
|
||||
|
||||
extern struct nl_dect_cluster * nl_dect_cluster_alloc(void);
|
||||
extern void nl_dect_cluster_get(struct nl_dect_cluster *);
|
||||
extern void nl_dect_cluster_put(struct nl_dect_cluster *);
|
||||
|
||||
extern unsigned int nl_dect_cluster_get_index(const struct nl_dect_cluster *);
|
||||
|
||||
extern void nl_dect_cluster_set_name(struct nl_dect_cluster *,
|
||||
const char *);
|
||||
extern bool nl_dect_cluster_test_name(const struct nl_dect_cluster *);
|
||||
extern const char * nl_dect_cluster_get_name(const struct nl_dect_cluster *);
|
||||
|
||||
extern void nl_dect_cluster_set_mode(struct nl_dect_cluster *,
|
||||
uint8_t mode);
|
||||
extern bool nl_dect_cluster_test_mode(const struct nl_dect_cluster *);
|
||||
extern uint8_t nl_dect_cluster_get_mode(const struct nl_dect_cluster *);
|
||||
|
||||
extern void nl_dect_cluster_set_pari(struct nl_dect_cluster *,
|
||||
const struct nl_dect_ari *);
|
||||
extern bool nl_dect_cluster_test_pari(const struct nl_dect_cluster *);
|
||||
extern const struct nl_dect_ari *nl_dect_cluster_get_pari(const struct nl_dect_cluster *);
|
||||
|
||||
extern char * nl_dect_cluster_mode2str(enum dect_cluster_modes,
|
||||
char *, size_t);
|
||||
extern enum dect_cluster_modes nl_dect_cluster_str2mode(const char *);
|
||||
|
||||
extern int nl_dect_cluster_alloc_cache(struct nl_sock *,
|
||||
struct nl_cache **);
|
||||
|
||||
extern int nl_dect_cluster_build_msg(struct nl_msg *,
|
||||
struct nl_dect_cluster *);
|
||||
|
||||
extern int nl_dect_cluster_build_add_request(struct nl_dect_cluster *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cluster_add(struct nl_sock *,
|
||||
struct nl_dect_cluster *, int);
|
||||
|
||||
extern int nl_dect_cluster_build_del_request(struct nl_dect_cluster *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cluster_delete(struct nl_sock *,
|
||||
struct nl_dect_cluster *, int);
|
||||
|
||||
extern int nl_dect_cluster_build_query_request(struct nl_dect_cluster *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cluster_query(struct nl_sock *,
|
||||
struct nl_dect_cluster *, int);
|
||||
|
||||
extern char * nl_dect_cluster_i2name(struct nl_cache *, int, char *,
|
||||
size_t);
|
||||
extern int nl_dect_cluster_name2i(struct nl_cache *, const char *);
|
||||
|
||||
#endif /* NETLINK_DECT_CLUSTER_H */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _NETLINK_DECT_H
|
||||
#define _NETLINK_DECT_H
|
||||
|
||||
extern double nl_dect_rssi_to_dbm(uint8_t);
|
||||
|
||||
#endif /* _NETLINK_DECT_H */
|
|
@ -0,0 +1,94 @@
|
|||
#ifndef NETLINK_DECT_LLME_H
|
||||
#define NETLINK_DECT_LLME_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_llme_msg;
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern struct nl_dect_llme_msg *nl_dect_llme_msg_alloc(void);
|
||||
extern void nl_dect_llme_msg_get(struct nl_dect_llme_msg *);
|
||||
extern void nl_dect_llme_msg_put(struct nl_dect_llme_msg *);
|
||||
|
||||
extern int nl_dect_llme_build_request(struct nl_dect_llme_msg *,
|
||||
struct nl_msg **);
|
||||
extern int nl_dect_llme_request(struct nl_sock *,
|
||||
struct nl_dect_llme_msg *);
|
||||
|
||||
extern int nl_dect_llme_build_response(struct nl_dect_llme_msg *,
|
||||
struct nl_msg **);
|
||||
extern int nl_dect_llme_respond(struct nl_sock *, struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_msg_set_index(struct nl_dect_llme_msg *, int);
|
||||
extern void nl_dect_llme_msg_set_type(struct nl_dect_llme_msg *,
|
||||
enum dect_llme_msg_types);
|
||||
extern enum dect_llme_msg_types nl_dect_llme_msg_get_type(const struct nl_dect_llme_msg *);
|
||||
extern void nl_dect_llme_msg_set_op(struct nl_dect_llme_msg *,
|
||||
enum dect_llme_ops);
|
||||
extern enum dect_llme_ops nl_dect_llme_msg_get_op(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern char * nl_dect_llme_msgtype2str(enum dect_llme_msg_types,
|
||||
char *, size_t);
|
||||
extern enum dect_llme_msg_types nl_dect_llme_str2msgtype(const char *);
|
||||
|
||||
extern char * nl_dect_llme_op2str(enum dect_llme_ops,
|
||||
char *, size_t);
|
||||
extern enum dect_llme_ops nl_dect_llme_str2op(const char *);
|
||||
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_pari(struct nl_dect_llme_msg *lmsg,
|
||||
const struct nl_dect_ari *);
|
||||
extern bool nl_dect_llme_mac_info_test_pari(const struct nl_dect_llme_msg *);
|
||||
extern const struct nl_dect_ari *nl_dect_llme_mac_info_get_pari(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_rpn(struct nl_dect_llme_msg *,
|
||||
uint8_t);
|
||||
extern uint8_t nl_dect_llme_mac_info_get_rpn(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_rssi(struct nl_dect_llme_msg *,
|
||||
uint8_t);
|
||||
extern uint8_t nl_dect_llme_mac_info_get_rssi(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_fpc(struct nl_dect_llme_msg *,
|
||||
uint32_t);
|
||||
extern uint32_t nl_dect_llme_mac_info_get_fpc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_hlc(struct nl_dect_llme_msg *,
|
||||
uint16_t);
|
||||
extern uint16_t nl_dect_llme_mac_info_get_hlc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_efpc(struct nl_dect_llme_msg *,
|
||||
uint16_t);
|
||||
extern uint16_t nl_dect_llme_mac_info_get_efpc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_ehlc(struct nl_dect_llme_msg *,
|
||||
uint32_t);
|
||||
extern uint32_t nl_dect_llme_mac_info_get_ehlc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_efpc2(struct nl_dect_llme_msg *,
|
||||
uint16_t);
|
||||
extern uint16_t nl_dect_llme_mac_info_get_efpc2(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_ehlc2(struct nl_dect_llme_msg *,
|
||||
uint32_t);
|
||||
extern uint32_t nl_dect_llme_mac_info_get_ehlc2(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern char * nl_dect_llme_fpc2str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_llme_str2fpc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_hlc2str(uint16_t, char *, size_t);
|
||||
extern uint16_t nl_dect_llme_str2hlc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_efpc2str(uint16_t, char *, size_t);
|
||||
extern uint16_t nl_dect_llme_str2efpc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_ehlc2str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_llme_str2ehlc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_efpc22str(uint16_t, char *, size_t);
|
||||
extern uint16_t nl_dect_llme_str22efpc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_ehlc22str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_llme_str22ehlc(const char *);
|
||||
|
||||
#endif /* NETLINK_DECT_LLME_H */
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef NETLINK_DECT_TRANSCEIVER_H
|
||||
#define NETLINK_DECT_TRANSCEIVER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_transceiver;
|
||||
|
||||
extern struct nl_object_ops nl_dect_transceiver_obj_ops;
|
||||
|
||||
extern struct nl_dect_transceiver *nl_dect_transceiver_alloc(void);
|
||||
extern void nl_dect_transceiver_get(struct nl_dect_transceiver *);
|
||||
extern void nl_dect_transceiver_put(struct nl_dect_transceiver *);
|
||||
|
||||
extern void nl_dect_transceiver_set_name(struct nl_dect_transceiver *,
|
||||
const char *);
|
||||
extern bool nl_dect_transceiver_test_name(const struct nl_dect_transceiver *);
|
||||
extern const char * nl_dect_transceiver_get_name(const struct nl_dect_transceiver *);
|
||||
|
||||
extern void nl_dect_transceiver_set_type(struct nl_dect_transceiver *,
|
||||
const char *);
|
||||
extern bool nl_dect_transceiver_test_type(const struct nl_dect_transceiver *);
|
||||
extern const char * nl_dect_transceiver_get_type(const struct nl_dect_transceiver *);
|
||||
|
||||
extern void nl_dect_transceiver_set_features(struct nl_dect_transceiver *,
|
||||
uint32_t);
|
||||
extern void nl_dect_transceiver_set_index(struct nl_dect_transceiver *,
|
||||
int);
|
||||
extern void nl_dect_transceiver_set_link(struct nl_dect_transceiver *,
|
||||
uint8_t);
|
||||
|
||||
extern void nl_dect_transceiver_set_band(struct nl_dect_transceiver *,
|
||||
uint8_t);
|
||||
extern bool nl_dect_transceiver_test_band(const struct nl_dect_transceiver *);
|
||||
extern uint8_t nl_dect_transceiver_get_band(const struct nl_dect_transceiver *);
|
||||
|
||||
extern int nl_dect_transceiver_build_msg(struct nl_msg *,
|
||||
struct nl_dect_transceiver *);
|
||||
extern int nl_dect_transceiver_build_change_request(struct nl_dect_transceiver *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_transceiver_change(struct nl_sock *,
|
||||
struct nl_dect_transceiver *, int flags);
|
||||
|
||||
extern const char * nl_dect_transceiver_features2str(uint32_t, char *, size_t);
|
||||
|
||||
extern const char * nl_dect_slot_state2str(uint8_t, char *, size_t);
|
||||
extern uint8_t nl_dect_slot_str2state(const char *);
|
||||
|
||||
extern const char * nl_dect_slot_flags2str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_slot_str2flags(const char *);
|
||||
|
||||
extern const char * nl_dect_slot_packet2str(uint8_t, char *, size_t);
|
||||
extern uint8_t nl_dect_slot_str2packet(const char *);
|
||||
|
||||
extern int nl_dect_transceiver_alloc_cache(struct nl_sock *,
|
||||
struct nl_cache **);
|
||||
|
||||
#endif /* NETLINK_DECT_TRANSCEIVER_H */
|
|
@ -93,6 +93,8 @@ extern unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *);
|
|||
extern struct nl_msg * nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *);
|
||||
extern int nfnl_queue_msg_send_verdict(struct nl_sock *,
|
||||
const struct nfnl_queue_msg *);
|
||||
extern int nfnl_queue_msg_send_verdict_batch(struct nl_sock *,
|
||||
const struct nfnl_queue_msg *);
|
||||
extern int nfnl_queue_msg_send_verdict_payload(struct nl_sock *,
|
||||
const struct nfnl_queue_msg *,
|
||||
const void *, unsigned );
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_NETLINK_H_
|
||||
|
@ -26,19 +26,23 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
#include <netlink/version.h>
|
||||
#include <netlink/errno.h>
|
||||
#include <netlink/types.h>
|
||||
#include <netlink/handlers.h>
|
||||
#include <netlink/socket.h>
|
||||
#include <netlink/object.h>
|
||||
#include <netlink/cache-api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ucred;
|
||||
struct nl_cache_ops;
|
||||
struct nl_parser_param;
|
||||
struct nl_object;
|
||||
struct nl_sock;
|
||||
|
||||
extern int nl_debug;
|
||||
extern struct nl_dump_params nl_debug_dp;
|
||||
|
|
|
@ -1,375 +1,19 @@
|
|||
/*
|
||||
* netlink/object-api.c Object API
|
||||
* netlink/object-api.h 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>
|
||||
* Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_OBJECT_API_H_
|
||||
#define NETLINK_OBJECT_API_H_
|
||||
#ifndef NETLINK_DUMMY_OBJECT_API_H_
|
||||
#define NETLINK_DUMMY_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;
|
||||
|
||||
struct nl_object
|
||||
{
|
||||
NLHDR_COMMON
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 attribute is available in only one of both objects
|
||||
* @arg A an object
|
||||
* @arg B another object
|
||||
* @arg ATTR attribute bit
|
||||
*
|
||||
* @return True if the attribute is available in only one of both objects,
|
||||
* otherwise false is returned.
|
||||
*/
|
||||
#define AVAILABLE_MISMATCH(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_MISMATCH(A, B, ATTR) || \
|
||||
(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_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);
|
||||
|
||||
|
||||
/**
|
||||
* update function
|
||||
*
|
||||
* Will be called when the object given by first argument
|
||||
* needs to be updated with the contents of the second object
|
||||
*
|
||||
* The function must return 0 for success and error for failure
|
||||
* to update. In case of failure its assumed that the original
|
||||
* object is not touched
|
||||
*/
|
||||
int (*oo_update)(struct nl_object *, struct nl_object *);
|
||||
|
||||
/**
|
||||
* Hash Key generator function
|
||||
*
|
||||
* When called returns a hash key for the object being
|
||||
* referenced. This key will be used by higher level hash functions
|
||||
* to build association lists. Each object type gets to specify
|
||||
* it's own key formulation
|
||||
*/
|
||||
void (*oo_keygen)(struct nl_object *, uint32_t *, uint32_t);
|
||||
|
||||
char *(*oo_attrs2str)(int, char *, size_t);
|
||||
|
||||
/**
|
||||
* Get key attributes by family function
|
||||
*/
|
||||
uint32_t (*oo_id_attrs_get)(struct nl_object *);
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <netlink/object.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,7 @@ extern struct nl_cache * nl_object_get_cache(struct nl_object *);
|
|||
extern const char * nl_object_get_type(const struct nl_object *);
|
||||
extern int nl_object_get_msgtype(const struct nl_object *);
|
||||
struct nl_object_ops * nl_object_get_ops(const struct nl_object *);
|
||||
uint32_t nl_object_get_id_attrs(struct nl_object *obj);
|
||||
|
||||
|
||||
static inline void * nl_object_priv(struct nl_object *obj)
|
||||
|
|
|
@ -99,7 +99,6 @@ typedef enum {
|
|||
|
||||
extern struct rtnl_link *rtnl_link_alloc(void);
|
||||
extern void rtnl_link_put(struct rtnl_link *);
|
||||
extern void rtnl_link_free(struct rtnl_link *);
|
||||
|
||||
extern int rtnl_link_alloc_cache(struct nl_sock *, int, struct nl_cache **);
|
||||
extern struct rtnl_link *rtnl_link_get(struct nl_cache *, int);
|
||||
|
@ -141,6 +140,10 @@ extern int rtnl_link_str2operstate(const char *);
|
|||
extern char * rtnl_link_mode2str(uint8_t, char *, size_t);
|
||||
extern int rtnl_link_str2mode(const char *);
|
||||
|
||||
/* Carrier State Translations */
|
||||
extern char * rtnl_link_carrier2str(uint8_t, char *, size_t);
|
||||
extern int rtnl_link_str2carrier(const char *);
|
||||
|
||||
/* Access Functions */
|
||||
extern void rtnl_link_set_qdisc(struct rtnl_link *, const char *);
|
||||
extern char * rtnl_link_get_qdisc(struct rtnl_link *);
|
||||
|
@ -182,6 +185,9 @@ extern int rtnl_link_get_link(struct rtnl_link *);
|
|||
extern void rtnl_link_set_master(struct rtnl_link *, int);
|
||||
extern int rtnl_link_get_master(struct rtnl_link *);
|
||||
|
||||
extern void rtnl_link_set_carrier(struct rtnl_link *, uint8_t);
|
||||
extern uint8_t rtnl_link_get_carrier(struct rtnl_link *);
|
||||
|
||||
extern void rtnl_link_set_operstate(struct rtnl_link *, uint8_t);
|
||||
extern uint8_t rtnl_link_get_operstate(struct rtnl_link *);
|
||||
|
||||
|
|
|
@ -6,132 +6,15 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_API_H_
|
||||
#define NETLINK_LINK_API_H_
|
||||
#ifndef NETLINK_DUMMY_LINK_API_H_
|
||||
#define NETLINK_DUMMY_LINK_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup link_api
|
||||
*
|
||||
* Available operations to modules implementing a link info type.
|
||||
*/
|
||||
struct rtnl_link_info_ops
|
||||
{
|
||||
/** Name of link info type, must match name on kernel side */
|
||||
char * io_name;
|
||||
|
||||
/** Reference count, DO NOT MODIFY */
|
||||
int io_refcnt;
|
||||
|
||||
/** Called to assign an info type to a link.
|
||||
* Has to allocate enough resources to hold attributes. Can
|
||||
* use link->l_info to store a pointer. */
|
||||
int (*io_alloc)(struct rtnl_link *);
|
||||
|
||||
/** Called to parse the link info attribute.
|
||||
* Must parse the attribute and assign all values to the link.
|
||||
*/
|
||||
int (*io_parse)(struct rtnl_link *,
|
||||
struct nlattr *,
|
||||
struct nlattr *);
|
||||
|
||||
/** Called when the link object is dumped.
|
||||
* Must dump the info type specific attributes. */
|
||||
void (*io_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
|
||||
struct nl_dump_params *);
|
||||
|
||||
/** Called when a link object is cloned.
|
||||
* Must clone all info type specific attributes. */
|
||||
int (*io_clone)(struct rtnl_link *, struct rtnl_link *);
|
||||
|
||||
/** Called when construction a link netlink message.
|
||||
* Must append all info type specific attributes to the message. */
|
||||
int (*io_put_attrs)(struct nl_msg *, struct rtnl_link *);
|
||||
|
||||
/** Called to release all resources previously allocated
|
||||
* in either io_alloc() or io_parse(). */
|
||||
void (*io_free)(struct rtnl_link *);
|
||||
|
||||
struct nl_list_head io_list;
|
||||
};
|
||||
|
||||
extern struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *);
|
||||
extern void rtnl_link_info_ops_put(struct rtnl_link_info_ops *);
|
||||
extern int rtnl_link_register_info(struct rtnl_link_info_ops *);
|
||||
extern int rtnl_link_unregister_info(struct rtnl_link_info_ops *);
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup link_api
|
||||
*
|
||||
* Available operations to modules implementing a link address family.
|
||||
*/
|
||||
struct rtnl_link_af_ops
|
||||
{
|
||||
/** The address family this operations set implements */
|
||||
const unsigned int ao_family;
|
||||
|
||||
/** Number of users of this operations, DO NOT MODIFY. */
|
||||
int ao_refcnt;
|
||||
|
||||
/** Validation policy for IFLA_PROTINFO attribute. This pointer
|
||||
* can be set to a nla_policy structure describing the minimal
|
||||
* requirements the attribute must meet. Failure of meeting these
|
||||
* requirements will result in a parsing error. */
|
||||
const struct nla_policy *ao_protinfo_policy;
|
||||
|
||||
/** Called after address family has been assigned to link. Must
|
||||
* allocate data buffer to hold address family specific data and
|
||||
* store it in link->l_af_data. */
|
||||
void * (*ao_alloc)(struct rtnl_link *);
|
||||
|
||||
/** Called when the link is cloned, must allocate a clone of the
|
||||
* address family specific buffer and return it. */
|
||||
void * (*ao_clone)(struct rtnl_link *, void *);
|
||||
|
||||
/** Called when the link gets freed. Must free all allocated data */
|
||||
void (*ao_free)(struct rtnl_link *, void *);
|
||||
|
||||
/** Called if a IFLA_PROTINFO attribute needs to be parsed. Typically
|
||||
* stores the parsed data in the address family specific buffer. */
|
||||
int (*ao_parse_protinfo)(struct rtnl_link *,
|
||||
struct nlattr *, void *);
|
||||
|
||||
/** Called if a IFLA_AF_SPEC attribute needs to be parsed. Typically
|
||||
* stores the parsed data in the address family specific buffer. */
|
||||
int (*ao_parse_af)(struct rtnl_link *,
|
||||
struct nlattr *, void *);
|
||||
|
||||
/** Called if a link message is sent to the kernel. Must append the
|
||||
* link address family specific attributes to the message. */
|
||||
int (*ao_fill_af)(struct rtnl_link *,
|
||||
struct nl_msg *msg, void *);
|
||||
|
||||
/** Dump address family specific link attributes */
|
||||
void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
|
||||
struct nl_dump_params *,
|
||||
void *);
|
||||
};
|
||||
|
||||
extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int);
|
||||
extern void rtnl_link_af_ops_put(struct rtnl_link_af_ops *);
|
||||
extern void * rtnl_link_af_alloc(struct rtnl_link *,
|
||||
const struct rtnl_link_af_ops *);
|
||||
extern void * rtnl_link_af_data(const struct rtnl_link *,
|
||||
const struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_register(struct rtnl_link_af_ops *);
|
||||
extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#warning "You are including a deprecated header file, include <netlink/route/link.h>."
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2011-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_BONDING_H_
|
||||
|
@ -19,6 +19,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct rtnl_link *rtnl_link_bond_alloc(void);
|
||||
|
||||
extern int rtnl_link_bond_add(struct nl_sock *, const char *,
|
||||
struct rtnl_link *);
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* netlink/route/link/bridge.h Bridge
|
||||
*
|
||||
* 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) 2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_BRIDGE_H_
|
||||
#define NETLINK_LINK_BRIDGE_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Bridge flags
|
||||
* @ingroup bridge
|
||||
*/
|
||||
enum rtnl_link_bridge_flags {
|
||||
RTNL_BRIDGE_HAIRPIN_MODE = 0x0001,
|
||||
RTNL_BRIDGE_BPDU_GUARD = 0x0002,
|
||||
RTNL_BRIDGE_ROOT_BLOCK = 0x0004,
|
||||
RTNL_BRIDGE_FAST_LEAVE = 0x0008,
|
||||
};
|
||||
|
||||
extern struct rtnl_link *rtnl_link_bridge_alloc(void);
|
||||
|
||||
extern int rtnl_link_is_bridge(struct rtnl_link *);
|
||||
extern int rtnl_link_bridge_has_ext_info(struct rtnl_link *);
|
||||
|
||||
extern int rtnl_link_bridge_set_port_state(struct rtnl_link *, uint8_t );
|
||||
extern int rtnl_link_bridge_get_port_state(struct rtnl_link *);
|
||||
|
||||
extern int rtnl_link_bridge_set_priority(struct rtnl_link *, uint16_t);
|
||||
extern int rtnl_link_bridge_get_priority(struct rtnl_link *);
|
||||
|
||||
extern int rtnl_link_bridge_set_cost(struct rtnl_link *, uint32_t);
|
||||
extern int rtnl_link_bridge_get_cost(struct rtnl_link *, uint32_t *);
|
||||
|
||||
extern int rtnl_link_bridge_unset_flags(struct rtnl_link *, unsigned int);
|
||||
extern int rtnl_link_bridge_set_flags(struct rtnl_link *, unsigned int);
|
||||
extern int rtnl_link_bridge_get_flags(struct rtnl_link *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@ extern int rtnl_link_can_str2ctrlmode(const char *);
|
|||
|
||||
extern int rtnl_link_can_restart(struct rtnl_link *);
|
||||
extern int rtnl_link_can_freq(struct rtnl_link *, uint32_t *);
|
||||
extern int rtnl_link_can_state(struct rtnl_link *, uint32_t *);
|
||||
|
||||
extern int rtnl_link_can_berr_rx(struct rtnl_link *);
|
||||
extern int rtnl_link_can_berr_tx(struct rtnl_link *);
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
/*
|
||||
* netlink/route/link/info-api.h Link Info API
|
||||
* netlink/route/link/info-api.h Link Modules 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-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_INFO_API_H_
|
||||
#define NETLINK_LINK_INFO_API_H_
|
||||
#ifndef NETLINK_DUMMY_LINK_INFO_API_H_
|
||||
#define NETLINK_DUMMY_LINK_INFO_API_H_
|
||||
|
||||
#warning "<netlink/route/link/info-api.h> is obsolete and may be removed in the future."
|
||||
#warning "include <netlink/route/link/api.h> instead.
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
#include <netlink/route/link/api.h>
|
||||
#warning "You are including a deprecated header file, include <netlink/route/link.h>."
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* netlink/route/link/macvlan.h MACVLAN 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) 2013 Michael Braun <michael-dev@fami-braun.de>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_MACVLAN_H_
|
||||
#define NETLINK_LINK_MACVLAN_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct rtnl_link *rtnl_link_macvlan_alloc(void);
|
||||
|
||||
extern int rtnl_link_is_macvlan(struct rtnl_link *);
|
||||
|
||||
extern char * rtnl_link_macvlan_mode2str(int, char *, size_t);
|
||||
extern int rtnl_link_macvlan_str2mode(const char *);
|
||||
|
||||
extern char * rtnl_link_macvlan_flags2str(int, char *, size_t);
|
||||
extern int rtnl_link_macvlan_str2flags(const char *);
|
||||
|
||||
extern int rtnl_link_macvlan_set_mode(struct rtnl_link *,
|
||||
uint32_t);
|
||||
extern uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *);
|
||||
|
||||
extern int rtnl_link_macvlan_set_flags(struct rtnl_link *,
|
||||
uint16_t);
|
||||
extern int rtnl_link_macvlan_unset_flags(struct rtnl_link *,
|
||||
uint16_t);
|
||||
extern uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_LINK_VLAN_H_
|
||||
|
@ -27,6 +27,8 @@ struct vlan_map
|
|||
|
||||
#define VLAN_PRIO_MAX 7
|
||||
|
||||
extern struct rtnl_link *rtnl_link_vlan_alloc(void);
|
||||
|
||||
extern int rtnl_link_is_vlan(struct rtnl_link *);
|
||||
|
||||
extern char * rtnl_link_vlan_flags2str(int, char *, size_t);
|
||||
|
|
|
@ -54,7 +54,6 @@ extern int rtnl_route_alloc_cache(struct nl_sock *, int, int,
|
|||
struct nl_cache **);
|
||||
|
||||
extern void rtnl_route_get(struct rtnl_route *);
|
||||
extern void rtnl_route_put(struct rtnl_route *);
|
||||
|
||||
extern int rtnl_route_parse(struct nlmsghdr *, struct rtnl_route **);
|
||||
extern int rtnl_route_build_msg(struct nl_msg *, struct rtnl_route *);
|
||||
|
|
|
@ -6,138 +6,16 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#ifndef NETLINK_TC_API_H_
|
||||
#define NETLINK_TC_API_H_
|
||||
#ifndef NETLINK_DUMMY_TC_API_H_
|
||||
#define NETLINK_DUMMY_TC_API_H_
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/msg.h>
|
||||
#include <netlink/route/tc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum rtnl_tc_type {
|
||||
RTNL_TC_TYPE_QDISC,
|
||||
RTNL_TC_TYPE_CLASS,
|
||||
RTNL_TC_TYPE_CLS,
|
||||
__RTNL_TC_TYPE_MAX,
|
||||
};
|
||||
|
||||
#define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1)
|
||||
|
||||
/**
|
||||
* Traffic control object operations
|
||||
* @ingroup tc
|
||||
*
|
||||
* This structure holds function pointers and settings implementing
|
||||
* the features of each traffic control object implementation.
|
||||
*/
|
||||
struct rtnl_tc_ops
|
||||
{
|
||||
/**
|
||||
* Name of traffic control module
|
||||
*/
|
||||
char *to_kind;
|
||||
|
||||
/**
|
||||
* Type of traffic control object
|
||||
*/
|
||||
enum rtnl_tc_type to_type;
|
||||
|
||||
|
||||
/**
|
||||
* Size of private data
|
||||
*/
|
||||
size_t to_size;
|
||||
|
||||
/**
|
||||
* Dump callbacks
|
||||
*/
|
||||
void (*to_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, void *,
|
||||
struct nl_dump_params *);
|
||||
/**
|
||||
* Used to fill the contents of TCA_OPTIONS
|
||||
*/
|
||||
int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *);
|
||||
|
||||
/**
|
||||
* Uesd to to fill tc related messages, unlike with to_msg_fill,
|
||||
* the contents is not encapsulated with a TCA_OPTIONS nested
|
||||
* attribute.
|
||||
*/
|
||||
int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *);
|
||||
|
||||
/**
|
||||
* TCA_OPTIONS message parser
|
||||
*/
|
||||
int (*to_msg_parser)(struct rtnl_tc *, void *);
|
||||
|
||||
/**
|
||||
* Called before a tc object is destroyed
|
||||
*/
|
||||
void (*to_free_data)(struct rtnl_tc *, void *);
|
||||
|
||||
/**
|
||||
* Called whenever a classifier object needs to be cloned
|
||||
*/
|
||||
int (*to_clone)(void *, void *);
|
||||
|
||||
/**
|
||||
* Internal, don't touch
|
||||
*/
|
||||
struct nl_list_head to_list;
|
||||
};
|
||||
|
||||
struct rtnl_tc_type_ops
|
||||
{
|
||||
enum rtnl_tc_type tt_type;
|
||||
|
||||
char *tt_dump_prefix;
|
||||
|
||||
/**
|
||||
* Dump callbacks
|
||||
*/
|
||||
void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *,
|
||||
struct nl_dump_params *);
|
||||
};
|
||||
|
||||
extern int rtnl_tc_msg_parse(struct nlmsghdr *,
|
||||
struct rtnl_tc *);
|
||||
extern int rtnl_tc_msg_build(struct rtnl_tc *, int,
|
||||
int, struct nl_msg **);
|
||||
|
||||
extern void rtnl_tc_free_data(struct nl_object *);
|
||||
extern int rtnl_tc_clone(struct nl_object *,
|
||||
struct nl_object *);
|
||||
extern void rtnl_tc_dump_line(struct nl_object *,
|
||||
struct nl_dump_params *);
|
||||
extern void rtnl_tc_dump_details(struct nl_object *,
|
||||
struct nl_dump_params *);
|
||||
extern void rtnl_tc_dump_stats(struct nl_object *,
|
||||
struct nl_dump_params *);
|
||||
extern int rtnl_tc_compare(struct nl_object *,
|
||||
struct nl_object *,
|
||||
uint32_t, int);
|
||||
|
||||
extern void * rtnl_tc_data(struct rtnl_tc *);
|
||||
extern void * rtnl_tc_data_check(struct rtnl_tc *,
|
||||
struct rtnl_tc_ops *);
|
||||
|
||||
extern struct rtnl_tc_ops * rtnl_tc_lookup_ops(enum rtnl_tc_type,
|
||||
const char *);
|
||||
extern struct rtnl_tc_ops * rtnl_tc_get_ops(struct rtnl_tc *);
|
||||
extern int rtnl_tc_register(struct rtnl_tc_ops *);
|
||||
extern void rtnl_tc_unregister(struct rtnl_tc_ops *);
|
||||
|
||||
extern void rtnl_tc_type_register(struct rtnl_tc_type_ops *);
|
||||
extern void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#warning "You are including a deprecated header file, include <netlink/route/tc.h>."
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,15 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum rtnl_tc_type {
|
||||
RTNL_TC_TYPE_QDISC,
|
||||
RTNL_TC_TYPE_CLASS,
|
||||
RTNL_TC_TYPE_CLS,
|
||||
__RTNL_TC_TYPE_MAX,
|
||||
};
|
||||
|
||||
#define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1)
|
||||
|
||||
/**
|
||||
* Compute tc handle based on major and minor parts
|
||||
* @ingroup tc
|
||||
|
|
|
@ -13,7 +13,7 @@ AM_LDFLAGS = \
|
|||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la
|
||||
libnl-3.la libnl-genl-3.la libnl-route-3.la libnl-nf-3.la libnl-dect-3.la
|
||||
|
||||
libnl_3_la_SOURCES = \
|
||||
addr.c attr.c cache.c cache_mngr.c cache_mngt.c data.c \
|
||||
|
@ -32,6 +32,12 @@ libnl_nf_3_la_SOURCES = \
|
|||
netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \
|
||||
netfilter/exp.c netfilter/exp_obj.c
|
||||
|
||||
libnl_dect_3_la_LIBADD = libnl-3.la
|
||||
libnl_dect_3_la_SOURCES = \
|
||||
dect/ari.c dect/cell.c dect/cell_obj.c \
|
||||
dect/cluster.c dect/cluster_obj.c dect/dect.c dect/llme.c \
|
||||
dect/transceiver.c dect/transceiver_obj.c
|
||||
|
||||
CLEANFILES = \
|
||||
route/pktloc_grammar.c route/pktloc_grammar.h \
|
||||
route/pktloc_syntax.c route/pktloc_syntax.h \
|
||||
|
@ -69,7 +75,7 @@ libnl_route_3_la_SOURCES = \
|
|||
\
|
||||
route/link/api.c route/link/vlan.c route/link/dummy.c \
|
||||
route/link/bridge.c route/link/inet6.c route/link/inet.c \
|
||||
route/link/bonding.c route/link/can.c \
|
||||
route/link/bonding.c route/link/can.c route/link/macvlan.c \
|
||||
\
|
||||
route/qdisc/blackhole.c route/qdisc/cbq.c route/qdisc/dsmark.c \
|
||||
route/qdisc/fifo.c route/qdisc/htb.c route/qdisc/netem.c \
|
||||
|
|
236
lib/addr.c
236
lib/addr.c
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/addr.h>
|
||||
|
@ -170,9 +170,17 @@ static void addr_destroy(struct nl_addr *addr)
|
|||
*/
|
||||
|
||||
/**
|
||||
* Allocate new abstract address object.
|
||||
* @arg maxsize Maximum size of the binary address.
|
||||
* @return Newly allocated address object or NULL
|
||||
* Allocate empty abstract address
|
||||
* @arg maxsize Upper limit of the binary address to be stored
|
||||
*
|
||||
* The new address object will be empty with a prefix length of 0 and will
|
||||
* be capable of holding binary addresses up to the specified limit.
|
||||
*
|
||||
* @see nl_addr_build()
|
||||
* @see nl_addr_parse()
|
||||
* @see nl_addr_put()
|
||||
*
|
||||
* @return Allocated address object or NULL upon failure.
|
||||
*/
|
||||
struct nl_addr *nl_addr_alloc(size_t maxsize)
|
||||
{
|
||||
|
@ -189,11 +197,21 @@ struct nl_addr *nl_addr_alloc(size_t maxsize)
|
|||
}
|
||||
|
||||
/**
|
||||
* Allocate new abstract address object based on a binary address.
|
||||
* @arg family Address family.
|
||||
* @arg buf Buffer containing the binary address.
|
||||
* @arg size Length of binary address buffer.
|
||||
* @return Newly allocated address handle or NULL
|
||||
* Allocate abstract address based on a binary address.
|
||||
* @arg family Address family
|
||||
* @arg buf Binary address
|
||||
* @arg size Length of binary address
|
||||
*
|
||||
* This function will allocate an abstract address capable of holding the
|
||||
* binary address specified. The prefix length will be set to the full
|
||||
* length of the binary address provided.
|
||||
*
|
||||
* @see nl_addr_alloc()
|
||||
* @see nl_addr_alloc_attr()
|
||||
* @see nl_addr_parse()
|
||||
* @see nl_addr_put()
|
||||
*
|
||||
* @return Allocated address object or NULL upon failure.
|
||||
*/
|
||||
struct nl_addr *nl_addr_build(int family, void *buf, size_t size)
|
||||
{
|
||||
|
@ -214,14 +232,25 @@ struct nl_addr *nl_addr_build(int family, void *buf, size_t size)
|
|||
}
|
||||
|
||||
/**
|
||||
* Allocate abstract address based on netlink attribute.
|
||||
* @arg nla Netlink attribute of unspecific type.
|
||||
* Allocate abstract address based on Netlink attribute.
|
||||
* @arg nla Netlink attribute
|
||||
* @arg family Address family.
|
||||
*
|
||||
* Considers the netlink attribute payload a address of the specified
|
||||
* family and allocates a new abstract address based on it.
|
||||
* Allocates an abstract address based on the specified Netlink attribute
|
||||
* by interpreting the payload of the Netlink attribute as the binary
|
||||
* address.
|
||||
*
|
||||
* @return Newly allocated address handle or NULL.
|
||||
* This function is identical to:
|
||||
* @code
|
||||
* nl_addr_build(family, nla_data(nla), nla_len(nla));
|
||||
* @endcode
|
||||
*
|
||||
* @see nl_addr_alloc()
|
||||
* @see nl_addr_build()
|
||||
* @see nl_addr_parse()
|
||||
* @see nl_addr_put()
|
||||
*
|
||||
* @return Allocated address object or NULL upon failure.
|
||||
*/
|
||||
struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
|
||||
{
|
||||
|
@ -229,13 +258,13 @@ struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
|
|||
}
|
||||
|
||||
/**
|
||||
* Allocate abstract address object based on a character string
|
||||
* Allocate abstract address based on character string
|
||||
* @arg addrstr Address represented as character string.
|
||||
* @arg hint Address family hint or AF_UNSPEC.
|
||||
* @arg result Pointer to store resulting address.
|
||||
*
|
||||
* Regognizes the following address formats:
|
||||
*@code
|
||||
* @code
|
||||
* Format Len Family
|
||||
* ----------------------------------------------------------------
|
||||
* IPv6 address format 16 AF_INET6
|
||||
|
@ -253,6 +282,10 @@ struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
|
|||
* The prefix length may be appened at the end prefixed with a
|
||||
* slash, e.g. 10.0.0.0/8.
|
||||
*
|
||||
* @see nl_addr_alloc()
|
||||
* @see nl_addr_build()
|
||||
* @see nl_addr_put()
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
|
||||
|
@ -424,10 +457,16 @@ errout:
|
|||
}
|
||||
|
||||
/**
|
||||
* Clone existing abstract address object.
|
||||
* @arg addr Abstract address object.
|
||||
* @return Newly allocated abstract address object being a duplicate of the
|
||||
* specified address object or NULL if a failure occured.
|
||||
* Clone existing abstract address object
|
||||
* @arg addr Abstract address object
|
||||
*
|
||||
* Allocates new abstract address representing an identical clone of an
|
||||
* existing address.
|
||||
*
|
||||
* @see nl_addr_alloc()
|
||||
* @see nl_addr_put()
|
||||
*
|
||||
* @return Allocated abstract address or NULL upon failure.
|
||||
*/
|
||||
struct nl_addr *nl_addr_clone(struct nl_addr *addr)
|
||||
{
|
||||
|
@ -447,6 +486,18 @@ struct nl_addr *nl_addr_clone(struct nl_addr *addr)
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Increase the reference counter of an abstract address
|
||||
* @arg addr Abstract address
|
||||
*
|
||||
* Increases the reference counter of the address and thus prevents the
|
||||
* release of the memory resources until the reference is given back
|
||||
* using the function nl_addr_put().
|
||||
*
|
||||
* @see nl_addr_put()
|
||||
*
|
||||
* @return Pointer to the existing abstract address
|
||||
*/
|
||||
struct nl_addr *nl_addr_get(struct nl_addr *addr)
|
||||
{
|
||||
addr->a_refcnt++;
|
||||
|
@ -454,6 +505,15 @@ struct nl_addr *nl_addr_get(struct nl_addr *addr)
|
|||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the reference counter of an abstract address
|
||||
* @arg addr Abstract addr
|
||||
*
|
||||
* @note The resources of the abstract address will be freed after the
|
||||
* last reference to the address has been returned.
|
||||
*
|
||||
* @see nl_addr_get()
|
||||
*/
|
||||
void nl_addr_put(struct nl_addr *addr)
|
||||
{
|
||||
if (!addr)
|
||||
|
@ -466,9 +526,10 @@ void nl_addr_put(struct nl_addr *addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* Check whether an abstract address object is shared.
|
||||
* Check whether an abstract address is shared.
|
||||
* @arg addr Abstract address object.
|
||||
* @return Non-zero if the abstract address object is shared, otherwise 0.
|
||||
*
|
||||
* @return Non-zero if the abstract address is shared, otherwise 0.
|
||||
*/
|
||||
int nl_addr_shared(struct nl_addr *addr)
|
||||
{
|
||||
|
@ -483,12 +544,21 @@ int nl_addr_shared(struct nl_addr *addr)
|
|||
*/
|
||||
|
||||
/**
|
||||
* Compares two abstract address objects.
|
||||
* @arg a A abstract address object.
|
||||
* @arg b Another abstract address object.
|
||||
* Compare abstract addresses
|
||||
* @arg a An abstract address
|
||||
* @arg b Another abstract address
|
||||
*
|
||||
* @return Integer less than, equal to or greather than zero if \c is found,
|
||||
* respectively to be less than, to, or be greater than \c b.
|
||||
* Verifies whether the address family, address length, prefix length, and
|
||||
* binary addresses of two abstract addresses matches.
|
||||
*
|
||||
* @note This function will *not* respect the prefix length in the sense
|
||||
* that only the actual prefix will be compared. Please refer to the
|
||||
* nl_addr_cmp_prefix() function if you require this functionality.
|
||||
*
|
||||
* @see nl_addr_cmp_prefix()
|
||||
*
|
||||
* @return Integer less than, equal to or greather than zero if the two
|
||||
* addresses match.
|
||||
*/
|
||||
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
|
||||
{
|
||||
|
@ -509,12 +579,17 @@ int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
|
|||
}
|
||||
|
||||
/**
|
||||
* Compares the prefix of two abstract address objects.
|
||||
* @arg a A abstract address object.
|
||||
* @arg b Another abstract address object.
|
||||
* Compare the prefix of two abstract addresses
|
||||
* @arg a An abstract address
|
||||
* @arg b Another abstract address
|
||||
*
|
||||
* @return Integer less than, equal to or greather than zero if \c is found,
|
||||
* respectively to be less than, to, or be greater than \c b.
|
||||
* Verifies whether the address family and the binary address covered by
|
||||
* the smaller prefix length of the two abstract addresses matches.
|
||||
*
|
||||
* @see nl_addr_cmp()
|
||||
*
|
||||
* @return Integer less than, equal to or greather than zero if the two
|
||||
* addresses match.
|
||||
*/
|
||||
int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
|
||||
{
|
||||
|
@ -525,8 +600,8 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
|
|||
int bytes = len / 8;
|
||||
|
||||
d = memcmp(a->a_addr, b->a_addr, bytes);
|
||||
if (d == 0) {
|
||||
int mask = (1UL << (len % 8)) - 1UL;
|
||||
if (d == 0 && (len % 8) != 0) {
|
||||
int mask = (0xFF00 >> (len % 8)) & 0xFF;
|
||||
|
||||
d = (a->a_addr[bytes] & mask) -
|
||||
(b->a_addr[bytes] & mask);
|
||||
|
@ -538,7 +613,9 @@ int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
|
|||
|
||||
/**
|
||||
* Returns true if the address consists of all zeros
|
||||
* @arg addr Address to look at.
|
||||
* @arg addr Abstract address
|
||||
*
|
||||
* @return 1 if the binary address consists of all zeros, 0 otherwise.
|
||||
*/
|
||||
int nl_addr_iszero(struct nl_addr *addr)
|
||||
{
|
||||
|
@ -552,11 +629,11 @@ int nl_addr_iszero(struct nl_addr *addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if an address matches a certain family.
|
||||
* Check if address string is parseable for a specific address family
|
||||
* @arg addr Address represented as character string.
|
||||
* @arg family Desired address family.
|
||||
*
|
||||
* @return 1 if the address is of the desired address family,
|
||||
* @return 1 if the address is parseable assuming the specified address family,
|
||||
* otherwise 0 is returned.
|
||||
*/
|
||||
int nl_addr_valid(char *addr, int family)
|
||||
|
@ -588,9 +665,10 @@ int nl_addr_valid(char *addr, int family)
|
|||
}
|
||||
|
||||
/**
|
||||
* Guess address family of an abstract address object based on address size.
|
||||
* Guess address family of abstract address based on address size
|
||||
* @arg addr Abstract address object.
|
||||
* @return Address family or AF_UNSPEC if guessing wasn't successful.
|
||||
*
|
||||
* @return Numeric address family or AF_UNSPEC
|
||||
*/
|
||||
int nl_addr_guess_family(struct nl_addr *addr)
|
||||
{
|
||||
|
@ -666,7 +744,7 @@ int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa,
|
|||
* Call getaddrinfo() for an abstract address object.
|
||||
* @arg addr Abstract address object.
|
||||
* @arg result Pointer to store resulting address list.
|
||||
*
|
||||
*
|
||||
* Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST
|
||||
* mode.
|
||||
*
|
||||
|
@ -744,11 +822,26 @@ int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set address family
|
||||
* @arg addr Abstract address object
|
||||
* @arg family Address family
|
||||
*
|
||||
* @see nl_addr_get_family()
|
||||
*/
|
||||
void nl_addr_set_family(struct nl_addr *addr, int family)
|
||||
{
|
||||
addr->a_family = family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return address family
|
||||
* @arg addr Abstract address object
|
||||
*
|
||||
* @see nl_addr_set_family()
|
||||
*
|
||||
* @return The numeric address family or `AF_UNSPEC`
|
||||
*/
|
||||
int nl_addr_get_family(struct nl_addr *addr)
|
||||
{
|
||||
return addr->a_family;
|
||||
|
@ -759,6 +852,20 @@ int nl_addr_get_family(struct nl_addr *addr)
|
|||
* @arg addr Abstract address object.
|
||||
* @arg buf Buffer containing binary address.
|
||||
* @arg len Length of buffer containing binary address.
|
||||
*
|
||||
* Modifies the binary address portion of the abstract address. The
|
||||
* abstract address must be capable of holding the required amount
|
||||
* or this function will fail.
|
||||
*
|
||||
* @note This function will *not* modify the prefix length. It is within
|
||||
* the responsibility of the caller to set the prefix length to the
|
||||
* desirable length.
|
||||
*
|
||||
* @see nl_addr_alloc()
|
||||
* @see nl_addr_get_binary_addr()
|
||||
* @see nl_addr_get_len()
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
|
||||
{
|
||||
|
@ -766,7 +873,10 @@ int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
|
|||
return -NLE_RANGE;
|
||||
|
||||
addr->a_len = len;
|
||||
memcpy(addr->a_addr, buf, len);
|
||||
memset(addr->a_addr, 0, addr->a_maxsize);
|
||||
|
||||
if (len)
|
||||
memcpy(addr->a_addr, buf, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -774,6 +884,11 @@ int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
|
|||
/**
|
||||
* Get binary address of abstract address object.
|
||||
* @arg addr Abstract address object.
|
||||
*
|
||||
* @see nl_addr_set_binary_addr()
|
||||
* @see nl_addr_get_len()
|
||||
*
|
||||
* @return Pointer to binary address of length nl_addr_get_len()
|
||||
*/
|
||||
void *nl_addr_get_binary_addr(struct nl_addr *addr)
|
||||
{
|
||||
|
@ -783,20 +898,32 @@ void *nl_addr_get_binary_addr(struct nl_addr *addr)
|
|||
/**
|
||||
* Get length of binary address of abstract address object.
|
||||
* @arg addr Abstract address object.
|
||||
*
|
||||
* @see nl_addr_get_binary_addr()
|
||||
* @see nl_addr_set_binary_addr()
|
||||
*/
|
||||
unsigned int nl_addr_get_len(struct nl_addr *addr)
|
||||
{
|
||||
return addr->a_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prefix length of an abstract address
|
||||
* @arg addr Abstract address object
|
||||
* @arg prefixlen New prefix length
|
||||
*
|
||||
* @see nl_addr_get_prefixlen()
|
||||
*/
|
||||
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
|
||||
{
|
||||
addr->a_prefixlen = prefixlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prefix length of abstract address object.
|
||||
* @arg addr Abstract address object.
|
||||
* Return prefix length of abstract address object.
|
||||
* @arg addr Abstract address object
|
||||
*
|
||||
* @see nl_addr_set_prefixlen()
|
||||
*/
|
||||
unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
|
||||
{
|
||||
|
@ -878,7 +1005,6 @@ prefix:
|
|||
static const struct trans_tbl afs[] = {
|
||||
__ADD(AF_UNSPEC,unspec)
|
||||
__ADD(AF_UNIX,unix)
|
||||
__ADD(AF_LOCAL,local)
|
||||
__ADD(AF_INET,inet)
|
||||
__ADD(AF_AX25,ax25)
|
||||
__ADD(AF_IPX,ipx)
|
||||
|
@ -894,17 +1020,35 @@ static const struct trans_tbl afs[] = {
|
|||
__ADD(AF_SECURITY,security)
|
||||
__ADD(AF_KEY,key)
|
||||
__ADD(AF_NETLINK,netlink)
|
||||
__ADD(AF_ROUTE,route)
|
||||
__ADD(AF_PACKET,packet)
|
||||
__ADD(AF_ASH,ash)
|
||||
__ADD(AF_ECONET,econet)
|
||||
__ADD(AF_ATMSVC,atmsvc)
|
||||
__ADD(AF_RDS,rds)
|
||||
__ADD(AF_SNA,sna)
|
||||
__ADD(AF_IRDA,irda)
|
||||
__ADD(AF_PPPOX,pppox)
|
||||
__ADD(AF_WANPIPE,wanpipe)
|
||||
__ADD(AF_LLC,llc)
|
||||
__ADD(AF_CAN,can)
|
||||
__ADD(AF_TIPC,tipc)
|
||||
__ADD(AF_BLUETOOTH,bluetooth)
|
||||
__ADD(AF_IUCV,iucv)
|
||||
__ADD(AF_RXRPC,rxrpc)
|
||||
__ADD(AF_ISDN,isdn)
|
||||
__ADD(AF_PHONET,phonet)
|
||||
#ifdef AF_IEEE802154
|
||||
__ADD(AF_IEEE802154,ieee802154)
|
||||
#endif
|
||||
#ifdef AF_CAIF
|
||||
__ADD(AF_CAIF,caif)
|
||||
#endif
|
||||
#ifdef AF_ALG
|
||||
__ADD(AF_ALG,alg)
|
||||
#endif
|
||||
#ifdef AF_NFC
|
||||
__ADD(AF_NFC,nfc)
|
||||
#endif
|
||||
};
|
||||
|
||||
char *nl_af2str(int family, char *buf, size_t size)
|
||||
|
|
70
lib/attr.c
70
lib/attr.c
|
@ -6,10 +6,10 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/addr.h>
|
||||
|
@ -182,6 +182,7 @@ static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
|
|||
[NLA_U32] = sizeof(uint32_t),
|
||||
[NLA_U64] = sizeof(uint64_t),
|
||||
[NLA_STRING] = 1,
|
||||
[NLA_FLAG] = 0,
|
||||
};
|
||||
|
||||
static int validate_nla(struct nlattr *nla, int maxtype,
|
||||
|
@ -204,9 +205,6 @@ static int validate_nla(struct nlattr *nla, int maxtype,
|
|||
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;
|
||||
|
||||
|
@ -252,20 +250,24 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
|
|||
nla_for_each_attr(nla, head, len, rem) {
|
||||
int type = nla_type(nla);
|
||||
|
||||
if (type == 0) {
|
||||
NL_DBG(1, "Illegal nla->nla_type == 0\n");
|
||||
/* Padding attributes */
|
||||
if (type == 0)
|
||||
continue;
|
||||
|
||||
if (type > maxtype)
|
||||
continue;
|
||||
|
||||
if (policy) {
|
||||
err = validate_nla(nla, maxtype, policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (type <= maxtype) {
|
||||
if (policy) {
|
||||
err = validate_nla(nla, maxtype, policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
if (tb[type])
|
||||
NL_DBG(1, "Attribute of type %#x found multiple times in message, "
|
||||
"previous attribute is being ignored.\n", type);
|
||||
|
||||
tb[type] = nla;
|
||||
}
|
||||
tb[type] = nla;
|
||||
}
|
||||
|
||||
if (rem > 0)
|
||||
|
@ -462,7 +464,7 @@ struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
|
|||
|
||||
tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
|
||||
|
||||
if ((tlen + msg->nm_nlh->nlmsg_len) > msg->nm_size)
|
||||
if (tlen > msg->nm_size)
|
||||
return NULL;
|
||||
|
||||
nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
|
||||
|
@ -820,8 +822,7 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
|
|||
* Kernel can't handle empty nested attributes, trim the
|
||||
* attribute header again
|
||||
*/
|
||||
msg->nm_nlh->nlmsg_len -= NLA_HDRLEN;
|
||||
memset(nlmsg_tail(msg->nm_nlh), 0, NLA_HDRLEN);
|
||||
nla_nest_cancel(msg, start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -849,6 +850,28 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the addition of a nested attribute
|
||||
* @arg msg Netlink message
|
||||
* @arg attr Nested netlink attribute
|
||||
*
|
||||
* Removes any partially added nested Netlink attribute from the message
|
||||
* by resetting the message to the size before the call to nla_nest_start()
|
||||
* and by overwriting any potentially touched message segments with 0.
|
||||
*/
|
||||
void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) attr;
|
||||
if (len < 0)
|
||||
BUG();
|
||||
else if (len > 0) {
|
||||
msg->nm_nlh->nlmsg_len -= len;
|
||||
memset(nlmsg_tail(msg->nm_nlh), 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create attribute index based on nested attribute
|
||||
* @arg tb Index array to be filled (maxtype+1 elements).
|
||||
|
@ -868,6 +891,17 @@ int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
|
|||
return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if attribute has NLA_F_NESTED flag set
|
||||
* @arg attr Netlink attribute
|
||||
*
|
||||
* @return True if attribute has NLA_F_NESTED flag set, oterhwise False.
|
||||
*/
|
||||
int nla_is_nested(struct nlattr *attr)
|
||||
{
|
||||
return !!(attr->nla_type & NLA_F_NESTED);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
|
103
lib/cache.c
103
lib/cache.c
|
@ -49,7 +49,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/object.h>
|
||||
|
@ -307,6 +307,9 @@ struct nl_cache *nl_cache_subset(struct nl_cache *orig,
|
|||
if (!cache)
|
||||
return NULL;
|
||||
|
||||
NL_DBG(2, "Filling subset of cache %p <%s> with filter %p into %p\n",
|
||||
orig, nl_cache_name(orig), filter, cache);
|
||||
|
||||
nl_list_for_each_entry(obj, &orig->c_items, ce_list) {
|
||||
if (!nl_object_match_filter(obj, filter))
|
||||
continue;
|
||||
|
@ -341,6 +344,8 @@ struct nl_cache *nl_cache_clone(struct nl_cache *cache)
|
|||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
NL_DBG(2, "Cloning %p into %p\n", cache, clone);
|
||||
|
||||
nl_list_for_each_entry(obj, &cache->c_items, ce_list)
|
||||
nl_cache_add(clone, obj);
|
||||
|
||||
|
@ -362,7 +367,7 @@ 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_DBG(2, "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);
|
||||
|
@ -375,7 +380,7 @@ static void __nl_cache_free(struct nl_cache *cache)
|
|||
if (cache->hashtable)
|
||||
nl_hash_table_free(cache->hashtable);
|
||||
|
||||
NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
|
||||
NL_DBG(2, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
|
||||
free(cache);
|
||||
}
|
||||
|
||||
|
@ -386,6 +391,9 @@ static void __nl_cache_free(struct nl_cache *cache)
|
|||
void nl_cache_get(struct nl_cache *cache)
|
||||
{
|
||||
cache->c_refcnt++;
|
||||
|
||||
NL_DBG(3, "Incremented cache %p <%s> reference count to %d\n",
|
||||
cache, nl_cache_name(cache), cache->c_refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -403,8 +411,9 @@ void nl_cache_free(struct nl_cache *cache)
|
|||
return;
|
||||
|
||||
cache->c_refcnt--;
|
||||
NL_DBG(4, "Returned cache reference %p, %d remaining\n",
|
||||
cache, cache->c_refcnt);
|
||||
|
||||
NL_DBG(3, "Decremented cache %p <%s> reference count, %d remaining\n",
|
||||
cache, nl_cache_name(cache), cache->c_refcnt);
|
||||
|
||||
if (cache->c_refcnt <= 0)
|
||||
__nl_cache_free(cache);
|
||||
|
@ -439,8 +448,8 @@ static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
|
|||
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));
|
||||
NL_DBG(3, "Added object %p to cache %p <%s>, nitems %d\n",
|
||||
obj, cache, nl_cache_name(cache), cache->c_nitems);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -476,6 +485,8 @@ int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
|
|||
return -NLE_OBJ_MISMATCH;
|
||||
|
||||
if (!nl_list_empty(&obj->ce_list)) {
|
||||
NL_DBG(3, "Object %p already in cache, cloning new object\n", obj);
|
||||
|
||||
new = nl_object_clone(obj);
|
||||
if (!new)
|
||||
return -NLE_NOMEM;
|
||||
|
@ -514,7 +525,8 @@ 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);
|
||||
NL_DBG(3, "Moving object %p from cache %p to cache %p\n",
|
||||
obj, obj->ce_cache, cache);
|
||||
|
||||
/* Acquire reference, if already in a cache this will be
|
||||
* reverted during removal */
|
||||
|
@ -547,7 +559,7 @@ void nl_cache_remove(struct nl_object *obj)
|
|||
if (cache->hashtable) {
|
||||
ret = nl_hash_table_del(cache->hashtable, obj);
|
||||
if (ret < 0)
|
||||
NL_DBG(3, "Failed to delete %p from cache %p <%s>.\n",
|
||||
NL_DBG(2, "Failed to delete %p from cache %p <%s>.\n",
|
||||
obj, cache, nl_cache_name(cache));
|
||||
}
|
||||
|
||||
|
@ -556,7 +568,7 @@ void nl_cache_remove(struct nl_object *obj)
|
|||
nl_object_put(obj);
|
||||
cache->c_nitems--;
|
||||
|
||||
NL_DBG(1, "Deleted %p from cache %p <%s>.\n",
|
||||
NL_DBG(2, "Deleted object %p from cache %p <%s>.\n",
|
||||
obj, cache, nl_cache_name(cache));
|
||||
}
|
||||
|
||||
|
@ -630,12 +642,12 @@ void nl_cache_set_flags(struct nl_cache *cache, unsigned int flags)
|
|||
static 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;
|
||||
|
||||
NL_DBG(2, "Requesting update from kernel for cache %p <%s>\n",
|
||||
cache, nl_cache_name(cache));
|
||||
|
||||
return cache->c_ops->co_request_update(cache, sk);
|
||||
}
|
||||
|
||||
|
@ -674,8 +686,8 @@ static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache,
|
|||
.params = param,
|
||||
};
|
||||
|
||||
NL_DBG(1, "Picking up answer for cache %p <%s>...\n",
|
||||
cache, nl_cache_name(cache));
|
||||
NL_DBG(2, "Picking up answer for cache %p <%s>\n",
|
||||
cache, nl_cache_name(cache));
|
||||
|
||||
cb = nl_cb_clone(sk->s_cb);
|
||||
if (cb == NULL)
|
||||
|
@ -685,9 +697,8 @@ static int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache,
|
|||
|
||||
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_DBG(2, "While picking up for %p <%s>, recvmsgs() returned %d: %s\n",
|
||||
cache, nl_cache_name(cache), err, nl_geterror(err));
|
||||
|
||||
nl_cb_put(cb);
|
||||
|
||||
|
@ -800,6 +811,9 @@ int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
|
|||
return cache_include(cache, obj, &ops->co_msgtypes[i],
|
||||
change_cb, data);
|
||||
|
||||
NL_DBG(3, "Object %p does not seem to belong to cache %p <%s>\n",
|
||||
obj, cache, nl_cache_name(cache));
|
||||
|
||||
return -NLE_MSGTYPE_NOSUPPORT;
|
||||
}
|
||||
|
||||
|
@ -951,9 +965,12 @@ restart:
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
NL_DBG(2, "Updating cache %p <%s> for family %u, request sent, waiting for reply\n",
|
||||
cache, nl_cache_name(cache), grp ? grp->ag_family : AF_UNSPEC);
|
||||
|
||||
err = nl_cache_pickup(sk, cache);
|
||||
if (err == -NLE_DUMP_INTR) {
|
||||
NL_DBG(1, "dump interrupted, restarting!\n");
|
||||
NL_DBG(2, "Dump interrupted, restarting!\n");
|
||||
goto restart;
|
||||
} else if (err < 0)
|
||||
break;
|
||||
|
@ -963,9 +980,6 @@ restart:
|
|||
} while (grp && grp->ag_group &&
|
||||
(cache->c_flags & NL_CACHE_AF_ITER));
|
||||
|
||||
NL_DBG(2, "Upading cache %p <%s>, request sent, waiting for dump...\n",
|
||||
cache, nl_cache_name(cache));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1022,6 +1036,45 @@ struct nl_object *nl_cache_search(struct nl_cache *cache,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find object in cache
|
||||
* @arg cache Cache
|
||||
* @arg filter object acting as a filter
|
||||
*
|
||||
* Searches the cache for an object which matches the object filter.
|
||||
* If the filter attributes matches the object type id attributes,
|
||||
* and the cache supports hash lookups, a faster hashtable lookup
|
||||
* is used to return the object. Else, function nl_object_match_filter() is
|
||||
* used to determine if the objects match. If a matching object is
|
||||
* found, the reference counter is incremented and the object is returned.
|
||||
*
|
||||
* Therefore, if an object is returned, the reference to the object
|
||||
* must be returned by calling nl_object_put() after usage.
|
||||
*
|
||||
* @return Reference to object or NULL if not found.
|
||||
*/
|
||||
struct nl_object *nl_cache_find(struct nl_cache *cache,
|
||||
struct nl_object *filter)
|
||||
{
|
||||
struct nl_object *obj;
|
||||
|
||||
if (cache->c_ops == NULL)
|
||||
BUG();
|
||||
|
||||
if ((nl_object_get_id_attrs(filter) == filter->ce_mask)
|
||||
&& cache->hashtable)
|
||||
return __cache_fast_lookup(cache, filter);
|
||||
|
||||
nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
|
||||
if (nl_object_match_filter(obj, filter)) {
|
||||
nl_object_get(obj);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all objects of a cache
|
||||
* @arg cache Cache
|
||||
|
@ -1033,8 +1086,8 @@ 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_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);
|
||||
|
@ -1076,7 +1129,7 @@ void nl_cache_dump_filter(struct nl_cache *cache,
|
|||
struct nl_object_ops *ops;
|
||||
struct nl_object *obj;
|
||||
|
||||
NL_DBG(2, "Dumping cache %p <%s> filter %p\n",
|
||||
NL_DBG(2, "Dumping cache %p <%s> with filter %p\n",
|
||||
cache, nl_cache_name(cache), filter);
|
||||
|
||||
if (type > NL_DUMP_MAX || type < 0)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
|
@ -435,7 +435,7 @@ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr)
|
|||
}
|
||||
|
||||
nl_cb_put(cb);
|
||||
if (err < 0)
|
||||
if (err < 0 && err != -NLE_AGAIN)
|
||||
return err;
|
||||
|
||||
return nread;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <linux/socket.h>
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
#define ARI_ATTR_CLASS 0x01
|
||||
#define ARI_ATTR_FPN 0x02
|
||||
#define ARI_ATTR_FPS 0x03
|
||||
#define ARI_ATTR_EMC 0x04
|
||||
#define ARI_ATTR_EIC 0x05
|
||||
#define ARI_ATTR_POC 0x06
|
||||
#define ARI_ATTR_GOP 0x07
|
||||
#define ARI_ATTR_FIL 0x08
|
||||
|
||||
static struct nla_policy nl_dect_ari_policy[DECTA_ARI_MAX + 1] = {
|
||||
[DECTA_ARI_CLASS] = { .type = NLA_U8 },
|
||||
[DECTA_ARI_FPN] = { .type = NLA_U32 },
|
||||
[DECTA_ARI_FPS] = { .type = NLA_U32 },
|
||||
[DECTA_ARI_EMC] = { .type = NLA_U16 },
|
||||
[DECTA_ARI_EIC] = { .type = NLA_U16 },
|
||||
[DECTA_ARI_POC] = { .type = NLA_U16 },
|
||||
[DECTA_ARI_GOP] = { .type = NLA_U32 },
|
||||
[DECTA_ARI_FIL] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
int nl_dect_parse_ari(struct nl_dect_ari *ari, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *tb[DECTA_ARI_MAX + 1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_ARI_MAX, nla, nl_dect_ari_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_ARI_CLASS] == NULL)
|
||||
return -NLE_INVAL;
|
||||
|
||||
memset(ari, 0, sizeof(ari));
|
||||
ari->ari_class = nla_get_u8(tb[DECTA_ARI_CLASS]);
|
||||
if (tb[DECTA_ARI_FPN] != NULL)
|
||||
ari->ari_fpn = nla_get_u32(tb[DECTA_ARI_FPN]);
|
||||
|
||||
switch (ari->ari_class) {
|
||||
case DECT_ARC_A:
|
||||
if (tb[DECTA_ARI_EMC] != NULL)
|
||||
ari->ari_u.emc = nla_get_u16(tb[DECTA_ARI_EMC]);
|
||||
break;
|
||||
case DECT_ARC_B:
|
||||
if (tb[DECTA_ARI_EIC] != NULL)
|
||||
ari->ari_u.eic = nla_get_u16(tb[DECTA_ARI_EIC]);
|
||||
if (tb[DECTA_ARI_FPS] != NULL)
|
||||
ari->ari_fps = nla_get_u32(tb[DECTA_ARI_FPS]);
|
||||
break;
|
||||
case DECT_ARC_C:
|
||||
if (tb[DECTA_ARI_POC] != NULL)
|
||||
ari->ari_u.poc = nla_get_u16(tb[DECTA_ARI_POC]);
|
||||
if (tb[DECTA_ARI_FPS] != NULL)
|
||||
ari->ari_fps = nla_get_u32(tb[DECTA_ARI_FPS]);
|
||||
break;
|
||||
case DECT_ARC_D:
|
||||
if (tb[DECTA_ARI_GOP] != NULL)
|
||||
ari->ari_u.gop = nla_get_u32(tb[DECTA_ARI_GOP]);
|
||||
break;
|
||||
case DECT_ARC_E:
|
||||
if (tb[DECTA_ARI_FIL] != NULL)
|
||||
ari->ari_u.fil = nla_get_u16(tb[DECTA_ARI_FIL]);
|
||||
break;
|
||||
default:
|
||||
return -NLE_INVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_fill_ari(struct nl_msg *msg, const struct nl_dect_ari *ari, int attr)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
|
||||
nla = nla_nest_start(msg, attr);
|
||||
if (nla == NULL)
|
||||
goto nla_put_failure;
|
||||
|
||||
NLA_PUT_U8(msg, DECTA_ARI_CLASS, ari->ari_class);
|
||||
NLA_PUT_U32(msg, DECTA_ARI_FPN, ari->ari_fpn);
|
||||
|
||||
switch (ari->ari_class) {
|
||||
case DECT_ARC_A:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_EMC, ari->ari_u.emc);
|
||||
break;
|
||||
case DECT_ARC_B:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_EIC, ari->ari_u.eic);
|
||||
NLA_PUT_U32(msg, DECTA_ARI_FPS, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_C:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_POC, ari->ari_u.poc);
|
||||
NLA_PUT_U32(msg, DECTA_ARI_FPS, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_D:
|
||||
NLA_PUT_U32(msg, DECTA_ARI_GOP, ari->ari_u.gop);
|
||||
break;
|
||||
case DECT_ARC_E:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_FIL, ari->ari_u.fil);
|
||||
break;
|
||||
}
|
||||
nla_nest_end(msg, nla);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
void nl_dect_dump_ari(const struct nl_dect_ari *ari, struct nl_dump_params *p)
|
||||
{
|
||||
nl_dump(p, "class %c ", 'A' + ari->ari_class);
|
||||
|
||||
switch (ari->ari_class) {
|
||||
case DECT_ARC_A:
|
||||
nl_dump(p, "(residential) EMC: %.4x FPN: %.5x",
|
||||
ari->ari_u.emc, ari->ari_fpn);
|
||||
break;
|
||||
case DECT_ARC_B:
|
||||
nl_dump(p, "(private multiple cell) EIC: %.4x FPN: %.2x FPS: %x",
|
||||
ari->ari_u.eic, ari->ari_fpn, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_C:
|
||||
nl_dump(p, "(public) POC: %.4x FPN: %.2x FPS: %x",
|
||||
ari->ari_u.poc, ari->ari_fpn, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_D:
|
||||
nl_dump(p, "(public GSM) GOP: %.5x FPN: %.2x",
|
||||
ari->ari_u.gop, ari->ari_fpn);
|
||||
break;
|
||||
case DECT_ARC_E:
|
||||
nl_dump(p, "(PP to PP) FIL: %.4x FPN: %.3x",
|
||||
ari->ari_u.fil, ari->ari_fpn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static struct trans_tbl ari_classes[] = {
|
||||
__ADD(DECT_ARC_A, a)
|
||||
__ADD(DECT_ARC_B, b)
|
||||
__ADD(DECT_ARC_C, c)
|
||||
__ADD(DECT_ARC_D, d)
|
||||
__ADD(DECT_ARC_E, e)
|
||||
};
|
||||
|
||||
const char *nl_dect_ari_class2str(enum dect_ari_classes class, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(class, buf, len, ari_classes, ARRAY_SIZE(ari_classes));
|
||||
}
|
||||
|
||||
enum dect_ari_classes nl_dect_ari_str2class(const char *str)
|
||||
{
|
||||
return __str2type(str, ari_classes, ARRAY_SIZE(ari_classes));
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_class(struct nl_dect_ari *ari, enum dect_ari_classes class)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_CLASS;
|
||||
ari->ari_class = class;
|
||||
}
|
||||
|
||||
enum dect_ari_classes nl_dect_ari_get_class(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_class;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_fpn(struct nl_dect_ari *ari, uint32_t fpn)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_FPN;
|
||||
ari->ari_fpn = fpn;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_ari_get_fpn(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_fpn;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_fps(struct nl_dect_ari *ari, uint32_t fps)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_FPS;
|
||||
ari->ari_fps = fps;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_ari_get_fps(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_fps;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_emc(struct nl_dect_ari *ari, uint16_t emc)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_EMC;
|
||||
ari->ari_u.emc = emc;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_emc(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.emc;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_eic(struct nl_dect_ari *ari, uint16_t eic)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_EIC;
|
||||
ari->ari_u.eic = eic;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_eic(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.eic;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_poc(struct nl_dect_ari *ari, uint16_t poc)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_POC;
|
||||
ari->ari_u.poc = poc;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_poc(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.poc;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_gop(struct nl_dect_ari *ari, uint32_t gop)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_GOP;
|
||||
ari->ari_u.gop = gop;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_ari_get_gop(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.gop;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_fil(struct nl_dect_ari *ari, uint16_t fil)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_FIL;
|
||||
ari->ari_u.fil = fil;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_fil(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.fil;
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* lib/nl_dect/cell.c DECT Cell objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nl_dect
|
||||
* @defgroup nl_dect Transceivers
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_cache_ops nl_dect_cell_ops;
|
||||
/** @endcond */
|
||||
|
||||
static struct nla_policy cell_policy[DECTA_CELL_MAX + 1] = {
|
||||
[DECTA_CELL_NAME] = { .type = NLA_STRING, .maxlen = 16 },
|
||||
[DECTA_CELL_FLAGS] = { .type = NLA_U32 },
|
||||
[DECTA_CELL_TRANSCEIVERS] = { .type = NLA_NESTED },
|
||||
[DECTA_CELL_CLUSTER] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int cell_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, struct nl_parser_param *pp)
|
||||
{
|
||||
struct dectmsg *dm = nlmsg_data(n);
|
||||
struct nl_dect_cell *cell;
|
||||
struct nlattr *tb[DECTA_CELL_MAX + 1], *nla;
|
||||
int rem, err;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_CELL_MAX, cell_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cell = nl_dect_cell_alloc();
|
||||
if (cell == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
cell->ce_msgtype = n->nlmsg_type;
|
||||
cell->c_index = dm->dm_index;
|
||||
|
||||
if (tb[DECTA_CELL_NAME] != NULL)
|
||||
nl_dect_cell_set_name(cell, nla_data(tb[DECTA_CELL_NAME]));
|
||||
if (tb[DECTA_CELL_FLAGS] != NULL)
|
||||
nl_dect_cell_set_flags(cell, nla_get_u32(tb[DECTA_CELL_FLAGS]));
|
||||
if (tb[DECTA_CELL_TRANSCEIVERS] != NULL) {
|
||||
unsigned int i = 0;
|
||||
nla_for_each_nested(nla, tb[DECTA_CELL_TRANSCEIVERS], rem) {
|
||||
char *id = nla_strdup(nla);
|
||||
if (id == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
nl_dect_cell_set_transceiver(cell, i++, id);
|
||||
}
|
||||
}
|
||||
if (tb[DECTA_CELL_CLUSTER] != NULL)
|
||||
nl_dect_cell_set_link(cell, nla_get_u8(tb[DECTA_CELL_CLUSTER]));
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)cell, pp);
|
||||
errout:
|
||||
nl_dect_cell_put(cell);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cell_request_update(struct nl_cache *c, struct nl_sock *h)
|
||||
{
|
||||
struct dectmsg dm;
|
||||
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
return nl_send_simple(h, DECT_GET_CELL, NLM_F_DUMP, &dm, sizeof(dm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Cache Management
|
||||
* @{
|
||||
*/
|
||||
int nl_dect_cell_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
struct nl_cache *cache;
|
||||
int err;
|
||||
|
||||
cache = nl_cache_alloc(&nl_dect_cell_ops);
|
||||
if (cache == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
|
||||
free(cache);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nl_dect_cell *nl_dect_cell_get_by_name(struct nl_cache *cache, const char *name)
|
||||
{
|
||||
struct nl_dect_cell *cell;
|
||||
|
||||
nl_list_for_each_entry(cell, &cache->c_items, ce_list) {
|
||||
if (!strcmp(cell->c_name, name)) {
|
||||
nl_object_get((struct nl_object *)cell);
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nl_dect_cell *nl_dect_cell_get_by_index(struct nl_cache *cache, int index)
|
||||
{
|
||||
struct nl_dect_cell *cell;
|
||||
|
||||
nl_list_for_each_entry(cell, &cache->c_items, ce_list) {
|
||||
if (cell->c_index == index) {
|
||||
nl_object_get((struct nl_object *)cell);
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Device creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int build_cell_msg(struct nl_dect_cell *tmpl, int cmd, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_dect_cell_build_msg(msg, tmpl);
|
||||
if (err < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_cell_build_add_request(struct nl_dect_cell *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cell_msg(tmpl, DECT_NEW_CELL, NLM_F_CREATE | flags,
|
||||
result);
|
||||
}
|
||||
|
||||
int nl_dect_cell_add(struct nl_sock *sk, struct nl_dect_cell *cell, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cell_build_add_request(cell, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_cell_build_del_request(struct nl_dect_cell *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cell_msg(tmpl, DECT_DEL_CELL, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_cell_delete(struct nl_sock *sk, struct nl_dect_cell *tmpl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cell_build_del_request(tmpl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Name <-> Index Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
char *nl_dect_cell_i2name(struct nl_cache *cache, int index, char *buf, size_t len)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_dect_cell_get_by_index(cache, index);
|
||||
|
||||
if (cell != NULL) {
|
||||
strncpy(buf, cell->c_name, len - 1);
|
||||
buf[len - 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nl_dect_cell_name2i(struct nl_cache *cache, const char *name)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_dect_cell_get_by_name(cache, name);
|
||||
|
||||
if (cell != NULL)
|
||||
return cell->c_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct nl_cache_ops nl_dect_cell_ops = {
|
||||
.co_name = "nl_dect/cell",
|
||||
.co_hdrsize = 0,
|
||||
.co_msgtypes = {
|
||||
{ DECT_NEW_CELL, NL_ACT_NEW, "new" },
|
||||
{ DECT_DEL_CELL, NL_ACT_NEW, "del" },
|
||||
{ DECT_GET_CELL, NL_ACT_GET, "get" },
|
||||
END_OF_MSGTYPES_LIST
|
||||
},
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_request_update = cell_request_update,
|
||||
.co_msg_parser = cell_msg_parser,
|
||||
.co_obj_ops = &nl_dect_cell_obj_ops,
|
||||
};
|
||||
|
||||
static void __init cell_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_cell_ops);
|
||||
}
|
||||
|
||||
static void __exit cell_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_cell_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* lib/dect/cell.c DECT Cell objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define CELL_ATTR_INDEX 0x0001
|
||||
#define CELL_ATTR_NAME 0x0002
|
||||
#define CELL_ATTR_FLAGS 0x0004
|
||||
#define CELL_ATTR_TRANSCEIVER 0x0008
|
||||
#define CELL_ATTR_LINK 0x0010
|
||||
/** @endcond */
|
||||
|
||||
static void cell_free_data(struct nl_object *obj)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_object_priv(obj);
|
||||
unsigned int i;
|
||||
|
||||
if (cell == NULL)
|
||||
return;
|
||||
for (i = 0; i < 16; i++)
|
||||
free(cell->c_transceiver[i]);
|
||||
}
|
||||
|
||||
static void cell_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_object_priv(obj);
|
||||
struct nl_cache *cluster_cache;
|
||||
unsigned int i;
|
||||
char buf[64];
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_NAME)
|
||||
nl_dump(p, "%u: DECT Cell %s", cell->c_index, cell->c_name);
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_LINK) {
|
||||
cluster_cache = nl_cache_mngt_require("nl_dect/cluster");
|
||||
if (cluster_cache != NULL) {
|
||||
nl_dect_cluster_i2name(cluster_cache, cell->c_link, buf,
|
||||
sizeof(buf));
|
||||
nl_dump(p, "@%s", buf);
|
||||
} else
|
||||
nl_dump(p, "@%u", cell->c_link);
|
||||
}
|
||||
nl_dump(p, ":");
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_FLAGS) {
|
||||
nl_dect_cell_flags2str(cell->c_flags, buf, sizeof(buf));
|
||||
nl_dump(p, " <%s>", buf);
|
||||
}
|
||||
nl_dump(p, "\n");
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_TRANSCEIVER) {
|
||||
for (i = 0; i < 16 && cell->c_transceiver[i] != NULL; i++)
|
||||
nl_dump(p, "\tTransceiver: %s\n",
|
||||
cell->c_transceiver[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_cell *nl_dect_cell_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_cell *)nl_object_alloc(&nl_dect_cell_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_cell_get(struct nl_dect_cell *cell)
|
||||
{
|
||||
nl_object_get((struct nl_object *)cell);
|
||||
}
|
||||
|
||||
void nl_dect_cell_put(struct nl_dect_cell *cell)
|
||||
{
|
||||
nl_object_put((struct nl_object *)cell);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
void nl_dect_cell_set_index(struct nl_dect_cell *cell, int index)
|
||||
{
|
||||
cell->c_index = index;
|
||||
cell->ce_mask |= CELL_ATTR_INDEX;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_index(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_INDEX);
|
||||
}
|
||||
|
||||
int nl_dect_cell_get_index(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_index;
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_name(struct nl_dect_cell *cell, const char *name)
|
||||
{
|
||||
cell->c_name = strdup(name);
|
||||
cell->ce_mask |= CELL_ATTR_NAME;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_name(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_NAME);
|
||||
}
|
||||
|
||||
const char *nl_dect_cell_get_name(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_name;
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_flags(struct nl_dect_cell *cell, uint32_t flags)
|
||||
{
|
||||
cell->c_flags = flags;
|
||||
cell->ce_mask |= CELL_ATTR_FLAGS;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_flags(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_FLAGS);
|
||||
}
|
||||
|
||||
uint32_t nl_dect_cell_get_flags(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_flags;
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_transceiver(struct nl_dect_cell *cell, unsigned int i,
|
||||
const char *id)
|
||||
{
|
||||
cell->c_transceiver[i] = strdup(id);
|
||||
cell->ce_mask |= CELL_ATTR_TRANSCEIVER;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_transceiver(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_TRANSCEIVER);
|
||||
}
|
||||
|
||||
const char *nl_dect_cell_get_transceiver(const struct nl_dect_cell *cell,
|
||||
unsigned int i)
|
||||
{
|
||||
return cell->c_transceiver[i];
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_link(struct nl_dect_cell *cell, int link)
|
||||
{
|
||||
cell->c_link = link;
|
||||
cell->ce_mask |= CELL_ATTR_LINK;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_link(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_LINK);
|
||||
}
|
||||
|
||||
int nl_dect_cell_get_link(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_link;
|
||||
}
|
||||
|
||||
int nl_dect_cell_build_msg(struct nl_msg *msg, struct nl_dect_cell *cell)
|
||||
{
|
||||
struct dectmsg dm = {
|
||||
.dm_index = cell->c_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
if (cell->ce_mask & CELL_ATTR_NAME)
|
||||
NLA_PUT_STRING(msg, DECTA_CELL_NAME, cell->c_name);
|
||||
if (cell->ce_mask & CELL_ATTR_FLAGS)
|
||||
NLA_PUT_U32(msg, DECTA_CELL_FLAGS, cell->c_flags);
|
||||
if (cell->ce_mask & CELL_ATTR_LINK)
|
||||
NLA_PUT_U8(msg, DECTA_CELL_CLUSTER, cell->c_link);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static struct trans_tbl cell_flags[] = {
|
||||
__ADD(DECT_CELL_CCP, ccp)
|
||||
__ADD(DECT_CELL_SLAVE, slave)
|
||||
__ADD(DECT_CELL_MONITOR, monitor)
|
||||
};
|
||||
|
||||
char *nl_dect_cell_flags2str(uint32_t flags, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(flags, buf, len, cell_flags, ARRAY_SIZE(cell_flags));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_cell_str2flags(const char *str)
|
||||
{
|
||||
return __str2flags(str, cell_flags, ARRAY_SIZE(cell_flags));
|
||||
}
|
||||
|
||||
/** @cond SKIP */
|
||||
struct nl_object_ops nl_dect_cell_obj_ops = {
|
||||
.oo_name = "nl_dect/cell",
|
||||
.oo_size = sizeof(struct nl_dect_cell),
|
||||
.oo_free_data = cell_free_data,
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = cell_dump,
|
||||
},
|
||||
.oo_id_attrs = CELL_ATTR_NAME,
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* lib/dect/cluster.c DECT Cluster objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nl_dect
|
||||
* @defgroup nl_dect Transceivers
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_cache_ops nl_dect_cluster_ops;
|
||||
/** @endcond */
|
||||
|
||||
static struct nla_policy mbc_tb_policy[DECTA_MBC_TB_MAX + 1] = {
|
||||
[DECTA_MBC_TB_LBN] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_TB_ECN] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_TB_CELL] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_TB_RX_SLOT] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_TB_TX_SLOT] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int tb_msg_parser(struct nlattr *nla, struct nl_dect_mbc *mbc)
|
||||
{
|
||||
struct nlattr *tb[DECTA_MBC_TB_MAX + 1];
|
||||
struct nl_dect_mbc_tb *mtb;
|
||||
int err;
|
||||
|
||||
if (nla_type(nla) != DECTA_LIST_ELEM)
|
||||
return -NLE_INVAL;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_MBC_TB_MAX, nla, mbc_tb_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
mtb = &mbc->mbc_tbs[mbc->mbc_ntbs++];
|
||||
if (tb[DECTA_MBC_TB_LBN] != NULL)
|
||||
mtb->mtb_lbn = nla_get_u8(tb[DECTA_MBC_TB_LBN]);
|
||||
if (tb[DECTA_MBC_TB_ECN] != NULL)
|
||||
mtb->mtb_ecn = nla_get_u8(tb[DECTA_MBC_TB_ECN]);
|
||||
if (tb[DECTA_MBC_TB_CELL] != NULL)
|
||||
mtb->mtb_cell = nla_get_u8(tb[DECTA_MBC_TB_CELL]);
|
||||
if (tb[DECTA_MBC_TB_RX_SLOT] != NULL)
|
||||
mtb->mtb_rx_slot = nla_get_u8(tb[DECTA_MBC_TB_RX_SLOT]);
|
||||
if (tb[DECTA_MBC_TB_TX_SLOT] != NULL)
|
||||
mtb->mtb_tx_slot = nla_get_u8(tb[DECTA_MBC_TB_TX_SLOT]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nla_policy mbc_stats_policy[DECTA_MBC_STATS_MAX + 1] = {
|
||||
[DECTA_MBC_STATS_CS_RX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_MBC_STATS_CS_TX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_MBC_STATS_I_RX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_MBC_STATS_I_TX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_MBC_STATS_HANDOVERS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int mbc_stats_msg_parser(struct nlattr *nla, struct nl_dect_mbc *mbc)
|
||||
{
|
||||
struct nlattr *tb[DECTA_MBC_STATS_MAX + 1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_MBC_MAX, nla, mbc_stats_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_MBC_STATS_CS_RX_BYTES] != NULL)
|
||||
mbc->mbc_cs_rx_bytes = nla_get_u32(tb[DECTA_MBC_STATS_CS_RX_BYTES]);
|
||||
if (tb[DECTA_MBC_STATS_CS_TX_BYTES] != NULL)
|
||||
mbc->mbc_cs_tx_bytes = nla_get_u32(tb[DECTA_MBC_STATS_CS_TX_BYTES]);
|
||||
if (tb[DECTA_MBC_STATS_I_RX_BYTES] != NULL)
|
||||
mbc->mbc_i_rx_bytes = nla_get_u32(tb[DECTA_MBC_STATS_I_RX_BYTES]);
|
||||
if (tb[DECTA_MBC_STATS_I_TX_BYTES] != NULL)
|
||||
mbc->mbc_i_tx_bytes = nla_get_u32(tb[DECTA_MBC_STATS_I_TX_BYTES]);
|
||||
if (tb[DECTA_MBC_STATS_HANDOVERS] != NULL)
|
||||
mbc->mbc_handovers = nla_get_u32(tb[DECTA_MBC_STATS_HANDOVERS]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nla_policy mbc_policy[DECTA_MBC_MAX + 1] = {
|
||||
[DECTA_MBC_MCEI] = { .type = NLA_U32 },
|
||||
[DECTA_MBC_SERVICE] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_STATE] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_CIPHER_STATE] = { .type = NLA_U8 },
|
||||
[DECTA_MBC_TBS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int mbc_msg_parser(struct nlattr *nla, struct nl_dect_cluster *cl)
|
||||
{
|
||||
struct nlattr *tb[DECTA_MBC_MAX + 1];
|
||||
struct nl_dect_mbc *mbc;
|
||||
int err, rem;
|
||||
|
||||
if (nla_type(nla) != DECTA_LIST_ELEM)
|
||||
return -NLE_INVAL;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_MBC_MAX, nla, mbc_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
mbc = &cl->cl_mbcs[cl->cl_nmbcs++];
|
||||
if (tb[DECTA_MBC_MCEI] != NULL)
|
||||
mbc->mbc_mcei = nla_get_u32(tb[DECTA_MBC_MCEI]);
|
||||
if (tb[DECTA_MBC_SERVICE] != NULL)
|
||||
mbc->mbc_service = nla_get_u8(tb[DECTA_MBC_SERVICE]);
|
||||
if (tb[DECTA_MBC_STATE] != NULL)
|
||||
mbc->mbc_state = nla_get_u8(tb[DECTA_MBC_STATE]);
|
||||
if (tb[DECTA_MBC_CIPHER_STATE] != NULL)
|
||||
mbc->mbc_cipher_state = nla_get_u8(tb[DECTA_MBC_CIPHER_STATE]);
|
||||
if (tb[DECTA_MBC_STATS] != NULL) {
|
||||
err = mbc_stats_msg_parser(tb[DECTA_MBC_STATS], mbc);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (tb[DECTA_MBC_TBS] != NULL) {
|
||||
nla_for_each_nested(nla, tb[DECTA_MBC_TBS], rem) {
|
||||
err = tb_msg_parser(nla, mbc);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nla_policy cluster_policy[DECTA_CLUSTER_MAX + 1] = {
|
||||
[DECTA_CLUSTER_NAME] = { .type = NLA_STRING, .maxlen = 16 },
|
||||
[DECTA_CLUSTER_MODE] = { .type = NLA_U8 },
|
||||
[DECTA_CLUSTER_PARI] = { .type = NLA_NESTED },
|
||||
[DECTA_CLUSTER_CELLS] = { .type = NLA_NESTED },
|
||||
[DECTA_CLUSTER_MBCS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int cluster_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, struct nl_parser_param *pp)
|
||||
{
|
||||
struct dectmsg *dm = nlmsg_data(n);
|
||||
struct nl_dect_cluster *cl;
|
||||
struct nlattr *tb[DECTA_CLUSTER_MAX + 1], *nla;
|
||||
int err, rem;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_CLUSTER_MAX, cluster_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cl = nl_dect_cluster_alloc();
|
||||
if (cl == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
cl->ce_msgtype = n->nlmsg_type;
|
||||
cl->cl_index = dm->dm_index;
|
||||
|
||||
if (tb[DECTA_CLUSTER_NAME] != NULL) {
|
||||
char *name = nla_strdup(tb[DECTA_CLUSTER_NAME]);
|
||||
if (name == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
nl_dect_cluster_set_name(cl, name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (tb[DECTA_CLUSTER_MODE] != NULL)
|
||||
nl_dect_cluster_set_mode(cl, nla_get_u8(tb[DECTA_CLUSTER_MODE]));
|
||||
|
||||
if (tb[DECTA_CLUSTER_PARI] != NULL) {
|
||||
struct nl_dect_ari pari;
|
||||
|
||||
err = nl_dect_parse_ari(&pari, tb[DECTA_CLUSTER_PARI]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
nl_dect_cluster_set_pari(cl, &pari);
|
||||
}
|
||||
|
||||
if (tb[DECTA_CLUSTER_MBCS] != NULL) {
|
||||
nla_for_each_nested(nla, tb[DECTA_CLUSTER_MBCS], rem) {
|
||||
err = mbc_msg_parser(nla, cl);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)cl, pp);
|
||||
errout:
|
||||
nl_dect_cluster_put(cl);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cluster_request_update(struct nl_cache *c, struct nl_sock *h)
|
||||
{
|
||||
struct dectmsg dm;
|
||||
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
return nl_send_simple(h, DECT_GET_CLUSTER, NLM_F_DUMP, &dm, sizeof(dm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Cache Management
|
||||
* @{
|
||||
*/
|
||||
int nl_dect_cluster_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
struct nl_cache *cache;
|
||||
int err;
|
||||
|
||||
cache = nl_cache_alloc(&nl_dect_cluster_ops);
|
||||
if (cache == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
|
||||
free(cache);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nl_dect_cluster *nl_dect_cluster_get_by_name(struct nl_cache *cache,
|
||||
const char *name)
|
||||
{
|
||||
struct nl_dect_cluster *cl;
|
||||
|
||||
nl_list_for_each_entry(cl, &cache->c_items, ce_list) {
|
||||
if (!strcmp(cl->cl_name, name)) {
|
||||
nl_object_get((struct nl_object *)cl);
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nl_dect_cluster *nl_dect_cluster_get_by_index(struct nl_cache *cache, int index)
|
||||
{
|
||||
struct nl_dect_cluster *cl;
|
||||
|
||||
nl_list_for_each_entry(cl, &cache->c_items, ce_list) {
|
||||
if (cl->cl_index == index) {
|
||||
nl_object_get((struct nl_object *)cl);
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Device creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int build_cluster_msg(struct nl_dect_cluster *tmpl, int cmd, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_dect_cluster_build_msg(msg, tmpl);
|
||||
if (err < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_add_request(struct nl_dect_cluster *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cluster_msg(tmpl, DECT_NEW_CLUSTER, NLM_F_CREATE | flags,
|
||||
result);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_add(struct nl_sock *sk, struct nl_dect_cluster *cl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cluster_build_add_request(cl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_del_request(struct nl_dect_cluster *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cluster_msg(tmpl, DECT_DEL_CLUSTER, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_delete(struct nl_sock *sk, struct nl_dect_cluster *tmpl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cluster_build_del_request(tmpl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_query_request(struct nl_dect_cluster *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cluster_msg(tmpl, DECT_GET_CLUSTER, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_query(struct nl_sock *sk, struct nl_dect_cluster *cl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cluster_build_query_request(cl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Name <-> Index Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
char *nl_dect_cluster_i2name(struct nl_cache *cache, int index,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_dect_cluster_get_by_index(cache, index);
|
||||
|
||||
if (cl != NULL) {
|
||||
strncpy(buf, cl->cl_name, len - 1);
|
||||
buf[len - 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nl_dect_cluster_name2i(struct nl_cache *cache, const char *name)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_dect_cluster_get_by_name(cache, name);
|
||||
|
||||
if (cl != NULL)
|
||||
return cl->cl_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct nl_cache_ops nl_dect_cluster_ops = {
|
||||
.co_name = "nl_dect/cluster",
|
||||
.co_hdrsize = 0,
|
||||
.co_msgtypes = {
|
||||
{ DECT_NEW_CLUSTER, NL_ACT_NEW, "new" },
|
||||
{ DECT_DEL_CLUSTER, NL_ACT_NEW, "del" },
|
||||
{ DECT_GET_CLUSTER, NL_ACT_GET, "get" },
|
||||
END_OF_MSGTYPES_LIST
|
||||
},
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_request_update = cluster_request_update,
|
||||
.co_msg_parser = cluster_msg_parser,
|
||||
.co_obj_ops = &nl_dect_cluster_obj_ops,
|
||||
};
|
||||
|
||||
static void __init cluster_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_cluster_ops);
|
||||
}
|
||||
|
||||
static void __exit cluster_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_cluster_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* lib/dect/cluster.c DECT Cluster objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
#include <linux/dect.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define CL_ATTR_NAME 0x0001
|
||||
#define CL_ATTR_MODE 0x0002
|
||||
#define CL_ATTR_PARI 0x0004
|
||||
/** @endcond */
|
||||
|
||||
char *nl_dect_mbc_state2string(enum dect_mbc_state state,
|
||||
char *buf, size_t len);
|
||||
char *nl_dect_mbc_service2string(enum dect_mac_service_types type,
|
||||
char *buf, size_t len);
|
||||
char *nl_dect_mbc_cipher2string(enum dect_cipher_states state,
|
||||
char *buf, size_t len);
|
||||
|
||||
static void cluster_free_data(struct nl_object *obj)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_object_priv(obj);
|
||||
|
||||
if (cl == NULL)
|
||||
return;
|
||||
free(cl->cl_name);
|
||||
}
|
||||
|
||||
static void mbc_tb_dump(struct nl_dect_mbc_tb *mtb, struct nl_dump_params *p)
|
||||
{
|
||||
nl_dump(p, "\t TB: LBN: %u ECN: %u Cell: %u RX/TX-Slots: %u/%u\n",
|
||||
mtb->mtb_lbn, mtb->mtb_ecn,
|
||||
mtb->mtb_cell, mtb->mtb_rx_slot, mtb->mtb_tx_slot);
|
||||
}
|
||||
|
||||
static void mbc_dump(struct nl_dect_mbc *mbc, struct nl_dump_params *p)
|
||||
{
|
||||
unsigned int i;
|
||||
char buf[64];
|
||||
|
||||
nl_dump(p, "\tMBC: MCEI %u\n", mbc->mbc_mcei);
|
||||
nl_dump(p, "\t State: %s\n",
|
||||
nl_dect_mbc_state2string(mbc->mbc_state,
|
||||
buf, sizeof(buf)));
|
||||
nl_dump(p, "\t Service: %s\n",
|
||||
nl_dect_mbc_service2string(mbc->mbc_service,
|
||||
buf, sizeof(buf)));
|
||||
nl_dump(p, "\t Cipher state: %s\n",
|
||||
nl_dect_mbc_cipher2string(mbc->mbc_cipher_state,
|
||||
buf, sizeof(buf)));
|
||||
nl_dump(p, "\t Cs-channel RX-Bytes: %u TX-Bytes: %u\n",
|
||||
mbc->mbc_cs_rx_bytes, mbc->mbc_cs_tx_bytes);
|
||||
nl_dump(p, "\t I-channel RX-Bytes: %u TX-Bytes: %u\n",
|
||||
mbc->mbc_i_rx_bytes, mbc->mbc_i_tx_bytes);
|
||||
|
||||
for (i = 0; i < mbc->mbc_ntbs; i++)
|
||||
mbc_tb_dump(&mbc->mbc_tbs[i], p);
|
||||
}
|
||||
|
||||
static void cluster_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_object_priv(obj);
|
||||
unsigned int i;
|
||||
char buf[64];
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_NAME)
|
||||
nl_dump_line(p, "%d: DECT Cluster %s:\n",
|
||||
cl->cl_index, cl->cl_name);
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_MODE)
|
||||
nl_dump_line(p, "\tMode: %s\n",
|
||||
nl_dect_cluster_mode2str(cl->cl_mode,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_PARI) {
|
||||
nl_dump(p, "\tPARI: ");
|
||||
nl_dect_dump_ari(&cl->cl_pari, p);
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
||||
nl_dump(p, "\n");
|
||||
for (i = 0; i < cl->cl_nmbcs; i++)
|
||||
mbc_dump(&cl->cl_mbcs[i], p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_cluster *nl_dect_cluster_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_cluster *)nl_object_alloc(&nl_dect_cluster_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_cluster_get(struct nl_dect_cluster *cl)
|
||||
{
|
||||
nl_object_get((struct nl_object *)cl);
|
||||
}
|
||||
|
||||
void nl_dect_cluster_put(struct nl_dect_cluster *cl)
|
||||
{
|
||||
nl_object_put((struct nl_object *)cl);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
unsigned int nl_dect_cluster_get_index(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return cl->cl_index;
|
||||
}
|
||||
|
||||
void nl_dect_cluster_set_name(struct nl_dect_cluster *cl, const char *name)
|
||||
{
|
||||
cl->cl_name = strdup(name);
|
||||
cl->ce_mask |= CL_ATTR_NAME;
|
||||
}
|
||||
|
||||
bool nl_dect_cluster_test_name(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return !!(cl->ce_mask & CL_ATTR_NAME);
|
||||
}
|
||||
|
||||
const char *nl_dect_cluster_get_name(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return cl->cl_name;
|
||||
}
|
||||
|
||||
void nl_dect_cluster_set_mode(struct nl_dect_cluster *cl, uint8_t mode)
|
||||
{
|
||||
cl->cl_mode = mode;
|
||||
cl->ce_mask |= CL_ATTR_MODE;
|
||||
}
|
||||
|
||||
bool nl_dect_cluster_test_mode(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return !!(cl->ce_mask & CL_ATTR_MODE);
|
||||
}
|
||||
|
||||
uint8_t nl_dect_cluster_get_mode(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return cl->cl_mode;
|
||||
}
|
||||
|
||||
void nl_dect_cluster_set_pari(struct nl_dect_cluster *cl, const struct nl_dect_ari *pari)
|
||||
{
|
||||
memcpy(&cl->cl_pari, pari, sizeof(cl->cl_pari));
|
||||
cl->ce_mask |= CL_ATTR_PARI;
|
||||
}
|
||||
|
||||
bool nl_dect_cluster_test_pari(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return !!(cl->ce_mask & CL_ATTR_PARI);
|
||||
}
|
||||
|
||||
const struct nl_dect_ari *nl_dect_cluster_get_pari(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return &cl->cl_pari;
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_msg(struct nl_msg *msg, struct nl_dect_cluster *cl)
|
||||
{
|
||||
struct dectmsg dm = {
|
||||
.dm_index = cl->cl_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_NAME)
|
||||
NLA_PUT_STRING(msg, DECTA_CLUSTER_NAME, cl->cl_name);
|
||||
if (nl_dect_fill_ari(msg, &cl->cl_pari, DECTA_CLUSTER_PARI) < 0)
|
||||
goto nla_put_failure;
|
||||
if (cl->ce_mask & CL_ATTR_MODE)
|
||||
NLA_PUT_U8(msg, DECTA_CLUSTER_MODE, cl->cl_mode);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static struct trans_tbl cluster_modes[] = {
|
||||
__ADD(DECT_MODE_FP, FP)
|
||||
__ADD(DECT_MODE_PP, PP)
|
||||
};
|
||||
|
||||
char *nl_dect_cluster_mode2str(enum dect_cluster_modes mode, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(mode, buf, len, cluster_modes,
|
||||
ARRAY_SIZE(cluster_modes));
|
||||
}
|
||||
|
||||
enum dect_cluster_modes nl_dect_cluster_str2mode(const char *str)
|
||||
{
|
||||
return __str2type(str, cluster_modes, ARRAY_SIZE(cluster_modes));
|
||||
}
|
||||
|
||||
static struct trans_tbl mbc_states[] = {
|
||||
__ADD(DECT_MBC_NONE, none)
|
||||
__ADD(DECT_MBC_INITIATED, initiated)
|
||||
__ADD(DECT_MBC_ESTABLISHED, established)
|
||||
__ADD(DECT_MBC_RELEASED, released)
|
||||
};
|
||||
|
||||
char *nl_dect_mbc_state2string(enum dect_mbc_state state,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return __type2str(state, buf, len, mbc_states,
|
||||
ARRAY_SIZE(mbc_states));
|
||||
}
|
||||
|
||||
static struct trans_tbl mac_service_types[] = {
|
||||
__ADD(DECT_SERVICE_IN_MIN_DELAY, IN_min_delay)
|
||||
__ADD(DECT_SERVICE_IPX_ENCODED_PROTECTED, IPX_encoded_protected)
|
||||
__ADD(DECT_SERVICE_IN_NORMAL_DELAY, IN_normal_delay)
|
||||
__ADD(DECT_SERVICE_UNKNOWN, unknown)
|
||||
__ADD(DECT_SERVICE_C_CHANNEL_ONLY, C_channel_only)
|
||||
__ADD(DECT_SERVICE_IP_ERROR_DETECTION, IP_error_detection)
|
||||
__ADD(DECT_SERVICE_IPQ_ERROR_DETECTION, IPQ_error_detection)
|
||||
};
|
||||
|
||||
char *nl_dect_mbc_service2string(enum dect_mac_service_types type,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return __type2str(type, buf, len, mac_service_types,
|
||||
ARRAY_SIZE(mac_service_types));
|
||||
}
|
||||
|
||||
static struct trans_tbl cipher_states[] = {
|
||||
__ADD(DECT_CIPHER_DISABLED, disabled)
|
||||
__ADD(DECT_CIPHER_ENABLED, enabled)
|
||||
};
|
||||
|
||||
char *nl_dect_mbc_cipher2string(enum dect_cipher_states state,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return __type2str(state, buf, len, cipher_states,
|
||||
ARRAY_SIZE(cipher_states));
|
||||
}
|
||||
|
||||
/** @cond SKIP */
|
||||
struct nl_object_ops nl_dect_cluster_obj_ops = {
|
||||
.oo_name = "nl_dect/cluster",
|
||||
.oo_size = sizeof(struct nl_dect_cluster),
|
||||
.oo_free_data = cluster_free_data,
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = cluster_dump,
|
||||
},
|
||||
.oo_id_attrs = CL_ATTR_NAME,
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* lib/dect/dect.c DECT
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/dect.h>
|
||||
|
||||
double nl_dect_rssi_to_dbm(uint8_t rssi)
|
||||
{
|
||||
if (rssi == 0)
|
||||
return 0;
|
||||
return -93 + (rssi * 60.0 / 255);
|
||||
}
|
|
@ -0,0 +1,776 @@
|
|||
/*
|
||||
* lib/dect/llme.c DECT Lower Layer Management Entity Objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup dect
|
||||
* @defgroup dect LLME
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/dect.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <netlink/dect/llme.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_object_ops llme_msg_obj_ops;
|
||||
/** @endcond */
|
||||
|
||||
#define MAC_INFO_ATTR_PARI 0x0010000
|
||||
#define MAC_INFO_ATTR_RPN 0x0020000
|
||||
#define MAC_INFO_ATTR_RSSI 0x0040000
|
||||
#define MAC_INFO_ATTR_FPC 0x0080000
|
||||
#define MAC_INFO_ATTR_HLC 0x0100000
|
||||
#define MAC_INFO_ATTR_EFPC 0x0200000
|
||||
#define MAC_INFO_ATTR_EHLC 0x0400000
|
||||
#define MAC_INFO_ATTR_EFPC2 0x0800000
|
||||
#define MAC_INFO_ATTR_EHLC2 0x1000000
|
||||
#define MAC_INFO_ATTR_MFN 0x2000000
|
||||
|
||||
static inline struct nl_dect_llme_mac_info *mac_info(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return (void *)&lmsg->lm_mi;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_pari(struct nl_dect_llme_msg *lmsg,
|
||||
const struct nl_dect_ari *pari)
|
||||
{
|
||||
struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
|
||||
|
||||
memcpy(&mi->mi_pari, pari, sizeof(mi->mi_pari));
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_PARI;
|
||||
}
|
||||
|
||||
bool nl_dect_llme_mac_info_test_pari(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return !!(lmsg->ce_mask & MAC_INFO_ATTR_PARI);
|
||||
}
|
||||
|
||||
const struct nl_dect_ari *nl_dect_llme_mac_info_get_pari(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return &mac_info(lmsg)->mi_pari;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_rpn(struct nl_dect_llme_msg *lmsg, uint8_t rpn)
|
||||
{
|
||||
mac_info(lmsg)->mi_rpn = rpn;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_RPN;
|
||||
}
|
||||
|
||||
uint8_t nl_dect_llme_mac_info_get_rpn(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_rpn;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_rssi(struct nl_dect_llme_msg *lmsg, uint8_t rssi)
|
||||
{
|
||||
mac_info(lmsg)->mi_rssi = rssi;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_RSSI;
|
||||
}
|
||||
|
||||
uint8_t nl_dect_llme_mac_info_get_rssi(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_rssi;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_fpc(struct nl_dect_llme_msg *lmsg, uint32_t fpc)
|
||||
{
|
||||
mac_info(lmsg)->mi_fpc = fpc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_FPC;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_info_get_fpc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_fpc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_hlc(struct nl_dect_llme_msg *lmsg, uint16_t hlc)
|
||||
{
|
||||
mac_info(lmsg)->mi_hlc = hlc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_HLC;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_mac_info_get_hlc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_hlc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_efpc(struct nl_dect_llme_msg *lmsg, uint16_t efpc)
|
||||
{
|
||||
mac_info(lmsg)->mi_efpc = efpc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_EFPC;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_mac_info_get_efpc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_efpc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_ehlc(struct nl_dect_llme_msg *lmsg, uint32_t ehlc)
|
||||
{
|
||||
mac_info(lmsg)->mi_ehlc = ehlc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_EHLC;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_info_get_ehlc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_ehlc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_efpc2(struct nl_dect_llme_msg *lmsg, uint16_t efpc2)
|
||||
{
|
||||
mac_info(lmsg)->mi_efpc2 = efpc2;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_EFPC2;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_mac_info_get_efpc2(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_efpc2;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_ehlc2(struct nl_dect_llme_msg *lmsg, uint32_t ehlc2)
|
||||
{
|
||||
mac_info(lmsg)->mi_ehlc2 = ehlc2;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_EHLC2;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_info_get_ehlc2(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_ehlc2;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_mfn(struct nl_dect_llme_msg *lmsg, uint32_t mfn)
|
||||
{
|
||||
mac_info(lmsg)->mi_mfn = mfn;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_MFN;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_info_get_mfn(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_mfn;
|
||||
}
|
||||
|
||||
|
||||
static struct trans_tbl fixed_part_capabilities[] = {
|
||||
__ADD(DECT_FPC_EXTENDED_FP_INFO, extended_fp_info)
|
||||
__ADD(DECT_FPC_DOUBLE_DUPLEX_BEARER_CONNECTION, double_duplex_bearer_connection)
|
||||
__ADD(DECT_FPC_RESERVED, reserved)
|
||||
__ADD(DECT_FPC_DOUBLE_SLOT, double_slot)
|
||||
__ADD(DECT_FPC_HALF_SLOT, half_slot)
|
||||
__ADD(DECT_FPC_FULL_SLOT, full_slot)
|
||||
__ADD(DECT_FPC_FREQ_CONTROL, frequency_control)
|
||||
__ADD(DECT_FPC_PAGE_REPETITION, page_repetition)
|
||||
__ADD(DECT_FPC_CO_SETUP_ON_DUMMY, co_setup_on_dummy)
|
||||
__ADD(DECT_FPC_CL_UPLINK, cl_uplink)
|
||||
__ADD(DECT_FPC_CL_DOWNLINK, cl_downlink)
|
||||
__ADD(DECT_FPC_BASIC_A_FIELD_SETUP, basic_a_field_setup)
|
||||
__ADD(DECT_FPC_ADV_A_FIELD_SETUP, advanced_a_field_setup)
|
||||
__ADD(DECT_FPC_B_FIELD_SETUP, b_field_setup)
|
||||
__ADD(DECT_FPC_CF_MESSAGES, cf_messages)
|
||||
__ADD(DECT_FPC_IN_MIN_DELAY, in_min_delay)
|
||||
__ADD(DECT_FPC_IN_NORM_DELAY, in_normal_delay)
|
||||
__ADD(DECT_FPC_IP_ERROR_DETECTION, ip_error_detection)
|
||||
__ADD(DECT_FPC_IP_ERROR_CORRECTION, ip_error_correction)
|
||||
__ADD(DECT_FPC_MULTIBEARER_CONNECTIONS, multibearer_connections)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_fpc2str(uint32_t fpc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(fpc, buf, len, fixed_part_capabilities,
|
||||
ARRAY_SIZE(fixed_part_capabilities));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_str2fpc(const char *str)
|
||||
{
|
||||
return __str2flags(str, fixed_part_capabilities,
|
||||
ARRAY_SIZE(fixed_part_capabilities));
|
||||
}
|
||||
|
||||
static struct trans_tbl higher_layer_capabilities[] = {
|
||||
__ADD(DECT_HLC_ADPCM_G721_VOICE, adpcm_g721_voice)
|
||||
__ADD(DECT_HLC_GAP_PAP_BASIC_SPEECH, gap_pap_basic_speech)
|
||||
__ADD(DECT_HLC_NON_VOICE_CIRCUIT_SWITCHED, non_voice_circuit_switched_service)
|
||||
__ADD(DECT_HLC_NON_VOICE_PACKET_SWITCHED, non_voice_packet_switched_service)
|
||||
__ADD(DECT_HLC_STANDARD_AUTHENTICATION, standard_authentication)
|
||||
__ADD(DECT_HLC_STANDARD_CIPHERING, standard_ciphering)
|
||||
__ADD(DECT_HLC_LOCATION_REGISTRATION, location_registration)
|
||||
__ADD(DECT_HLC_SIM_SERVICES, sim_services)
|
||||
__ADD(DECT_HLC_NON_STATIC_FIXED_PART, non_static_fixed_part)
|
||||
__ADD(DECT_HLC_CISS_SERVICE, ciss_service)
|
||||
__ADD(DECT_HLC_CLMS_SERVICE, clms_service)
|
||||
__ADD(DECT_HLC_COMS_SERVICE, coms_service)
|
||||
__ADD(DECT_HLC_ACCESS_RIGHTS_REQUESTS, access_rights_requests)
|
||||
__ADD(DECT_HLC_EXTERNAL_HANDOVER, external_handover)
|
||||
__ADD(DECT_HLC_CONNECTION_HANDOVER, connection_handover)
|
||||
__ADD(DECT_HLC_RESERVED, reserved)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_hlc2str(uint16_t hlc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(hlc, buf, len, higher_layer_capabilities,
|
||||
ARRAY_SIZE(higher_layer_capabilities));
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_str2hlc(const char *str)
|
||||
{
|
||||
return __str2flags(str, higher_layer_capabilities,
|
||||
ARRAY_SIZE(higher_layer_capabilities));
|
||||
}
|
||||
|
||||
static struct trans_tbl extended_fixed_part_capabilities[] = {
|
||||
__ADD(DECT_EFPC_SYNC_PROLONGED_PREAMBLE, prolonged_preamble)
|
||||
__ADD(DECT_EFPC_MAC_SUSPEND_RESUME, suspend_resume)
|
||||
__ADD(DECT_EFPC_MAC_IP_Q_SERVICE, ip_q_service)
|
||||
__ADD(DECT_EFPC_EXTENDED_FP_INFO2, extended_fp_info2)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_efpc2str(uint16_t efpc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(efpc, buf, len, extended_fixed_part_capabilities,
|
||||
ARRAY_SIZE(extended_fixed_part_capabilities));
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_str2efpc(const char *str)
|
||||
{
|
||||
return __str2flags(str, extended_fixed_part_capabilities,
|
||||
ARRAY_SIZE(extended_fixed_part_capabilities));
|
||||
}
|
||||
static struct trans_tbl extended_higher_layer_capabilities[] = {
|
||||
__ADD(DECT_EHLC_ISDN_DATA_SERVICE, isdn_data_service)
|
||||
__ADD(DECT_EHLC_DPRS_FREL, dprs_frel)
|
||||
__ADD(DECT_EHLC_DPRS_STREAM, dprs_stream)
|
||||
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_D, data_service_profile_d)
|
||||
__ADD(DECT_EHLC_LRMS, lrms)
|
||||
__ADD(DECT_EHLC_ASYMETRIC_BEARERS, asymetric_bearers)
|
||||
__ADD(DECT_EHLC_EMERGENCY_CALLS, emergency_calls)
|
||||
__ADD(DECT_EHLC_TPUI_LOCATION_REGISTRATION, tpui_location_registration)
|
||||
__ADD(DECT_EHLC_GPS_SYNCHRONIZED, gps_synchronized)
|
||||
__ADD(DECT_EHLC_ISDN_INTERMEDIATE_SYSTEM, isdn_intermediate_system)
|
||||
__ADD(DECT_EHLC_RAP_PART_1_PROFILE, rap_1_profile)
|
||||
__ADD(DECT_EHLC_V_24, v_24)
|
||||
__ADD(DECT_EHLC_PPP, ppp)
|
||||
__ADD(DECT_EHLC_IP, ip)
|
||||
__ADD(DECT_EHLC_TOKEN_RING, token_ring)
|
||||
__ADD(DECT_EHLC_ETHERNET, ethernet)
|
||||
__ADD(DECT_EHLC_IP_ROAMING, ip_roaming)
|
||||
__ADD(DECT_EHLC_GENERIC_MEDIA_ENCAPSULATION, generic_media_encapsulation)
|
||||
__ADD(DECT_EHLC_BASIC_ODAP, basic_odap)
|
||||
__ADD(DECT_EHLC_F_MMS_INTERWORKING_PROFILE, mms_interworking_profile)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_ehlc2str(uint32_t ehlc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(ehlc, buf, len, extended_higher_layer_capabilities,
|
||||
ARRAY_SIZE(extended_higher_layer_capabilities));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_str2ehlc(const char *str)
|
||||
{
|
||||
return __str2flags(str, extended_higher_layer_capabilities,
|
||||
ARRAY_SIZE(extended_higher_layer_capabilities));
|
||||
}
|
||||
|
||||
static struct trans_tbl extended_fixed_part_capabilities2[] = {
|
||||
__ADD(DECT_EFPC2_NO_EMISSION_CARRIER, no_emission_carrier)
|
||||
__ADD(DECT_EFPC2_GF, gf_channel)
|
||||
__ADD(DECT_EFPC2_SI_PF, si_pf_channel)
|
||||
__ADD(DECT_EFPC2_IP_F, ip_f_channel)
|
||||
__ADD(DECT_EFPC2_LONG_SLOT_J672, long_slot_j672)
|
||||
__ADD(DECT_EFPC2_LONG_SLOT_J640, long_slot_j640)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_efpc22str(uint16_t efpc2, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(efpc2, buf, len, extended_fixed_part_capabilities2,
|
||||
ARRAY_SIZE(extended_fixed_part_capabilities2));
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_str2efpc2(const char *str)
|
||||
{
|
||||
return __str2flags(str, extended_fixed_part_capabilities2,
|
||||
ARRAY_SIZE(extended_fixed_part_capabilities2));
|
||||
}
|
||||
|
||||
static struct trans_tbl extended_higher_layer_capabilities2[] = {
|
||||
__ADD(DECT_EHLC2_NG_DECT_PERMANENT_CLIR, permanent_clir)
|
||||
__ADD(DECT_EHLC2_NG_DECT_MULTIPLE_CALLS, multiple_calls)
|
||||
__ADD(DECT_EHLC2_NG_DECT_MULTIPLE_LINES, multiple_lines)
|
||||
__ADD(DECT_EHLC2_EASY_PAIRING, easy_pairing)
|
||||
__ADD(DECT_EHLC2_LIST_ACCESS_FEATURES, list_access_features)
|
||||
__ADD(DECT_EHLC2_NO_EMISSION_MODE, no_emission_mode)
|
||||
__ADD(DECT_EHLC2_NG_DECT_CALL_DEFLECTION, call_deflection)
|
||||
__ADD(DECT_EHLC2_NG_DECT_INTRUSION_CALL, intrusion_call)
|
||||
__ADD(DECT_EHLC2_NG_DECT_CONFERENCE_CALL, conference_call)
|
||||
__ADD(DECT_EHLC2_NG_DECT_PARALLEL_CALLS, parallel_calls)
|
||||
__ADD(DECT_EHLC2_NG_DECT_CALL_TRANSFER, call_transfer)
|
||||
__ADD(DECT_EHLC2_NG_DECT_EXTENDED_WIDEBAND, extended_wideband)
|
||||
__ADD(DECT_EHLC2_PACKET_DATA_CATEGORY_MASK, packet_data)
|
||||
__ADD(DECT_EHLC2_NG_DECT_WIDEBAND, wideband)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_ehlc22str(uint32_t ehlc2, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(ehlc2, buf, len, extended_higher_layer_capabilities2,
|
||||
ARRAY_SIZE(extended_higher_layer_capabilities2));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_str22ehlc(const char *str)
|
||||
{
|
||||
return __str2flags(str, extended_higher_layer_capabilities2,
|
||||
ARRAY_SIZE(extended_higher_layer_capabilities2));
|
||||
}
|
||||
|
||||
|
||||
static void nl_dect_llme_mac_info_dump(const struct nl_dect_llme_msg *lmsg,
|
||||
struct nl_dump_params *p)
|
||||
{
|
||||
const struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
|
||||
char buf[256];
|
||||
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_PARI) {
|
||||
nl_dump(p, "\n\tARI: ");
|
||||
nl_dect_dump_ari(&mi->mi_pari, p);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_RPN)
|
||||
nl_dump(p, " RPN: %x", mi->mi_rpn);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_RSSI)
|
||||
nl_dump(p, " signal level: %.2fdBm", nl_dect_rssi_to_dbm(mi->mi_rssi));
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_FPC && mi->mi_fpc) {
|
||||
nl_dect_llme_fpc2str(mi->mi_fpc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tMAC layer capabilities: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EFPC && mi->mi_efpc) {
|
||||
nl_dect_llme_efpc2str(mi->mi_efpc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tExtended MAC layer capabilities: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EFPC2 && mi->mi_efpc2) {
|
||||
nl_dect_llme_efpc22str(mi->mi_efpc2, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tExtended MAC layer capabilities 2: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_HLC && mi->mi_hlc) {
|
||||
nl_dect_llme_hlc2str(mi->mi_hlc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tHigher layer capabilities: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC && mi->mi_ehlc) {
|
||||
nl_dect_llme_ehlc2str(mi->mi_ehlc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tExtended higher layer capabilities: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC2 && mi->mi_ehlc2) {
|
||||
nl_dect_llme_ehlc22str(mi->mi_ehlc2, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tExtended higher layer capabilities 2: %s", buf);
|
||||
}
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
||||
|
||||
static struct nla_policy nl_dect_mac_info_policy[DECTA_MAC_INFO_MAX + 1] = {
|
||||
[DECTA_MAC_INFO_PARI] = { .type = NLA_NESTED },
|
||||
[DECTA_MAC_INFO_RPN] = { .type = NLA_U8 },
|
||||
[DECTA_MAC_INFO_RSSI] = { .type = NLA_U8 },
|
||||
[DECTA_MAC_INFO_SARI_LIST] = { .type = NLA_NESTED },
|
||||
[DECTA_MAC_INFO_FPC] = { .type = NLA_U32 },
|
||||
[DECTA_MAC_INFO_HLC] = { .type = NLA_U16 },
|
||||
[DECTA_MAC_INFO_EFPC] = { .type = NLA_U16 },
|
||||
[DECTA_MAC_INFO_EHLC] = { .type = NLA_U32 },
|
||||
[DECTA_MAC_INFO_EFPC2] = { .type = NLA_U16 },
|
||||
[DECTA_MAC_INFO_EHLC2] = { .type = NLA_U32 },
|
||||
[DECTA_MAC_INFO_MFN] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int nl_dect_llme_mac_info_parse(struct nl_dect_llme_msg *lmsg,
|
||||
struct nlattr *tb[])
|
||||
{
|
||||
struct nl_dect_ari pari;
|
||||
int err;
|
||||
|
||||
if (tb[DECTA_MAC_INFO_PARI] != NULL) {
|
||||
err = nl_dect_parse_ari(&pari, tb[DECTA_MAC_INFO_PARI]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
nl_dect_llme_mac_info_set_pari(lmsg, &pari);
|
||||
}
|
||||
if (tb[DECTA_MAC_INFO_RPN] != NULL)
|
||||
nl_dect_llme_mac_info_set_rpn(lmsg, nla_get_u8(tb[DECTA_MAC_INFO_RPN]));
|
||||
if (tb[DECTA_MAC_INFO_RSSI] != NULL)
|
||||
nl_dect_llme_mac_info_set_rssi(lmsg, nla_get_u8(tb[DECTA_MAC_INFO_RSSI]));
|
||||
if (tb[DECTA_MAC_INFO_FPC] != NULL)
|
||||
nl_dect_llme_mac_info_set_fpc(lmsg, nla_get_u32(tb[DECTA_MAC_INFO_FPC]));
|
||||
if (tb[DECTA_MAC_INFO_HLC] != NULL)
|
||||
nl_dect_llme_mac_info_set_hlc(lmsg, nla_get_u16(tb[DECTA_MAC_INFO_HLC]));
|
||||
if (tb[DECTA_MAC_INFO_EFPC] != NULL)
|
||||
nl_dect_llme_mac_info_set_efpc(lmsg, nla_get_u16(tb[DECTA_MAC_INFO_EFPC]));
|
||||
if (tb[DECTA_MAC_INFO_EHLC] != NULL)
|
||||
nl_dect_llme_mac_info_set_ehlc(lmsg, nla_get_u32(tb[DECTA_MAC_INFO_EHLC]));
|
||||
if (tb[DECTA_MAC_INFO_EFPC2] != NULL)
|
||||
nl_dect_llme_mac_info_set_efpc2(lmsg, nla_get_u16(tb[DECTA_MAC_INFO_EFPC2]));
|
||||
if (tb[DECTA_MAC_INFO_EHLC2] != NULL)
|
||||
nl_dect_llme_mac_info_set_ehlc2(lmsg, nla_get_u32(tb[DECTA_MAC_INFO_EHLC2]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl_dect_llme_mac_info_build(struct nl_msg *msg,
|
||||
struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
|
||||
int err;
|
||||
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_PARI) {
|
||||
err = nl_dect_fill_ari(msg, &mi->mi_pari, DECTA_MAC_INFO_PARI);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_RPN)
|
||||
NLA_PUT_U8(msg, DECTA_MAC_INFO_RPN, mi->mi_rpn);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_FPC)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_INFO_FPC, mi->mi_fpc);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_HLC)
|
||||
NLA_PUT_U16(msg, DECTA_MAC_INFO_HLC, mi->mi_hlc);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EFPC)
|
||||
NLA_PUT_U16(msg, DECTA_MAC_INFO_EFPC, mi->mi_efpc);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_INFO_EHLC, mi->mi_ehlc);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EFPC2)
|
||||
NLA_PUT_U16(msg, DECTA_MAC_INFO_EFPC2, mi->mi_efpc2);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC2)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_INFO_EHLC2, mi->mi_ehlc2);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_MFN)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_INFO_MFN, mi->mi_mfn);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static const struct nl_dect_llme_link {
|
||||
int (*parse)(struct nl_dect_llme_msg *, struct nlattr *[]);
|
||||
int (*build)(struct nl_msg *, struct nl_dect_llme_msg *);
|
||||
void (*dump)(const struct nl_dect_llme_msg *, struct nl_dump_params *);
|
||||
struct nla_policy *policy;
|
||||
unsigned int maxtype;
|
||||
} nl_dect_llme_dispatch[DECT_LLME_MAX + 1] = {
|
||||
[DECT_LLME_SCAN] = {
|
||||
.policy = nl_dect_mac_info_policy,
|
||||
.maxtype = DECTA_MAC_INFO_MAX,
|
||||
.parse = nl_dect_llme_mac_info_parse,
|
||||
.build = nl_dect_llme_mac_info_build,
|
||||
.dump = nl_dect_llme_mac_info_dump,
|
||||
},
|
||||
[DECT_LLME_MAC_INFO] = {
|
||||
.policy = nl_dect_mac_info_policy,
|
||||
.maxtype = DECTA_MAC_INFO_MAX,
|
||||
.parse = nl_dect_llme_mac_info_parse,
|
||||
.build = nl_dect_llme_mac_info_build,
|
||||
.dump = nl_dect_llme_mac_info_dump,
|
||||
},
|
||||
[DECT_LLME_MAC_RFP_PRELOAD] = {
|
||||
.policy = nl_dect_mac_info_policy,
|
||||
.maxtype = DECTA_MAC_INFO_MAX,
|
||||
.parse = nl_dect_llme_mac_info_parse,
|
||||
.build = nl_dect_llme_mac_info_build,
|
||||
.dump = nl_dect_llme_mac_info_dump,
|
||||
},
|
||||
};
|
||||
|
||||
static void llme_msg_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_llme_msg *lmsg = nl_object_priv(obj);
|
||||
const struct nl_dect_llme_link *link;
|
||||
char buf1[64], buf2[64];
|
||||
|
||||
nl_dect_llme_msgtype2str(lmsg->lm_type, buf1, sizeof(buf1));
|
||||
nl_dect_llme_op2str(lmsg->lm_op, buf2, sizeof(buf2));
|
||||
nl_dump(p, "%s-%s: ", buf1, buf2);
|
||||
|
||||
link = &nl_dect_llme_dispatch[lmsg->lm_type];
|
||||
link->dump(lmsg, p);
|
||||
}
|
||||
|
||||
static struct nla_policy nl_dect_llme_policy[DECTA_LLME_MAX + 1] = {
|
||||
[DECTA_LLME_OP] = { .type = NLA_U8 },
|
||||
[DECTA_LLME_TYPE] = { .type = NLA_U8 },
|
||||
[DECTA_LLME_DATA] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int llme_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, struct nl_parser_param *pp)
|
||||
{
|
||||
const struct nl_dect_llme_link *link;
|
||||
struct dectmsg *dm = nlmsg_data(n);
|
||||
struct nlattr *tb[DECTA_LLME_MAX + 1];
|
||||
struct nl_dect_llme_msg *lmsg;
|
||||
uint8_t op, type;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_LLME_MAX, nl_dect_llme_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_LLME_OP] == NULL ||
|
||||
tb[DECTA_LLME_TYPE] == NULL ||
|
||||
tb[DECTA_LLME_DATA] == NULL)
|
||||
return -NLE_INVAL;
|
||||
|
||||
type = nla_get_u8(tb[DECTA_LLME_TYPE]);
|
||||
if (type > DECT_LLME_MAX)
|
||||
return -NLE_INVAL;
|
||||
link = &nl_dect_llme_dispatch[type];
|
||||
|
||||
op = nla_get_u8(tb[DECTA_LLME_OP]);
|
||||
switch (op) {
|
||||
case DECT_LLME_REQUEST:
|
||||
case DECT_LLME_INDICATE:
|
||||
case DECT_LLME_RESPONSE:
|
||||
case DECT_LLME_CONFIRM:
|
||||
if (link->parse == NULL)
|
||||
return -NLE_OPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
return -NLE_INVAL;
|
||||
}
|
||||
|
||||
lmsg = nl_dect_llme_msg_alloc();
|
||||
lmsg->ce_msgtype = n->nlmsg_type;
|
||||
lmsg->lm_index = dm->dm_index;
|
||||
|
||||
nl_dect_llme_msg_set_type(lmsg, type);
|
||||
nl_dect_llme_msg_set_op(lmsg, op);
|
||||
|
||||
if (1) {
|
||||
struct nlattr *nla[link->maxtype + 1];
|
||||
|
||||
err = nla_parse_nested(nla, link->maxtype, tb[DECTA_LLME_DATA],
|
||||
link->policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
err = link->parse(lmsg, nla);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)lmsg, pp);
|
||||
errout:
|
||||
nl_dect_llme_msg_put(lmsg);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name message creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int nl_dect_llme_build_msg(struct nl_msg *msg, struct nl_dect_llme_msg *lmsg,
|
||||
enum dect_llme_ops op)
|
||||
{
|
||||
const struct nl_dect_llme_link *link;
|
||||
struct nlattr *nest;
|
||||
struct dectmsg dm = {
|
||||
.dm_index = lmsg->lm_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_U8(msg, DECTA_LLME_OP, op);
|
||||
NLA_PUT_U8(msg, DECTA_LLME_TYPE, lmsg->lm_type);
|
||||
|
||||
link = &nl_dect_llme_dispatch[lmsg->lm_type];
|
||||
nest = nla_nest_start(msg, DECTA_LLME_DATA);
|
||||
if (nest == NULL)
|
||||
goto nla_put_failure;
|
||||
if (link->build(msg, lmsg) < 0)
|
||||
goto nla_put_failure;
|
||||
nla_nest_end(msg, nest);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static int build_llme_msg(struct nl_dect_llme_msg *tmpl, enum dect_llme_ops op,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if (!(msg = nlmsg_alloc_simple(DECT_LLME_MSG, 0)))
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if ((err = nl_dect_llme_build_msg(msg, tmpl, op)) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_llme_build_request(struct nl_dect_llme_msg *tmpl,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_llme_msg(tmpl, DECT_LLME_REQUEST, result);
|
||||
}
|
||||
|
||||
int nl_dect_llme_request(struct nl_sock *sk, struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nl_dect_llme_build_request(lmsg, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_llme_build_response(struct nl_dect_llme_msg *tmpl,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_llme_msg(tmpl, DECT_LLME_RESPONSE, result);
|
||||
}
|
||||
|
||||
int nl_dect_llme_respond(struct nl_sock *sk, struct nl_dect_llme_msg *tmpl)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nl_dect_llme_build_response(tmpl, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_set_index(struct nl_dect_llme_msg *lmsg, int index)
|
||||
{
|
||||
lmsg->lm_index = index;
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_set_type(struct nl_dect_llme_msg *lmsg,
|
||||
enum dect_llme_msg_types type)
|
||||
{
|
||||
lmsg->lm_type = type;
|
||||
}
|
||||
|
||||
enum dect_llme_msg_types nl_dect_llme_msg_get_type(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return lmsg->lm_type;
|
||||
}
|
||||
|
||||
enum dect_llme_ops nl_dect_llme_msg_get_op(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return lmsg->lm_op;
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_set_op(struct nl_dect_llme_msg *lmsg, enum dect_llme_ops op)
|
||||
{
|
||||
lmsg->lm_op = op;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_llme_msg *nl_dect_llme_msg_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_llme_msg *)nl_object_alloc(&llme_msg_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_get(struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
nl_object_get((struct nl_object *)lmsg);
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_put(struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
nl_object_put((struct nl_object *)lmsg);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct trans_tbl llme_types[] = {
|
||||
__ADD(DECT_LLME_SCAN, SCAN)
|
||||
__ADD(DECT_LLME_MAC_INFO, MAC_INFO)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_msgtype2str(enum dect_llme_msg_types type, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(type, buf, len, llme_types, ARRAY_SIZE(llme_types));
|
||||
}
|
||||
|
||||
enum dect_llme_msg_types nl_dect_llme_str2msgtype(const char *str)
|
||||
{
|
||||
return __str2type(str, llme_types, ARRAY_SIZE(llme_types));
|
||||
}
|
||||
|
||||
static struct trans_tbl llme_ops[] = {
|
||||
__ADD(DECT_LLME_REQUEST, req)
|
||||
__ADD(DECT_LLME_INDICATE, ind)
|
||||
__ADD(DECT_LLME_RESPONSE, res)
|
||||
__ADD(DECT_LLME_CONFIRM, cfm)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_op2str(enum dect_llme_ops op, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(op, buf, len, llme_ops, ARRAY_SIZE(llme_ops));
|
||||
}
|
||||
|
||||
enum dect_llme_ops nl_dect_llme_str2op(const char *str)
|
||||
{
|
||||
return __str2type(str, llme_ops, ARRAY_SIZE(llme_ops));
|
||||
}
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_object_ops llme_msg_obj_ops = {
|
||||
.oo_name = "nl_dect/llme_msg",
|
||||
.oo_size = sizeof(struct nl_dect_llme_msg),
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = llme_msg_dump,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nl_cache_ops nl_dect_llme_msg_ops = {
|
||||
.co_name = "nl_dect/llme_msg",
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_msgtypes = {
|
||||
{ DECT_LLME_MSG, NL_ACT_NEW, "new" },
|
||||
END_OF_MSGTYPES_LIST,
|
||||
},
|
||||
.co_msg_parser = llme_msg_parser,
|
||||
.co_obj_ops = &llme_msg_obj_ops,
|
||||
};
|
||||
/** @endcond */
|
||||
|
||||
static void __init llme_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_llme_msg_ops);
|
||||
}
|
||||
|
||||
static void __exit llme_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_llme_msg_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* lib/dect/transceiver.c DECT Transceiver objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup dect
|
||||
* @defgroup dect Transceivers
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/transceiver.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_cache_ops nl_dect_transceiver_ops;
|
||||
/** @endcond */
|
||||
|
||||
#define DECTNAMSIZ 16
|
||||
|
||||
static struct nla_policy transceiver_policy[DECTA_TRANSCEIVER_MAX + 1] = {
|
||||
[DECTA_TRANSCEIVER_NAME] = { .type = NLA_STRING, .maxlen = DECTNAMSIZ },
|
||||
[DECTA_TRANSCEIVER_TYPE] = { .type = NLA_STRING },
|
||||
[DECTA_TRANSCEIVER_FEATURES] = { .type = NLA_U32 },
|
||||
[DECTA_TRANSCEIVER_LINK] = { .type = NLA_U8 },
|
||||
[DECTA_TRANSCEIVER_STATS] = { .type = NLA_NESTED },
|
||||
[DECTA_TRANSCEIVER_BAND] = { .type = NLA_U8 },
|
||||
[DECTA_TRANSCEIVER_SLOTS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct nla_policy stats_policy[DECTA_TRANSCEIVER_STATS_MAX + 1] = {
|
||||
[DECTA_TRANSCEIVER_STATS_EVENT_BUSY] = { .type = NLA_U32 },
|
||||
[DECTA_TRANSCEIVER_STATS_EVENT_LATE] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static struct nla_policy slot_policy[DECTA_SLOT_MAX + 1] = {
|
||||
[DECTA_SLOT_NUM] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_STATE] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_FLAGS] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_PACKET] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_CARRIER] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_FREQUENCY] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_PHASEOFF] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RSSI] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_RX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RX_PACKETS] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RX_A_CRC_ERRORS] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RX_X_CRC_ERRORS] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RX_Z_CRC_ERRORS] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_TX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_TX_PACKETS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int slot_parser(struct nl_dect_transceiver *trx, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *tb[DECTA_SLOT_MAX + 1];
|
||||
struct nl_dect_transceiver_slot *dts;
|
||||
uint8_t slot;
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_SLOT_MAX, nla, slot_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_SLOT_NUM] == NULL)
|
||||
return -NLE_INVAL;
|
||||
slot = nla_get_u8(tb[DECTA_SLOT_NUM]);
|
||||
dts = &trx->trx_slots[slot];
|
||||
|
||||
dts->dts_valid = 1;
|
||||
if (tb[DECTA_SLOT_STATE] != NULL)
|
||||
dts->dts_state = nla_get_u8(tb[DECTA_SLOT_STATE]);
|
||||
if (tb[DECTA_SLOT_FLAGS] != NULL)
|
||||
dts->dts_flags = nla_get_u32(tb[DECTA_SLOT_FLAGS]);
|
||||
if (tb[DECTA_SLOT_PACKET] != NULL)
|
||||
dts->dts_packet = nla_get_u8(tb[DECTA_SLOT_PACKET]);
|
||||
if (tb[DECTA_SLOT_CARRIER] != NULL)
|
||||
dts->dts_carrier = nla_get_u8(tb[DECTA_SLOT_CARRIER]);
|
||||
if (tb[DECTA_SLOT_FREQUENCY] != NULL)
|
||||
dts->dts_frequency = nla_get_u32(tb[DECTA_SLOT_FREQUENCY]);
|
||||
if (tb[DECTA_SLOT_PHASEOFF] != NULL)
|
||||
dts->dts_phaseoff = nla_get_u32(tb[DECTA_SLOT_PHASEOFF]);
|
||||
if (tb[DECTA_SLOT_RSSI] != NULL)
|
||||
dts->dts_rssi = nla_get_u8(tb[DECTA_SLOT_RSSI]);
|
||||
if (tb[DECTA_SLOT_RX_BYTES] != NULL)
|
||||
dts->dts_rx_bytes = nla_get_u32(tb[DECTA_SLOT_RX_BYTES]);
|
||||
if (tb[DECTA_SLOT_RX_PACKETS] != NULL)
|
||||
dts->dts_rx_packets = nla_get_u32(tb[DECTA_SLOT_RX_PACKETS]);
|
||||
if (tb[DECTA_SLOT_RX_A_CRC_ERRORS] != NULL)
|
||||
dts->dts_rx_a_crc_errors = nla_get_u32(tb[DECTA_SLOT_RX_A_CRC_ERRORS]);
|
||||
if (tb[DECTA_SLOT_RX_X_CRC_ERRORS] != NULL)
|
||||
dts->dts_rx_x_crc_errors = nla_get_u32(tb[DECTA_SLOT_RX_X_CRC_ERRORS]);
|
||||
if (tb[DECTA_SLOT_RX_Z_CRC_ERRORS] != NULL)
|
||||
dts->dts_rx_z_crc_errors = nla_get_u32(tb[DECTA_SLOT_RX_Z_CRC_ERRORS]);
|
||||
if (tb[DECTA_SLOT_TX_BYTES] != NULL)
|
||||
dts->dts_tx_bytes = nla_get_u32(tb[DECTA_SLOT_TX_BYTES]);
|
||||
if (tb[DECTA_SLOT_TX_PACKETS] != NULL)
|
||||
dts->dts_tx_packets = nla_get_u32(tb[DECTA_SLOT_TX_PACKETS]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stats_parser(struct nl_dect_transceiver *trx, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *tb[DECTA_TRANSCEIVER_STATS_MAX + 1];
|
||||
struct nl_dect_transceiver_stats *stats = &trx->trx_stats;
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_TRANSCEIVER_STATS_MAX, nla, stats_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_STATS_EVENT_BUSY] != NULL)
|
||||
stats->trx_event_busy =
|
||||
nla_get_u32(tb[DECTA_TRANSCEIVER_STATS_EVENT_BUSY]);
|
||||
if (tb[DECTA_TRANSCEIVER_STATS_EVENT_LATE] != NULL)
|
||||
stats->trx_event_late =
|
||||
nla_get_u32(tb[DECTA_TRANSCEIVER_STATS_EVENT_LATE]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transceiver_msg_parser(struct nl_cache_ops *ops,
|
||||
struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n,
|
||||
struct nl_parser_param *pp)
|
||||
{
|
||||
struct nlattr *tb[DECTA_TRANSCEIVER_MAX + 1], *nla;
|
||||
struct nl_dect_transceiver *trx;
|
||||
int err;
|
||||
|
||||
trx = nl_dect_transceiver_alloc();
|
||||
if (trx == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
trx->ce_msgtype = n->nlmsg_type;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(struct dectmsg), tb, DECTA_TRANSCEIVER_MAX,
|
||||
transceiver_policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_NAME] != NULL) {
|
||||
char name[DECTNAMSIZ];
|
||||
nla_strlcpy(name, tb[DECTA_TRANSCEIVER_NAME], sizeof(name));
|
||||
nl_dect_transceiver_set_name(trx, name);
|
||||
}
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_TYPE] != NULL) {
|
||||
char *type = nla_strdup(tb[DECTA_TRANSCEIVER_TYPE]);
|
||||
if (type == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
nl_dect_transceiver_set_type(trx, type);
|
||||
free(type);
|
||||
}
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_FEATURES] != NULL)
|
||||
nl_dect_transceiver_set_features(trx, nla_get_u32(tb[DECTA_TRANSCEIVER_FEATURES]));
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_LINK] != NULL)
|
||||
nl_dect_transceiver_set_link(trx, nla_get_u8(tb[DECTA_TRANSCEIVER_LINK]));
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_STATS] != NULL) {
|
||||
err = stats_parser(trx, tb[DECTA_TRANSCEIVER_STATS]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_BAND] != NULL)
|
||||
nl_dect_transceiver_set_band(trx, nla_get_u8(tb[DECTA_TRANSCEIVER_BAND]));
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_SLOTS] != NULL) {
|
||||
int rem;
|
||||
nla_for_each_nested(nla, tb[DECTA_TRANSCEIVER_SLOTS], rem) {
|
||||
if (nla_type(nla) != DECTA_LIST_ELEM)
|
||||
continue;
|
||||
err = slot_parser(trx, nla);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)trx, pp);
|
||||
errout:
|
||||
nl_dect_transceiver_put(trx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int transceiver_request_update(struct nl_cache *c, struct nl_sock *h)
|
||||
{
|
||||
struct dectmsg dm;
|
||||
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
return nl_send_simple(h, DECT_GET_TRANSCEIVER, NLM_F_DUMP,
|
||||
&dm, sizeof(dm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Cache Management
|
||||
* @{
|
||||
*/
|
||||
int nl_dect_transceiver_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
struct nl_cache *cache;
|
||||
int err;
|
||||
|
||||
cache = nl_cache_alloc(&nl_dect_transceiver_ops);
|
||||
if (cache == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
|
||||
free(cache);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Transceiver creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int build_transceiver_msg(struct nl_dect_transceiver *tmpl, int cmd,
|
||||
int flags, struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_dect_transceiver_build_msg(msg, tmpl);
|
||||
if (err < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_transceiver_build_change_request(struct nl_dect_transceiver *tmpl,
|
||||
int flags, struct nl_msg **result)
|
||||
{
|
||||
return build_transceiver_msg(tmpl, DECT_NEW_TRANSCEIVER, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_transceiver_change(struct nl_sock *sk, struct nl_dect_transceiver *trx,
|
||||
int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_transceiver_build_change_request(trx, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
static struct nl_cache_ops nl_dect_transceiver_ops = {
|
||||
.co_name = "nl_dect/transceiver",
|
||||
.co_hdrsize = 0,
|
||||
.co_msgtypes = {
|
||||
{ DECT_NEW_TRANSCEIVER, NL_ACT_NEW, "new" },
|
||||
{ DECT_GET_TRANSCEIVER, NL_ACT_GET, "get" },
|
||||
{ DECT_DEL_TRANSCEIVER, NL_ACT_DEL, "del" },
|
||||
END_OF_MSGTYPES_LIST
|
||||
},
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_request_update = transceiver_request_update,
|
||||
.co_msg_parser = transceiver_msg_parser,
|
||||
.co_obj_ops = &nl_dect_transceiver_obj_ops,
|
||||
};
|
||||
|
||||
static void __init transceiver_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_transceiver_ops);
|
||||
}
|
||||
|
||||
static void __exit transceiver_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_transceiver_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* lib/dect/transceiver_obj.c DECT Transceiver objects
|
||||
*
|
||||
* 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) 2009 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/dect/dect.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/transceiver.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define TRANSCEIVER_ATTR_NAME 0x0001
|
||||
#define TRANSCEIVER_ATTR_TYPE 0x0002
|
||||
#define TRANSCEIVER_ATTR_FEATURES 0x0004
|
||||
#define TRANSCEIVER_ATTR_INDEX 0x0008
|
||||
#define TRANSCEIVER_ATTR_LINK 0x0010
|
||||
#define TRANSCEIVER_ATTR_BAND 0x0020
|
||||
/** @endtsond */
|
||||
|
||||
static void transceiver_free_data(struct nl_object *obj)
|
||||
{
|
||||
struct nl_dect_transceiver *trx = nl_object_priv(obj);
|
||||
|
||||
if (trx == NULL)
|
||||
return;
|
||||
free(trx->trx_name);
|
||||
free(trx->trx_type);
|
||||
}
|
||||
|
||||
static void slot_dump(struct nl_dect_transceiver_slot *dts, unsigned int n,
|
||||
struct nl_dump_params *p)
|
||||
{
|
||||
int64_t offset;
|
||||
char buf[64];
|
||||
|
||||
nl_dect_slot_state2str(dts->dts_state, buf, sizeof(buf));
|
||||
nl_dump(p, "\tslot %u: <%s", n, buf);
|
||||
if (dts->dts_flags) {
|
||||
nl_dect_slot_flags2str(dts->dts_flags, buf, sizeof(buf));
|
||||
nl_dump(p, ",%s", buf);
|
||||
}
|
||||
nl_dump(p, "> ");
|
||||
|
||||
if (dts->dts_state != DECT_SLOT_IDLE) {
|
||||
nl_dump(p, "packet: %s ",
|
||||
nl_dect_slot_packet2str(dts->dts_packet, buf,
|
||||
sizeof(buf)));
|
||||
|
||||
nl_dump(p, "carrier: %u (%u.%03u MHz", dts->dts_carrier,
|
||||
dts->dts_frequency / 1000, dts->dts_frequency % 1000);
|
||||
|
||||
if (dts->dts_state == DECT_SLOT_RX) {
|
||||
offset = (int64_t)dts->dts_frequency *
|
||||
dts->dts_phaseoff /
|
||||
DECT_PHASE_OFFSET_SCALE;
|
||||
nl_dump(p, " %+" PRId64 ".%03" PRIu64 " kHz",
|
||||
offset / 1000000,
|
||||
llabs(offset) % 1000000 / 1000);
|
||||
}
|
||||
nl_dump(p, ")");
|
||||
}
|
||||
|
||||
if (dts->dts_state == DECT_SLOT_RX)
|
||||
nl_dump(p, " signal level: %.2fdBm",
|
||||
nl_dect_rssi_to_dbm(dts->dts_rssi));
|
||||
nl_dump(p, "\n");
|
||||
|
||||
nl_dump(p, "\t RX: bytes %u packets %u a-crc-errors %u "
|
||||
"x-crc-errors %u z-crc-errors %u\n",
|
||||
dts->dts_rx_bytes, dts->dts_rx_packets,
|
||||
dts->dts_rx_a_crc_errors,
|
||||
dts->dts_rx_x_crc_errors,
|
||||
dts->dts_rx_z_crc_errors);
|
||||
nl_dump(p, "\t TX: bytes %u packets %u\n",
|
||||
dts->dts_tx_bytes, dts->dts_tx_packets);
|
||||
}
|
||||
|
||||
static void transceiver_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_transceiver *trx = nl_object_priv(obj);
|
||||
struct nl_dect_transceiver_stats *stats = &trx->trx_stats;
|
||||
struct nl_dect_transceiver_slot *dts;
|
||||
struct nl_cache *cell_cache;
|
||||
char buf[64];
|
||||
unsigned int n;
|
||||
|
||||
nl_dump(p, "DECT Transceiver ");
|
||||
if (trx->trx_name != NULL)
|
||||
nl_dump_line(p, "%s", trx->trx_name);
|
||||
|
||||
if (trx->trx_link) {
|
||||
cell_cache = nl_cache_mngt_require("nl_dect/cell");
|
||||
if (cell_cache != NULL) {
|
||||
nl_dump(p, "@%s",
|
||||
nl_dect_cell_i2name(cell_cache, trx->trx_link,
|
||||
buf, sizeof(buf)));
|
||||
} else
|
||||
nl_dump(p, "@%d", trx->trx_link);
|
||||
}
|
||||
nl_dump(p, ":\n");
|
||||
if (trx->trx_type != NULL)
|
||||
nl_dump_line(p, "\tType: %s\n", trx->trx_type);
|
||||
if (trx->trx_features != 0)
|
||||
nl_dump_line(p, "\tFeatures: %s\n",
|
||||
nl_dect_transceiver_features2str(trx->trx_features,
|
||||
buf, sizeof(buf)));
|
||||
nl_dump(p, "\tRF-band: %.5u\n", trx->trx_band);
|
||||
nl_dump(p, "\tEvents: busy: %u late: %u\n",
|
||||
stats->trx_event_busy, stats->trx_event_late);
|
||||
|
||||
nl_dump(p, "\n");
|
||||
for (n = 0; n < 24; n++) {
|
||||
dts = &trx->trx_slots[n];
|
||||
if (!dts->dts_valid)
|
||||
continue;
|
||||
slot_dump(dts, n, p);
|
||||
}
|
||||
}
|
||||
|
||||
static int nl_dect_transceiver_compare(struct nl_object *_a, struct nl_object *_b,
|
||||
uint32_t attrs, int flags)
|
||||
{
|
||||
struct nl_dect_transceiver *a = (struct nl_dect_transceiver *)_a;
|
||||
struct nl_dect_transceiver *b = (struct nl_dect_transceiver *)_b;
|
||||
int diff = 0;
|
||||
|
||||
#define TRX_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TRANSCEIVER_ATTR_##ATTR, a, b, EXPR)
|
||||
|
||||
diff |= TRX_DIFF(NAME, strcmp(a->trx_name, b->trx_name));
|
||||
diff |= TRX_DIFF(LINK, a->trx_link != b->trx_link);
|
||||
|
||||
#undef TRX_DIFF
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_transceiver *nl_dect_transceiver_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_transceiver *)nl_object_alloc(&nl_dect_transceiver_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_get(struct nl_dect_transceiver *trx)
|
||||
{
|
||||
nl_object_get((struct nl_object *)trx);
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_put(struct nl_dect_transceiver *trx)
|
||||
{
|
||||
nl_object_put((struct nl_object *)trx);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
void nl_dect_transceiver_set_name(struct nl_dect_transceiver *trx, const char *name)
|
||||
{
|
||||
trx->trx_name = strdup(name);
|
||||
trx->ce_mask |= TRANSCEIVER_ATTR_NAME;
|
||||
}
|
||||
|
||||
bool nl_dect_transceiver_test_name(const struct nl_dect_transceiver *trx)
|
||||
{
|
||||
return !!(trx->ce_mask & TRANSCEIVER_ATTR_NAME);
|
||||
}
|
||||
|
||||
const char *nl_dect_transceiver_get_name(const struct nl_dect_transceiver *trx)
|
||||
{
|
||||
return trx->trx_name;
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_set_type(struct nl_dect_transceiver *trx, const char *type)
|
||||
{
|
||||
trx->trx_type = strdup(type);
|
||||
trx->ce_mask |= TRANSCEIVER_ATTR_TYPE;
|
||||
}
|
||||
|
||||
bool nl_dect_transceiver_test_type(const struct nl_dect_transceiver *trx)
|
||||
{
|
||||
return !!(trx->ce_mask & TRANSCEIVER_ATTR_TYPE);
|
||||
}
|
||||
|
||||
const char *nl_dect_transceiver_get_type(const struct nl_dect_transceiver *trx)
|
||||
{
|
||||
return trx->trx_type;
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_set_features(struct nl_dect_transceiver *trx, uint32_t features)
|
||||
{
|
||||
trx->trx_features = features;
|
||||
trx->ce_mask |= TRANSCEIVER_ATTR_FEATURES;
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_set_index(struct nl_dect_transceiver *trx, int index)
|
||||
{
|
||||
trx->trx_index = index;
|
||||
trx->ce_mask |= TRANSCEIVER_ATTR_INDEX;
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_set_link(struct nl_dect_transceiver *trx, uint8_t link)
|
||||
{
|
||||
trx->trx_link = link;
|
||||
trx->ce_mask |= TRANSCEIVER_ATTR_LINK;
|
||||
}
|
||||
|
||||
void nl_dect_transceiver_set_band(struct nl_dect_transceiver *trx, uint8_t band)
|
||||
{
|
||||
trx->trx_band = band;
|
||||
trx->ce_mask |= TRANSCEIVER_ATTR_BAND;
|
||||
}
|
||||
|
||||
bool nl_dect_transceiver_test_band(const struct nl_dect_transceiver *trx)
|
||||
{
|
||||
return !!(trx->ce_mask & TRANSCEIVER_ATTR_BAND);
|
||||
}
|
||||
|
||||
uint8_t nl_dect_transceiver_get_band(const struct nl_dect_transceiver *trx)
|
||||
{
|
||||
return trx->trx_band;
|
||||
}
|
||||
|
||||
static struct trans_tbl trx_features[] = {
|
||||
__ADD(DECT_TRANSCEIVER_SLOW_HOPPING, slow-hopping)
|
||||
__ADD(DECT_TRANSCEIVER_PACKET_P64, p64)
|
||||
};
|
||||
|
||||
const char *nl_dect_transceiver_features2str(uint32_t features, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(features, buf, len, trx_features,
|
||||
ARRAY_SIZE(trx_features));
|
||||
}
|
||||
|
||||
static struct trans_tbl slot_states[] = {
|
||||
__ADD(DECT_SLOT_IDLE, idle)
|
||||
__ADD(DECT_SLOT_SCANNING, scanning)
|
||||
__ADD(DECT_SLOT_RX, rx)
|
||||
__ADD(DECT_SLOT_TX, tx)
|
||||
};
|
||||
|
||||
const char *nl_dect_slot_state2str(uint8_t state, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(state, buf, len, slot_states,
|
||||
ARRAY_SIZE(slot_states));
|
||||
}
|
||||
|
||||
uint8_t nl_dect_slot_str2state(const char *str)
|
||||
{
|
||||
return __str2type(str, slot_states, ARRAY_SIZE(slot_states));
|
||||
}
|
||||
|
||||
static struct trans_tbl slot_flags[] = {
|
||||
__ADD(DECT_SLOT_SYNC, sync)
|
||||
__ADD(DECT_SLOT_CIPHER, cipher)
|
||||
};
|
||||
|
||||
const char *nl_dect_slot_flags2str(uint32_t state, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(state, buf, len, slot_flags, ARRAY_SIZE(slot_flags));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_slot_str2flags(const char *str)
|
||||
{
|
||||
return __str2flags(str, slot_flags, ARRAY_SIZE(slot_flags));
|
||||
}
|
||||
|
||||
static struct trans_tbl packet_types[] = {
|
||||
__ADD(DECT_PACKET_P00, P00)
|
||||
__ADD(DECT_PACKET_P08, P08)
|
||||
__ADD(DECT_PACKET_P32, P32)
|
||||
__ADD(DECT_PACKET_P80, P80)
|
||||
__ADD(DECT_PACKET_P640j, P640j)
|
||||
__ADD(DECT_PACKET_P640j, P672j)
|
||||
};
|
||||
|
||||
const char *nl_dect_slot_packet2str(uint8_t pkt, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(pkt, buf, len, packet_types, ARRAY_SIZE(packet_types));
|
||||
}
|
||||
|
||||
uint8_t nl_dect_slot_str2packet(const char *str)
|
||||
{
|
||||
return __str2type(str, packet_types, ARRAY_SIZE(packet_types));
|
||||
}
|
||||
|
||||
int nl_dect_transceiver_build_msg(struct nl_msg *msg, struct nl_dect_transceiver *trx)
|
||||
{
|
||||
struct dectmsg dm = {
|
||||
.dm_index = trx->trx_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
if (trx->ce_mask & TRANSCEIVER_ATTR_NAME)
|
||||
NLA_PUT_STRING(msg, DECTA_TRANSCEIVER_NAME, trx->trx_name);
|
||||
if (trx->ce_mask & TRANSCEIVER_ATTR_LINK)
|
||||
NLA_PUT_U8(msg, DECTA_TRANSCEIVER_LINK, trx->trx_link);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
/** @cond SKIP */
|
||||
struct nl_object_ops nl_dect_transceiver_obj_ops = {
|
||||
.oo_name = "nl_dect/transceiver",
|
||||
.oo_size = sizeof(struct nl_dect_transceiver),
|
||||
.oo_free_data = transceiver_free_data,
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = transceiver_dump,
|
||||
},
|
||||
.oo_compare = nl_dect_transceiver_compare,
|
||||
.oo_id_attrs = TRANSCEIVER_ATTR_NAME,
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
|
@ -9,7 +9,7 @@
|
|||
* Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
|
||||
static const char *errmsg[NLE_MAX+1] = {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/utils.h>
|
||||
|
@ -124,7 +124,7 @@ errout:
|
|||
static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct flnl_result *res = (struct flnl_result *) obj;
|
||||
char buf[128];
|
||||
char buf[256];
|
||||
|
||||
nl_dump_line(p, "table %s prefixlen %u next-hop-selector %u\n",
|
||||
rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)),
|
||||
|
@ -133,7 +133,7 @@ static void result_dump_line(struct nl_object *obj, struct nl_dump_params *p)
|
|||
nl_rtntype2str(res->fr_type, buf, sizeof(buf)));
|
||||
nl_dump(p, "scope %s error %s (%d)\n",
|
||||
rtnl_scope2str(res->fr_scope, buf, sizeof(buf)),
|
||||
strerror(-res->fr_error), res->fr_error);
|
||||
strerror_r(-res->fr_error, buf, sizeof(buf)), res->fr_error);
|
||||
}
|
||||
|
||||
static void result_dump_details(struct nl_object *obj, struct nl_dump_params *p)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/utils.h>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-generic.h>
|
||||
#include <netlink-private/genl.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
|
@ -239,7 +239,7 @@ static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk,
|
|||
{
|
||||
struct nl_msg *msg;
|
||||
struct genl_family *ret;
|
||||
struct nl_cb *cb;
|
||||
struct nl_cb *cb, *orig;
|
||||
int rc;
|
||||
|
||||
ret = genl_family_alloc();
|
||||
|
@ -252,7 +252,12 @@ static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk,
|
|||
if (!msg)
|
||||
goto out_fam_free;
|
||||
|
||||
if (!(cb = nl_cb_clone(nl_socket_get_cb(sk))))
|
||||
if (!(orig = nl_socket_get_cb(sk)))
|
||||
goto out_msg_free;
|
||||
|
||||
cb = nl_cb_clone(orig);
|
||||
nl_cb_put(orig);
|
||||
if (!cb)
|
||||
goto out_msg_free;
|
||||
|
||||
if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-generic.h>
|
||||
#include <netlink-private/genl.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-generic.h>
|
||||
#include <netlink-private/genl.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/utils.h>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-generic.h>
|
||||
#include <netlink-private/genl.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/mngt.h>
|
||||
|
@ -295,6 +295,10 @@ static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
|
|||
family = genl_ctrl_search_by_name(ctrl, ops->o_name);
|
||||
if (family != NULL) {
|
||||
ops->o_id = genl_family_get_id(family);
|
||||
|
||||
if (ops->o_cache_ops)
|
||||
ops->o_cache_ops->co_msgtypes[0].mt_id = ops->o_id;
|
||||
|
||||
genl_family_put(family);
|
||||
|
||||
return 0;
|
||||
|
@ -302,6 +306,32 @@ static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
|
|||
|
||||
return -NLE_OBJ_NOTFOUND;
|
||||
}
|
||||
|
||||
int genl_resolve_id(struct genl_ops *ops)
|
||||
{
|
||||
struct nl_sock *sk;
|
||||
int err = 0;
|
||||
|
||||
/* Check if resolved already */
|
||||
if (ops->o_id != GENL_ID_GENERATE)
|
||||
return 0;
|
||||
|
||||
if (!ops->o_name)
|
||||
return -NLE_INVAL;
|
||||
|
||||
if (!(sk = nl_socket_alloc()))
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if ((err = genl_connect(sk)) < 0)
|
||||
goto errout_free;
|
||||
|
||||
err = genl_ops_resolve(sk, ops);
|
||||
|
||||
errout_free:
|
||||
nl_socket_free(sk);
|
||||
|
||||
return err;
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/msg.h>
|
||||
|
@ -79,9 +79,10 @@ static int nl_error_handler_verbose(struct sockaddr_nl *who,
|
|||
struct nlmsgerr *e, void *arg)
|
||||
{
|
||||
FILE *ofd = arg ? arg : stderr;
|
||||
char buf[256];
|
||||
|
||||
fprintf(ofd, "-- Error received: %s\n-- Original message: ",
|
||||
strerror(-e->error));
|
||||
strerror_r(-e->error, buf, sizeof(buf)));
|
||||
print_header_content(ofd, &e->msg);
|
||||
fprintf(ofd, "\n");
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* Copyright (c) 2012 Cumulus Networks, Inc
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/object.h>
|
||||
#include <netlink/hash.h>
|
||||
#include <netlink/hashtable.h>
|
||||
|
|
190
lib/msg.c
190
lib/msg.c
|
@ -26,7 +26,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/cache.h>
|
||||
|
@ -153,7 +153,7 @@ struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
|
|||
*/
|
||||
int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
|
||||
{
|
||||
return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
|
||||
return max_t(int, nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen), 0);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -767,7 +767,7 @@ static inline void dump_hex(FILE *ofd, char *start, int len, int prefix)
|
|||
int i, a, c, limit;
|
||||
char ascii[21] = {0};
|
||||
|
||||
limit = 18 - (prefix * 2);
|
||||
limit = 16 - (prefix * 2);
|
||||
prefix_line(ofd, prefix);
|
||||
fprintf(ofd, " ");
|
||||
|
||||
|
@ -777,7 +777,7 @@ static inline void dump_hex(FILE *ofd, char *start, int len, int prefix)
|
|||
fprintf(ofd, "%02x ", v);
|
||||
ascii[a++] = isprint(v) ? v : '.';
|
||||
|
||||
if (c == limit-1) {
|
||||
if (++c >= limit) {
|
||||
fprintf(ofd, "%s\n", ascii);
|
||||
if (i < (len - 1)) {
|
||||
prefix_line(ofd, prefix);
|
||||
|
@ -785,8 +785,7 @@ static inline void dump_hex(FILE *ofd, char *start, int len, int prefix)
|
|||
}
|
||||
a = c = 0;
|
||||
memset(ascii, 0, sizeof(ascii));
|
||||
} else
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (c != 0) {
|
||||
|
@ -816,14 +815,62 @@ static void print_hdr(FILE *ofd, struct nl_msg *msg)
|
|||
} else
|
||||
nl_nlmsgtype2str(nlh->nlmsg_type, buf, sizeof(buf));
|
||||
|
||||
fprintf(ofd, " .nlmsg_type = %d <%s>\n", nlh->nlmsg_type, buf);
|
||||
fprintf(ofd, " .nlmsg_flags = %d <%s>\n", nlh->nlmsg_flags,
|
||||
fprintf(ofd, " .type = %d <%s>\n", nlh->nlmsg_type, buf);
|
||||
fprintf(ofd, " .flags = %d <%s>\n", nlh->nlmsg_flags,
|
||||
nl_nlmsg_flags2str(nlh->nlmsg_flags, buf, sizeof(buf)));
|
||||
fprintf(ofd, " .nlmsg_seq = %d\n", nlh->nlmsg_seq);
|
||||
fprintf(ofd, " .nlmsg_pid = %d\n", nlh->nlmsg_pid);
|
||||
fprintf(ofd, " .seq = %d\n", nlh->nlmsg_seq);
|
||||
fprintf(ofd, " .port = %d\n", nlh->nlmsg_pid);
|
||||
|
||||
}
|
||||
|
||||
static void print_genl_hdr(FILE *ofd, void *start)
|
||||
{
|
||||
struct genlmsghdr *ghdr = start;
|
||||
|
||||
fprintf(ofd, " [GENERIC NETLINK HEADER] %zu octets\n", GENL_HDRLEN);
|
||||
fprintf(ofd, " .cmd = %u\n", ghdr->cmd);
|
||||
fprintf(ofd, " .version = %u\n", ghdr->version);
|
||||
fprintf(ofd, " .unused = %#x\n", ghdr->reserved);
|
||||
}
|
||||
|
||||
static void *print_genl_msg(struct nl_msg *msg, FILE *ofd, struct nlmsghdr *hdr,
|
||||
struct nl_cache_ops *ops, int *payloadlen)
|
||||
{
|
||||
void *data = nlmsg_data(hdr);
|
||||
|
||||
if (*payloadlen < GENL_HDRLEN)
|
||||
return data;
|
||||
|
||||
print_genl_hdr(ofd, data);
|
||||
|
||||
*payloadlen -= GENL_HDRLEN;
|
||||
data += GENL_HDRLEN;
|
||||
|
||||
if (ops) {
|
||||
int hdrsize = ops->co_hdrsize - GENL_HDRLEN;
|
||||
|
||||
if (hdrsize > 0) {
|
||||
if (*payloadlen < hdrsize)
|
||||
return data;
|
||||
|
||||
fprintf(ofd, " [HEADER] %d octets\n", hdrsize);
|
||||
dump_hex(ofd, data, hdrsize, 0);
|
||||
|
||||
*payloadlen -= hdrsize;
|
||||
data += hdrsize;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void dump_attr(FILE *ofd, struct nlattr *attr, int prefix)
|
||||
{
|
||||
int len = nla_len(attr);
|
||||
|
||||
dump_hex(ofd, nla_data(attr), len, prefix);
|
||||
}
|
||||
|
||||
static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen,
|
||||
int prefix)
|
||||
{
|
||||
|
@ -834,14 +881,18 @@ static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen,
|
|||
int padlen, alen = nla_len(nla);
|
||||
|
||||
prefix_line(ofd, prefix);
|
||||
fprintf(ofd, " [ATTR %02d%s] %d octets\n", nla_type(nla),
|
||||
nla->nla_type & NLA_F_NESTED ? " NESTED" : "",
|
||||
alen);
|
||||
|
||||
if (nla->nla_type & NLA_F_NESTED)
|
||||
if (nla->nla_type == 0)
|
||||
fprintf(ofd, " [ATTR PADDING] %d octets\n", alen);
|
||||
else
|
||||
fprintf(ofd, " [ATTR %02d%s] %d octets\n", nla_type(nla),
|
||||
nla_is_nested(nla) ? " NESTED" : "",
|
||||
alen);
|
||||
|
||||
if (nla_is_nested(nla))
|
||||
dump_attrs(ofd, nla_data(nla), alen, prefix+1);
|
||||
else
|
||||
dump_hex(ofd, nla_data(nla), alen, prefix);
|
||||
dump_attr(ofd, nla, prefix);
|
||||
|
||||
padlen = nla_padlen(alen);
|
||||
if (padlen > 0) {
|
||||
|
@ -859,6 +910,63 @@ static void dump_attrs(FILE *ofd, struct nlattr *attrs, int attrlen,
|
|||
}
|
||||
}
|
||||
|
||||
static void dump_error_msg(struct nl_msg *msg, FILE *ofd)
|
||||
{
|
||||
struct nlmsghdr *hdr = nlmsg_hdr(msg);
|
||||
struct nlmsgerr *err = nlmsg_data(hdr);
|
||||
|
||||
fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err));
|
||||
|
||||
if (nlmsg_len(hdr) >= sizeof(*err)) {
|
||||
char buf[256];
|
||||
struct nl_msg *errmsg;
|
||||
|
||||
fprintf(ofd, " .error = %d \"%s\"\n", err->error,
|
||||
strerror_r(-err->error, buf, sizeof(buf)));
|
||||
fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr));
|
||||
|
||||
errmsg = nlmsg_inherit(&err->msg);
|
||||
print_hdr(ofd, errmsg);
|
||||
nlmsg_free(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_msg(struct nl_msg *msg, FILE *ofd, struct nlmsghdr *hdr)
|
||||
{
|
||||
struct nl_cache_ops *ops;
|
||||
int payloadlen = nlmsg_len(hdr);
|
||||
int attrlen = 0;
|
||||
void *data;
|
||||
|
||||
data = nlmsg_data(hdr);
|
||||
ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg),
|
||||
hdr->nlmsg_type);
|
||||
if (ops) {
|
||||
attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
|
||||
payloadlen -= attrlen;
|
||||
}
|
||||
|
||||
if (msg->nm_protocol == NETLINK_GENERIC)
|
||||
data = print_genl_msg(msg, ofd, hdr, ops, &payloadlen);
|
||||
|
||||
if (payloadlen) {
|
||||
fprintf(ofd, " [PAYLOAD] %d octets\n", payloadlen);
|
||||
dump_hex(ofd, data, payloadlen, 0);
|
||||
}
|
||||
|
||||
if (attrlen) {
|
||||
struct nlattr *attrs;
|
||||
int attrlen;
|
||||
|
||||
attrs = nlmsg_attrdata(hdr, ops->co_hdrsize);
|
||||
attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
|
||||
dump_attrs(ofd, attrs, attrlen, 0);
|
||||
}
|
||||
|
||||
if (ops)
|
||||
nl_cache_ops_put(ops);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump message in human readable format to file descriptor
|
||||
* @arg msg Message to print
|
||||
|
@ -869,56 +977,18 @@ void nl_msg_dump(struct nl_msg *msg, FILE *ofd)
|
|||
struct nlmsghdr *hdr = nlmsg_hdr(msg);
|
||||
|
||||
fprintf(ofd,
|
||||
"-------------------------- BEGIN NETLINK MESSAGE "
|
||||
"---------------------------\n");
|
||||
"-------------------------- BEGIN NETLINK MESSAGE ---------------------------\n");
|
||||
|
||||
fprintf(ofd, " [HEADER] %zu octets\n", sizeof(struct nlmsghdr));
|
||||
fprintf(ofd, " [NETLINK HEADER] %zu octets\n", sizeof(struct nlmsghdr));
|
||||
print_hdr(ofd, msg);
|
||||
|
||||
if (hdr->nlmsg_type == NLMSG_ERROR &&
|
||||
hdr->nlmsg_len >= nlmsg_msg_size(sizeof(struct nlmsgerr))) {
|
||||
struct nl_msg *errmsg;
|
||||
struct nlmsgerr *err = nlmsg_data(hdr);
|
||||
|
||||
fprintf(ofd, " [ERRORMSG] %zu octets\n", sizeof(*err));
|
||||
fprintf(ofd, " .error = %d \"%s\"\n", err->error,
|
||||
strerror(-err->error));
|
||||
fprintf(ofd, " [ORIGINAL MESSAGE] %zu octets\n", sizeof(*hdr));
|
||||
|
||||
errmsg = nlmsg_inherit(&err->msg);
|
||||
print_hdr(ofd, errmsg);
|
||||
nlmsg_free(errmsg);
|
||||
} else if (nlmsg_len(hdr) > 0) {
|
||||
struct nl_cache_ops *ops;
|
||||
int payloadlen = nlmsg_len(hdr);
|
||||
int attrlen = 0;
|
||||
|
||||
ops = nl_cache_ops_associate_safe(nlmsg_get_proto(msg),
|
||||
hdr->nlmsg_type);
|
||||
if (ops) {
|
||||
attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
|
||||
payloadlen -= attrlen;
|
||||
}
|
||||
|
||||
fprintf(ofd, " [PAYLOAD] %d octets\n", payloadlen);
|
||||
dump_hex(ofd, nlmsg_data(hdr), payloadlen, 0);
|
||||
|
||||
if (attrlen) {
|
||||
struct nlattr *attrs;
|
||||
int attrlen;
|
||||
|
||||
attrs = nlmsg_attrdata(hdr, ops->co_hdrsize);
|
||||
attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
|
||||
dump_attrs(ofd, attrs, attrlen, 0);
|
||||
}
|
||||
|
||||
if (ops)
|
||||
nl_cache_ops_put(ops);
|
||||
}
|
||||
if (hdr->nlmsg_type == NLMSG_ERROR)
|
||||
dump_error_msg(msg, ofd);
|
||||
else if (nlmsg_len(hdr) > 0)
|
||||
print_msg(msg, ofd, hdr);
|
||||
|
||||
fprintf(ofd,
|
||||
"--------------------------- END NETLINK MESSAGE "
|
||||
"---------------------------\n");
|
||||
"--------------------------- END NETLINK MESSAGE ---------------------------\n");
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/ct.h>
|
||||
|
@ -174,15 +174,28 @@ static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
|||
if (tb[CTA_PROTO_DST_PORT])
|
||||
nfnl_ct_set_dst_port(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
|
||||
if (tb[CTA_PROTO_ICMP_ID])
|
||||
nfnl_ct_set_icmp_id(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
|
||||
if (tb[CTA_PROTO_ICMP_TYPE])
|
||||
nfnl_ct_set_icmp_type(ct, repl,
|
||||
|
||||
if (ct->ct_family == AF_INET) {
|
||||
if (tb[CTA_PROTO_ICMP_ID])
|
||||
nfnl_ct_set_icmp_id(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
|
||||
if (tb[CTA_PROTO_ICMP_TYPE])
|
||||
nfnl_ct_set_icmp_type(ct, repl,
|
||||
nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
|
||||
if (tb[CTA_PROTO_ICMP_CODE])
|
||||
nfnl_ct_set_icmp_code(ct, repl,
|
||||
if (tb[CTA_PROTO_ICMP_CODE])
|
||||
nfnl_ct_set_icmp_code(ct, repl,
|
||||
nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
|
||||
} else if (ct->ct_family == AF_INET6) {
|
||||
if (tb[CTA_PROTO_ICMPV6_ID])
|
||||
nfnl_ct_set_icmp_id(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_ICMPV6_ID])));
|
||||
if (tb[CTA_PROTO_ICMPV6_TYPE])
|
||||
nfnl_ct_set_icmp_type(ct, repl,
|
||||
nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]));
|
||||
if (tb[CTA_PROTO_ICMPV6_CODE])
|
||||
nfnl_ct_set_icmp_code(ct, repl,
|
||||
nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -426,17 +439,31 @@ static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
|
|||
NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
|
||||
htons(nfnl_ct_get_dst_port(ct, repl)));
|
||||
|
||||
if (nfnl_ct_test_icmp_id(ct, repl))
|
||||
NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
|
||||
htons(nfnl_ct_get_icmp_id(ct, repl)));
|
||||
if (family == AF_INET) {
|
||||
if (nfnl_ct_test_icmp_id(ct, repl))
|
||||
NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
|
||||
htons(nfnl_ct_get_icmp_id(ct, repl)));
|
||||
|
||||
if (nfnl_ct_test_icmp_type(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
|
||||
nfnl_ct_get_icmp_type(ct, repl));
|
||||
if (nfnl_ct_test_icmp_type(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
|
||||
nfnl_ct_get_icmp_type(ct, repl));
|
||||
|
||||
if (nfnl_ct_test_icmp_code(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
|
||||
nfnl_ct_get_icmp_code(ct, repl));
|
||||
if (nfnl_ct_test_icmp_code(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
|
||||
nfnl_ct_get_icmp_code(ct, repl));
|
||||
} else if (family == AF_INET6) {
|
||||
if (nfnl_ct_test_icmp_id(ct, repl))
|
||||
NLA_PUT_U16(msg, CTA_PROTO_ICMPV6_ID,
|
||||
htons(nfnl_ct_get_icmp_id(ct, repl)));
|
||||
|
||||
if (nfnl_ct_test_icmp_type(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_TYPE,
|
||||
nfnl_ct_get_icmp_type(ct, repl));
|
||||
|
||||
if (nfnl_ct_test_icmp_code(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_CODE,
|
||||
nfnl_ct_get_icmp_code(ct, repl));
|
||||
}
|
||||
|
||||
nla_nest_end(msg, proto);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <linux/netfilter/nf_conntrack_common.h>
|
||||
#include <linux/netfilter/nf_conntrack_tcp.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/ct.h>
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/exp.h>
|
||||
|
@ -70,7 +70,7 @@ static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
|
|||
};
|
||||
|
||||
static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = {
|
||||
[CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 },
|
||||
[CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 },
|
||||
[CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
|
@ -195,7 +195,7 @@ static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr)
|
|||
return err;
|
||||
|
||||
if (tb[CTA_EXPECT_NAT_DIR])
|
||||
nfnl_exp_set_nat_dir(exp, nla_get_u8(tb[CTA_EXPECT_NAT_DIR]));
|
||||
nfnl_exp_set_nat_dir(exp, nla_get_u32(tb[CTA_EXPECT_NAT_DIR]));
|
||||
|
||||
if (tb[CTA_EXPECT_NAT_TUPLE]) {
|
||||
err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]);
|
||||
|
@ -351,7 +351,11 @@ static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp,
|
|||
|
||||
int type = exp_get_tuple_attr(cta);
|
||||
|
||||
tuple = nla_nest_start(msg, cta);
|
||||
if (cta == CTA_EXPECT_NAT)
|
||||
tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE);
|
||||
else
|
||||
tuple = nla_nest_start(msg, cta);
|
||||
|
||||
if (!tuple)
|
||||
goto nla_put_failure;
|
||||
|
||||
|
@ -416,11 +420,11 @@ static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp)
|
|||
nat = nla_nest_start(msg, CTA_EXPECT_NAT);
|
||||
|
||||
if (nfnl_exp_test_nat_dir(exp)) {
|
||||
NLA_PUT_U8(msg, CTA_EXPECT_NAT_DIR,
|
||||
NLA_PUT_U32(msg, CTA_EXPECT_NAT_DIR,
|
||||
nfnl_exp_get_nat_dir(exp));
|
||||
}
|
||||
|
||||
if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT_TUPLE)) < 0)
|
||||
if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nat);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <linux/netfilter/nf_conntrack_common.h>
|
||||
#include <linux/netfilter/nf_conntrack_tcp.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/exp.h>
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <linux/netfilter/nfnetlink_log.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/log.h>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <linux/netfilter/nfnetlink_log.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/log_msg.h>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* Copyright (c) 2007 Secure Computing Corporation
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/netfilter.h>
|
||||
#include <netlink/netfilter/log_msg.h>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/log.h>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/netfilter.h>
|
||||
#include <linux/netfilter.h>
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <linux/netfilter/nfnetlink_queue.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/queue.h>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <linux/netfilter/nfnetlink_queue.h>
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/queue_msg.h>
|
||||
|
@ -163,12 +163,14 @@ errout:
|
|||
|
||||
/** @} */
|
||||
|
||||
struct nl_msg *nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg)
|
||||
static struct nl_msg *
|
||||
__nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg,
|
||||
uint8_t type)
|
||||
{
|
||||
struct nl_msg *nlmsg;
|
||||
struct nfqnl_msg_verdict_hdr verdict;
|
||||
|
||||
nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_VERDICT, 0,
|
||||
nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, type, 0,
|
||||
nfnl_queue_msg_get_family(msg),
|
||||
nfnl_queue_msg_get_group(msg));
|
||||
if (nlmsg == NULL)
|
||||
|
@ -191,6 +193,18 @@ nla_put_failure:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct nl_msg *
|
||||
nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg)
|
||||
{
|
||||
return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT);
|
||||
}
|
||||
|
||||
struct nl_msg *
|
||||
nfnl_queue_msg_build_verdict_batch(const struct nfnl_queue_msg *msg)
|
||||
{
|
||||
return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT_BATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message verdict/mark
|
||||
* @arg nlh netlink messsage header
|
||||
|
@ -214,6 +228,29 @@ int nfnl_queue_msg_send_verdict(struct nl_sock *nlh,
|
|||
return wait_for_ack(nlh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message batched verdict/mark
|
||||
* @arg nlh netlink messsage header
|
||||
* @arg msg queue msg
|
||||
* @return 0 on OK or error code
|
||||
*/
|
||||
int nfnl_queue_msg_send_verdict_batch(struct nl_sock *nlh,
|
||||
const struct nfnl_queue_msg *msg)
|
||||
{
|
||||
struct nl_msg *nlmsg;
|
||||
int err;
|
||||
|
||||
nlmsg = nfnl_queue_msg_build_verdict_batch(msg);
|
||||
if (nlmsg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_send_auto_complete(nlh, nlmsg);
|
||||
nlmsg_free(nlmsg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return wait_for_ack(nlh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message verdict including the payload
|
||||
* @arg nlh netlink messsage header
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/netfilter.h>
|
||||
#include <netlink/netfilter/queue_msg.h>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/queue.h>
|
||||
|
||||
|
|
9
lib/nl.c
9
lib/nl.c
|
@ -25,7 +25,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/handlers.h>
|
||||
|
@ -597,7 +597,7 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
|
|||
flags |= MSG_PEEK | MSG_TRUNC;
|
||||
|
||||
if (page_size == 0)
|
||||
page_size = getpagesize();
|
||||
page_size = getpagesize() * 4;
|
||||
|
||||
iov.iov_len = sk->s_bufsize ? : page_size;
|
||||
iov.iov_base = malloc(iov.iov_len);
|
||||
|
@ -627,11 +627,6 @@ retry:
|
|||
NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
|
||||
goto retry;
|
||||
}
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
NL_DBG(3, "recvmsg() returned EAGAIN||EWOULDBLOCK, aborting\n");
|
||||
retval = 0;
|
||||
goto abort;
|
||||
}
|
||||
retval = -nl_syserr2nlerr(errno);
|
||||
goto abort;
|
||||
}
|
||||
|
|
35
lib/object.c
35
lib/object.c
|
@ -27,7 +27,7 @@
|
|||
* ~~~~
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/object.h>
|
||||
|
@ -165,7 +165,12 @@ int nl_object_update(struct nl_object *dst, struct nl_object *src)
|
|||
*/
|
||||
void nl_object_free(struct nl_object *obj)
|
||||
{
|
||||
struct nl_object_ops *ops = obj_ops(obj);
|
||||
struct nl_object_ops *ops;
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
ops = obj_ops(obj);
|
||||
|
||||
if (obj->ce_refcnt > 0)
|
||||
NL_DBG(1, "Warning: Freeing object in use...\n");
|
||||
|
@ -316,8 +321,10 @@ int nl_object_identical(struct nl_object *a, struct nl_object *b)
|
|||
if (req_attrs_a != req_attrs_b)
|
||||
return 0;
|
||||
req_attrs = req_attrs_a;
|
||||
} else {
|
||||
} else if (ops->oo_id_attrs) {
|
||||
req_attrs = ops->oo_id_attrs;
|
||||
} else {
|
||||
req_attrs = 0xFFFFFFFF;
|
||||
}
|
||||
if (req_attrs == 0xFFFFFFFF)
|
||||
req_attrs = a->ce_mask & b->ce_mask;
|
||||
|
@ -506,6 +513,28 @@ struct nl_object_ops *nl_object_get_ops(const struct nl_object *obj)
|
|||
return obj->ce_ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return object id attribute mask
|
||||
* @arg obj object
|
||||
*
|
||||
* @return object id attribute mask
|
||||
*/
|
||||
uint32_t nl_object_get_id_attrs(struct nl_object *obj)
|
||||
{
|
||||
struct nl_object_ops *ops = obj_ops(obj);
|
||||
uint32_t id_attrs;
|
||||
|
||||
if (!ops)
|
||||
return 0;
|
||||
|
||||
if (ops->oo_id_attrs_get)
|
||||
id_attrs = ops->oo_id_attrs_get(obj);
|
||||
else
|
||||
id_attrs = ops->oo_id_attrs;
|
||||
|
||||
return id_attrs;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/rtnl.h>
|
||||
#include <netlink/route/addr.h>
|
||||
|
@ -199,8 +199,9 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
|||
struct rtnl_addr *addr;
|
||||
struct ifaddrmsg *ifa;
|
||||
struct nlattr *tb[IFA_MAX+1];
|
||||
int err, peer_prefix = 0, family;
|
||||
int err, family;
|
||||
struct nl_cache *link_cache;
|
||||
struct nl_addr *plen_addr = NULL;
|
||||
|
||||
addr = rtnl_addr_alloc();
|
||||
if (!addr)
|
||||
|
@ -244,6 +245,7 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
|||
if (!addr->a_local)
|
||||
goto errout_nomem;
|
||||
addr->ce_mask |= ADDR_ATTR_LOCAL;
|
||||
plen_addr = addr->a_local;
|
||||
}
|
||||
|
||||
if (tb[IFA_ADDRESS]) {
|
||||
|
@ -263,12 +265,13 @@ static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
|||
} else {
|
||||
addr->a_peer = a;
|
||||
addr->ce_mask |= ADDR_ATTR_PEER;
|
||||
peer_prefix = 1;
|
||||
}
|
||||
|
||||
plen_addr = a;
|
||||
}
|
||||
|
||||
nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local,
|
||||
addr->a_prefixlen);
|
||||
if (plen_addr)
|
||||
nl_addr_set_prefixlen(plen_addr, addr->a_prefixlen);
|
||||
|
||||
/* IPv4 only */
|
||||
if (tb[IFA_BROADCAST]) {
|
||||
|
@ -814,10 +817,39 @@ int rtnl_addr_get_family(struct rtnl_addr *addr)
|
|||
return addr->a_family;
|
||||
}
|
||||
|
||||
void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix)
|
||||
/**
|
||||
* Set the prefix length / netmask
|
||||
* @arg addr Address
|
||||
* @arg prefixlen Length of prefix (netmask)
|
||||
*
|
||||
* Modifies the length of the prefix. If the address object contains a peer
|
||||
* address the prefix length will apply to it, otherwise the prefix length
|
||||
* will apply to the local address of the address.
|
||||
*
|
||||
* If the address object contains a peer or local address the corresponding
|
||||
* `struct nl_addr` will be updated with the new prefix length.
|
||||
*
|
||||
* @note Specifying a length of 0 will remove the prefix length alltogether.
|
||||
*
|
||||
* @see rtnl_addr_get_prefixlen()
|
||||
*/
|
||||
void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen)
|
||||
{
|
||||
addr->a_prefixlen = prefix;
|
||||
addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
|
||||
addr->a_prefixlen = prefixlen;
|
||||
|
||||
if (prefixlen)
|
||||
addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
|
||||
else
|
||||
addr->ce_mask &= ~ADDR_ATTR_PREFIXLEN;
|
||||
|
||||
/*
|
||||
* The prefix length always applies to the peer address if
|
||||
* a peer address is present.
|
||||
*/
|
||||
if (addr->a_peer)
|
||||
nl_addr_set_prefixlen(addr->a_peer, prefixlen);
|
||||
else if (addr->a_local)
|
||||
nl_addr_set_prefixlen(addr->a_local, prefixlen);
|
||||
}
|
||||
|
||||
int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -15,10 +15,10 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/tc-api.h>
|
||||
#include <netlink-private/route/tc-api.h>
|
||||
#include <netlink/route/class.h>
|
||||
#include <netlink/route/qdisc.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -15,8 +15,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/route/tc.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -15,11 +15,11 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/route/tc-api.h>
|
||||
#include <netlink-private/route/tc-api.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2008-2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -22,10 +22,10 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/tc-api.h>
|
||||
#include <netlink-private/route/tc-api.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
#include <netlink/route/cls/basic.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2009-2011 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2009-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,12 +16,12 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/route/tc-api.h>
|
||||
#include <netlink-private/route/tc-api.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
#include <netlink/route/cls/cgroup.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
#include <linux/tc_ematch/tc_em_cmp.h>
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
#include <netlink/route/cls/ematch/meta.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
#include <netlink/route/cls/ematch/nbyte.h>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
|
||||
* Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink-tc.h>
|
||||
#include <netlink-private/netlink.h>
|
||||
#include <netlink-private/tc.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/route/cls/ematch.h>
|
||||
#include <netlink/route/cls/ematch/text.h>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue