1. 07 Mar, 2019 1 commit
  2. 05 Mar, 2019 1 commit
  3. 22 Feb, 2019 1 commit
    • Thomas Haller's avatar
      all: move nm_utils_hexstr2bin*() to shared · 53b747ff
      Thomas Haller authored
      libnm exposes simplified variants of hexstr2bin in its public API. I
      think that was a mistake, because libnm should provide NetworkManager
      specific utils. It should not provide such string functions.
      However, nmcli used to need this, so it was added to libnm.
      The better approach is to add it to our internally shared static
      library, so that all interested components can make use of it.
  4. 21 Feb, 2019 1 commit
  5. 12 Feb, 2019 2 commits
  6. 06 Feb, 2019 1 commit
    • Thomas Haller's avatar
      all: don't use "static inline" in source files · d25ed082
      Thomas Haller authored
      For static functions inside a module, the compiler determines on its own
      whether to inline the function.
      Also, "inline" was used at some places that don't immediatly look like
      candidates for inlining. It was most likely a copy&paste error.
  7. 24 Jan, 2019 1 commit
  8. 11 Jan, 2019 1 commit
    • Thomas Haller's avatar
      libnm,core: accept failure to _nm_setting_get_property() in _log_connection_get_property() · 3846976e
      Thomas Haller authored
      _log_connection_get_property() is a hack, as it cannot meaningfully print complex
      properties. Also, it uses _nm_setting_get_property() which can only work with GObject
      base properties.
      Don't assert against _nm_setting_get_property() returning success. Eventually
      we should replace _nm_setting_get_property() by something better. But for the moment,
      it's fine to being unable to print a property value.
  9. 07 Jan, 2019 2 commits
  10. 19 Dec, 2018 1 commit
    • Thomas Haller's avatar
      all: don't use static buffer for nm_utils_inet*_ntop() · a51c09dc
      Thomas Haller authored
      While nm_utils_inet*_ntop() accepts a %NULL buffer to fallback
      to a static buffer, don't do that.
      I find the possibility of using a static buffer here error prone
      and something that should be avoided. There is of course the downside,
      that in some cases it requires an additional line of code to allocate
      the buffer on the stack as auto-variable.
  11. 14 Dec, 2018 1 commit
  12. 12 Dec, 2018 8 commits
    • Thomas Haller's avatar
      core: never fail reading host-id timestamp and never change it · a68d027b
      Thomas Haller authored
      The timestamp of the host-id is the timestamp of the secret_key file.
      Under normal circumstances, reading the timestamp should never fail,
      and reading it multiple times should always yield the same result.
      If we unexpectedly fail to read the timestamp from the file we want:
      - log a warning, so that the user can find out what's wrong. But
        do so only once.
      - we don't want to handle errors or fail operation due to a missing
        timestamp. Remember, it's not supposed to ever fail, and if it does,
        just log a warning and proceed with a fake timestamp instead. In
        that case something is wrong, but using a non-stable, fake timestamp
        is the least of the problems here.
        We already have a stable identifier (the host-id) which we can use to
        generate a fake timestamp. Use it.
      In case the user would replace the secret_key file, we also don't want
      that accessing nm_utils_host_id_get_timestamp*() yields different
      results. It's not implemented (nor necessary) to support reloading a
      different timestamp. Hence, nm_utils_host_id_get_timestamp() should
      memoize the value and ensure that it never changes.
    • Thomas Haller's avatar
    • Thomas Haller's avatar
      core/trivial: rename nm_utils_get_boot_id_*() · d693e03a
      Thomas Haller authored
      Rename to nm_utils_boot_id_*(), it matches nm_utils_machine_id_*()
      and nm_utils_host_id_get().
    • Thomas Haller's avatar
      core/trivial: rename secret-key to host-key · 6ffcd263
      Thomas Haller authored
      Now that the secret-key is hashed with the machine-id, the name is
      no longer best.
      Sure, part of the key are persisted in /var/lib/NetworkManager/secret_key
      file, which the user is well advised to keep secret.
      But what nm_utils_secret_key_get() returns is first and foremost a binary
      key that is per-host and used for hashing a per-host component. It's
      really the "host-id". Compare that to what we also have, the
      "machine-id" and the "boot-id".
    • Thomas Haller's avatar
      core: fix race creating secret-key · bc9f18c6
      Thomas Haller authored
      Reading the secret key may result in generating and
      writing a new key to disk.
      Do that under the lock.
    • Thomas Haller's avatar
      core: combine secret-key with /etc/machine-id · deb19abf
      Thomas Haller authored
      NetworkManager loads (and generates) a secret key as
      The secret key is used for seeding a per-host component when generating
      hashed, stable data. For example, it contributes to "ipv4.dhcp-client-id=duid"
      "ipv6.addr-gen-mode=stable-privacy", "ethernet.cloned-mac-address=stable", etc.
      As such, it corresponds to the identity of the host.
      Also "/etc/machine-id" is the host's identity. When cloning a virtual machine,
      it may be a good idea to generate a new "/etc/machine-id", at least in those
      cases where the VM's identity shall be different. Systemd provides various
      mechanisms for doing that, like accepting a new machine-id via kernel command line.
      For the same reason, the user should also regenerate a new NetworkManager's
      secrey key when the host's identity shall change. However, that is less obvious,
      less understood and less documented.
      Support and use a new variant of secret key. This secret key is combined
      with "/etc/machine-id" by sha256 hashing it together. That means, when the
      user generates a new machine-id, NetworkManager's per-host key also changes.
      Since we don't want to change behavior for existing installations, we
      only do this when generating a new secret key file. For that, we encode
      a version tag inside the "/var/lib/NetworkManager/secret_key" file.
      Note that this is all abstracted by nm_utils_secret_key_get(). For
      version 2 secret-keys, it internally combines the secret_key file with
      machine-id (via sha256). The advantage is that callers don't care that
      the secret-key now also contains the machine-id. Also, since we want to
      stick to the previous behavior if we have an old secret-key, this is
      nicely abstracted. Otherwise, the caller would not only need to handle
      two per-host parts, but it would also need to check the version to
      determine whether the machine-id should be explicitly included.
      At this point, nm_utils_secret_key_get() should be renamed to
    • Thomas Haller's avatar
      core: use define for secret_key filename · 2c7c3332
      Thomas Haller authored
    • Thomas Haller's avatar
      core: fix printing error for failure reading secret-key · 7b9cd2e3
      Thomas Haller authored
      g_file_get_contents() fails with G_FILE_ERROR, G_FILE_ERROR_NOENT when the
      file does not exist.
      That wasn't obvious to me, nm_utils_error_is_notfound() to the rescue.
      Fixes: dbcb1d6d
  13. 11 Dec, 2018 1 commit
    • Thomas Haller's avatar
      core: fix match spec behavior for a list of all "except:" · a7ef23b3
      Thomas Haller authored
      If the spec specifies only negative matches (and none of them matches),
      then the result shall be positive.
          [connection*] match-device=except:dhcp-plugin:dhclient
          [connection*] match-device=except:interface-name:eth0
          [.config] enabled=except:nm-version:1.14
      should be the same as:
          [connection*] match-device=*,except:dhcp-plugin:dhclient
          [connection*] match-device=*,except:interface-name:eth0
          [.config] enabled=*,except:nm-version:1.14
      and match by default. Previously, such specs would never yield a
      positive match, which seems wrong.
      Note that "except:" already has a special meaning. It is not merely
      "not:". That is because we don't support "and:" nor grouping, but all
      matches are combined by an implicit "or:". With such a meaning, having
      a "not:" would be unclear to define. Instead it is defined that any
      "except:" match always wins and makes the entire condition to explicitly
      not match. As such, it makes sense to treat a match that only consists
      of "except:" matches special.
      This is a change in behavior, but the alternative meaning makes
      little sense.
  14. 29 Nov, 2018 1 commit
  15. 13 Nov, 2018 7 commits
    • Thomas Haller's avatar
      all: add "${MAC}" substituion for "connection.stable-id" · 7ffbf712
      Thomas Haller authored
      We already had "${DEVICE}" which uses the interface name.
      In times of predictable interface naming, that works well.
      It allows the user to generate IDs per device which don't
      change when the hardware is replaced.
      "${MAC}" is similar, except that is uses the permanent MAC
      address of the device. The substitution results in the empty
      word, if the device has no permanent MAC address (like software
      The per-device substitutions "${DEVICE}" and "${MAC}" are especially
      interesting with "connection.multi-connect=multiple".
    • Thomas Haller's avatar
      dhcp: reimplement node-specific DHCP client-id generation from systemd · a5579577
      Thomas Haller authored
      Our internal DHCP client (from systemd) defaults to a particular client ID.
      It is currently exposed as nm_sd_utils_generate_default_dhcp_client_id()
      and is based on the systemd implementation.
      One problem with that is, that it internally looks up the interface name
      with if_indextoname() and reads /etc/machine-id. Both makes it harder
      for testing.
      Another problem is, that this way of generating the client-id is
      currently limited to internal client. Why? If you use dhclient plugin,
      you may still want to use the same algorithm. Also, there is no explict
      "ipv4.dhcp-client-id" mode to select this client-id (so that it could
      be used in combination with "dhclient" plugin).
      As such, this code will be useful also aside systemd DHCP plugin.
      Hence, the function should not be obviously tied to systemd code.
      The implementation is simple enough, and since we already have a
      unit-test, refactor the code to our own implementation.
    • Thomas Haller's avatar
      core: pass boot-id to nm_utils_stable_id_parse() · c51e63fe
      Thomas Haller authored
      For testing purpose, it's bad to let nm_utils_stable_id_parse()
      directly access nm_utils_get_boot_id_str(). Instead, the function
      should have no side-effects.
      Since the boot-id is anyway cached, accessing it is cheap. Even
      if it likely won't be needed.
    • Thomas Haller's avatar
      core: don't persist secret-key for tests · 581e1c32
      Thomas Haller authored
      Tests might access the secret-key.
      For CI builds we may very well build NM as root and also run
      unit tests. In such a situation it's bad to persist the secret
      key. For example, the SELinux label may be wrong, and subsequently
      starting NetworkManager may cause errors. Avoid persisting the secret
      key for tests.
    • Thomas Haller's avatar
      core: refactor loading machine-id and cache it · 83083112
      Thomas Haller authored
      Previously, whenever we needed /etc/machine-id we would re-load it
      from file. The are 3 downsides of that:
       - the smallest downside is the runtime overhead of repeatedly
         reading the file and parse it.
       - as we read it multiple times, it may change anytime. Most
         code in NetworkManager does not expect or handle a change of
         the machine-id.
         Generally, the admin should make sure that the machine-id is properly
         initialized before NetworkManager starts, and not change it. As such,
         a change of the machine-id should never happen in practice.
         But if it would change, we would get odd behaviors. Note for example
         how generate_duid_from_machine_id() already cached the generated DUID
         and only read it once.
         It's better to pick the machine-id once, and rely to use the same
         one for the remainder of the program.
         If the admin wants to change the machine-id, NetworkManager must be
         restarted as well (in case the admin cares).
         Also, as we now only load it once, it makes sense to log an error
         (once) when we fail to read the machine-id.
       - previously, loading the machine-id could fail each time. And we
         have to somehow handle that error. It seems, the best thing what we
         anyway can do, is to log an error once and continue with a fake
         machine-id. Here we add a fake machine-id based on the secret-key
         or the boot-id. Now obtaining a machine-id can no longer fail
         and error handling is no longer necessary.
      Also, ensure that a machine-id of all zeros is not valid.
      Technically, a machine-id is not an RFC 4122 UUID. But it's
      the same size, so we also use NMUuid data structure for it.
      While at it, also refactor caching of the boot-id and the secret
      key. In particular, fix the thread-safety of the double-checked
      locking implementations.
    • Thomas Haller's avatar
      core: minor cleanup of initializing nm_utils_get_testing() · e1413111
      Thomas Haller authored
      - add a commnt about thread-safety.
      - minor refactoring initializing the value in nm_utils_get_testing().
        Instead of returning the flags we just set, go back to the begin
        and re-read the value (which must be initialized by now). No big
        difference, but feels a bit nicer to me.
    • Thomas Haller's avatar
      all: cleanup GChecksum handling · eb9f950a
      Thomas Haller authored
      - prefer nm_auto_free_checksum over explicit free.
      - use nm_utils_checksum_get_digest*().
      - prefer defines for digest length.
      - assume g_checksum_new() cannot fail.
  16. 01 Nov, 2018 1 commit
    • Thomas Haller's avatar
      device: add "dhcp-plugin" match spec for device · b9eb264e
      Thomas Haller authored
      The need for this is the following:
      "ipv4.dhcp-client-id" can be specified via global connection defaults.
      In absence of any configuration in NetworkManager, the default depends
      on the DHCP client plugin. In case of "dhclient", the default further
      depends on /etc/dhcp.
      For "internal" plugin, we may very well want to change the default
      client-id to "mac" by universally installing a configuration
      However, if we the user happens to enable "dhclient" plugin, this also
      forces the client-id and overrules configuration from /etc/dhcp. The real
      problem is, that dhclient can be configured via means outside of NetworkManager,
      so our defaults shall not overwrite defaults from /etc/dhcp.
      With the new device spec, we can avoid this issue:
      This will be part of the solution for rh#1640494. Note that merely
      dropping a configuration snippet is not yet enough. More fixes for
      DHCP will follow. Also, bug rh#1640494 may have alternative solutions
      as well. The nice part of this new feature is that it is generally
      useful for configuring connection defaults and not specifically for
      the client-id issue.
      Note that this match spec is per-device, although the plugin is selected
      globally. That makes some sense, because in the future we may or may not
      configure the DHCP plugin per-device or per address family.
  17. 23 Oct, 2018 1 commit
    • Thomas Haller's avatar
      core: add nm_utils_file_is_in_path() for checking paths · f90b3adc
      Thomas Haller authored
      Add a helper function for the common check whether a file is
      inside a path. Also, this function handles special cases like
      repeated file separators. However, as it is still entirely text
      based, it also cannot recognize if two (literally) different
      paths reference the same inode/file.
  18. 18 Oct, 2018 2 commits
  19. 04 Oct, 2018 1 commit
  20. 17 Sep, 2018 1 commit
  21. 04 Sep, 2018 2 commits
  22. 11 Aug, 2018 1 commit
  23. 11 Jul, 2018 1 commit
    • Thomas Haller's avatar
      all: don't use gchar/gshort/gint/glong but C types · e1c7a2b5
      Thomas Haller authored
      We commonly don't use the glib typedefs for char/short/int/long,
      but their C types directly.
          $ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
          $ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
      One could argue that using the glib typedefs is preferable in
      public API (of our glib based libnm library) or where it clearly
      is related to glib, like during
        g_object_set (obj, PROPERTY, (gint) value, NULL);
      However, that argument does not seem strong, because in practice we don't
      follow that argument today, and seldomly use the glib typedefs.
      Also, the style guide for this would be hard to formalize, because
      "using them where clearly related to a glib" is a very loose suggestion.
      Also note that glib typedefs will always just be typedefs of the
      underlying C types. There is no danger of glib changing the meaning
      of these typedefs (because that would be a major API break of glib).
      A simple style guide is instead: don't use these typedefs.
      No manual actions, I only ran the bash script:
        FILES=($(git ls-files '*.[hc]'))
        sed -i \
            -e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
            -e 's/\<g\(char\|short\|int\|long\|float\|double\)\>  /\1   /g' \
            -e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \