Commit Graph

22921 Commits

Author SHA1 Message Date
Thomas Haller
e7836cd151 build/meson: rename "nm_core_dep" to "libnm_core_dep"
The library is called "libnm_core". So the dependency should be called
"libnm_core_dep", like in all other cases.

(cherry picked from commit c27ad37c27)
2019-04-18 20:13:49 +02:00
Thomas Haller
284ac92eee shared: build helper "libnm-libnm-core-{intern|aux}.la" library for libnm-core
"libnm-core" implements common functionality for "NetworkManager" and
"libnm".

Note that clients like "nmcli" cannot access the internal API provided
by "libnm-core". So, if nmcli wants to do something that is also done by
"libnm-core", , "libnm", or "NetworkManager", the code would have to be
duplicated.

Instead, such code can be in "libnm-libnm-core-{intern|aux}.la".
Note that:

  0) "libnm-libnm-core-intern.la" is used by libnm-core itsself.
     On the other hand, "libnm-libnm-core-aux.la" is not used by
     libnm-core, but provides utilities on top of it.

  1) they both extend "libnm-core" with utlities that are not public
     API of libnm itself. Maybe part of the code should one day become
     public API of libnm. On the other hand, this is code for which
     we may not want to commit to a stable interface or which we
     don't want to provide as part of the API.

  2) "libnm-libnm-core-intern.la" is statically linked by "libnm-core"
     and thus directly available to "libnm" and "NetworkManager".
     On the other hand, "libnm-libnm-core-aux.la" may be used by "libnm"
     and "NetworkManager".
     Both libraries may be statically linked by libnm clients (like
     nmcli).

  3) it must only use glib, libnm-glib-aux.la, and the public API
     of libnm-core.
     This is important: it must not use "libnm-core/nm-core-internal.h"
     nor "libnm-core/nm-utils-private.h" so the static library is usable
     by nmcli which couldn't access these.

Note that "shared/nm-meta-setting.c" is an entirely different case,
because it behaves differently depending on whether linking against
"libnm-core" or the client programs. As such, this file must be compiled
twice.

(cherry picked from commit af07ed01c0)
2019-04-18 20:07:44 +02:00
Thomas Haller
87f7e6844d shared: move "nm-dbus-compat.h" header to "nm-std-aux/nm-dbus-compat.h"
(cherry picked from commit 8183335878)
2019-04-18 20:03:54 +02:00
Thomas Haller
d984b2ce4a shared: move most of "shared/nm-utils" to "shared/nm-glib-aux"
From the files under "shared/nm-utils" we build an internal library
that provides glib-based helper utilities.

Move the files of that basic library to a new subdirectory
"shared/nm-glib-aux" and rename the helper library "libnm-core-base.la"
to "libnm-glib-aux.la".

Reasons:

 - the name "utils" is overused in our code-base. Everything's an
   "utils". Give this thing a more distinct name.

 - there were additional files under "shared/nm-utils", which are not
   part of this internal library "libnm-utils-base.la". All the files
   that are part of this library should be together in the same
   directory, but files that are not, should not be there.

 - the new name should better convey what this library is and what is isn't:
   it's a set of utilities and helper functions that extend glib with
   funcitonality that we commonly need.

There are still some files left under "shared/nm-utils". They have less
a unifying propose to be in their own directory, so I leave them there
for now. But at least they are separate from "shared/nm-glib-aux",
which has a very clear purpose.

(cherry picked from commit 80db06f768)
2019-04-18 19:57:27 +02:00
Thomas Haller
956215868c shared: move udev helper to separate directory "shared/nm-udev-aux"
We built (among others) two libraries from the sources in "shared/nm-utils":
"libnm-utils-base.la" and "libnm-utils-udev.la".

It's confusing. Instead use directories so there is a direct
correspondence between these internal libraries and the source files.

(cherry picked from commit 2973d68253)
2019-04-18 19:46:50 +02:00
Thomas Haller
0a6f21fb8d shared: split C-only helper "shared/nm-std-aux" utils out of "shared/nm-utils"
"shared/nm-utils" contains general purpose utility functions that only
depend on glib (and extend glib with some helper functions).

We will also add code that does not use glib, hence it would be good
if the part of "shared/nm-utils" that does not depend on glib, could be
used by these future projects.

