dect
/
libnl
Archived
13
0
Fork 0

Compare commits

...

134 Commits

Author SHA1 Message Date
Patrick McHardy 6ae22c1b39 Merge /home/kaber/src/repos/libnl.git 2013-06-28 18:11:40 +02:00
Thomas Graf 01cfa9c1db msg: Avoid returning a negative value for nlmsg_attrlen()
If a hdrlen was provided that was greather than the actual
message length, a negative attributes length would result.

This was typically happening for RTM_GETLINK requests where
we can get a away with a 4 bytes header on the request side
but the response would use a 16 bytes header.

This resulted in strange -8 bytes leftover debug messages.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-06-27 18:29:17 +02:00
Holger Eitzenberger d612180cda netfilter/queue: introduce nfnl_queue_msg_send_verdict_batch()
The batched verdict implicitely ACKs all queue packet IDs up to the
one send back, which reduces the number of verdict messages send
to the kernel.

Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-06-27 01:16:15 +02:00
Holger Eitzenberger 34a96ba5c2 netfilter/queue: generalize nfnl_queue_msg_build_verdict()
Generalize netfilter/queue to allow sending batched verdicts
later.

Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-06-27 01:15:34 +02:00
Andrew Collins 53ac502a2b Handle -NLE_AGAIN in nl_cache_mngr_data_ready
Since commit "nl: Return -NLE_AGAIN if non-blocking socket would block",
nl_cache_mngr_data_ready returns -NLE_AGAIN to callers on non-blocking sockets.
Change it to consider -NLE_AGAIN as a non-error case as it is expected behavior
with the nl_recv changes.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-06-27 01:12:36 +02:00
Andrew Collins 87bbfb6b12 Default to comparing all attributes if no oo_id_attrs defined
Since commit: "cache pickup: Avoid duplicates during cache pickup",
nfnl_ct_alloc_cache no longer properly fills the cache, as it doesn't
define oo_id_attrs so all items are considered duplicates.

Instead of adding a ~0 oo_id_attrs to ct_obj, this changes
nl_object_identical to default to comparing all attributes if
neither oo_id_attrs_get or oo_id_attrs are provided.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-06-27 01:12:28 +02:00
Thomas Graf c1de0f3129 Merge branch 'master' of https://github.com/michael-dev/libnl 2013-05-24 14:37:02 +02:00
Michael Braun c76393e203 Add macvlan support
This patch add support for kernel macvlan interfaces.

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
2013-05-16 17:04:08 +02:00
Thomas Graf c4d846f239 3.2.22 release 2013-05-14 14:09:07 +02:00
Thomas Graf 807fddc4cd nl: Increase receive buffer size to 4 pages
Assuming that the kernel does not send more than a page is no longer valid,
and enabling MSG_PEEK'ing by default to figure out the exact message buffer
requirements can have a negative influence on the performance of existing
applications. Bumping the default receive buffer space to 4 pages seems
a sane default.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-05-08 13:52:27 +02:00
Nathan Lynch 8983fa9914 rtnl_link_af_unregister: fix locking
rtnl_link_af_unregister() attempts to write-lock info_lock twice
instead of releasing it before returning.  It also will return with
info_lock write-locked if passed a NULL ops.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-05-08 13:48:24 +02:00
Thomas Graf 183052d047 Prepare for 3.2.22-rc1 release
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 12:52:26 +02:00
Thomas Graf ed1f4cba2c tests: Include util.h in dist
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 12:51:58 +02:00
Thomas Graf 4e9aa6a9a6 tests: Add basic attribute unit tests
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 12:31:52 +02:00
Thomas Graf ffc0ee3540 configure: Convert ENABLE_UNIT_TESTS to a mere AM conditional
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 11:41:15 +02:00
Emmanuel Thierry 979ea335b0 Wrong calcultation in nla_reserve
There seams to be an error in the calculation of needed space for the message in nla_reserve. The current size of the message is counted twice: Once in NLMSG_ALIGN, once in the condition below.
This causes nla_put_* calls to be rejected if the allocation size of the message has been strictly calculated by the caller.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 10:34:50 +02:00
Thomas Graf 3a6d256da5 attr: Fix typo in nla_is_nested()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 10:33:52 +02:00
Thomas Graf 37f788f391 Merge branch 'fixes' of https://github.com/socketpair/libnl 2013-04-28 10:25:47 +02:00
Thomas Graf c07a6a30c2 attr: nla_is_nested() must access nla_type directly
Can't used nla_type() as it applies NLA_TYPE_MASK first

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-28 10:23:28 +02:00
Коренберг Марк (дома) 33396faca5 Fix leak of cb if nl_socket_alloc_cb() failed to allocate socket
- each *_get() should have corresponding *_put(). That rule was broken in nl_socket_alloc()
- Also, check if cb is NULL in nl_socket_set_cb (calls BUG())
2013-04-28 02:08:50 +06:00
Thomas Graf ead4cdeb99 tests: Make unit test building optional
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-27 14:27:10 +02:00
Коренберг Марк (дома) 59db7fb35b dump_attrs: "NLA_F_NESTED" => nla_is_nested(nla) 2013-04-26 23:50:54 +06:00
Thomas Graf d505165f2b autoconf: Use PKG_CHECK_MODULES() instead of AM_PATH_CHECK()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-05 10:44:06 +02:00
Thomas Graf d3cf89ea94 addr: only translate more recent address family names and ARP types if defined
Helps making libnl compilable with older kernel headers

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-05 10:37:55 +02:00
Emmanuel Roullit ea436445ad Perform no operation on nl_object_free(NULL).
Passing a NULL pointer would cause a NULL pointer dereference within
nl_object_free().
Returning early on NULL pointer is the behavior free(3) and other
nl*_free() functions.

