Commit graph

1501 commits

Author SHA1 Message Date
Thomas Haller
b8398b9e79 platform: add NMPRulesManager for syncing routing rules
Routing rules are unlike addresses or routes not tied to an interface.
NetworkManager thinks in terms of connection profiles. That works well
for addresses and routes, as one profile configures addresses and routes
for one device. For example, when activating a profile on a device, the
configuration does not interfere with the addresses/routes of other
devices. That is not the case for routing rules, which are global, netns-wide
entities.

When one connection profile specifies rules, then this per-device configuration
must be merged with the global configuration. And when a device disconnects later,
the rules must be removed.

Add a new NMPRulesManager API to track/untrack routing rules. Devices can
register/add there the routing rules they require. And the sync method will
apply the configuration. This is be implemented on top of NMPlatform's
caching API.
2019-03-13 09:47:37 +01:00
Thomas Haller
5ae2431b0f platform/tests: add tests for handling policy routing rules 2019-03-13 09:03:59 +01:00
Thomas Haller
9992ac1cf8 platform: add routing-rule add/delete netlink functions 2019-03-13 09:03:59 +01:00
Thomas Haller
9934a6a0e3 platform: add support for routing-rule objects and cache them in platform
Add and implement NMPlatformRoutingRule types and let the platform cache
handle rules.

Rules are special in two ways:

- they don't have an ifindex. That makes them different from all other
  currently existing NMPlatform* types, which have an "ifindex" field and
  "implement" NMPlatformObjWithIfindex.

- they have an address family, but contrary to addresses and routes, there
  is only one NMPlatformRoutingRule object to handle both address
  families.

Both of these points require some special considerations.

Kernel treats routing-rules quite similar to routes. That is, kernel
allows to add different rules/routes, as long as they differ in certain
fields. These "fields" make up the identity of the rules/routes. But
in practice, it's not defined which fields contribute to the identity
of these objects. That makes using the netlink API very hard. For
example, when kernel gains support for a new attribute which
NetworkManager does not know yet, then users can add two rules/routes
that look the same to NetworkManager. That can easily result in cache
inconsistencies.

Another problem is, that older kernel versions may not yet support all
fields, which NetworkManager (and newer kernels) considers for identity.
The older kernel will not simply reject netlink messages with these unknown
keys, instead it will proceed adding the route/rule without it. That means,
the added route/rule will have a different identity than what NetworkManager
intended to add.
2019-03-13 09:03:59 +01:00
Thomas Haller
b9ee40b86b platform: separate the refresh-type from the object type
Currently, there is a directy one to one relation between

 - DELAYED_ACTION_TYPE_REFRESH_ALL_*

 - REFRESH_ALL_TYPE_*

 - NMP_OBJECT_TYPE_*

For IP addresses, routes and routing policy rules, when we request
a refresh-all (NLM_F_DUMP), we want to specify the address family.

For addresses and routes that is currently solved by having two
sets of NMPObject types, for each address family one.

I think that is cumbersome because the implementations of both address
families are quite similar. By implementing both families as different
object types, we have a lot of duplicate code and it's hard to see where
the families actually differ. It would be better to have only one NMPObject
type, but then when we "refresh-all" such types, we still want to be able
to dump all (AF_UNSPEC) or only a particular address family (AF_INET, AF_INET6).

Decouple REFRESH_ALL_TYPE_* from NMP_OBJECT_TYPE_* to make that
possible.
2019-03-13 09:03:59 +01:00
Thomas Haller
0a2a861782 platform/trivial: rename enum DELAYED_ACTION_IDX_REFRESH_ALL_* to REFRESH_ALL_TYPE_*
While these numbers are strongly related to DELAYED_ACTION_TYPE_REFRESH_ALL_*,
they differ in their meaning.

These are the refresh-all-types that we support. While some of the delayed-actions
are indeed for refresh-all, they are not the same thing.