Also, we use the term "utils" everywhere. While that covers the purpose
and content well, having everything called "nm-something-utils" is not
great. Instead, call this "nm-std-aux", inspired by "c-util/c-stdaux".

(cherry picked from commit b434b9ec07)
2019-04-18 19:17:23 +02:00
Thomas Haller
e63f835dee cli,all: merge branch 'th/strsplit-pt4'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/117

(cherry picked from commit df3c7c3ff4)
2019-04-18 18:52:00 +02:00
Thomas Haller
5b2d0f0f9f cli: use "escaped-tokens" style for splitting "vlan.xgress-priority-map" list
There should be little difference here, because the priority list is
(and was) never serialized with special characters like backslashes or
delimiters that require escaping.

Likewise, no working code actually tried to set such characters.

Still, drop the plain VALUE_STRSPLIT_MODE_STRIPPED and use
VALUE_STRSPLIT_MODE_ESCAPED_TOKENS_WITH_SPACES instead. We should have
a small set of modes that we use for splitting strings.

(cherry picked from commit 7f01da917e)
2019-04-18 18:51:21 +02:00
Thomas Haller
f6237b3f24 cli: cleanup _get_fcn_vlan_xgress_priority_map()
- merge the pointless helper function vlan_priorities_to_string()
  into the only caller _get_fcn_vlan_xgress_priority_map().

- minor cleanups, like setting out-is-default if num==0, not
  based on whether we have a non-empty string. There is not difference
  in practice, because nm_setting_vlan_get_priority() never fails.
  Hence they are identical. But nm_setting_vlan_get_priority() has
  an API that allows it to fail, so we should declare the default
  depending on the number of vlan priorities.

- don't allocate the temporary GString instance if we won't need it.

- only append the delimiter if needed, and not truncate it afterwards.
  It might have even worse performance this way, but it feels more
  correct to me.

- also cache the result of nm_setting_vlan_get_num_priorities().
  NMSettingVlan's implementation is horrible and uses a GSList to
  track the list of priorities. This makes it relatively expensive
  to call get-num-priorities repeatedly (and pointless).

(cherry picked from commit bbfd366805)
2019-04-18 18:51:21 +02:00
Thomas Haller
0e54f55cd8 cli: unify set of characters to tokenize list properties
the only change in behaviour is for VALUE_STRSPLIT_MODE_MULTILIST.
Previously, we would split at " \t,", now we will also split at
the white space characters "\n\r\f".

(cherry picked from commit 7a92fb6bf4)
2019-04-18 18:51:21 +02:00
Thomas Haller
585077c5ba shared: remove unused _nm_utils_escape_plain()/_nm_utils_escape_spaces() API
... and the "unescape" variants.

This is replaced by nm_utils_escaped_tokens_split()
and nm_utils_escaped_tokens_escape*() API.

(cherry picked from commit 304eab8703)
2019-04-18 18:51:21 +02:00
Thomas Haller
93eb40eda9 ifcfg-rh: use nm_utils_escaped_tokens* for "MATCH_INTERFACE_NAME"
For one, use NM_ASCII_SPACES as delimiter when reading
"MATCH_INTERFACE_NAME". Previously, it was only " \t".

I think there is no change in behavior otherwise.

(cherry picked from commit 941f27d350)
2019-04-18 18:51:21 +02:00
Thomas Haller
f6d73aff70 cli: refactor multilist property handling of "match.interface-names"
We had %VALUE_STRSPLIT_MODE_MULTILIST_WITH_ESCAPE, which was used
by "match.interface-names". This uses nm_utils_strsplit_set_full()
with %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING and
_nm_utils_unescape_plain().

We want eventually to use nm_utils_escaped_tokens_split() everywhere.

We already have %VALUE_STRSPLIT_MODE_ESCAPED_TOKENS, which splits the
list at ',' (and strips whitespaces at the around the delimiter). That
differs from what %VALUE_STRSPLIT_MODE_MULTILIST_WITH_ESCAPE did, which
also considered whitespace a delimiter.

So, we need a new mode %VALUE_STRSPLIT_MODE_ESCAPED_TOKENS_WITH_SPACES
which replaces the previous mode.

Note that the previous implementation did almost the same thing. In
fact, I cannot imagine examples where they behaved differently, but
my feeling is that there might be some edge cases where this changes
behavior.