Signed-off-by: Emmanuel Roullit <emmanuel.roullit@gmail.com>
2013-04-03 21:17:33 +02:00
Thomas Graf 56eb22fa74 msg: Pretty print generic netlink header in nl_msg_dump()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-02 23:13:15 +02:00
Thomas Graf 375a6294a4 nl: Return -NLE_AGAIN if non-blocking socket would block
Previously 0 was returned which gave the caller no chance of detecting
when a non-blocking socket would block. If a caller intends to never
see an error message it should utilize poll()/select() to only read
when the socket has pending data or information.

Reported-by: Holger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-02 11:58:18 +02:00
Thomas Graf df66b0f267 genl: Fix cb reference leak in genl_ctrl_probe_by_name()
nl_socket_get_cb() bumps the cb reference counter

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-02 11:51:53 +02:00
Holger Eitzenberger 18152ca916 ct: add ICMPv6 type,code and ID
Add ICMPv6 type, code and ID (if set) by using the already available
conntrack atttributes.

Currently the ICMPv6 conntrack objects in libnl are without type, code
and ID.  This e. g. is the output of nl_object_dump() without the patch:

  ipv6-icmp ::1 <-> ::1
  id 0xdd0871f0 family inet6 timeout 30s <NOREPLY,SNAT_INIT,DNAT_INIT>

The attached patch tries to solve that.  It then looks like

  ipv6-icmp ::1 <-> ::1 icmp type 128 code 0 id 28253
  id 0xdf3a11f0 family inet6 timeout 30s <SNAT_INIT,DNAT_INIT>

It is the 'small' approach, because it reuses the existing ICMP
attributes of the conntrack object (currently only used for IPv4).
This way I can avoid to add new _icmp6_get_, _icmp6_set_ and
_icmp6_test_ functions.

Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-02 11:42:59 +02:00
Thomas Graf ff567100d6 nl: Print file:line:func in debugging messages and provide --disable-debug to disable debugging
Compiling libnl with --disable-debug will result in the ignorance
of the 'NLDBG' environment variable.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-02 11:39:30 +02:00
Thomas Graf f9241d57fe cache: Improve debugging messages of cache operations
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-01 11:46:30 +02:00
Patrick McHardy d2b5cbd88a Merge git://git.infradead.org/users/tgr/libnl
Signed-off-by: Patrick McHardy <kaber@trash.net>