Rename the enum.
2019-03-13 09:03:59 +01:00
Thomas Haller
7c5ad2d910 platform: drop unused nm_platform_refresh_all()
The function is unused. It would require redesign to work with
future changes, and since it's unused, just drop it.

The long reasoning is:

    Currently, a refresh-all is tied to an NMPObjectType. However, with
    NMPObjectRoutingRule (for policy-routing-rules) that will no longer
    be the case.

    That is because NMPObjectRoutingRule will be one object type for
    AF_INET and AF_INET6. Contrary to IPv4 addresses and routes, where
    there are two sets of NMPObject types.

    The reason is, that it's preferable to treat IPv4 and IPv6 objects
    similarly, that is: as the same type with an address family property.

    That also follows netlink, which uses RTM_GET* messages for both
    address families, and the address family is expressed inside the
    message.

    But then an API like nm_platform_refresh_all() makes little sense,
    it would require at least an addr_family argument. But since the
    API is unused, just drop it.
2019-03-13 09:03:59 +01:00
Thomas Haller
bbfb8a9b33 platform: suppress unnecessary logging in do_request_all_no_delayed_actions()
When we refresh all links, we clear all flags to refresh a specific
link. However, only log a message if there was anything to clear.
2019-03-13 09:03:59 +01:00
Thomas Haller
2c37a3fb1e platform: add NULL check in inline nmp_object_unref() function
This allows the compiler to see that this function does nothing for %NULL.
That is not so unusual, as we use nm_auto_nmpobj to free objects. Often
the compiler can see that these pointers are %NULL.
2019-03-13 09:03:59 +01:00
Thomas Haller
ac4a1deba0 platform: add NMPlatformObjWithIfindex helper structure for handling NMPObject types
Until now, all implemented NMPObject types have an ifindex field (from
links, addresses, routes, qdisc to tfilter).

The NMPObject structure contains a union of all available types, that
makes it easier to down-case from an NMPObject pointer to the actual
content.

The "object" field of NMPObject of type NMPlatformObject is the lowest
common denominator.

We will add NMPlatformRoutingRules (for policy routing rules). That type
won't have an ifindex field.

Hence, drop the "ifindex" field from NMPlatformObject type. But also add
a new type NMPlatformObjWithIfindex, that can represent all types that
have an ifindex.
2019-03-13 09:03:59 +01:00
Thomas Haller
667aa52f89 platform: move nmp_class_from_type() to header to allow inlining 2019-03-13 09:03:59 +01:00
Thomas Haller
8f3724a6bd platform: drop unnecessary casts from NMP_OBJECT_CAST_*() macros
It's wrong to cast here. The caller must always provide an
NMPObject pointer.
2019-03-13 09:03:59 +01:00
Thomas Haller
7259195a91 platform: unify IPv4 and IPv6 variables for NMPlatformVTableRoute 2019-03-13 09:03:59 +01:00
Thomas Haller
4e399d82ac platform/wireguard: fix WGPEER_A_LAST_HANDSHAKE_TIME to use int64 typed timespec structure
The netlink API changed for WireGuard. Adjust for that.

https://git.zx2c4.com/WireGuard/commit/?id=c870c7af53f44a37814dfc76ceb8ad88e290fcd8
2019-03-07 17:54:25 +01:00
Thomas Haller
7451a6a649 core: use nm_utils_memeqzero_secret() for printing WireGuard key 2019-03-07 17:54:25 +01:00
Lubomir Rintel
d551a0893e platform/linux: fix detection of IFA_FLAGS support
The condition got accidentally reversed, which means we're always
undecided and thus wrongly assuming support and never being able to set
any addresses.

This would bother the few that are struck with 3.4 android kernels. Very
few indeed, given this got unnoticed since 1.10.