(cherry picked from commit 6093f49304)
2019-04-18 18:51:21 +02:00
Thomas Haller
53b3e3d709 cli: return early when splitting with %VALUE_STRSPLIT_MODE_STRIPPED
The reminder of the function only does (something akin to) g_strstrip().
As we split the strings are spaces to begin with, there is nothing to
strip and we can return right away.

(cherry picked from commit b74d9a0bd5)
2019-04-18 18:51:20 +02:00
Thomas Haller
55a46f91e5 cli: drop unused strsplit_with_escape mode for objlist properties
(cherry picked from commit 3f5df5ab72)
2019-04-18 18:51:20 +02:00
Thomas Haller
f4a7c2eb9e cli: assert for proper escaping when creating objlist string
(cherry picked from commit 84bd1d38df)
2019-04-18 18:51:20 +02:00
Thomas Haller
872025d27c cli: default splitting list properties with escaped-tokens style
When splitting (and concatenating) list-typed properties,
we really should use nm_utils_escaped_tokens_split()
and nm_utils_escaped_tokens_escape*().

Make that the default, and mark all properties to opt-in to the
legacy behavior.

(cherry picked from commit 5a71592087)
2019-04-18 18:51:20 +02:00
Thomas Haller
4eaff61f35 cli: fix splitting of multilist property in setter
The modes VALUE_STRSPLIT_MODE_OBJLIST* and VALUE_STRSPLIT_MODE_MULTILIST* are
different. We must use the right mode.

For example, _get_fcn_match_interface_name() concatenates the interface-names
with space. So, the tokenizer of the setter must also use space as delimiter.
VALUE_STRSPLIT_MODE_MULTILIST_WITH_ESCAPE does that correctly,
VALUE_STRSPLIT_MODE_OBJLIST_WITH_ESCAPE does not.

(cherry picked from commit 758bf32640)
2019-04-18 18:51:20 +02:00
Thomas Haller
c26a421479 cli: fix handling empty match.interface-name property
(cherry picked from commit 6bef72364d)
2019-04-18 18:51:20 +02:00
Thomas Haller
30bb93cd93 platform: merge branch 'th/platform-routing-rules-compare'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/115

(cherry picked from commit c76aaa94ed)
2019-04-18 11:19:43 +02:00
Thomas Haller
062be85d82 platform: compare routing rules according to kernel support for FRA_L3MDEV
Also, in nm_platform_routing_rule_cmp() always compare the routing
table field, also if l3mdev is set. For kernel, we cannot set table and
l3mdev together, hence such rules don't really exist (or if we try to
configure it, it will be rejected by kernel). But as far as
nm_platform_routing_rule_cmp() is concerned, if the table is set,
always compare it.

(cherry picked from commit b6ff02e76f)
2019-04-18 11:19:26 +02:00
Thomas Haller
d440391350 platform: compare routing rules according to kernel support for FRA_UID_RANGE
(cherry picked from commit b843c1eab8)
2019-04-18 11:19:26 +02:00
Thomas Haller
11fd01c50e platform: compare routing rules according to kernel support for FRA_IP_PROTO
... and FRA_SPORT_RANGE and FRA_DPORT_RANGE.

(cherry picked from commit 6a6d982c01)
2019-04-18 11:19:26 +02:00
Thomas Haller
f9fe215599 platform: compare routing rules according to kernel support for FRA_PROTOCOL
For routes and routing rules, kernel uses a certain (not stictly defined) set
of attributes to decide whether to routes/rules are identical.

That is a problem, as different kernel versions disagree on whether
two routes/rules are the same (EEXIST) or not.

Note that when NetworkManager tries to add a rule with protocol set to
anything but RTPROT_UNSPEC, then kernel will ignore the attribute if it
doesn't have support for it. Meaning: the added rule will have a
different protocol setting then intended.

Note that NMPRulesManager will add a rule if it doesn't find it in the
platform cache so far. That means, when looking into the platform cache
we must ignore or honor the protocol like kernel does.

This does not only affect FRA_PROTOCOL, but all attributes where kernel
and NetworkManager disagrees. But the protocol is the most prominent
one, because the rules tracked by nmp_rules_manager_track_default()
specify the protocol.