Conflicts:
	include/linux/netlink.h
	lib/Makefile.am
	lib/error.c
	libnl-3.0.pc.in
	src/Makefile.am
2013-04-01 11:44:59 +02:00
Thomas Graf ad545f2854 genl: Update mt_id of cache ops when resolving genl id
The cache layer uses the message type array stored in the cache
ops to lookup which cache a message belongs to. Update to the
the message array with the resolved generic netlink id to make
it compatible with the caching API.

Allows to use nl_cache_refill() and others for generic netlink
based caches with dynamic generic netlink ids.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-01 11:21:22 +02:00
Thomas Graf aad041c46f genl: Provide internal function to resolve name to id
Like genl_ops_resolve() but uses its own socket.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-04-01 11:14:49 +02:00
roopa 6c9be5a316 nl-route-add: Add NLM_F_EXCL flag to route add
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-24 10:58:18 +01:00
Tony Cheneau 23e26e9e05 Remove rtnl_link_free() declaration from the header file.
Reason: there is no rtnl_link_free() definition anywhere in the code.

Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-17 17:31:53 +01:00
Tony Cheneau 4db11517fd Remove superfluous declaration of rtnl_route_put()
rtnl_route_put() is declared twice in the same header file

Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-17 17:31:45 +01:00
Thomas Graf b39c9f7a53 rtnl-addr: Fix invalid call to nl_addr_set_prefixlen() if neither local or peer address are present
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 18:57:15 +01:00
Thomas Graf 549d26dc87 rtnl-addr: Inherit prefix length to nl_addr objs in rtnl_addr_set_prefixlen()
Previously if using rtnl_addr_set_prefixlen() the new prefix length
was not forwarded to the corresponding 'struct nl_addr' objects
associated with address already and thus the comparison function
would fail.

This patch also clears the internal ADDR_ATTR_PREFIXLEN flag if
the prefix length has been reset.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 18:52:17 +01:00
Thomas Graf e09e7f1035 tests: Add check based unit test system
Introduces new unit tests based on `check`. Each subsystem/module can
have its own unit tests in tests/check-<name>.c that will be linked
together in tests/check-all.c.

Running 'make check' will compile and run the unit tests automatically.

A reference unit test implementation has been done for the abstract
address module.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 16:25:17 +01:00
Thomas Graf 780a0423dc addr: Update to latest address familiy definition for translation
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 16:09:19 +01:00
Thomas Graf 88527534ba addr: improve API reference documentation for nl_addr_*()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 15:37:46 +01:00
Thomas Graf f0f33c394b addr: Reset unused portion of binary address in nl_addr_set_binary_addr()
memset() the binary address before overwriting it with new data
to avoid leaving around old portions of the address.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 14:41:12 +01:00
Thomas Graf f72bfc7220 msg: Pretty print error message header even if incomplete
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 12:46:14 +01:00
Thomas Graf c608b4d151 msg: Pretty print padding attributes in nl_msg_dump()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 12:46:12 +01:00
Thomas Graf 1395c69901 attr: Warn application if nla_parse() observes same attribute multiple times
Use a debugging message to warn applications if an attribute is
found multiple times in the same message. It is perfectly valid
to rely on this behaviour but it is likely to indicate a bug.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 12:46:09 +01:00
Thomas Graf 64315f731c attr: No longer warn about attribute of type 0
The kernel will start using type 0 attributes for padding purposes.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 12:46:06 +01:00
Thomas Graf 60b370de8c attr: Do not enforce maximum length for NLA_FLAG attributes
Although wasteful, NLA_FLAG with non zero payload cause no harm
and should thus not be rejected.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 12:46:04 +01:00
Thomas Graf 9e6cdbf6fc attr: Add nla_nest_cancel() to remove partially added nested attributes
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-03-14 12:46:01 +01:00
Thomas Graf 4d7680c19c Use thread-safe strerror_r() instead of strerror()
We have only ever fed well known error codes into strerror()
so it should never have been a problem though.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-28 13:07:04 +01:00
roopa ded20487fd link: Fix rtnl_link_af_data_compare return value
This patch fixes a bug where because of the af_ops check
being first in the function, we were returning ~0 if af_ops
was null even if both objects really did not have af_data
and we should be returning 0.

