diff options
| author | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
| commit | 28028b26b3371756811e95d894f709f4b1207c00 (patch) | |
| tree | 6fe7316fd743b51042db47601a8ef8814b3134ac /shared | |
| parent | e22609983008e1a669196ad64ba3a59ae8c76e0d (diff) | |
New upstream version 1.22.0 upstream/1.22.0
Diffstat (limited to 'shared')
125 files changed, 3517 insertions, 1765 deletions
diff --git a/shared/meson.build b/shared/meson.build index af903d3c..5f96d49d 100644 --- a/shared/meson.build +++ b/shared/meson.build @@ -1,353 +1,260 @@ shared_inc = include_directories('.') -############################################################################### +nm_default_dep = declare_dependency(include_directories: [top_inc, shared_inc]) -shared_c_stdaux = static_library( - 'c-stdaux', - c_args: '-std=c11', - sources: files('c-stdaux/src/c-stdaux.h'), +glib_nm_default_dep = declare_dependency(dependencies: [glib_dep, nm_default_dep]) + +libc_siphash = static_library( + 'c-siphash', + sources: 'c-siphash/src/c-siphash.c', + include_directories: include_directories('c-stdaux/src'), +) + +libc_rbtree = static_library( + 'c-rbtree', + sources: 'c-rbtree/src/c-rbtree.c', + include_directories: include_directories('c-stdaux/src'), + c_args: '-std=c11', ) -shared_c_stdaux_dep = declare_dependency( - include_directories: shared_inc, +sources = files( + 'n-acd/src/n-acd.c', + 'n-acd/src/n-acd-probe.c', + 'n-acd/src/util/timer.c', ) -############################################################################### +if enable_ebpf + sources += files('n-acd/src/n-acd-bpf.c') +else + sources += files('n-acd/src/n-acd-bpf-fallback.c') +endif -shared_c_siphash = static_library( - 'c-siphash', - include_directories: [ - include_directories('c-stdaux/src'), - ], - sources: 'c-siphash/src/c-siphash.c', +incs = include_directories( + 'c-list/src', + 'c-rbtree/src', + 'c-siphash/src', + 'c-stdaux/src', ) -shared_c_siphash_dep = declare_dependency( - include_directories: shared_inc, - link_with: shared_c_siphash, +c_flags = [ + '-D_GNU_SOURCE', + '-DSO_ATTACH_BPF=50', + '-std=c11', + '-Wno-pointer-arith', + '-Wno-vla', +] + +links = [ + libc_rbtree, + libc_siphash, +] + +libn_acd = static_library( + 'n-acd', + sources: sources, + include_directories: incs, + c_args: c_flags, + link_with: links, ) -############################################################################### - -shared_c_rbtree = static_library( - 'c-rbtree', - c_args: '-std=c11', - include_directories: [ - include_directories('c-stdaux/src'), - ], - sources: files('c-rbtree/src/c-rbtree.c', - 'c-rbtree/src/c-rbtree.h', - 'c-rbtree/src/c-rbtree-private.h'), +libn_acd_dep = declare_dependency( + include_directories: shared_inc, + link_with: libn_acd, ) -shared_c_rbtree_dep = declare_dependency( - include_directories: shared_inc, - link_with: shared_c_rbtree, +sources = files( + 'n-dhcp4/src/n-dhcp4-c-connection.c', + 'n-dhcp4/src/n-dhcp4-c-lease.c', + 'n-dhcp4/src/n-dhcp4-client.c', + 'n-dhcp4/src/n-dhcp4-c-probe.c', + 'n-dhcp4/src/n-dhcp4-incoming.c', + 'n-dhcp4/src/n-dhcp4-outgoing.c', + 'n-dhcp4/src/n-dhcp4-socket.c', + 'n-dhcp4/src/util/packet.c', + 'n-dhcp4/src/util/socket.c', ) -############################################################################### +incs = include_directories( + 'c-list/src', + 'c-siphash/src', + 'c-stdaux/src', +) -if enable_ebpf - shared_n_acd_bpf_files = files('n-acd/src/n-acd-bpf.c') -else - shared_n_acd_bpf_files = files('n-acd/src/n-acd-bpf-fallback.c') -endif +c_flags = [ + '-D_GNU_SOURCE', + '-Wno-declaration-after-statement', + '-Wno-pointer-arith', +] -shared_n_acd = static_library( - 'n-acd', - sources: files('n-acd/src/n-acd.c', - 'n-acd/src/n-acd.h', - 'n-acd/src/n-acd-private.h', - 'n-acd/src/n-acd-probe.c', - 'n-acd/src/util/timer.c', - 'n-acd/src/util/timer.h') - + shared_n_acd_bpf_files, - c_args: [ - '-D_GNU_SOURCE', - '-DSO_ATTACH_BPF=50', - '-std=c11', - '-Wno-pointer-arith', - '-Wno-vla', - ], - include_directories: [ - include_directories('c-stdaux/src'), - include_directories('c-siphash/src'), - include_directories('c-list/src'), - include_directories('c-rbtree/src'), - ], - dependencies: [ - shared_c_siphash_dep, - shared_c_rbtree_dep, - ], +libn_dhcp4 = static_library( + 'n-dhcp4', + sources: sources, + c_args: c_flags, + include_directories: incs, + link_with: libc_siphash, ) -shared_n_acd_dep = declare_dependency( - include_directories: shared_inc, - link_with: shared_n_acd, +libn_dhcp4_dep = declare_dependency( + include_directories: shared_inc, + link_with: libn_dhcp4, ) -############################################################################### - -shared_n_dhcp4 = static_library( - 'n-dhcp4', - sources: files('n-dhcp4/src/n-dhcp4-c-connection.c', - 'n-dhcp4/src/n-dhcp4-c-lease.c', - 'n-dhcp4/src/n-dhcp4-c-probe.c', - 'n-dhcp4/src/n-dhcp4-client.c', - 'n-dhcp4/src/n-dhcp4-incoming.c', - 'n-dhcp4/src/n-dhcp4-outgoing.c', - 'n-dhcp4/src/n-dhcp4-private.h', - 'n-dhcp4/src/n-dhcp4-socket.c', - 'n-dhcp4/src/n-dhcp4.h', - 'n-dhcp4/src/util/packet.c', - 'n-dhcp4/src/util/packet.h', - 'n-dhcp4/src/util/socket.c', - 'n-dhcp4/src/util/socket.h'), - c_args: [ - '-D_GNU_SOURCE', - '-Wno-declaration-after-statement', - '-Wno-pointer-arith', - ], - include_directories: [ - include_directories('c-list/src'), - include_directories('c-siphash/src'), - include_directories('c-stdaux/src'), - ], - dependencies: [ - shared_c_siphash_dep, - ], +nm_version_macro_header = configure_file( + input: 'nm-version-macros.h.in', + output: '@BASENAME@', + configuration: data_conf, ) -shared_n_dhcp4_dep = declare_dependency( - include_directories: shared_inc, - link_with: shared_n_dhcp4, -) +nm_ethtool_utils_source = files('nm-libnm-core-intern/nm-ethtool-utils.c') -############################################################################### +nm_libnm_core_aux_source = files('nm-libnm-core-aux/nm-libnm-core-aux.c') -version_conf = configuration_data() -version_conf.set('NM_MAJOR_VERSION', nm_major_version) -version_conf.set('NM_MINOR_VERSION', nm_minor_version) -version_conf.set('NM_MICRO_VERSION', nm_micro_version) +nm_libnm_core_utils_source = files('nm-libnm-core-intern/nm-libnm-core-utils.c') -version_header = configure_file( - input: 'nm-version-macros.h.in', - output: 'nm-version-macros.h', - configuration: version_conf, -) +nm_meta_setting_source = files('nm-meta-setting.c') -shared_nm_meta_setting_c = files('nm-meta-setting.c') +nm_test_utils_impl_source = files('nm-test-utils-impl.c') -shared_nm_test_utils_impl_c = files('nm-test-utils-impl.c') +nm_vpn_plugin_utils_source = files('nm-utils/nm-vpn-plugin-utils.c') -shared_nm_utils_nm_vpn_plugin_utils_c = files('nm-utils/nm-vpn-plugin-utils.c') +c_flags = [ + '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), + '-DNETWORKMANAGER_COMPILATION=0', +] -############################################################################### +libnm_std_aux = static_library( + 'nm-std-aux', + sources: 'nm-std-aux/c-list-util.c', + c_args: c_flags, +) -shared_nm_std_aux = static_library( - 'nm-std-aux', - sources: files('nm-std-aux/c-list-util.c'), - c_args: [ - '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), - '-DNETWORKMANAGER_COMPILATION=0', - ], - include_directories: [ - top_inc, - shared_inc, - ], - dependencies: [ - ], +sources = files( + 'nm-glib-aux/nm-dbus-aux.c', + 'nm-glib-aux/nm-dedup-multi.c', + 'nm-glib-aux/nm-enum-utils.c', + 'nm-glib-aux/nm-errno.c', + 'nm-glib-aux/nm-hash-utils.c', + 'nm-glib-aux/nm-io-utils.c', + 'nm-glib-aux/nm-json-aux.c', + 'nm-glib-aux/nm-keyfile-aux.c', + 'nm-glib-aux/nm-logging-base.c', + 'nm-glib-aux/nm-random-utils.c', + 'nm-glib-aux/nm-ref-string.c', + 'nm-glib-aux/nm-secret-utils.c', + 'nm-glib-aux/nm-shared-utils.c', + 'nm-glib-aux/nm-time-utils.c', ) -shared_nm_std_aux_dep = declare_dependency( - link_with: shared_nm_std_aux, - include_directories: [ - top_inc, - shared_inc, - ], +c_flags = [ + '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), + '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB)', +] + +links = [ + libc_siphash, + libnm_std_aux, +] + +libnm_utils_base = static_library( + 'nm-utils-base', + sources: sources, + dependencies: glib_nm_default_dep, + c_args: c_flags, + link_with: links, ) -############################################################################### +libnm_utils_base_dep = declare_dependency( + dependencies: glib_nm_default_dep, + link_with: libnm_utils_base, +) -shared_nm_glib_aux_c_args = [ - '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), - '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB)', +deps = [ + glib_nm_default_dep, + libudev_dep, ] -shared_nm_glib_aux = static_library( - 'nm-utils-base', - sources: files('nm-glib-aux/nm-dbus-aux.c', - 'nm-glib-aux/nm-dedup-multi.c', - 'nm-glib-aux/nm-enum-utils.c', - 'nm-glib-aux/nm-errno.c', - 'nm-glib-aux/nm-hash-utils.c', - 'nm-glib-aux/nm-io-utils.c', - 'nm-glib-aux/nm-json-aux.c', - 'nm-glib-aux/nm-keyfile-aux.c', - 'nm-glib-aux/nm-random-utils.c', - 'nm-glib-aux/nm-secret-utils.c', - 'nm-glib-aux/nm-shared-utils.c', - 'nm-glib-aux/nm-time-utils.c'), - c_args: shared_nm_glib_aux_c_args, - include_directories: [ - top_inc, - shared_inc, - ], - dependencies: [ - glib_dep, - shared_nm_std_aux_dep, - ], +libnm_udev_aux = static_library( + 'nm-udev-aux', + sources: 'nm-udev-aux/nm-udev-utils.c', + dependencies: deps, + c_args: c_flags, ) -shared_nm_glib_aux_dep = declare_dependency( - link_with: shared_nm_glib_aux, - include_directories: [ - top_inc, - shared_inc, - ], - dependencies: glib_dep, +libnm_udev_aux_dep = declare_dependency( + include_directories: shared_inc, + link_with: libnm_udev_aux, ) -############################################################################### - -shared_nm_udev_aux = static_library( - 'nm-udev-aux', - sources: files('nm-udev-aux/nm-udev-utils.c'), - c_args: shared_nm_glib_aux_c_args, - include_directories: [ - top_inc, - shared_inc, - ], - dependencies: [ - glib_dep, - shared_nm_glib_aux_dep, - libudev_dep, - ], +sources = files( + 'systemd/src/basic/alloc-util.c', + 'systemd/src/basic/escape.c', + 'systemd/src/basic/env-file.c', + 'systemd/src/basic/env-util.c', + 'systemd/src/basic/ether-addr-util.c', + 'systemd/src/basic/extract-word.c', + 'systemd/src/basic/fd-util.c', + 'systemd/src/basic/fileio.c', + 'systemd/src/basic/format-util.c', + 'systemd/src/basic/fs-util.c', + 'systemd/src/basic/hash-funcs.c', + 'systemd/src/basic/hashmap.c', + 'systemd/src/basic/hexdecoct.c', + 'systemd/src/basic/hostname-util.c', + 'systemd/src/basic/in-addr-util.c', + 'systemd/src/basic/io-util.c', + 'systemd/src/basic/memory-util.c', + 'systemd/src/basic/mempool.c', + 'systemd/src/basic/parse-util.c', + 'systemd/src/basic/path-util.c', + 'systemd/src/basic/prioq.c', + 'systemd/src/basic/process-util.c', + 'systemd/src/basic/random-util.c', + 'systemd/src/basic/socket-util.c', + 'systemd/src/basic/stat-util.c', + 'systemd/src/basic/string-table.c', + 'systemd/src/basic/string-util.c', + 'systemd/src/basic/strv.c', + 'systemd/src/basic/strxcpyx.c', + 'systemd/src/basic/time-util.c', + 'systemd/src/basic/tmpfile-util.c', + 'systemd/src/basic/utf8.c', + 'systemd/src/basic/util.c', + 'systemd/src/shared/dns-domain.c', + 'systemd/nm-sd-utils-shared.c', ) -shared_nm_udev_aux_dep = declare_dependency( - link_with: shared_nm_udev_aux, - include_directories: [ - top_inc, - shared_inc, - ], - dependencies: [ - glib_dep, - shared_nm_glib_aux_dep, - libudev_dep, - ], +incs = include_directories( + 'systemd/sd-adapt-shared', + 'systemd/src/basic', + 'systemd/src/shared', ) -############################################################################### +c_flags = [ + '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD_SHARED', +] libnm_systemd_shared = static_library( 'nm-systemd-shared', - sources: files( - 'systemd/src/basic/alloc-util.c', - 'systemd/src/basic/escape.c', - 'systemd/src/basic/env-file.c', - 'systemd/src/basic/env-util.c', - 'systemd/src/basic/ether-addr-util.c', - 'systemd/src/basic/extract-word.c', - 'systemd/src/basic/fd-util.c', - 'systemd/src/basic/fileio.c', - 'systemd/src/basic/format-util.c', - 'systemd/src/basic/fs-util.c', - 'systemd/src/basic/hash-funcs.c', - 'systemd/src/basic/hashmap.c', - 'systemd/src/basic/hexdecoct.c', - 'systemd/src/basic/hostname-util.c', - 'systemd/src/basic/in-addr-util.c', - 'systemd/src/basic/io-util.c', - 'systemd/src/basic/memory-util.c', - 'systemd/src/basic/mempool.c', - 'systemd/src/basic/parse-util.c', - 'systemd/src/basic/path-util.c', - 'systemd/src/basic/prioq.c', - 'systemd/src/basic/process-util.c', - 'systemd/src/basic/random-util.c', - 'systemd/src/basic/socket-util.c', - 'systemd/src/basic/stat-util.c', - 'systemd/src/basic/string-table.c', - 'systemd/src/basic/string-util.c', - 'systemd/src/basic/strv.c', - 'systemd/src/basic/strxcpyx.c', - 'systemd/src/basic/time-util.c', - 'systemd/src/basic/tmpfile-util.c', - 'systemd/src/basic/utf8.c', - 'systemd/src/basic/util.c', - 'systemd/src/shared/dns-domain.c', - 'systemd/nm-sd-utils-shared.c', - ), - include_directories: include_directories( - 'systemd/sd-adapt-shared', - 'systemd/src/basic', - 'systemd/src/shared', - ), - dependencies: shared_nm_glib_aux_dep, - c_args: [ - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD_SHARED', - '-DG_LOG_DOMAIN="libnm"', - ], + sources: sources, + include_directories: incs, + dependencies: glib_nm_default_dep, + c_args: c_flags, ) libnm_systemd_shared_dep = declare_dependency( - include_directories: include_directories( - 'systemd/sd-adapt-shared', - 'systemd/src/basic', - 'systemd/src/shared', - ), - dependencies: [ - shared_nm_glib_aux_dep, - ], - link_with: [ - libnm_systemd_shared, - ], + include_directories: incs, + dependencies: glib_dep, + link_with: libnm_systemd_shared, ) libnm_systemd_logging_stub = static_library( 'nm-systemd-logging-stub', - sources: files( - 'systemd/nm-logging-stub.c', - ), - include_directories: include_directories( - 'systemd/sd-adapt-shared', - 'systemd/src/basic', - ), - dependencies: shared_nm_glib_aux_dep, - c_args: [ - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD_SHARED', - '-DG_LOG_DOMAIN="libnm"', - ], -) - -libnm_systemd_shared_no_logging_dep = declare_dependency( - dependencies: [ - libnm_systemd_shared_dep, - ], - link_with: [ - libnm_systemd_logging_stub, - ], + sources: 'systemd/nm-logging-stub.c', + dependencies: glib_nm_default_dep, + c_args: c_flags, ) -############################################################################### - -exe = executable( - 'nm-utils/tests/test-shared-general', - [ 'nm-utils/tests/test-shared-general.c' ], - c_args: [ - '-DNETWORKMANAGER_COMPILATION_TEST', - '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)', - ], - dependencies: [ - shared_nm_glib_aux_dep, - libnm_systemd_shared_no_logging_dep, - shared_c_siphash_dep, - ], -) - -test( - 'shared/nm-utils/tests/test-shared-general', - test_script, - args: test_args + [exe.full_path()] -) +if enable_tests + subdir('nm-utils/tests') +endif diff --git a/shared/n-dhcp4/src/n-dhcp4-c-connection.c b/shared/n-dhcp4/src/n-dhcp4-c-connection.c index 5c50dacf..8a2ddb36 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-connection.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-connection.c @@ -513,6 +513,7 @@ static int n_dhcp4_c_connection_new_message(NDhcp4CConnection *connection, n_dhcp4_c_connection_init_header(connection, header); message->userdata.type = type; + message->userdata.message_type = message_type; /* * Note that some implementations expect the MESSAGE_TYPE option to be @@ -690,6 +691,7 @@ int n_dhcp4_c_connection_select_new(NDhcp4CConnection *connection, */ message->userdata.start_time = offer->userdata.start_time; message->userdata.base_time = offer->userdata.base_time; + message->userdata.client_addr = client.s_addr; n_dhcp4_incoming_get_xid(offer, &xid); n_dhcp4_outgoing_set_xid(message, xid); @@ -763,6 +765,7 @@ int n_dhcp4_c_connection_renew_new(NDhcp4CConnection *connection, if (r) return r; + message->userdata.client_addr = connection->client_ip; *requestp = message; message = NULL; return 0; @@ -796,6 +799,7 @@ int n_dhcp4_c_connection_rebind_new(NDhcp4CConnection *connection, if (r) return r; + message->userdata.client_addr = connection->client_ip; *requestp = message; message = NULL; return 0; @@ -847,6 +851,7 @@ int n_dhcp4_c_connection_decline_new(NDhcp4CConnection *connection, return r; } + message->userdata.client_addr = client.s_addr; *requestp = message; message = NULL; return 0; @@ -889,6 +894,7 @@ int n_dhcp4_c_connection_inform_new(NDhcp4CConnection *connection, if (r) return r; + message->userdata.client_addr = connection->client_ip; *requestp = message; message = NULL; return 0; @@ -955,9 +961,36 @@ int n_dhcp4_c_connection_release_new(NDhcp4CConnection *connection, return 0; } +static const char *message_type_to_str(uint8_t type) { + switch (type) { + case N_DHCP4_MESSAGE_DISCOVER: + return "DISCOVER"; + case N_DHCP4_MESSAGE_OFFER: + return "OFFER"; + case N_DHCP4_MESSAGE_REQUEST: + return "REQUEST"; + case N_DHCP4_MESSAGE_DECLINE: + return "DECLINE"; + case N_DHCP4_MESSAGE_ACK: + return "ACK"; + case N_DHCP4_MESSAGE_NAK: + return "NACK"; + case N_DHCP4_MESSAGE_RELEASE: + return "RELEASE"; + case N_DHCP4_MESSAGE_INFORM: + return "INFORM"; + case N_DHCP4_MESSAGE_FORCERENEW: + return "FORCERENEW"; + default: + return "UNKNOWN"; + } +} + static int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, NDhcp4Outgoing *request, uint64_t timestamp) { + char server_addr[INET_ADDRSTRLEN]; + char client_addr[INET_ADDRSTRLEN]; int r; /* @@ -1015,6 +1048,22 @@ static int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, c_assert(0); } + if (request->userdata.client_addr == INADDR_ANY) { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "sent %s to %s", + message_type_to_str(request->userdata.message_type), + inet_ntop(AF_INET, &connection->server_ip, + server_addr, sizeof(server_addr))); + } else { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "sent %s of %s to %s", + message_type_to_str(request->userdata.message_type), + inet_ntop(AF_INET, &request->userdata.client_addr, + client_addr, sizeof(client_addr)), + inet_ntop(AF_INET, &connection->server_ip, + server_addr, sizeof(server_addr))); + } + ++request->userdata.n_send; return 0; } @@ -1066,6 +1115,8 @@ int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection, int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, NDhcp4Incoming **messagep) { _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = NULL; + char serv_addr[INET_ADDRSTRLEN]; + char client_addr[INET_ADDRSTRLEN]; uint8_t type; int r; @@ -1118,6 +1169,22 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, if (r) return r; + if (type == N_DHCP4_MESSAGE_OFFER || type == N_DHCP4_MESSAGE_ACK) { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "received %s of %s from %s", + message_type_to_str(type), + inet_ntop(AF_INET, &message->message.header.yiaddr, + client_addr, sizeof(client_addr)), + inet_ntop(AF_INET, &message->message.header.siaddr, + serv_addr, sizeof(serv_addr))); + } else { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "received %s from %s", + message_type_to_str(type), + inet_ntop(AF_INET, &message->message.header.siaddr, + serv_addr, sizeof(serv_addr))); + } + switch (type) { case N_DHCP4_MESSAGE_OFFER: case N_DHCP4_MESSAGE_ACK: diff --git a/shared/n-dhcp4/src/n-dhcp4-c-lease.c b/shared/n-dhcp4/src/n-dhcp4-c-lease.c index c14a9daf..695a112a 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-lease.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-lease.c @@ -218,6 +218,18 @@ _c_public_ void n_dhcp4_client_lease_get_siaddr(NDhcp4ClientLease *lease, struct } /** + * n_dhcp4_client_lease_get_basetime() - get the timestamp when the lease was received. + * @lease: the lease to operate on + * @ns_basetimep: return argument for the base time in nano seconds + * + * Gets the timestamp when the lease was received in CLOCK_BOOTTIME. This + * is also the base timestamp for the expiration of the lifetime and t1/t2. + */ +_c_public_ void n_dhcp4_client_lease_get_basetime(NDhcp4ClientLease *lease, uint64_t *ns_basetimep) { + *ns_basetimep = lease->message->userdata.base_time; +} + +/** * n_dhcp4_client_lease_get_lifetime() - get the lifetime * @lease: the lease to operate on * @ns_lifetimep: return argument for the lifetime in nano seconds diff --git a/shared/n-dhcp4/src/n-dhcp4-c-probe.c b/shared/n-dhcp4/src/n-dhcp4-c-probe.c index 107c18bb..2bced4cf 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-probe.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-probe.c @@ -800,7 +800,8 @@ static int n_dhcp4_client_probe_transition_lifetime(NDhcp4ClientProbe *probe) { return 0; } -static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp4Incoming *message) { +static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp4Incoming *message_take) { + _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = message_take; _c_cleanup_(n_dhcp4_client_lease_unrefp) NDhcp4ClientLease *lease = NULL; NDhcp4CEventNode *node; int r; @@ -818,7 +819,7 @@ static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp if (r) return r; - /* message consumed, do not fail */ + message = NULL; /* consumed */ n_dhcp4_client_lease_link(lease, probe); @@ -843,7 +844,8 @@ static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp return 0; } -static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4Incoming *message) { +static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4Incoming *message_take) { + _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = message_take; _c_cleanup_(n_dhcp4_client_lease_unrefp) NDhcp4ClientLease *lease = NULL; NDhcp4CEventNode *node; int r; @@ -862,7 +864,7 @@ static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4I if (r) return r; - /* message consumed, do not fail */ + message = NULL; /* consumed */ n_dhcp4_client_lease_link(lease, probe); @@ -885,7 +887,7 @@ static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4I if (r) return r; - /* message consumed, don to fail */ + message = NULL; /* consumed */ n_dhcp4_client_lease_link(lease, probe); @@ -1100,16 +1102,17 @@ int n_dhcp4_client_probe_dispatch_timer(NDhcp4ClientProbe *probe, uint64_t ns_no r = n_dhcp4_client_probe_transition_lifetime(probe); if (r) return r; - } else if (ns_now >= probe->current_lease->t2) { + } else if (ns_now >= probe->current_lease->t2 && + probe->state != N_DHCP4_CLIENT_PROBE_STATE_REBINDING) { r = n_dhcp4_client_probe_transition_t2(probe, ns_now); if (r) return r; - } else if (ns_now >= probe->current_lease->t1) { + } else if (ns_now >= probe->current_lease->t1 && + probe->state == N_DHCP4_CLIENT_PROBE_STATE_BOUND) { r = n_dhcp4_client_probe_transition_t1(probe, ns_now); if (r) return r; } - break; default: /* ignore */ @@ -1167,17 +1170,15 @@ int n_dhcp4_client_probe_dispatch_io(NDhcp4ClientProbe *probe, uint32_t events) switch (type) { case N_DHCP4_MESSAGE_OFFER: r = n_dhcp4_client_probe_transition_offer(probe, message); + message = NULL; /* consumed */ if (r) return r; - else - message = NULL; /* consumed */ break; case N_DHCP4_MESSAGE_ACK: r = n_dhcp4_client_probe_transition_ack(probe, message); + message = NULL; /* consumed */ if (r) return r; - else - message = NULL; /* consumed */ break; case N_DHCP4_MESSAGE_NAK: r = n_dhcp4_client_probe_transition_nak(probe); diff --git a/shared/n-dhcp4/src/n-dhcp4-client.c b/shared/n-dhcp4/src/n-dhcp4-client.c index 5f7794fb..0bfe48ee 100644 --- a/shared/n-dhcp4/src/n-dhcp4-client.c +++ b/shared/n-dhcp4/src/n-dhcp4-client.c @@ -94,6 +94,9 @@ int n_dhcp4_client_config_dup(NDhcp4ClientConfig *config, NDhcp4ClientConfig **d dup->n_mac = config->n_mac; memcpy(dup->broadcast_mac, config->broadcast_mac, sizeof(dup->broadcast_mac)); dup->n_broadcast_mac = config->n_broadcast_mac; + dup->log.level = config->log.level; + dup->log.func = config->log.func; + dup->log.data = config->log.data; r = n_dhcp4_client_config_set_client_id(dup, config->client_id, @@ -248,6 +251,15 @@ _c_public_ int n_dhcp4_client_config_set_client_id(NDhcp4ClientConfig *config, c return 0; } +_c_public_ void n_dhcp4_client_config_set_log_level(NDhcp4ClientConfig *config, int level) { + config->log.level = level; +} + +_c_public_ void n_dhcp4_client_config_set_log_func(NDhcp4ClientConfig *config, NDhcp4LogFunc func, void *data) { + config->log.func = func; + config->log.data = data; +} + /** * n_dhcp4_c_event_node_new() - allocate new event * @nodep: output argument for new event @@ -376,8 +388,14 @@ _c_public_ int n_dhcp4_client_new(NDhcp4Client **clientp, NDhcp4ClientConfig *co return -errno; client->fd_timer = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK); - if (client->fd_timer < 0) - return -errno; + if (client->fd_timer < 0) { + if (errno != EINVAL) + return -errno; + client->fd_timer = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (client->fd_timer < 0) + return -errno; + client->timerfd_is_monotonic = true; + } ev.data.u32 = N_DHCP4_CLIENT_EPOLL_TIMER; r = epoll_ctl(client->fd_epoll, EPOLL_CTL_ADD, client->fd_timer, &ev); @@ -487,8 +505,24 @@ void n_dhcp4_client_arm_timer(NDhcp4Client *client) { n_dhcp4_client_probe_get_timeout(client->current_probe, &timeout); if (timeout != client->scheduled_timeout) { + uint64_t scheduled_timeout = timeout; + int flags = TFD_TIMER_ABSTIME; + + if ( timeout != 0 + && client->timerfd_is_monotonic) { + uint64_t now; + + /* the timerfd ticks with CLOCK_MONOTONIC. Calculate and set the relative + * timeout. */ + now = n_dhcp4_gettime(CLOCK_BOOTTIME); + if (timeout <= now) + timeout = 1; + else + timeout = timeout - now; + flags = 0; + } r = timerfd_settime(client->fd_timer, - TFD_TIMER_ABSTIME, + flags, &(struct itimerspec){ .it_value = { .tv_sec = timeout / UINT64_C(1000000000), @@ -498,7 +532,7 @@ void n_dhcp4_client_arm_timer(NDhcp4Client *client) { NULL); c_assert(r >= 0); - client->scheduled_timeout = timeout; + client->scheduled_timeout = scheduled_timeout; } } diff --git a/shared/n-dhcp4/src/n-dhcp4-incoming.c b/shared/n-dhcp4/src/n-dhcp4-incoming.c index 255da458..e7234c0a 100644 --- a/shared/n-dhcp4/src/n-dhcp4-incoming.c +++ b/shared/n-dhcp4/src/n-dhcp4-incoming.c @@ -365,10 +365,7 @@ static int n_dhcp4_incoming_query_u32(NDhcp4Incoming *message, uint8_t option, u memcpy(&be32, data, sizeof(be32)); - if (be32 == (uint32_t)-1) - *u32p = 0; - else - *u32p = ntohl(be32); + *u32p = ntohl(be32); return 0; } diff --git a/shared/n-dhcp4/src/n-dhcp4-private.h b/shared/n-dhcp4/src/n-dhcp4-private.h index c38ddbfc..1cf5f25e 100644 --- a/shared/n-dhcp4/src/n-dhcp4-private.h +++ b/shared/n-dhcp4/src/n-dhcp4-private.h @@ -11,6 +11,7 @@ #include <stdlib.h> #include <time.h> #include <unistd.h> +#include <syslog.h> #include "n-dhcp4.h" typedef struct NDhcp4CConnection NDhcp4CConnection; @@ -198,6 +199,8 @@ struct NDhcp4Outgoing { struct { uint8_t type; + uint8_t message_type; + uint32_t client_addr; uint64_t start_time; uint64_t base_time; uint64_t send_time; @@ -239,6 +242,11 @@ struct NDhcp4ClientConfig { size_t n_broadcast_mac; uint8_t *client_id; size_t n_client_id; + struct { + int level; + NDhcp4LogFunc func; + void *data; + } log; }; #define N_DHCP4_CLIENT_CONFIG_NULL(_x) { \ @@ -324,6 +332,7 @@ struct NDhcp4Client { uint64_t scheduled_timeout; bool preempted : 1; + bool timerfd_is_monotonic : 1; }; #define N_DHCP4_CLIENT_NULL(_x) { \ @@ -686,3 +695,19 @@ static inline uint64_t n_dhcp4_gettime(clockid_t clock) { return ts.tv_sec * 1000ULL * 1000ULL * 1000ULL + ts.tv_nsec; } + +#define n_dhcp4_c_log(_config, _level, ...) \ + do { \ + const NDhcp4ClientConfig *__config = _config; \ + \ + if (_level <= __config->log.level && __config->log.func) { \ + if (1) { \ + _config->log.func(_level, \ + __config->log.data, \ + __VA_ARGS__); \ + } else { \ + /* To have the compiler check arguments */ \ + printf(__VA_ARGS__); \ + } \ + } \ + } while (0) diff --git a/shared/n-dhcp4/src/n-dhcp4-socket.c b/shared/n-dhcp4/src/n-dhcp4-socket.c index b9ac176f..c7e89772 100644 --- a/shared/n-dhcp4/src/n-dhcp4-socket.c +++ b/shared/n-dhcp4/src/n-dhcp4-socket.c @@ -195,6 +195,10 @@ int n_dhcp4_c_socket_udp_new(int *sockfdp, if (sockfd < 0) return -errno; + r = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (r < 0) + return -errno; + r = setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; diff --git a/shared/n-dhcp4/src/n-dhcp4.h b/shared/n-dhcp4/src/n-dhcp4.h index ef75eca7..d3747662 100644 --- a/shared/n-dhcp4/src/n-dhcp4.h +++ b/shared/n-dhcp4/src/n-dhcp4.h @@ -29,6 +29,8 @@ typedef struct NDhcp4ServerEvent NDhcp4ServerEvent; typedef struct NDhcp4ServerIp NDhcp4ServerIp; typedef struct NDhcp4ServerLease NDhcp4ServerLease; +typedef void (*NDhcp4LogFunc)(int level, void *data, const char *fmt, ...); + #define N_DHCP4_CLIENT_START_DELAY_RFC2131 (UINT64_C(9000)) enum { @@ -111,6 +113,8 @@ void n_dhcp4_client_config_set_request_broadcast(NDhcp4ClientConfig *config, boo void n_dhcp4_client_config_set_mac(NDhcp4ClientConfig *config, const uint8_t *mac, size_t n_mac); void n_dhcp4_client_config_set_broadcast_mac(NDhcp4ClientConfig *config, const uint8_t *mac, size_t n_mac); int n_dhcp4_client_config_set_client_id(NDhcp4ClientConfig *config, const uint8_t *id, size_t n_id); +void n_dhcp4_client_config_set_log_level(NDhcp4ClientConfig *config, int level); +void n_dhcp4_client_config_set_log_func(NDhcp4ClientConfig *config, NDhcp4LogFunc func, void *data); /* client-probe configs */ @@ -157,6 +161,7 @@ NDhcp4ClientLease *n_dhcp4_client_lease_unref(NDhcp4ClientLease *lease); void n_dhcp4_client_lease_get_yiaddr(NDhcp4ClientLease *lease, struct in_addr *yiaddr); void n_dhcp4_client_lease_get_siaddr(NDhcp4ClientLease *lease, struct in_addr *siaddr); +void n_dhcp4_client_lease_get_basetime(NDhcp4ClientLease *lease, uint64_t *ns_basetimep); void n_dhcp4_client_lease_get_lifetime(NDhcp4ClientLease *lease, uint64_t *ns_lifetimep); int n_dhcp4_client_lease_query(NDhcp4ClientLease *lease, uint8_t option, uint8_t **datap, size_t *n_datap); diff --git a/shared/nm-default.h b/shared/nm-default.h index 16a756c2..ace6ede1 100644 --- a/shared/nm-default.h +++ b/shared/nm-default.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2015 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2015 Red Hat, Inc. */ #ifndef __NM_DEFAULT_H__ @@ -295,6 +280,10 @@ _nm_g_return_if_fail_warning (const char *log_domain, #include "nm-logging.h" #endif +#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE +#include "nm-libnm-utils.h" +#endif + #if ((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM) && !((NETWORKMANAGER_COMPILATION) & (NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_PRIVATE | NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_INTERNAL)) #include "NetworkManager.h" #endif diff --git a/shared/nm-glib-aux/nm-c-list.h b/shared/nm-glib-aux/nm-c-list.h index 7512730d..256dda74 100644 --- a/shared/nm-glib-aux/nm-c-list.h +++ b/shared/nm-glib-aux/nm-c-list.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2014 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NM_C_LIST_H__ @@ -32,6 +17,12 @@ _what && c_list_contains (list, &_what->member); \ }) +/* iterate over the list backwards. */ +#define nm_c_list_for_each_entry_prev(_iter, _list, _m) \ + for (_iter = c_list_entry ((_list)->prev, __typeof__ (*_iter), _m); \ + &(_iter)->_m != (_list); \ + _iter = c_list_entry ((_iter)->_m.prev, __typeof__ (*_iter), _m)) + /*****************************************************************************/ typedef struct { @@ -88,8 +79,25 @@ nm_c_list_elem_free_all (CList *head, GDestroyNotify free_fcn) nm_c_list_elem_free_full (elem, free_fcn); } +#define nm_c_list_elem_find_first(head, arg, predicate) \ + ({ \ + CList *const _head = (head); \ + NMCListElem *_result = NULL; \ + NMCListElem *_elem; \ + \ + c_list_for_each_entry (_elem, _head, lst) { \ + void *const arg = _elem->data; \ + \ + if (predicate) { \ + _result = _elem; \ + break; \ + } \ + } \ + _result; \ + }) + /** - * nm_c_list_elem_find_first: + * nm_c_list_elem_find_first_ptr: * @head: the @CList head of a list containing #NMCListElem elements. * Note that the head is not itself part of the list. * @needle: the needle pointer. @@ -100,15 +108,9 @@ nm_c_list_elem_free_all (CList *head, GDestroyNotify free_fcn) * Returns: the found list element or %NULL if not found. */ static inline NMCListElem * -nm_c_list_elem_find_first (CList *head, gconstpointer needle) +nm_c_list_elem_find_first_ptr (CList *head, gconstpointer needle) { - NMCListElem *elem; - - c_list_for_each_entry (elem, head, lst) { - if (elem->data == needle) - return elem; - } - return NULL; + return nm_c_list_elem_find_first (head, x, x == needle); } /*****************************************************************************/ diff --git a/shared/nm-glib-aux/nm-dbus-aux.c b/shared/nm-glib-aux/nm-dbus-aux.c index 083c4fee..75b282bc 100644 --- a/shared/nm-glib-aux/nm-dbus-aux.c +++ b/shared/nm-glib-aux/nm-dbus-aux.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" @@ -67,3 +52,315 @@ nm_dbus_connection_call_get_name_owner (GDBusConnection *dbus_connection, _nm_dbus_connection_call_get_name_owner_cb, nm_utils_user_data_pack (user_data, callback)); } + +/*****************************************************************************/ + +static void +_nm_dbus_connection_call_get_all_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + gpointer orig_user_data; + NMDBusConnectionCallDefaultCb callback; + + nm_utils_user_data_unpack (user_data, &orig_user_data, &callback); + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error); + + nm_assert ((!!ret) != (!!error)); + + callback (ret, error, orig_user_data); +} + +void +nm_dbus_connection_call_get_all (GDBusConnection *dbus_connection, + const char *bus_name, + const char *object_path, + const char *interface_name, + int timeout_msec, + GCancellable *cancellable, + NMDBusConnectionCallDefaultCb callback, + gpointer user_data) +{ + nm_assert (callback); + + g_dbus_connection_call (dbus_connection, + bus_name, + object_path, + DBUS_INTERFACE_PROPERTIES, + "GetAll", + g_variant_new ("(s)", interface_name), + G_VARIANT_TYPE ("(a{sv})"), + G_DBUS_CALL_FLAGS_NONE, + timeout_msec, + cancellable, + _nm_dbus_connection_call_get_all_cb, + nm_utils_user_data_pack (user_data, callback)); +} + +/*****************************************************************************/ + +typedef struct { + NMDBusConnectionSignalObjectMangerCb callback; + gpointer user_data; + GDestroyNotify user_data_free_func; +} SubscribeObjectManagerData; + +static void +_subscribe_object_manager_cb (GDBusConnection *connection, + const char *sender_name, + const char *arg_object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + const SubscribeObjectManagerData *d = user_data; + + nm_assert (nm_streq0 (interface_name, DBUS_INTERFACE_OBJECT_MANAGER)); + + if (nm_streq (signal_name, "InterfacesAdded")) { + gs_unref_variant GVariant *interfaces_and_properties = NULL; + const char *object_path; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oa{sa{sv}})"))) + return; + + g_variant_get (parameters, + "(&o@a{sa{sv}})", + &object_path, + &interfaces_and_properties); + + d->callback (object_path, interfaces_and_properties, NULL, d->user_data); + return; + } + + if (nm_streq (signal_name, "InterfacesRemoved")) { + gs_free const char **interfaces = NULL; + const char *object_path; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oas)"))) + return; + + g_variant_get (parameters, + "(&o^a&s)", + &object_path, + &interfaces); + + d->callback (object_path, NULL, interfaces, d->user_data); + return; + } +} + +static void +_subscribe_object_manager_data_free (gpointer ptr) +{ + SubscribeObjectManagerData *d = ptr; + + if (d->user_data_free_func) + d->user_data_free_func (d->user_data); + nm_g_slice_free (d); +} + +guint +nm_dbus_connection_signal_subscribe_object_manager (GDBusConnection *dbus_connection, + const char *service_name, + const char *object_path, + NMDBusConnectionSignalObjectMangerCb callback, + gpointer user_data, + GDestroyNotify user_data_free_func) +{ + SubscribeObjectManagerData *d; + + g_return_val_if_fail (callback, 0); + + d = g_slice_new (SubscribeObjectManagerData); + *d = (SubscribeObjectManagerData) { + .callback = callback, + .user_data = user_data, + .user_data_free_func = user_data_free_func, + }; + + return nm_dbus_connection_signal_subscribe_object_manager_plain (dbus_connection, + service_name, + object_path, + NULL, + _subscribe_object_manager_cb, + d, + _subscribe_object_manager_data_free); +} + +/*****************************************************************************/ + +static void +_nm_dbus_connection_call_get_managed_objects_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + gs_unref_variant GVariant *ret = NULL; + gs_unref_variant GVariant *arg = NULL; + gs_free_error GError *error = NULL; + gpointer orig_user_data; + NMDBusConnectionCallDefaultCb callback; + + nm_utils_user_data_unpack (user_data, &orig_user_data, &callback); + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error); + + nm_assert ((!!ret) != (!!error)); + + if (ret) { + nm_assert (g_variant_is_of_type (ret, G_VARIANT_TYPE ("(a{oa{sa{sv}}})"))); + arg = g_variant_get_child_value (ret, 0); + } + + callback (arg, error, orig_user_data); +} + +void +nm_dbus_connection_call_get_managed_objects (GDBusConnection *dbus_connection, + const char *bus_name, + const char *object_path, + GDBusCallFlags flags, + int timeout_msec, + GCancellable *cancellable, + NMDBusConnectionCallDefaultCb callback, + gpointer user_data) +{ + nm_assert (callback); + + g_dbus_connection_call (dbus_connection, + bus_name, + object_path, + DBUS_INTERFACE_OBJECT_MANAGER, + "GetManagedObjects", + NULL, + G_VARIANT_TYPE ("(a{oa{sa{sv}}})"), + flags, + timeout_msec, + cancellable, + _nm_dbus_connection_call_get_managed_objects_cb, + nm_utils_user_data_pack (user_data, callback)); +} + +/*****************************************************************************/ + +static void +_call_finish_cb (GObject *source, + GAsyncResult *result, + gpointer user_data, + gboolean return_void, + gboolean strip_dbus_error) +{ + gs_unref_object GTask *task = user_data; + gs_unref_variant GVariant *ret = NULL; + GError *error = NULL; + + nm_assert (G_IS_DBUS_CONNECTION (source)); + nm_assert (G_IS_TASK (user_data)); + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + if (!ret) { + if (strip_dbus_error) + g_dbus_error_strip_remote_error (error); + g_task_return_error (task, error); + return; + } + + if (!return_void) { + nm_assert (!g_variant_is_of_type (ret, G_VARIANT_TYPE ("()"))); + g_task_return_pointer (task, g_steal_pointer (&ret), (GDestroyNotify) g_variant_unref); + } else { + nm_assert (g_variant_is_of_type (ret, G_VARIANT_TYPE ("()"))); + g_task_return_boolean (task, TRUE); + } +} + +/** + * nm_dbus_connection_call_finish_void_cb: + * + * A default callback to pass as callback to g_dbus_connection_call(). + * + * - user_data must be a GTask, whose reference will be consumed by the + * callback. + * - the return GVariant must be a empty tuple "()". + * - the GTask is returned either with error or TRUE boolean. + */ +void +nm_dbus_connection_call_finish_void_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + _call_finish_cb (source, result, user_data, TRUE, FALSE); +} + +/** + * nm_dbus_connection_call_finish_void_strip_dbus_error_cb: + * + * Like nm_dbus_connection_call_finish_void_cb(). The difference + * is that on error this will first call g_dbus_error_strip_remote_error() on the error. + */ +void +nm_dbus_connection_call_finish_void_strip_dbus_error_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + _call_finish_cb (source, result, user_data, TRUE, TRUE); +} + +/** + * nm_dbus_connection_call_finish_variant_cb: + * + * A default callback to pass as callback to g_dbus_connection_call(). + * + * - user_data must be a GTask, whose reference will be consumed by the + * callback. + * - the return GVariant must not be an empty tuple "()". + * - the GTask is returned either with error or with a pointer containing the GVariant. + */ +void +nm_dbus_connection_call_finish_variant_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + _call_finish_cb (source, result, user_data, FALSE, FALSE); +} + +/** + * nm_dbus_connection_call_finish_variant_strip_dbus_error_cb: + * + * Like nm_dbus_connection_call_finish_variant_strip_dbus_error_cb(). The difference + * is that on error this will first call g_dbus_error_strip_remote_error() on the error. + */ +void +nm_dbus_connection_call_finish_variant_strip_dbus_error_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + _call_finish_cb (source, result, user_data, FALSE, TRUE); +} + +/*****************************************************************************/ + +gboolean +_nm_dbus_error_is (GError *error, ...) +{ + gs_free char *dbus_error = NULL; + const char *name; + va_list ap; + + dbus_error = g_dbus_error_get_remote_error (error); + if (!dbus_error) + return FALSE; + + va_start (ap, error); + while ((name = va_arg (ap, const char *))) { + if (nm_streq (dbus_error, name)) + return TRUE; + } + va_end (ap); + + return FALSE; +} diff --git a/shared/nm-glib-aux/nm-dbus-aux.h b/shared/nm-glib-aux/nm-dbus-aux.h index 271a7d9c..840e23c2 100644 --- a/shared/nm-glib-aux/nm-dbus-aux.h +++ b/shared/nm-glib-aux/nm-dbus-aux.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_DBUS_AUX_H__ @@ -42,6 +27,12 @@ nm_clear_g_dbus_connection_signal (GDBusConnection *dbus_connection, /*****************************************************************************/ +typedef void (*NMDBusConnectionCallDefaultCb) (GVariant *result, + GError *error, + gpointer user_data); + +/*****************************************************************************/ + static inline void nm_dbus_connection_call_start_service_by_name (GDBusConnection *dbus_connection, const char *name, @@ -91,11 +82,126 @@ typedef void (*NMDBusConnectionCallGetNameOwnerCb) (const char *name_owner, gpointer user_data); void nm_dbus_connection_call_get_name_owner (GDBusConnection *dbus_connection, - const char *service_name, - int timeout_msec, - GCancellable *cancellable, - NMDBusConnectionCallGetNameOwnerCb callback, - gpointer user_data); + const char *service_name, + int timeout_msec, + GCancellable *cancellable, + NMDBusConnectionCallGetNameOwnerCb callback, + gpointer user_data); + +static inline guint +nm_dbus_connection_signal_subscribe_properties_changed (GDBusConnection *dbus_connection, + const char *bus_name, + const char *object_path, + const char *interface_name, + GDBusSignalCallback callback, + gpointer user_data, + GDestroyNotify user_data_free_func) + +{ + nm_assert (bus_name); + + /* it seems that using a non-unique name causes problems that we get signals + * also from unrelated senders. Usually, you are anyway monitoring the name-owner, + * so you should have the unique name at hand. + * + * If not, investigate this, ensure that it works, and lift this restriction. */ + nm_assert (g_dbus_is_unique_name (bus_name)); + + return g_dbus_connection_signal_subscribe (dbus_connection, + bus_name, + DBUS_INTERFACE_PROPERTIES, + "PropertiesChanged", + object_path, + interface_name, + G_DBUS_SIGNAL_FLAGS_NONE, + callback, + user_data, + user_data_free_func); +} + +void nm_dbus_connection_call_get_all (GDBusConnection *dbus_connection, + const char *bus_name, + const char *object_path, + const char *interface_name, + int timeout_msec, + GCancellable *cancellable, + NMDBusConnectionCallDefaultCb callback, + gpointer user_data); + +/*****************************************************************************/ + +static inline guint +nm_dbus_connection_signal_subscribe_object_manager_plain (GDBusConnection *dbus_connection, + const char *service_name, + const char *object_path, + const char *signal_name, + GDBusSignalCallback callback, + gpointer user_data, + GDestroyNotify user_data_free_func) +{ + return g_dbus_connection_signal_subscribe (dbus_connection, + service_name, + DBUS_INTERFACE_OBJECT_MANAGER, + signal_name, + object_path, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + callback, + user_data, + user_data_free_func); +} + +typedef void (*NMDBusConnectionSignalObjectMangerCb) (const char *object_path, + GVariant *added_interfaces_and_properties, + const char *const*removed_interfaces, + gpointer user_data); + +guint nm_dbus_connection_signal_subscribe_object_manager (GDBusConnection *dbus_connection, + const char *service_name, + const char *object_path, + NMDBusConnectionSignalObjectMangerCb callback, + gpointer user_data, + GDestroyNotify user_data_free_func); + +void nm_dbus_connection_call_get_managed_objects (GDBusConnection *dbus_connection, + const char *bus_name, + const char *object_path, + GDBusCallFlags flags, + int timeout_msec, + GCancellable *cancellable, + NMDBusConnectionCallDefaultCb callback, + gpointer user_data); + +/*****************************************************************************/ + +void nm_dbus_connection_call_finish_void_cb (GObject *source, + GAsyncResult *result, + gpointer user_data); + +void nm_dbus_connection_call_finish_void_strip_dbus_error_cb (GObject *source, + GAsyncResult *result, + gpointer user_data); + +void nm_dbus_connection_call_finish_variant_cb (GObject *source, + GAsyncResult *result, + gpointer user_data); + +void nm_dbus_connection_call_finish_variant_strip_dbus_error_cb (GObject *source, + GAsyncResult *result, + gpointer user_data); + +/*****************************************************************************/ + +gboolean _nm_dbus_error_is (GError *error, ...) G_GNUC_NULL_TERMINATED; + +#define nm_dbus_error_is(error, ...) \ + ({ \ + GError *const _error = (error); \ + \ + _error && _nm_dbus_error_is (_error, __VA_ARGS__, NULL); \ + }) + +#define NM_DBUS_ERROR_NAME_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" /*****************************************************************************/ diff --git a/shared/nm-glib-aux/nm-dedup-multi.c b/shared/nm-glib-aux/nm-dedup-multi.c index 345062ca..6e23228e 100644 --- a/shared/nm-glib-aux/nm-dedup-multi.c +++ b/shared/nm-glib-aux/nm-dedup-multi.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-glib-aux/nm-dedup-multi.h b/shared/nm-glib-aux/nm-dedup-multi.h index ca15c516..6867ae79 100644 --- a/shared/nm-glib-aux/nm-dedup-multi.h +++ b/shared/nm-glib-aux/nm-dedup-multi.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_DEDUP_MULTI_H__ diff --git a/shared/nm-glib-aux/nm-enum-utils.c b/shared/nm-glib-aux/nm-enum-utils.c index b16267a5..e105a4f5 100644 --- a/shared/nm-glib-aux/nm-enum-utils.c +++ b/shared/nm-glib-aux/nm-enum-utils.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -225,7 +210,7 @@ _nm_utils_enum_from_str_full (GType type, char **err_token, const NMUtilsEnumValueInfo *value_infos) { - GTypeClass *klass; + nm_auto_unref_gtypeclass GTypeClass *klass = NULL; gboolean ret = FALSE; int value = 0; gs_free char *str_clone = NULL; @@ -317,7 +302,6 @@ _nm_utils_enum_from_str_full (GType type, NM_SET_OUT (err_token, !ret && s[0] ? g_strdup (s) : NULL); NM_SET_OUT (out_value, ret ? value : 0); - g_type_class_unref (klass); return ret; } diff --git a/shared/nm-glib-aux/nm-enum-utils.h b/shared/nm-glib-aux/nm-enum-utils.h index 20db07cc..d863dabd 100644 --- a/shared/nm-glib-aux/nm-enum-utils.h +++ b/shared/nm-glib-aux/nm-enum-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_ENUM_UTILS_H__ diff --git a/shared/nm-glib-aux/nm-errno.c b/shared/nm-glib-aux/nm-errno.c index 30eb9a8e..9133d87d 100644 --- a/shared/nm-glib-aux/nm-errno.c +++ b/shared/nm-glib-aux/nm-errno.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-glib-aux/nm-errno.h b/shared/nm-glib-aux/nm-errno.h index d77735a7..1d329b25 100644 --- a/shared/nm-glib-aux/nm-errno.h +++ b/shared/nm-glib-aux/nm-errno.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_ERRNO_H__ diff --git a/shared/nm-glib-aux/nm-glib.h b/shared/nm-glib-aux/nm-glib.h index bdb7ea5b..dfb75bf0 100644 --- a/shared/nm-glib-aux/nm-glib.h +++ b/shared/nm-glib-aux/nm-glib.h @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2008 - 2018 Red Hat, Inc. + * Copyright (C) 2008 - 2018 Red Hat, Inc. */ #ifndef __NM_GLIB_H__ @@ -569,6 +556,49 @@ _nm_g_value_unset (GValue *value) #define g_value_unset _nm_g_value_unset #endif +/* G_PID_FORMAT was added only in 2.53.5. Define it ourself. + * + * If this was about "pid_t", we would check SIZEOF_PID_T, and set + * PRIi32/PRIi16, like systemd does. But it's actually about + * GPid, which glib typedefs as an "int". + * + * There is a test_gpid() that check that GPid is really a typedef + * for int. */ +#undef G_PID_FORMAT +#define G_PID_FORMAT "i" + +/*****************************************************************************/ + +#if !GLIB_CHECK_VERSION (2, 57, 2) +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) +#endif + +/*****************************************************************************/ + +/* Glib implements g_atomic_pointer_compare_and_exchange() as a macro. + * For one, to inline the atomic operation and also to perform some type checks + * on the arguments. + * Depending on compiler and glib version, glib passes the arguments as they + * are to __atomic_compare_exchange_n(). Some clang version don't accept const + * pointers there. Reimplement the macro to get that right, but with stronger + * type checks (as we use typeof()). Had one job. */ +static inline gboolean +_g_atomic_pointer_compare_and_exchange (volatile void *atomic, + gconstpointer oldval, + gconstpointer newval) +{ + return g_atomic_pointer_compare_and_exchange ((void **) atomic, (void *) oldval, (void *) newval); +} +#undef g_atomic_pointer_compare_and_exchange +#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \ + ({ \ + typeof (atomic) const _atomic = (atomic); \ + typeof (*_atomic) const _oldval = (oldval); \ + typeof (*_atomic) const _newval = (newval); \ + \ + _g_atomic_pointer_compare_and_exchange (_atomic, _oldval, _newval); \ + }) + /*****************************************************************************/ #endif /* __NM_GLIB_H__ */ diff --git a/shared/nm-glib-aux/nm-hash-utils.c b/shared/nm-glib-aux/nm-hash-utils.c index a6158269..cd51bbaf 100644 --- a/shared/nm-glib-aux/nm-hash-utils.c +++ b/shared/nm-glib-aux/nm-hash-utils.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -201,6 +186,26 @@ nm_pstr_equal (gconstpointer a, gconstpointer b) } guint +nm_pint_hash (gconstpointer p) +{ + const int *s = p; + + if (!s) + return nm_hash_static (298377461u); + return nm_hash_val (1208815757u, *s); +} + +gboolean +nm_pint_equals (gconstpointer a, gconstpointer b) +{ + const int *s1 = a; + const int *s2 = a; + + return s1 == s2 + || (s1 && s2 && *s1 == *s2); +} + +guint nm_pdirect_hash (gconstpointer p) { const void *const*s = p; @@ -221,3 +226,34 @@ nm_pdirect_equal (gconstpointer a, gconstpointer b) && s2 && *s1 == *s2); } + +guint +nm_ppdirect_hash (gconstpointer p) +{ + const void *const*const*s = p; + + if (!s) + return nm_hash_static (396534869u); + if (!*s) + return nm_hash_static (1476102263u); + return nm_direct_hash (**s); +} + +gboolean +nm_ppdirect_equal (gconstpointer a, gconstpointer b) +{ + const void *const*const*s1 = a; + const void *const*const*s2 = b; + + if (s1 == s2) + return TRUE; + if (!s1 || !s2) + return FALSE; + + if (*s1 == *s2) + return TRUE; + if (!*s1 || !*s2) + return FALSE; + + return **s1 == **s2; +} diff --git a/shared/nm-glib-aux/nm-hash-utils.h b/shared/nm-glib-aux/nm-hash-utils.h index aa0a3d7c..21c5e584 100644 --- a/shared/nm-glib-aux/nm-hash-utils.h +++ b/shared/nm-glib-aux/nm-hash-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_HASH_UTILS_H__ @@ -293,13 +278,29 @@ gboolean nm_pstr_equal (gconstpointer a, gconstpointer b); /*****************************************************************************/ +/* nm_pint_*() are for hashing keys that are pointers to int values, + * that is, "const int *" types. */ + +guint nm_pint_hash (gconstpointer p); +gboolean nm_pint_equals (gconstpointer a, gconstpointer b); + +/*****************************************************************************/ + /* this hashes/compares the pointer value that we point to. Basically, - * (((const void *const*) a) == ((const void *const*) b)). */ + * (*((const void *const*) a) == *((const void *const*) b)). */ guint nm_pdirect_hash (gconstpointer p); gboolean nm_pdirect_equal (gconstpointer a, gconstpointer b); +/* this hashes/compares the direct pointer value by following pointers to + * pointers 2 times. + * (**((const void *const*const*) a) == **((const void *const*const*) b)). */ + +guint nm_ppdirect_hash (gconstpointer p); + +gboolean nm_ppdirect_equal (gconstpointer a, gconstpointer b); + /*****************************************************************************/ #define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x" @@ -311,15 +312,15 @@ gboolean nm_pdirect_equal (gconstpointer a, gconstpointer b); * * Note that there is a chance that two different pointer values hash to the same obfuscated * value. So beware of that when reviewing logs. However, such a collision is very unlikely. */ -#define nm_hash_obfuscate_ptr(static_seed, val) \ - ({ \ - NMHashState _h; \ - const void *_val_obf_ptr = (val); \ - \ - nm_hash_init (&_h, (static_seed)); \ - nm_hash_update_val (&_h, _val_obf_ptr); \ - nm_hash_complete_u64 (&_h); \ - }) +static inline guint64 +nm_hash_obfuscate_ptr (guint static_seed, gconstpointer val) +{ + NMHashState h; + + nm_hash_init (&h, static_seed); + nm_hash_update_val (&h, val); + return nm_hash_complete_u64 (&h); +} /* if you want to log obfuscated pointer for a certain context (like, NMPRuleManager * logging user-tags), then you are advised to use nm_hash_obfuscate_ptr() with your diff --git a/shared/nm-glib-aux/nm-io-utils.c b/shared/nm-glib-aux/nm-io-utils.c index 23133ec5..ec0cd4c8 100644 --- a/shared/nm-glib-aux/nm-io-utils.c +++ b/shared/nm-glib-aux/nm-io-utils.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -32,9 +17,9 @@ /*****************************************************************************/ -_nm_printf (3, 4) +_nm_printf (4, 5) static int -_get_contents_error (GError **error, int errsv, const char *format, ...) +_get_contents_error (GError **error, int errsv, int *out_errsv, const char *format, ...) { nm_assert (NM_ERRNO_NATIVE (errsv)); @@ -53,13 +38,17 @@ _get_contents_error (GError **error, int errsv, const char *format, ...) msg, nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); } - return -errsv; + + nm_assert (errsv > 0); + NM_SET_OUT (out_errsv, errsv); + + return FALSE; } -#define _get_contents_error_errno(error, ...) \ +#define _get_contents_error_errno(error, out_errsv, ...) \ ({ \ int _errsv = (errno); \ \ - _get_contents_error (error, _errsv, __VA_ARGS__); \ + _get_contents_error (error, _errsv, out_errsv, __VA_ARGS__); \ }) static char * @@ -110,21 +99,25 @@ _mem_realloc (char *old, gboolean do_bzero_mem, gsize cur_len, gsize new_len) * the NUL byte. That is, it reads only files up to a length of * @max_length - 1 bytes. * @length: optional output argument of the read file size. + * @out_errsv: (allow-none) (out): on error, a positive errno. or zero. + * @error: + * * * A reimplementation of g_file_get_contents() with a few differences: * - accepts an open fd, instead of a path name. This allows you to * use openat(). * - limits the maximum filesize to max_length. * - * Returns: a negative error code on failure. + * Returns: TRUE on success. */ -int +gboolean nm_utils_fd_get_contents (int fd, gboolean close_fd, gsize max_length, NMUtilsFileGetContentsFlags flags, char **contents, gsize *length, + int *out_errsv, GError **error) { nm_auto_close int fd_keeper = close_fd ? fd : -1; @@ -133,12 +126,14 @@ nm_utils_fd_get_contents (int fd, const bool do_bzero_mem = NM_FLAGS_HAS (flags, NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET); int errsv; - g_return_val_if_fail (fd >= 0, -EINVAL); - g_return_val_if_fail (contents, -EINVAL); - g_return_val_if_fail (!error || !*error, -EINVAL); + g_return_val_if_fail (fd >= 0, FALSE); + g_return_val_if_fail (contents && !*contents, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + + NM_SET_OUT (length, 0); if (fstat (fd, &stat_buf) < 0) - return _get_contents_error_errno (error, "failure during fstat"); + return _get_contents_error_errno (error, out_errsv, "failure during fstat"); if (!max_length) { /* default to a very large size, but not extreme */ @@ -151,23 +146,23 @@ nm_utils_fd_get_contents (int fd, ssize_t n_read; if (n_stat > max_length - 1) - return _get_contents_error (error, EMSGSIZE, "file too large (%zu+1 bytes with maximum %zu bytes)", n_stat, max_length); + return _get_contents_error (error, EMSGSIZE, out_errsv, "file too large (%zu+1 bytes with maximum %zu bytes)", n_stat, max_length); str = g_try_malloc (n_stat + 1); if (!str) - return _get_contents_error (error, ENOMEM, "failure to allocate buffer of %zu+1 bytes", n_stat); + return _get_contents_error (error, ENOMEM, out_errsv, "failure to allocate buffer of %zu+1 bytes", n_stat); n_read = nm_utils_fd_read_loop (fd, str, n_stat, TRUE); if (n_read < 0) { if (do_bzero_mem) nm_explicit_bzero (str, n_stat); - return _get_contents_error (error, -n_read, "error reading %zu bytes from file descriptor", n_stat); + return _get_contents_error (error, -n_read, out_errsv, "error reading %zu bytes from file descriptor", n_stat); } str[n_read] = '\0'; if (n_read < n_stat) { if (!(str = _mem_realloc (str, do_bzero_mem, n_stat + 1, n_read + 1))) - return _get_contents_error (error, ENOMEM, "failure to reallocate buffer with %zu bytes", n_read + 1); + return _get_contents_error (error, ENOMEM, out_errsv, "failure to reallocate buffer with %zu bytes", n_read + 1); } NM_SET_OUT (length, n_read); } else { @@ -181,13 +176,13 @@ nm_utils_fd_get_contents (int fd, else { fd2 = fcntl (fd, F_DUPFD_CLOEXEC, 0); if (fd2 < 0) - return _get_contents_error_errno (error, "error during dup"); + return _get_contents_error_errno (error, out_errsv, "error during dup"); } if (!(f = fdopen (fd2, "r"))) { errsv = errno; nm_close (fd2); - return _get_contents_error (error, errsv, "failure during fdopen"); + return _get_contents_error (error, errsv, out_errsv, "failure during fdopen"); } n_have = 0; @@ -201,14 +196,14 @@ nm_utils_fd_get_contents (int fd, if (ferror (f)) { if (do_bzero_mem) nm_explicit_bzero (buf, sizeof (buf)); - return _get_contents_error (error, errsv, "error during fread"); + return _get_contents_error (error, errsv, out_errsv, "error during fread"); } if ( n_have > G_MAXSIZE - 1 - n_read || n_have + n_read + 1 > max_length) { if (do_bzero_mem) nm_explicit_bzero (buf, sizeof (buf)); - return _get_contents_error (error, EMSGSIZE, "file stream too large (%zu+1 bytes with maximum %zu bytes)", + return _get_contents_error (error, EMSGSIZE, out_errsv, "file stream too large (%zu+1 bytes with maximum %zu bytes)", (n_have > G_MAXSIZE - 1 - n_read) ? G_MAXSIZE : n_have + n_read, max_length); } @@ -230,7 +225,7 @@ nm_utils_fd_get_contents (int fd, if (!(str = _mem_realloc (str, do_bzero_mem, old_n_alloc, n_alloc))) { if (do_bzero_mem) nm_explicit_bzero (buf, sizeof (buf)); - return _get_contents_error (error, ENOMEM, "failure to allocate buffer of %zu bytes", n_alloc); + return _get_contents_error (error, ENOMEM, out_errsv, "failure to allocate buffer of %zu bytes", n_alloc); } } @@ -247,7 +242,7 @@ nm_utils_fd_get_contents (int fd, str[n_have] = '\0'; if (n_have + 1 < n_alloc) { if (!(str = _mem_realloc (str, do_bzero_mem, n_alloc, n_have + 1))) - return _get_contents_error (error, ENOMEM, "failure to truncate buffer to %zu bytes", n_have + 1); + return _get_contents_error (error, ENOMEM, out_errsv, "failure to truncate buffer to %zu bytes", n_have + 1); } } @@ -255,7 +250,8 @@ nm_utils_fd_get_contents (int fd, } *contents = g_steal_pointer (&str); - return 0; + NM_SET_OUT (out_errsv, 0); + return TRUE; } /** @@ -270,54 +266,49 @@ nm_utils_fd_get_contents (int fd, * the NUL byte. That is, it reads only files up to a length of * @max_length - 1 bytes. * @length: optional output argument of the read file size. + * @out_errsv: (allow-none) (out): on error, a positive errno. or zero. + * @error: * * A reimplementation of g_file_get_contents() with a few differences: * - accepts an @dirfd to open @filename relative to that path via openat(). * - limits the maximum filesize to max_length. * - uses O_CLOEXEC on internal file descriptor + * - optionally returns the native errno on failure. * - * Returns: a negative error code on failure. + * Returns: TRUE on success. */ -int +gboolean nm_utils_file_get_contents (int dirfd, const char *filename, gsize max_length, NMUtilsFileGetContentsFlags flags, char **contents, gsize *length, + int *out_errsv, GError **error) { int fd; - int errsv; - char bstrerr[NM_STRERROR_BUFSIZE]; - g_return_val_if_fail (filename && filename[0], -EINVAL); + g_return_val_if_fail (filename && filename[0], FALSE); + g_return_val_if_fail (contents && !*contents, FALSE); + + NM_SET_OUT (length, 0); if (dirfd >= 0) { fd = openat (dirfd, filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { - errsv = errno; - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "Failed to open file \"%s\" with openat: %s", - filename, - nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); - return -NM_ERRNO_NATIVE (errsv); + return _get_contents_error_errno (error, + out_errsv, + "Failed to open file \"%s\" with openat", + filename); } } else { fd = open (filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { - errsv = errno; - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "Failed to open file \"%s\": %s", - filename, - nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); - return -NM_ERRNO_NATIVE (errsv); + return _get_contents_error_errno (error, + out_errsv, + "Failed to open file \"%s\"", + filename); } } return nm_utils_fd_get_contents (fd, @@ -326,6 +317,7 @@ nm_utils_file_get_contents (int dirfd, flags, contents, length, + out_errsv, error); } @@ -340,6 +332,7 @@ nm_utils_file_set_contents (const char *filename, const char *contents, gssize length, mode_t mode, + int *out_errsv, GError **error) { gs_free char *tmp_name = NULL; @@ -347,7 +340,6 @@ nm_utils_file_set_contents (const char *filename, int errsv; gssize s; int fd; - char bstrerr[NM_STRERROR_BUFSIZE]; g_return_val_if_fail (filename, FALSE); g_return_val_if_fail (contents || !length, FALSE); @@ -360,33 +352,26 @@ nm_utils_file_set_contents (const char *filename, tmp_name = g_strdup_printf ("%s.XXXXXX", filename); fd = g_mkstemp_full (tmp_name, O_RDWR | O_CLOEXEC, mode); if (fd < 0) { - errsv = errno; - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to create file %s: %s", - tmp_name, - nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); - return FALSE; + return _get_contents_error_errno (error, + out_errsv, + "failed to create file %s", + tmp_name); } while (length > 0) { s = write (fd, contents, length); if (s < 0) { - errsv = errno; + errsv = NM_ERRNO_NATIVE (errno); if (errsv == EINTR) continue; nm_close (fd); unlink (tmp_name); - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to write to file %s: %s", - tmp_name, - nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); - return FALSE; + return _get_contents_error (error, + errsv, + out_errsv, + "failed to write to file %s", + tmp_name); } g_assert (s <= length); @@ -404,34 +389,28 @@ nm_utils_file_set_contents (const char *filename, if ( lstat (filename, &statbuf) == 0 && statbuf.st_size > 0) { if (fsync (fd) != 0) { - errsv = errno; - + errsv = NM_ERRNO_NATIVE (errno); nm_close (fd); unlink (tmp_name); - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to fsync %s: %s", - tmp_name, - nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); - return FALSE; + return _get_contents_error (error, + errsv, + out_errsv, + "failed to fsync %s", + tmp_name); } } nm_close (fd); if (rename (tmp_name, filename)) { - errsv = errno; + errsv = NM_ERRNO_NATIVE (errno); unlink (tmp_name); - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "failed to rename %s to %s: %s", - tmp_name, - filename, - nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr))); - return FALSE; + return _get_contents_error (error, + errsv, + out_errsv, + "failed rename %s to %s", + tmp_name, + filename); } return TRUE; diff --git a/shared/nm-glib-aux/nm-io-utils.h b/shared/nm-glib-aux/nm-io-utils.h index 121fc481..18dc5f74 100644 --- a/shared/nm-glib-aux/nm-io-utils.h +++ b/shared/nm-glib-aux/nm-io-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_IO_UTILS_H__ @@ -37,26 +22,29 @@ typedef enum { NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET = (1 << 0), } NMUtilsFileGetContentsFlags; -int nm_utils_fd_get_contents (int fd, - gboolean close_fd, - gsize max_length, - NMUtilsFileGetContentsFlags flags, - char **contents, - gsize *length, - GError **error); - -int nm_utils_file_get_contents (int dirfd, - const char *filename, - gsize max_length, - NMUtilsFileGetContentsFlags flags, - char **contents, - gsize *length, - GError **error); +gboolean nm_utils_fd_get_contents (int fd, + gboolean close_fd, + gsize max_length, + NMUtilsFileGetContentsFlags flags, + char **contents, + gsize *length, + int *out_errsv, + GError **error); + +gboolean nm_utils_file_get_contents (int dirfd, + const char *filename, + gsize max_length, + NMUtilsFileGetContentsFlags flags, + char **contents, + gsize *length, + int *out_errsv, + GError **error); gboolean nm_utils_file_set_contents (const char *filename, const char *contents, gssize length, mode_t mode, + int *out_errsv, GError **error); struct stat; diff --git a/shared/nm-glib-aux/nm-jansson.h b/shared/nm-glib-aux/nm-jansson.h index d4642319..0a75cff5 100644 --- a/shared/nm-glib-aux/nm-jansson.h +++ b/shared/nm-glib-aux/nm-jansson.h @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_JANSSON_H__ diff --git a/shared/nm-glib-aux/nm-json-aux.c b/shared/nm-glib-aux/nm-json-aux.c index 6f04ef2b..a738ab72 100644 --- a/shared/nm-glib-aux/nm-json-aux.c +++ b/shared/nm-glib-aux/nm-json-aux.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-glib-aux/nm-json-aux.h b/shared/nm-glib-aux/nm-json-aux.h index 19d43ce4..ed3be376 100644 --- a/shared/nm-glib-aux/nm-json-aux.h +++ b/shared/nm-glib-aux/nm-json-aux.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_JSON_AUX_H__ diff --git a/shared/nm-glib-aux/nm-keyfile-aux.c b/shared/nm-glib-aux/nm-keyfile-aux.c index 989c773f..8b2af7a8 100644 --- a/shared/nm-glib-aux/nm-keyfile-aux.c +++ b/shared/nm-glib-aux/nm-keyfile-aux.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" @@ -186,7 +171,6 @@ nm_key_file_db_destroy (NMKeyFileDB *self) void nm_key_file_db_start (NMKeyFileDB *self) { - int r; gs_free char *contents = NULL; gsize contents_len; gs_free_error GError *error = NULL; @@ -196,14 +180,14 @@ nm_key_file_db_start (NMKeyFileDB *self) self->is_started = TRUE; - r = nm_utils_file_get_contents (-1, - self->filename, - 20*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - &contents_len, - &error); - if (r < 0) { + if (!nm_utils_file_get_contents (-1, + self->filename, + 20*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + &contents_len, + NULL, + &error)) { _LOGD ("failed to read \"%s\": %s", self->filename, error->message); return; } diff --git a/shared/nm-glib-aux/nm-keyfile-aux.h b/shared/nm-glib-aux/nm-keyfile-aux.h index 8563f4d1..0f729c72 100644 --- a/shared/nm-glib-aux/nm-keyfile-aux.h +++ b/shared/nm-glib-aux/nm-keyfile-aux.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_KEYFILE_AUX_H__ diff --git a/shared/nm-glib-aux/nm-logging-base.c b/shared/nm-glib-aux/nm-logging-base.c new file mode 100644 index 00000000..47b3e993 --- /dev/null +++ b/shared/nm-glib-aux/nm-logging-base.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#include "nm-default.h" + +#include "nm-logging-base.h" + +#include <syslog.h> + +/*****************************************************************************/ + +const LogLevelDesc level_desc[_LOGL_N] = { + [LOGL_TRACE] = { "TRACE", "<trace>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, }, + [LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, }, + [LOGL_INFO] = { "INFO", "<info>", LOG_INFO, G_LOG_LEVEL_INFO, }, + [LOGL_WARN] = { "WARN", "<warn>", LOG_WARNING, G_LOG_LEVEL_MESSAGE, }, + [LOGL_ERR] = { "ERR", "<error>", LOG_ERR, G_LOG_LEVEL_MESSAGE, }, + [_LOGL_OFF] = { "OFF", NULL, 0, 0, }, + [_LOGL_KEEP] = { "KEEP", NULL, 0, 0, }, +}; + +gboolean +_nm_log_parse_level (const char *level, + NMLogLevel *out_level) +{ + int i; + + if (!level) + return FALSE; + + for (i = 0; i < (int) G_N_ELEMENTS (level_desc); i++) { + if (!g_ascii_strcasecmp (level_desc[i].name, level)) { + NM_SET_OUT (out_level, i); + return TRUE; + } + } + + return FALSE; +} diff --git a/shared/nm-glib-aux/nm-logging-base.h b/shared/nm-glib-aux/nm-logging-base.h new file mode 100644 index 00000000..3d964a6e --- /dev/null +++ b/shared/nm-glib-aux/nm-logging-base.h @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#ifndef __NM_LOGGING_BASE_H__ +#define __NM_LOGGING_BASE_H__ + +#include "nm-logging-fwd.h" + +typedef struct { + const char *name; + const char *level_str; + + /* nm-logging uses syslog internally. Note that the three most-verbose syslog levels + * are LOG_DEBUG, LOG_INFO and LOG_NOTICE. Journal already highlights LOG_NOTICE + * as special. + * + * On the other hand, we have three levels LOGL_TRACE, LOGL_DEBUG and LOGL_INFO, + * which are regular messages not to be highlighted. For that reason, we must map + * LOGL_TRACE and LOGL_DEBUG both to syslog level LOG_DEBUG. */ + int syslog_level; + + GLogLevelFlags g_log_level; +} LogLevelDesc; + +extern const LogLevelDesc level_desc[_LOGL_N]; + +gboolean _nm_log_parse_level (const char *level, + NMLogLevel *out_level); + +#endif /* __NM_LOGGING_BASE_H__ */ diff --git a/shared/nm-glib-aux/nm-logging-fwd.h b/shared/nm-glib-aux/nm-logging-fwd.h index c60a20b5..47661788 100644 --- a/shared/nm-glib-aux/nm-logging-fwd.h +++ b/shared/nm-glib-aux/nm-logging-fwd.h @@ -1,26 +1,11 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2006 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#ifndef __NM_LOGGING_DEFINES_H__ -#define __NM_LOGGING_DEFINES_H__ +#ifndef __NM_LOGGING_FWD_H__ +#define __NM_LOGGING_FWD_H__ /* Log domains */ @@ -127,6 +112,19 @@ nm_log_level_from_syslog (int syslog_level) } } +static inline int +nm_log_level_to_syslog (NMLogLevel nm_level) +{ + switch (nm_level) { + case LOGL_ERR: return 3; /* LOG_ERR */ + case LOGL_WARN: return 4; /* LOG_WARN */ + case LOGL_INFO: return 5; /* LOG_NOTICE */ + case LOGL_DEBUG: return 6; /* LOG_INFO */ + case LOGL_TRACE: return 7; /* LOG_DEBUG */ + default: return 0; /* LOG_EMERG */ + } +} + /*****************************************************************************/ struct timespec; @@ -137,4 +135,120 @@ extern void _nm_utils_monotonic_timestamp_initialized (const struct timespec *tp gint64 offset_sec, gboolean is_boottime); -#endif /* __NM_LOGGING_DEFINES_H__ */ +/*****************************************************************************/ + +#define _LOGL_TRACE LOGL_TRACE +#define _LOGL_DEBUG LOGL_DEBUG +#define _LOGL_INFO LOGL_INFO +#define _LOGL_WARN LOGL_WARN +#define _LOGL_ERR LOGL_ERR + +/* This is the default definition of _NMLOG_ENABLED(). Special implementations + * might want to undef this and redefine it. */ +#define _NMLOG_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG_DOMAIN)) ) + +#define _LOGT(...) _NMLOG (_LOGL_TRACE, __VA_ARGS__) +#define _LOGD(...) _NMLOG (_LOGL_DEBUG, __VA_ARGS__) +#define _LOGI(...) _NMLOG (_LOGL_INFO , __VA_ARGS__) +#define _LOGW(...) _NMLOG (_LOGL_WARN , __VA_ARGS__) +#define _LOGE(...) _NMLOG (_LOGL_ERR , __VA_ARGS__) + +#define _LOGT_ENABLED(...) _NMLOG_ENABLED (_LOGL_TRACE, ##__VA_ARGS__) +#define _LOGD_ENABLED(...) _NMLOG_ENABLED (_LOGL_DEBUG, ##__VA_ARGS__) +#define _LOGI_ENABLED(...) _NMLOG_ENABLED (_LOGL_INFO , ##__VA_ARGS__) +#define _LOGW_ENABLED(...) _NMLOG_ENABLED (_LOGL_WARN , ##__VA_ARGS__) +#define _LOGE_ENABLED(...) _NMLOG_ENABLED (_LOGL_ERR , ##__VA_ARGS__) + +#define _LOGT_err(errsv, ...) _NMLOG_err (errsv, _LOGL_TRACE, __VA_ARGS__) +#define _LOGD_err(errsv, ...) _NMLOG_err (errsv, _LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_err(errsv, ...) _NMLOG_err (errsv, _LOGL_INFO , __VA_ARGS__) +#define _LOGW_err(errsv, ...) _NMLOG_err (errsv, _LOGL_WARN , __VA_ARGS__) +#define _LOGE_err(errsv, ...) _NMLOG_err (errsv, _LOGL_ERR , __VA_ARGS__) + +/* _LOGT() and _LOGt() both log with level TRACE, but the latter is disabled by default, + * unless building with --with-more-logging. */ +#if NM_MORE_LOGGING +#define _LOGt_ENABLED(...) _NMLOG_ENABLED (_LOGL_TRACE, ##__VA_ARGS__) +#define _LOGt(...) _NMLOG (_LOGL_TRACE, __VA_ARGS__) +#define _LOGt_err(errsv, ...) _NMLOG_err (errsv, _LOGL_TRACE, __VA_ARGS__) +#else +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOGt_ENABLED(...) ( FALSE && (_NMLOG_ENABLED (_LOGL_TRACE, ##__VA_ARGS__)) ) +#define _LOGt(...) G_STMT_START { if (FALSE) { _NMLOG (_LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#define _LOGt_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG_err (errsv, _LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#endif + +/*****************************************************************************/ + +/* Some implementation define a second set of logging macros, for a separate + * use. As with the _LOGD() macro family above, the exact implementation + * depends on the file that uses them. + * Still, it encourages a common pattern to have the common set of macros + * like _LOG2D(), _LOG2I(), etc. and have _LOG2t() which by default + * is disabled at compile time. */ + +#define _NMLOG2_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG2_DOMAIN)) ) + +#define _LOG2T(...) _NMLOG2 (_LOGL_TRACE, __VA_ARGS__) +#define _LOG2D(...) _NMLOG2 (_LOGL_DEBUG, __VA_ARGS__) +#define _LOG2I(...) _NMLOG2 (_LOGL_INFO , __VA_ARGS__) +#define _LOG2W(...) _NMLOG2 (_LOGL_WARN , __VA_ARGS__) +#define _LOG2E(...) _NMLOG2 (_LOGL_ERR , __VA_ARGS__) + +#define _LOG2T_ENABLED(...) _NMLOG2_ENABLED (_LOGL_TRACE, ##__VA_ARGS__) +#define _LOG2D_ENABLED(...) _NMLOG2_ENABLED (_LOGL_DEBUG, ##__VA_ARGS__) +#define _LOG2I_ENABLED(...) _NMLOG2_ENABLED (_LOGL_INFO , ##__VA_ARGS__) +#define _LOG2W_ENABLED(...) _NMLOG2_ENABLED (_LOGL_WARN , ##__VA_ARGS__) +#define _LOG2E_ENABLED(...) _NMLOG2_ENABLED (_LOGL_ERR , ##__VA_ARGS__) + +#define _LOG2T_err(errsv, ...) _NMLOG2_err (errsv, _LOGL_TRACE, __VA_ARGS__) +#define _LOG2D_err(errsv, ...) _NMLOG2_err (errsv, _LOGL_DEBUG, __VA_ARGS__) +#define _LOG2I_err(errsv, ...) _NMLOG2_err (errsv, _LOGL_INFO , __VA_ARGS__) +#define _LOG2W_err(errsv, ...) _NMLOG2_err (errsv, _LOGL_WARN , __VA_ARGS__) +#define _LOG2E_err(errsv, ...) _NMLOG2_err (errsv, _LOGL_ERR , __VA_ARGS__) + +#if NM_MORE_LOGGING +#define _LOG2t_ENABLED(...) _NMLOG2_ENABLED (_LOGL_TRACE, ##__VA_ARGS__) +#define _LOG2t(...) _NMLOG2 (_LOGL_TRACE, __VA_ARGS__) +#define _LOG2t_err(errsv, ...) _NMLOG2_err (errsv, _LOGL_TRACE, __VA_ARGS__) +#else +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOG2t_ENABLED(...) ( FALSE && (_NMLOG2_ENABLED (_LOGL_TRACE, ##__VA_ARGS__)) ) +#define _LOG2t(...) G_STMT_START { if (FALSE) { _NMLOG2 (_LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#define _LOG2t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG2_err (errsv, _LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#endif + +#define _NMLOG3_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG3_DOMAIN)) ) + +#define _LOG3T(...) _NMLOG3 (_LOGL_TRACE, __VA_ARGS__) +#define _LOG3D(...) _NMLOG3 (_LOGL_DEBUG, __VA_ARGS__) +#define _LOG3I(...) _NMLOG3 (_LOGL_INFO , __VA_ARGS__) +#define _LOG3W(...) _NMLOG3 (_LOGL_WARN , __VA_ARGS__) +#define _LOG3E(...) _NMLOG3 (_LOGL_ERR , __VA_ARGS__) + +#define _LOG3T_ENABLED(...) _NMLOG3_ENABLED (_LOGL_TRACE, ##__VA_ARGS__) +#define _LOG3D_ENABLED(...) _NMLOG3_ENABLED (_LOGL_DEBUG, ##__VA_ARGS__) +#define _LOG3I_ENABLED(...) _NMLOG3_ENABLED (_LOGL_INFO , ##__VA_ARGS__) +#define _LOG3W_ENABLED(...) _NMLOG3_ENABLED (_LOGL_WARN , ##__VA_ARGS__) +#define _LOG3E_ENABLED(...) _NMLOG3_ENABLED (_LOGL_ERR , ##__VA_ARGS__) + +#define _LOG3T_err(errsv, ...) _NMLOG3_err (errsv, _LOGL_TRACE, __VA_ARGS__) +#define _LOG3D_err(errsv, ...) _NMLOG3_err (errsv, _LOGL_DEBUG, __VA_ARGS__) +#define _LOG3I_err(errsv, ...) _NMLOG3_err (errsv, _LOGL_INFO , __VA_ARGS__) +#define _LOG3W_err(errsv, ...) _NMLOG3_err (errsv, _LOGL_WARN , __VA_ARGS__) +#define _LOG3E_err(errsv, ...) _NMLOG3_err (errsv, _LOGL_ERR , __VA_ARGS__) + +#if NM_MORE_LOGGING +#define _LOG3t_ENABLED(...) _NMLOG3_ENABLED (_LOGL_TRACE, ##__VA_ARGS__) +#define _LOG3t(...) _NMLOG3 (_LOGL_TRACE, __VA_ARGS__) +#define _LOG3t_err(errsv, ...) _NMLOG3_err (errsv, _LOGL_TRACE, __VA_ARGS__) +#else +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOG3t_ENABLED(...) ( FALSE && (_NMLOG3_ENABLED (_LOGL_TRACE, ##__VA_ARGS__)) ) +#define _LOG3t(...) G_STMT_START { if (FALSE) { _NMLOG3 (_LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#define _LOG3t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG3_err (errsv, _LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#endif + +/*****************************************************************************/ + +#endif /* __NM_LOGGING_FWD_H__ */ diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h index 9502c442..d1ea04c0 100644 --- a/shared/nm-glib-aux/nm-macros-internal.h +++ b/shared/nm-glib-aux/nm-macros-internal.h @@ -1,22 +1,7 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2012 Colin Walters <walters@verbum.org>. - * (C) Copyright 2014 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2012 Colin Walters <walters@verbum.org>. + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NM_MACROS_INTERNAL_H__ @@ -324,6 +309,12 @@ _nm_auto_protect_errno (int *p_saved_errno) NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_unref_gsource, g_source_unref); #define nm_auto_unref_gsource nm_auto(_nm_auto_unref_gsource) +NM_AUTO_DEFINE_FCN0 (guint, _nm_auto_remove_source, g_source_remove); +#define nm_auto_remove_source nm_auto(_nm_auto_remove_source) + +NM_AUTO_DEFINE_FCN0 (GIOChannel *, _nm_auto_unref_io_channel, g_io_channel_unref) +#define nm_auto_unref_io_channel nm_auto(_nm_auto_unref_io_channel) + NM_AUTO_DEFINE_FCN0 (GMainLoop *, _nm_auto_unref_gmainloop, g_main_loop_unref); #define nm_auto_unref_gmainloop nm_auto(_nm_auto_unref_gmainloop) @@ -644,6 +635,13 @@ NM_G_ERROR_MSG (GError *error) #define _NM_ENSURE_TYPE_CONST(type, value) ((const type) (value)) #endif +#if _NM_CC_SUPPORT_GENERIC && ( !defined (__clang__) || __clang_major__ > 3 ) +#define NM_STRUCT_OFFSET_ENSURE_TYPE(type, container, field) (_Generic ( (&(((container *) NULL)->field))[0] , \ + type: G_STRUCT_OFFSET (container, field))) +#else +#define NM_STRUCT_OFFSET_ENSURE_TYPE(type, container, field) G_STRUCT_OFFSET (container, field) +#endif + #if _NM_CC_SUPPORT_GENERIC /* these macros cast (value) to * - "const char **" (for "MC", mutable-const) @@ -1045,7 +1043,7 @@ _nm_gobject_notify_together_impl (obj_type *obj, guint n, const property_enums_t g_object_thaw_notify ((GObject *) obj); \ } \ \ -static inline void \ +_nm_unused static inline void \ _notify (obj_type *obj, property_enums_type prop) \ { \ _nm_gobject_notify_together_impl (obj, 1, &prop); \ @@ -1270,6 +1268,25 @@ nm_clear_g_cancellable_disconnect (GCancellable *cancellable, gulong *cancellabl /*****************************************************************************/ +static inline const char * +nm_dbus_path_not_empty (const char *str) +{ + nm_assert (!str || str[0] == '/'); + return !str || (str[0] == '/' && str[1] == '\0') + ? NULL + : str; +} + +/*****************************************************************************/ + +/* GVariantType is basically a C string. But G_VARIANT_TYPE() is not suitable + * to initialize a static variable (because it evaluates a function check that + * the string is valid). Add an alternative macro that does the plain cast. + * + * Here you loose the assertion check that G_VARIANT_TYPE() to ensure the + * string is valid. */ +#define NM_G_VARIANT_TYPE(fmt) ((const GVariantType *) (""fmt"")) + static inline GVariant * nm_g_variant_ref (GVariant *v) { @@ -1989,4 +2006,18 @@ nm_close (int fd) #define NM_PID_T_INVAL ((pid_t) -1) +/*****************************************************************************/ + +NM_AUTO_DEFINE_FCN_VOID0 (GMutex *, _nm_auto_unlock_g_mutex, g_mutex_unlock) + +#define nm_auto_unlock_g_mutex nm_auto (_nm_auto_unlock_g_mutex) + +#define _NM_G_MUTEX_LOCKED(lock, uniq) \ + nm_auto_unlock_g_mutex GMutex *NM_UNIQ_T(nm_lock, uniq) = (lock) + +#define NM_G_MUTEX_LOCKED(lock) \ + _NM_G_MUTEX_LOCKED (lock, NM_UNIQ) + +/*****************************************************************************/ + #endif /* __NM_MACROS_INTERNAL_H__ */ diff --git a/shared/nm-glib-aux/nm-obj.h b/shared/nm-glib-aux/nm-obj.h index 06016bdd..cbfdba63 100644 --- a/shared/nm-glib-aux/nm-obj.h +++ b/shared/nm-glib-aux/nm-obj.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_OBJ_H__ diff --git a/shared/nm-glib-aux/nm-random-utils.c b/shared/nm-glib-aux/nm-random-utils.c index f56f8b99..95063c94 100644 --- a/shared/nm-glib-aux/nm-random-utils.c +++ b/shared/nm-glib-aux/nm-random-utils.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-glib-aux/nm-random-utils.h b/shared/nm-glib-aux/nm-random-utils.h index 8e134ee9..056af38a 100644 --- a/shared/nm-glib-aux/nm-random-utils.h +++ b/shared/nm-glib-aux/nm-random-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_RANDOM_UTILS_H__ diff --git a/shared/nm-glib-aux/nm-ref-string.c b/shared/nm-glib-aux/nm-ref-string.c new file mode 100644 index 00000000..0a0b0d3a --- /dev/null +++ b/shared/nm-glib-aux/nm-ref-string.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#include "nm-default.h" + +#include "nm-ref-string.h" + +/*****************************************************************************/ + +typedef struct { + NMRefString r; + volatile int ref_count; + char str_data[]; +} RefString; + +G_LOCK_DEFINE_STATIC (gl_lock); +static GHashTable *gl_hash; + +/* the first field of NMRefString is a pointer to the NUL terminated string. + * This also allows to compare strings with nm_pstr_equal(), although, pointer + * equality might be better. */ +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMRefString, str) == 0); +G_STATIC_ASSERT (G_STRUCT_OFFSET (RefString, r) == 0); +G_STATIC_ASSERT (G_STRUCT_OFFSET (RefString, r.str) == 0); + +/*****************************************************************************/ + +static guint +_ref_string_hash (gconstpointer ptr) +{ + const RefString *a = ptr; + NMHashState h; + + nm_hash_init (&h, 1463435489u); + nm_hash_update (&h, a->r.str, a->r.len); + return nm_hash_complete (&h); +} + +static gboolean +_ref_string_equal (gconstpointer pa, gconstpointer pb) +{ + const RefString *a = pa; + const RefString *b = pb; + + return a->r.len == b->r.len + && memcmp (a->r.str, b->r.str, a->r.len) == 0; +} + +/*****************************************************************************/ + +static void +_ASSERT (const RefString *rstr0) +{ +#if NM_MORE_ASSERTS + int r; + + nm_assert (rstr0); + + G_LOCK (gl_lock); + r = g_atomic_int_get (&rstr0->ref_count); + + nm_assert (r > 0); + nm_assert (r < G_MAXINT); + + nm_assert (rstr0 == g_hash_table_lookup (gl_hash, rstr0)); + G_UNLOCK (gl_lock); +#endif +} + +/** + * nm_ref_string_new_len: + * @cstr: the string to intern. Must contain @len bytes. + * If @len is zero, @cstr may be %NULL. Note that it is + * accetable that the string contains a NUL character + * within the first @len bytes. That is, the string is + * not treated as a NUL terminated string, but as binary. + * Also, contrary to strncpy(), this will read all the + * first @len bytes. It won't stop at the first NUL. + * @len: the length of the string (usually there is no NUL character + * within the first @len bytes, but that would be acceptable as well + * to add binary data). + * + * Note that the resulting NMRefString instance will always be NUL terminated + * (at position @len). + * + * Note that NMRefString are always interned/deduplicated. If such a string + * already exists, the existing instance will be refered and returned. + * + * + * Since all NMRefString are shared and interned, you may use + * pointer equality to compare them. Note that if a NMRefString contains + * a NUL character (meaning, if + * + * strlen (nm_ref_string_get_str (str)) != nm_ref_string_get_len (str) + * + * ), then pointer in-equality does not mean that the NUL terminated strings + * are also unequal. In other words, for strings that contain NUL characters, + * + * if (str1 != str2) + * assert (!nm_streq0 (nm_ref_string_get_str (str1), nm_ref_string_get_str (str2))); + * + * might not hold! + * + * + * NMRefString is thread-safe. + * + * Returns: (transfer full): the interned string. This is + * never %NULL, but note that %NULL is also a valid NMRefString. + * The result must be unrefed with nm_ref_string_unref(). + */ +NMRefString * +nm_ref_string_new_len (const char *cstr, gsize len) +{ + RefString *rstr0; + + G_LOCK (gl_lock); + + if (G_UNLIKELY (!gl_hash)) { + gl_hash = g_hash_table_new_full (_ref_string_hash, _ref_string_equal, g_free, NULL); + rstr0 = NULL; + } else { + NMRefString rr_lookup = { + .len = len, + .str = cstr, + }; + + rstr0 = g_hash_table_lookup (gl_hash, &rr_lookup); + } + + if (rstr0) { + nm_assert (({ + int r = g_atomic_int_get (&rstr0->ref_count); + + (r >= 0 && r < G_MAXINT); + })); + g_atomic_int_inc (&rstr0->ref_count); + } else { + rstr0 = g_malloc (sizeof (RefString) + 1 + len); + rstr0->ref_count = 1; + *((gsize *) &rstr0->r.len) = len; + *((const char **) &rstr0->r.str) = rstr0->str_data; + if (len > 0) + memcpy (rstr0->str_data, cstr, len); + rstr0->str_data[len] = '\0'; + + if (!g_hash_table_add (gl_hash, rstr0)) + nm_assert_not_reached (); + } + + G_UNLOCK (gl_lock); + + return &rstr0->r; +} + +NMRefString * +nm_ref_string_ref (NMRefString *rstr) +{ + RefString *const rstr0 = (RefString *) rstr; + + if (!rstr) + return NULL; + + _ASSERT (rstr0); + + g_atomic_int_inc (&rstr0->ref_count); + return &rstr0->r; +} + +void +_nm_ref_string_unref_non_null (NMRefString *rstr) +{ + RefString *const rstr0 = (RefString *) rstr; + + _ASSERT (rstr0); + + if (G_LIKELY (!g_atomic_int_dec_and_test (&rstr0->ref_count))) + return; + + G_LOCK (gl_lock); + + /* in the fast-path above, we already decremented the ref-count to zero. + * We need recheck that the ref-count is still zero. */ + + if (g_atomic_int_get (&rstr0->ref_count) == 0) { + if (!g_hash_table_remove (gl_hash, rstr0)) + nm_assert_not_reached (); + } else { +#if NM_MORE_ASSERTS > 5 + nm_assert (g_hash_table_lookup (gl_hash, rstr0) == rstr0); +#endif + } + + G_UNLOCK (gl_lock); +} + +/*****************************************************************************/ diff --git a/shared/nm-glib-aux/nm-ref-string.h b/shared/nm-glib-aux/nm-ref-string.h new file mode 100644 index 00000000..c80b75ea --- /dev/null +++ b/shared/nm-glib-aux/nm-ref-string.h @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#ifndef __NM_REF_STRING_H__ +#define __NM_REF_STRING_H__ + +/*****************************************************************************/ + +typedef struct _NMRefString { + const char *const str; + const gsize len; +} NMRefString; + +/*****************************************************************************/ + +NMRefString *nm_ref_string_new_len (const char *cstr, gsize len); + +static inline NMRefString * +nm_ref_string_new (const char *cstr) +{ + return cstr + ? nm_ref_string_new_len (cstr, strlen (cstr)) + : NULL; +} + +NMRefString *nm_ref_string_ref (NMRefString *rstr); +void _nm_ref_string_unref_non_null (NMRefString *rstr); + +static inline void +nm_ref_string_unref (NMRefString *rstr) +{ + if (rstr) + _nm_ref_string_unref_non_null (rstr); +} + +NM_AUTO_DEFINE_FCN_VOID0 (NMRefString *, _nm_auto_ref_string, _nm_ref_string_unref_non_null) +#define nm_auto_ref_string nm_auto(_nm_auto_ref_string) + +/*****************************************************************************/ + +static inline const char * +nm_ref_string_get_str (NMRefString *rstr) +{ + return rstr ? rstr->str : NULL; +} + +static inline gsize +nm_ref_string_get_len (NMRefString *rstr) +{ + return rstr ? rstr->len : 0u; +} + +static inline gboolean +NM_IS_REF_STRING (const NMRefString *rstr) +{ +#if NM_MORE_ASSERTS > 10 + if (rstr) { + nm_auto_ref_string NMRefString *r2 = NULL; + + r2 = nm_ref_string_new_len (rstr->str, rstr->len); + nm_assert (rstr == r2); + } +#endif + + /* Technically, %NULL is also a valid NMRefString (according to nm_ref_string_new(), + * nm_ref_string_get_str() and nm_ref_string_unref()). However, NM_IS_REF_STRING() + * does not think so. If callers want to allow %NULL, they need to check + * separately. */ + return !!rstr; +} + +#endif /* __NM_REF_STRING_H__ */ diff --git a/shared/nm-glib-aux/nm-secret-utils.c b/shared/nm-glib-aux/nm-secret-utils.c index aeb88877..5b0afe46 100644 --- a/shared/nm-glib-aux/nm-secret-utils.c +++ b/shared/nm-glib-aux/nm-secret-utils.c @@ -1,22 +1,7 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. - * (C) Copyright 2015 - 2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. + * Copyright (C) 2015 - 2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */ #include "nm-default.h" diff --git a/shared/nm-glib-aux/nm-secret-utils.h b/shared/nm-glib-aux/nm-secret-utils.h index 0fd1ac8b..1b98b7e9 100644 --- a/shared/nm-glib-aux/nm-secret-utils.h +++ b/shared/nm-glib-aux/nm-secret-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_SECRET_UTILS_H__ diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c index 9bfd5ae2..8e1c8b58 100644 --- a/shared/nm-glib-aux/nm-shared-utils.c +++ b/shared/nm-glib-aux/nm-shared-utils.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2016 Red Hat, Inc. */ #include "nm-default.h" @@ -26,6 +11,7 @@ #include <poll.h> #include <fcntl.h> #include <sys/syscall.h> +#include <glib-unix.h> #include "nm-errno.h" @@ -555,6 +541,102 @@ _nm_utils_ip4_prefix_to_netmask (guint32 prefix) return prefix < 32 ? ~htonl(0xFFFFFFFF >> prefix) : 0xFFFFFFFF; } +gconstpointer +nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen) +{ + g_return_val_if_fail (dst, NULL); + + switch (family) { + case AF_INET: + g_return_val_if_fail (plen <= 32, NULL); + + if (!src) { + /* allow "self-assignment", by specifying %NULL as source. */ + src = dst; + } + + *((guint32 *) dst) = nm_utils_ip4_address_clear_host_address (*((guint32 *) src), plen); + break; + case AF_INET6: + nm_utils_ip6_address_clear_host_address (dst, src, plen); + break; + default: + g_return_val_if_reached (NULL); + } + return dst; +} + +/* nm_utils_ip4_address_clear_host_address: + * @addr: source ip6 address + * @plen: prefix length of network + * + * returns: the input address, with the host address set to 0. + */ +in_addr_t +nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen) +{ + return addr & _nm_utils_ip4_prefix_to_netmask (plen); +} + +/* nm_utils_ip6_address_clear_host_address: + * @dst: destination output buffer, will contain the network part of the @src address + * @src: source ip6 address + * @plen: prefix length of network + * + * Note: this function is self assignment safe, to update @src inplace, set both + * @dst and @src to the same destination or set @src NULL. + */ +const struct in6_addr * +nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen) +{ + g_return_val_if_fail (plen <= 128, NULL); + g_return_val_if_fail (dst, NULL); + + if (!src) + src = dst; + + if (plen < 128) { + guint nbytes = plen / 8; + guint nbits = plen % 8; + + if (nbytes && dst != src) + memcpy (dst, src, nbytes); + if (nbits) { + dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits))); + nbytes++; + } + if (nbytes <= 15) + memset (&dst->s6_addr[nbytes], 0, 16 - nbytes); + } else if (src != dst) + *dst = *src; + + return dst; +} + +int +nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen) +{ + int nbytes; + guint8 va, vb, m; + + if (plen >= 128) + NM_CMP_DIRECT_MEMCMP (addr_a, addr_b, sizeof (struct in6_addr)); + else { + nbytes = plen / 8; + if (nbytes) + NM_CMP_DIRECT_MEMCMP (addr_a, addr_b, nbytes); + + plen = plen % 8; + if (plen != 0) { + m = ~((1 << (8 - plen)) - 1); + va = ((((const guint8 *) addr_a))[nbytes]) & m; + vb = ((((const guint8 *) addr_b))[nbytes]) & m; + NM_CMP_DIRECT (va, vb); + } + } + return 0; +} + /** * _nm_utils_ip4_get_default_prefix: * @ip: an IPv4 address (in network byte order) @@ -601,11 +683,80 @@ nm_utils_ip_is_site_local (int addr_family, /*****************************************************************************/ +static gboolean +_parse_legacy_addr4 (const char *text, in_addr_t *out_addr) +{ + gs_free char *s_free = NULL; + struct in_addr a1; + guint8 bin[sizeof (a1)]; + char *s; + int i; + + if (inet_aton (text, &a1) != 1) + return FALSE; + + /* OK, inet_aton() accepted the format. That's good, because we want + * to accept IPv4 addresses in octal format, like 255.255.000.000. + * That's what "legacy" means here. inet_pton() doesn't accept those. + * + * But inet_aton() also ignores trailing garbage and formats with fewer than + * 4 digits. That is just too crazy and we don't do that. Perform additional checks + * and reject some forms that inet_aton() accepted. + * + * Note that we still should (of course) accept everything that inet_pton() + * accepts. However this code never gets called if inet_pton() succeeds + * (see below, aside the assertion code). */ + + if (NM_STRCHAR_ANY (text, ch, ( !(ch >= '0' && ch <= '9') + && !NM_IN_SET (ch, '.', 'x')))) { + /* We only accepts '.', digits, and 'x' for "0x". */ + return FALSE; + } + + s = nm_memdup_maybe_a (300, text, strlen (text) + 1, &s_free); + + for (i = 0; i < G_N_ELEMENTS (bin); i++) { + char *current_token = s; + gint32 v; + + s = strchr (s, '.'); + if (s) { + s[0] = '\0'; + s++; + } + + if ((i == G_N_ELEMENTS (bin) - 1) != (s == NULL)) { + /* Exactly for the last digit, we expect to have no more following token. + * But this isn't the case. Abort. */ + return FALSE; + } + + v = _nm_utils_ascii_str_to_int64 (current_token, 0, 0, 0xFF, -1); + if (v == -1) { + /* we do accept octal and hex (even with leading "0x"). But something + * about this token is wrong. */ + return FALSE; + } + + bin[i] = v; + } + + if (memcmp (bin, &a1, sizeof (bin)) != 0) { + /* our parsing did not agree with what inet_aton() gave. Something + * is wrong. Abort. */ + return FALSE; + } + + *out_addr = a1.s_addr; + return TRUE; +} + gboolean -nm_utils_parse_inaddr_bin (int addr_family, - const char *text, - int *out_addr_family, - gpointer out_addr) +nm_utils_parse_inaddr_bin_full (int addr_family, + gboolean accept_legacy, + const char *text, + int *out_addr_family, + gpointer out_addr) { NMIPAddr addrbin; @@ -617,8 +768,26 @@ nm_utils_parse_inaddr_bin (int addr_family, } else g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE); - if (inet_pton (addr_family, text, &addrbin) != 1) - return FALSE; + if (inet_pton (addr_family, text, &addrbin) != 1) { + if ( accept_legacy + && addr_family == AF_INET + && _parse_legacy_addr4 (text, &addrbin.addr4)) { + /* The address is in some legacy format which inet_aton() accepts, but not inet_pton(). + * Most likely octal digits (leading zeros). We accept the address. */ + } else + return FALSE; + } + +#if NM_MORE_ASSERTS > 10 + if (addr_family == AF_INET) { + in_addr_t a; + + /* The legacy parser should accept everything that inet_pton() accepts too. Meaning, + * it should strictly parse *more* formats. And of course, parse it the same way. */ + nm_assert (_parse_legacy_addr4 (text, &a)); + nm_assert (addrbin.addr4 == a); + } +#endif NM_SET_OUT (out_addr_family, addr_family); if (out_addr) @@ -2302,6 +2471,44 @@ nm_utils_hash_keys_to_array (GHashTable *hash, return keys; } +gpointer * +nm_utils_hash_values_to_array (GHashTable *hash, + GCompareDataFunc compare_func, + gpointer user_data, + guint *out_len) +{ + GHashTableIter iter; + gpointer value; + gpointer *arr; + guint i, len; + + if ( !hash + || (len = g_hash_table_size (hash)) == 0u) { + NM_SET_OUT (out_len, 0); + return NULL; + } + + arr = g_new (gpointer, ((gsize) len) + 1); + i = 0; + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &value)) + arr[i++] = value; + + nm_assert (i == len); + arr[len] = NULL; + + if ( len > 1 + && compare_func) { + g_qsort_with_data (arr, + len, + sizeof (gpointer), + compare_func, + user_data); + } + + return arr; +} + gboolean nm_utils_hashtable_same_keys (const GHashTable *a, const GHashTable *b) @@ -2370,6 +2577,10 @@ nm_utils_strv_make_deep_copied_n (const char **strv, gsize len) * is negative or zero (in which case %NULL will be returned). * @len: the length of strings in @str. If negative, strv is assumed * to be a NULL terminated array. + * @deep_copied: if %TRUE, clones the individual strings. In that case, + * the returned array must be freed with g_strfreev(). Otherwise, the + * strings themself are not copied. You must take care of who owns the + * strings yourself. * * Like g_strdupv(), with two differences: * @@ -2384,10 +2595,13 @@ nm_utils_strv_make_deep_copied_n (const char **strv, gsize len) * array with g_strfreev(). Allowing that would be error prone. * * Returns: (transfer full): a clone of the strv array. Always - * %NULL terminated. + * %NULL terminated. Depending on @deep_copied, the strings are + * cloned or not. */ char ** -nm_utils_strv_dup (gpointer strv, gssize len) +nm_utils_strv_dup (gpointer strv, + gssize len, + gboolean deep_copied) { gsize i, l; char **v; @@ -2415,7 +2629,10 @@ nm_utils_strv_dup (gpointer strv, gssize len) g_return_val_if_reached (v); } - v[i] = g_strdup (src[i]); + if (deep_copied) + v[i] = g_strdup (src[i]); + else + v[i] = (char *) src[i]; } v[l] = NULL; return v; @@ -2657,7 +2874,9 @@ nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid) g_return_val_if_fail (pid > 0, 0); - nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid); + G_STATIC_ASSERT_EXPR (sizeof (GPid) >= sizeof (pid_t)); + + nm_sprintf_buf (filename, "/proc/%"G_PID_FORMAT"/stat", (GPid) pid); if (!g_file_get_contents (filename, &contents, &length, NULL)) goto fail; @@ -2845,6 +3064,24 @@ nm_utils_g_slist_strlist_cmp (const GSList *a, const GSList *b) } } +char * +nm_utils_g_slist_strlist_join (const GSList *a, const char *separator) +{ + GString *str = NULL; + + if (!a) + return NULL; + + for (; a; a = a->next) { + if (!str) + str = g_string_new (NULL); + else + g_string_append (str, separator); + g_string_append (str, a->data); + } + return g_string_free (str, FALSE); +} + /*****************************************************************************/ gpointer @@ -3275,3 +3512,478 @@ nm_utils_gvariant_vardict_filter_drop_one (GVariant *src, _gvariant_vardict_filter_drop_one, (gpointer) key); } + +/*****************************************************************************/ + +static gboolean +debug_key_matches (const char *key, + const char *token, + guint length) +{ + /* may not call GLib functions: see note in g_parse_debug_string() */ + for (; length; length--, key++, token++) { + char k = (*key == '_') ? '-' : g_ascii_tolower (*key ); + char t = (*token == '_') ? '-' : g_ascii_tolower (*token); + + if (k != t) + return FALSE; + } + + return *key == '\0'; +} + +/** + * nm_utils_parse_debug_string: + * @string: the string to parse + * @keys: the debug keys + * @nkeys: number of entries in @keys + * + * Similar to g_parse_debug_string(), but does not special + * case "help" or "all". + * + * Returns: the flags + */ +guint +nm_utils_parse_debug_string (const char *string, + const GDebugKey *keys, + guint nkeys) +{ + guint i; + guint result = 0; + const char *q; + + if (string == NULL) + return 0; + + while (*string) { + q = strpbrk (string, ":;, \t"); + if (!q) + q = string + strlen (string); + + for (i = 0; i < nkeys; i++) { + if (debug_key_matches (keys[i].key, string, q - string)) + result |= keys[i].value; + } + + string = q; + if (*string) + string++; + } + + return result; +} + +/*****************************************************************************/ + +GSource * +nm_g_idle_source_new (int priority, + GSourceFunc func, + gpointer user_data, + GDestroyNotify destroy_notify) +{ + GSource *source; + + source = g_idle_source_new (); + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + g_source_set_callback (source, func, user_data, destroy_notify); + return source; +} + +GSource * +nm_g_timeout_source_new (guint timeout_ms, + int priority, + GSourceFunc func, + gpointer user_data, + GDestroyNotify destroy_notify) +{ + GSource *source; + + source = g_timeout_source_new (timeout_ms); + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + g_source_set_callback (source, func, user_data, destroy_notify); + return source; +} + +GSource * +nm_g_unix_signal_source_new (int signum, + int priority, + GSourceFunc handler, + gpointer user_data, + GDestroyNotify notify) +{ + GSource *source; + + source = g_unix_signal_source_new (signum); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + g_source_set_callback (source, handler, user_data, notify); + return source; +} + +/*****************************************************************************/ + +#define _CTX_LOG(fmt, ...) \ + G_STMT_START { \ + if (FALSE) { \ + gint64 _ts = g_get_monotonic_time () / 100; \ + \ + g_printerr (">>>> [%"G_GINT64_FORMAT".%05"G_GINT64_FORMAT"] [src:%p]: " fmt "\n", \ + _ts / 10000, \ + _ts % 10000, \ + (ctx_src), \ + ##__VA_ARGS__); \ + } \ + } G_STMT_END + +typedef struct { + int fd; + guint events; + guint registered_events; + union { + int one; + int *many; + } idx; + gpointer tag; + bool stale:1; + bool has_many_idx:1; +} PollData; + +typedef struct { + GSource source; + GMainContext *context; + GHashTable *fds; + GPollFD *fds_arr; + int fds_len; + int max_priority; + bool acquired:1; +} CtxIntegSource; + +static void +_poll_data_free (gpointer user_data) +{ + PollData *poll_data = user_data; + + if (poll_data->has_many_idx) + g_free (poll_data->idx.many); + nm_g_slice_free (poll_data); +} + +static void +_ctx_integ_source_reacquire (CtxIntegSource *ctx_src) +{ + if (G_LIKELY ( ctx_src->acquired + && g_main_context_is_owner (ctx_src->context))) + return; + + /* the parent context now iterates on a different thread. + * We need to release and reacquire the inner context. */ + + if (ctx_src->acquired) + g_main_context_release (ctx_src->context); + + if (G_UNLIKELY (!g_main_context_acquire (ctx_src->context))) { + /* Nobody is supposed to reacquire the context while we use it. This is a bug + * of the user. */ + ctx_src->acquired = FALSE; + g_return_if_reached (); + } + ctx_src->acquired = TRUE; +} + +static gboolean +_ctx_integ_source_prepare (GSource *source, + int *out_timeout) +{ + CtxIntegSource *ctx_src = ((CtxIntegSource *) source); + int max_priority; + int timeout = -1; + gboolean any_ready; + int fds_allocated; + int fds_len_old; + gs_free GPollFD *fds_arr_old = NULL; + GHashTableIter h_iter; + PollData *poll_data; + gboolean fds_changed; + int i; + + _CTX_LOG ("prepare..."); + + _ctx_integ_source_reacquire (ctx_src); + + any_ready = g_main_context_prepare (ctx_src->context, &max_priority); + + fds_arr_old = g_steal_pointer (&ctx_src->fds_arr); + fds_len_old = ctx_src->fds_len; + + fds_allocated = NM_MAX (1, fds_len_old); /* there is at least the wakeup's FD */ + ctx_src->fds_arr = g_new (GPollFD, fds_allocated); + + while ((ctx_src->fds_len = g_main_context_query (ctx_src->context, + max_priority, + &timeout, + ctx_src->fds_arr, + fds_allocated)) > fds_allocated) { + fds_allocated = ctx_src->fds_len; + g_free (ctx_src->fds_arr); + ctx_src->fds_arr = g_new (GPollFD, fds_allocated); + } + + fds_changed = FALSE; + if (fds_len_old != ctx_src->fds_len) + fds_changed = TRUE; + else { + for (i = 0; i < ctx_src->fds_len; i++) { + if ( fds_arr_old[i].fd != ctx_src->fds_arr[i].fd + || fds_arr_old[i].events != ctx_src->fds_arr[i].events) { + fds_changed = TRUE; + break; + } + } + } + + if (G_UNLIKELY (fds_changed)) { + + g_hash_table_iter_init (&h_iter, ctx_src->fds); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &poll_data, NULL)) + poll_data->stale = TRUE; + + for (i = 0; i < ctx_src->fds_len; i++) { + const GPollFD *fd = &ctx_src->fds_arr[i]; + + poll_data = g_hash_table_lookup (ctx_src->fds, &fd->fd); + + if (G_UNLIKELY (!poll_data)) { + poll_data = g_slice_new (PollData); + *poll_data = (PollData) { + .fd = fd->fd, + .idx.one = i, + .has_many_idx = FALSE, + .events = fd->events, + .registered_events = 0, + .tag = NULL, + .stale = FALSE, + }; + g_hash_table_add (ctx_src->fds, poll_data); + nm_assert (poll_data == g_hash_table_lookup (ctx_src->fds, &fd->fd)); + continue; + } + + if (G_LIKELY (poll_data->stale)) { + if (poll_data->has_many_idx) { + g_free (poll_data->idx.many); + poll_data->has_many_idx = FALSE; + } + poll_data->events = fd->events; + poll_data->idx.one = i; + poll_data->stale = FALSE; + continue; + } + + /* How odd. We have duplicate FDs. In fact, currently g_main_context_query() always + * coalesces the FDs and this cannot happen. However, that is not documented behavior, + * so we should not rely on that. So we need to keep a list of indexes... */ + poll_data->events |= fd->events; + if (!poll_data->has_many_idx) { + int idx0; + + idx0 = poll_data->idx.one; + poll_data->has_many_idx = TRUE; + poll_data->idx.many = g_new (int, 4); + poll_data->idx.many[0] = 2; /* number allocated */ + poll_data->idx.many[1] = 2; /* number used */ + poll_data->idx.many[2] = idx0; + poll_data->idx.many[3] = i; + } else { + if (poll_data->idx.many[0] == poll_data->idx.many[1]) { + poll_data->idx.many[0] *= 2; + poll_data->idx.many = g_realloc (poll_data->idx.many, sizeof (int) * (2 + poll_data->idx.many[0])); + } + poll_data->idx.many[2 + poll_data->idx.many[1]] = i; + poll_data->idx.many[1]++; + } + + } + + g_hash_table_iter_init (&h_iter, ctx_src->fds); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &poll_data, NULL)) { + if (poll_data->stale) { + nm_assert (poll_data->tag); + nm_assert (poll_data->events == poll_data->registered_events); + _CTX_LOG ("prepare: remove poll fd=%d, events=0x%x", poll_data->fd, poll_data->events); + g_source_remove_unix_fd (&ctx_src->source, poll_data->tag); + g_hash_table_iter_remove (&h_iter); + continue; + } + if (!poll_data->tag) { + _CTX_LOG ("prepare: add poll fd=%d, events=0x%x", poll_data->fd, poll_data->events); + poll_data->registered_events = poll_data->events; + poll_data->tag = g_source_add_unix_fd (&ctx_src->source, poll_data->fd, poll_data->registered_events); + continue; + } + if (poll_data->registered_events != poll_data->events) { + _CTX_LOG ("prepare: update poll fd=%d, events=0x%x", poll_data->fd, poll_data->events); + poll_data->registered_events = poll_data->events; + g_source_modify_unix_fd (&ctx_src->source, poll_data->tag, poll_data->registered_events); + } + } + } + + NM_SET_OUT (out_timeout, timeout); + ctx_src->max_priority = max_priority; + + _CTX_LOG ("prepare: done, any-ready=%d, timeout=%d, max-priority=%d", any_ready, timeout, max_priority); + + /* we always need to poll, because we have some file descriptors. */ + return FALSE; +} + +static gboolean +_ctx_integ_source_check (GSource *source) +{ + CtxIntegSource *ctx_src = ((CtxIntegSource *) source); + GHashTableIter h_iter; + gboolean some_ready; + PollData *poll_data; + + nm_assert (ctx_src->context); + + _CTX_LOG ("check"); + + _ctx_integ_source_reacquire (ctx_src); + + g_hash_table_iter_init (&h_iter, ctx_src->fds); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &poll_data, NULL)) { + guint revents; + + revents = g_source_query_unix_fd (&ctx_src->source, poll_data->tag); + if (G_UNLIKELY (poll_data->has_many_idx)) { + int num = poll_data->idx.many[1]; + int *p_idx = &poll_data->idx.many[2]; + + for (; num > 0; num--, p_idx++) + ctx_src->fds_arr[*p_idx].revents = revents; + } else + ctx_src->fds_arr[poll_data->idx.one].revents = revents; + } + + some_ready = g_main_context_check (ctx_src->context, + ctx_src->max_priority, + ctx_src->fds_arr, + ctx_src->fds_len); + + _CTX_LOG ("check (some-ready=%d)...", some_ready); + + return some_ready; +} + +static gboolean +_ctx_integ_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + CtxIntegSource *ctx_src = ((CtxIntegSource *) source); + + nm_assert (ctx_src->context); + + _ctx_integ_source_reacquire (ctx_src); + + _CTX_LOG ("dispatch"); + + g_main_context_dispatch (ctx_src->context); + + return G_SOURCE_CONTINUE; +} + +static void +_ctx_integ_source_finalize (GSource *source) +{ + CtxIntegSource *ctx_src = ((CtxIntegSource *) source); + GHashTableIter h_iter; + PollData *poll_data; + + g_return_if_fail (ctx_src->context); + + _CTX_LOG ("finalize..."); + + g_hash_table_iter_init (&h_iter, ctx_src->fds); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &poll_data, NULL)) { + nm_assert (poll_data->tag); + _CTX_LOG ("prepare: remove poll fd=%d, events=0x%x", poll_data->fd, poll_data->events); + g_source_remove_unix_fd (&ctx_src->source, poll_data->tag); + g_hash_table_iter_remove (&h_iter); + } + + nm_clear_pointer (&ctx_src->fds, g_hash_table_unref); + nm_clear_g_free (&ctx_src->fds_arr); + ctx_src->fds_len = 0; + + if (ctx_src->acquired) { + ctx_src->acquired = FALSE; + g_main_context_release (ctx_src->context); + } + + nm_clear_pointer (&ctx_src->context, g_main_context_unref); +} + +static GSourceFuncs ctx_integ_source_funcs = { + .prepare = _ctx_integ_source_prepare, + .check = _ctx_integ_source_check, + .dispatch = _ctx_integ_source_dispatch, + .finalize = _ctx_integ_source_finalize, +}; + +/** + * nm_utils_g_main_context_create_integrate_source: + * @inner_context: the inner context that will be integrated to an + * outer #GMainContext. + * + * By integrating the inner context with an outer context, when iterating the outer + * context sources on the inner context will be dispatched. Note that while the + * created source exists, the @inner_context will be acquired. The user gets restricted + * what to do with the inner context. In particular while the inner context is integrated, + * the user should not acquire the inner context again or explicitly iterate it. What + * the user of course still can (and wants to) do is attaching new sources to the inner + * context. + * + * Note that GSource has a priority. While each context dispatches events based on + * their source's priorities, the outer context dispatches to the inner context + * only with one priority (the priority of the created source). That is, the sources + * from the two contexts are kept separate and are not sorted by their priorities. + * + * Returns: a newly created GSource that should be attached to the + * outer context. + */ +GSource * +nm_utils_g_main_context_create_integrate_source (GMainContext *inner_context) +{ + CtxIntegSource *ctx_src; + + g_return_val_if_fail (inner_context, NULL); + + if (!g_main_context_acquire (inner_context)) { + /* We require to acquire the context while it's integrated. We need to keep it acquired + * for the entire duration. + * + * This is also necessary because g_source_attach() only wakes up the context, if + * the context is currently acquired. */ + g_return_val_if_reached (NULL); + } + + ctx_src = (CtxIntegSource *) g_source_new (&ctx_integ_source_funcs, sizeof (CtxIntegSource)); + + g_source_set_name (&ctx_src->source, "ContextIntegrateSource"); + + ctx_src->context = g_main_context_ref (inner_context); + ctx_src->fds = g_hash_table_new_full (nm_pint_hash, nm_pint_equals, _poll_data_free, NULL); + ctx_src->fds_len = 0; + ctx_src->fds_arr = NULL; + ctx_src->acquired = TRUE; + ctx_src->max_priority = G_MAXINT; + + _CTX_LOG ("create new integ-source for %p", inner_context); + + return &ctx_src->source; +} diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index d9c430d4..3bd1afae 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2016 Red Hat, Inc. */ #ifndef __NM_SHARED_UTILS_H__ @@ -104,6 +89,16 @@ nm_utils_addr_family_to_size (int addr_family) g_return_val_if_reached (0); } +static inline int +nm_utils_addr_family_from_size (gsize len) +{ + switch (len) { + case sizeof (in_addr_t): return AF_INET; + case sizeof (struct in6_addr): return AF_INET6; + } + return AF_UNSPEC; +} + #define nm_assert_addr_family(addr_family) \ nm_assert (NM_IN_SET ((addr_family), AF_INET, AF_INET6)) @@ -537,15 +532,29 @@ nm_utils_escaped_tokens_escape_gstr (const char *str, guint32 _nm_utils_ip4_prefix_to_netmask (guint32 prefix); guint32 _nm_utils_ip4_get_default_prefix (guint32 ip); +gconstpointer nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen); +in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen); +const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen); +int nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen); + gboolean nm_utils_ip_is_site_local (int addr_family, const void *address); /*****************************************************************************/ -gboolean nm_utils_parse_inaddr_bin (int addr_family, - const char *text, - int *out_addr_family, - gpointer out_addr); +gboolean nm_utils_parse_inaddr_bin_full (int addr_family, + gboolean accept_legacy, + const char *text, + int *out_addr_family, + gpointer out_addr); +static inline gboolean +nm_utils_parse_inaddr_bin (int addr_family, + const char *text, + int *out_addr_family, + gpointer out_addr) +{ + return nm_utils_parse_inaddr_bin_full (addr_family, FALSE, text, out_addr_family, out_addr); +} gboolean nm_utils_parse_inaddr (int addr_family, const char *text, @@ -652,8 +661,9 @@ _nm_g_slice_free_fcn_define (8) _nm_g_slice_free_fcn_define (10) _nm_g_slice_free_fcn_define (12) _nm_g_slice_free_fcn_define (16) +_nm_g_slice_free_fcn_define (32) -#define _nm_g_slice_free_fcn1(mem_size) \ +#define nm_g_slice_free_fcn1(mem_size) \ ({ \ void (*_fcn) (gpointer); \ \ @@ -666,7 +676,8 @@ _nm_g_slice_free_fcn_define (16) || ((mem_size) == 8) \ || ((mem_size) == 10) \ || ((mem_size) == 12) \ - || ((mem_size) == 16)); \ + || ((mem_size) == 16) \ + || ((mem_size) == 32)); \ switch ((mem_size)) { \ case 1: _fcn = _nm_g_slice_free_fcn_1; break; \ case 2: _fcn = _nm_g_slice_free_fcn_2; break; \ @@ -675,6 +686,7 @@ _nm_g_slice_free_fcn_define (16) case 10: _fcn = _nm_g_slice_free_fcn_10; break; \ case 12: _fcn = _nm_g_slice_free_fcn_12; break; \ case 16: _fcn = _nm_g_slice_free_fcn_16; break; \ + case 32: _fcn = _nm_g_slice_free_fcn_32; break; \ default: g_assert_not_reached (); _fcn = NULL; break; \ } \ _fcn; \ @@ -688,14 +700,38 @@ _nm_g_slice_free_fcn_define (16) * Returns: a function pointer with GDestroyNotify signature * for g_slice_free(type,*). * - * Only certain types are implemented. You'll get an assertion - * using the wrong type. */ -#define nm_g_slice_free_fcn(type) (_nm_g_slice_free_fcn1 (sizeof (type))) + * Only certain types are implemented. You'll get a compile time + * error for the wrong types. */ +#define nm_g_slice_free_fcn(type) (nm_g_slice_free_fcn1 (sizeof (type))) #define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn (gint64)) /*****************************************************************************/ +static inline void +nm_g_set_error_take (GError **error, GError *error_take) +{ + if (!error_take) + g_return_if_reached (); + if (!error) { + g_error_free (error_take); + return; + } + if (*error) { + g_error_free (error_take); + g_return_if_reached (); + } + *error = error_take; +} + +#define nm_g_set_error_take_lazy(error, error_take_lazy) \ + G_STMT_START { \ + GError **_error = (error); \ + \ + if (_error) \ + nm_g_set_error_take (_error, (error_take_lazy)); \ + } G_STMT_END + /** * NMUtilsError: * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error @@ -750,6 +786,17 @@ GQuark nm_utils_error_quark (void); void nm_utils_error_set_cancelled (GError **error, gboolean is_disposing, const char *instance_name); + +static inline GError * +nm_utils_error_new_cancelled (gboolean is_disposing, + const char *instance_name) +{ + GError *error = NULL; + + nm_utils_error_set_cancelled (&error, is_disposing, instance_name); + return error; +} + gboolean nm_utils_error_is_cancelled (GError *error, gboolean consider_is_disposing); @@ -792,6 +839,11 @@ nm_utils_error_set_literal (GError **error, int error_code, const char *literal) sizeof (_bstrerr))); \ } G_STMT_END +#define nm_utils_error_new(error_code, ...) \ + ( (NM_NARG (__VA_ARGS__) == 1) \ + ? g_error_new_literal (NM_UTILS_ERROR, (error_code), _NM_UTILS_MACRO_FIRST (__VA_ARGS__)) \ + : g_error_new (NM_UTILS_ERROR, (error_code), __VA_ARGS__)) + /*****************************************************************************/ gboolean nm_g_object_set_property (GObject *object, @@ -906,6 +958,82 @@ nm_g_variant_unref_floating (GVariant *var) g_variant_unref (var); } +static inline void +nm_g_source_destroy_and_unref (GSource *source) +{ + g_source_destroy (source); + g_source_unref (source); +} + +#define nm_clear_g_source_inst(ptr) (nm_clear_pointer ((ptr), nm_g_source_destroy_and_unref)) + +NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_destroy_and_unref_gsource, nm_g_source_destroy_and_unref); +#define nm_auto_destroy_and_unref_gsource nm_auto(_nm_auto_destroy_and_unref_gsource) + +NM_AUTO_DEFINE_FCN0 (GMainContext *, _nm_auto_pop_gmaincontext, g_main_context_pop_thread_default) +#define nm_auto_pop_gmaincontext nm_auto (_nm_auto_pop_gmaincontext) + +GSource *nm_g_idle_source_new (int priority, + GSourceFunc func, + gpointer user_data, + GDestroyNotify destroy_notify); + +GSource *nm_g_timeout_source_new (guint timeout_ms, + int priority, + GSourceFunc func, + gpointer user_data, + GDestroyNotify destroy_notify); + +GSource *nm_g_unix_signal_source_new (int signum, + int priority, + GSourceFunc handler, + gpointer user_data, + GDestroyNotify notify); + +static inline GSource * +nm_g_source_attach (GSource *source, + GMainContext *context) +{ + g_source_attach (source, context); + return source; +} + +NM_AUTO_DEFINE_FCN0 (GMainContext *, _nm_auto_unref_gmaincontext, g_main_context_unref) +#define nm_auto_unref_gmaincontext nm_auto (_nm_auto_unref_gmaincontext) + +static inline GMainContext * +nm_g_main_context_push_thread_default (GMainContext *context) +{ + /* This function is to work together with nm_auto_pop_gmaincontext. */ + if (G_UNLIKELY (!context)) + context = g_main_context_default (); + g_main_context_push_thread_default (context); + return context; +} + +static inline GMainContext * +nm_g_main_context_push_thread_default_if_necessary (GMainContext *context) +{ + GMainContext *cur_context; + + cur_context = g_main_context_get_thread_default (); + if (cur_context == context) + return NULL; + + if (G_UNLIKELY (!cur_context)) { + cur_context = g_main_context_default (); + if (cur_context == context) + return NULL; + } else if (G_UNLIKELY (!context)) { + context = g_main_context_default (); + if (cur_context == context) + return NULL; + } + + g_main_context_push_thread_default (context); + return context; +} + /*****************************************************************************/ static inline int @@ -966,6 +1094,11 @@ gpointer *nm_utils_hash_keys_to_array (GHashTable *hash, gpointer user_data, guint *out_len); +gpointer *nm_utils_hash_values_to_array (GHashTable *hash, + GCompareDataFunc compare_func, + gpointer user_data, + guint *out_len); + static inline const char ** nm_utils_strdict_get_keys (const GHashTable *hash, gboolean sorted, @@ -990,7 +1123,9 @@ nm_utils_strv_make_deep_copied_nonnull (const char **strv) return nm_utils_strv_make_deep_copied (strv) ?: g_new0 (char *, 1); } -char **nm_utils_strv_dup (gpointer strv, gssize len); +char **nm_utils_strv_dup (gpointer strv, + gssize len, + gboolean deep_copied); /*****************************************************************************/ @@ -999,6 +1134,8 @@ GSList *nm_utils_g_slist_find_str (const GSList *list, int nm_utils_g_slist_strlist_cmp (const GSList *a, const GSList *b); +char *nm_utils_g_slist_strlist_join (const GSList *a, const char *separator); + /*****************************************************************************/ gssize nm_utils_ptrarray_find_binary_search (gconstpointer *list, @@ -1160,6 +1297,15 @@ nm_utils_dbus_normalize_object_path (const char *path) guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid); +static inline gboolean +nm_utils_process_state_is_dead (char pstate) +{ + /* "/proc/[pid]/stat" returns a state as the 3rd fields (see `man 5 proc`). + * Some of these states indicate the the process is effectively dead (or a zombie). + */ + return NM_IN_SET (pstate, 'Z', 'x', 'X'); +} + /*****************************************************************************/ gpointer _nm_utils_user_data_pack (int nargs, gconstpointer *args); @@ -1183,6 +1329,10 @@ void nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback, /*****************************************************************************/ +GSource *nm_utils_g_main_context_create_integrate_source (GMainContext *internal); + +/*****************************************************************************/ + static inline void nm_strv_ptrarray_add_string_take (GPtrArray *cmd, char *str) @@ -1252,4 +1402,34 @@ guint8 *nm_utils_hexstr2bin_alloc (const char *hexstr, gsize required_len, gsize *out_len); +/*****************************************************************************/ + +static inline GTask * +nm_g_task_new (gpointer source_object, + GCancellable *cancellable, + gpointer source_tag, + GAsyncReadyCallback callback, + gpointer callback_data) +{ + GTask *task; + + task = g_task_new (source_object, cancellable, callback, callback_data); + if (source_tag) + g_task_set_source_tag (task, source_tag); + return task; +} + +static inline gboolean +nm_g_task_is_valid (gpointer task, + gpointer source_object, + gpointer source_tag) +{ + return g_task_is_valid (task, source_object) + && g_task_get_source_tag (task) == source_tag; +} + +guint nm_utils_parse_debug_string (const char *string, + const GDebugKey *keys, + guint nkeys); + #endif /* __NM_SHARED_UTILS_H__ */ diff --git a/shared/nm-glib-aux/nm-time-utils.c b/shared/nm-glib-aux/nm-time-utils.c index 7735f29d..20d663bc 100644 --- a/shared/nm-glib-aux/nm-time-utils.c +++ b/shared/nm-glib-aux/nm-time-utils.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -234,12 +219,17 @@ nm_utils_get_monotonic_timestamp_s (void) * @timestamp_ns_per_tick: How many nanoseconds make one unit of @timestamp? E.g. if * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; if @timestamp is * in nanoseconds, pass 1; if @timestamp is in milliseconds, pass %NM_UTILS_NS_PER_SECOND/1000. + * This must be a multiple of 10, and between 1 and %NM_UTILS_NS_PER_SECOND. * * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime(). * The unit is the same as the passed in @timestamp based on @timestamp_ns_per_tick. * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds. - * If @timestamp is non-positive, it returns -1. Note that a (valid) monotonic-timestamp - * is always positive. + * + * Note that valid monotonic-timestamps are always positive numbers (counting roughly since + * the application is running). However, it might make sense to calculate a timestamp from + * before the application was running, hence negative @timestamp is allowed. The result + * in that case might also be a negative timestamp (in CLOCK_BOOTTIME), which would indicate + * that the timestamp lies in the past before the machine was booted. * * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC. **/ @@ -256,9 +246,6 @@ nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_ timestamp_ns_per_tick % 10 == 0), -1); - /* Check that the timestamp is in a valid range. */ - g_return_val_if_fail (timestamp >= 0, -1); - /* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful * value (because he has no idea what these timestamps would be). That would be a bug. */ nm_assert (g_atomic_pointer_get (&p_global_state)); @@ -270,12 +257,60 @@ nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_ /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */ offset = p->offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick); - /* check for overflow. */ - g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64); + nm_assert (offset <= 0 && offset > G_MININT64); + + /* check for overflow (note that offset is non-positive). */ + g_return_val_if_fail (timestamp < G_MAXINT64 + offset, G_MAXINT64); return timestamp - offset; } +/** + * nm_utils_monotonic_timestamp_from_boottime: + * @boottime: the timestamp from CLOCK_BOOTTIME (or CLOCK_MONOTONIC, if + * kernel does not support CLOCK_BOOTTIME and monotonic timestamps are based + * on CLOCK_MONOTONIC). + * @timestamp_ns_per_tick: the scale in which @boottime is. If @boottime is in + * nano seconds, this should be 1. If it is in milli seconds, this should be + * %NM_UTILS_NS_PER_SECOND/1000, etc. + * + * Returns: the same timestamp in monotonic timestamp scale. + * + * Note that commonly monotonic timestamps are positive. But they may not + * be positive in this case. That's when boottime is taken from a time before + * the monotonic timestamps started counting. So, that means a zero or negative + * value is still a valid timestamp. + * + * This is the inverse of nm_utils_monotonic_timestamp_as_boottime(). + */ +gint64 +nm_utils_monotonic_timestamp_from_boottime (guint64 boottime, gint64 timestamp_ns_per_tick) +{ + const GlobalState *p; + gint64 offset; + + /* only support ns-per-tick being a multiple of 10. */ + g_return_val_if_fail (timestamp_ns_per_tick == 1 + || (timestamp_ns_per_tick > 0 && + timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND && + timestamp_ns_per_tick % 10 == 0), + -1); + + p = _t_get_global_state (); + + nm_assert (p->offset_sec <= 0); + + /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */ + offset = p->offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick); + + nm_assert (offset <= 0 && offset > G_MININT64); + + /* check for overflow (note that offset is non-positive). */ + g_return_val_if_fail (boottime < G_MAXINT64, G_MAXINT64); + + return (gint64) boottime + offset; +} + gint64 nm_utils_clock_gettime_ns (clockid_t clockid) { diff --git a/shared/nm-glib-aux/nm-time-utils.h b/shared/nm-glib-aux/nm-time-utils.h index 52d6637d..8bf41b96 100644 --- a/shared/nm-glib-aux/nm-time-utils.h +++ b/shared/nm-glib-aux/nm-time-utils.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_TIME_UTILS_H__ @@ -42,6 +27,7 @@ gint64 nm_utils_get_monotonic_timestamp_us (void); gint64 nm_utils_get_monotonic_timestamp_ms (void); gint32 nm_utils_get_monotonic_timestamp_s (void); gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns); +gint64 nm_utils_monotonic_timestamp_from_boottime (guint64 boottime, gint64 timestamp_ns_per_tick); static inline gint64 nm_utils_get_monotonic_timestamp_ns_cached (gint64 *cache_now) diff --git a/shared/nm-glib-aux/nm-value-type.h b/shared/nm-glib-aux/nm-value-type.h index b4d6898f..6fe6f072 100644 --- a/shared/nm-glib-aux/nm-value-type.h +++ b/shared/nm-glib-aux/nm-value-type.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_VALUE_TYPE_H__ diff --git a/shared/nm-libnm-core-aux/nm-dispatcher-api.h b/shared/nm-libnm-core-aux/nm-dispatcher-api.h index 0ee0f0a8..96f512e0 100644 --- a/shared/nm-libnm-core-aux/nm-dispatcher-api.h +++ b/shared/nm-libnm-core-aux/nm-dispatcher-api.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2012 Red Hat, Inc. */ diff --git a/shared/nm-libnm-core-aux/nm-libnm-core-aux.c b/shared/nm-libnm-core-aux/nm-libnm-core-aux.c index a04256b7..f827726f 100644 --- a/shared/nm-libnm-core-aux/nm-libnm-core-aux.c +++ b/shared/nm-libnm-core-aux/nm-libnm-core-aux.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-libnm-core-aux/nm-libnm-core-aux.h b/shared/nm-libnm-core-aux/nm-libnm-core-aux.h index d8960ad5..8a835205 100644 --- a/shared/nm-libnm-core-aux/nm-libnm-core-aux.h +++ b/shared/nm-libnm-core-aux/nm-libnm-core-aux.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_LIBNM_CORE_AUX_H__ diff --git a/shared/nm-libnm-core-intern/nm-common-macros.h b/shared/nm-libnm-core-intern/nm-common-macros.h index 8352e405..5f011efd 100644 --- a/shared/nm-libnm-core-intern/nm-common-macros.h +++ b/shared/nm-libnm-core-intern/nm-common-macros.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2016 Red Hat, Inc. */ #ifndef __NM_COMMON_MACROS_H__ @@ -56,6 +41,19 @@ NM_CLONED_MAC_IS_SPECIAL (const char *str) NM_CLONED_MAC_STABLE); } -/*****************************************************************************/ +#define NM_IAID_MAC "mac" +#define NM_IAID_PERM_MAC "perm-mac" +#define NM_IAID_IFNAME "ifname" +#define NM_IAID_STABLE "stable" + +static inline gboolean +NM_IAID_IS_SPECIAL (const char *str) +{ + return NM_IN_STRSET (str, + NM_IAID_MAC, + NM_IAID_PERM_MAC, + NM_IAID_IFNAME, + NM_IAID_STABLE); +} #endif /* __NM_COMMON_MACROS_H__ */ diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.c b/shared/nm-libnm-core-intern/nm-ethtool-utils.c index 635d77c5..2bc182cf 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.c +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.h b/shared/nm-libnm-core-intern/nm-ethtool-utils.h index 71ad9860..463d8e8f 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.h +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_ETHTOOL_UTILS_H__ diff --git a/shared/nm-libnm-core-intern/nm-libnm-core-utils.c b/shared/nm-libnm-core-intern/nm-libnm-core-utils.c index d1e5f754..9bf0b120 100644 --- a/shared/nm-libnm-core-intern/nm-libnm-core-utils.c +++ b/shared/nm-libnm-core-intern/nm-libnm-core-utils.c @@ -1,19 +1,4 @@ -/* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ +// SPDX-License-Identifier: LGPL-2.1+ #include "nm-default.h" diff --git a/shared/nm-libnm-core-intern/nm-libnm-core-utils.h b/shared/nm-libnm-core-intern/nm-libnm-core-utils.h index 35d6c5ad..42e9fc64 100644 --- a/shared/nm-libnm-core-intern/nm-libnm-core-utils.h +++ b/shared/nm-libnm-core-intern/nm-libnm-core-utils.h @@ -1,19 +1,4 @@ -/* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ +// SPDX-License-Identifier: LGPL-2.1+ #ifndef __NM_LIBNM_SHARED_UTILS_H__ #define __NM_LIBNM_SHARED_UTILS_H__ diff --git a/shared/nm-meta-setting.c b/shared/nm-meta-setting.c index d50739ba..af5aa842 100644 --- a/shared/nm-meta-setting.c +++ b/shared/nm-meta-setting.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2017 - 2018 Red Hat, Inc. + * Copyright (C) 2017 - 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-meta-setting.h b/shared/nm-meta-setting.h index 157a715f..3976bfe1 100644 --- a/shared/nm-meta-setting.h +++ b/shared/nm-meta-setting.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2017 - 2018 Red Hat, Inc. + * Copyright (C) 2017 - 2018 Red Hat, Inc. */ #ifndef __NM_META_SETTING_H__ diff --git a/shared/nm-std-aux/c-list-util.c b/shared/nm-std-aux/c-list-util.c index eb545b2d..a6741c4c 100644 --- a/shared/nm-std-aux/c-list-util.c +++ b/shared/nm-std-aux/c-list-util.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "c-list-util.h" diff --git a/shared/nm-std-aux/c-list-util.h b/shared/nm-std-aux/c-list-util.h index a1fe7169..d1aaa0b1 100644 --- a/shared/nm-std-aux/c-list-util.h +++ b/shared/nm-std-aux/c-list-util.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __C_LIST_UTIL_H__ diff --git a/shared/nm-std-aux/nm-dbus-compat.h b/shared/nm-std-aux/nm-dbus-compat.h index 8528bd07..bd010f45 100644 --- a/shared/nm-std-aux/nm-dbus-compat.h +++ b/shared/nm-std-aux/nm-dbus-compat.h @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. */ #ifndef __NM_DBUS_COMPAT_H__ @@ -44,6 +31,8 @@ /** The interface supported by most dbus peers */ #define DBUS_INTERFACE_PEER "org.freedesktop.DBus.Peer" +#define DBUS_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager" + /** This is a special interface whose methods can only be invoked * by the local implementation (messages from remote apps aren't * allowed to specify this interface). diff --git a/shared/nm-test-libnm-utils.h b/shared/nm-test-libnm-utils.h index 4c921f4c..63e3b4c7 100644 --- a/shared/nm-test-libnm-utils.h +++ b/shared/nm-test-libnm-utils.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2014 - 2015 Red Hat, Inc. + * Copyright (C) 2014 - 2015 Red Hat, Inc. */ #include "NetworkManager.h" @@ -81,3 +67,4 @@ void nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo, GVariant *connection, gboolean verify_connection); +NMClient *nmtstc_client_new (gboolean allow_iterate_main_context); diff --git a/shared/nm-test-utils-impl.c b/shared/nm-test-utils-impl.c index eca037ba..0805d0b9 100644 --- a/shared/nm-test-utils-impl.c +++ b/shared/nm-test-utils-impl.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2010 - 2015 Red Hat, Inc. - * + * Copyright (C) 2010 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -420,3 +406,192 @@ nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo, g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()"))); g_variant_unref (result); } + +/*****************************************************************************/ + +typedef struct { + GMainLoop *loop; + NMClient *client; +} NMTstcClientNewData; + +static void +_nmtstc_client_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMTstcClientNewData *d = user_data; + gs_free_error GError *error = NULL; + + g_assert (!d->client); + + d->client = nm_client_new_finish (res, + nmtst_get_rand_bool () ? &error : NULL); + + nmtst_assert_success (NM_IS_CLIENT (d->client), error); + + g_main_loop_quit (d->loop); +} + +static NMClient * +_nmtstc_client_new (gboolean sync) +{ + gs_free_error GError *error = NULL; + NMClient *client; + + /* Create a NMClient instance synchronously, and arbitrarily use either + * the sync or async constructor. + * + * Note that the sync and async construct differ in one important aspect: + * the async constructor iterates the current g_main_context_get_thread_default(), + * while the sync constructor does not! Aside from that, both should behave + * pretty much the same way. */ + + if (sync) { + nm_auto_destroy_and_unref_gsource GSource *source = NULL; + + if (nmtst_get_rand_bool ()) { + /* the current main context must not be iterated! */ + source = g_idle_source_new (); + g_source_set_callback (source, nmtst_g_source_assert_not_called, NULL, NULL); + g_source_attach (source, g_main_context_get_thread_default ()); + } + + if (nmtst_get_rand_bool ()) { + gboolean success; + + client = g_object_new (NM_TYPE_CLIENT, NULL); + g_assert (NM_IS_CLIENT (client)); + + success = g_initable_init (G_INITABLE (client), + NULL, + nmtst_get_rand_bool () ? &error : NULL); + nmtst_assert_success (success, error); + } else { + client = nm_client_new (NULL, + nmtst_get_rand_bool () ? &error : NULL); + } + } else { + nm_auto_unref_gmainloop GMainLoop *loop = NULL; + NMTstcClientNewData d = { .loop = NULL, }; + + loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + + d.loop = loop; + nm_client_new_async (NULL, + _nmtstc_client_new_cb, + &d); + g_main_loop_run (loop); + g_assert (NM_IS_CLIENT (d.client)); + client = d.client; + } + + nmtst_assert_success (NM_IS_CLIENT (client), error); + return client; +} + +typedef struct { + GMainLoop *loop; + NMClient *client; + bool sync; +} NewSyncInsideDispatchedData; + +static gboolean +_nmtstc_client_new_inside_loop_do (gpointer user_data) +{ + NewSyncInsideDispatchedData *d = user_data; + + g_assert (d->loop); + g_assert (!d->client); + + d->client = nmtstc_client_new (d->sync); + g_main_loop_quit (d->loop); + return G_SOURCE_CONTINUE; +} + +static NMClient * +_nmtstc_client_new_inside_loop (gboolean sync) +{ + GMainContext *context = g_main_context_get_thread_default (); + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new (context, FALSE); + NewSyncInsideDispatchedData d = { + .sync = sync, + .loop = loop, + }; + nm_auto_destroy_and_unref_gsource GSource *source = NULL; + + source = g_idle_source_new (); + g_source_set_callback (source, _nmtstc_client_new_inside_loop_do, &d, NULL); + g_source_attach (source, context); + + g_main_loop_run (loop); + g_assert (NM_IS_CLIENT (d.client)); + return d.client; +} + +static NMClient * +_nmtstc_client_new_extra_context (void) +{ + GMainContext *inner_context; + NMClient *client; + GSource *source; + guint key_idx; + + inner_context = g_main_context_new (); + g_main_context_push_thread_default (inner_context); + + client = nmtstc_client_new (TRUE); + + source = nm_utils_g_main_context_create_integrate_source (inner_context); + + g_main_context_pop_thread_default (inner_context); + g_main_context_unref (inner_context); + + g_source_attach (source, g_main_context_get_thread_default ()); + + for (key_idx = 0; TRUE; key_idx++) { + char s[100]; + + /* nmtstc_client_new() may call _nmtstc_client_new_extra_context() repeatedly. We + * need to attach the source to a previously unused key. */ + nm_sprintf_buf (s, "nm-test-extra-context-%u", key_idx); + if (!g_object_get_data (G_OBJECT (client), s)) { + g_object_set_data_full (G_OBJECT (client), + s, + source, + (GDestroyNotify) nm_g_source_destroy_and_unref); + break; + } + } + + return client; +} + +NMClient * +nmtstc_client_new (gboolean allow_iterate_main_context) +{ + gboolean inside_loop; + gboolean sync; + + if (nmtst_get_rand_uint32 () % 5 == 0) + return _nmtstc_client_new_extra_context (); + + if (!allow_iterate_main_context) { + sync = TRUE; + inside_loop = FALSE; + } else { + /* The caller allows to iterate the main context. That that point, + * we can both use the synchronous and the asynchronous initialization, + * both should yield the same result. Choose one randomly. */ + sync = nmtst_get_rand_bool (); + inside_loop = ((nmtst_get_rand_uint32 () % 3) == 0); + } + + if (inside_loop) { + /* Create the client on an idle handler of the current context. + * In practice, it should make no difference, which this check + * tries to prove. */ + return _nmtstc_client_new_inside_loop (sync); + } + + return _nmtstc_client_new (sync); +} diff --git a/shared/nm-udev-aux/nm-udev-utils.c b/shared/nm-udev-aux/nm-udev-utils.c index e9dfd8d0..1b0927df 100644 --- a/shared/nm-udev-aux/nm-udev-utils.c +++ b/shared/nm-udev-aux/nm-udev-utils.c @@ -1,19 +1,5 @@ -/* nm-udev-utils.c - udev utils functions - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/shared/nm-udev-aux/nm-udev-utils.h b/shared/nm-udev-aux/nm-udev-utils.h index 0e5895ef..92fce699 100644 --- a/shared/nm-udev-aux/nm-udev-utils.h +++ b/shared/nm-udev-aux/nm-udev-utils.h @@ -1,19 +1,5 @@ -/* nm-udev-utils.h - udev utils functions - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/shared/nm-utils/nm-compat.c b/shared/nm-utils/nm-compat.c index ea3e5392..895d9550 100644 --- a/shared/nm-utils/nm-compat.c +++ b/shared/nm-utils/nm-compat.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-utils/nm-compat.h b/shared/nm-utils/nm-compat.h index a8e3ee97..55f764c7 100644 --- a/shared/nm-utils/nm-compat.h +++ b/shared/nm-utils/nm-compat.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_COMPAT_H__ diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index d7a8788d..f0ea1179 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2014 Red Hat, Inc. + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NM_TEST_UTILS_H__ @@ -1024,6 +1010,34 @@ _nmtst_main_loop_quit_on_notify (GObject *object, GParamSpec *pspec, gpointer us } #define nmtst_main_loop_quit_on_notify ((GCallback) _nmtst_main_loop_quit_on_notify) +static inline gboolean +_nmtst_main_context_iterate_until_timeout (gpointer user_data) +{ + gboolean *p_had_pointer = user_data; + + g_assert (!*p_had_pointer); + *p_had_pointer = TRUE; + return G_SOURCE_CONTINUE; +} + +#define nmtst_main_context_iterate_until(context, timeout_ms, condition) \ + G_STMT_START { \ + nm_auto_destroy_and_unref_gsource GSource *_source = NULL; \ + GMainContext *_context = (context); \ + gboolean _had_timeout = FALSE; \ + \ + _source = g_timeout_source_new (timeout_ms); \ + g_source_set_callback (_source, _nmtst_main_context_iterate_until_timeout, &_had_timeout, NULL); \ + g_source_attach (_source, _context); \ + \ + while (TRUE) { \ + if (condition) \ + break; \ + g_main_context_iteration (_context, TRUE); \ + g_assert (!_had_timeout && #condition); \ + } \ + } G_STMT_END + /*****************************************************************************/ static inline const char * @@ -2297,4 +2311,13 @@ nmtst_keyfile_get_num_keys (GKeyFile *keyfile, /*****************************************************************************/ +static inline gboolean +nmtst_g_source_assert_not_called (gpointer user_data) +{ + g_assert_not_reached (); + return G_SOURCE_CONTINUE; +} + +/*****************************************************************************/ + #endif /* __NM_TEST_UTILS_H__ */ diff --git a/shared/nm-utils/nm-vpn-editor-plugin-call.h b/shared/nm-utils/nm-vpn-editor-plugin-call.h index ea5e27b0..ab473083 100644 --- a/shared/nm-utils/nm-vpn-editor-plugin-call.h +++ b/shared/nm-utils/nm-vpn-editor-plugin-call.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/shared/nm-utils/nm-vpn-plugin-macros.h b/shared/nm-utils/nm-vpn-plugin-macros.h index 97260f5f..f154147f 100644 --- a/shared/nm-utils/nm-vpn-plugin-macros.h +++ b/shared/nm-utils/nm-vpn-plugin-macros.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2016 Red Hat, Inc. + * Copyright (C) 2016 Red Hat, Inc. */ #ifndef __NM_VPN_PLUGIN_MACROS_H__ diff --git a/shared/nm-utils/nm-vpn-plugin-utils.c b/shared/nm-utils/nm-vpn-plugin-utils.c index afc05bdf..8616ae5f 100644 --- a/shared/nm-utils/nm-vpn-plugin-utils.c +++ b/shared/nm-utils/nm-vpn-plugin-utils.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2016,2018 Red Hat, Inc. + * Copyright (C) 2016, 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/nm-utils/nm-vpn-plugin-utils.h b/shared/nm-utils/nm-vpn-plugin-utils.h index 961e0187..2a31b677 100644 --- a/shared/nm-utils/nm-vpn-plugin-utils.h +++ b/shared/nm-utils/nm-vpn-plugin-utils.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2016 Red Hat, Inc. + * Copyright (C) 2016 Red Hat, Inc. */ #ifndef __NM_VPN_PLUGIN_UTILS_H__ diff --git a/shared/nm-utils/tests/meson.build b/shared/nm-utils/tests/meson.build new file mode 100644 index 00000000..1ee5efff --- /dev/null +++ b/shared/nm-utils/tests/meson.build @@ -0,0 +1,21 @@ +test_unit = 'test-shared-general' + +c_flags = [ + '-DNETWORKMANAGER_COMPILATION_TEST', + '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)', +] + +exe = executable( + test_unit, + test_unit + '.c', + c_args: c_flags, + dependencies: libnm_utils_base_dep, + link_with: libnm_systemd_logging_stub, +) + +test( + 'shared/nm-utils/' + test_unit, + test_script, + args: test_args + [exe.full_path()], + timeout: default_test_timeout, +) diff --git a/shared/nm-utils/tests/test-shared-general.c b/shared/nm-utils/tests/test-shared-general.c index 24affba7..34da19b3 100644 --- a/shared/nm-utils/tests/test-shared-general.c +++ b/shared/nm-utils/tests/test-shared-general.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #define NM_TEST_UTILS_NO_LIBNM 1 @@ -24,12 +10,38 @@ #include "nm-std-aux/unaligned.h" #include "nm-glib-aux/nm-random-utils.h" #include "nm-glib-aux/nm-time-utils.h" +#include "nm-glib-aux/nm-ref-string.h" #include "nm-utils/nm-test-utils.h" /*****************************************************************************/ static void +test_gpid (void) +{ + const int *int_ptr; + GPid pid = 42; + + /* We redefine G_PID_FORMAT, because it's only available since glib 2.53.5. + * + * Also, this is the format for GPid, which for glib is always a typedef + * for "int". Add a check for that here. + * + * G_PID_FORMAT is not about pid_t, which might be a smaller int, and which we would + * check with SIZEOF_PID_T. */ + G_STATIC_ASSERT (sizeof (GPid) == sizeof (int)); + + g_assert_cmpstr (""G_PID_FORMAT, ==, "i"); + + /* check that it's really "int". We will get a compiler warning, if that's not + * the case. */ + int_ptr = &pid; + g_assert_cmpint (*int_ptr, ==, 42); +} + +/*****************************************************************************/ + +static void test_monotonic_timestamp (void) { g_assert (nm_utils_get_monotonic_timestamp_s () > 0); @@ -510,12 +522,45 @@ test_nm_utils_bin2hexstr (void) /*****************************************************************************/ +static void +test_nm_ref_string (void) +{ + nm_auto_ref_string NMRefString *s1 = NULL; + NMRefString *s2; + + s1 = nm_ref_string_new ("hallo"); + g_assert (s1); + g_assert_cmpstr (s1->str, ==, "hallo"); + g_assert_cmpint (s1->len, ==, strlen ("hallo")); + + s2 = nm_ref_string_new ("hallo"); + g_assert (s2 == s1); + nm_ref_string_unref (s2); + + s2 = nm_ref_string_new (NULL); + g_assert (!s2); + nm_ref_string_unref (s2); + +#define STR_WITH_NUL "hallo\0test\0" + s2 = nm_ref_string_new_len (STR_WITH_NUL, NM_STRLEN (STR_WITH_NUL)); + g_assert (s2); + g_assert_cmpstr (s2->str, ==, "hallo"); + g_assert_cmpint (s2->len, ==, NM_STRLEN (STR_WITH_NUL)); + g_assert_cmpint (s2->len, >, strlen (s2->str)); + g_assert_cmpmem (s2->str, s2->len, STR_WITH_NUL, NM_STRLEN (STR_WITH_NUL)); + g_assert (s2->str[s2->len] == '\0'); + nm_ref_string_unref (s2); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) { nmtst_init (&argc, &argv, TRUE); + g_test_add_func ("/general/test_gpid", test_gpid); g_test_add_func ("/general/test_monotonic_timestamp", test_monotonic_timestamp); g_test_add_func ("/general/test_nmhash", test_nmhash); g_test_add_func ("/general/test_nm_make_strv", test_make_strv); @@ -526,6 +571,7 @@ int main (int argc, char **argv) g_test_add_func ("/general/test_strv_cmp", test_strv_cmp); g_test_add_func ("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy); g_test_add_func ("/general/test_nm_utils_bin2hexstr", test_nm_utils_bin2hexstr); + g_test_add_func ("/general/test_nm_ref_string", test_nm_ref_string); return g_test_run (); } diff --git a/shared/nm-version-macros.h b/shared/nm-version-macros.h index f1f44713..a5c79c1e 100644 --- a/shared/nm-version-macros.h +++ b/shared/nm-version-macros.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2011, 2015 Red Hat, Inc. + * Copyright (C) 2011, 2015 Red Hat, Inc. */ #ifndef __NM_VERSION_MACROS_H__ @@ -36,7 +22,7 @@ * Evaluates to the minor version number of NetworkManager which this source * is compiled against. */ -#define NM_MINOR_VERSION (20) +#define NM_MINOR_VERSION (22) /** * NM_MICRO_VERSION: @@ -44,7 +30,7 @@ * Evaluates to the micro version number of NetworkManager which this source * compiled against. */ -#define NM_MICRO_VERSION (8) +#define NM_MICRO_VERSION (0) /** * NM_CHECK_VERSION: @@ -76,8 +62,7 @@ #define NM_VERSION_1_16 (NM_ENCODE_VERSION (1, 16, 0)) #define NM_VERSION_1_18 (NM_ENCODE_VERSION (1, 18, 0)) #define NM_VERSION_1_20 (NM_ENCODE_VERSION (1, 20, 0)) -#define NM_VERSION_1_20_2 (NM_ENCODE_VERSION (1, 20, 2)) -#define NM_VERSION_1_20_6 (NM_ENCODE_VERSION (1, 20, 6)) +#define NM_VERSION_1_22 (NM_ENCODE_VERSION (1, 22, 0)) /* For releases, NM_API_VERSION is equal to NM_VERSION. * diff --git a/shared/nm-version-macros.h.in b/shared/nm-version-macros.h.in index c65a1f88..961febb0 100644 --- a/shared/nm-version-macros.h.in +++ b/shared/nm-version-macros.h.in @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2011, 2015 Red Hat, Inc. + * Copyright (C) 2011, 2015 Red Hat, Inc. */ #ifndef __NM_VERSION_MACROS_H__ @@ -76,8 +62,7 @@ #define NM_VERSION_1_16 (NM_ENCODE_VERSION (1, 16, 0)) #define NM_VERSION_1_18 (NM_ENCODE_VERSION (1, 18, 0)) #define NM_VERSION_1_20 (NM_ENCODE_VERSION (1, 20, 0)) -#define NM_VERSION_1_20_2 (NM_ENCODE_VERSION (1, 20, 2)) -#define NM_VERSION_1_20_6 (NM_ENCODE_VERSION (1, 20, 6)) +#define NM_VERSION_1_22 (NM_ENCODE_VERSION (1, 22, 0)) /* For releases, NM_API_VERSION is equal to NM_VERSION. * diff --git a/shared/systemd/nm-logging-stub.c b/shared/systemd/nm-logging-stub.c index 95ff51e5..64a96daa 100644 --- a/shared/systemd/nm-logging-stub.c +++ b/shared/systemd/nm-logging-stub.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/shared/systemd/nm-sd-utils-shared.c b/shared/systemd/nm-sd-utils-shared.c index 7206fa52..85fd6a35 100644 --- a/shared/systemd/nm-sd-utils-shared.c +++ b/shared/systemd/nm-sd-utils-shared.c @@ -1,18 +1,5 @@ -/* 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ @@ -22,9 +9,10 @@ #include "nm-sd-adapt-shared.h" -#include "path-util.h" -#include "hexdecoct.h" #include "dns-domain.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "path-util.h" /*****************************************************************************/ @@ -52,7 +40,7 @@ nm_sd_utils_path_startswith (const char *path, const char *prefix) /*****************************************************************************/ -gboolean +int nm_sd_utils_unbase64char (char ch, gboolean accept_padding_equal) { if ( ch == '=' @@ -96,3 +84,13 @@ int nm_sd_dns_name_to_wire_format (const char *domain, { return dns_name_to_wire_format (domain, buffer, len, canonical); } + +int nm_sd_dns_name_is_valid (const char *s) +{ + return dns_name_is_valid (s); +} + +gboolean nm_sd_hostname_is_valid (const char *s, bool allow_trailing_dot) +{ + return hostname_is_valid (s, allow_trailing_dot); +} diff --git a/shared/systemd/nm-sd-utils-shared.h b/shared/systemd/nm-sd-utils-shared.h index 48a8cf37..3495a31d 100644 --- a/shared/systemd/nm-sd-utils-shared.h +++ b/shared/systemd/nm-sd-utils-shared.h @@ -1,18 +1,5 @@ -/* 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; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ @@ -44,4 +31,7 @@ int nm_sd_dns_name_to_wire_format (const char *domain, size_t len, gboolean canonical); +int nm_sd_dns_name_is_valid (const char *s); +gboolean nm_sd_hostname_is_valid(const char *s, bool allow_trailing_dot); + #endif /* __NM_SD_UTILS_SHARED_H__ */ diff --git a/shared/systemd/sd-adapt-shared/btrfs-util.h b/shared/systemd/sd-adapt-shared/dhcp-server-internal.h index 637892c2..637892c2 100644 --- a/shared/systemd/sd-adapt-shared/btrfs-util.h +++ b/shared/systemd/sd-adapt-shared/dhcp-server-internal.h diff --git a/shared/systemd/sd-adapt-shared/missing.h b/shared/systemd/sd-adapt-shared/missing.h deleted file mode 100644 index d0b460a7..00000000 --- a/shared/systemd/sd-adapt-shared/missing.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -/* dummy header */ - -#include "missing_fcntl.h" -#include "missing_socket.h" -#include "missing_stat.h" -#include "missing_type.h" diff --git a/shared/systemd/sd-adapt-shared/cgroup-util.h b/shared/systemd/sd-adapt-shared/missing_fs.h index 637892c2..637892c2 100644 --- a/shared/systemd/sd-adapt-shared/cgroup-util.h +++ b/shared/systemd/sd-adapt-shared/missing_fs.h diff --git a/shared/systemd/sd-adapt-shared/device-nodes.h b/shared/systemd/sd-adapt-shared/missing_magic.h index 637892c2..637892c2 100644 --- a/shared/systemd/sd-adapt-shared/device-nodes.h +++ b/shared/systemd/sd-adapt-shared/missing_magic.h diff --git a/shared/systemd/sd-adapt-shared/procfs-util.h b/shared/systemd/sd-adapt-shared/missing_network.h index 637892c2..637892c2 100644 --- a/shared/systemd/sd-adapt-shared/procfs-util.h +++ b/shared/systemd/sd-adapt-shared/missing_network.h diff --git a/shared/systemd/sd-adapt-shared/missing_sched.h b/shared/systemd/sd-adapt-shared/missing_sched.h new file mode 100644 index 00000000..637892c2 --- /dev/null +++ b/shared/systemd/sd-adapt-shared/missing_sched.h @@ -0,0 +1,3 @@ +#pragma once + +/* dummy header */ diff --git a/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h b/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h index 8dd93341..490cae92 100644 --- a/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h +++ b/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h @@ -1,17 +1,5 @@ -/* 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ diff --git a/shared/systemd/src/basic/alloc-util.c b/shared/systemd/src/basic/alloc-util.c index c97d8700..e355b60f 100644 --- a/shared/systemd/src/basic/alloc-util.c +++ b/shared/systemd/src/basic/alloc-util.c @@ -80,7 +80,7 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { * take possession of the extra space. This should be cheap, since libc doesn't have to move * the memory for this. */ - qq = realloc(q, bn * size); + qq = reallocarray(q, bn, size); if (_likely_(qq)) { *p = qq; *allocated = bn; diff --git a/shared/systemd/src/basic/env-file.c b/shared/systemd/src/basic/env-file.c index 5860b050..30ee135a 100644 --- a/shared/systemd/src/basic/env-file.c +++ b/shared/systemd/src/basic/env-file.c @@ -488,6 +488,8 @@ static int merge_env_file_push( free_and_replace(value, expanded_value); + log_debug("%s:%u: setting %s=%s", filename, line, key, value); + return load_env_file_push(filename, line, key, value, env, n_pushed); } diff --git a/shared/systemd/src/basic/env-util.c b/shared/systemd/src/basic/env-util.c index cd9d3176..d16890d9 100644 --- a/shared/systemd/src/basic/env-util.c +++ b/shared/systemd/src/basic/env-util.c @@ -6,7 +6,6 @@ #include <limits.h> #include <stdarg.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> #include "alloc-util.h" diff --git a/shared/systemd/src/basic/errno-util.h b/shared/systemd/src/basic/errno-util.h index 6053cde6..8f1be6c0 100644 --- a/shared/systemd/src/basic/errno-util.h +++ b/shared/systemd/src/basic/errno-util.h @@ -86,3 +86,18 @@ static inline bool ERRNO_IS_RESOURCE(int r) { ENFILE, ENOMEM); } + +/* Three different errors for "operation/system call/ioctl not supported" */ +static inline bool ERRNO_IS_NOT_SUPPORTED(int r) { + return IN_SET(abs(r), + EOPNOTSUPP, + ENOTTY, + ENOSYS); +} + +/* Two different errors for access problems */ +static inline bool ERRNO_IS_PRIVILEGE(int r) { + return IN_SET(abs(r), + EACCES, + EPERM); +} diff --git a/shared/systemd/src/basic/extract-word.c b/shared/systemd/src/basic/extract-word.c index 15cbaafb..2da25b03 100644 --- a/shared/systemd/src/basic/extract-word.c +++ b/shared/systemd/src/basic/extract-word.c @@ -8,7 +8,6 @@ #include <stddef.h> #include <stdint.h> #include <stdlib.h> -#include <string.h> #include <syslog.h> #include "alloc-util.h" @@ -30,8 +29,6 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra assert(p); assert(ret); - /* Those two don't make sense together. */ - assert(!FLAGS_SET(flags, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE)); /* Bail early if called after last value or with no input */ if (!*p) diff --git a/shared/systemd/src/basic/fd-util.c b/shared/systemd/src/basic/fd-util.c index 941053bf..ea2c1612 100644 --- a/shared/systemd/src/basic/fd-util.c +++ b/shared/systemd/src/basic/fd-util.c @@ -5,7 +5,6 @@ #include <errno.h> #include <fcntl.h> #include <sys/resource.h> -#include <sys/socket.h> #include <sys/stat.h> #include <unistd.h> @@ -18,7 +17,8 @@ #include "io-util.h" #include "macro.h" #include "memfd-util.h" -#include "missing.h" +#include "missing_fcntl.h" +#include "missing_syscall.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/shared/systemd/src/basic/fileio.c b/shared/systemd/src/basic/fileio.c index bd2afbbe..3bffa1c5 100644 --- a/shared/systemd/src/basic/fileio.c +++ b/shared/systemd/src/basic/fileio.c @@ -10,7 +10,6 @@ #include <stdint.h> #include <stdio_ext.h> #include <stdlib.h> -#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -22,7 +21,6 @@ #include "hexdecoct.h" #include "log.h" #include "macro.h" -#include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" @@ -314,6 +312,113 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { } #endif /* NM_IGNORED */ +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) { + _cleanup_free_ char *buf = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + size_t n, size; + int n_retries; + char *p; + + assert(ret_contents); + + /* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work + * with two sorts of virtual files. One sort uses "seq_file", and the results of + * the first read are buffered for the second read. The other sort uses "raw" + * reads which always go direct to the device. In the latter case, the content of + * the virtual file must be retrieved with a single read otherwise a second read + * might get the new value instead of finding EOF immediately. That's the reason + * why the usage of fread(3) is prohibited in this case as it always performs a + * second call to read(2) looking for EOF. See issue 13585. */ + + fd = open(filename, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + /* Start size for files in /proc which usually report a file size of 0. */ + size = LINE_MAX / 2; + + /* Limit the number of attempts to read the number of bytes returned by fstat(). */ + n_retries = 3; + + for (;;) { + if (n_retries <= 0) + return -EIO; + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISREG(st.st_mode)) + return -EBADF; + + /* Be prepared for files from /proc which generally report a file size of 0. */ + if (st.st_size > 0) { + size = st.st_size; + n_retries--; + } else + size = size * 2; + + if (size > READ_FULL_BYTES_MAX) + return -E2BIG; + + p = realloc(buf, size + 1); + if (!p) + return -ENOMEM; + buf = TAKE_PTR(p); + + for (;;) { + ssize_t k; + + /* Read one more byte so we can detect whether the content of the + * file has already changed or the guessed size for files from /proc + * wasn't large enough . */ + k = read(fd, buf, size + 1); + if (k >= 0) { + n = k; + break; + } + + if (errno != -EINTR) + return -errno; + } + + /* Consider a short read as EOF */ + if (n <= size) + break; + + /* Hmm... either we read too few bytes from /proc or less likely the content + * of the file might have been changed (and is now bigger) while we were + * processing, let's try again either with a bigger guessed size or the new + * file size. */ + + if (lseek(fd, 0, SEEK_SET) < 0) + return -errno; + } + + if (n < size) { + p = realloc(buf, n + 1); + if (!p) + return -ENOMEM; + buf = TAKE_PTR(p); + } + + if (!ret_size) { + /* Safety check: if the caller doesn't want to know the size of what we + * just read it will rely on the trailing NUL byte. But if there's an + * embedded NUL byte, then we should refuse operation as otherwise + * there'd be ambiguity about what we just read. */ + + if (memchr(buf, 0, n)) + return -EBADMSG; + } else + *ret_size = n; + + buf[n] = 0; + *ret_contents = TAKE_PTR(buf); + + return 0; +} + int read_full_stream_full( FILE *f, const char *filename, @@ -346,9 +451,9 @@ int read_full_stream_full( if (st.st_size > READ_FULL_BYTES_MAX) return -E2BIG; - /* Start with the right file size, but be prepared for files from /proc which generally report a file - * size of 0. Note that we increase the size to read here by one, so that the first read attempt - * already makes us notice the EOF. */ + /* Start with the right file size. Note that we increase the size + * to read here by one, so that the first read attempt already + * makes us notice the EOF. */ if (st.st_size > 0) n_next = st.st_size + 1; @@ -508,7 +613,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin assert(pattern); assert(field); - r = read_full_file(filename, &status, NULL); + r = read_full_virtual_file(filename, &status, NULL); if (r < 0) return r; @@ -942,10 +1047,10 @@ int warn_file_is_world_accessible(const char *filename, struct stat *st, const c if (unit) log_syntax(unit, LOG_WARNING, filename, line, 0, - "%s has %04o mode that is too permissive, please adjust the access mode.", + "%s has %04o mode that is too permissive, please adjust the ownership and access mode.", filename, st->st_mode & 07777); else - log_warning("%s has %04o mode that is too permissive, please adjust the access mode.", + log_warning("%s has %04o mode that is too permissive, please adjust the ownership and access mode.", filename, st->st_mode & 07777); return 0; } diff --git a/shared/systemd/src/basic/fileio.h b/shared/systemd/src/basic/fileio.h index 05f6c89d..31bfef33 100644 --- a/shared/systemd/src/basic/fileio.h +++ b/shared/systemd/src/basic/fileio.h @@ -56,6 +56,7 @@ int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **co static inline int read_full_file(const char *filename, char **contents, size_t *size) { return read_full_file_full(filename, 0, contents, size); } +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size); int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size); static inline int read_full_stream(FILE *f, char **contents, size_t *size) { return read_full_stream_full(f, NULL, 0, contents, size); diff --git a/shared/systemd/src/basic/format-util.c b/shared/systemd/src/basic/format-util.c index 7a3e735b..62477f53 100644 --- a/shared/systemd/src/basic/format-util.c +++ b/shared/systemd/src/basic/format-util.c @@ -2,15 +2,26 @@ #include "nm-sd-adapt-shared.h" -#include <stdio.h> - #include "format-util.h" #include "memory-util.h" +#include "stdio-util.h" -char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) { +assert_cc(DECIMAL_STR_MAX(int) + 1 <= IF_NAMESIZE + 1); +char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag) { /* Buffer is always cleared */ memzero(buf, IF_NAMESIZE + 1); - return if_indextoname(ifindex, buf); + if (if_indextoname(ifindex, buf)) + return buf; + + if (!FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX)) + return NULL; + + if (FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX_WITH_PERCENT)) + snprintf(buf, IF_NAMESIZE + 1, "%%%d", ifindex); + else + snprintf(buf, IF_NAMESIZE + 1, "%d", ifindex); + + return buf; } char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) { diff --git a/shared/systemd/src/basic/format-util.h b/shared/systemd/src/basic/format-util.h index e0d184a5..59622508 100644 --- a/shared/systemd/src/basic/format-util.h +++ b/shared/systemd/src/basic/format-util.h @@ -68,7 +68,15 @@ # error Unknown ino_t size #endif -char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]); +typedef enum { + FORMAT_IFNAME_IFINDEX = 1 << 0, + FORMAT_IFNAME_IFINDEX_WITH_PERCENT = (1 << 1) | FORMAT_IFNAME_IFINDEX, +} FormatIfnameFlag; + +char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag); +static inline char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) { + return format_ifname_full(ifindex, buf, 0); +} typedef enum { FORMAT_BYTES_USE_IEC = 1 << 0, diff --git a/shared/systemd/src/basic/fs-util.c b/shared/systemd/src/basic/fs-util.c index 56385fa2..e30f40fb 100644 --- a/shared/systemd/src/basic/fs-util.c +++ b/shared/systemd/src/basic/fs-util.c @@ -4,13 +4,9 @@ #include <errno.h> #include <stddef.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <sys/stat.h> #include <linux/falloc.h> #include <linux/magic.h> -#include <time.h> #include <unistd.h> #include "alloc-util.h" @@ -20,7 +16,9 @@ #include "locale-util.h" #include "log.h" #include "macro.h" -#include "missing.h" +#include "missing_fcntl.h" +#include "missing_fs.h" +#include "missing_syscall.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" @@ -669,6 +667,18 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) { } #if 0 /* NM_IGNORED */ +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { + + if (inotify_add_watch(fd, pathname, mask) < 0) { + if (errno == ENOSPC) + return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname); + + return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname); + } + + return 0; +} + static bool unsafe_transition(const struct stat *a, const struct stat *b) { /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files @@ -707,7 +717,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { n1, path); } -int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) { +int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; _cleanup_close_ int fd = -1; unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */ @@ -719,10 +729,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, assert(path); /* Either the file may be missing, or we return an fd to the final object, but both make no sense */ - if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN)) + if ((flags & CHASE_NONEXISTENT) && ret_fd) return -EINVAL; - if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN)) + if ((flags & CHASE_STEP) && ret_fd) return -EINVAL; if (isempty(path)) @@ -741,24 +751,24 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races - * at a minimum. + * to a minimum. * * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this * function what to do when encountering a symlink with an absolute path as directory: prefix it by the * specified path. * - * There are three ways to invoke this function: + * There are five ways to invoke this function: * - * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned - * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set 0 is returned if the file - * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set >= 0 is returned if the destination was - * found, -ENOENT if it doesn't. + * 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is + * returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 + * is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is + * returned if the destination was found, -ENOENT if it wasn't. * - * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file + * 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file * descriptor is returned as return value. This is useful to open files relative to some root * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using - * fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with + * fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with * CHASE_NONEXISTENT. * * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first @@ -769,26 +779,26 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * * 4. With CHASE_SAFE: in this case the path must not contain unsafe transitions, i.e. transitions from * unprivileged to privileged files or directories. In such cases the return value is -ENOLINK. If - * CHASE_WARN is also set a warning describing the unsafe transition is emitted. + * CHASE_WARN is also set, a warning describing the unsafe transition is emitted. * - * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, the path normalization is - * aborted and -EREMOTE is returned. If CHASE_WARN is also set a warning showing the path of the mount point - * is emitted. - * - * */ + * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization + * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of + * the mount point is emitted. + */ /* A root directory of "/" or "" is identical to none */ if (empty_or_root(original_root)) original_root = NULL; - if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) { - /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set + if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) { + /* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root set * and doesn't care about any of the other special features we provide either. */ r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); if (r < 0) return -errno; - return r; + *ret_fd = r; + return 0; } if (original_root) { @@ -797,7 +807,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return r; if (flags & CHASE_PREFIX_ROOT) { - /* We don't support relative paths in combination with a root directory */ if (!path_is_absolute(path)) return -EINVAL; @@ -942,7 +951,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { char *joined; - _cleanup_free_ char *destination = NULL; /* This is a symlink, in this case read the destination. But let's make sure we don't follow @@ -1028,15 +1036,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - if (ret) - *ret = TAKE_PTR(done); + if (ret_path) + *ret_path = TAKE_PTR(done); - if (flags & CHASE_OPEN) { - /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by - * opening /proc/self/fd/xyz. */ + if (ret_fd) { + /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a + * proper fd by opening /proc/self/fd/xyz. */ assert(fd >= 0); - return TAKE_FD(fd); + *ret_fd = TAKE_FD(fd); } if (flags & CHASE_STEP) @@ -1045,14 +1053,14 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return exists; chased_one: - if (ret) { + if (ret_path) { char *c; c = strjoin(strempty(done), todo); if (!c) return -ENOMEM; - *ret = c; + *ret_path = c; } return 0; @@ -1081,9 +1089,10 @@ int chase_symlinks_and_open( return r; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); r = fd_reopen(path_fd, open_flags); if (r < 0) @@ -1106,6 +1115,7 @@ int chase_symlinks_and_opendir( _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; DIR *d; + int r; if (!ret_dir) return -EINVAL; @@ -1122,9 +1132,10 @@ int chase_symlinks_and_opendir( return 0; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); d = opendir(procfs_path); @@ -1143,10 +1154,12 @@ int chase_symlinks_and_stat( const char *root, unsigned chase_flags, char **ret_path, - struct stat *ret_stat) { + struct stat *ret_stat, + int *ret_fd) { _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; + int r; assert(path); assert(ret_stat); @@ -1162,18 +1175,18 @@ int chase_symlinks_and_stat( return 1; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); if (fstat(path_fd, ret_stat) < 0) return -errno; if (ret_path) *ret_path = TAKE_PTR(p); - - if (chase_flags & CHASE_OPEN) - return TAKE_FD(path_fd); + if (ret_fd) + *ret_fd = TAKE_FD(path_fd); return 1; } @@ -1307,6 +1320,17 @@ int fsync_directory_of_file(int fd) { return 0; } +int fsync_full(int fd) { + int r, q; + + /* Sync both the file and the directory */ + + r = fsync(fd) < 0 ? -errno : 0; + q = fsync_directory_of_file(fd); + + return r < 0 ? r : q; +} + int fsync_path_at(int at_fd, const char *path) { _cleanup_close_ int opened_fd = -1; int fd; diff --git a/shared/systemd/src/basic/fs-util.h b/shared/systemd/src/basic/fs-util.h index c5527cc4..78d68be9 100644 --- a/shared/systemd/src/basic/fs-util.h +++ b/shared/systemd/src/basic/fs-util.h @@ -72,27 +72,28 @@ union inotify_event_buffer { }; int inotify_add_watch_fd(int fd, int what, uint32_t mask); +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask); enum { - CHASE_PREFIX_ROOT = 1 << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */ - CHASE_NONEXISTENT = 1 << 1, /* If set, it's OK if the path doesn't actually exist. */ - CHASE_NO_AUTOFS = 1 << 2, /* If set, return -EREMOTE if autofs mount point found */ - CHASE_SAFE = 1 << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */ - CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */ - CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */ - CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */ - CHASE_NOFOLLOW = 1 << 7, /* Only valid with CHASE_OPEN: when the path's right-most component refers to symlink return O_PATH fd of the symlink, rather than following it. */ - CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */ + CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */ + CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */ + CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ + CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */ + CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */ + CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */ + CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's + * right-most component refers to symlink, return O_PATH fd of the symlink. */ + CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */ }; /* How many iterations to execute before returning -ELOOP */ #define CHASE_SYMLINKS_MAX 32 -int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret); +int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd); int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); -int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat); +int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); /* Useful for usage with _cleanup_(), removes a directory and frees the pointer */ static inline void rmdir_and_free(char *p) { @@ -114,6 +115,7 @@ void unlink_tempfilep(char (*p)[]); int unlinkat_deallocate(int fd, const char *name, int flags); int fsync_directory_of_file(int fd); +int fsync_full(int fd); int fsync_path_at(int at_fd, const char *path); int syncfs_path(int atfd, const char *path); diff --git a/shared/systemd/src/basic/hash-funcs.c b/shared/systemd/src/basic/hash-funcs.c index 03695098..1b0d1292 100644 --- a/shared/systemd/src/basic/hash-funcs.c +++ b/shared/systemd/src/basic/hash-funcs.c @@ -55,11 +55,7 @@ void path_hash_func(const char *q, struct siphash *state) { } } -int path_compare_func(const char *a, const char *b) { - return path_compare(a, b); -} - -DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare_func); +DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare); #endif /* NM_IGNORED */ void trivial_hash_func(const void *p, struct siphash *state) { diff --git a/shared/systemd/src/basic/hash-funcs.h b/shared/systemd/src/basic/hash-funcs.h index 0d2d4283..7bb5d1cd 100644 --- a/shared/systemd/src/basic/hash-funcs.h +++ b/shared/systemd/src/basic/hash-funcs.h @@ -79,7 +79,6 @@ extern const struct hash_ops string_hash_ops; extern const struct hash_ops string_hash_ops_free_free; void path_hash_func(const char *p, struct siphash *state); -int path_compare_func(const char *a, const char *b) _pure_; extern const struct hash_ops path_hash_ops; /* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings diff --git a/shared/systemd/src/basic/hashmap.c b/shared/systemd/src/basic/hashmap.c index b1ae08cd..1aa00947 100644 --- a/shared/systemd/src/basic/hashmap.c +++ b/shared/systemd/src/basic/hashmap.c @@ -5,7 +5,6 @@ #include <errno.h> #include <stdint.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "fileio.h" @@ -13,7 +12,7 @@ #include "macro.h" #include "memory-util.h" #include "mempool.h" -#include "missing.h" +#include "missing_syscall.h" #include "process-util.h" #include "random-util.h" #include "set.h" diff --git a/shared/systemd/src/basic/hostname-util.c b/shared/systemd/src/basic/hostname-util.c index 60a94b96..00a92cb7 100644 --- a/shared/systemd/src/basic/hostname-util.c +++ b/shared/systemd/src/basic/hostname-util.c @@ -5,7 +5,6 @@ #include <errno.h> #include <limits.h> #include <stdio.h> -#include <string.h> #include <sys/utsname.h> #include <unistd.h> diff --git a/shared/systemd/src/basic/io-util.c b/shared/systemd/src/basic/io-util.c index 9669c463..4f57f044 100644 --- a/shared/systemd/src/basic/io-util.c +++ b/shared/systemd/src/basic/io-util.c @@ -6,7 +6,6 @@ #include <limits.h> #include <poll.h> #include <stdio.h> -#include <time.h> #include <unistd.h> #include "io-util.h" diff --git a/shared/systemd/src/basic/macro.h b/shared/systemd/src/basic/macro.h index 43c51326..fc733366 100644 --- a/shared/systemd/src/basic/macro.h +++ b/shared/systemd/src/basic/macro.h @@ -316,17 +316,18 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { extern void __coverity_panic__(void); -static inline int __coverity_check__(int condition) { +static inline void __coverity_check__(int condition) { + if (!condition) + __coverity_panic__(); +} + +static inline int __coverity_check_and_return__(int condition) { return condition; } -#define assert_message_se(expr, message) \ - do { \ - if (__coverity_check__(!(expr))) \ - __coverity_panic__(); \ - } while (false) +#define assert_message_se(expr, message) __coverity_check__(!!(expr)) -#define assert_log(expr, message) __coverity_check__(!!(expr)) +#define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) #else /* ! __COVERITY__ */ diff --git a/shared/systemd/src/basic/memory-util.h b/shared/systemd/src/basic/memory-util.h index 9cb8ac3c..46a6907a 100644 --- a/shared/systemd/src/basic/memory-util.h +++ b/shared/systemd/src/basic/memory-util.h @@ -11,6 +11,7 @@ size_t page_size(void) _pure_; #define PAGE_ALIGN(l) ALIGN_TO((l), page_size()) +#define PAGE_ALIGN_DOWN(l) (l & ~(page_size() - 1)) /* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */ static inline void memcpy_safe(void *dst, const void *src, size_t n) { diff --git a/shared/systemd/src/basic/missing_random.h b/shared/systemd/src/basic/missing_random.h new file mode 100644 index 00000000..2e76031b --- /dev/null +++ b/shared/systemd/src/basic/missing_random.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if USE_SYS_RANDOM_H +# include <sys/random.h> +#else +# include <linux/random.h> +#endif + +#ifndef GRND_NONBLOCK +#define GRND_NONBLOCK 0x0001 +#endif + +#ifndef GRND_RANDOM +#define GRND_RANDOM 0x0002 +#endif diff --git a/shared/systemd/src/basic/parse-util.c b/shared/systemd/src/basic/parse-util.c index 76ef6e09..96cc43a2 100644 --- a/shared/systemd/src/basic/parse-util.c +++ b/shared/systemd/src/basic/parse-util.c @@ -5,11 +5,9 @@ #include <errno.h> #include <inttypes.h> #include <linux/oom.h> -#include <locale.h> #include <net/if.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/socket.h> #include "alloc-util.h" @@ -17,7 +15,7 @@ #include "extract-word.h" #include "locale-util.h" #include "macro.h" -#include "missing.h" +#include "missing_network.h" #include "parse-util.h" #include "process-util.h" #include "stat-util.h" diff --git a/shared/systemd/src/basic/path-util.c b/shared/systemd/src/basic/path-util.c index e39656bc..5bcc35e5 100644 --- a/shared/systemd/src/basic/path-util.c +++ b/shared/systemd/src/basic/path-util.c @@ -6,8 +6,6 @@ #include <limits.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <sys/stat.h> #include <unistd.h> /* When we include libgen.h because we need dirname() we immediately @@ -22,7 +20,6 @@ #include "glob-util.h" #include "log.h" #include "macro.h" -#include "missing.h" #include "nulstr-util.h" #include "parse-util.h" #include "path-util.h" @@ -276,7 +273,7 @@ char **path_strv_resolve(char **l, const char *root) { } else t = *s; - r = chase_symlinks(t, root, 0, &u); + r = chase_symlinks(t, root, 0, &u, NULL); if (r == -ENOENT) { if (root) { u = TAKE_PTR(orig); @@ -658,7 +655,9 @@ int find_binary(const char *name, char **ret) { return 0; } - last_error = -errno; + /* PATH entries which we don't have access to are ignored, as per tradition. */ + if (errno != EACCES) + last_error = -errno; } return last_error; diff --git a/shared/systemd/src/basic/path-util.h b/shared/systemd/src/basic/path-util.h index cd6216bb..88aef2f3 100644 --- a/shared/systemd/src/basic/path-util.h +++ b/shared/systemd/src/basic/path-util.h @@ -40,6 +40,10 @@ #endif #endif /* NM_IGNORED */ +#ifndef DEFAULT_USER_PATH +# define DEFAULT_USER_PATH DEFAULT_PATH +#endif + bool is_path(const char *p) _pure_; int path_split_and_make_absolute(const char *p, char ***ret); bool path_is_absolute(const char *p) _pure_; diff --git a/shared/systemd/src/basic/process-util.c b/shared/systemd/src/basic/process-util.c index 317815fe..14561670 100644 --- a/shared/systemd/src/basic/process-util.c +++ b/shared/systemd/src/basic/process-util.c @@ -6,11 +6,9 @@ #include <errno.h> #include <limits.h> #include <linux/oom.h> -#include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/mman.h> #include <sys/mount.h> #include <sys/personality.h> @@ -27,8 +25,8 @@ #include "alloc-util.h" #include "architecture.h" -#include "escape.h" #include "env-util.h" +#include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -37,8 +35,10 @@ #include "log.h" #include "macro.h" #include "memory-util.h" -#include "missing.h" +#include "missing_sched.h" +#include "missing_syscall.h" #include "namespace-util.h" +#include "path-util.h" #include "process-util.h" #include "raw-clone.h" #include "rlimit-util.h" @@ -58,13 +58,17 @@ #define COMM_MAX_LEN 128 static int get_process_state(pid_t pid) { + _cleanup_free_ char *line = NULL; const char *p; char state; int r; - _cleanup_free_ char *line = NULL; assert(pid >= 0); + /* Shortcut: if we are enquired about our own state, we are obviously running */ + if (pid == 0 || pid == getpid_cached()) + return (unsigned char) 'R'; + p = procfs_file_alloca(pid, "stat"); r = read_one_line_file(p, &line); @@ -87,24 +91,35 @@ static int get_process_state(pid_t pid) { int get_process_comm(pid_t pid, char **ret) { _cleanup_free_ char *escaped = NULL, *comm = NULL; - const char *p; int r; assert(ret); assert(pid >= 0); + if (pid == 0 || pid == getpid_cached()) { + comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */ + if (!comm) + return -ENOMEM; + + if (prctl(PR_GET_NAME, comm) < 0) + return -errno; + } else { + const char *p; + + p = procfs_file_alloca(pid, "comm"); + + /* Note that process names of kernel threads can be much longer than TASK_COMM_LEN */ + r = read_one_line_file(p, &comm); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + } + escaped = new(char, COMM_MAX_LEN); if (!escaped) return -ENOMEM; - p = procfs_file_alloca(pid, "comm"); - - r = read_one_line_file(p, &comm); - if (r == -ENOENT) - return -ESRCH; - if (r < 0) - return r; - /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */ cellescape(escaped, COMM_MAX_LEN, comm); @@ -507,6 +522,9 @@ int get_process_cwd(pid_t pid, char **cwd) { assert(pid >= 0); + if (pid == 0 || pid == getpid_cached()) + return safe_getcwd(cwd); + p = procfs_file_alloca(pid, "cwd"); return get_process_link_contents(p, cwd); diff --git a/shared/systemd/src/basic/process-util.h b/shared/systemd/src/basic/process-util.h index 20f663e2..66853c6e 100644 --- a/shared/systemd/src/basic/process-util.h +++ b/shared/systemd/src/basic/process-util.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include <alloca.h> #include <errno.h> #include <sched.h> #include <signal.h> diff --git a/shared/systemd/src/basic/random-util.c b/shared/systemd/src/basic/random-util.c index c70871bf..86917ca3 100644 --- a/shared/systemd/src/basic/random-util.c +++ b/shared/systemd/src/basic/random-util.c @@ -19,16 +19,13 @@ # include <sys/auxv.h> #endif -#if USE_SYS_RANDOM_H -# include <sys/random.h> -#else -# include <linux/random.h> -#endif - #include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "io-util.h" -#include "missing.h" +#include "missing_random.h" +#include "missing_syscall.h" +#include "parse-util.h" #include "random-util.h" #include "siphash24.h" #include "time-util.h" @@ -398,3 +395,28 @@ void random_bytes(void *p, size_t n) { /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */ pseudo_random_bytes(p, n); } + +#if 0 /* NM_IGNORED */ +size_t random_pool_size(void) { + _cleanup_free_ char *s = NULL; + int r; + + /* Read pool size, if possible */ + r = read_one_line_file("/proc/sys/kernel/random/poolsize", &s); + if (r < 0) + log_debug_errno(r, "Failed to read pool size from kernel: %m"); + else { + unsigned sz; + + r = safe_atou(s, &sz); + if (r < 0) + log_debug_errno(r, "Failed to parse pool size: %s", s); + else + /* poolsize is in bits on 2.6, but we want bytes */ + return CLAMP(sz / 8, RANDOM_POOL_SIZE_MIN, RANDOM_POOL_SIZE_MAX); + } + + /* Use the minimum as default, if we can't retrieve the correct value */ + return RANDOM_POOL_SIZE_MIN; +} +#endif /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/random-util.h b/shared/systemd/src/basic/random-util.h index 148b6c78..facc11b9 100644 --- a/shared/systemd/src/basic/random-util.h +++ b/shared/systemd/src/basic/random-util.h @@ -31,3 +31,9 @@ static inline uint32_t random_u32(void) { } int rdrand(unsigned long *ret); + +/* Some limits on the pool sizes when we deal with the kernel random pool */ +#define RANDOM_POOL_SIZE_MIN 512U +#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U) + +size_t random_pool_size(void); diff --git a/shared/systemd/src/basic/set.h b/shared/systemd/src/basic/set.h index 2bb26c68..5f195617 100644 --- a/shared/systemd/src/basic/set.h +++ b/shared/systemd/src/basic/set.h @@ -102,8 +102,8 @@ static inline void *set_steal_first(Set *s) { /* no set_steal_first_key */ /* no set_first_key */ -static inline void *set_first(Set *s) { - return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), false, NULL); +static inline void *set_first(const Set *s) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE((Set *) s), false, NULL); } /* no set_next */ diff --git a/shared/systemd/src/basic/socket-util.c b/shared/systemd/src/basic/socket-util.c index b822ed03..cded4545 100644 --- a/shared/systemd/src/basic/socket-util.c +++ b/shared/systemd/src/basic/socket-util.c @@ -13,7 +13,7 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> +#include <sys/ioctl.h> #include <unistd.h> #include "alloc-util.h" @@ -25,7 +25,7 @@ #include "log.h" #include "macro.h" #include "memory-util.h" -#include "missing.h" +#include "missing_socket.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/shared/systemd/src/basic/stat-util.c b/shared/systemd/src/basic/stat-util.c index c9837fa1..071050f2 100644 --- a/shared/systemd/src/basic/stat-util.c +++ b/shared/systemd/src/basic/stat-util.c @@ -2,12 +2,9 @@ #include "nm-sd-adapt-shared.h" -#include <dirent.h> #include <errno.h> #include <fcntl.h> -#include <linux/magic.h> #include <sched.h> -#include <sys/stat.h> #include <sys/statvfs.h> #include <sys/types.h> #include <unistd.h> @@ -17,7 +14,8 @@ #include "fd-util.h" #include "fs-util.h" #include "macro.h" -#include "missing.h" +#include "missing_fs.h" +#include "missing_magic.h" #include "parse-util.h" #include "stat-util.h" #include "string-util.h" @@ -340,7 +338,7 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) { if (r < 0) return r; - return chase_symlinks(p, NULL, 0, ret); + return chase_symlinks(p, NULL, 0, ret, NULL); } int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) { diff --git a/shared/systemd/src/basic/string-table.h b/shared/systemd/src/basic/string-table.h index 42fe4f43..2d3cf814 100644 --- a/shared/systemd/src/basic/string-table.h +++ b/shared/systemd/src/basic/string-table.h @@ -5,7 +5,6 @@ #include <errno.h> #include <stddef.h> #include <stdio.h> -#include <string.h> #include <sys/types.h> #include "macro.h" diff --git a/shared/systemd/src/basic/string-util.c b/shared/systemd/src/basic/string-util.c index 2d34603e..3d2feb18 100644 --- a/shared/systemd/src/basic/string-util.c +++ b/shared/systemd/src/basic/string-util.c @@ -7,7 +7,6 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "escape.h" @@ -750,7 +749,7 @@ static void advance_offsets( } char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { - const char *i, *begin = NULL; + const char *begin = NULL; enum { STATE_OTHER, STATE_ESCAPE, @@ -758,7 +757,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { STATE_CSO, } state = STATE_OTHER; char *obuf = NULL; - size_t osz = 0, isz, shift[2] = {}; + size_t osz = 0, isz, shift[2] = {}, n_carriage_returns = 0; FILE *f; assert(ibuf); @@ -769,6 +768,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { * 1. Replaces TABs by 8 spaces * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences + * 4. Strip trailing \r characters (since they would "move the cursor", but have no + * other effect). * * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as * are any other special characters. Truncated ANSI sequences are left-as is too. This call is @@ -784,14 +785,24 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { if (!f) return NULL; - for (i = *ibuf; i < *ibuf + isz + 1; i++) { + for (const char *i = *ibuf; i < *ibuf + isz + 1; i++) { switch (state) { case STATE_OTHER: if (i >= *ibuf + isz) /* EOT */ break; - else if (*i == '\x1B') + + if (*i == '\r') { + n_carriage_returns++; + break; + } else if (*i == '\n') + /* Ignore carriage returns before new line */ + n_carriage_returns = 0; + for (; n_carriage_returns > 0; n_carriage_returns--) + fputc('\r', f); + + if (*i == '\x1B') state = STATE_ESCAPE; else if (*i == '\t') { fputs(" ", f); @@ -802,6 +813,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; case STATE_ESCAPE: + assert(n_carriage_returns == 0); + if (i >= *ibuf + isz) { /* EOT */ fputc('\x1B', f); advance_offsets(i - *ibuf, highlight, shift, 1); @@ -822,6 +835,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; case STATE_CSI: + assert(n_carriage_returns == 0); if (i >= *ibuf + isz || /* EOT … */ !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */ @@ -836,6 +850,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { break; case STATE_CSO: + assert(n_carriage_returns == 0); if (i >= *ibuf + isz || /* EOT … */ (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */ @@ -855,7 +870,6 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { fclose(f); return mfree(obuf); } - fclose(f); free_and_replace(*ibuf, obuf); diff --git a/shared/systemd/src/basic/string-util.h b/shared/systemd/src/basic/string-util.h index 76767afc..04cc82b3 100644 --- a/shared/systemd/src/basic/string-util.h +++ b/shared/systemd/src/basic/string-util.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include <alloca.h> #include <stdbool.h> #include <stddef.h> #include <string.h> @@ -45,6 +44,22 @@ static inline const char *strna(const char *s) { return s ?: "n/a"; } +static inline const char* yes_no(bool b) { + return b ? "yes" : "no"; +} + +static inline const char* true_false(bool b) { + return b ? "true" : "false"; +} + +static inline const char* one_zero(bool b) { + return b ? "1" : "0"; +} + +static inline const char* enable_disable(bool b) { + return b ? "enable" : "disable"; +} + static inline bool isempty(const char *p) { return !p || !p[0]; } diff --git a/shared/systemd/src/basic/strv.c b/shared/systemd/src/basic/strv.c index ba23178a..aa467132 100644 --- a/shared/systemd/src/basic/strv.c +++ b/shared/systemd/src/basic/strv.c @@ -7,7 +7,6 @@ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "escape.h" diff --git a/shared/systemd/src/basic/strv.h b/shared/systemd/src/basic/strv.h index e80964ac..fbfa96a5 100644 --- a/shared/systemd/src/basic/strv.h +++ b/shared/systemd/src/basic/strv.h @@ -157,6 +157,18 @@ void strv_print(char **l); _found; \ }) +#define ENDSWITH_SET(p, ...) \ + ({ \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = endswith(_p, *_i); \ + if (_found) \ + break; \ + } \ + _found; \ + }) + #define FOREACH_STRING(x, y, ...) \ for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ x; \ diff --git a/shared/systemd/src/basic/time-util.c b/shared/systemd/src/basic/time-util.c index aa790023..4411127a 100644 --- a/shared/systemd/src/basic/time-util.c +++ b/shared/systemd/src/basic/time-util.c @@ -6,9 +6,7 @@ #include <errno.h> #include <limits.h> #include <stdlib.h> -#include <string.h> #include <sys/mman.h> -#include <sys/stat.h> #include <sys/time.h> #include <sys/timerfd.h> #include <sys/timex.h> @@ -839,8 +837,12 @@ int parse_timestamp(const char *t, usec_t *usec) { } if (r == 0) { bool with_tz = true; + char *colon_tz; - if (setenv("TZ", tz, 1) != 0) { + /* tzset(3) says $TZ should be prefixed with ":" if we reference timezone files */ + colon_tz = strjoina(":", tz); + + if (setenv("TZ", colon_tz, 1) != 0) { shared->return_value = negative_errno(); _exit(EXIT_FAILURE); } @@ -1196,7 +1198,10 @@ bool ntp_synced(void) { if (adjtimex(&txc) < 0) return false; - if (txc.status & STA_UNSYNC) + /* Consider the system clock synchronized if the reported maximum error is smaller than the maximum + * value (16 seconds). Ignore the STA_UNSYNC flag as it may have been set to prevent the kernel from + * touching the RTC. */ + if (txc.maxerror >= 16000000) return false; return true; @@ -1262,6 +1267,7 @@ int get_timezones(char ***ret) { } strv_sort(zones); + strv_uniq(zones); } else if (errno != ENOENT) return -errno; @@ -1282,6 +1288,10 @@ bool timezone_is_valid(const char *name, int log_level) { if (isempty(name)) return false; + /* Always accept "UTC" as valid timezone, since it's the fallback, even if user has no timezones installed. */ + if (streq(name, "UTC")) + return true; + if (name[0] == '/') return false; @@ -1388,13 +1398,22 @@ bool clock_supported(clockid_t clock) { } #if 0 /* NM_IGNORED */ -int get_timezone(char **tz) { +int get_timezone(char **ret) { _cleanup_free_ char *t = NULL; const char *e; char *z; int r; r = readlink_malloc("/etc/localtime", &t); + if (r == -ENOENT) { + /* If the symlink does not exist, assume "UTC", like glibc does*/ + z = strdup("UTC"); + if (!z) + return -ENOMEM; + + *ret = z; + return 0; + } if (r < 0) return r; /* returns EINVAL if not a symlink */ @@ -1409,7 +1428,7 @@ int get_timezone(char **tz) { if (!z) return -ENOMEM; - *tz = z; + *ret = z; return 0; } @@ -1421,8 +1440,8 @@ struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) { return utc ? gmtime_r(t, tm) : localtime_r(t, tm); } -unsigned long usec_to_jiffies(usec_t u) { - static thread_local unsigned long hz = 0; +static uint32_t sysconf_clock_ticks_cached(void) { + static thread_local uint32_t hz = 0; long r; if (hz == 0) { @@ -1432,7 +1451,17 @@ unsigned long usec_to_jiffies(usec_t u) { hz = r; } - return DIV_ROUND_UP(u , USEC_PER_SEC / hz); + return hz; +} + +uint32_t usec_to_jiffies(usec_t u) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(u, USEC_PER_SEC / hz); +} + +usec_t jiffies_to_usec(uint32_t j) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(j * USEC_PER_SEC, hz); } usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) { diff --git a/shared/systemd/src/basic/time-util.h b/shared/systemd/src/basic/time-util.h index e3a529d9..4c371257 100644 --- a/shared/systemd/src/basic/time-util.h +++ b/shared/systemd/src/basic/time-util.h @@ -136,7 +136,8 @@ int get_timezone(char **timezone); time_t mktime_or_timegm(struct tm *tm, bool utc); struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); -unsigned long usec_to_jiffies(usec_t usec); +uint32_t usec_to_jiffies(usec_t usec); +usec_t jiffies_to_usec(uint32_t jiffies); bool in_utc_timezone(void); diff --git a/shared/systemd/src/basic/tmpfile-util.c b/shared/systemd/src/basic/tmpfile-util.c index c02ce3df..d8a689e0 100644 --- a/shared/systemd/src/basic/tmpfile-util.c +++ b/shared/systemd/src/basic/tmpfile-util.c @@ -2,7 +2,6 @@ #include "nm-sd-adapt-shared.h" -#include <stdio.h> #include <sys/mman.h> #include "alloc-util.h" diff --git a/shared/systemd/src/basic/utf8.c b/shared/systemd/src/basic/utf8.c index 3c51fa1f..ba28e129 100644 --- a/shared/systemd/src/basic/utf8.c +++ b/shared/systemd/src/basic/utf8.c @@ -28,7 +28,6 @@ #include <errno.h> #include <stdbool.h> #include <stdlib.h> -#include <string.h> #include "alloc-util.h" #include "gunicode.h" diff --git a/shared/systemd/src/basic/util.c b/shared/systemd/src/basic/util.c index 23aa6b26..8a3f95dc 100644 --- a/shared/systemd/src/basic/util.c +++ b/shared/systemd/src/basic/util.c @@ -2,50 +2,23 @@ #include "nm-sd-adapt-shared.h" -#include <alloca.h> #include <errno.h> #include <fcntl.h> -#include <sched.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include <sys/mman.h> -#include <sys/prctl.h> -#include <sys/statfs.h> -#include <sys/sysmacros.h> -#include <sys/types.h> -#include <unistd.h> #include "alloc-util.h" -#include "btrfs-util.h" #include "build.h" -#include "def.h" -#include "device-nodes.h" #include "dirent-util.h" #include "env-file.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" -#include "format-util.h" -#include "hashmap.h" #include "hostname-util.h" #include "log.h" #include "macro.h" -#include "missing.h" #include "parse-util.h" -#include "path-util.h" -#include "process-util.h" -#include "procfs-util.h" -#include "set.h" -#include "signal-util.h" #include "stat-util.h" #include "string-util.h" -#include "strv.h" -#include "time-util.h" -#include "umask-util.h" -#include "user-util.h" #include "util.h" #include "virt.h" diff --git a/shared/systemd/src/basic/util.h b/shared/systemd/src/basic/util.h index 25e6ab81..6fc7480f 100644 --- a/shared/systemd/src/basic/util.h +++ b/shared/systemd/src/basic/util.h @@ -5,22 +5,6 @@ #include "macro.h" -static inline const char* yes_no(bool b) { - return b ? "yes" : "no"; -} - -static inline const char* true_false(bool b) { - return b ? "true" : "false"; -} - -static inline const char* one_zero(bool b) { - return b ? "1" : "0"; -} - -static inline const char* enable_disable(bool b) { - return b ? "enable" : "disable"; -} - extern int saved_argc; extern char **saved_argv; diff --git a/shared/systemd/src/shared/dns-domain.c b/shared/systemd/src/shared/dns-domain.c index 92543ebe..9bba7359 100644 --- a/shared/systemd/src/shared/dns-domain.c +++ b/shared/systemd/src/shared/dns-domain.c @@ -14,7 +14,6 @@ #include <endian.h> #include <netinet/in.h> #include <stdio.h> -#include <string.h> #include <sys/socket.h> #include "alloc-util.h" |