(cherry picked from commit ef4f8ccf6d)
2019-04-18 11:19:26 +02:00
Thomas Haller
a9cf54c4ce platform: detect kernel support for FRA_L3MDEV
(cherry picked from commit eba4fd56f5)
2019-04-18 11:19:26 +02:00
Thomas Haller
ff686dd6c1 platform: detect kernel support for FRA_UID_RANGE
(cherry picked from commit 1dd1dcb81e)
2019-04-18 11:19:26 +02:00
Thomas Haller
4127583189 platform: detect kernel support for FRA_IP_PROTO, FRA_SPORT_RANGE, FRA_DPORT_RANGE
(cherry picked from commit 91252bb2fb)
2019-04-18 11:19:26 +02:00
Thomas Haller
6bfce3587e platform: detect kernel support for FRA_PROTOCOL
(cherry picked from commit cd62d43963)
2019-04-18 11:19:26 +02:00
Thomas Haller
bf36fa11d2 platform: refactor detecting kernel features
Next we will need to detect more kernel features. First refactor the
handling of these to require less code changes and be more efficient.
A plain nm_platform_kernel_support_get() only reqiures to access an
array in the common case.

The other important change is that the function no longer requires a
NMPlatform instance. This allows us to check kernel support from
anywhere. The only thing is that we require kernel support to be
initialized before calling this function. That means, an NMPlatform
instance must have detected support before.

(cherry picked from commit ee269b318e)
2019-04-18 11:19:26 +02:00
Beniamino Galvani
73e32e43c8 bridge: merge branch 'bg/bridge-vlan-ranges'
In some cases it is convenient to specify ranges of bridge vlans, as
already supported by iproute2 and natively by kernel.

https://bugzilla.redhat.com/show_bug.cgi?id=1652910
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/114
(cherry picked from commit 693252d049)
2019-04-18 09:53:52 +02:00
Thomas Haller
05a547133b libnm: minor refactoring of _nm_utils_bridge_vlan_verify_list()
- if there is only one vlan in the list, then we can return success
  early. That is, because one NMBridgeVlan instance is always valid
  due to the way how users must use the API to construct the element.

- the implementation for check_normalizable is only correct, if there
  are no duplicate or overlapping ranges. Assert for that. In fact,
  all callers first check for errors and then for normalizable errors.

- avoid duplicate calls to nm_bridge_vlan_get_vid_range(). There are
  duplicate assertions that we don't need.

- only check for pvid once per range.

- combine calls to g_hash_table_contains() and g_hash_table_add().

(cherry picked from commit a358da096f)
2019-04-18 09:53:24 +02:00
Beniamino Galvani
6ac953e9b3 all: use escaped_tokens API for bridge vlans
(cherry picked from commit 9f23c5e2de)
2019-04-18 09:53:22 +02:00
Thomas Haller
116218110f device: avoid multiple allocations in setting_vlans_to_platform()
We don't need GPtrArray to construct an array of fixed side.
Actually, we also don't need to malloc each NMPlatformBridgeVlan
element individually. Just allocate one buffer and append them
to the end.

(cherry picked from commit 6bc8ee87af)
2019-04-18 09:53:20 +02:00
Beniamino Galvani
da204257b1 all: support bridge vlan ranges
In some cases it is convenient to specify ranges of bridge vlans, as
already supported by iproute2 and natively by kernel. With this commit
it becomes possible to add a range in this way:

 nmcli connection modify eth0-slave +bridge-port.vlans "100-200 untagged"

vlan ranges can't be PVIDs because only one PVID vlan can exist.

https://bugzilla.redhat.com/show_bug.cgi?id=1652910
(cherry picked from commit 7093515777)
2019-04-18 09:53:18 +02:00
Beniamino Galvani
ea8ed6ce16 clients: fix typos
(cherry picked from commit ea16cf59f6)
2019-04-18 09:53:16 +02:00
Thomas Haller
fd8b78dd6a libnm-core/tests: fix "-Werror=logical-not-parentheses" warning in _sock_addr_endpoint()
CC       libnm-core/tests/libnm_core_tests_test_general-test-general.o
  In file included from ../shared/nm-default.h:280:0,
                   from ../libnm-core/tests/test-general.c:24:
  ../libnm-core/tests/test-general.c: In function _sock_addr_endpoint:
  ../libnm-core/tests/test-general.c:5911:18: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses]
    g_assert (!host == (port == -1));
                    ^
  ../shared/nm-utils/nm-macros-internal.h:1793:7: note: in definition of macro __NM_G_BOOLEAN_EXPR_IMPL
     if (expr) \
         ^
  /usr/include/glib-2.0/glib/gmacros.h:376:43: note: in expansion of macro _G_BOOLEAN_EXPR
   #define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 1))
                                             ^
  /usr/include/glib-2.0/glib/gtestutils.h:116:49: note: in expansion of macro G_LIKELY
                                                if G_LIKELY (expr) ; else \
                                                   ^
  ../libnm-core/tests/test-general.c:5911:2: note: in expansion of macro g_assert
    g_assert (!host == (port == -1));
    ^