Fixes: 8670aacc7c ('platform: cleanup detecting kernel support for IFA_FLAGS and IPv6LL')
2019-03-07 10:17:42 +01:00
Marco Trevisan (Treviño)
73005fcf5b nm: Fix syntax on introspection annotations
Various annotations were added using multiple colons, while only one has
to be added or g-ir-introspect will consider them part of the description

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/94
2019-03-07 10:04:41 +01:00
Thomas Haller
5551b3ab55 Revert "build/meson: name platform tests like autotools"
Older versions of meson don't support building the same names
multiple times.

  Meson encountered an error in file src/tests/meson.build, line 14, column 2:
  Tried to create target "test-general", but a target of that name already exists.

We really need to use unique filenames everywhere. Revert the name
change for now.

This breaks again the valgrind workaround in "tools/run-nm-test.sh".

This reverts commit 5466edc63e.
2019-02-23 07:40:03 +01:00
Thomas Haller
5466edc63e build/meson: name platform tests like autotools
Meson and autotools should name the tests the same way.
Also, all tests binaries built by autotools start on purpose
with "test-". Do that for meson too.

Also, otherwise "tools/run-nm-test.sh" fails to workaround
valgrind failures for platform tests as it does not expect
the tests to be named that way:

    if [ $HAS_ERRORS -eq 0 ]; then
        # valgrind doesn't support setns syscall and spams the logfile.
        # hack around it...
        if [ "$TEST_NAME" = 'test-link-linux' -o \
             "$TEST_NAME" = 'test-acd' ]; then
            if [ -z "$(sed -e '/^--[0-9]\+-- WARNING: unhandled .* syscall: /,/^--[0-9]\+-- it at http.*\.$/d' "$LOGFILE")" ]; then
                HAS_ERRORS=1
            fi
        fi
    fi
2019-02-23 07:24:35 +01:00
Thomas Haller
b1f6d53bc4 build/meson: increase timeouts for some tests
The defaults for test timeouts in meson is 30 seconds. That is not long
enough when running

  $ NMTST_USE_VALGRIND=1 ninja -C build test

Note that meson supports --timeout-multiplier, and automatically
increases the timeout when running under valgrind. However, meson
does not understand that we are running tests under valgrind via
NMTST_USE_VALGRIND=1 environment variable.

Timeouts are really not expected to be reached and are a mean of last
resort. Hence, increasing the timeout to a large value is likely to
have no effect or to fix test failures where the timeout was too rigid.
It's unlikely that the test indeed hangs and the increase of timeout
causes a unnecessary increase of waittime before aborting.
2019-02-23 07:20:49 +01:00
Thomas Haller
bf863aba93 platform: move creation of nlmsg dump request in separate function
Split out the creation of the nlmsg with the netlink dump request.
Also, add a (still unused) parameter to overwrite the preferred
address family.
2019-02-22 10:08:00 +01:00
Thomas Haller
40e0ff9fbf platform: pass lookup instance to nmp_cache_dirty_set_all() instead of object-type
We already have NMPLookup to express a set of objects that can be looked
up via the multi-index.

Change the behavior of nmp_cache_dirty_set_all(), not to accept an
object-type. Instead, make it generally useful and accept a lookup
instance that is used to filter the elements that should be set as
dirty.
2019-02-22 10:08:00 +01:00
Thomas Haller
d431de70ac platform: refactor FOR_EACH_DELAYED_ACTION() macro to have only one for(;;) statement
for-each macros can be nice to use. However, such macros are potentially
error prone, as they abstract C control statements and scoping blocks.

I find it ugly to expand the macro to:

    for (...)
       if (...)

Instead, move the additional "if" check inside the loop's condition
expression, so that the macro only expands to one "for(;;)" statement.
2019-02-22 10:07:33 +01:00
Thomas Haller
7bb6433214 platform: create id-only objects for deleting qdisc/tfilter in event_valid_msg()
It does not matter too much, but the code optimizes for deletion events.
In that case, we don't require parsing the full netlink message.
Instead, it's enough to parse only the ID part so that we can find the
object in the cache that is to be removed removed.