Its better to have the af_data present check before anything else.

So, Rearranged some of the code in rtnl_link_af_data_compare.
Changes include:
	- Do the attribute present check before anything else
	- If ao_compare op not present, return ~0

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Reviewed-by: Wilson Kok <wkok@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-24 17:11:36 +01:00
roopa 8f151fadda link: move af_data_compare to the end
In the current code if rtnl_link_af_data_compare returns value > 0
we mark PROTINFO attribute in the diff mask and return without
comparing flags.

This patch makes af_data to be the last thing we compare.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Reviewed-by: Wilson Kok <wkok@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-24 17:06:54 +01:00
Thomas Graf 1ecf98a23e bond: Provide rtnl_link_bond_alloc()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-14 12:48:00 +01:00
Thomas Graf ee4122a12e vlan: Provide rtnl_link_vlan_alloc()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-14 12:42:22 +01:00
Thomas Graf bb9911b5a3 netlink: Forward declare frequent libnl types to ease inclusion deps
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-14 12:37:10 +01:00
Thomas Graf 5a5aa73158 bridge: Provide rtnl_link_bridge_alloc()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-14 12:34:57 +01:00
Thomas Graf fd19dae352 bridge: Support the new bridging attributes
This provides support for the new bridging attributes provided
in IFLA_PROTINFO while maintaining backwards compatibility
with older kernels.

A set of new API functions are exported to access the bridging
information. rtnl_link_bridge_has_ext_info() can be used to
check whether a bridge object has been constructed based on
the newly available attributes or the old message format.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-07 11:39:27 +01:00
Thomas Graf 9f8548b551 attr: Provide nla_is_nested() function
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-05 22:31:31 +01:00
Thomas Graf 8026fe2e3a link: Free and realloc af specific data upon rtnl_link_set_family()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-05 13:52:22 +01:00
Thomas Graf 4a793a4235 link: Hold af_ops reference for each AF_SPEC block during lifetime of link object
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-05 13:46:42 +01:00
Thomas Graf e5767684a6 link: Modify link policy on the stack
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-05 13:21:10 +01:00
Thomas Graf 2d36371aa1 link: Keep reference to af_ops during lifetime of link object
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-05 13:18:25 +01:00
Thomas Graf 8b8e26b333 link: Fix af_ops leak on ENOMEM
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-05 13:03:02 +01:00
Holger Dengler 506020ae99 can: Fix nested message creation in can_put_attrs()
Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Holger Dengler <dengler@linutronix.de>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-01 12:24:37 +01:00
Thomas Graf 1c24480180 can: Include "linux/can/netlink.h" in the distribution
Needed to compile if local kernel headers are outdated.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-01 10:51:33 +01:00
Thomas Graf 8571f58f23 neigh: Remove check for AF_UNSPEC in rtnl_neigh_get()
This check was introduces to not accidently return AF_BRIDGE objects
to unaware API users as they do differ in structure. However, such
objects are only available if explicitely requests using the
NL_CACHE_AF_ITER flag or by using arg1 == AF_BRIDGE for the cache.

Therefore remove this check and allow rtnl_neigh_get() to be used to
fetch any neighbor object of a cache.

Reported-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-01 10:45:01 +01:00
Thomas Graf 2005c2ecac cache: Make NL_ACT_* and nl_cache_ops_(get|put)() available
Move NL_ACT_* definition and the functions nl_cache_ops_get()
and nl_cache_ops_put() into the public facing API. They can
be considered stable.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-02-01 10:21:58 +01:00
Thomas Graf 87458abbd0 Fix mask calculation in nl_addr_cmp_prefix()
Signed-off-by: Malte Langermann <mlangermann@radiodata.biz>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-31 10:59:10 +01:00
Thomas Graf 73cb5f57ba Merge branch 'nattuple' of https://github.com/rmfought/libnl 2013-01-31 10:47:58 +01:00
roopa b06c23a9dd link cache: remove AF_UNSPEC check in rtnl_get_link and rtnl_get_link_by_name
This patch reverts back the AF_UNSPEC check introduced by AF_BRIDGE
changes at http://lists.infradead.org/pipermail/libnl/2012-November/000796.html