Fixes: 713e879d76 ('libnm: add NMSockAddrEndpoint API')
(cherry picked from commit 1e8c08730f)
2019-04-18 09:48:40 +02:00
Thomas Haller
aabba1e4c2 ifcfg-rh: fix compiler warning in read_routing_rules_parse()
CC       src/settings/plugins/ifcfg-rh/src_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la-nms-ifcfg-rh-reader.lo
  In file included from ../shared/nm-default.h:280:0,
                   from ../src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:21:
  ../src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c: In function read_routing_rules_parse:
  ../src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:4309:27: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses]
     nm_assert (!key_is_ipv4 == NM_STR_HAS_PREFIX (key, "ROUTING_RULE6_"));
                             ^
  ../shared/nm-utils/nm-macros-internal.h:1793:7: note: in definition of macro __NM_G_BOOLEAN_EXPR_IMPL
     if (expr) \
         ^
  /usr/include/glib-2.0/glib/gmacros.h:376:43: note: in expansion of macro _G_BOOLEAN_EXPR
   #define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 1))
                                             ^
  /usr/include/glib-2.0/glib/gtestutils.h:116:49: note: in expansion of macro G_LIKELY
                                                if G_LIKELY (expr) ; else \
                                                   ^
  ../shared/nm-utils/nm-macros-internal.h:973:40: note: in expansion of macro g_assert
   #define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END
                                          ^
  ../src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:4309:3: note: in expansion of macro nm_assert
     nm_assert (!key_is_ipv4 == NM_STR_HAS_PREFIX (key, "ROUTING_RULE6_"));
     ^

Fixes: 4d46804437
(cherry picked from commit c6e6dcae70)
2019-04-18 09:36:09 +02:00
Rodrigo Lledó
5fbd3d4e45 po: update Spanish (es) translation
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/116
(cherry picked from commit 0e7a5c7324)
2019-04-17 17:42:31 +02:00
Thomas Haller
98870c8965 all: merge branch 'th/strsplit-pt3'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/107

(cherry picked from commit b5a86c10a0)
2019-04-17 11:27:51 +02:00
Thomas Haller
45fad3bb20 shared: add nm_utils_escaped_tokens_escape_gstr_assert()
(cherry picked from commit 832adf323e)
2019-04-17 11:27:14 +02:00
Thomas Haller
c0feedbaae shared/tests: add unit tests for new flags of nm_utils_strsplit_set_full()
(cherry picked from commit a7d1e14e6d)
2019-04-17 11:27:11 +02:00
Thomas Haller
da7ce5374d shared: remove unused nm_utils_str_simpletokens_extract_next()
This can be replaced by nm_utils_escaped_tokens_split().

Note that nm_utils_escaped_tokens_split() does not behave exactly
the same. For example, nm_utils_str_simpletokens_extract_next() would
remove all backslashes and leave only the following character.
nm_utils_escaped_tokens_split() instead only strips backslashes
that preceed a delimiter, whitespace or another backslash.

But we should have one preferred way of tokenizing, and I find this
preferable, because it allows for most backslashes to appear verbatim.

(cherry picked from commit ced7dbe8bf)
2019-04-17 11:27:11 +02:00
Thomas Haller
b583f3a482 cli: use nm_utils_escaped_tokens_*() for handling policy routes
Optimally, all list types properties in nmcli support proper escaping.
For that, we should use nm_utils_escaped_tokens_*() API.

For now, just change that for policy routes. They were just added recently,
so no change in behavior of released API.