Fix that for qdisc/tfilter objects.
2019-02-22 10:06:35 +01:00
Thomas Haller
e43d1d90f3 platform: minor cleanup in event_valid_msg() 2019-02-22 10:05:00 +01:00
Thomas Haller
08bc38cb5c platform/wifi: don't use __u32 type in "nm-wifi-utils-nl80211.c"
Also, use unsignd (guint) variable as index. That is fine, because
nla_len() returns a (signed) int.
2019-02-22 10:05:00 +01:00
Thomas Haller
60e4595101 platform: cleanup parsing of RTA_MULTIPATH in _new_from_nl_route()
I think the code before was correct. At the very least because
we only run the while-loop at most once because multipath routes
are not supported.

However, it seems odd that the while loop checks for

    "tlen >= rtnh->rtnh_len"

but later we do

    "tlen -= RTNH_ALIGN (rtnh->rtnh_len)"

Well, arguably, tlen itself is aligned to 4 bytes (as kernel sends
the netlink message that way). So, it was indeed fine.

Still, confusing. Try to check more explicitly for the buffer sizes.
2019-02-22 10:05:00 +01:00
Thomas Haller
1b7e89ad7d platform: use nla_data_as() at some places
nla_data_as() has a static assertion that casting to the pointer is
valid (regarding the alignment of the structure). It also contains
an nm_assert() that the data is in fact large enough.

It's safer, hence prefer it a some places where it makes sense.
2019-02-22 10:04:48 +01:00
Thomas Haller
f7e4310a0f platform: use nm_auto_nlmsg cleanup macro instead of explict nlmsg_free() 2019-02-22 09:58:09 +01:00
Thomas Haller
a41ca7cc89 platform: use nlmsg_append_struct() macro instead of nlmsg_append()
- nlmsg_append_struct() determines the size based on the argument.
  It avoids typing, but more importantly: it avoids typing redundant
  information (which we might get wrong).

- also, declare the structs as const, where possible.
2019-02-22 09:58:09 +01:00
Thomas Haller
98e42a4552 platform: prettify parsing MACSec from netlink 2019-02-22 09:58:09 +01:00
Thomas Haller
dca6d24aab platform: drop READ_STAT64() macro from _new_from_nl_link()
It doesn't make it easier to read. Also, the code comment points
out something rather obvious, as we later use unaligned API to access the
fields.
2019-02-22 09:58:09 +01:00
Thomas Haller
9cc592ae05 platform: don't use memset() to initialize variable in _new_from_nl_route() 2019-02-22 09:58:09 +01:00
Thomas Haller
495cfd9129 platform: sort #include in "nm-linux-platform.h" 2019-02-22 09:58:09 +01:00
Thomas Haller
451073e5bb platform: use nla_get_be64() helper 2019-02-22 09:58:09 +01:00
Thomas Haller
815e0329c0 platform/netlink: cleanup nlmsg_append() and add nlmsg_append_struct() macro 2019-02-22 09:58:09 +01:00
Thomas Haller
020000433b platform/netlink: add nla_data_as() macro
This macro casts the return pointer and asserts that the netlink attribute
is suitably large.
2019-02-22 09:58:09 +01:00
Thomas Haller
5920f187d3 platform/netlink: add more RTM message types in to-string function nl_nlmsghdr_to_str() 2019-02-22 09:58:09 +01:00
Thomas Haller
bc7bf3c861 platform/netlink: add nla_get_be64() helper 2019-02-22 09:58:09 +01:00
Thomas Haller
fac357ac8b platform/netlink: require valid nla argument for nla_get_u64()
nla_get_u64() was unlike all other nla_get_u*() implementations, in that it
would allow for a missing/invalid nla argument, and return 0.

Don't do this. For one, don't behave different than other getters.
Also, there really is no space to report errors. Hence, the caller must
make sure that the attribute is present and suitable -- like for other
nla_get_*() functions.

None of the callers relied on being able to pass NULL attribute.