After the addition of AF_BRIDGE support, link cache can now contain objects of
type AF_BRIDGE. To make sure existing api's did not return AF_BRIDGE objects
and surprise existing callers, I introduced the check for AF_UNSPEC.

But from what Andy Wang reported, rtnl_link_get_by_name returns the first
link object with matching ifindex and that could have not only been AF_UNSPEC
but also of family AF_INET6. And his app always got an AF_INET6 object prior
to the patch that introduced the AF_UNSPEC check.

I could just add AF_INET6 family check along with AF_UNSPEC in the apis and that
should work well.

But thinking about it some more, removing the AF_UNSPEC change seems to be safer at
this point. That way this api will retain its semantics and return the first object
with matching ifindex. It could be of any supported family. The user will know if the
cache contains bridge objects, because they are available only with the cache flag
NL_CACHE_AF_ITER. Besides, if new users want to search for a specific object,
nl_cache_find is a better option.

Reported-by: Andy Wang <Andy.Wang@watchguard.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-31 10:09:12 +01:00
Rich Fought 4f088d38ae netfilter: correct error in construction of NAT tuple 2013-01-29 15:10:01 -08:00
Benedikt Spranger 6cc5fdc0e9 can: add helper function to get CAN bus state
Add a helper function to get the CAN bus state.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
2013-01-25 19:51:33 +01:00
Thomas Graf 4cb375a812 Merge pull request #29 from rmfought/natdir32
netfilter: expectation NAT direction is 32 bit attribute
2013-01-24 08:32:35 -08:00
Rich Fought 87244f739c netfilter: keep 8-bit API for 32-bit NAT dir attribute 2013-01-24 08:18:35 -08:00
Thomas Graf 83c762d7cf 3.2.21 release 2013-01-24 15:00:26 +01:00
Thomas Graf b6afd0bf1a Provide better help text when bumping CURRENT,AGE,REVISION
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-24 14:34:22 +01:00
Thomas Graf 776cde0a10 Remove obsolete warning from <netlink/object-api.h> as it breaks NM build
NM uses -Werror=cpp thus the build breaks if we emit #warning upon
inclusion of <netlink/object-api.h>

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-24 14:29:18 +01:00
Thomas Graf c4f803366e Fix build warnings of nl-(qdisc|class|cls)-add
Reported-by: Jeroen Roovers <jer@gentoo.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-24 14:10:33 +01:00
Thomas Graf c6abb44e38 Fix test-cache-mngr test
Needs to include <netlink-private/cache-api.h>

Reported-by: Jeroen Roovers <jer@gentoo.org>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-24 14:05:48 +01:00
Thomas Graf 1b9de9a49d Provide compat headers for removed private API
Some projects seem to have mistakenly included the private
API headers without actually needing them.