(cherry picked from commit d59f046bb6)
2019-04-17 11:27:11 +02:00
Thomas Haller
2d1ae8dd97 libnm: use nm_utils_escaped_tokens_*() for parsing NMIPRoutingRule
Replace nm_utils_str_simpletokens_extract_next() by
nm_utils_escaped_tokens_split().

nm_utils_escaped_tokens_split() should become our first choice for
parsing and tokenizing.

Note that both nm_utils_str_simpletokens_extract_next() and
nm_utils_escaped_tokens_split() need to strdup the string once,
and tokenizing takes O(n). So, they are roughtly the same performance
wise. The only difference is, that as we iterate through the tokens,
we might abort early on error with nm_utils_str_simpletokens_extract_next()
and not parse the entire string. But that is a small benefit, since we
anyway always strdup() the string (being O(n) already).

Note that to-string will no longer escape ',' and ';'. This is a change
in behavior, of unreleased API. Also note, that escaping these is no
longer necessary, because nmcli soon will also use nm_utils_escaped_tokens_*().

Another change in behavior is that nm_utils_str_simpletokens_extract_next()
treated invalid escape sequences (backslashes followed by an arbitrary
character), buy stripping the backslash. nm_utils_escaped_tokens_*()
leaves such backslashes as is, and only honors them if they are followed
by a whitespace (the delimiter) or another backslash. The disadvantage
of the new approach is that backslashes are treated differently
depending on the following character. The benefit is, that most
backslashes can now be written verbatim, not requiring them to escape
them with a double-backslash.

Yes, there is a problem with these nested escape schemes:

  - the caller may already need to escape backslash in shell.

  - then nmcli will use backslash escaping to split the rules at ','.

  - then nm_ip_routing_rule_from_string() will honor backslash escaping
    for spaces.

  - then iifname and oifname use backslash escaping for nm_utils_buf_utf8safe_escape()
    to express non-UTF-8 characters (because interface names are not
    necessarily UTF-8).

This is only redeamed because escaping is really only necessary for very
unusual cases, if you want to embed a backslash, a space, a comma, or a
non-UTF-8 character. But if you have to, now you will be able to express
that.

The other upside of these layers of escaping is that they become all
indendent from each other:

  - shell can accept quoted/escaped arguments and will unescape them.

  - nmcli can do the tokenizing for ',' (and escape the content
    unconditionally when converting to string).

  - nm_ip_routing_rule_from_string() can do its tokenizing without
    special consideration of utf8safe escaping.

  - NMIPRoutingRule takes iifname/oifname as-is and is not concerned
    about nm_utils_buf_utf8safe_escape(). However, before configuring
    the rule in kernel, this utf8safe escape will be unescaped to get
    the interface name (which is non-UTF8 binary).

(cherry picked from commit b6d0be2d3b)
2019-04-17 11:27:11 +02:00
Thomas Haller
0deb3024bc cli: add new style for tokenizing/concatenating list options in nmcli
nmcli supports list options (optlist and multilist properties).
These commonly are individual items, concatenated by a delimiter.

It should be generally possibly to express every value. That means, we
need some for of escaping mechanism for delimiters.

Currently this is all inconsistent or no escaping is supported. I intend
to fix that (which will be a change in behavior).

For now, just add yet another style of tokenzing/concatenating list
items in nmcli. This is the style to replace all other styles.

(cherry picked from commit ba956bd499)
2019-04-17 11:27:11 +02:00
Thomas Haller
0cc5fe78b3 shared: add nm_utils_escaped_tokens_escape()
This escapes strings so that they can be concatenated with a delimiter
and without loss tokenized with nm_utils_escaped_tokens_split().

Note that this is similar to _nm_utils_escape_plain() and
_nm_utils_escape_spaces(). The difference is that
nm_utils_escaped_tokens_escape() also escapes the last trailing
whitespace. That means, if delimiters contains all NM_ASCII_SPACES, then
it is identical to _nm_utils_escape_spaces(). Otherwise, the trailing
space is treated specially. That is, because
nm_utils_escaped_tokens_split() uses NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP,
to strip leading and trailing whitespace. To still express a trailing
whitespace, the last whitespace must be escaped. Note that
NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP also honors escaping any whitespace
(not only at the last position), but when escaping we don't need to
escape them, because unescaped (non-trailing) whitespace are taken just
fine.