Also, inline the function and use unaligned_read_ne64(). That is our
preferred way for reading unaligned data, not memcpy().
2019-02-22 09:58:09 +01:00
Thomas Haller
af13eb6cac platform/netlink: add assertions for nla_get_*() functions
These are only nm_assert(), meaning on non-DEBUG builds they
are not enabled.

Callers are supposed to first check that the netlink attribute
is suitable. Hence, we just assert.
2019-02-22 09:58:09 +01:00
Thomas Haller
5044c33ead platform/netlink: use designated initializer in nlmsg_alloc_size() 2019-02-22 09:58:09 +01:00
Thomas Haller
f7df8fda1a platform/netlink: assert for valid policy for string attribute in validate_nla
The policy for strings must indicate a minlen of at least 1.

Everything else is a bug, because the policy contains invalid
data -- and is determined at compile-time.
2019-02-22 09:58:09 +01:00
Thomas Haller
82e31b2816 platform/netlink: cleanup nla_memcpy()
- use size_t arguments for the memory sizes. While sizes from netlink
  API currently are int typed and inherrently limited, use the more
  appropriate data type.

- rename the arguments. The "count" is really the size of the
  destination buffer.

- return how many bytes we wanted to write (like g_strlcpy()).
  That makes more sense than how many bytes we actually wrote
  because previously, we could not detect truncation.
  Anyway, none of the callers cared about the return-value either
  way.
2019-02-22 09:58:09 +01:00
Thomas Haller
b080146cc6 platform/netlink: cleanup nla_strlcpy()
- let nla_strlcpy() return how many bytes we would like to have
  copied. That way, the caller could detect string truncation.
  In practice, no caller cared about that.

- the code before would also fill the entire buffer with zeros first,
  like strncpy(). We still do that. However, only copy the bytes up
  to the first NUL byte. The previous version would have copied
  "a\0b\0" (with srclen 4) as "a\0b". Strip all bytes after the
  first NUL character from src. That seems more correct here.

- accept nla argument as %NULL.
2019-02-22 09:58:09 +01:00
Thomas Haller
6c24846929 platform/trivial: coding style fixes/whitespace 2019-02-22 09:58:09 +01:00
Thomas Haller
6f8208c0d4 platform/netlink: cleanup nla_parse*() code by using safer macros
- drop explicit MAX sizes like

      static const struct nla_policy policy[IFLA_INET6_MAX+1] = {

  The compiler will deduce that.

  It saves redundant information (which is possibly wrong). Also,
  the max define might be larger than we actually need it, so we
  just waste a few bytes of static memory and do unnecesary steps
  during validation.

  Also, the compiler will catch bugs, if the array size of policy/tb
  is too short for what we access later (-Warray-bounds).

- avoid redundant size specifiers like:

      static const struct nla_policy policy[IFLA_INET6_MAX+1] = {
      ...
      struct nlattr *tb[IFLA_INET6_MAX+1];
      ...
      err = nla_parse_nested (tb, IFLA_INET6_MAX, attr, policy);

- use the nla_parse*_arr() macros that determine the maxtype
  based on the argument types.

- move declaration of "static const struct nla_policy policy" variable
  to the beginning, before auto variables.

- drop unneeded temporay error variables.
2019-02-22 09:58:09 +01:00
Thomas Haller
cf22d28c2e platform/netlink: add nla_parse* macros that safely determine the max-type
The common idiom is to stack allocate the tb array. Hence,
the maxtype is redundant. Add macros that autodetect the
maxtype based on the C type infomation.

Also, there is a static assertion that the size of the policy
(if provided) matches.
2019-02-22 09:58:09 +01:00
Thomas Haller
6245569c6d platform/netlink: cleanup unnecessary "goto out" from nla_parse() 2019-02-22 09:58:09 +01:00
Thomas Haller
d8727f6aa9 platform/netlink: fix return value of nla_get_s8() 2019-02-22 09:58:09 +01:00