Provide dummy headers referring to the real headers to
provide backwards compatibility.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-24 14:03:52 +01:00
Thomas Graf 9680f910f4 Move private header files to <netlink-private/*>
This clarifies the seperation between public and private
header files.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-24 13:51:24 +01:00
Rich Fought 56352ab9f6 netfilter: expectation NAT direction is 32 bit attribute 2013-01-23 13:59:27 -08:00
Jiri Pirko 1419851eb4 fix includes after removing some headers
commit f20bbe1f07
Author: Thomas Graf <tgraf@suug.ch>
Date:   Tue Jan 22 19:10:38 2013 +0100

    No longer install module API headers

This commit causes a regression so no app using libnl can be compiled
against it. This patch fixes it by removing includes of no-longe
existing headers.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-23 13:37:29 +01:00
Thomas Graf 26e22d887e 3.2.20 release 2013-01-23 11:02:54 +01:00
roopa 1481f97d36 route cache: This patch adds route priority to route object oo_id_attrs
The kernel allows multiple entries in the main table which differ in the
priority value. In libnl currently, since priority is not part of the base
netlink route message, it is not used as part of the key. This patch
includes priority in the key/oo_id_attrs and defaults the value to zero
for messages where priority is not included.

One point to note is that the actual selection of route from multiple
options is done implicitly in the kernel by storing the routes in sort
priority order, but there is no explicit communication to a client of libnl
of that.

Signed-off-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-23 11:02:51 +01:00
Thomas Graf 2b96c3381d Remove obsolete release notes at end of configure
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-23 11:02:49 +01:00
Thomas Graf f20bbe1f07 No longer install module API headers
Various header files providing an API to implement own cache and
object types or implement link types have been available in the
past. Their API is marked unstable in the documentation and nobody
is using them so far.

Technically they have been causing ABI breakages in at least two
3.2.x releases. In order to avoid future accidental breakage, no
longer install these and require module developers to clone the
git tree and build modules off the git tree directly to make sure
that the API is unstable at this point.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-23 11:02:44 +01:00
Thomas Graf 7559157f2d Undo soname bump
The soname was bumped before 3.2.18 was released to reflect
an ABI change in the cache and object API.

This caused a discussion with various distribution maintainers
involved as it prevented them from including the release in
their stable branches. This is especially unfortunate as the
corresponding API is unused outside of libnl as of now.

For this reason, I have decided to undo the soname bump and
instead remove the corresponding header files from the list of
installable headers and thus remove them from the public API.

This is a API break technically but since nobody is using
them it should not matter. If you are in fact using any of the
*-api.h headers please let me know and we are most likely to
start a new development branch.

If your application linked against 3.2.18 or 3.2.19 you will need
to relink if you want it to use >= 3.2.20.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-23 11:02:37 +01:00
Thomas Graf 5291af6fb5 link: fix reference leak in rtnl_link_af_data_compare()
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-18 14:49:33 +01:00
roopa 5c3f2f015a link: Add af data compare to link objects
Today the link compare function does not
compare af data of a link. We have found a
need for this to get approriate change callbacks
when af_data of a link changes.

This patch adds support to compare af_data
to link_compare function. This patch today
only adds support to compare af_data set by
PROTINFO attributes. It can be extended to
support compares of af_data set by AF_SPEC
attributes

It has been tested for AF_BRIDGE objects.
In case of AF_BRIDGE objects, this helps with
bridge port change notification callbacks.

Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-18 14:42:18 +01:00
roopa 99399ca9c0 Add new rtnl_link_af_data_compare function to compare af_data
This patch adds a new api rtnl_linl_af_data_compare to
compare link af_data

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-18 14:41:58 +01:00
Thomas Graf 6b4a2cb634 3.2.19 release 2013-01-17 14:02:35 +01:00
roopa 310ec86b39 Add ao_compare support to bridge family af_data
This patch adds support for ao_compare operation
to bridge link af data operations.

Adds field ce_mask to struct bridge_data to work
with the ATTR attributes. I can submit separate
patches to introduce mask field to ATTR macros.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-12 11:38:35 +01:00
roopa 09213ee5ee link af ops: Add new ao_compare op to compare link af_data
This patch adds new operation to compare link af_data.
ao_compare is similar to object oo_compare operation.
This op can be used 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.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-12 11:37:32 +01:00
roopa b1ebda9241 cache: Add new nl_cache_find api
This patch adds new cache find api

nl_cache_find api was suggested by Thomas.

Unlike nl_cache_search, this patch uses
nl_object_match_filter() to look for an
object match.

Am not sure this matches what was decided
on the list few weeks back. I will be happy
to make any changes.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-11 13:52:50 +01:00
Flavio Leitner 3540e44b15 link: add carrier support
Signed-off-by: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2013-01-11 13:44:47 +01:00
Patrick McHardy 94cd080452 dect: transceiver: resync kernel header for P64 definitions
Signed-off-by: Patrick McHardy <kaber@trash.net>
2012-02-09 20:41:07 +01:00
Patrick McHardy c2fdebea42 libnl: resync netlink.h with kernel
Signed-off-by: Patrick McHardy <kaber@trash.net>
2012-02-09 20:37:20 +01:00
Patrick McHardy 4cec8d361c packet 2011-07-06 04:39:35 +02:00
Patrick McHardy 68915b1292 dect: add support for MBC statistics
Signed-off-by: Patrick McHardy <kaber@trash.net>
2011-06-18 06:04:58 +02:00
Patrick McHardy 450d03b24b headers: resync netlink.h
Signed-off-by: Patrick McHardy <kaber@trash.net>
2011-06-18 06:04:51 +02:00
Patrick McHardy 29abe5d86f dect: support transceiver features attribute
Signed-off-by: Patrick McHardy <kaber@trash.net>
2011-04-12 02:54:23 +02:00
Patrick McHardy 93a9e4dc6a Merge git://git.kernel.org/pub/scm/libs/netlink/libnl 2011-03-21 19:11:19 +01:00
Erik Tews 3c6622aeb8 dect: llme: implemented setting the multiframe number
Patch from Eric: "Implemented setting the multiframe number using
nl_dect_llme_mac_info_set_mfn".

Signed-off-by: Patrick McHardy <kaber@trash.net>
2011-03-19 02:26:40 +01:00
Patrick McHardy 2a591b7b2b Merge 192.168.0.100:/repos/git/libnl
Conflicts:
	include/netlink-types.h
	lib/Makefile.am
	src/.gitignore
	src/Makefile.am

Signed-off-by: Patrick McHardy <kaber@trash.net>
2011-03-19 00:47:14 +01:00
Patrick McHardy 56a447dffd dect: llme: add nl_dect_llme_mac_info_test_pari() function
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-11-14 19:34:38 +01:00
Patrick McHardy ac50c84f8c Merge branch 'master' of /repos/git/libnl
Conflicts:
	lib/Makefile.am
	src/Makefile.am

Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-10-15 04:16:08 +02:00
Patrick McHardy 2dc8bc1921 dect: show Z-CRC errors in transceiver statistics
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-09-10 16:49:00 +02:00
Patrick McHardy 432a1a31f2 unbind 2010-09-02 02:08:59 +02:00
Patrick McHardy edaf9cac24 dect: support monitor mode
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-08-19 18:41:56 +02:00
Patrick McHardy 2080dce45e package config: include nl-cli in Libs
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-08-19 18:39:38 +02:00
Patrick McHardy ac263675d1 dect: support DECT_LLME_MAC_RFP_PRELOAD
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-08-04 22:48:25 +02:00
Patrick McHardy a9886abe70 dect: rename DECT_HLC_ACCESS_RIGHT_REQUESTS to DECT_HLC_ACCESS_RIGHTS_REQUESTS
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-08-04 22:48:23 +02:00
Patrick McHardy 6ff91c4799 Merge branch 'master' of x2:/home/dect/git/libnl 2010-05-20 18:14:52 +02:00
Patrick McHardy 47a4c5a4c0 Merge branch 'master' of /repos/git/libnl 2010-05-20 17:20:12 +02:00
Patrick McHardy c17d47977e Merge branch 'master' of x2:/repos/git/libnl 2010-03-19 01:05:09 +01:00
Patrick McHardy 44fde8fcbb dect: adapt capability handling to latest kernel changes
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-03-08 04:02:53 +01:00
Patrick McHardy 2826c89a77 dect: transceiver: add missing DECT_DEL_TRANSCEIVER handling
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-12-30 00:57:56 +01:00
Patrick McHardy 17e2ac82ca dect: fixup example programs for latest library changes
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-12-17 17:30:24 +01:00
Patrick McHardy d9c446dd4f Merge branch 'master' of /repos/git/libnl
Conflicts:
	include/netlink/cli/utils.h

Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-12-17 17:21:30 +01:00
Patrick McHardy ff81f73c8a dect: support different ARI classes in dect-cluster-add
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-12-13 11:42:23 +01:00
Patrick McHardy accc75c463 libnl: dect: add cell slave mode support
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-12-04 11:04:51 +01:00
Patrick McHardy 71f3690295 libnl: dect: add DECT_SLOT_SYNC flag
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-12-04 09:57:22 +01:00
Patrick McHardy f5b6c85296 dect: support DECTA_SLOT_FLAGS attribute
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-11-26 03:21:30 +01:00
Patrick McHardy c335c58b68 dect: add X-crc statistic
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-11-26 03:21:28 +01:00
Patrick McHardy 464d806d27 dect: transceiver: show RF-band as 5 digit number
This is how the bands are officially numbered.

Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-11-12 14:38:34 +01:00
Patrick McHardy 9a8cbfdf5a Merge branch 'master' of x2:/repos/git/libnl
Conflicts:

	include/Makefile
	lib/Makefile
	src/Makefile

Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-11-12 13:36:05 +01:00
Patrick McHardy c60e16afd0 Merge branch 'master' of 192.168.0.100:/home/dect/git/libnl 2009-07-18 08:01:15 +02:00
Patrick McHardy d9cf87a0bc dect: add crc error statistic
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-07-18 08:00:12 +02:00
Patrick McHardy 1d25939936 dect: clarify error message
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-05-28 18:42:36 +02:00
Patrick McHardy 598dcf6c52 dect: resync netlink API with phase offset changes and display offset of each slot
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-05-10 15:10:12 +02:00
Patrick McHardy 85e8099cc4 dect: slightly more informative scan output
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-05-08 16:08:27 +02:00
Patrick McHardy be93d3d46c libnl: import DECT support
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-05-06 18:55:44 +02:00
Patrick McHardy b24d4fa5db libnl: add ENODEV to errno code table
Signed-off-by: Patrick McHardy <kaber@trash.net>
2009-05-06 18:53:39 +02:00
174 changed files with 8559 additions and 1402 deletions

View File

@ -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 "

View File

@ -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])

View File

@ -2316,6 +2316,7 @@ int put_opts(struct nl_msg *msg)
return 0;
nla_put_failure:
nla_nest_cancel(msg, opts);
return -EMSGSIZE;
}
--------

View File

@ -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 */