The pair nm_utils_escaped_tokens_split() and
nm_utils_escaped_tokens_escape() are proposed as default way of
tokenizing a list of items. For example, with

  $ nmcli connection modify "$PROFILE" +ipv4.routing-rules 'priority 5 from 192.168.7.5/32 table 5, priority 6 iif a\, from 192.168.7.5/32 table 6'

Here we implement a to/from string function to handle one item
(nm_ip_routing_rule_{from,to}_string()). When such elements are combined with ',',
then we need to support an additional layer of escaping on top of that.
The advantage is that the indvidual to/from string functions are agnostic
to this second layer of escaping/tokenizing that nmcli employs to handle
a list of these items.
The disadvantage is that we possibly get multiple layers of backslash
escapings. That is only mitigated by the fact that nm_utils_escaped_tokens_*()
supports a syntax for which *most* characters don't need any special escaping.
Only delimiters, backslash, and the trailing space needs escaping, and
these are cases are expected to be few.

(cherry picked from commit e206e3d4d8)
2019-04-17 11:27:10 +02:00
Thomas Haller
4181ed86ac shared: add NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED to nm_utils_strsplit_set_full()
Add a new flag that will remove escape characters after splitting
the string.

This implements a special kind of backslash escaping. It's not C escape
sequences (like '\n' or '\020'), but simply to take the special character
following the backslash verbatim. Note that the backslash is only
considered special, if it's followed by a delimiter, another backslash,
or a whitespace (in combination with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).

The main purpose of this form of escaping is nmcli's list options, like

  $ nmcli connection modify "$PROFILE" +ipv4.routing-rules 'priority 5 from 192.168.7.5/32 table 5, priority 6 iif a\, from 192.168.7.5/32 table 6'

It's a contrieved example, but the list options are a list of IP
addresses, rules, etc. They implement their own syntax for one element,
and are concatenated by ','. To support that one element may have
arbitrary characters (including the delimiter and whitespaces), nmcli
employs a tokenization with this special kind of escaping.

(cherry picked from commit 9522aaf226)
2019-04-17 11:27:10 +02:00
Thomas Haller
c75a1d7e16 shared: add NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP to nm_utils_strsplit_set_full()
This will essentially call g_strstrip() on each token.

There are some specialties:

 - if the resulting word is empty after stripping, then according to
   %NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, the empty token will be
   removed. If that results in an empty string array, %NULL will be
   returned.

 - if %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING is set, then
   whitespace that is backslash escaped is not removed.

Since this is a post-operation that happens after tokeninzing, it
could be done as a separate function. And we already have this function:
_nm_utils_unescape_plain() and _nm_utils_unescape_spaces().
However, that is ugly for several reasons:

 - the stripping should be part of the tokenizing, you shouldn't need
   several steps.

 - nm_utils_strsplit_set_full() returns a "const char **" which
   indicates the strings must not be freed. However, it is perfectly
   valid to modify the string inplace. Hence, the post-op function
   would need to cast the strings to "char *", which seems ugly
   (although we do that on many places, and it's guaranteed to work).

 - _nm_utils_unescape_plain()/_nm_utils_unescape_spaces() is indeed
   already used together with nm_utils_strsplit_set_full(). However,
   it requires to initialize the cb_lookup buffer twice. I would expect
   that initializing the cb_lookup buffer is a large portion of what
   the function does already (for short strings).
   This issue will be solved in the next commit by adding yet another flag
   which allows to unescape.

(cherry picked from commit 5b2b0dcadf)
2019-04-17 11:27:10 +02:00
Thomas Haller
53ab539dd1 cli: avoid duplicate delimiters when printing objlist property
Usually, obj_to_str_fcn() should not fail and always add something.
If not, remove the delimiter again.

(cherry picked from commit 720bc30bd9)
2019-04-17 11:27:10 +02:00
Thomas Haller
3383bb4feb cli: fix crash in split_required_fields_for_con_show()
Depending on the architecture (calling convention), function
arguments are evaluated in one order or the other.

https://bugzilla.redhat.com/show_bug.cgi?id=1700409

Fixes: 34e60bf228 ('cli: cleanup split_required_fields_for_con_show()')
(cherry picked from commit f4afb38bd9)
2019-04-16 16:01:37 +02:00