View File

@ -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

206
include/linux/dect.h Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -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

185
include/linux/if_bridge.h Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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" {

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 *);

View File

@ -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" {

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 );

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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 *);

View File

@ -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

View File

@ -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 *);

View File

@ -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

View File

@ -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 *);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 *);

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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)

View File

@ -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);
}
/** @} */
/** @} */

View File

@ -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)

View File

@ -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;

View File

@ -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>

View File

@ -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>

245
lib/dect/ari.c Normal file
View File

@ -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;
}

267
lib/dect/cell.c Normal file
View File

@ -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);
}
/** @} */

234
lib/dect/cell_obj.c Normal file
View File

@ -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 */
/** @} */

417
lib/dect/cluster.c Normal file
View File

@ -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);
}
/** @} */

274
lib/dect/cluster_obj.c Normal file
View File

@ -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 */
/** @} */

22
lib/dect/dect.c Normal file
View File

@ -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);
}

776
lib/dect/llme.c Normal file
View File

@ -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);
}
/** @} */

307
lib/dect/transceiver.c Normal file
View File

@ -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);
}
/** @} */

335
lib/dect/transceiver_obj.c Normal file
View File

@ -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 */
/** @} */

View File

@ -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] = {

View File

@ -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)

View File

@ -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>

View File

@ -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,

View File

@ -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>

View File

@ -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>

View File

@ -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 */
/**

View File

@ -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");

View File

@ -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
View File

@ -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");
}
/** @} */

View File

@ -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);

View File

@ -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>

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -61,7 +61,7 @@
* @{
*/
#include <netlink-local.h>
#include <netlink-private/netlink.h>
#include <netlink/netlink.h>
#include <netlink/netfilter/nfnl.h>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -16,7 +16,7 @@
* @{
*/
#include <netlink-local.h>
#include <netlink-private/netlink.h>
#include <netlink/netfilter/nfnl.h>
#include <netlink/netfilter/queue.h>

View File

@ -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;
}

View File

@ -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;
}
/** @} */
/** @} */

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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