diff options
| author | Michael Biebl <biebl@debian.org> | 2018-09-08 17:44:06 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-09-08 17:44:06 +0200 |
| commit | 8f7a3cbbdd0c0a48277c341dd3a8ec8743ae9735 (patch) | |
| tree | 4353551fcb59cc822c3cadf2f4888f70601e8fbf /libnm-core | |
| parent | caf1db9d6fbc056cc6c76a24574890f6c7895f3d (diff) | |
New upstream version 1.13.90 upstream/1.13.90
Diffstat (limited to 'libnm-core')
90 files changed, 9836 insertions, 4956 deletions
diff --git a/libnm-core/crypto.c b/libnm-core/crypto.c deleted file mode 100644 index c4e48475..00000000 --- a/libnm-core/crypto.c +++ /dev/null @@ -1,816 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ - -/* - * Dan Williams <dcbw@redhat.com> - * - * 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 2007 - 2011 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include <string.h> -#include <strings.h> -#include <unistd.h> -#include <stdlib.h> - -#include "crypto.h" -#include "nm-errors.h" - -#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----" -#define PEM_RSA_KEY_END "-----END RSA PRIVATE KEY-----" - -#define PEM_DSA_KEY_BEGIN "-----BEGIN DSA PRIVATE KEY-----" -#define PEM_DSA_KEY_END "-----END DSA PRIVATE KEY-----" - -#define PEM_CERT_BEGIN "-----BEGIN CERTIFICATE-----" -#define PEM_CERT_END "-----END CERTIFICATE-----" - -#define PEM_PKCS8_ENC_KEY_BEGIN "-----BEGIN ENCRYPTED PRIVATE KEY-----" -#define PEM_PKCS8_ENC_KEY_END "-----END ENCRYPTED PRIVATE KEY-----" - -#define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----" -#define PEM_PKCS8_DEC_KEY_END "-----END PRIVATE KEY-----" - -static gboolean -find_tag (const char *tag, - const guint8 *data, - gsize data_len, - gsize start_at, - gsize *out_pos) -{ - gsize i, taglen; - gsize len = data_len - start_at; - - g_return_val_if_fail (out_pos != NULL, FALSE); - - taglen = strlen (tag); - if (len >= taglen) { - for (i = 0; i < len - taglen + 1; i++) { - if (memcmp (data + start_at + i, tag, taglen) == 0) { - *out_pos = start_at + i; - return TRUE; - } - } - } - return FALSE; -} - -#define DEK_INFO_TAG "DEK-Info: " -#define PROC_TYPE_TAG "Proc-Type: " - -static GByteArray * -parse_old_openssl_key_file (const guint8 *data, - gsize data_len, - NMCryptoKeyType *out_key_type, - char **out_cipher, - char **out_iv, - GError **error) -{ - GByteArray *bindata = NULL; - char **lines = NULL; - char **ln = NULL; - gsize start = 0, end = 0; - GString *str = NULL; - int enc_tags = 0; - NMCryptoKeyType key_type; - char *iv = NULL; - char *cipher = NULL; - unsigned char *tmp = NULL; - gsize tmp_len = 0; - const char *start_tag; - const char *end_tag; - guint8 save_end = 0; - - *out_key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - *out_iv = NULL; - *out_cipher = NULL; - - if (find_tag (PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) { - key_type = NM_CRYPTO_KEY_TYPE_RSA; - start_tag = PEM_RSA_KEY_BEGIN; - end_tag = PEM_RSA_KEY_END; - } else if (find_tag (PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) { - key_type = NM_CRYPTO_KEY_TYPE_DSA; - start_tag = PEM_DSA_KEY_BEGIN; - end_tag = PEM_DSA_KEY_END; - } else - goto parse_error; - - start += strlen (start_tag); - if (!find_tag (end_tag, data, data_len, start, &end)) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM key file had no end tag '%s'."), - end_tag); - goto parse_error; - } - - save_end = data[end]; - ((guint8 *)data)[end] = '\0'; - lines = g_strsplit ((const char *) (data + start), "\n", 0); - ((guint8 *)data)[end] = save_end; - - if (!lines || g_strv_length (lines) <= 1) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Doesn't look like a PEM private key file.")); - goto parse_error; - } - - str = g_string_new_len (NULL, end - start); - for (ln = lines; *ln; ln++) { - char *p = *ln; - - /* Chug leading spaces */ - p = g_strstrip (p); - if (!*p) - continue; - - if (!strncmp (p, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG))) { - if (enc_tags++ != 0 || str->len != 0) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: Proc-Type was not first tag.")); - goto parse_error; - } - - p += strlen (PROC_TYPE_TAG); - if (strcmp (p, "4,ENCRYPTED")) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: unknown Proc-Type tag '%s'."), - p); - goto parse_error; - } - } else if (!strncmp (p, DEK_INFO_TAG, strlen (DEK_INFO_TAG))) { - char *comma; - - if (enc_tags++ != 1 || str->len != 0) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: DEK-Info was not the second tag.")); - goto parse_error; - } - - p += strlen (DEK_INFO_TAG); - - /* Grab the IV first */ - comma = strchr (p, ','); - if (!comma || (*(comma + 1) == '\0')) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: no IV found in DEK-Info tag.")); - goto parse_error; - } - *comma++ = '\0'; - if (!g_ascii_isxdigit (*comma)) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: invalid format of IV in DEK-Info tag.")); - goto parse_error; - } - iv = g_strdup (comma); - - /* Get the private key cipher */ - if (!strcasecmp (p, "DES-EDE3-CBC")) { - cipher = g_strdup (p); - } else if (!strcasecmp (p, "DES-CBC")) { - cipher = g_strdup (p); - } else if (!strcasecmp (p, "AES-128-CBC")) { - cipher = g_strdup (p); - } else { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Malformed PEM file: unknown private key cipher '%s'."), - p); - goto parse_error; - } - } else { - if (enc_tags == 1) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); - goto parse_error; - } - g_string_append (str, p); - } - } - - tmp = g_base64_decode (str->str, &tmp_len); - if (tmp == NULL || !tmp_len) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Could not decode private key.")); - goto parse_error; - } - g_string_free (str, TRUE); - - if (lines) - g_strfreev (lines); - - bindata = g_byte_array_sized_new (tmp_len); - g_byte_array_append (bindata, tmp, tmp_len); - g_free (tmp); - - *out_key_type = key_type; - *out_iv = iv; - *out_cipher = cipher; - return bindata; - -parse_error: - g_free (tmp); - g_free (cipher); - g_free (iv); - if (str) - g_string_free (str, TRUE); - if (lines) - g_strfreev (lines); - return NULL; -} - -static GByteArray * -parse_pkcs8_key_file (const guint8 *data, - gsize data_len, - gboolean *out_encrypted, - GError **error) -{ - GByteArray *key = NULL; - gsize start = 0, end = 0; - unsigned char *der = NULL; - guint8 save_end; - gsize length = 0; - const char *start_tag = NULL, *end_tag = NULL; - gboolean encrypted = FALSE; - - /* Try encrypted first, decrypted next */ - if (find_tag (PEM_PKCS8_ENC_KEY_BEGIN, data, data_len, 0, &start)) { - start_tag = PEM_PKCS8_ENC_KEY_BEGIN; - end_tag = PEM_PKCS8_ENC_KEY_END; - encrypted = TRUE; - } else if (find_tag (PEM_PKCS8_DEC_KEY_BEGIN, data, data_len, 0, &start)) { - start_tag = PEM_PKCS8_DEC_KEY_BEGIN; - end_tag = PEM_PKCS8_DEC_KEY_END; - encrypted = FALSE; - } else { - g_set_error_literal (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to find expected PKCS#8 start tag.")); - return NULL; - } - - start += strlen (start_tag); - if (!find_tag (end_tag, data, data_len, start, &end)) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to find expected PKCS#8 end tag '%s'."), - end_tag); - return NULL; - } - - /* g_base64_decode() wants a NULL-terminated string */ - save_end = data[end]; - ((guint8 *)data)[end] = '\0'; - der = g_base64_decode ((const char *) (data + start), &length); - ((guint8 *)data)[end] = save_end; - - if (der && length) { - key = g_byte_array_sized_new (length); - g_byte_array_append (key, der, length); - g_assert (key->len == length); - *out_encrypted = encrypted; - } else { - g_set_error_literal (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to decode PKCS#8 private key.")); - } - - g_free (der); - return key; -} - -static GByteArray * -file_to_g_byte_array (const char *filename, GError **error) -{ - char *contents; - GByteArray *array = NULL; - gsize length = 0; - - if (g_file_get_contents (filename, &contents, &length, error)) { - array = g_byte_array_sized_new (length); - g_byte_array_append (array, (guint8 *) contents, length); - g_assert (array->len == length); - g_free (contents); - } - return array; -} - -/* - * Convert a hex string into bytes. - */ -static char * -convert_iv (const char *src, - gsize *out_len, - GError **error) -{ - int num; - int i; - char conv[3]; - char *c; - - g_return_val_if_fail (src != NULL, NULL); - - num = strlen (src); - if (num % 2) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("IV must be an even number of bytes in length.")); - return NULL; - } - - num /= 2; - c = g_malloc0 (num + 1); - - conv[2] = '\0'; - for (i = 0; i < num; i++) { - conv[0] = src[(i * 2)]; - conv[1] = src[(i * 2) + 1]; - if (!g_ascii_isxdigit (conv[0]) || !g_ascii_isxdigit (conv[1])) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("IV contains non-hexadecimal digits.")); - goto error; - } - - c[i] = strtol(conv, NULL, 16); - } - *out_len = num; - return c; - -error: - g_free (c); - return NULL; -} - -char * -crypto_make_des_aes_key (const char *cipher, - const char *salt, - const gsize salt_len, - const char *password, - gsize *out_len, - GError **error) -{ - char *key; - guint32 digest_len; - - g_return_val_if_fail (cipher != NULL, NULL); - g_return_val_if_fail (salt != NULL, NULL); - g_return_val_if_fail (salt_len >= 8, NULL); - g_return_val_if_fail (password != NULL, NULL); - g_return_val_if_fail (out_len != NULL, NULL); - - if (!strcmp (cipher, "DES-EDE3-CBC")) - digest_len = 24; - else if (!strcmp (cipher, "DES-CBC")) - digest_len = 8; - else if (!strcmp (cipher, "AES-128-CBC")) - digest_len = 16; - else { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Private key cipher '%s' was unknown."), - cipher); - return NULL; - } - - if (password[0] == '\0') - return NULL; - - key = g_malloc0 (digest_len + 1); - - crypto_md5_hash (salt, - 8, - password, - strlen (password), - key, - digest_len); - - *out_len = digest_len; - return key; -} - -static GByteArray * -decrypt_key (const char *cipher, - int key_type, - const guint8 *data, - gsize data_len, - const char *iv, - const char *password, - GError **error) -{ - char *bin_iv = NULL; - gsize bin_iv_len = 0; - char *key = NULL; - gsize key_len = 0; - char *output = NULL; - gsize decrypted_len = 0; - GByteArray *decrypted = NULL; - - g_return_val_if_fail (password != NULL, NULL); - - bin_iv = convert_iv (iv, &bin_iv_len, error); - if (!bin_iv) - return NULL; - - /* Convert the password and IV into a DES or AES key */ - key = crypto_make_des_aes_key (cipher, bin_iv, bin_iv_len, password, &key_len, error); - if (!key || !key_len) - goto out; - - output = crypto_decrypt (cipher, key_type, - data, data_len, - bin_iv, bin_iv_len, - key, key_len, - &decrypted_len, - error); - if (output && decrypted_len) { - decrypted = g_byte_array_sized_new (decrypted_len); - g_byte_array_append (decrypted, (guint8 *) output, decrypted_len); - } - -out: - /* Don't leak stale key material */ - if (key) - memset (key, 0, key_len); - g_free (output); - g_free (key); - g_free (bin_iv); - - return decrypted; -} - -GByteArray * -crypto_decrypt_openssl_private_key_data (const guint8 *data, - gsize data_len, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error) -{ - GByteArray *decrypted = NULL; - NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - GByteArray *parsed; - char *iv = NULL; - char *cipher = NULL; - - g_return_val_if_fail (data != NULL, NULL); - if (out_key_type) - g_return_val_if_fail (*out_key_type == NM_CRYPTO_KEY_TYPE_UNKNOWN, NULL); - - if (!crypto_init (error)) - return NULL; - - parsed = parse_old_openssl_key_file (data, data_len, &key_type, &cipher, &iv, NULL); - /* return the key type even if decryption failed */ - if (out_key_type) - *out_key_type = key_type; - - if (!parsed) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Unable to determine private key type.")); - return NULL; - } - - if (password) { - if (!cipher || !iv) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_PASSWORD, - _("Password provided, but key was not encrypted.")); - } else { - decrypted = decrypt_key (cipher, - key_type, - parsed->data, - parsed->len, - iv, - password, - error); - } - } else if (!cipher && !iv) - decrypted = g_byte_array_ref (parsed); - - g_byte_array_unref (parsed); - g_free (cipher); - g_free (iv); - - return decrypted; -} - -GByteArray * -crypto_decrypt_openssl_private_key (const char *file, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error) -{ - GByteArray *contents; - GByteArray *key = NULL; - - if (!crypto_init (error)) - return NULL; - - contents = file_to_g_byte_array (file, error); - if (contents) { - key = crypto_decrypt_openssl_private_key_data (contents->data, contents->len, - password, out_key_type, error); - g_byte_array_free (contents, TRUE); - } - return key; -} - -static GByteArray * -extract_pem_cert_data (GByteArray *contents, GError **error) -{ - GByteArray *cert = NULL; - gsize start = 0, end = 0; - unsigned char *der = NULL; - guint8 save_end; - gsize length = 0; - - if (!find_tag (PEM_CERT_BEGIN, contents->data, contents->len, 0, &start)) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM certificate had no start tag '%s'."), - PEM_CERT_BEGIN); - goto done; - } - - start += strlen (PEM_CERT_BEGIN); - if (!find_tag (PEM_CERT_END, contents->data, contents->len, start, &end)) { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("PEM certificate had no end tag '%s'."), - PEM_CERT_END); - goto done; - } - - /* g_base64_decode() wants a NULL-terminated string */ - save_end = contents->data[end]; - contents->data[end] = '\0'; - der = g_base64_decode ((const char *) (contents->data + start), &length); - contents->data[end] = save_end; - - if (der && length) { - cert = g_byte_array_sized_new (length); - g_byte_array_append (cert, der, length); - g_assert (cert->len == length); - } else { - g_set_error (error, NM_CRYPTO_ERROR, - NM_CRYPTO_ERROR_INVALID_DATA, - _("Failed to decode certificate.")); - } - -done: - g_free (der); - return cert; -} - -GByteArray * -crypto_load_and_verify_certificate (const char *file, - NMCryptoFileFormat *out_file_format, - GError **error) -{ - GByteArray *array, *contents; - - g_return_val_if_fail (file != NULL, NULL); - g_return_val_if_fail (out_file_format != NULL, NULL); - g_return_val_if_fail (*out_file_format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, NULL); - - if (!crypto_init (error)) - return NULL; - - contents = file_to_g_byte_array (file, error); - if (!contents) - return NULL; - - /* Check for PKCS#12 */ - if (crypto_is_pkcs12_data (contents->data, contents->len, NULL)) { - *out_file_format = NM_CRYPTO_FILE_FORMAT_PKCS12; - return contents; - } - - /* Check for plain DER format */ - if (contents->len > 2 && contents->data[0] == 0x30 && contents->data[1] == 0x82) { - *out_file_format = crypto_verify_cert (contents->data, contents->len, error); - } else { - array = extract_pem_cert_data (contents, error); - if (!array) { - g_byte_array_free (contents, TRUE); - return NULL; - } - - *out_file_format = crypto_verify_cert (array->data, array->len, error); - g_byte_array_free (array, TRUE); - } - - if (*out_file_format != NM_CRYPTO_FILE_FORMAT_X509) { - g_byte_array_free (contents, TRUE); - contents = NULL; - } - - return contents; -} - -gboolean -crypto_is_pkcs12_data (const guint8 *data, - gsize data_len, - GError **error) -{ - GError *local = NULL; - gboolean success; - - if (!data_len) - return FALSE; - - g_return_val_if_fail (data != NULL, FALSE); - - if (!crypto_init (error)) - return FALSE; - - success = crypto_verify_pkcs12 (data, data_len, NULL, &local); - if (success == FALSE) { - /* If the error was just a decryption error, then it's pkcs#12 */ - if (local) { - if (g_error_matches (local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) { - success = TRUE; - g_error_free (local); - } else - g_propagate_error (error, local); - } - } - return success; -} - -gboolean -crypto_is_pkcs12_file (const char *file, GError **error) -{ - GByteArray *contents; - gboolean success = FALSE; - - g_return_val_if_fail (file != NULL, FALSE); - - if (!crypto_init (error)) - return FALSE; - - contents = file_to_g_byte_array (file, error); - if (contents) { - success = crypto_is_pkcs12_data (contents->data, contents->len, error); - g_byte_array_free (contents, TRUE); - } - return success; -} - -/* Verifies that a private key can be read, and if a password is given, that - * the private key can be decrypted with that password. - */ -NMCryptoFileFormat -crypto_verify_private_key_data (const guint8 *data, - gsize data_len, - const char *password, - gboolean *out_is_encrypted, - GError **error) -{ - GByteArray *tmp; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - NMCryptoKeyType ktype = NM_CRYPTO_KEY_TYPE_UNKNOWN; - gboolean is_encrypted = FALSE; - - g_return_val_if_fail (data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - g_return_val_if_fail (out_is_encrypted == NULL || *out_is_encrypted == FALSE, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - - if (!crypto_init (error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - /* Check for PKCS#12 first */ - if (crypto_is_pkcs12_data (data, data_len, NULL)) { - is_encrypted = TRUE; - if (!password || crypto_verify_pkcs12 (data, data_len, password, error)) - format = NM_CRYPTO_FILE_FORMAT_PKCS12; - } else { - /* Maybe it's PKCS#8 */ - tmp = parse_pkcs8_key_file (data, data_len, &is_encrypted, NULL); - if (tmp) { - if (!password || crypto_verify_pkcs8 (tmp->data, tmp->len, is_encrypted, password, error)) - format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; - } else { - char *cipher, *iv; - - /* Or it's old-style OpenSSL */ - tmp = parse_old_openssl_key_file (data, data_len, &ktype, - &cipher, &iv, NULL); - if (tmp) { - format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; - is_encrypted = (cipher && iv); - g_free (cipher); - g_free (iv); - } - } - - if (tmp) { - /* Don't leave key data around */ - memset (tmp->data, 0, tmp->len); - g_byte_array_free (tmp, TRUE); - } - } - - if (out_is_encrypted) - *out_is_encrypted = is_encrypted; - return format; -} - -NMCryptoFileFormat -crypto_verify_private_key (const char *filename, - const char *password, - gboolean *out_is_encrypted, - GError **error) -{ - GByteArray *contents; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - g_return_val_if_fail (filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); - - if (!crypto_init (error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; - - contents = file_to_g_byte_array (filename, error); - if (contents) { - format = crypto_verify_private_key_data (contents->data, contents->len, password, out_is_encrypted, error); - g_byte_array_free (contents, TRUE); - } - return format; -} - -void -crypto_md5_hash (const char *salt, - gssize salt_len, - const char *password, - gssize password_len, - char *buffer, - gsize buflen) -{ - GChecksum *ctx; - gsize digest_len; - char digest[16]; - gsize bufidx = 0; - int i; - - nm_assert (g_checksum_type_get_length (G_CHECKSUM_MD5) == sizeof (digest)); - - g_return_if_fail (password_len == 0 || password); - g_return_if_fail (buffer != NULL); - g_return_if_fail (buflen > 0); - g_return_if_fail (salt_len == 0 || salt); - - ctx = g_checksum_new (G_CHECKSUM_MD5); - - if (salt_len < 0) - salt_len = strlen (salt); - if (password_len < 0) - password_len = strlen (password); - - for (;;) { - if (password_len > 0) - g_checksum_update (ctx, (const guchar *) password, password_len); - if (salt_len > 0) - g_checksum_update (ctx, (const guchar *) salt, salt_len); - - digest_len = sizeof (digest); - g_checksum_get_digest (ctx, (guchar *) digest, &digest_len); - nm_assert (digest_len == sizeof (digest)); - - for (i = 0; i < sizeof (digest); i++) { - if (bufidx >= buflen) - goto done; - buffer[bufidx++] = digest[i]; - } - - g_checksum_reset (ctx); - g_checksum_update (ctx, (const guchar *) digest, sizeof (digest)); - } - -done: - memset (digest, 0, sizeof (digest)); - g_checksum_free (ctx); -} diff --git a/libnm-core/crypto.h b/libnm-core/crypto.h deleted file mode 100644 index e89f0919..00000000 --- a/libnm-core/crypto.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ - -/* - * Dan Williams <dcbw@redhat.com> - * - * 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 2007 - 2014 Red Hat, Inc. - */ - -#ifndef __CRYPTO_H__ -#define __CRYPTO_H__ - -#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) -#error Cannot use this header. -#endif - -#define MD5_HASH_LEN 20 -#define CIPHER_DES_EDE3_CBC "DES-EDE3-CBC" -#define CIPHER_DES_CBC "DES-CBC" -#define CIPHER_AES_CBC "AES-128-CBC" - -typedef enum { - NM_CRYPTO_KEY_TYPE_UNKNOWN = 0, - NM_CRYPTO_KEY_TYPE_RSA, - NM_CRYPTO_KEY_TYPE_DSA -} NMCryptoKeyType; - -typedef enum { - NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0, - NM_CRYPTO_FILE_FORMAT_X509, - NM_CRYPTO_FILE_FORMAT_RAW_KEY, - NM_CRYPTO_FILE_FORMAT_PKCS12 -} NMCryptoFileFormat; - -gboolean crypto_init (GError **error); - -GByteArray *crypto_decrypt_openssl_private_key_data (const guint8 *data, - gsize data_len, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error); - -GByteArray *crypto_decrypt_openssl_private_key (const char *file, - const char *password, - NMCryptoKeyType *out_key_type, - GError **error); - -GByteArray *crypto_load_and_verify_certificate (const char *file, - NMCryptoFileFormat *out_file_format, - GError **error); - -gboolean crypto_is_pkcs12_file (const char *file, GError **error); - -gboolean crypto_is_pkcs12_data (const guint8 *data, gsize len, GError **error); - -NMCryptoFileFormat crypto_verify_private_key_data (const guint8 *data, - gsize data_len, - const char *password, - gboolean *out_is_encrypted, - GError **error); - -NMCryptoFileFormat crypto_verify_private_key (const char *file, - const char *password, - gboolean *out_is_encrypted, - GError **error); - -/* Internal utils API bits for crypto providers */ - -void crypto_md5_hash (const char *salt, - gssize salt_len, - const char *password, - gssize password_len, - char *buffer, - gsize buflen); - -char *crypto_make_des_aes_key (const char *cipher, - const char *salt, - const gsize salt_len, - const char *password, - gsize *out_len, - GError **error); - -char * crypto_decrypt (const char *cipher, - int key_type, - const guint8 *data, - gsize data_len, - const char *iv, - const gsize iv_len, - const char *key, - const gsize key_len, - gsize *out_len, - GError **error); - -char * crypto_encrypt (const char *cipher, - const guint8 *data, - gsize data_len, - const char *iv, - gsize iv_len, - const char *key, - gsize key_len, - gsize *out_len, - GError **error); - -gboolean crypto_randomize (void *buffer, gsize buffer_len, GError **error); - -NMCryptoFileFormat crypto_verify_cert (const guint8 *data, - gsize len, - GError **error); - -gboolean crypto_verify_pkcs12 (const guint8 *data, - gsize data_len, - const char *password, - GError **error); - -gboolean crypto_verify_pkcs8 (const guint8 *data, - gsize data_len, - gboolean is_encrypted, - const char *password, - GError **error); - -#endif /* __CRYPTO_H__ */ diff --git a/libnm-core/meson.build b/libnm-core/meson.build index 7b143706..eb6fcce9 100644 --- a/libnm-core/meson.build +++ b/libnm-core/meson.build @@ -5,6 +5,7 @@ libnm_core_headers = files( 'nm-core-types.h', 'nm-dbus-interface.h', 'nm-errors.h', + 'nm-setting-6lowpan.h', 'nm-setting-8021x.h', 'nm-setting-adsl.h', 'nm-setting-bluetooth.h', @@ -24,6 +25,7 @@ libnm_core_headers = files( 'nm-setting-ip6-config.h', 'nm-setting-macsec.h', 'nm-setting-macvlan.h', + 'nm-setting-match.h', 'nm-setting-olpc-mesh.h', 'nm-setting-ovs-bridge.h', 'nm-setting-ovs-interface.h', @@ -33,6 +35,7 @@ libnm_core_headers = files( 'nm-setting-pppoe.h', 'nm-setting-proxy.h', 'nm-setting-serial.h', + 'nm-setting-sriov.h', 'nm-setting-tc-config.h', 'nm-setting-team-port.h', 'nm-setting-team.h', @@ -45,6 +48,7 @@ libnm_core_headers = files( 'nm-setting-wired.h', 'nm-setting-wireless-security.h', 'nm-setting-wireless.h', + 'nm-setting-wpan.h', 'nm-setting.h', 'nm-simple-connection.h', 'nm-utils.h', @@ -55,6 +59,7 @@ libnm_core_headers = files( ) libnm_core_settings_sources = files( + 'nm-setting-6lowpan.c', 'nm-setting-8021x.c', 'nm-setting-adsl.c', 'nm-setting-bluetooth.c', @@ -65,6 +70,7 @@ libnm_core_settings_sources = files( 'nm-setting-connection.c', 'nm-setting-dcb.c', 'nm-setting-dummy.c', + 'nm-setting-ethtool.c', 'nm-setting-generic.c', 'nm-setting-gsm.c', 'nm-setting-infiniband.c', @@ -74,6 +80,7 @@ libnm_core_settings_sources = files( 'nm-setting-ip6-config.c', 'nm-setting-macsec.c', 'nm-setting-macvlan.c', + 'nm-setting-match.c', 'nm-setting-olpc-mesh.c', 'nm-setting-ovs-bridge.c', 'nm-setting-ovs-interface.c', @@ -83,6 +90,7 @@ libnm_core_settings_sources = files( 'nm-setting-pppoe.c', 'nm-setting-proxy.c', 'nm-setting-serial.c', + 'nm-setting-sriov.c', 'nm-setting-tc-config.c', 'nm-setting-team-port.c', 'nm-setting-team.c', @@ -94,12 +102,12 @@ libnm_core_settings_sources = files( 'nm-setting-wimax.c', 'nm-setting-wired.c', 'nm-setting-wireless-security.c', - 'nm-setting-wireless.c' + 'nm-setting-wireless.c', + 'nm-setting-wpan.c' ) libnm_core_sources = libnm_core_settings_sources + files( - 'crypto.c', - 'crypto_' + crypto + '.c', + 'nm-crypto.c', 'nm-connection.c', 'nm-dbus-utils.c', 'nm-errors.c', @@ -127,7 +135,6 @@ libnm_core_enum = gnome.mkenums( ) deps = [ - crypto_dep, dl_dep, libudev_dep, shared_dep, @@ -138,12 +145,6 @@ deps = [ cflags = [ '-DG_LOG_DOMAIN="@0@"'.format(libnm_name), '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE', - '-DLIBEXECDIR="@0@"'.format(nm_libexecdir), - '-DNMLOCALEDIR="@0@"'.format(nm_localedir), - '-DNMCONFDIR="@0@"'.format(nm_pkgconfdir), - '-DNMLIBDIR="@0@"'.format(nm_pkglibdir), - '-DNMPLUGINDIR="@0@"'.format(nm_plugindir), - '-DNMVPNDIR="@0@"'.format(nm_vpndir) ] if enable_json_validation @@ -151,9 +152,36 @@ if enable_json_validation deps += jansson_dep endif +if (crypto_gnutls_dep.found()) + libnm_crypto_gnutls = static_library( + 'nm-crypto-gnutls', + sources: [ 'nm-crypto-gnutls.c' ], + dependencies: deps + [ crypto_gnutls_dep ], + c_args: cflags + ) +endif + +if (crypto_nss_dep.found()) + libnm_crypto_nss = static_library( + 'nm-crypto-nss', + sources: [ 'nm-crypto-nss.c' ], + dependencies: deps + [ crypto_nss_dep ], + c_args: cflags + ) +endif + +if crypto == 'gnutls' + libnm_crypto = libnm_crypto_gnutls +elif crypto == 'nss' + libnm_crypto = libnm_crypto_nss +else + error('bug') +endif + libnm_core_sources_all = libnm_core_sources libnm_core_sources_all += libnm_core_enum -libnm_core_sources_all += shared_nm_utils_nm_meta_setting_c +libnm_core_sources_all += shared_nm_meta_setting_c +libnm_core_sources_all += shared_nm_ethtool_utils_c libnm_core_sources_all += shared_files_libnm_core libnm_core_sources_all += [version_header] @@ -161,6 +189,7 @@ libnm_core = static_library( 'nm-core', sources: libnm_core_sources_all, dependencies: deps, + link_with: libnm_crypto, c_args: cflags ) diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 0c4d7ce1..a5df0814 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2017 Red Hat, Inc. + * Copyright 2007 - 2018 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -225,6 +225,40 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name) return type ? _connection_get_setting (connection, type) : NULL; } +/*****************************************************************************/ + +gpointer /* (NMSetting *) */ +_nm_connection_check_main_setting (NMConnection *connection, + const char *setting_name, + GError **error) +{ + NMSetting *setting; + + nm_assert (NM_IS_CONNECTION (connection)); + nm_assert (setting_name); + + if (!nm_connection_is_type (connection, setting_name)) { + nm_utils_error_set (error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "connection type is not \"%s\"", + setting_name); + return NULL; + } + + setting = nm_connection_get_setting_by_name (connection, setting_name); + if (!setting) { + nm_utils_error_set (error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "connection misses \"%s\" settings", + setting_name); + return NULL; + } + + return setting; +} + +/*****************************************************************************/ + static gboolean validate_permissions_type (GVariant *variant, GError **error) { @@ -809,16 +843,34 @@ _normalize_ethernet_link_neg (NMConnection *self) return FALSE; } +/** + * _supports_addr_family: + * @self: a #NMConnection + * @family: AF_* + * + * Check whether the connection supports certain L3 address family, + * in order to be able to tell whether is should have the corresponding + * setting ("ipv4" for AF_INET and "ipv6" for AF_INET6). + * + * If AF_UNSPEC is given, then the function checks whether the connection + * supports any L3 configuration at all. + * + * Returns: %TRUE if the AF is supported, %FALSE otherwise + **/ static gboolean -_without_ip_config (NMConnection *self) +_supports_addr_family (NMConnection *self, int family) { const char *connection_type = nm_connection_get_connection_type (self); - g_return_val_if_fail (connection_type, FALSE); + g_return_val_if_fail (connection_type, TRUE); if (strcmp (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) + return TRUE; + if (strcmp (connection_type, NM_SETTING_WPAN_SETTING_NAME) == 0) return FALSE; + if (strcmp (connection_type, NM_SETTING_6LOWPAN_SETTING_NAME) == 0) + return family == AF_INET6 || family == AF_UNSPEC; - return !!nm_setting_connection_get_master (nm_connection_get_setting_connection (self)); + return !nm_setting_connection_get_master (nm_connection_get_setting_connection (self)); } static gboolean @@ -841,32 +893,18 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) s_ip6 = nm_connection_get_setting_ip6_config (self); s_proxy = nm_connection_get_setting_proxy (self); - if (_without_ip_config (self)) { - /* Slave connections don't have IP configuration. */ - - if (s_ip4) - nm_connection_remove_setting (self, NM_TYPE_SETTING_IP4_CONFIG); - - if (s_ip6) - nm_connection_remove_setting (self, NM_TYPE_SETTING_IP6_CONFIG); - - if (s_proxy) - nm_connection_remove_setting (self, NM_TYPE_SETTING_PROXY); - - return s_ip4 || s_ip6 || s_proxy; - } else { - /* Ensure all non-slave connections have IP4 and IP6 settings objects. If no - * IP6 setting was specified, then assume that means IP6 config is allowed - * to fail. But if no IP4 setting was specified, assume the caller was just - * being lazy. - */ + if (_supports_addr_family (self, AF_INET)) { if (!s_ip4) { + /* But if no IP4 setting was specified, assume the caller was just + * being lazy and use the default method. + */ setting = nm_setting_ip4_config_new (); g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, default_ip4_method, NULL); nm_connection_add_setting (self, setting); + changed = TRUE; } else { if ( nm_setting_ip_config_get_gateway (s_ip4) && nm_setting_ip_config_get_never_default (s_ip4)) { @@ -890,7 +928,18 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) changed = TRUE; } } + } else { + if (s_ip4) { + nm_connection_remove_setting (self, NM_TYPE_SETTING_IP4_CONFIG); + changed = TRUE; + } + } + + if (_supports_addr_family (self, AF_INET6)) { if (!s_ip6) { + /* If no IP6 setting was specified, then assume that means IP6 config is + * allowed to fail. + */ setting = nm_setting_ip6_config_new (); g_object_set (setting, @@ -898,6 +947,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); nm_connection_add_setting (self, setting); + changed = TRUE; } else { const char *token; @@ -930,14 +980,27 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) changed = TRUE; } } + } else { + if (s_ip6) { + nm_connection_remove_setting (self, NM_TYPE_SETTING_IP6_CONFIG); + changed = TRUE; + } + } + if (_supports_addr_family (self, AF_UNSPEC)) { if (!s_proxy) { setting = nm_setting_proxy_new (); nm_connection_add_setting (self, setting); + changed = TRUE; + } + } else { + if (s_proxy) { + nm_connection_remove_setting (self, NM_TYPE_SETTING_PROXY); + changed = TRUE; } - - return !s_ip4 || !s_ip6 || !s_proxy || changed; } + + return changed; } static gboolean @@ -1129,6 +1192,38 @@ _normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters) } static gboolean +_normalize_ip_tunnel_wired_setting (NMConnection *self, GHashTable *parameters) +{ + NMSettingIPTunnel *s_ip_tunnel; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (self); + if (!s_ip_tunnel) + return FALSE; + + if ( nm_connection_get_setting_wired (self) + && !NM_IN_SET (nm_setting_ip_tunnel_get_mode (s_ip_tunnel), + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + nm_connection_remove_setting (self, NM_TYPE_SETTING_WIRED); + return TRUE; + } + + return FALSE; +} + +static gboolean +_normalize_sriov_vf_order (NMConnection *self, GHashTable *parameters) +{ + NMSettingSriov *s_sriov; + + s_sriov = nm_connection_get_setting_sriov (self); + if (!s_sriov) + return FALSE; + + return _nm_setting_sriov_sort_vfs (s_sriov); +} + +static gboolean _normalize_required_settings (NMConnection *self, GHashTable *parameters) { NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self); @@ -1288,39 +1383,79 @@ _nm_connection_verify (NMConnection *connection, GError **error) nm_assert (normalizable_error_type != NM_SETTING_VERIFY_ERROR); if (NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS, NM_SETTING_VERIFY_NORMALIZABLE)) { - if (_without_ip_config (connection)) { - if (s_ip4 || s_ip6 || s_proxy) { + if (_supports_addr_family (connection, AF_INET)) { + if (!s_ip4 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { + g_set_error_literal (&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting is required for non-slave connections")); + g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME); + + /* having a master without IP config was not a verify() error, accept + * it for backward compatibility. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + } + } else { + if (s_ip4) { g_clear_error (&normalizable_error); g_set_error_literal (&normalizable_error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, _("setting not allowed in slave connection")); - g_prefix_error (&normalizable_error, "%s: ", - s_ip4 - ? NM_SETTING_IP4_CONFIG_SETTING_NAME - : (s_ip6 - ? NM_SETTING_IP6_CONFIG_SETTING_NAME - : NM_SETTING_PROXY_SETTING_NAME)); + g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME); /* having a slave with IP config *was* and is a verify() error. */ normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; } - } else { - if ( normalizable_error_type == NM_SETTING_VERIFY_SUCCESS - && (!s_ip4 || !s_ip6 || !s_proxy)) { + } + + if (_supports_addr_family (connection, AF_INET6)) { + if (!s_ip6 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { g_set_error_literal (&normalizable_error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, _("setting is required for non-slave connections")); - g_prefix_error (&normalizable_error, "%s: ", - !s_ip4 - ? NM_SETTING_IP4_CONFIG_SETTING_NAME - : (!s_ip6 - ? NM_SETTING_IP6_CONFIG_SETTING_NAME - : NM_SETTING_PROXY_SETTING_NAME)); + g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME); + /* having a master without IP config was not a verify() error, accept * it for backward compatibility. */ normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; } + } else { + if (s_ip6) { + g_clear_error (&normalizable_error); + g_set_error_literal (&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting not allowed in slave connection")); + g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME); + /* having a slave with IP config *was* and is a verify() error. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } + + if (_supports_addr_family (connection, AF_UNSPEC)) { + if (!s_proxy && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) { + g_set_error_literal (&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting is required for non-slave connections")); + g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME); + + /* having a master without proxy config was not a verify() error, accept + * it for backward compatibility. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + } + } else { + if (s_proxy) { + g_clear_error (&normalizable_error); + g_set_error_literal (&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting not allowed in slave connection")); + g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME); + /* having a slave with proxy config *was* and is a verify() error. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } } } @@ -1433,6 +1568,8 @@ nm_connection_normalize (NMConnection *connection, was_modified |= _normalize_team_port_config (connection, parameters); was_modified |= _normalize_bluetooth_type (connection, parameters); was_modified |= _normalize_ovs_interface_type (connection, parameters); + was_modified |= _normalize_ip_tunnel_wired_setting (connection, parameters); + was_modified |= _normalize_sriov_vf_order (connection, parameters); /* Verify anew. */ success = _nm_connection_verify (connection, error); @@ -1858,9 +1995,10 @@ nm_connection_for_each_setting_value (NMConnection *connection, * nm_connection_dump: * @connection: the #NMConnection * - * Print the connection to stdout. For debugging purposes ONLY, should NOT - * be used for serialization of the connection or machine-parsed in any way. The - * output format is not guaranteed to be stable and may change at any time. + * Print the connection (including secrets!) to stdout. For debugging + * purposes ONLY, should NOT be used for serialization of the setting, + * or machine-parsed in any way. The output format is not guaranteed to + * be stable and may change at any time. **/ void nm_connection_dump (NMConnection *connection) @@ -1943,6 +2081,32 @@ nm_connection_get_interface_name (NMConnection *connection) return s_con ? nm_setting_connection_get_interface_name (s_con) : NULL; } +NMConnectionMultiConnect +_nm_connection_get_multi_connect (NMConnection *connection) +{ + NMSettingConnection *s_con; + NMConnectionMultiConnect multi_connect; + const NMConnectionMultiConnect DEFAULT = NM_CONNECTION_MULTI_CONNECT_SINGLE; + + /* connection.multi_connect property cannot be specified via regular + * connection defaults in NetworkManager.conf, because those are per-device, + * and we need to determine the multi_connect independent of a particular + * device. + * + * There is however still a default-value, so theoretically, the default + * value could be specified in NetworkManager.conf. Just not as [connection*] + * and indepdented of a device. */ + + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) + return DEFAULT; + + multi_connect = nm_setting_connection_get_multi_connect (s_con); + return multi_connect == NM_CONNECTION_MULTI_CONNECT_DEFAULT + ? DEFAULT + : multi_connect; +} + gboolean _nm_connection_verify_required_interface_name (NMConnection *connection, GError **error) @@ -2033,7 +2197,8 @@ nm_connection_is_virtual (NMConnection *connection) if (!type) return FALSE; - if ( !strcmp (type, NM_SETTING_BOND_SETTING_NAME) + if ( !strcmp (type, NM_SETTING_6LOWPAN_SETTING_NAME) + || !strcmp (type, NM_SETTING_BOND_SETTING_NAME) || !strcmp (type, NM_SETTING_DUMMY_SETTING_NAME) || !strcmp (type, NM_SETTING_TEAM_SETTING_NAME) || !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME) @@ -2114,6 +2279,22 @@ nm_connection_get_virtual_device_description (NMConnection *connection) /*****************************************************************************/ /** + * nm_connection_get_setting_6lowpan: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSetting6Lowpan the connection might contain. + * + * Returns: (transfer none): an #NMSetting6Lowpan if the connection contains one, otherwise %NULL + * + * Since: 1.14 + **/ +NMSetting6Lowpan * +nm_connection_get_setting_6lowpan (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_6LOWPAN); +} + +/** * nm_connection_get_setting_802_1x: * @connection: the #NMConnection * @@ -2520,6 +2701,22 @@ nm_connection_get_setting_serial (NMConnection *connection) } /** + * nm_connection_get_setting_sriov: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingSriov the connection might contain. + * + * Returns: (transfer none): an #NMSettingSriov if the connection contains one, otherwise %NULL + * + * Since: 1.14 + **/ +NMSettingSriov * +nm_connection_get_setting_sriov (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_SRIOV); +} + +/** * nm_connection_get_setting_tc_config: * @connection: the #NMConnection * @@ -2679,6 +2876,22 @@ nm_connection_get_setting_vlan (NMConnection *connection) return _connection_get_setting_check (connection, NM_TYPE_SETTING_VLAN); } +/** + * nm_connection_get_setting_wpan: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingWpan the connection might contain. + * + * Returns: (transfer none): an #NMSettingWpan if the connection contains one, otherwise %NULL + * + * Since: 1.14 + **/ +NMSettingWpan * +nm_connection_get_setting_wpan (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_WPAN); +} + NMSettingBluetooth * _nm_connection_get_setting_bluetooth_for_nap (NMConnection *connection) { diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h index 6d23cfdb..312760f1 100644 --- a/libnm-core/nm-connection.h +++ b/libnm-core/nm-connection.h @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2017 Red Hat, Inc. + * Copyright 2007 - 2018 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -193,6 +193,8 @@ const char * nm_connection_get_connection_type (NMConnection *connection); gboolean nm_connection_is_virtual (NMConnection *connection); char * nm_connection_get_virtual_device_description (NMConnection *connection); +NM_AVAILABLE_IN_1_14 +NMSetting6Lowpan * nm_connection_get_setting_6lowpan (NMConnection *connection); NMSetting8021x * nm_connection_get_setting_802_1x (NMConnection *connection); NMSettingBluetooth * nm_connection_get_setting_bluetooth (NMConnection *connection); NMSettingBond * nm_connection_get_setting_bond (NMConnection *connection); @@ -229,6 +231,8 @@ NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnec NM_AVAILABLE_IN_1_6 NMSettingProxy * nm_connection_get_setting_proxy (NMConnection *connection); NMSettingSerial * nm_connection_get_setting_serial (NMConnection *connection); +NM_AVAILABLE_IN_1_14 +NMSettingSriov * nm_connection_get_setting_sriov (NMConnection *connection); NM_AVAILABLE_IN_1_12 NMSettingTCConfig * nm_connection_get_setting_tc_config (NMConnection *connection); NMSettingTun * nm_connection_get_setting_tun (NMConnection *connection); @@ -241,6 +245,8 @@ NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security (NMConnec NMSettingVlan * nm_connection_get_setting_vlan (NMConnection *connection); NM_AVAILABLE_IN_1_2 NMSettingVxlan * nm_connection_get_setting_vxlan (NMConnection *connection); +NM_AVAILABLE_IN_1_14 +NMSettingWpan * nm_connection_get_setting_wpan (NMConnection *connection); G_END_DECLS diff --git a/libnm-core/nm-core-enum-types.c.template b/libnm-core/nm-core-enum-types.c.template index 9c08f526..605fa34a 100644 --- a/libnm-core/nm-core-enum-types.c.template +++ b/libnm-core/nm-core-enum-types.c.template @@ -48,6 +48,7 @@ #include "nm-setting-wired.h" #include "nm-setting-wireless-security.h" #include "nm-setting-wireless.h" +#include "nm-setting-wpan.h" #include "nm-setting.h" #include "nm-simple-connection.h" #include "nm-utils.h" diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 2a2045e6..f0d4e40f 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -15,7 +15,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * (C) Copyright 2014 - 2017 Red Hat, Inc. + * (C) Copyright 2014 - 2018 Red Hat, Inc. */ #ifndef NM_CORE_NM_INTERNAL_H @@ -37,6 +37,7 @@ #include "nm-connection.h" #include "nm-core-enum-types.h" +#include "nm-setting-6lowpan.h" #include "nm-setting-8021x.h" #include "nm-setting-adsl.h" #include "nm-setting-bluetooth.h" @@ -56,6 +57,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-macsec.h" #include "nm-setting-macvlan.h" +#include "nm-setting-match.h" #include "nm-setting-olpc-mesh.h" #include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-interface.h" @@ -64,6 +66,7 @@ #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" #include "nm-setting-serial.h" +#include "nm-setting-sriov.h" #include "nm-setting-tc-config.h" #include "nm-setting-team-port.h" #include "nm-setting-team.h" @@ -75,12 +78,14 @@ #include "nm-setting-wired.h" #include "nm-setting-wireless-security.h" #include "nm-setting-wireless.h" +#include "nm-setting-wpan.h" #include "nm-setting.h" #include "nm-simple-connection.h" #include "nm-utils.h" #include "nm-vpn-dbus-interface.h" #include "nm-core-types-internal.h" #include "nm-vpn-editor-plugin.h" +#include "nm-meta-setting.h" /* IEEE 802.1D-1998 timer values */ #define NM_BR_MIN_HELLO_TIME 1 @@ -137,6 +142,10 @@ gboolean _nm_connection_replace_settings (NMConnection *connection, NMSettingParseFlags parse_flags, GError **error); +gpointer _nm_connection_check_main_setting (NMConnection *connection, + const char *setting_name, + GError **error); + /** * NMSettingVerifyResult: * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully @@ -161,49 +170,43 @@ NMConnection *_nm_simple_connection_new_from_dbus (GVariant *dict, NMSettingParseFlags parse_flags, GError **error); -/* - * A setting's priority should roughly follow the OSI layer model, but it also - * controls which settings get asked for secrets first. Thus settings which - * relate to things that must be working first, like hardware, should get a - * higher priority than things which layer on top of the hardware. For example, - * the GSM/CDMA settings should provide secrets before the PPP setting does, - * because a PIN is required to unlock the device before PPP can even start. - * Even settings without secrets should be assigned the right priority. - * - * 0: reserved for invalid - * - * 1: reserved for the Connection setting - * - * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. - * These priority 1 settings are also "base types", which means that at least - * one of them is required for the connection to be valid, and their name is - * valid in the 'type' property of the Connection setting. - * - * 4: hardware-related auxiliary settings that require a base setting to be - * successful first, like Wi-Fi security, 802.1x, etc. - * - * 5: hardware-independent settings that are required before IP connectivity - * can be established, like PPP, PPPoE, etc. - * - * 6: IP-level stuff - * - * 10: NMSettingUser - */ -typedef enum { /*< skip >*/ - NM_SETTING_PRIORITY_INVALID = 0, - NM_SETTING_PRIORITY_CONNECTION = 1, - NM_SETTING_PRIORITY_HW_BASE = 2, - NM_SETTING_PRIORITY_HW_NON_BASE = 3, - NM_SETTING_PRIORITY_HW_AUX = 4, - NM_SETTING_PRIORITY_AUX = 5, - NM_SETTING_PRIORITY_IP = 6, - NM_SETTING_PRIORITY_USER = 10, -} NMSettingPriority; - NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting); gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); +/*****************************************************************************/ + +GHashTable *_nm_setting_gendata_hash (NMSetting *setting, + gboolean create_if_necessary); + +void _nm_setting_gendata_notify (NMSetting *setting, + gboolean keys_changed); + +guint _nm_setting_gendata_get_all (NMSetting *setting, + const char *const**out_names, + GVariant *const**out_values); + +gboolean _nm_setting_gendata_reset_from_hash (NMSetting *setting, + GHashTable *new); + +void _nm_setting_gendata_to_gvalue (NMSetting *setting, + GValue *value); + +GVariant *nm_setting_gendata_get (NMSetting *setting, + const char *name); + +const char *const*nm_setting_gendata_get_all_names (NMSetting *setting, + guint *out_len); + +GVariant *const*nm_setting_gendata_get_all_values (NMSetting *setting); + +/*****************************************************************************/ + +guint nm_setting_ethtool_init_features (NMSettingEthtool *setting, + NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */); + +/*****************************************************************************/ + #define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3) guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length); @@ -212,6 +215,13 @@ const char *nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboole char *_nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case); void _nm_utils_bin2str_full (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out); +guint8 *_nm_utils_str2bin_full (const char *asc, + gboolean delimiter_required, + const char *delimiter_candidates, + guint8 *buffer, + gsize buffer_length, + gsize *out_len); + GSList * _nm_utils_hash_values_to_slist (GHashTable *hash); GHashTable *_nm_utils_copy_strdict (GHashTable *strdict); @@ -224,6 +234,9 @@ gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route); const char **_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length); GHashTable *_nm_ip_route_get_attributes_direct (NMIPRoute *route); +NMSriovVF *_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error); +gboolean _nm_sriov_vf_attribute_validate_all (const NMSriovVF *vf, GError **error); + static inline void _nm_auto_ip_route_unref (NMIPRoute **v) { @@ -232,12 +245,6 @@ _nm_auto_ip_route_unref (NMIPRoute **v) } #define nm_auto_ip_route_unref nm_auto (_nm_auto_ip_route_unref) -GPtrArray *_nm_utils_copy_slist_to_array (const GSList *list, - NMUtilsCopyFunc copy_func, - GDestroyNotify unref_func); -GSList *_nm_utils_copy_array_to_slist (const GPtrArray *array, - NMUtilsCopyFunc copy_func); - GPtrArray *_nm_utils_copy_array (const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func); @@ -245,15 +252,6 @@ GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array); gssize _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer needle); -gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data, - gssize *out_idx_first, - gssize *out_idx_last); -gssize _nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data); - GSList * _nm_utils_strv_to_slist (char **strv, gboolean deep_copy); char ** _nm_utils_slist_to_strv (GSList *slist, gboolean deep_copy); @@ -296,12 +294,6 @@ void _nm_dbus_errors_init (void); extern gboolean _nm_utils_is_manager_process; -GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data, - gsize len, - const char *in_password, - char **out_password, - GError **error); - gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy, const char *signal_name, const GVariantType *signature, @@ -318,11 +310,11 @@ GVariant *_nm_dbus_proxy_call_finish (GDBusProxy *proxy, GError **error); GVariant *_nm_dbus_proxy_call_sync (GDBusProxy *proxy, - const gchar *method_name, + const char *method_name, GVariant *parameters, const GVariantType *reply_type, GDBusCallFlags flags, - gint timeout_msec, + int timeout_msec, GCancellable *cancellable, GError **error); @@ -331,6 +323,13 @@ gboolean _nm_dbus_error_has_name (GError *error, /*****************************************************************************/ +char *_nm_utils_ssid_to_string_arr (const guint8 *ssid, gsize len); +char *_nm_utils_ssid_to_string (GBytes *ssid); +char *_nm_utils_ssid_to_utf8 (GBytes *ssid); +gboolean _nm_utils_is_empty_ssid (GBytes *ssid); + +/*****************************************************************************/ + gboolean _nm_vpn_plugin_info_check_file (const char *filename, gboolean check_absolute, gboolean do_validate_filename, @@ -427,6 +426,8 @@ _nm_connection_get_uuid (NMConnection *connection) return connection ? nm_connection_get_uuid (connection) : NULL; } +NMConnectionMultiConnect _nm_connection_get_multi_connect (NMConnection *connection); + /*****************************************************************************/ typedef enum { @@ -511,4 +512,89 @@ _nm_connection_type_is_master (const char *type) gboolean _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin); /*****************************************************************************/ + +gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting); + +/*****************************************************************************/ + +typedef struct _NMSettInfoSetting NMSettInfoSetting; + +typedef GVariant *(*NMSettingPropertyGetFunc) (NMSetting *setting, + const char *property); +typedef GVariant *(*NMSettingPropertySynthFunc) (NMSetting *setting, + NMConnection *connection, + const char *property); +typedef gboolean (*NMSettingPropertySetFunc) (NMSetting *setting, + GVariant *connection_dict, + const char *property, + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error); +typedef gboolean (*NMSettingPropertyNotSetFunc) (NMSetting *setting, + GVariant *connection_dict, + const char *property, + NMSettingParseFlags parse_flags, + GError **error); +typedef GVariant *(*NMSettingPropertyTransformToFunc) (const GValue *from); +typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from, + GValue *to); + +typedef struct { + const char *name; + GParamSpec *param_spec; + const GVariantType *dbus_type; + + NMSettingPropertyGetFunc get_func; + NMSettingPropertySynthFunc synth_func; + NMSettingPropertySetFunc set_func; + NMSettingPropertyNotSetFunc not_set_func; + + NMSettingPropertyTransformToFunc to_dbus; + NMSettingPropertyTransformFromFunc from_dbus; +} NMSettInfoProperty; + +typedef struct { + const GVariantType *(*get_variant_type) (const struct _NMSettInfoSetting *sett_info, + const char *name, + GError **error); +} NMSettInfoSettGendata; + +typedef struct { + /* if set, then this setting class has no own fields. Instead, its + * data is entirely based on gendata. Meaning: it tracks all data + * as native GVariants. + * It might have some GObject properties, but these are merely accessors + * to the underlying gendata. + * + * Note, that at the moment there are few hooks, to customize the behavior + * of the setting further. They are currently unneeded. This is desired, + * but could be added when there is a good reason. + * + * However, a few hooks there are... see NMSettInfoSettGendata. */ + const NMSettInfoSettGendata *gendata_info; +} NMSettInfoSettDetail; + +struct _NMSettInfoSetting { + NMSettingClass *setting_class; + const NMSettInfoProperty *property_infos; + guint property_infos_len; + NMSettInfoSettDetail detail; +}; + +const NMSettInfoSetting *_nm_sett_info_setting_get (NMSettingClass *setting_class); + +const NMSettInfoProperty *_nm_sett_info_property_get (NMSettingClass *setting_class, + const char *property_name); + +/*****************************************************************************/ + +NMSetting8021xCKScheme _nm_setting_802_1x_cert_get_scheme (GBytes *bytes, GError **error); + +GBytes *_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme, + const guint8 *val_bin, + gssize val_len, + GError **error); + +/*****************************************************************************/ + #endif diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index 6a274333..89d99579 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2014 - 2017 Red Hat, Inc. + * Copyright 2014 - 2018 Red Hat, Inc. */ #ifndef __NM_CORE_TYPES_H__ @@ -29,6 +29,7 @@ typedef struct _NMConnection NMConnection; typedef struct _NMSetting NMSetting; +typedef struct _NMSetting6Lowpan NMSetting6Lowpan; typedef struct _NMSetting8021x NMSetting8021x; typedef struct _NMSettingAdsl NMSettingAdsl; typedef struct _NMSettingBluetooth NMSettingBluetooth; @@ -39,6 +40,7 @@ typedef struct _NMSettingCdma NMSettingCdma; typedef struct _NMSettingConnection NMSettingConnection; typedef struct _NMSettingDcb NMSettingDcb; typedef struct _NMSettingDummy NMSettingDummy; +typedef struct _NMSettingEthtool NMSettingEthtool; typedef struct _NMSettingGeneric NMSettingGeneric; typedef struct _NMSettingGsm NMSettingGsm; typedef struct _NMSettingInfiniband NMSettingInfiniband; @@ -49,6 +51,7 @@ typedef struct _NMSettingIP4Config NMSettingIP4Config; typedef struct _NMSettingIP6Config NMSettingIP6Config; typedef struct _NMSettingMacsec NMSettingMacsec; typedef struct _NMSettingMacvlan NMSettingMacvlan; +typedef struct _NMSettingMatch NMSettingMatch; typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh; typedef struct _NMSettingOvsBridge NMSettingOvsBridge; typedef struct _NMSettingOvsInterface NMSettingOvsInterface; @@ -57,6 +60,7 @@ typedef struct _NMSettingOvsPort NMSettingOvsPort; typedef struct _NMSettingPpp NMSettingPpp; typedef struct _NMSettingPppoe NMSettingPppoe; typedef struct _NMSettingSerial NMSettingSerial; +typedef struct _NMSettingSriov NMSettingSriov; typedef struct _NMSettingTCConfig NMSettingTCConfig; typedef struct _NMSettingTeam NMSettingTeam; typedef struct _NMSettingTeamPort NMSettingTeamPort; @@ -69,6 +73,7 @@ typedef struct _NMSettingWimax NMSettingWimax; typedef struct _NMSettingWired NMSettingWired; typedef struct _NMSettingWireless NMSettingWireless; typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity; +typedef struct _NMSettingWpan NMSettingWpan; typedef struct _NMSimpleConnection NMSimpleConnection; #endif /* __NM_CORE_TYPES_H__ */ diff --git a/libnm-core/crypto_gnutls.c b/libnm-core/nm-crypto-gnutls.c index 53a3ba4a..6c897e6d 100644 --- a/libnm-core/crypto_gnutls.c +++ b/libnm-core/nm-crypto-gnutls.c @@ -23,26 +23,53 @@ #include "nm-default.h" +#include "nm-crypto-impl.h" + #include <gnutls/gnutls.h> #include <gnutls/crypto.h> #include <gnutls/x509.h> #include <gnutls/pkcs12.h> -#include "crypto.h" +#include "nm-utils/nm-secret-utils.h" #include "nm-errors.h" -#define SALT_LEN 8 +/*****************************************************************************/ + +static gboolean +_get_cipher_info (NMCryptoCipherType cipher, + int *out_cipher_mech, + guint8 *out_real_iv_len) +{ + static const int cipher_mechs[] = { + [NM_CRYPTO_CIPHER_DES_EDE3_CBC] = GNUTLS_CIPHER_3DES_CBC, + [NM_CRYPTO_CIPHER_DES_CBC] = GNUTLS_CIPHER_DES_CBC, + [NM_CRYPTO_CIPHER_AES_128_CBC] = GNUTLS_CIPHER_AES_128_CBC, + [NM_CRYPTO_CIPHER_AES_192_CBC] = GNUTLS_CIPHER_AES_192_CBC, + [NM_CRYPTO_CIPHER_AES_256_CBC] = GNUTLS_CIPHER_AES_256_CBC, + }; + + g_return_val_if_fail (_NM_INT_NOT_NEGATIVE (cipher) && (gsize) cipher < G_N_ELEMENTS (cipher_mechs), FALSE); + + if (cipher_mechs[cipher] == 0) + return FALSE; -static gboolean initialized = FALSE; + NM_SET_OUT (out_cipher_mech, cipher_mechs[cipher]); + NM_SET_OUT (out_real_iv_len, nm_crypto_cipher_get_info (cipher)->real_iv_len); + return TRUE; +} + +/*****************************************************************************/ gboolean -crypto_init (GError **error) +_nm_crypto_init (GError **error) { + static gboolean initialized = FALSE; + if (initialized) return TRUE; - if (gnutls_global_init() != 0) { - gnutls_global_deinit(); + if (gnutls_global_init () != 0) { + gnutls_global_deinit (); g_set_error_literal (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the crypto engine.")); @@ -53,55 +80,47 @@ crypto_init (GError **error) return TRUE; } -char * -crypto_decrypt (const char *cipher, - int key_type, - const guint8 *data, - gsize data_len, - const char *iv, - const gsize iv_len, - const char *key, - const gsize key_len, - gsize *out_len, - GError **error) +/*****************************************************************************/ + +guint8 * +_nmtst_crypto_decrypt (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const guint8 *iv, + gsize iv_len, + const guint8 *key, + gsize key_len, + gsize *out_len, + GError **error) { gnutls_cipher_hd_t ctx; gnutls_datum_t key_dt, iv_dt; int err; - int cipher_mech, i; - char *output = NULL; - gboolean success = FALSE; - gsize pad_len, real_iv_len; - - if (!crypto_init (error)) - return NULL; + int cipher_mech; + nm_auto_clear_secret_ptr NMSecretPtr output = { 0 }; + guint8 pad_i, pad_len; + guint8 real_iv_len; - if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { - cipher_mech = GNUTLS_CIPHER_3DES_CBC; - real_iv_len = SALT_LEN; - } else if (!strcmp (cipher, CIPHER_DES_CBC)) { - cipher_mech = GNUTLS_CIPHER_DES_CBC; - real_iv_len = SALT_LEN; - } else if (!strcmp (cipher, CIPHER_AES_CBC)) { - cipher_mech = GNUTLS_CIPHER_AES_128_CBC; - real_iv_len = 16; - } else { + if (!_get_cipher_info (cipher, &cipher_mech, &real_iv_len)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Private key cipher '%s' was unknown."), - cipher); + _("Unsupported key cipher for decryption")); return NULL; } + if (!_nm_crypto_init (error)) + return NULL; + if (iv_len < real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, - _("Invalid IV length (must be at least %zd)."), - real_iv_len); + _("Invalid IV length (must be at least %u)."), + (guint) real_iv_len); return NULL; } - output = g_malloc0 (data_len); + output.len = data_len; + output.bin = g_malloc (data_len); key_dt.data = (unsigned char *) key; key_dt.size = key_len; @@ -114,103 +133,81 @@ crypto_decrypt (const char *cipher, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to initialize the decryption cipher context: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); - goto out; + return NULL; } - err = gnutls_cipher_decrypt2 (ctx, data, data_len, output, data_len); + err = gnutls_cipher_decrypt2 (ctx, data, data_len, output.bin, output.len); + + gnutls_cipher_deinit (ctx); + if (err < 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); - goto out; + return NULL; } - pad_len = output[data_len - 1]; + + pad_len = output.len > 0 + ? output.bin[output.len - 1] + : 0; /* Check if the padding at the end of the decrypted data is valid */ - if (pad_len == 0 || pad_len > real_iv_len) { + if ( pad_len == 0 + || pad_len > real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: unexpected padding length.")); - goto out; + return NULL; } /* Validate tail padding; last byte is the padding size, and all pad bytes * should contain the padding size. */ - for (i = 1; i <= pad_len; ++i) { - if (output[data_len - i] != pad_len) { + for (pad_i = 1; pad_i <= pad_len; ++pad_i) { + if (output.bin[data_len - pad_i] != pad_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key.")); - goto out; + return NULL; } } - *out_len = data_len - pad_len; - success = TRUE; - -out: - if (!success) { - if (output) { - /* Don't expose key material */ - memset (output, 0, data_len); - g_free (output); - output = NULL; - } - } - gnutls_cipher_deinit (ctx); - return output; + *out_len = output.len - pad_len; + return g_steal_pointer (&output.bin); } -char * -crypto_encrypt (const char *cipher, - const guint8 *data, - gsize data_len, - const char *iv, - const gsize iv_len, - const char *key, - gsize key_len, - gsize *out_len, - GError **error) +guint8 * +_nmtst_crypto_encrypt (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const guint8 *iv, + gsize iv_len, + const guint8 *key, + gsize key_len, + gsize *out_len, + GError **error) { gnutls_cipher_hd_t ctx; gnutls_datum_t key_dt, iv_dt; int err; int cipher_mech; - char *output = NULL; - gboolean success = FALSE; - gsize padded_buf_len, pad_len, output_len; - char *padded_buf = NULL; - guint32 i; + nm_auto_clear_secret_ptr NMSecretPtr output = { 0 }; + nm_auto_clear_secret_ptr NMSecretPtr padded_buf = { 0 }; + gsize i, pad_len; - if (!crypto_init (error)) - return NULL; + nm_assert (iv_len); - if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) - cipher_mech = GNUTLS_CIPHER_3DES_CBC; - else if (!strcmp (cipher, CIPHER_AES_CBC)) - cipher_mech = GNUTLS_CIPHER_AES_128_CBC; - else { + if ( cipher == NM_CRYPTO_CIPHER_DES_CBC + || !_get_cipher_info (cipher, &cipher_mech, NULL)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Private key cipher '%s' was unknown."), - cipher); + _("Unsupported key cipher for encryption")); return NULL; } - /* If data_len % ivlen == 0, then we add another complete block - * onto the end so that the decrypter knows there's padding. - */ - pad_len = iv_len - (data_len % iv_len); - output_len = padded_buf_len = data_len + pad_len; - padded_buf = g_malloc0 (padded_buf_len); - - memcpy (padded_buf, data, data_len); - for (i = 0; i < pad_len; i++) - padded_buf[data_len + i] = (guint8) (pad_len & 0xFF); - - output = g_malloc0 (output_len); + if (!_nm_crypto_init (error)) + return NULL; key_dt.data = (unsigned char *) key; key_dt.size = key_len; @@ -223,51 +220,50 @@ crypto_encrypt (const char *cipher, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to initialize the encryption cipher context: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); - goto out; + return NULL; } - err = gnutls_cipher_encrypt2 (ctx, padded_buf, padded_buf_len, output, output_len); + /* If data_len % ivlen == 0, then we add another complete block + * onto the end so that the decrypter knows there's padding. + */ + pad_len = iv_len - (data_len % iv_len); + + padded_buf.len = data_len + pad_len; + padded_buf.bin = g_malloc (padded_buf.len); + memcpy (padded_buf.bin, data, data_len); + for (i = 0; i < pad_len; i++) + padded_buf.bin[data_len + i] = (guint8) (pad_len & 0xFF); + + output.len = padded_buf.len; + output.bin = g_malloc (output.len); + + err = gnutls_cipher_encrypt2 (ctx, padded_buf.bin, padded_buf.len, output.bin, output.len); + + gnutls_cipher_deinit (ctx); + if (err < 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to encrypt the data: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); - goto out; - } - - *out_len = output_len; - success = TRUE; - -out: - if (padded_buf) { - memset (padded_buf, 0, padded_buf_len); - g_free (padded_buf); - padded_buf = NULL; + return NULL; } - if (!success) { - if (output) { - /* Don't expose key material */ - memset (output, 0, output_len); - g_free (output); - output = NULL; - } - } - gnutls_cipher_deinit (ctx); - return output; + *out_len = output.len; + return g_steal_pointer (&output.bin); } -NMCryptoFileFormat -crypto_verify_cert (const unsigned char *data, - gsize len, - GError **error) +gboolean +_nm_crypto_verify_x509 (const guint8 *data, + gsize len, + GError **error) { gnutls_x509_crt_t der; gnutls_datum_t dt; int err; - if (!crypto_init (error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + if (!_nm_crypto_init (error)) + return FALSE; err = gnutls_x509_crt_init (&der); if (err < 0) { @@ -275,7 +271,7 @@ crypto_verify_cert (const unsigned char *data, NM_CRYPTO_ERROR_INVALID_DATA, _("Error initializing certificate data: %s"), gnutls_strerror (err)); - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + return FALSE; } /* Try DER first */ @@ -284,36 +280,35 @@ crypto_verify_cert (const unsigned char *data, err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_DER); if (err == GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit (der); - return NM_CRYPTO_FILE_FORMAT_X509; + return TRUE; } /* And PEM next */ err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_PEM); gnutls_x509_crt_deinit (der); if (err == GNUTLS_E_SUCCESS) - return NM_CRYPTO_FILE_FORMAT_X509; + return TRUE; g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %s"), gnutls_strerror (err)); - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + return FALSE; } gboolean -crypto_verify_pkcs12 (const guint8 *data, - gsize data_len, - const char *password, - GError **error) +_nm_crypto_verify_pkcs12 (const guint8 *data, + gsize data_len, + const char *password, + GError **error) { gnutls_pkcs12_t p12; gnutls_datum_t dt; - gboolean success = FALSE; int err; g_return_val_if_fail (data != NULL, FALSE); - if (!crypto_init (error)) + if (!_nm_crypto_init (error)) return FALSE; dt.data = (unsigned char *) data; @@ -338,31 +333,32 @@ crypto_verify_pkcs12 (const guint8 *data, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %s"), gnutls_strerror (err)); - goto out; + gnutls_pkcs12_deinit (p12); + return FALSE; } } err = gnutls_pkcs12_verify_mac (p12, password); - if (err == GNUTLS_E_SUCCESS) - success = TRUE; - else { + + gnutls_pkcs12_deinit (p12); + + if (err != GNUTLS_E_SUCCESS) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %s"), gnutls_strerror (err)); + return FALSE; } -out: - gnutls_pkcs12_deinit (p12); - return success; + return TRUE; } gboolean -crypto_verify_pkcs8 (const guint8 *data, - gsize data_len, - gboolean is_encrypted, - const char *password, - GError **error) +_nm_crypto_verify_pkcs8 (const guint8 *data, + gsize data_len, + gboolean is_encrypted, + const char *password, + GError **error) { gnutls_x509_privkey_t p8; gnutls_datum_t dt; @@ -370,12 +366,9 @@ crypto_verify_pkcs8 (const guint8 *data, g_return_val_if_fail (data != NULL, FALSE); - if (!crypto_init (error)) + if (!_nm_crypto_init (error)) return FALSE; - dt.data = (unsigned char *) data; - dt.size = data_len; - err = gnutls_x509_privkey_init (&p8); if (err < 0) { g_set_error (error, NM_CRYPTO_ERROR, @@ -385,11 +378,15 @@ crypto_verify_pkcs8 (const guint8 *data, return FALSE; } + dt.data = (unsigned char *) data; + dt.size = data_len; + err = gnutls_x509_privkey_import_pkcs8 (p8, &dt, GNUTLS_X509_FMT_DER, is_encrypted ? password : NULL, is_encrypted ? 0 : GNUTLS_PKCS_PLAIN); + gnutls_x509_privkey_deinit (p8); if (err < 0) { @@ -413,9 +410,9 @@ crypto_verify_pkcs8 (const guint8 *data, } gboolean -crypto_randomize (void *buffer, gsize buffer_len, GError **error) +_nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error) { - if (!crypto_init (error)) + if (!_nm_crypto_init (error)) return FALSE; gnutls_rnd (GNUTLS_RND_RANDOM, buffer, buffer_len); diff --git a/libnm-core/nm-crypto-impl.h b/libnm-core/nm-crypto-impl.h new file mode 100644 index 00000000..91865152 --- /dev/null +++ b/libnm-core/nm-crypto-impl.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * 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 2007 - 2018 Red Hat, Inc. + */ + +#ifndef __NM_CRYPTO_IMPL_H__ +#define __NM_CRYPTO_IMPL_H__ + +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif + +#include "nm-crypto.h" + +gboolean _nm_crypto_init (GError **error); + +gboolean _nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error); + +gboolean _nm_crypto_verify_x509 (const guint8 *data, + gsize len, + GError **error); + +gboolean _nm_crypto_verify_pkcs12 (const guint8 *data, + gsize data_len, + const char *password, + GError **error); + +gboolean _nm_crypto_verify_pkcs8 (const guint8 *data, + gsize data_len, + gboolean is_encrypted, + const char *password, + GError **error); + +/*****************************************************************************/ + +guint8 *_nmtst_crypto_encrypt (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const guint8 *iv, + gsize iv_len, + const guint8 *key, + gsize key_len, + gsize *out_len, + GError **error); + +guint8 *_nmtst_crypto_decrypt (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const guint8 *iv, + gsize iv_len, + const guint8 *key, + gsize key_len, + gsize *out_len, + GError **error); + +#endif /* __NM_CRYPTO_IMPL_H__ */ diff --git a/libnm-core/crypto_nss.c b/libnm-core/nm-crypto-nss.c index 56e91e26..711dde4b 100644 --- a/libnm-core/crypto_nss.c +++ b/libnm-core/nm-crypto-nss.c @@ -23,6 +23,8 @@ #include "nm-default.h" +#include "nm-crypto-impl.h" + #include <prinit.h> #include <nss.h> #include <pk11pub.h> @@ -33,20 +35,46 @@ #include <ciferfam.h> #include <p12plcy.h> -#include "crypto.h" +#include "nm-utils/nm-secret-utils.h" #include "nm-errors.h" -static gboolean initialized = FALSE; +/*****************************************************************************/ + +static gboolean +_get_cipher_info (NMCryptoCipherType cipher, + CK_MECHANISM_TYPE *out_cipher_mech, + guint8 *out_real_iv_len) +{ + static const CK_MECHANISM_TYPE cipher_mechs[] = { + [NM_CRYPTO_CIPHER_DES_EDE3_CBC] = CKM_DES3_CBC_PAD, + [NM_CRYPTO_CIPHER_DES_CBC] = CKM_DES_CBC_PAD, + [NM_CRYPTO_CIPHER_AES_128_CBC] = CKM_AES_CBC_PAD, + [NM_CRYPTO_CIPHER_AES_192_CBC] = CKM_AES_CBC_PAD, + [NM_CRYPTO_CIPHER_AES_256_CBC] = CKM_AES_CBC_PAD, + }; + + g_return_val_if_fail (_NM_INT_NOT_NEGATIVE (cipher) && (gsize) cipher < G_N_ELEMENTS (cipher_mechs), FALSE); + + if (!cipher_mechs[cipher]) + return FALSE; + + NM_SET_OUT (out_cipher_mech, cipher_mechs[cipher]); + NM_SET_OUT (out_real_iv_len, nm_crypto_cipher_get_info (cipher)->real_iv_len); + return TRUE; +} + +/*****************************************************************************/ gboolean -crypto_init (GError **error) +_nm_crypto_init (GError **error) { + static gboolean initialized = FALSE; SECStatus ret; if (initialized) return TRUE; - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); + PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); ret = NSS_NoDB_Init (NULL); if (ret != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, @@ -57,72 +85,61 @@ crypto_init (GError **error) return FALSE; } - SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); - SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); - SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); - SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); - SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); - SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); - SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); + SEC_PKCS12EnableCipher (PKCS12_RC4_40, 1); + SEC_PKCS12EnableCipher (PKCS12_RC4_128, 1); + SEC_PKCS12EnableCipher (PKCS12_RC2_CBC_40, 1); + SEC_PKCS12EnableCipher (PKCS12_RC2_CBC_128, 1); + SEC_PKCS12EnableCipher (PKCS12_DES_56, 1); + SEC_PKCS12EnableCipher (PKCS12_DES_EDE3_168, 1); + SEC_PKCS12SetPreferredCipher (PKCS12_DES_EDE3_168, 1); initialized = TRUE; return TRUE; } -char * -crypto_decrypt (const char *cipher, - int key_type, - const guint8 *data, - gsize data_len, - const char *iv, - const gsize iv_len, - const char *key, - const gsize key_len, - gsize *out_len, - GError **error) +guint8 * +_nmtst_crypto_decrypt (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const guint8 *iv, + gsize iv_len, + const guint8 *key, + gsize key_len, + gsize *out_len, + GError **error) { - char *output = NULL; - int decrypted_len = 0; CK_MECHANISM_TYPE cipher_mech; PK11SlotInfo *slot = NULL; SECItem key_item; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; + nm_auto_clear_secret_ptr NMSecretPtr output = { 0 }; SECStatus s; gboolean success = FALSE; - unsigned pad_len = 0, extra = 0; - guint32 i, real_iv_len = 0; - - if (!crypto_init (error)) - return NULL; + int decrypted_len = 0; + unsigned extra = 0; + unsigned pad_len = 0; + guint32 i; + guint8 real_iv_len; - if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { - cipher_mech = CKM_DES3_CBC_PAD; - real_iv_len = 8; - } else if (!strcmp (cipher, CIPHER_DES_CBC)) { - cipher_mech = CKM_DES_CBC_PAD; - real_iv_len = 8; - } else if (!strcmp (cipher, CIPHER_AES_CBC)) { - cipher_mech = CKM_AES_CBC_PAD; - real_iv_len = 16; - } else { + if (!_get_cipher_info (cipher, &cipher_mech, &real_iv_len)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Private key cipher '%s' was unknown."), - cipher); + _("Unsupported key cipher for decryption")); return NULL; } if (iv_len < real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, - _("Invalid IV length (must be at least %d)."), - real_iv_len); + _("Invalid IV length (must be at least %u)."), + (guint) real_iv_len); return NULL; } - output = g_malloc0 (data_len); + if (!_nm_crypto_init (error)) + return NULL; slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { @@ -160,10 +177,13 @@ crypto_decrypt (const char *cipher, goto out; } + output.len = data_len; + output.bin = g_malloc (data_len); + s = PK11_CipherOp (ctx, - (unsigned char *) output, + (unsigned char *) output.bin, &decrypted_len, - data_len, + output.len, data, data_len); if (s != SECSuccess) { @@ -182,7 +202,7 @@ crypto_decrypt (const char *cipher, } s = PK11_DigestFinal (ctx, - (unsigned char *) (output + decrypted_len), + (unsigned char *) &output.bin[decrypted_len], &extra, data_len - decrypted_len); if (s != SECSuccess) { @@ -192,6 +212,7 @@ crypto_decrypt (const char *cipher, PORT_GetError ()); goto out; } + decrypted_len += extra; pad_len = data_len - decrypted_len; @@ -207,7 +228,7 @@ crypto_decrypt (const char *cipher, * should contain the padding size. */ for (i = pad_len; i > 0; i--) { - if (output[data_len - i] != pad_len) { + if (output.bin[data_len - i] != pad_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key.")); @@ -215,7 +236,6 @@ crypto_decrypt (const char *cipher, } } - *out_len = decrypted_len; success = TRUE; out: @@ -228,27 +248,25 @@ out: if (slot) PK11_FreeSlot (slot); - if (!success) { - if (output) { - /* Don't expose key material */ - memset (output, 0, data_len); - g_free (output); - output = NULL; - } - } - return output; + if (!success) + return NULL; + + if (decrypted_len < output.len) + nm_explicit_bzero (&output.bin[decrypted_len], output.len - decrypted_len); + *out_len = decrypted_len; + return g_steal_pointer (&output.bin); } -char * -crypto_encrypt (const char *cipher, - const guint8 *data, - gsize data_len, - const char *iv, - gsize iv_len, - const char *key, - gsize key_len, - gsize *out_len, - GError **error) +guint8 * +_nmtst_crypto_encrypt (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const guint8 *iv, + gsize iv_len, + const guint8 *key, + gsize key_len, + gsize *out_len, + GError **error) { SECStatus ret; CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; @@ -258,46 +276,29 @@ crypto_encrypt (const char *cipher, PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; - unsigned char *output, *padded_buf; - gsize output_len; + nm_auto_clear_secret_ptr NMSecretPtr padded_buf = { 0 }; + nm_auto_clear_secret_ptr NMSecretPtr output = { 0 }; int encrypted_len = 0, i; gboolean success = FALSE; - gsize padded_buf_len, pad_len; - - if (!crypto_init (error)) - return NULL; + gsize pad_len; - if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) - cipher_mech = CKM_DES3_CBC_PAD; - else if (!strcmp (cipher, CIPHER_AES_CBC)) - cipher_mech = CKM_AES_CBC_PAD; - else { + if ( cipher == NM_CRYPTO_CIPHER_DES_CBC + || !_get_cipher_info (cipher, &cipher_mech, NULL)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, - _("Private key cipher '%s' was unknown."), - cipher); + _("Unsupported key cipher for encryption")); return NULL; } - /* If data->len % ivlen == 0, then we add another complete block - * onto the end so that the decrypter knows there's padding. - */ - pad_len = iv_len - (data_len % iv_len); - output_len = padded_buf_len = data_len + pad_len; - padded_buf = g_malloc0 (padded_buf_len); - - memcpy (padded_buf, data, data_len); - for (i = 0; i < pad_len; i++) - padded_buf[data_len + i] = (guint8) (pad_len & 0xFF); - - output = g_malloc0 (output_len); + if (!_nm_crypto_init (error)) + return NULL; slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the encryption cipher slot.")); - goto out; + return NULL; } sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); @@ -324,7 +325,22 @@ crypto_encrypt (const char *cipher, goto out; } - ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len); + /* If data->len % ivlen == 0, then we add another complete block + * onto the end so that the decrypter knows there's padding. + */ + pad_len = iv_len - (data_len % iv_len); + + padded_buf.len = data_len + pad_len; + padded_buf.bin = g_malloc (padded_buf.len); + + memcpy (padded_buf.bin, data, data_len); + for (i = 0; i < pad_len; i++) + padded_buf.bin[data_len + i] = (guint8) (pad_len & 0xFF); + + output.len = padded_buf.len; + output.bin = g_malloc (output.len); + + ret = PK11_CipherOp (ctx, output.bin, &encrypted_len, output.len, padded_buf.bin, padded_buf.len); if (ret != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, @@ -333,46 +349,41 @@ crypto_encrypt (const char *cipher, goto out; } - if (encrypted_len != output_len) { + if (encrypted_len != output.len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Unexpected amount of data after encrypting.")); goto out; } - *out_len = encrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); - if (sym_key) - PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); + if (sym_key) + PK11_FreeSymKey (sym_key); if (slot) PK11_FreeSlot (slot); - memset (padded_buf, 0, padded_buf_len); - g_free (padded_buf); + if (!success) + return NULL; - if (!success) { - memset (output, 0, output_len); - g_free (output); - output = NULL; - } - return (char *) output; + *out_len = output.len; + return g_steal_pointer (&output.bin); } -NMCryptoFileFormat -crypto_verify_cert (const unsigned char *data, - gsize len, - GError **error) +gboolean +_nm_crypto_verify_x509 (const guint8 *data, + gsize len, + GError **error) { CERTCertificate *cert; - if (!crypto_init (error)) - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + if (!_nm_crypto_init (error)) + return FALSE; /* Try DER/PEM first */ cert = CERT_DecodeCertFromPackage ((char *) data, len); @@ -380,76 +391,85 @@ crypto_verify_cert (const unsigned char *data, g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %d"), - PORT_GetError()); - return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + PORT_GetError ()); + return FALSE; } CERT_DestroyCertificate (cert); - return NM_CRYPTO_FILE_FORMAT_X509; + return TRUE; } gboolean -crypto_verify_pkcs12 (const guint8 *data, - gsize data_len, - const char *password, - GError **error) +_nm_crypto_verify_pkcs12 (const guint8 *data, + gsize data_len, + const char *password, + GError **error) { SEC_PKCS12DecoderContext *p12ctx = NULL; SECItem pw = { 0 }; PK11SlotInfo *slot = NULL; SECStatus s; - gunichar2 *ucs2_password; - glong ucs2_chars = 0; -#ifndef WORDS_BIGENDIAN - guint16 *p; -#endif /* WORDS_BIGENDIAN */ + gboolean success = FALSE; - if (error) - g_return_val_if_fail (*error == NULL, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); - if (!crypto_init (error)) + if (!_nm_crypto_init (error)) return FALSE; /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do * any conversions for us. */ if (password && *password) { - if (!g_utf8_validate (password, -1, NULL)) { + nm_auto_clear_secret_ptr NMSecretPtr ucs2_password = { 0 }; + + if (g_utf8_validate (password, -1, NULL)) { + long ucs2_chars; + + ucs2_password.bin = (guint8 *) g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); + + /* cannot fail, because password is valid UTF-8*/ + nm_assert (ucs2_password.bin && ucs2_chars > 0); + + ucs2_password.len = ucs2_chars * 2; + } + + if (!ucs2_password.bin || ucs2_password.len == 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_PASSWORD, _("Password must be UTF-8")); return FALSE; } - ucs2_password = g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); - /* Can't fail if g_utf8_validate() succeeded */ - g_return_val_if_fail (ucs2_password != NULL && ucs2_chars != 0, FALSE); - - ucs2_chars *= 2; /* convert # UCS2 characters -> bytes */ - pw.data = PORT_ZAlloc(ucs2_chars + 2); - memcpy (pw.data, ucs2_password, ucs2_chars); - pw.len = ucs2_chars + 2; /* include terminating NULL */ - - memset (ucs2_password, 0, ucs2_chars); - g_free (ucs2_password); - -#ifndef WORDS_BIGENDIAN - for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++) - *p = GUINT16_SWAP_LE_BE (*p); -#endif /* WORDS_BIGENDIAN */ - } else { - /* NULL password */ - pw.data = NULL; - pw.len = 0; + + pw.data = PORT_ZAlloc (ucs2_password.len + 2); + memcpy (pw.data, ucs2_password.bin, ucs2_password.len); + pw.len = ucs2_password.len + 2; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + { + guint16 *p, *p_end; + + p_end = (guint16 *) &(((guint8 *) pw.data)[ucs2_password.len]); + for (p = (guint16 *) pw.data; p < p_end; p++) + *p = GUINT16_SWAP_LE_BE (*p); + } +#endif + } + + slot = PK11_GetInternalKeySlot (); + if (!slot) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_FAILED, + _("Couldn't initialize slot")); + goto out; } - slot = PK11_GetInternalKeySlot(); p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (!p12ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#12 decoder: %d"), - PORT_GetError()); - goto error; + PORT_GetError ()); + goto out; } s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len); @@ -457,8 +477,8 @@ crypto_verify_pkcs12 (const guint8 *data, g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %d"), - PORT_GetError()); - goto error; + PORT_GetError ()); + goto out; } s = SEC_PKCS12DecoderVerify (p12ctx); @@ -466,35 +486,34 @@ crypto_verify_pkcs12 (const guint8 *data, g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %d"), - PORT_GetError()); - goto error; + PORT_GetError ()); + goto out; } - SEC_PKCS12DecoderFinish (p12ctx); - SECITEM_ZfreeItem (&pw, PR_FALSE); - return TRUE; + success = TRUE; -error: +out: if (p12ctx) SEC_PKCS12DecoderFinish (p12ctx); - if (slot) - PK11_FreeSlot(slot); + PK11_FreeSlot (slot); + + if (pw.data) + SECITEM_ZfreeItem (&pw, PR_FALSE); - SECITEM_ZfreeItem (&pw, PR_FALSE); - return FALSE; + return success; } gboolean -crypto_verify_pkcs8 (const guint8 *data, - gsize data_len, - gboolean is_encrypted, - const char *password, - GError **error) +_nm_crypto_verify_pkcs8 (const guint8 *data, + gsize data_len, + gboolean is_encrypted, + const char *password, + GError **error) { g_return_val_if_fail (data != NULL, FALSE); - if (!crypto_init (error)) + if (!_nm_crypto_init (error)) return FALSE; /* NSS apparently doesn't do PKCS#8 natively, but you have to put the @@ -505,11 +524,11 @@ crypto_verify_pkcs8 (const guint8 *data, } gboolean -crypto_randomize (void *buffer, gsize buffer_len, GError **error) +_nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error) { SECStatus s; - if (!crypto_init (error)) + if (!_nm_crypto_init (error)) return FALSE; s = PK11_GenerateRandom (buffer, buffer_len); diff --git a/libnm-core/nm-crypto.c b/libnm-core/nm-crypto.c new file mode 100644 index 00000000..7a6e8d18 --- /dev/null +++ b/libnm-core/nm-crypto.c @@ -0,0 +1,1035 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * 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 2007 - 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-crypto.h" + +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include <stdlib.h> + +#include "nm-utils/nm-secret-utils.h" +#include "nm-utils/nm-io-utils.h" + +#include "nm-crypto-impl.h" +#include "nm-utils.h" +#include "nm-errors.h" + +#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----" +#define PEM_RSA_KEY_END "-----END RSA PRIVATE KEY-----" + +#define PEM_DSA_KEY_BEGIN "-----BEGIN DSA PRIVATE KEY-----" +#define PEM_DSA_KEY_END "-----END DSA PRIVATE KEY-----" + +#define PEM_CERT_BEGIN "-----BEGIN CERTIFICATE-----" +#define PEM_CERT_END "-----END CERTIFICATE-----" + +#define PEM_PKCS8_ENC_KEY_BEGIN "-----BEGIN ENCRYPTED PRIVATE KEY-----" +#define PEM_PKCS8_ENC_KEY_END "-----END ENCRYPTED PRIVATE KEY-----" + +#define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----" +#define PEM_PKCS8_DEC_KEY_END "-----END PRIVATE KEY-----" + +/*****************************************************************************/ + +static const NMCryptoCipherInfo cipher_infos[] = { +#define _CI(_cipher, _name, _digest_len, _real_iv_len) \ + [(_cipher) - 1] = { .cipher = _cipher, .name = ""_name"", .digest_len = _digest_len, .real_iv_len = _real_iv_len } + _CI (NM_CRYPTO_CIPHER_DES_EDE3_CBC, "DES-EDE3-CBC", 24, 8), + _CI (NM_CRYPTO_CIPHER_DES_CBC, "DES-CBC", 8, 8), + _CI (NM_CRYPTO_CIPHER_AES_128_CBC, "AES-128-CBC", 16, 16), + _CI (NM_CRYPTO_CIPHER_AES_192_CBC, "AES-192-CBC", 24, 16), + _CI (NM_CRYPTO_CIPHER_AES_256_CBC, "AES-256-CBC", 32, 16), +}; + +const NMCryptoCipherInfo * +nm_crypto_cipher_get_info (NMCryptoCipherType cipher) +{ + g_return_val_if_fail (cipher > NM_CRYPTO_CIPHER_UNKNOWN && (gsize) cipher < G_N_ELEMENTS (cipher_infos) + 1, NULL); + +#if NM_MORE_ASSERTS > 10 + { + int i, j; + + for (i = 0; i < (int) G_N_ELEMENTS (cipher_infos); i++) { + const NMCryptoCipherInfo *info = &cipher_infos[i]; + + nm_assert (info->cipher == (NMCryptoCipherType) (i + 1)); + nm_assert (info->name && info->name[0]); + for (j = 0; j < i; j++) + nm_assert (g_ascii_strcasecmp (info->name, cipher_infos[j].name) != 0); + } + } +#endif + + return &cipher_infos[cipher - 1]; +} + +const NMCryptoCipherInfo * +nm_crypto_cipher_get_info_by_name (const char *cipher_name, gssize p_len) +{ + int i; + + nm_assert (nm_crypto_cipher_get_info (NM_CRYPTO_CIPHER_DES_CBC)->cipher == NM_CRYPTO_CIPHER_DES_CBC); + + if (p_len < 0) { + if (!cipher_name) + return FALSE; + p_len = strlen (cipher_name); + } + + for (i = 0; i < (int) G_N_ELEMENTS (cipher_infos); i++) { + const NMCryptoCipherInfo *info = &cipher_infos[i]; + + if ( (gsize) p_len == strlen (info->name) + && g_ascii_strncasecmp (info->name, cipher_name, p_len) == 0) + return info; + } + return NULL; +} + +/*****************************************************************************/ + +static gboolean +find_tag (const char *tag, + const guint8 *data, + gsize data_len, + gsize start_at, + gsize *out_pos) +{ + gsize i, taglen; + gsize len = data_len - start_at; + + g_return_val_if_fail (out_pos != NULL, FALSE); + + taglen = strlen (tag); + if (len >= taglen) { + for (i = 0; i < len - taglen + 1; i++) { + if (memcmp (data + start_at + i, tag, taglen) == 0) { + *out_pos = start_at + i; + return TRUE; + } + } + } + return FALSE; +} + +#define DEK_INFO_TAG "DEK-Info: " +#define PROC_TYPE_TAG "Proc-Type: " + +static char * +_extract_line (const guint8 **p, const guint8 *p_end) +{ + const guint8 *x, *x0; + + nm_assert (p); + nm_assert (p_end); + nm_assert (*p); + nm_assert (*p < p_end); + + x = x0 = *p; + while (TRUE) { + if (x == p_end) { + *p = p_end; + break; + } + if (*x == '\0') { + /* the data contains embedded NUL. This is the end. */ + *p = p_end; + break; + } + if (*x == '\n') { + *p = x + 1; + break; + } + x++; + } + + if (x == x0) + return NULL; + return g_strndup ((char *) x0, x - x0); +} + +static gboolean +parse_old_openssl_key_file (const guint8 *data, + gsize data_len, + NMSecretPtr *out_parsed, + NMCryptoKeyType *out_key_type, + NMCryptoCipherType *out_cipher, + char **out_iv, + GError **error) +{ + gsize start = 0, end = 0; + nm_auto_free_secret char *str = NULL; + char *str_p; + gsize str_len; + int enc_tags = 0; + NMCryptoKeyType key_type; + nm_auto_clear_secret_ptr NMSecretPtr parsed = { 0 }; + nm_auto_clear_secret_ptr NMSecretPtr data_content = { 0 }; + nm_auto_free_secret char *iv = NULL; + NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN; + const char *start_tag; + const char *end_tag; + const guint8 *data_start, *data_end; + + nm_assert (!out_parsed || (out_parsed->len == 0 && !out_parsed->bin)); + nm_assert (!out_iv || !*out_iv); + + NM_SET_OUT (out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN); + NM_SET_OUT (out_cipher, NM_CRYPTO_CIPHER_UNKNOWN); + + if (find_tag (PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) { + key_type = NM_CRYPTO_KEY_TYPE_RSA; + start_tag = PEM_RSA_KEY_BEGIN; + end_tag = PEM_RSA_KEY_END; + } else if (find_tag (PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) { + key_type = NM_CRYPTO_KEY_TYPE_DSA; + start_tag = PEM_DSA_KEY_BEGIN; + end_tag = PEM_DSA_KEY_END; + } else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM key file had no start tag")); + return FALSE; + } + + start += strlen (start_tag); + if (!find_tag (end_tag, data, data_len, start, &end)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM key file had no end tag '%s'."), + end_tag); + return FALSE; + } + + str_len = end - start + 1; + str = g_new (char, str_len); + str[0] = '\0'; + str_p = str; + + data_start = &data[start]; + data_end = &data[end]; + + while (data_start < data_end) { + nm_auto_free_secret char *line = NULL; + char *p; + + line = _extract_line (&data_start, data_end); + if (!line) + continue; + + p = nm_secret_strchomp (nm_str_skip_leading_spaces (line)); + + if (!strncmp (p, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG))) { + if (enc_tags++ != 0 || str_p != str) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: Proc-Type was not first tag.")); + return FALSE; + } + + p += strlen (PROC_TYPE_TAG); + if (strcmp (p, "4,ENCRYPTED")) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: unknown Proc-Type tag '%s'."), + p); + return FALSE; + } + } else if (!strncmp (p, DEK_INFO_TAG, strlen (DEK_INFO_TAG))) { + const NMCryptoCipherInfo *cipher_info; + char *comma; + gsize p_len; + + if (enc_tags++ != 1 || str_p != str) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: DEK-Info was not the second tag.")); + return FALSE; + } + + p += strlen (DEK_INFO_TAG); + + /* Grab the IV first */ + comma = strchr (p, ','); + if (!comma || (*(comma + 1) == '\0')) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: no IV found in DEK-Info tag.")); + return FALSE; + } + p_len = comma - p; + comma++; + if (!g_ascii_isxdigit (*comma)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: invalid format of IV in DEK-Info tag.")); + return FALSE; + } + nm_free_secret (iv); + iv = g_strdup (comma); + + /* Get the private key cipher */ + cipher_info = nm_crypto_cipher_get_info_by_name (p, p_len); + if (!cipher_info) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Malformed PEM file: unknown private key cipher '%s'."), + p); + return FALSE; + } + cipher = cipher_info->cipher; + } else { + if (enc_tags == 1) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); + return FALSE; + } + nm_utils_strbuf_append_str (&str_p, &str_len, p); + nm_assert (str_len > 0); + } + } + + parsed.bin = (guint8 *) g_base64_decode (str, &parsed.len); + if (!parsed.bin || parsed.len == 0) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Could not decode private key.")); + nm_secret_ptr_clear (&parsed); + return FALSE; + } + + NM_SET_OUT (out_key_type, key_type); + NM_SET_OUT (out_iv, g_steal_pointer (&iv)); + NM_SET_OUT (out_cipher, cipher); + nm_secret_ptr_move (out_parsed, &parsed); + return TRUE; +} + +static gboolean +parse_pkcs8_key_file (const guint8 *data, + gsize data_len, + NMSecretPtr *parsed, + gboolean *out_encrypted, + GError **error) +{ + gsize start = 0, end = 0; + gs_free guchar *der = NULL; + const char *start_tag = NULL, *end_tag = NULL; + gboolean encrypted = FALSE; + nm_auto_free_secret char *der_base64 = NULL; + + nm_assert (parsed); + nm_assert (!parsed->bin); + nm_assert (parsed->len == 0); + nm_assert (out_encrypted); + + /* Try encrypted first, decrypted next */ + if (find_tag (PEM_PKCS8_ENC_KEY_BEGIN, data, data_len, 0, &start)) { + start_tag = PEM_PKCS8_ENC_KEY_BEGIN; + end_tag = PEM_PKCS8_ENC_KEY_END; + encrypted = TRUE; + } else if (find_tag (PEM_PKCS8_DEC_KEY_BEGIN, data, data_len, 0, &start)) { + start_tag = PEM_PKCS8_DEC_KEY_BEGIN; + end_tag = PEM_PKCS8_DEC_KEY_END; + encrypted = FALSE; + } else { + g_set_error_literal (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to find expected PKCS#8 start tag.")); + return FALSE; + } + + start += strlen (start_tag); + if (!find_tag (end_tag, data, data_len, start, &end)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to find expected PKCS#8 end tag '%s'."), + end_tag); + return FALSE; + } + + /* g_base64_decode() wants a NULL-terminated string */ + der_base64 = g_strndup ((char *) &data[start], end - start); + + parsed->bin = (guint8 *) g_base64_decode (der_base64, &parsed->len); + if (!parsed->bin || parsed->len == 0) { + g_set_error_literal (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to decode PKCS#8 private key.")); + nm_secret_ptr_clear (parsed); + return FALSE; + } + + *out_encrypted = encrypted; + return TRUE; +} + +static gboolean +file_read_contents (const char *filename, + NMSecretPtr *out_contents, + GError **error) +{ + nm_assert (out_contents); + nm_assert (out_contents->len == 0); + nm_assert (!out_contents->str); + + return nm_utils_file_get_contents (-1, + filename, + 100*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, + &out_contents->str, + &out_contents->len, + error) >= 0; +} + +GBytes * +nm_crypto_read_file (const char *filename, + GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 }; + + g_return_val_if_fail (filename, NULL); + + if (!file_read_contents (filename, &contents, error)) + return NULL; + return nm_secret_copy_to_gbytes (contents.bin, contents.len); +} + +/* + * Convert a hex string into bytes. + */ +static guint8 * +_nmtst_convert_iv (const char *src, + gsize *out_len, + GError **error) +{ + gsize i, num; + gs_free guint8 *c = NULL; + int c0, c1; + + nm_assert (src); + + num = strlen (src); + if ( num == 0 + || (num % 2) != 0) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("IV must be an even number of bytes in length.")); + return NULL; + } + + num /= 2; + c = g_malloc (num + 1); + + /* defensively add trailing NUL. This function returns binary data, + * do not assume it's NUL terminated. */ + c[num] = '\0'; + + for (i = 0; i < num; i++) { + if ( ((c0 = nm_utils_hexchar_to_int (*(src++))) < 0) + || ((c1 = nm_utils_hexchar_to_int (*(src++))) < 0)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("IV contains non-hexadecimal digits.")); + nm_explicit_bzero (c, i); + return FALSE; + } + + c[i] = (c0 << 4) + c1; + } + *out_len = num; + return g_steal_pointer (&c); +} + +guint8 * +nmtst_crypto_make_des_aes_key (NMCryptoCipherType cipher, + const guint8 *salt, + gsize salt_len, + const char *password, + gsize *out_len, + GError **error) +{ + guint8 *key; + const NMCryptoCipherInfo *cipher_info; + + g_return_val_if_fail (salt != NULL, NULL); + g_return_val_if_fail (salt_len >= 8, NULL); + g_return_val_if_fail (password != NULL, NULL); + g_return_val_if_fail (out_len != NULL, NULL); + + *out_len = 0; + + cipher_info = nm_crypto_cipher_get_info (cipher); + + g_return_val_if_fail (cipher_info, NULL); + + if (password[0] == '\0') + return NULL; + + key = g_malloc (cipher_info->digest_len); + + nm_crypto_md5_hash (salt, + 8, + (guint8 *) password, + strlen (password), + key, + cipher_info->digest_len); + + *out_len = cipher_info->digest_len; + return key; +} + +static gboolean +_nmtst_decrypt_key (NMCryptoCipherType cipher, + const guint8 *data, + gsize data_len, + const char *iv, + const char *password, + NMSecretPtr *parsed, + GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr bin_iv = { 0 }; + nm_auto_clear_secret_ptr NMSecretPtr key = { 0 }; + gs_free char *output = NULL; + + nm_assert (password); + nm_assert (cipher != NM_CRYPTO_CIPHER_UNKNOWN); + nm_assert (iv); + nm_assert (parsed); + nm_assert (!parsed->bin); + nm_assert (parsed->len == 0); + + bin_iv.bin = _nmtst_convert_iv (iv, &bin_iv.len, error); + if (!bin_iv.bin) + return FALSE; + + if (bin_iv.len < 8) { + g_set_error (error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("IV must contain at least 8 characters")); + return FALSE; + } + + /* Convert the password and IV into a DES or AES key */ + key.bin = nmtst_crypto_make_des_aes_key (cipher, bin_iv.bin, bin_iv.len, password, &key.len, error); + if (!key.bin || !key.len) + return FALSE; + + parsed->bin = _nmtst_crypto_decrypt (cipher, + data, + data_len, + bin_iv.bin, + bin_iv.len, + key.bin, + key.len, + &parsed->len, + error); + if (!parsed->bin || parsed->len == 0) { + nm_secret_ptr_clear (parsed); + return FALSE; + } + + return TRUE; +} + +GBytes * +nmtst_crypto_decrypt_openssl_private_key_data (const guint8 *data, + gsize data_len, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + nm_auto_clear_secret_ptr NMSecretPtr parsed = { 0 }; + nm_auto_free_secret char *iv = NULL; + NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN; + + g_return_val_if_fail (data != NULL, NULL); + + NM_SET_OUT (out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN); + + if (!_nm_crypto_init (error)) + return NULL; + + if (!parse_old_openssl_key_file (data, data_len, &parsed, &key_type, &cipher, &iv, NULL)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Unable to determine private key type.")); + return NULL; + } + + NM_SET_OUT (out_key_type, key_type); + + if (password) { + nm_auto_clear_secret_ptr NMSecretPtr parsed2 = { 0 }; + + if (cipher == NM_CRYPTO_CIPHER_UNKNOWN || !iv) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_PASSWORD, + _("Password provided, but key was not encrypted.")); + return NULL; + } + + if (!_nmtst_decrypt_key (cipher, + parsed.bin, + parsed.len, + iv, + password, + &parsed2, + error)) + return NULL; + + return nm_secret_copy_to_gbytes (parsed2.bin, parsed2.len); + } + + if (cipher != NM_CRYPTO_CIPHER_UNKNOWN || iv) + return NULL; + + return nm_secret_copy_to_gbytes (parsed.bin, parsed.len); +} + +GBytes * +nmtst_crypto_decrypt_openssl_private_key (const char *file, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 }; + + if (!_nm_crypto_init (error)) + return NULL; + + if (!file_read_contents (file, &contents, error)) + return NULL; + + return nmtst_crypto_decrypt_openssl_private_key_data (contents.bin, + contents.len, + password, + out_key_type, + error); +} + +static gboolean +extract_pem_cert_data (const guint8 *contents, + gsize contents_len, + NMSecretPtr *out_cert, + GError **error) +{ + gsize start = 0; + gsize end = 0; + nm_auto_free_secret char *der_base64 = NULL; + + nm_assert (contents); + nm_assert (out_cert); + nm_assert (out_cert->len == 0); + nm_assert (!out_cert->ptr); + + if (!find_tag (PEM_CERT_BEGIN, contents, contents_len, 0, &start)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM certificate had no start tag '%s'."), + PEM_CERT_BEGIN); + return FALSE; + } + + start += strlen (PEM_CERT_BEGIN); + if (!find_tag (PEM_CERT_END, contents, contents_len, start, &end)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("PEM certificate had no end tag '%s'."), + PEM_CERT_END); + return FALSE; + } + + /* g_base64_decode() wants a NULL-terminated string */ + der_base64 = g_strndup ((const char *) &contents[start], end - start); + + out_cert->bin = (guint8 *) g_base64_decode (der_base64, &out_cert->len); + if (!out_cert->bin || !out_cert->len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to decode certificate.")); + nm_secret_ptr_clear (out_cert); + return FALSE; + } + + return TRUE; +} + +gboolean +nm_crypto_load_and_verify_certificate (const char *file, + NMCryptoFileFormat *out_file_format, + GBytes **out_certificate, + GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 }; + + g_return_val_if_fail (file, FALSE); + nm_assert (!error || !*error); + + if (!_nm_crypto_init (error)) + goto out; + + if (!file_read_contents (file, &contents, error)) + goto out; + + if (contents.len == 0) { + g_set_error (error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Certificate file is empty")); + goto out; + } + + /* Check for PKCS#12 */ + if (nm_crypto_is_pkcs12_data (contents.bin, contents.len, NULL)) { + NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_PKCS12); + NM_SET_OUT (out_certificate, nm_secret_copy_to_gbytes (contents.bin, contents.len)); + return TRUE; + } + + /* Check for plain DER format */ + if (contents.len > 2 && contents.bin[0] == 0x30 && contents.bin[1] == 0x82) { + if (_nm_crypto_verify_x509 (contents.bin, contents.len, NULL)) { + NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_X509); + NM_SET_OUT (out_certificate, nm_secret_copy_to_gbytes (contents.bin, contents.len)); + return TRUE; + } + } else { + nm_auto_clear_secret_ptr NMSecretPtr pem_cert = { 0 }; + + if (extract_pem_cert_data (contents.bin, contents.len, &pem_cert, NULL)) { + if (_nm_crypto_verify_x509 (pem_cert.bin, pem_cert.len, NULL)) { + NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_X509); + NM_SET_OUT (out_certificate, nm_secret_copy_to_gbytes (contents.bin, contents.len)); + return TRUE; + } + } + } + + g_set_error (error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Failed to recognize certificate")); + +out: + NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + NM_SET_OUT (out_certificate, NULL); + return FALSE; +} + +gboolean +nm_crypto_is_pkcs12_data (const guint8 *data, + gsize data_len, + GError **error) +{ + GError *local = NULL; + gboolean success; + + if (!data_len) { + g_set_error (error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("Certificate file is empty")); + return FALSE; + } + + g_return_val_if_fail (data != NULL, FALSE); + + if (!_nm_crypto_init (error)) + return FALSE; + + success = _nm_crypto_verify_pkcs12 (data, data_len, NULL, &local); + if (success == FALSE) { + /* If the error was just a decryption error, then it's pkcs#12 */ + if (local) { + if (g_error_matches (local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) { + success = TRUE; + g_error_free (local); + } else + g_propagate_error (error, local); + } + } + return success; +} + +gboolean +nm_crypto_is_pkcs12_file (const char *file, GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 }; + + g_return_val_if_fail (file != NULL, FALSE); + + if (!_nm_crypto_init (error)) + return FALSE; + + if (!file_read_contents (file, &contents, error)) + return FALSE; + + return nm_crypto_is_pkcs12_data (contents.bin, contents.len, error); +} + +/* Verifies that a private key can be read, and if a password is given, that + * the private key can be decrypted with that password. + */ +NMCryptoFileFormat +nm_crypto_verify_private_key_data (const guint8 *data, + gsize data_len, + const char *password, + gboolean *out_is_encrypted, + GError **error) +{ + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gboolean is_encrypted = FALSE; + + g_return_val_if_fail (data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + g_return_val_if_fail (out_is_encrypted == NULL || *out_is_encrypted == FALSE, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + + if (!_nm_crypto_init (error)) + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + /* Check for PKCS#12 first */ + if (nm_crypto_is_pkcs12_data (data, data_len, NULL)) { + is_encrypted = TRUE; + if ( !password + || _nm_crypto_verify_pkcs12 (data, data_len, password, error)) + format = NM_CRYPTO_FILE_FORMAT_PKCS12; + } else { + nm_auto_clear_secret_ptr NMSecretPtr parsed = { 0 }; + + /* Maybe it's PKCS#8 */ + if (parse_pkcs8_key_file (data, data_len, &parsed, &is_encrypted, NULL)) { + if ( !password + || _nm_crypto_verify_pkcs8 (parsed.bin, parsed.len, is_encrypted, password, error)) + format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + } else { + NMCryptoCipherType cipher; + nm_auto_free_secret char *iv = NULL; + + /* Or it's old-style OpenSSL */ + if (parse_old_openssl_key_file (data, data_len, NULL, NULL, &cipher, &iv, NULL)) { + format = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + is_encrypted = (cipher != NM_CRYPTO_CIPHER_UNKNOWN && iv); + } + } + } + + if ( format == NM_CRYPTO_FILE_FORMAT_UNKNOWN + && error + && !*error) { + g_set_error (error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERROR_INVALID_DATA, + _("not a valid private key")); + } + + if (out_is_encrypted) + *out_is_encrypted = is_encrypted; + return format; +} + +NMCryptoFileFormat +nm_crypto_verify_private_key (const char *filename, + const char *password, + gboolean *out_is_encrypted, + GError **error) +{ + nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 }; + + g_return_val_if_fail (filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN); + + if (!_nm_crypto_init (error)) + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + if (!file_read_contents (filename, &contents, error)) + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + return nm_crypto_verify_private_key_data (contents.bin, contents.len, password, out_is_encrypted, error); +} + +void +nm_crypto_md5_hash (const guint8 *salt, + gsize salt_len, + const guint8 *password, + gsize password_len, + guint8 *buffer, + gsize buflen) +{ + nm_auto_free_checksum GChecksum *ctx = NULL; +#define MD5_DIGEST_LEN 16 + nm_auto_clear_static_secret_ptr const NMSecretPtr digest = NM_SECRET_PTR_STATIC (MD5_DIGEST_LEN); + gsize bufidx = 0; + int i; + + nm_assert (g_checksum_type_get_length (G_CHECKSUM_MD5) == MD5_DIGEST_LEN); + + g_return_if_fail (password_len == 0 || password); + g_return_if_fail (buffer); + g_return_if_fail (buflen > 0); + g_return_if_fail (salt_len == 0 || salt); + + ctx = g_checksum_new (G_CHECKSUM_MD5); + + for (;;) { + gsize digest_len; + + if (password_len > 0) + g_checksum_update (ctx, (const guchar *) password, password_len); + if (salt_len > 0) + g_checksum_update (ctx, (const guchar *) salt, salt_len); + + digest_len = MD5_DIGEST_LEN; + g_checksum_get_digest (ctx, digest.bin, &digest_len); + nm_assert (digest_len == MD5_DIGEST_LEN); + + for (i = 0; i < MD5_DIGEST_LEN; i++) { + if (bufidx >= buflen) + return; + buffer[bufidx++] = digest.bin[i]; + } + + g_checksum_reset (ctx); + g_checksum_update (ctx, digest.ptr, MD5_DIGEST_LEN); + } +} + +gboolean +nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error) +{ + return _nm_crypto_randomize (buffer, buffer_len, error); +} + + +/** + * nmtst_crypto_rsa_key_encrypt: + * @data: (array length=len): RSA private key data to be encrypted + * @len: length of @data + * @in_password: (allow-none): existing password to use, if any + * @out_password: (out) (allow-none): if @in_password was %NULL, a random + * password will be generated and returned in this argument + * @error: detailed error information on return, if an error occurred + * + * Encrypts the given RSA private key data with the given password (or generates + * a password if no password was given) and converts the data to PEM format + * suitable for writing to a file. It uses Triple DES cipher for the encryption. + * + * Returns: (transfer full): on success, PEM-formatted data suitable for writing + * to a PEM-formatted certificate/private key file. + **/ +GBytes * +nmtst_crypto_rsa_key_encrypt (const guint8 *data, + gsize len, + const char *in_password, + char **out_password, + GError **error) +{ + guint8 salt[8]; + nm_auto_clear_secret_ptr NMSecretPtr key = { 0 }; + nm_auto_clear_secret_ptr NMSecretPtr enc = { 0 }; + gs_unref_ptrarray GPtrArray *pem = NULL; + nm_auto_free_secret char *tmp_password = NULL; + nm_auto_free_secret char *enc_base64 = NULL; + gsize enc_base64_len; + const char *p; + gsize ret_len, ret_idx; + guint i; + NMSecretBuf *ret; + + g_return_val_if_fail (data, NULL); + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (!out_password || !*out_password, NULL); + + /* Make the password if needed */ + if (!in_password) { + nm_auto_clear_static_secret_ptr NMSecretPtr pw_buf = NM_SECRET_PTR_STATIC (32); + + if (!nm_crypto_randomize (pw_buf.bin, pw_buf.len, error)) + return NULL; + tmp_password = nm_utils_bin2hexstr (pw_buf.bin, pw_buf.len, -1); + in_password = tmp_password; + } + + if (!nm_crypto_randomize (salt, sizeof (salt), error)) + return NULL; + + key.bin = nmtst_crypto_make_des_aes_key (NM_CRYPTO_CIPHER_DES_EDE3_CBC, salt, sizeof (salt), in_password, &key.len, NULL); + if (!key.bin) + g_return_val_if_reached (NULL); + + enc.bin = _nmtst_crypto_encrypt (NM_CRYPTO_CIPHER_DES_EDE3_CBC, data, len, salt, sizeof (salt), key.bin, key.len, &enc.len, error); + if (!enc.bin) + return NULL; + + /* What follows is not the most efficient way to construct the pem + * file line-by-line. At least, it makes sure, that the data will be cleared + * again and not left around in memory. + * + * If this would not be test code, we should improve the implementation + * to avoid some of the copying. */ + pem = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_free_secret); + + g_ptr_array_add (pem, g_strdup ("-----BEGIN RSA PRIVATE KEY-----\n")); + g_ptr_array_add (pem, g_strdup ("Proc-Type: 4,ENCRYPTED\n")); + + /* Convert the salt to a hex string */ + g_ptr_array_add (pem, g_strdup_printf ("DEK-Info: %s,", + nm_crypto_cipher_get_info (NM_CRYPTO_CIPHER_DES_EDE3_CBC)->name)); + g_ptr_array_add (pem, nm_utils_bin2hexstr (salt, sizeof (salt), sizeof (salt) * 2)); + g_ptr_array_add (pem, g_strdup ("\n\n")); + + /* Convert the encrypted key to a base64 string */ + enc_base64 = g_base64_encode ((const guchar *) enc.bin, enc.len); + enc_base64_len = strlen (enc_base64); + for (p = enc_base64; (p - enc_base64) < (ptrdiff_t) enc_base64_len; p += 64) { + g_ptr_array_add (pem, g_strndup (p, 64)); + g_ptr_array_add (pem, g_strdup ("\n")); + } + + g_ptr_array_add (pem, g_strdup ("-----END RSA PRIVATE KEY-----\n")); + + ret_len = 0; + for (i = 0; i < pem->len; i++) + ret_len += strlen (pem->pdata[i]); + + ret = nm_secret_buf_new (ret_len + 1); + ret_idx = 0; + for (i = 0; i < pem->len; i++) { + const char *line = pem->pdata[i]; + gsize line_l = strlen (line); + + memcpy (&ret->bin[ret_idx], line, line_l); + ret_idx += line_l; + nm_assert (ret_idx <= ret_len); + } + nm_assert (ret_idx == ret_len); + ret->bin[ret_len] = '\0'; + + NM_SET_OUT (out_password, g_strdup (tmp_password)); + return nm_secret_buf_to_gbytes_take (ret, ret_len); +} diff --git a/libnm-core/nm-crypto.h b/libnm-core/nm-crypto.h new file mode 100644 index 00000000..54fbbc5f --- /dev/null +++ b/libnm-core/nm-crypto.h @@ -0,0 +1,125 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * 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 2007 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_CRYPTO_H__ +#define __NM_CRYPTO_H__ + +#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE) +#error Cannot use this header. +#endif + +typedef enum { + NM_CRYPTO_CIPHER_UNKNOWN, + NM_CRYPTO_CIPHER_DES_EDE3_CBC, + NM_CRYPTO_CIPHER_DES_CBC, + NM_CRYPTO_CIPHER_AES_128_CBC, + NM_CRYPTO_CIPHER_AES_192_CBC, + NM_CRYPTO_CIPHER_AES_256_CBC, +} NMCryptoCipherType; + +typedef struct { + const char *name; + NMCryptoCipherType cipher; + guint8 digest_len; + guint8 real_iv_len; +} NMCryptoCipherInfo; + +const NMCryptoCipherInfo *nm_crypto_cipher_get_info (NMCryptoCipherType cipher); +const NMCryptoCipherInfo *nm_crypto_cipher_get_info_by_name (const char *cipher_name, gssize p_len); + +typedef enum { + NM_CRYPTO_KEY_TYPE_UNKNOWN = 0, + NM_CRYPTO_KEY_TYPE_RSA, + NM_CRYPTO_KEY_TYPE_DSA +} NMCryptoKeyType; + +typedef enum { + NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0, + NM_CRYPTO_FILE_FORMAT_X509, + NM_CRYPTO_FILE_FORMAT_RAW_KEY, + NM_CRYPTO_FILE_FORMAT_PKCS12 +} NMCryptoFileFormat; + +/*****************************************************************************/ + +GBytes *nm_crypto_read_file (const char *filename, + GError **error); + +gboolean nm_crypto_load_and_verify_certificate (const char *file, + NMCryptoFileFormat *out_file_format, + GBytes **out_certificat, + GError **error); + +gboolean nm_crypto_is_pkcs12_file (const char *file, GError **error); + +gboolean nm_crypto_is_pkcs12_data (const guint8 *data, gsize len, GError **error); + +NMCryptoFileFormat nm_crypto_verify_private_key_data (const guint8 *data, + gsize data_len, + const char *password, + gboolean *out_is_encrypted, + GError **error); + +NMCryptoFileFormat nm_crypto_verify_private_key (const char *file, + const char *password, + gboolean *out_is_encrypted, + GError **error); + +void nm_crypto_md5_hash (const guint8 *salt, + gsize salt_len, + const guint8 *password, + gsize password_len, + guint8 *buffer, + gsize buflen); + +gboolean nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error); + +/*****************************************************************************/ + +GBytes *nmtst_crypto_decrypt_openssl_private_key_data (const guint8 *data, + gsize data_len, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error); + +GBytes *nmtst_crypto_decrypt_openssl_private_key (const char *file, + const char *password, + NMCryptoKeyType *out_key_type, + GError **error); + +GBytes *nmtst_crypto_rsa_key_encrypt (const guint8 *data, + gsize len, + const char *in_password, + char **out_password, + GError **error); + +guint8 *nmtst_crypto_make_des_aes_key (NMCryptoCipherType cipher, + const guint8 *salt, + gsize salt_len, + const char *password, + gsize *out_len, + GError **error); + +/*****************************************************************************/ + +#endif /* __NM_CRYPTO_H__ */ diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index e7c0bc2c..4e12dc63 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2004 - 2017 Red Hat, Inc. + * Copyright 2004 - 2018 Red Hat, Inc. */ /* Definitions related to NetworkManager's D-Bus interfaces. @@ -73,8 +73,11 @@ #define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" #define NM_DBUS_INTERFACE_DEVICE_PPP NM_DBUS_INTERFACE_DEVICE ".Ppp" #define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" +#define NM_DBUS_INTERFACE_DEVICE_WIREGUARD NM_DBUS_INTERFACE_DEVICE ".WireGuard" #define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" #define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" +#define NM_DBUS_INTERFACE_DEVICE_WPAN NM_DBUS_INTERFACE_DEVICE ".Wpan" +#define NM_DBUS_INTERFACE_DEVICE_6LOWPAN NM_DBUS_INTERFACE_DEVICE ".Lowpan" #define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics" #define NM_DBUS_INTERFACE_CHECKPOINT NM_DBUS_INTERFACE ".Checkpoint" @@ -212,6 +215,9 @@ typedef enum { * @NM_DEVICE_TYPE_OVS_INTERFACE: a Open vSwitch interface * @NM_DEVICE_TYPE_OVS_PORT: a Open vSwitch port * @NM_DEVICE_TYPE_OVS_BRIDGE: a Open vSwitch bridge + * @NM_DEVICE_TYPE_WPAN: a IEEE 802.15.4 (WPAN) MAC Layer Device + * @NM_DEVICE_TYPE_6LOWPAN: 6LoWPAN interface + * @NM_DEVICE_TYPE_WIREGUARD: a WireGuard interface * * #NMDeviceType values indicate the type of hardware represented by a * device object. @@ -244,6 +250,9 @@ typedef enum { NM_DEVICE_TYPE_OVS_INTERFACE = 24, NM_DEVICE_TYPE_OVS_PORT = 25, NM_DEVICE_TYPE_OVS_BRIDGE = 26, + NM_DEVICE_TYPE_WPAN = 27, + NM_DEVICE_TYPE_6LOWPAN = 28, + NM_DEVICE_TYPE_WIREGUARD = 29, } NMDeviceType; /** @@ -553,6 +562,7 @@ typedef enum { * @NM_DEVICE_STATE_REASON_OVSDB_FAILED: problem communicating with Open vSwitch database * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported + * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed * * Device state change reason codes */ @@ -623,6 +633,7 @@ typedef enum { NM_DEVICE_STATE_REASON_OVSDB_FAILED = 63, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65, + NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED = 66, } NMDeviceStateReason; /** @@ -645,6 +656,30 @@ typedef enum { } NMMetered; /** + * NMConnectionMultiConnect: + * @NM_CONNECTION_MULTI_CONNECT_DEFAULT: indicates that the per-connection + * setting is unspecified. In this case, it will fallback to the default + * value, which is @NM_CONNECTION_MULTI_CONNECT_SINGLE. + * @NM_CONNECTION_MULTI_CONNECT_SINGLE: the connection profile can only + * be active once at each moment. Activating a profile that is already active, + * will first deactivate it. + * @NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE: the profile can + * be manually activated multiple times on different devices. However, + * regarding autoconnect, the profile will autoconnect only if it is + * currently not connected otherwise. + * @NM_CONNECTION_MULTI_CONNECT_MULTIPLE: the profile can autoactivate + * and be manually activated multiple times together. + * + * Since: 1.14 + */ +typedef enum { + NM_CONNECTION_MULTI_CONNECT_DEFAULT = 0, + NM_CONNECTION_MULTI_CONNECT_SINGLE = 1, + NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE = 2, + NM_CONNECTION_MULTI_CONNECT_MULTIPLE = 3, +} NMConnectionMultiConnect; + +/** * NMActiveConnectionState: * @NM_ACTIVE_CONNECTION_STATE_UNKNOWN: the state of the connection is unknown * @NM_ACTIVE_CONNECTION_STATE_ACTIVATING: a network connection is being prepared @@ -803,16 +838,18 @@ typedef enum /*< flags >*/ { /** * NMIPTunnelMode: - * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode - * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel - * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel - * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel - * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel - * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel - * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel - * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel - * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel - * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel + * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode + * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel + * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel + * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel + * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel + * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel + * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel + * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel + * @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel + * @NM_IP_TUNNEL_MODE_IP6GRETAP: IPv6 GRETAP tunnel * * The tunneling mode. * @@ -829,6 +866,8 @@ typedef enum { NM_IP_TUNNEL_MODE_IPIP6 = 7, NM_IP_TUNNEL_MODE_IP6GRE = 8, NM_IP_TUNNEL_MODE_VTI6 = 9, + NM_IP_TUNNEL_MODE_GRETAP = 10, + NM_IP_TUNNEL_MODE_IP6GRETAP = 11, } NMIPTunnelMode; /** @@ -981,4 +1020,20 @@ typedef enum { /*< flags >*/ NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = (1LL << 5), } NMSettingsUpdate2Flags; +/** + * NMTernary: + * @NM_TERNARY_DEFAULT: use the globally-configured default value. + * @NM_TERNARY_FALSE: the option is disabled. + * @NM_TERNARY_TRUE: the option is enabled. + * + * An boolean value that can be overridden by a default. + * + * Since: 1.14 + **/ +typedef enum { + NM_TERNARY_DEFAULT = -1, + NM_TERNARY_FALSE = 0, + NM_TERNARY_TRUE = 1, +} NMTernary; + #endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-dbus-types.xml b/libnm-core/nm-dbus-types.xml index 117e4243..e3e9fca9 100644 --- a/libnm-core/nm-dbus-types.xml +++ b/libnm-core/nm-dbus-types.xml @@ -292,6 +292,21 @@ <entry role="enum_member_value"><para>= <literal>26</literal></para><para></para></entry> <entry role="enum_member_description"><para>a Open vSwitch bridge</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_WPAN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>27</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a IEEE 802.15.4 (WPAN) MAC Layer Device</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_6LOWPAN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>28</literal></para><para></para></entry> + <entry role="enum_member_description"><para>6LoWPAN interface</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_WIREGUARD</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>29</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a WireGuard interface</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1132,6 +1147,11 @@ <entry role="enum_member_value"><para>= <literal>65</literal></para><para></para></entry> <entry role="enum_member_description"><para>The selected IP method is not supported</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>66</literal></para><para></para></entry> + <entry role="enum_member_description"><para>configuration of SR-IOV parameters failed</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1183,6 +1203,46 @@ </refsect3> </refsect2> + <refsect2 id="NMConnectionMultiConnect" role="enum"> + <title>enum NMConnectionMultiConnect</title> + <indexterm zone="NMConnectionMultiConnect"> + <primary>NMConnectionMultiConnect</primary> + </indexterm> + <para><para>Since: 1.14</para><para></para></para> + <refsect3 role="enum_members"> + <title>Values</title> + <informaltable role="enum_members_table" pgwide="1" frame="none"> + <tgroup cols="4"> + <colspec colname="enum_members_name" colwidth="300px" /> + <colspec colname="enum_members_value" colwidth="100px"/> + <colspec colname="enum_members_description" /> + <tbody> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_DEFAULT</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry> + <entry role="enum_member_description"><para>indicates that the per-connection setting is unspecified. In this case, it will fallback to the default value, which is @NM_CONNECTION_MULTI_CONNECT_SINGLE.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_SINGLE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>1</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the connection profile can only be active once at each moment. Activating a profile that is already active, will first deactivate it.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>2</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the profile can be manually activated multiple times on different devices. However, regarding autoconnect, the profile will autoconnect only if it is currently not connected otherwise.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_MULTIPLE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>3</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the profile can autoactivate and be manually activated multiple times together.</para><para></para></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> + <refsect2 id="NMActiveConnectionState" role="enum"> <title>enum NMActiveConnectionState</title> <indexterm zone="NMActiveConnectionState"> @@ -1472,6 +1532,16 @@ <entry role="enum_member_value"><para>= <literal>9</literal></para><para></para></entry> <entry role="enum_member_description"><para>IPv6 VTI tunnel</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_IP_TUNNEL_MODE_GRETAP</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>10</literal></para><para></para></entry> + <entry role="enum_member_description"><para>GRETAP tunnel</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_IP_TUNNEL_MODE_IP6GRETAP</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>11</literal></para><para></para></entry> + <entry role="enum_member_description"><para>IPv6 GRETAP tunnel</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1713,4 +1783,39 @@ </refsect3> </refsect2> + <refsect2 id="NMTernary" role="enum"> + <title>enum NMTernary</title> + <indexterm zone="NMTernary"> + <primary>NMTernary</primary> + </indexterm> + <para><para>An boolean value that can be overridden by a default.</para><para>Since: 1.14</para><para></para></para> + <refsect3 role="enum_members"> + <title>Values</title> + <informaltable role="enum_members_table" pgwide="1" frame="none"> + <tgroup cols="4"> + <colspec colname="enum_members_name" colwidth="300px" /> + <colspec colname="enum_members_value" colwidth="100px"/> + <colspec colname="enum_members_description" /> + <tbody> + <row role="constant"> + <entry role="enum_member_name"><para>NM_TERNARY_DEFAULT</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>-1</literal></para><para></para></entry> + <entry role="enum_member_description"><para>use the globally-configured default value.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_TERNARY_FALSE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the option is disabled.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_TERNARY_TRUE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>1</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the option is enabled.</para><para></para></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> + </refentry> diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c index 8389bf36..25af7c99 100644 --- a/libnm-core/nm-dbus-utils.c +++ b/libnm-core/nm-dbus-utils.c @@ -117,7 +117,7 @@ dbus_signal_meta_marshal (GClosure *closure, * * The argument types in @c_handler correspond to the types output by * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular: - * - both 16-bit and 32-bit integers are passed as #gint/#guint + * - both 16-bit and 32-bit integers are passed as #int/#guint * - 'as' values are passed as #GStrv (char **) * - all other array, tuple, and dict types are passed as #GVariant * @@ -245,11 +245,11 @@ _nm_dbus_proxy_call_finish (GDBusProxy *proxy, */ GVariant * _nm_dbus_proxy_call_sync (GDBusProxy *proxy, - const gchar *method_name, + const char *method_name, GVariant *parameters, const GVariantType *reply_type, GDBusCallFlags flags, - gint timeout_msec, + int timeout_msec, GCancellable *cancellable, GError **error) { diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c index 5000b583..21f8b07d 100644 --- a/libnm-core/nm-keyfile-utils.c +++ b/libnm-core/nm-keyfile-utils.c @@ -109,8 +109,8 @@ nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ g_key_file_set_##stype##_list (kf, alias ?: group, key, list, length); \ } -DEFINE_KF_LIST_WRAPPER(integer, gint*, gint); -DEFINE_KF_LIST_WRAPPER(string, gchar **, const gchar* const); +DEFINE_KF_LIST_WRAPPER(integer, int*, int); +DEFINE_KF_LIST_WRAPPER(string, char **, const char* const); void nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf, @@ -173,19 +173,19 @@ nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ g_key_file_set_##stype (kf, alias ?: group, key, value); \ } -DEFINE_KF_WRAPPER(string, gchar*, const gchar*); -DEFINE_KF_WRAPPER(integer, gint, gint); +DEFINE_KF_WRAPPER(string, char*, const char*); +DEFINE_KF_WRAPPER(integer, int, int); DEFINE_KF_WRAPPER(uint64, guint64, guint64); DEFINE_KF_WRAPPER(boolean, gboolean, gboolean); -DEFINE_KF_WRAPPER(value, gchar*, const gchar*); +DEFINE_KF_WRAPPER(value, char*, const char*); -gchar ** +char ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, const char *group, gsize *out_length, GError **error) { - gchar **keys; + char **keys; const char *alias; GError *local = NULL; diff --git a/libnm-core/nm-keyfile-utils.h b/libnm-core/nm-keyfile-utils.h index 832ad0b4..46a6d564 100644 --- a/libnm-core/nm-keyfile-utils.h +++ b/libnm-core/nm-keyfile-utils.h @@ -46,8 +46,8 @@ void nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ const char *key, \ set_ctype list[], \ gsize length); -DEFINE_KF_LIST_WRAPPER_PROTO(integer, gint*, gint) -DEFINE_KF_LIST_WRAPPER_PROTO(string, gchar**, const gchar* const) +DEFINE_KF_LIST_WRAPPER_PROTO(integer, int*, int) +DEFINE_KF_LIST_WRAPPER_PROTO(string, char**, const char* const) void nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf, const char *group, @@ -66,14 +66,14 @@ void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ const char *group, \ const char *key, \ set_ctype value); -DEFINE_KF_WRAPPER_PROTO(string, gchar*, const gchar*) -DEFINE_KF_WRAPPER_PROTO(integer, gint, gint) +DEFINE_KF_WRAPPER_PROTO(string, char*, const char*) +DEFINE_KF_WRAPPER_PROTO(integer, int, int) DEFINE_KF_WRAPPER_PROTO(uint64, guint64, guint64) DEFINE_KF_WRAPPER_PROTO(boolean, gboolean, gboolean) -DEFINE_KF_WRAPPER_PROTO(value, gchar*, const gchar*) +DEFINE_KF_WRAPPER_PROTO(value, char*, const char*) /* Misc */ -gchar ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, +char ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, const char *group, gsize *out_length, GError **error); diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c index 5c94c35c..c7d87869 100644 --- a/libnm-core/nm-keyfile.c +++ b/libnm-core/nm-keyfile.c @@ -33,6 +33,7 @@ #include <string.h> #include <linux/pkt_sched.h> +#include "nm-utils/nm-secret-utils.h" #include "nm-common-macros.h" #include "nm-core-internal.h" #include "nm-keyfile-utils.h" @@ -119,6 +120,49 @@ setting_alias_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *k } static void +sriov_vfs_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + const char *setting_name = nm_setting_get_name (setting); + gs_unref_ptrarray GPtrArray *vfs = NULL; + gs_strfreev char **keys = NULL; + gsize n_keys = 0; + int i; + + keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL); + if (!keys || n_keys == 0) + return; + + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + + for (i = 0; i < n_keys; i++) { + gs_free char *value = NULL; + NMSriovVF *vf; + const char *rest; + + if (!g_str_has_prefix (keys[i], "vf.")) + continue; + + rest = &keys[i][3]; + + if (!NM_STRCHAR_ALL (rest, ch, g_ascii_isdigit (ch))) + continue; + + value = nm_keyfile_plugin_kf_get_string (info->keyfile, + setting_name, + keys[i], + NULL); + + vf = _nm_utils_sriov_vf_from_strparts (rest, value, NULL); + if (vf) + g_ptr_array_add (vfs, vf); + } + + g_object_set (G_OBJECT (setting), + key, vfs, + NULL); +} + +static void read_array_of_uint (GKeyFile *file, NMSetting *setting, const char *key) @@ -731,7 +775,7 @@ ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const cha } else addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64; - g_object_set (G_OBJECT (setting), key, (gint) addr_gen_mode, NULL); + g_object_set (G_OBJECT (setting), key, (int) addr_gen_mode, NULL); } static void @@ -896,7 +940,7 @@ unescape_semicolons (char *str) i++; str[j++] = str[i++];; } - str[j] = '\0'; + nm_explicit_bzero (&str[j], i - j); return j; } @@ -907,9 +951,10 @@ get_bytes (KeyfileReaderInfo *info, gboolean zero_terminate, gboolean unescape_semicolon) { - gs_free char *tmp_string = NULL; + nm_auto_free_secret char *tmp_string = NULL; gboolean may_be_int_list = TRUE; gsize length; + GBytes *result; /* New format: just a string * Old format: integer list; e.g. 11;25;38; @@ -926,7 +971,7 @@ get_bytes (KeyfileReaderInfo *info, * byte-array. The reason is that zero_terminate is there to terminate * *valid* strings. It's not there to terminated invalid (empty) strings. */ - return g_bytes_new_take (tmp_string, 0); + return g_bytes_new_static ("", 0); } for (length = 0; tmp_string[length]; length++) { @@ -943,12 +988,11 @@ get_bytes (KeyfileReaderInfo *info, /* Try to parse the string as a integer list. */ if (may_be_int_list && length > 0) { - gs_free guint8 *bin_data = NULL; + nm_auto_free_secret_buf NMSecretBuf *bin = NULL; const char *const s = tmp_string; gsize i, d; - const gsize BIN_DATA_LEN = (length / 2 + 3); - bin_data = g_malloc (BIN_DATA_LEN); + bin = nm_secret_buf_new (length / 2 + 3); #define DIGIT(c) ((c) - '0') i = 0; @@ -981,8 +1025,8 @@ get_bytes (KeyfileReaderInfo *info, break; } - bin_data[d++] = n; - nm_assert (d < BIN_DATA_LEN); + nm_assert (d < bin->len); + bin->bin[d++] = n; /* allow whitespace after the digit. */ while (g_ascii_isspace (s[i])) @@ -1000,16 +1044,23 @@ get_bytes (KeyfileReaderInfo *info, * string format before. We expect that this conversion cannot fail. */ if (d > 0) { /* note that @zero_terminate does not add a terminating '\0' to - * binary data as an integer list. - * - * But we add a '\0' to the bin_data pointer, just to avoid somebody - * (erronously!) reading the binary data as C-string. + * binary data as an integer list. If the bytes are expressed as + * an integer list, all potential NUL characters are supposed to + * be included there explicitly. * - * @d itself does not entail the '\0'. */ - nm_assert (d + 1 <= BIN_DATA_LEN); - bin_data = g_realloc (bin_data, d + 1); - bin_data[d] = '\0'; - return g_bytes_new_take (g_steal_pointer (&bin_data), d); + * However, in the spirit of defensive programming, we do append a + * NUL character to the buffer, although this character is hidden + * and only a mitigation for bugs. */ + + if (d + 10 < bin->len) { + /* hm, too much unused memory. Copy the memory to a suitable + * sized buffer. */ + return nm_secret_copy_to_gbytes (bin->bin, d); + } + + nm_assert (d < bin->len); + bin->bin[d] = '\0'; + return nm_secret_buf_to_gbytes_take (g_steal_pointer (&bin), d); } } @@ -1020,8 +1071,13 @@ get_bytes (KeyfileReaderInfo *info, length++; if (length == 0) return NULL; - tmp_string = g_realloc (tmp_string, length + (zero_terminate ? 0 : 1)); - return g_bytes_new_take (g_steal_pointer (&tmp_string), length); + + result = g_bytes_new_with_free_func (tmp_string, + length, + (GDestroyNotify) nm_free_secret, + tmp_string); + tmp_string = NULL; + return result; } static void @@ -1065,12 +1121,12 @@ get_cert_path (const char *base_dir, const guint8 *cert_path, gsize cert_path_le g_return_val_if_fail (base_dir != NULL, NULL); g_return_val_if_fail (cert_path != NULL, NULL); - base = path = g_malloc0 (cert_path_len + 1); - memcpy (path, cert_path, cert_path_len); + path = g_strndup ((char *) cert_path, cert_path_len); if (path[0] == '/') return path; + base = path; p = strrchr (path, '/'); if (p) base = p + 1; @@ -1104,8 +1160,9 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, const char *data = pdata; gboolean exists = FALSE; gsize validate_len; + gsize path_len, pathuri_len; gs_free char *path = NULL; - GByteArray *tmp; + gs_free char *pathuri = NULL; g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL); @@ -1148,18 +1205,16 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, * When returning TRUE, we must also be sure that @data_len does not look like * the deprecated format of list of integers. With this implementation that is the * case, as long as @consider_exists is FALSE. */ - tmp = g_byte_array_sized_new (strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + strlen (path) + 1); - g_byte_array_append (tmp, (const guint8 *) NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); - g_byte_array_append (tmp, (const guint8 *) path, strlen (path) + 1); - if (nm_setting_802_1x_check_cert_scheme (tmp->data, tmp->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) { - g_byte_array_unref (tmp); + path_len = strlen (path); + pathuri_len = (NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + 1) + path_len; + pathuri = g_new (char, pathuri_len); + memcpy (pathuri, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)); + memcpy (&pathuri[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)], path, path_len + 1); + if (nm_setting_802_1x_check_cert_scheme (pathuri, pathuri_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) return NULL; - } - g_free (path); - path = (char *) g_byte_array_free (tmp, FALSE); NM_SET_OUT (out_exists, exists); - return g_steal_pointer (&path); + return g_steal_pointer (&pathuri); } #define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \ @@ -1393,7 +1448,7 @@ qdisc_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) { const char *setting_name = nm_setting_get_name (setting); GPtrArray *qdiscs; - gs_strfreev gchar **keys = NULL; + gs_strfreev char **keys = NULL; gsize n_keys = 0; int i; @@ -1441,7 +1496,7 @@ tfilter_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) { const char *setting_name = nm_setting_get_name (setting); GPtrArray *tfilters; - gs_strfreev gchar **keys = NULL; + gs_strfreev char **keys = NULL; gsize n_keys = 0; int i; @@ -1510,6 +1565,37 @@ setting_alias_writer (KeyfileWriterInfo *info, } static void +sriov_vfs_writer (KeyfileWriterInfo *info, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GPtrArray *vfs; + guint i; + + vfs = g_value_get_boxed (value); + if (!vfs) + return; + + for (i = 0; i < vfs->len; i++) { + const NMSriovVF *vf = vfs->pdata[i]; + gs_free char *kf_value = NULL; + char kf_key[32]; + + kf_value = nm_utils_sriov_vf_to_str (vf, TRUE, NULL); + if (!kf_value) + continue; + + nm_sprintf_buf (kf_key, "vf.%u", nm_sriov_vf_get_index (vf)); + + nm_keyfile_plugin_kf_set_string (info->keyfile, + nm_setting_get_name (setting), + kf_key, + kf_value); + } +} + +static void write_array_of_uint (GKeyFile *file, NMSetting *setting, const char *key, @@ -1525,7 +1611,7 @@ write_array_of_uint (GKeyFile *file, g_return_if_fail (g_array_get_element_size (array) == sizeof (guint)); - tmp_array = g_new (gint, array->len); + tmp_array = g_new (int, array->len); for (i = 0; i < array->len; i++) { guint v = g_array_index (array, guint, i); @@ -2022,18 +2108,16 @@ typedef struct { }) typedef struct { - const char *setting_name; const ParseInfoProperty*const*properties; } ParseInfoSetting; -#define PARSE_INFO_SETTING(_setting_name, ...) \ - { \ - .setting_name = _setting_name, \ +#define PARSE_INFO_SETTING(setting_type, ...) \ + [setting_type] = (&((const ParseInfoSetting) { \ __VA_ARGS__ \ - } + })) -static const ParseInfoSetting parse_infos[] = { - PARSE_INFO_SETTING (NM_SETTING_WIRELESS_SETTING_NAME, +static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRELESS, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_BSSID, .parser = mac_address_parser_ETHER, @@ -2050,7 +2134,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_802_1X_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_802_1X, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_802_1X_CA_CERT, .parser = cert_parser, @@ -2082,7 +2166,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_WIRED_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRED, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, .parser = mac_address_parser_ETHER_cloned, @@ -2092,28 +2176,28 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_BLUETOOTH_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BLUETOOTH, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_BLUETOOTH_BDADDR, .parser = mac_address_parser_ETHER, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_BOND_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BOND, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_BOND_OPTIONS, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_BRIDGE_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BRIDGE, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_MAC_ADDRESS, .parser = mac_address_parser_ETHER, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_CONNECTION_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_CONNECTION, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_CONNECTION_READ_ONLY, .parser_skip = TRUE, @@ -2125,14 +2209,14 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_INFINIBAND_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_INFINIBAND, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_INFINIBAND_MAC_ADDRESS, .parser = mac_address_parser_INFINIBAND, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_IP4_CONFIG_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP4_CONFIG, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ADDRESSES, .parser_no_check_key = TRUE, @@ -2154,7 +2238,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_IP6_CONFIG_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, .parser_no_check_key = TRUE, @@ -2182,14 +2266,23 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_SERIAL_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_SERIAL_PARITY, .parser = parity_parser, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_TC_CONFIG_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SRIOV, + PARSE_INFO_PROPERTIES ( + PARSE_INFO_PROPERTY (NM_SETTING_SRIOV_VFS, + .parser_no_check_key = TRUE, + .parser = sriov_vfs_parser, + .writer = sriov_vfs_writer, + ), + ), + ), + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TC_CONFIG, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_QDISCS, .parser_no_check_key = TRUE, @@ -2203,7 +2296,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_TEAM_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG, .parser = team_config_parser, @@ -2270,7 +2363,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_TEAM_PORT_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM_PORT, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG, .parser = team_config_parser, @@ -2301,21 +2394,21 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_USER_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_USER, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_USER_DATA, .parser_no_check_key = TRUE, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_VLAN_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VLAN, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_VLAN_FLAGS, .writer_persist_default = TRUE, ), ), ), - PARSE_INFO_SETTING (NM_SETTING_VPN_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VPN, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_VPN_DATA, .parser_no_check_key = TRUE, @@ -2337,7 +2430,7 @@ static const ParseInfoSetting parse_infos[] = { ), ), ), - PARSE_INFO_SETTING (NM_SETTING_WIMAX_SETTING_NAME, + PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIMAX, PARSE_INFO_PROPERTIES ( PARSE_INFO_PROPERTY (NM_SETTING_WIMAX_MAC_ADDRESS, .parser = mac_address_parser_ETHER, @@ -2347,21 +2440,24 @@ static const ParseInfoSetting parse_infos[] = { }; static const ParseInfoProperty * -_parse_info_find (const char *setting_name, const char *property_name) +_parse_info_find (NMSetting *setting, + const char *property_name, + const char **out_setting_name) { + const NMMetaSettingInfo *setting_info; + const ParseInfoSetting *pis; gssize idx; -#if NM_MORE_ASSERTS > 5 +#if NM_MORE_ASSERTS > 10 { guint i, j; for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { - const ParseInfoSetting *pis = &parse_infos[i]; + pis = parse_infos[i]; + + if (!pis) + continue; - g_assert (pis->setting_name); - if ( i > 0 - && strcmp (pis[-1].setting_name, pis->setting_name) >= 0) - g_error ("Wrong order at index #%d: \"%s\" before \"%s\"", i - 1, pis[-1].setting_name, pis->setting_name); g_assert (pis->properties); g_assert (pis->properties[0]); for (j = 0; pis->properties[j]; j++) { @@ -2371,31 +2467,35 @@ _parse_info_find (const char *setting_name, const char *property_name) g_assert (pip->property_name); if ( j > 0 && (pip0 = pis->properties[j - 1]) - && strcmp (pip0->property_name, pip->property_name) >= 0) - g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", i, j - 1, pis->setting_name, pip0->property_name, pis->setting_name, pip->property_name); + && strcmp (pip0->property_name, pip->property_name) >= 0) { + g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", + i, j - 1, + nm_meta_setting_infos[i].setting_name, pip0->property_name, + nm_meta_setting_infos[i].setting_name, pip->property_name); + } } } } #endif - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoSetting, setting_name) == 0); - idx = _nm_utils_array_find_binary_search (parse_infos, - sizeof (ParseInfoSetting), - G_N_ELEMENTS (parse_infos), - &setting_name, - nm_strcmp_p_with_data, - NULL); - if (idx >= 0) { - const ParseInfoSetting *pis = &parse_infos[idx]; - - nm_assert (nm_streq (pis->setting_name, setting_name)); - idx = _nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties, - NM_PTRARRAY_LEN (pis->properties), - &property_name, - nm_strcmp_p_with_data, - NULL, - NULL, - NULL); + if ( !NM_IS_SETTING (setting) + || !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) { + /* handle invalid setting objects gracefully. */ + *out_setting_name = NULL; + return NULL; + } + + *out_setting_name = setting_info->setting_name; + + if ((pis = parse_infos[setting_info->meta_type])) { + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0); + idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties, + NM_PTRARRAY_LEN (pis->properties), + &property_name, + nm_strcmp_p_with_data, + NULL, + NULL, + NULL); if (idx >= 0) return pis->properties[idx]; } @@ -2426,9 +2526,9 @@ read_one_setting_value (NMSetting *setting, if (!(flags & G_PARAM_WRITABLE)) return; - setting_name = nm_setting_get_name (setting); + pip = _parse_info_find (setting, key, &setting_name); - pip = _parse_info_find (setting_name, key); + nm_assert (setting_name); if ( !pip && nm_streq (key, NM_SETTING_NAME)) @@ -2521,7 +2621,7 @@ read_one_setting_value (NMSetting *setting, } else g_object_set (setting, key, int_val, NULL); } else if (type == G_TYPE_BYTES) { - gint *tmp; + int *tmp; GByteArray *array; GBytes *bytes; gsize length; @@ -2554,7 +2654,7 @@ read_one_setting_value (NMSetting *setting, g_bytes_unref (bytes); g_free (tmp); } else if (type == G_TYPE_STRV) { - gchar **sa; + char **sa; gsize length; sa = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_name, key, &length, NULL); @@ -2580,11 +2680,11 @@ read_one_setting_value (NMSetting *setting, } } } else if (G_VALUE_HOLDS_ENUM (value)) { - gint int_val; + int int_val; int_val = nm_keyfile_plugin_kf_get_integer (keyfile, setting_name, key, &err); if (!err) - g_object_set (setting, key, (gint) int_val, NULL); + g_object_set (setting, key, (int) int_val, NULL); } else { if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, _("unhandled setting property type '%s'"), @@ -2596,6 +2696,8 @@ read_one_setting_value (NMSetting *setting, static NMSetting * read_setting (KeyfileReaderInfo *info) { + const NMSettInfoSetting *sett_info; + gs_unref_object NMSetting *setting = NULL; const char *alias; GType type; @@ -2604,22 +2706,92 @@ read_setting (KeyfileReaderInfo *info) alias = info->group; type = nm_setting_lookup_type (alias); - if (type) { - NMSetting *setting = g_object_new (type, NULL); - - info->setting = setting; - nm_setting_enumerate_values (setting, read_one_setting_value, info); - info->setting = NULL; - if (!info->error) - return setting; - - g_object_unref (setting); - } else { + if (!type) { handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN, _("invalid setting name '%s'"), info->group); + return NULL; } - return NULL; + setting = g_object_new (type, NULL); + + info->setting = setting; + + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + gs_free char **keys = NULL; + gsize i, n_keys; + + keys = g_key_file_get_keys (info->keyfile, info->group, &n_keys, NULL); + if (n_keys > 0) { + GHashTable *h = _nm_setting_gendata_hash (setting, TRUE); + + nm_utils_strv_sort (keys, n_keys); + for (i = 0; i < n_keys; i++) { + gs_free char *key = keys[i]; + gs_free_error GError *local = NULL; + const GVariantType *variant_type; + GVariant *variant; + + /* a GKeyfile can return duplicate keys, there is just no API to make sense + * of them. Skip them. */ + if ( i + 1 < n_keys + && nm_streq (key, keys[i + 1])) + continue; + + /* currently, the API is very simple. The setting class just returns + * the desired variant type, and keyfile reader will try to parse + * it accordingly. Note, that this does currently not allow, that + * a particular key can contain different variant types, nor is it + * very flexible in general. + * + * We add flexibility when we need it. Keep it simple for now. */ + variant_type = sett_info->detail.gendata_info->get_variant_type (sett_info, + key, + &local); + if (!variant_type) { + if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("invalid key '%s.%s'"), + info->group, key)) + break; + continue; + } + + if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN)) { + gboolean v; + + v = g_key_file_get_boolean (info->keyfile, + info->group, + key, + &local); + if (local) { + if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, + _("key '%s.%s' is not boolean"), + info->group, key)) + break; + continue; + } + variant = g_variant_new_boolean (v); + } else { + nm_assert_not_reached (); + continue; + } + + g_hash_table_insert (h, + g_steal_pointer (&key), + g_variant_take_ref (variant)); + } + for (; i < n_keys; i++) + g_free (keys[i]); + } + } else + nm_setting_enumerate_values (setting, read_one_setting_value, info); + + info->setting = NULL; + + if (info->error) + return NULL; + return g_steal_pointer (&setting); } static void @@ -2674,7 +2846,7 @@ nm_keyfile_read (GKeyFile *keyfile, gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; NMSetting *setting; - gchar **groups; + char **groups; gsize length; int i; gboolean vpn_secrets = FALSE; @@ -2694,7 +2866,7 @@ nm_keyfile_read (GKeyFile *keyfile, base_dir = base_dir_free = g_get_current_dir (); } } else - g_return_val_if_fail ("/", NULL); + g_return_val_if_fail (base_dir[0] == '/', NULL); connection = nm_simple_connection_new (); @@ -2800,12 +2972,22 @@ write_setting_value (NMSetting *setting, if (info->error) return; - setting_name = nm_setting_get_name (setting); - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); nm_assert (pspec); - pip = _parse_info_find (setting_name, key); + pip = _parse_info_find (setting, key, &setting_name); + + if (!setting_name) { + /* the setting type is unknown. That is highly unexpected + * (and as this is currently only called from NetworkManager + * daemon, not possible). + * + * Still, handle it gracefully, because later keyfile writer will become + * public API of libnm, where @setting is (untrusted) user input. + * + * Gracefully here just means: ignore the setting. */ + return; + } if ( !pip && nm_streq (key, NM_SETTING_NAME)) @@ -2879,7 +3061,7 @@ write_setting_value (NMSetting *setting, char **array; array = (char **) g_value_get_boxed (value); - nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array)); + nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const char **const) array, g_strv_length (array)); } else if (type == G_TYPE_HASH_TABLE) { write_hash_of_string (info->keyfile, setting, key, value); } else if (type == G_TYPE_ARRAY) { @@ -2888,7 +3070,7 @@ write_setting_value (NMSetting *setting, /* Flags are guint but GKeyFile has no uint reader, just uint64 */ nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value)); } else if (G_VALUE_HOLDS_ENUM (value)) - nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value)); + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_enum (value)); else g_warn_if_reached (); } @@ -2900,6 +3082,8 @@ nm_keyfile_write (NMConnection *connection, GError **error) { KeyfileWriterInfo info = { 0 }; + gs_free NMSetting **settings = NULL; + guint i, length = 0; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (!error || !*error, NULL); @@ -2912,12 +3096,59 @@ nm_keyfile_write (NMConnection *connection, info.error = NULL; info.handler = handler; info.user_data = user_data; - nm_connection_for_each_setting_value (connection, write_setting_value, &info); + + settings = nm_connection_get_settings (connection, &length); + for (i = 0; i < length; i++) { + const NMSettInfoSetting *sett_info; + NMSetting *setting = settings[i]; + + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + guint k, n_keys; + const char *const*keys; + + nm_assert (!nm_keyfile_plugin_get_alias_for_setting_name (sett_info->setting_class->setting_info->setting_name)); + + n_keys = _nm_setting_gendata_get_all (setting, &keys, NULL); + + if (n_keys > 0) { + const char *setting_name = sett_info->setting_class->setting_info->setting_name; + GHashTable *h = _nm_setting_gendata_hash (setting, FALSE); + + for (k = 0; k < n_keys; k++) { + const char *key = keys[k]; + GVariant *v; + + v = g_hash_table_lookup (h, key); + + if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + g_key_file_set_boolean (info.keyfile, + setting_name, + key, + g_variant_get_boolean (v)); + } else { + /* BUG: The variant type is not implemented. Since the connection + * verifies, this can only mean we either wrongly didn't reject + * the connection as invalid, or we didn't properly implement the + * variant type. */ + nm_assert_not_reached (); + continue; + } + } + } + } else + nm_setting_enumerate_values (setting, write_setting_value, &info); + + if (info.error) + break; + } if (info.error) { g_propagate_error (error, info.error); g_key_file_unref (info.keyfile); return NULL; } + return info.keyfile; } diff --git a/libnm-core/nm-property-compare.c b/libnm-core/nm-property-compare.c index 64ed663c..2a3ee397 100644 --- a/libnm-core/nm-property-compare.c +++ b/libnm-core/nm-property-compare.c @@ -27,7 +27,7 @@ #include "nm-property-compare.h" -static gint +static int _nm_property_compare_collection (GVariant *value1, GVariant *value2) { GVariant *child1, *child2; @@ -55,7 +55,7 @@ _nm_property_compare_collection (GVariant *value1, GVariant *value2) return 0; } -static gint +static int _nm_property_compare_vardict (GVariant *value1, GVariant *value2) { GVariantIter iter; @@ -87,7 +87,7 @@ _nm_property_compare_vardict (GVariant *value1, GVariant *value2) return 0; } -static gint +static int _nm_property_compare_strdict (GVariant *value1, GVariant *value2) { GVariantIter iter; @@ -119,7 +119,7 @@ nm_property_compare (GVariant *value1, GVariant *value2) { const GVariantType *type1; const GVariantType *type2; - gint ret; + int ret; if (value1 == value2) return 0; diff --git a/libnm-core/nm-setting-6lowpan.c b/libnm-core/nm-setting-6lowpan.c new file mode 100644 index 00000000..c0ce232d --- /dev/null +++ b/libnm-core/nm-setting-6lowpan.c @@ -0,0 +1,230 @@ +/* + * 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. + */ + +#include "nm-default.h" + +#include "nm-setting-private.h" +#include "nm-setting-6lowpan.h" + +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_PARENT, +); + +typedef struct { + char *parent; +} NMSetting6LowpanPrivate; + +/** + * NMSetting6Lowpan: + * + * 6LoWPAN Settings + */ +struct _NMSetting6Lowpan { + NMSetting parent; +}; + +struct _NMSetting6LowpanClass { + NMSettingClass parent; +}; + +/** + * SECTION:nm-setting-6lowpan + * @short_description: Describes connection properties for 6LoWPAN interfaces + * + * The #NMSetting6Lowpan object is a #NMSetting subclass that describes properties + * necessary for connection to 6LoWPAN interfaces. + **/ + +G_DEFINE_TYPE (NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING) + +#define NM_SETTING_6LOWPAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanPrivate)) + + +/** + * nm_setting_6lowpan_new: + * + * Creates a new #NMSetting6Lowpan object with default values. + * + * Returns: (transfer full): the new empty #NMSetting6Lowpan object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_6lowpan_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_6LOWPAN, NULL); +} + +/** + * nm_setting_6lowpan_get_parent: + * @setting: the #NMSetting6Lowpan + * + * Returns: the #NMSetting6Lowpan:parent property of the setting + * + * Since: 1.14 + **/ +const char * +nm_setting_6lowpan_get_parent (NMSetting6Lowpan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_6LOWPAN (setting), NULL); + return NM_SETTING_6LOWPAN_GET_PRIVATE (setting)->parent; +} + +/*********************************************************************/ + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting); + NMSettingConnection *s_con = NULL; + + if (connection) + s_con = nm_connection_get_setting_connection (connection); + + if (!priv->parent) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is not specified")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_6LOWPAN_SETTING_NAME, NM_SETTING_6LOWPAN_PARENT); + return FALSE; + } + + + + if (nm_utils_is_uuid (priv->parent)) { + /* If we have an NMSettingConnection:master with slave-type="6lowpan", + * then it must be the same UUID. + */ + if (s_con) { + const char *master = NULL, *slave_type = NULL; + + slave_type = nm_setting_connection_get_slave_type (s_con); + if (!g_strcmp0 (slave_type, NM_SETTING_6LOWPAN_SETTING_NAME)) + master = nm_setting_connection_get_master (s_con); + + if (master && g_strcmp0 (priv->parent, master) != 0) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' value doesn't match '%s=%s'"), + priv->parent, NM_SETTING_CONNECTION_MASTER, master); + g_prefix_error (error, "%s.%s: ", NM_SETTING_6LOWPAN_SETTING_NAME, NM_SETTING_6LOWPAN_PARENT); + return FALSE; + } + } + } else if (!nm_utils_iface_valid_name (priv->parent)) { + /* parent must be either a UUID or an interface name */ + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error (error, "%s.%s: ", NM_SETTING_6LOWPAN_SETTING_NAME, NM_SETTING_6LOWPAN_PARENT); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_6lowpan_init (NMSetting6Lowpan *setting) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSetting6Lowpan *setting = NM_SETTING_6LOWPAN (object); + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_PARENT: + g_free (priv->parent); + priv->parent = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSetting6Lowpan *setting = NM_SETTING_6LOWPAN (object); + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string (value, priv->parent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMSetting6Lowpan *setting = NM_SETTING_6LOWPAN (object); + NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting); + + g_free (priv->parent); + + G_OBJECT_CLASS (nm_setting_6lowpan_parent_class)->finalize (object); +} + +static void +nm_setting_6lowpan_class_init (NMSetting6LowpanClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMSetting6LowpanPrivate)); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSetting6Lowpan:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * from which this 6LowPAN interface should be created. + * + * Since: 1.14 + **/ + obj_properties[PROP_PARENT] = + g_param_spec_string (NM_SETTING_6LOWPAN_PARENT, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_6LOWPAN); +} diff --git a/libnm-core/nm-setting-6lowpan.h b/libnm-core/nm-setting-6lowpan.h new file mode 100644 index 00000000..73f57b7c --- /dev/null +++ b/libnm-core/nm-setting-6lowpan.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef __NM_SETTING_6LOWPAN_H__ +#define __NM_SETTING_6LOWPAN_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_6LOWPAN (nm_setting_6lowpan_get_type ()) +#define NM_SETTING_6LOWPAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6Lowpan)) +#define NM_SETTING_6LOWPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_6LOWPANCONFIG, NMSetting6LowpanClass)) +#define NM_IS_SETTING_6LOWPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_6LOWPAN)) +#define NM_IS_SETTING_6LOWPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_6LOWPAN)) +#define NM_SETTING_6LOWPAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanClass)) + +#define NM_SETTING_6LOWPAN_SETTING_NAME "6lowpan" + +#define NM_SETTING_6LOWPAN_PARENT "parent" + +typedef struct _NMSetting6LowpanClass NMSetting6LowpanClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_6lowpan_get_type (void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_6lowpan_new (void); + +NM_AVAILABLE_IN_1_14 +const char *nm_setting_6lowpan_get_parent (NMSetting6Lowpan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_6LOWPAN_H__ */ diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index 3b4240e6..7e004c90 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -26,8 +26,9 @@ #include <string.h> +#include "nm-utils/nm-secret-utils.h" #include "nm-utils.h" -#include "crypto.h" +#include "nm-crypto.h" #include "nm-utils-private.h" #include "nm-setting-private.h" #include "nm-core-enum-types.h" @@ -60,66 +61,44 @@ * ISBN: 978-1587051548 **/ -G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING, - _nm_register_setting (802_1X, NM_SETTING_PRIORITY_HW_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_802_1X) +/*****************************************************************************/ -#define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) +static NMSetting8021xCKFormat +_crypto_format_to_ck (NMCryptoFileFormat format) +{ + G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_UNKNOWN == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN) ); + G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_X509 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509) ); + G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_RAW_KEY == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY) ); + G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_PKCS12 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12) ); + + nm_assert (NM_IN_SET (format, NM_CRYPTO_FILE_FORMAT_UNKNOWN, + NM_CRYPTO_FILE_FORMAT_X509, + NM_CRYPTO_FILE_FORMAT_RAW_KEY, + NM_CRYPTO_FILE_FORMAT_PKCS12)); + return (NMSetting8021xCKFormat) format; +} -G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_UNKNOWN == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN) ); -G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_X509 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509) ); -G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_RAW_KEY == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY) ); -G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_PKCS12 == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12) ); +/*****************************************************************************/ + +typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2); + +typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, + gboolean phase2, + GError **error); typedef struct { - GSList *eap; /* GSList of strings */ - char *identity; - char *anonymous_identity; - char *pac_file; - GBytes *ca_cert; - char *ca_cert_password; - NMSettingSecretFlags ca_cert_password_flags; - char *ca_path; - char *subject_match; - GSList *altsubject_matches; - char *domain_suffix_match; - GBytes *client_cert; - char *client_cert_password; - NMSettingSecretFlags client_cert_password_flags; - char *phase1_peapver; - char *phase1_peaplabel; - char *phase1_fast_provisioning; - NMSetting8021xAuthFlags phase1_auth_flags; - char *phase2_auth; - char *phase2_autheap; - GBytes *phase2_ca_cert; - char *phase2_ca_cert_password; - NMSettingSecretFlags phase2_ca_cert_password_flags; - char *phase2_ca_path; - char *phase2_subject_match; - GSList *phase2_altsubject_matches; - char *phase2_domain_suffix_match; - GBytes *phase2_client_cert; - char *phase2_client_cert_password; - NMSettingSecretFlags phase2_client_cert_password_flags; - char *password; - NMSettingSecretFlags password_flags; - GBytes *password_raw; - NMSettingSecretFlags password_raw_flags; - char *pin; - NMSettingSecretFlags pin_flags; - GBytes *private_key; - char *private_key_password; - NMSettingSecretFlags private_key_password_flags; - GBytes *phase2_private_key; - char *phase2_private_key_password; - NMSettingSecretFlags phase2_private_key_password_flags; - gboolean system_ca_certs; - gint auth_timeout; -} NMSetting8021xPrivate; + const char *method; + EAPMethodNeedSecretsFunc ns_func; + EAPMethodValidateFunc v_func; +} EAPMethodsTable; -enum { - PROP_0, +static EAPMethodsTable eap_methods_table[]; + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMSetting8021x, PROP_EAP, PROP_IDENTITY, PROP_ANONYMOUS_IDENTITY, @@ -164,21 +143,558 @@ enum { PROP_PIN_FLAGS, PROP_SYSTEM_CA_CERTS, PROP_AUTH_TIMEOUT, +); - LAST_PROP -}; +typedef struct { + GSList *eap; /* GSList of strings */ + char *identity; + char *anonymous_identity; + char *pac_file; + GBytes *ca_cert; + char *ca_cert_password; + NMSettingSecretFlags ca_cert_password_flags; + char *ca_path; + char *subject_match; + GSList *altsubject_matches; + char *domain_suffix_match; + GBytes *client_cert; + char *client_cert_password; + NMSettingSecretFlags client_cert_password_flags; + char *phase1_peapver; + char *phase1_peaplabel; + char *phase1_fast_provisioning; + NMSetting8021xAuthFlags phase1_auth_flags; + char *phase2_auth; + char *phase2_autheap; + GBytes *phase2_ca_cert; + char *phase2_ca_cert_password; + NMSettingSecretFlags phase2_ca_cert_password_flags; + char *phase2_ca_path; + char *phase2_subject_match; + GSList *phase2_altsubject_matches; + char *phase2_domain_suffix_match; + GBytes *phase2_client_cert; + char *phase2_client_cert_password; + NMSettingSecretFlags phase2_client_cert_password_flags; + char *password; + NMSettingSecretFlags password_flags; + GBytes *password_raw; + NMSettingSecretFlags password_raw_flags; + char *pin; + NMSettingSecretFlags pin_flags; + GBytes *private_key; + char *private_key_password; + NMSettingSecretFlags private_key_password_flags; + GBytes *phase2_private_key; + char *phase2_private_key_password; + NMSettingSecretFlags phase2_private_key_password_flags; + gboolean system_ca_certs; + int auth_timeout; +} NMSetting8021xPrivate; + +G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) + +#define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) + +/*****************************************************************************/ /** - * nm_setting_802_1x_new: + * nm_setting_802_1x_check_cert_scheme: + * @pdata: (allow-none): the data pointer + * @length: the length of the data + * @error: (allow-none): (out): validation reason * - * Creates a new #NMSetting8021x object with default values. + * Determines and verifies the blob type. + * When setting certificate properties of NMSetting8021x + * the blob must be not UNKNOWN (or NULL). * - * Returns: the new empty #NMSetting8021x object + * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. + * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. + * + * Since: 1.2 **/ -NMSetting * -nm_setting_802_1x_new (void) +NMSetting8021xCKScheme +nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error) { - return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL); + const char *data = pdata; + NMSetting8021xCKScheme scheme; + gsize prefix_length; + + g_return_val_if_fail (!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + if (!length || !data) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("binary data missing")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + + if ( length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) { + scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; + prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + } else if ( length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11) + && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) { + scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; + prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11); + } else { + scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; + prefix_length = 0; + } + + if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) { + /* An actual URI must be NUL terminated, contain at least + * one non-NUL character, and contain only one trailing NUL + * chracter. + * And ensure it's UTF-8 valid too so we can pass it through + * D-Bus and stuff like that. */ + + if (data[length - 1] != '\0') { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("URI not NUL terminated")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + length--; + + if (length <= prefix_length) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("URI is empty")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + + if (!g_utf8_validate (data + prefix_length, length - prefix_length, NULL)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("URI is not valid UTF-8")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + } + + return scheme; +} + +NMSetting8021xCKScheme +_nm_setting_802_1x_cert_get_scheme (GBytes *bytes, GError **error) +{ + const char *data; + gsize length; + + if (!bytes) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("data missing")); + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + } + + data = g_bytes_get_data (bytes, &length); + return nm_setting_802_1x_check_cert_scheme (data, length, error); +} + +static gboolean +_cert_verify_scheme (NMSetting8021xCKScheme scheme, + GBytes *bytes, + GError **error) +{ + GError *local = NULL; + NMSetting8021xCKScheme scheme_detected; + + nm_assert (bytes); + + scheme_detected = _nm_setting_802_1x_cert_get_scheme (bytes, &local); + if (scheme_detected == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("certificate is invalid: %s"), local->message); + return FALSE; + } + + if (scheme_detected != scheme) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("certificate detected as invalid scheme")); + return FALSE; + } + + return TRUE; +} + +GBytes * +_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme, + const guint8 *val_bin, + gssize val_len, + GError **error) +{ + gs_unref_bytes GBytes *bytes = NULL; + guint8 *mem; + gsize total_len; + + nm_assert (val_bin); + + switch (scheme) { + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + if (val_len < 0) + val_len = strlen ((char *) val_bin) + 1; + + bytes = g_bytes_new (val_bin, val_len); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + if (val_len < 0) + val_len = strlen ((char *) val_bin) + 1; + + total_len = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + ((gsize) val_len); + + mem = g_new (guint8, total_len); + memcpy (mem, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); + memcpy (&mem[NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)], val_bin, val_len); + bytes = g_bytes_new_take (mem, total_len); + break; + default: + g_return_val_if_reached (NULL); + } + + if (!_cert_verify_scheme (scheme, bytes, error)) + return NULL; + + return g_steal_pointer (&bytes); +} + +static const char * +_cert_get_path (GBytes *bytes) +{ + const guint8 *bin; + + nm_assert (bytes); + nm_assert (g_bytes_get_size (bytes) >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); + + bin = g_bytes_get_data (bytes, NULL); + + nm_assert (bin); + nm_assert (bin[g_bytes_get_size (bytes) - 1] == '\0'); + nm_assert (g_str_has_prefix ((const char *) bin, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); + + return (const char *) &bin[NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)]; +} + +#define _cert_assert_scheme(cert, check_scheme, ret_val) \ + G_STMT_START { \ + NMSetting8021xCKScheme scheme; \ + \ + scheme = _nm_setting_802_1x_cert_get_scheme ((cert), NULL); \ + if (scheme != check_scheme) { \ + g_return_val_if_fail (scheme == check_scheme, ret_val); \ + return ret_val; \ + } \ + } G_STMT_END + +#define _cert_impl_get_scheme(setting, cert_field) \ + G_STMT_START { \ + NMSetting8021x *const _setting = (setting); \ + GBytes *_cert; \ + \ + g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \ + \ + return _nm_setting_802_1x_cert_get_scheme (_cert, NULL); \ + } G_STMT_END + +#define _cert_impl_get_blob(setting, cert_field) \ + G_STMT_START { \ + NMSetting8021x *const _setting = (setting); \ + GBytes *_cert; \ + \ + g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NULL); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \ + \ + _cert_assert_scheme (_cert, NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); \ + \ + return _cert; \ + } G_STMT_END + +#define _cert_impl_get_path(setting, cert_field) \ + G_STMT_START { \ + NMSetting8021x *const _setting = (setting); \ + GBytes *_cert; \ + \ + g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NULL); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \ + \ + _cert_assert_scheme (_cert, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); \ + \ + return _cert_get_path (_cert); \ + } G_STMT_END + +#define _cert_impl_get_uri(setting, cert_field) \ + G_STMT_START { \ + NMSetting8021x *const _setting = (setting); \ + GBytes *_cert; \ + \ + g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NULL); \ + \ + _cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \ + \ + _cert_assert_scheme (_cert, NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); \ + \ + return g_bytes_get_data (_cert, NULL); \ + } G_STMT_END + +static gboolean +_cert_impl_set (NMSetting8021x *setting, + _PropertyEnums property, + const char *value, + const char *password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + gs_unref_bytes GBytes *cert = NULL; + GBytes **p_cert = NULL; + GBytes **p_client_cert = NULL; + char **p_password = NULL; + _PropertyEnums notify_cert = property; + _PropertyEnums notify_password = PROP_0; + _PropertyEnums notify_client_cert = PROP_0; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail (NM_IN_SET (scheme, NM_SETTING_802_1X_CK_SCHEME_BLOB, + NM_SETTING_802_1X_CK_SCHEME_PATH, + NM_SETTING_802_1X_CK_SCHEME_PKCS11), FALSE); + } + + if (!value) { + /* coerce password to %NULL. It should be already. */ + password = NULL; + } + + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + + if (!value) { + /* pass. */ + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + cert = _nm_setting_802_1x_cert_value_to_bytes (scheme, (guint8 *) value, -1, error); + if (!cert) + goto err; + } else { + gs_unref_bytes GBytes *file = NULL; + + if (NM_IN_SET (property, PROP_PRIVATE_KEY, + PROP_PHASE2_PRIVATE_KEY)) { + file = nm_crypto_read_file (value, error); + if (!file) + goto err; + format = nm_crypto_verify_private_key_data (g_bytes_get_data (file, NULL), + g_bytes_get_size (file), + password, + NULL, + error); + if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) + goto err; + } else { + if (!nm_crypto_load_and_verify_certificate (value, &format, &file, error)) + goto err; + } + + nm_assert (format != NM_CRYPTO_FILE_FORMAT_UNKNOWN); + nm_assert (file); + + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + cert = g_steal_pointer (&file); + if (!_cert_verify_scheme (scheme, cert, error)) + goto err; + } else { + cert = _nm_setting_802_1x_cert_value_to_bytes (scheme, (guint8 *) value, -1, error); + if (!cert) + goto err; + } + } + + switch (property) { + case PROP_CA_CERT: + case PROP_PHASE2_CA_CERT: + if ( value + && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && format != NM_CRYPTO_FILE_FORMAT_X509) { + /* wpa_supplicant can only use raw x509 CA certs */ + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("CA certificate must be in X.509 format")); + goto err; + } + p_cert = (property == PROP_CA_CERT) + ? &priv->ca_cert + : &priv->phase2_ca_cert; + break; + case PROP_CLIENT_CERT: + case PROP_PHASE2_CLIENT_CERT: + if ( value + && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && !NM_IN_SET (format, NM_CRYPTO_FILE_FORMAT_X509, + NM_CRYPTO_FILE_FORMAT_PKCS12)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid certificate format")); + goto err; + } + p_cert = (property == PROP_CLIENT_CERT) + ? &priv->client_cert + : &priv->phase2_client_cert; + break; + case PROP_PRIVATE_KEY: + p_cert = &priv->private_key; + p_password = &priv->private_key_password; + p_client_cert = &priv->client_cert; + notify_password = PROP_PRIVATE_KEY_PASSWORD; + notify_client_cert = PROP_CLIENT_CERT; + break; + case PROP_PHASE2_PRIVATE_KEY: + p_cert = &priv->phase2_private_key; + p_password = &priv->phase2_private_key_password; + p_client_cert = &priv->phase2_client_cert; + notify_password = PROP_PHASE2_PRIVATE_KEY_PASSWORD; + notify_client_cert = PROP_PHASE2_CLIENT_CERT; + break; + default: + nm_assert_not_reached (); + break; + } + + /* As required by NM and wpa_supplicant, set the client-cert + * property to the same PKCS#12 data. + */ + if ( cert + && p_client_cert + && format == NM_CRYPTO_FILE_FORMAT_PKCS12 + && !nm_gbytes_equal0 (cert, *p_client_cert)) { + g_bytes_unref (*p_client_cert); + *p_client_cert = g_bytes_ref (cert); + } else + notify_client_cert = PROP_0; + + if ( p_cert + && !nm_gbytes_equal0 (cert, *p_cert)) { + g_bytes_unref (*p_cert); + *p_cert = g_steal_pointer (&cert); + } else + notify_cert = PROP_0; + + if ( p_password + && !nm_streq0 (password, *p_password)) { + nm_free_secret (*p_password); + *p_password = g_strdup (password); + } else + notify_password = PROP_0; + + nm_gobject_notify_together (setting, notify_cert, + notify_password, + notify_client_cert); + + NM_SET_OUT (out_format, _crypto_format_to_ck (format)); + return TRUE; + +err: + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + obj_properties[property]->name); + NM_SET_OUT (out_format, NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + return FALSE; +} + +static NMSetting8021xCKFormat +_cert_impl_get_key_format_from_bytes (GBytes *private_key) +{ + const char *path; + GError *error = NULL; + + if (!private_key) + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + switch (_nm_setting_802_1x_cert_get_scheme (private_key, NULL)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (nm_crypto_is_pkcs12_data (g_bytes_get_data (private_key, NULL), + g_bytes_get_size (private_key), + NULL)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + path = _cert_get_path (private_key); + if (nm_crypto_is_pkcs12_file (path, &error)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + if (error && error->domain == G_FILE_ERROR) { + g_error_free (error); + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + } + g_error_free (error); + return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; + default: + break; + } + + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; +} +#define _cert_impl_get_key_format(setting, private_key_field) \ + ({ \ + NMSetting8021x *_setting = (setting); \ + NMSetting8021xPrivate *_priv; \ + \ + g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); \ + \ + _priv = NM_SETTING_802_1X_GET_PRIVATE (_setting); \ + _cert_impl_get_key_format_from_bytes (_priv->private_key_field); \ + }) + +static gboolean +_cert_verify_property (GBytes *bytes, + const char *prop_name, + const char *password, + const char *password_prop_name, + GError **error) +{ + GError *local = NULL; + NMSetting8021xCKScheme scheme; + + if (!bytes) + return TRUE; + + scheme = _nm_setting_802_1x_cert_get_scheme (bytes, &local); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("certificate is invalid: %s"), local->message); + g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name); + g_error_free (local); + return FALSE; + } + + if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("password is not supported when certificate is not on a PKCS#11 token")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name); + return FALSE; + } + + return TRUE; } /*****************************************************************************/ @@ -253,7 +769,7 @@ nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap) } priv->eap = g_slist_append (priv->eap, g_ascii_strdown (eap, -1)); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP); + _notify (setting, PROP_EAP); return TRUE; } @@ -278,7 +794,7 @@ nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i) g_free (elt->data); priv->eap = g_slist_delete_link (priv->eap, elt); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP); + _notify (setting, PROP_EAP); } /** @@ -304,7 +820,7 @@ nm_setting_802_1x_remove_eap_method_by_value (NMSetting8021x *setting, for (iter = priv->eap; iter; iter = g_slist_next (iter)) { if (!strcmp (eap, (char *) iter->data)) { priv->eap = g_slist_delete_link (priv->eap, iter); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP); + _notify (setting, PROP_EAP); return TRUE; } } @@ -327,7 +843,7 @@ nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting) priv = NM_SETTING_802_1X_GET_PRIVATE (setting); g_slist_free_full (priv->eap, g_free); priv->eap = NULL; - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP); + _notify (setting, PROP_EAP); } /** @@ -423,134 +939,6 @@ nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting) return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs; } -static NMSetting8021xCKScheme -get_cert_scheme (GBytes *bytes, GError **error) -{ - const char *data; - gsize length; - - if (!bytes) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("data missing")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - - data = g_bytes_get_data (bytes, &length); - return nm_setting_802_1x_check_cert_scheme (data, length, error); -} - -/** - * nm_setting_802_1x_check_cert_scheme: - * @pdata: (allow-none): the data pointer - * @length: the length of the data - * @error: (allow-none): (out): validation reason - * - * Determines and verifies the blob type. - * When setting certificate properties of NMSetting8021x - * the blob must be not UNKNOWN (or NULL). - * - * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. - * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN. - * - * Since: 1.2 - **/ -NMSetting8021xCKScheme -nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error) -{ - const char *data = pdata; - NMSetting8021xCKScheme scheme; - gsize prefix_length; - - g_return_val_if_fail (!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - if (!length || !data) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("binary data missing")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - - if ( length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) - && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) { - scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; - prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); - } else if ( length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11) - && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) { - scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; - prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11); - } else { - scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; - prefix_length = 0; - } - - if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* An actual URI must be NUL terminated, contain at least - * one non-NUL character, and contain only one trailing NUL - * chracter. - * And ensure it's UTF-8 valid too so we can pass it through - * D-Bus and stuff like that. */ - - if (data[length - 1] != '\0') { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("URI not NUL terminated")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - length--; - - if (length <= prefix_length) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("URI is empty")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - - if (!g_utf8_validate (data + prefix_length, length - prefix_length, NULL)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("URI is not valid UTF-8")); - return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; - } - } - - return scheme; -} - -static GByteArray * -load_and_verify_certificate (const char *cert_path, - NMSetting8021xCKScheme scheme, - NMCryptoFileFormat *out_file_format, - GError **error) -{ - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *array; - - array = crypto_load_and_verify_certificate (cert_path, &format, error); - - if (!array || !array->len || format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) { - /* the array is empty or the format is already unknown. */ - format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* If we load the file as blob, we must ensure that the binary data does not - * start with file://. NMSetting8021x cannot represent blobs that start with - * file://. - * If that's the case, coerce the format to UNKNOWN. The callers will take care - * of that and not set the blob. */ - if (nm_setting_802_1x_check_cert_scheme (array->data, array->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB) - format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - } - - if (out_file_format) - *out_file_format = format; - return array; -} - /** * nm_setting_802_1x_get_ca_cert_scheme: * @setting: the #NMSetting8021x @@ -565,9 +953,7 @@ load_and_verify_certificate (const char *cert_path, NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting) { - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL); + _cert_impl_get_scheme (setting, ca_cert); } /** @@ -586,14 +972,7 @@ nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting) GBytes * nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_ca_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); - - return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert; + _cert_impl_get_blob (setting, ca_cert); } /** @@ -612,16 +991,7 @@ nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting) const char * nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_ca_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL); - return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + _cert_impl_get_path (setting, ca_cert); } /** @@ -643,35 +1013,7 @@ nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting) const char * nm_setting_802_1x_get_ca_cert_uri (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_ca_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL); - return (const char *)data; -} - -static GBytes * -path_to_scheme_value (const char *path) -{ - GByteArray *array; - gsize len; - - g_return_val_if_fail (path != NULL && path[0], NULL); - - len = strlen (path); - - /* Add the path scheme tag to the front, then the filename */ - array = g_byte_array_sized_new (len + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1); - g_byte_array_append (array, (const guint8 *) NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)); - g_byte_array_append (array, (const guint8 *) path, len); - g_byte_array_append (array, (const guint8 *) "\0", 1); - - return g_byte_array_free_to_bytes (array); + _cert_impl_get_uri (setting, ca_cert); } /** @@ -700,65 +1042,7 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting, NMSetting8021xCKFormat *out_format, GError **error) { - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); - - if (value) { - g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); - g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB - || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH - || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, - FALSE); - } - - if (out_format) - g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - g_clear_pointer (&priv->ca_cert, g_bytes_unref); - - if (!value) { - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT); - return TRUE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - priv->ca_cert = g_bytes_new (value, strlen (value) + 1); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT); - return TRUE; - } - - data = load_and_verify_certificate (value, scheme, &format, error); - if (data) { - /* wpa_supplicant can only use raw x509 CA certs */ - if (format == NM_CRYPTO_FILE_FORMAT_X509) { - if (out_format) - *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - priv->ca_cert = g_byte_array_free_to_bytes (data); - data = NULL; - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - priv->ca_cert = path_to_scheme_value (value); - else - g_assert_not_reached (); - } else { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("CA certificate must be in X.509 format")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CA_CERT); - } - if (data) - g_byte_array_unref (data); - } - - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT); - return priv->ca_cert != NULL; + return _cert_impl_set (setting, PROP_CA_CERT, value, NULL, scheme, out_format, error); } /** @@ -882,7 +1166,7 @@ nm_setting_802_1x_add_altsubject_match (NMSetting8021x *setting, priv->altsubject_matches = g_slist_append (priv->altsubject_matches, g_strdup (altsubject_match)); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES); + _notify (setting, PROP_ALTSUBJECT_MATCHES); return TRUE; } @@ -907,7 +1191,7 @@ nm_setting_802_1x_remove_altsubject_match (NMSetting8021x *setting, guint32 i) g_free (elt->data); priv->altsubject_matches = g_slist_delete_link (priv->altsubject_matches, elt); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES); + _notify (setting, PROP_ALTSUBJECT_MATCHES); } /** @@ -934,7 +1218,7 @@ nm_setting_802_1x_remove_altsubject_match_by_value (NMSetting8021x *setting, for (iter = priv->altsubject_matches; iter; iter = g_slist_next (iter)) { if (!strcmp (altsubject_match, (char *) iter->data)) { priv->altsubject_matches = g_slist_delete_link (priv->altsubject_matches, iter); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES); + _notify (setting, PROP_ALTSUBJECT_MATCHES); return TRUE; } } @@ -957,7 +1241,7 @@ nm_setting_802_1x_clear_altsubject_matches (NMSetting8021x *setting) priv = NM_SETTING_802_1X_GET_PRIVATE (setting); g_slist_free_full (priv->altsubject_matches, g_free); priv->altsubject_matches = NULL; - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES); + _notify (setting, PROP_ALTSUBJECT_MATCHES); } /** @@ -990,9 +1274,7 @@ nm_setting_802_1x_get_domain_suffix_match (NMSetting8021x *setting) NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting) { - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL); + _cert_impl_get_scheme (setting, client_cert); } /** @@ -1008,14 +1290,7 @@ nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting) GBytes * nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_client_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); - - return NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert; + _cert_impl_get_blob (setting, client_cert); } /** @@ -1031,16 +1306,7 @@ nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting) const char * nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_client_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL); - return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + _cert_impl_get_path (setting, client_cert); } /** @@ -1062,16 +1328,7 @@ nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting) const char * nm_setting_802_1x_get_client_cert_uri (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_client_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL); - return (const char *)data; + _cert_impl_get_uri (setting, client_cert); } /** @@ -1104,77 +1361,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting, NMSetting8021xCKFormat *out_format, GError **error) { - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); - - if (value) { - g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); - g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB - || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH - || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, - FALSE); - } - - if (out_format) - g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - g_clear_pointer (&priv->client_cert, g_bytes_unref); - - if (!value) { - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT); - return TRUE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - priv->client_cert = g_bytes_new (value, strlen (value) + 1); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT); - return TRUE; - } - - data = load_and_verify_certificate (value, scheme, &format, error); - if (data) { - gboolean valid = FALSE; - - switch (format) { - case NM_CRYPTO_FILE_FORMAT_X509: - if (out_format) - *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; - valid = TRUE; - break; - case NM_CRYPTO_FILE_FORMAT_PKCS12: - if (out_format) - *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; - valid = TRUE; - break; - default: - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid certificate format")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT); - break; - } - - if (valid) { - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - priv->client_cert = g_byte_array_free_to_bytes (data); - data = NULL; - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - priv->client_cert = path_to_scheme_value (value); - else - g_assert_not_reached (); - } - if (data) - g_byte_array_unref (data); - } - - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT); - return priv->client_cert != NULL; + return _cert_impl_set (setting, PROP_CLIENT_CERT, value, NULL, scheme, out_format, error); } /** @@ -1343,9 +1530,7 @@ nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting) NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting) { - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL); + _cert_impl_get_scheme (setting, phase2_ca_cert); } /** @@ -1364,14 +1549,7 @@ nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting) GBytes * nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); - - return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert; + _cert_impl_get_blob (setting, phase2_ca_cert); } /** @@ -1390,16 +1568,7 @@ nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting) const char * nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL); - return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + _cert_impl_get_path (setting, phase2_ca_cert); } /** @@ -1421,16 +1590,7 @@ nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting) const char * nm_setting_802_1x_get_phase2_ca_cert_uri (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL); - return (const char *)data; + _cert_impl_get_uri (setting, phase2_ca_cert); } /** @@ -1459,65 +1619,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting, NMSetting8021xCKFormat *out_format, GError **error) { - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); - - if (value) { - g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); - g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB - || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH - || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, - FALSE); - } - - if (out_format) - g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - g_clear_pointer (&priv->phase2_ca_cert, g_bytes_unref); - - if (!value) { - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT); - return TRUE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - priv->phase2_ca_cert = g_bytes_new (value, strlen (value) + 1); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT); - return TRUE; - } - - data = load_and_verify_certificate (value, scheme, &format, error); - if (data) { - /* wpa_supplicant can only use raw x509 CA certs */ - if (format == NM_CRYPTO_FILE_FORMAT_X509) { - if (out_format) - *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - priv->phase2_ca_cert = g_byte_array_free_to_bytes (data); - data = NULL; - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - priv->phase2_ca_cert = path_to_scheme_value (value); - else - g_assert_not_reached (); - } else { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid certificate format")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CA_CERT); - } - if (data) - g_byte_array_unref (data); - } - - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT); - return priv->phase2_ca_cert != NULL; + return _cert_impl_set (setting, PROP_PHASE2_CA_CERT, value, NULL, scheme, out_format, error); } /** @@ -1658,7 +1760,7 @@ nm_setting_802_1x_add_phase2_altsubject_match (NMSetting8021x *setting, priv->phase2_altsubject_matches = g_slist_append (priv->phase2_altsubject_matches, g_strdup (phase2_altsubject_match)); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); + _notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES); return TRUE; } @@ -1683,7 +1785,7 @@ nm_setting_802_1x_remove_phase2_altsubject_match (NMSetting8021x *setting, guint g_free (elt->data); priv->phase2_altsubject_matches = g_slist_delete_link (priv->phase2_altsubject_matches, elt); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); + _notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES); } /** @@ -1710,7 +1812,7 @@ nm_setting_802_1x_remove_phase2_altsubject_match_by_value (NMSetting8021x *setti for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next (iter)) { if (!strcmp (phase2_altsubject_match, (char *) iter->data)) { priv->phase2_altsubject_matches = g_slist_delete_link (priv->phase2_altsubject_matches, iter); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); + _notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES); return TRUE; } } @@ -1733,7 +1835,7 @@ nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting) priv = NM_SETTING_802_1X_GET_PRIVATE (setting); g_slist_free_full (priv->phase2_altsubject_matches, g_free); priv->phase2_altsubject_matches = NULL; - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); + _notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES); } /** @@ -1753,9 +1855,7 @@ nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting) NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting) { - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL); + _cert_impl_get_scheme (setting, phase2_client_cert); } /** @@ -1771,14 +1871,7 @@ nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting) GBytes * nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); - - return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert; + _cert_impl_get_blob (setting, phase2_client_cert); } /** @@ -1794,16 +1887,7 @@ nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting) const char * nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL); - return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + _cert_impl_get_path (setting, phase2_client_cert); } /** @@ -1825,16 +1909,7 @@ nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting) const char * nm_setting_802_1x_get_phase2_client_cert_uri (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL); - return (const char *)data; + _cert_impl_get_uri (setting, phase2_client_cert); } /** @@ -1867,78 +1942,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting, NMSetting8021xCKFormat *out_format, GError **error) { - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); - - if (value) { - g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); - g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB - || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH - || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, - FALSE); - } - - if (out_format) - g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); - - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - g_clear_pointer (&priv->phase2_client_cert, g_bytes_unref); - - if (!value) { - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - return TRUE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - priv->phase2_client_cert = g_bytes_new (value, strlen (value) + 1); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - return TRUE; - } - - data = load_and_verify_certificate (value, scheme, &format, error); - if (data) { - gboolean valid = FALSE; - - /* wpa_supplicant can only use raw x509 CA certs */ - switch (format) { - case NM_CRYPTO_FILE_FORMAT_X509: - if (out_format) - *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; - valid = TRUE; - break; - case NM_CRYPTO_FILE_FORMAT_PKCS12: - if (out_format) - *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; - valid = TRUE; - break; - default: - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid certificate format")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - break; - } - - if (valid) { - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - priv->phase2_client_cert = g_byte_array_free_to_bytes (data); - data = NULL; - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - priv->phase2_client_cert = path_to_scheme_value (value); - else - g_assert_not_reached (); - } - if (data) - g_byte_array_unref (data); - } - - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - return priv->phase2_client_cert != NULL; + return _cert_impl_set (setting, PROP_PHASE2_CLIENT_CERT, value, NULL, scheme, out_format, error); } /** @@ -2083,9 +2087,7 @@ nm_setting_802_1x_get_pin_flags (NMSetting8021x *setting) NMSetting8021xCKScheme nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting) { - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL); + _cert_impl_get_scheme (setting, private_key); } /** @@ -2105,14 +2107,7 @@ nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting) GBytes * nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_private_key_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); - - return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key; + _cert_impl_get_blob (setting, private_key); } /** @@ -2128,16 +2123,7 @@ nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting) const char * nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_private_key_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL); - return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + _cert_impl_get_path (setting, private_key); } /** @@ -2159,42 +2145,7 @@ nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting) const char * nm_setting_802_1x_get_private_key_uri (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_private_key_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL); - return (const char *)data; -} - -static void -free_secure_bytes (gpointer data) -{ - GByteArray *array = data; - - memset (array->data, 0, array->len); - g_byte_array_unref (array); -} - -static GBytes * -file_to_secure_bytes (const char *filename) -{ - char *contents; - GByteArray *array = NULL; - gsize length = 0; - - if (g_file_get_contents (filename, &contents, &length, NULL)) { - array = g_byte_array_sized_new (length); - g_byte_array_append (array, (guint8 *) contents, length); - memset (contents, 0, length); - g_free (contents); - return g_bytes_new_with_free_func (array->data, array->len, free_secure_bytes, array); - } - return NULL; + _cert_impl_get_uri (setting, private_key); } /** @@ -2244,88 +2195,7 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting, NMSetting8021xCKFormat *out_format, GError **error) { - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean password_changed = FALSE; - GError *local_err = NULL; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); - - if (value) { - g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); - g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB - || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH - || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, - FALSE); - } - - if (out_format) - g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); - - /* Ensure the private key is a recognized format and if the password was - * given, that it decrypts the private key. - */ - if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - format = crypto_verify_private_key (value, password, NULL, &local_err); - if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - local_err ? local_err->message : _("invalid private key")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY); - g_clear_error (&local_err); - return FALSE; - } - } - - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - if (value == NULL) { - if (priv->private_key) { - g_clear_pointer (&priv->private_key, g_bytes_unref); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY); - } - if (nm_clear_g_free (&priv->private_key_password)) - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); - return TRUE; - } - - /* this makes password self-assignment safe. */ - if (!nm_streq0 (priv->private_key_password, password)) { - g_free (priv->private_key_password); - priv->private_key_password = g_strdup (password); - password_changed = TRUE; - } - - g_bytes_unref (priv->private_key); - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* FIXME: potential race after verifying the private key above */ - /* FIXME: ensure blob doesn't start with file:// */ - priv->private_key = file_to_secure_bytes (value); - nm_assert (priv->private_key); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - priv->private_key = path_to_scheme_value (value); - else { - nm_assert (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11); - priv->private_key = g_bytes_new (value, strlen (value) + 1); - } - - /* As required by NM and wpa_supplicant, set the client-cert - * property to the same PKCS#12 data. - */ - if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) { - if (priv->client_cert) - g_bytes_unref (priv->client_cert); - priv->client_cert = g_bytes_ref (priv->private_key); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT); - } - - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY); - if (password_changed) - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); - - NM_SET_OUT (out_format, (NMSetting8021xCKFormat) format); - return priv->private_key != NULL; + return _cert_impl_set (setting, PROP_PRIVATE_KEY, value, password, scheme, out_format, error); } /** @@ -2369,38 +2239,7 @@ nm_setting_802_1x_get_private_key_password_flags (NMSetting8021x *setting) NMSetting8021xCKFormat nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting) { - NMSetting8021xPrivate *priv; - const char *path; - GError *error = NULL; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - if (!priv->private_key) - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - - switch (nm_setting_802_1x_get_private_key_scheme (setting)) { - case NM_SETTING_802_1X_CK_SCHEME_BLOB: - if (crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL), - g_bytes_get_size (priv->private_key), - NULL)) - return NM_SETTING_802_1X_CK_FORMAT_PKCS12; - return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; - case NM_SETTING_802_1X_CK_SCHEME_PATH: - path = nm_setting_802_1x_get_private_key_path (setting); - if (crypto_is_pkcs12_file (path, &error)) - return NM_SETTING_802_1X_CK_FORMAT_PKCS12; - if (error && error->domain == G_FILE_ERROR) { - g_error_free (error); - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - } - g_error_free (error); - return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; - default: - break; - } - - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + return _cert_impl_get_key_format (setting, private_key); } /** @@ -2451,9 +2290,7 @@ nm_setting_802_1x_get_phase2_private_key_password_flags (NMSetting8021x *setting NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting) { - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); - - return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL); + _cert_impl_get_scheme (setting, phase2_private_key); } /** @@ -2473,14 +2310,7 @@ nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting) GBytes * nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); - - return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key; + _cert_impl_get_blob (setting, phase2_private_key); } /** @@ -2496,16 +2326,7 @@ nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting) const char * nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL); - return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); + _cert_impl_get_path (setting, phase2_private_key); } /** @@ -2527,16 +2348,7 @@ nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting) const char * nm_setting_802_1x_get_phase2_private_key_uri (NMSetting8021x *setting) { - NMSetting8021xCKScheme scheme; - gconstpointer data; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); - - scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting); - g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); - - data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL); - return (const char *)data; + _cert_impl_get_uri (setting, phase2_private_key); } /** @@ -2586,88 +2398,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, NMSetting8021xCKFormat *out_format, GError **error) { - NMSetting8021xPrivate *priv; - NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - gboolean password_changed = FALSE; - GError *local_err = NULL; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); - - if (value) { - g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); - g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB - || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH - || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, - FALSE); - } - - if (out_format) - g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); - - /* Ensure the private key is a recognized format and if the password was - * given, that it decrypts the private key. - */ - if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - format = crypto_verify_private_key (value, password, NULL, &local_err); - if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - local_err ? local_err->message : _("invalid phase2 private key")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - g_clear_error (&local_err); - return FALSE; - } - } - - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - if (value == NULL) { - if (priv->phase2_private_key) { - g_clear_pointer (&priv->phase2_private_key, g_bytes_unref); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - } - if (nm_clear_g_free (&priv->phase2_private_key_password)) - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); - return TRUE; - } - - /* this makes password self-assignment safe. */ - if (!nm_streq0 (priv->phase2_private_key_password, password)) { - g_free (priv->phase2_private_key_password); - priv->phase2_private_key_password = g_strdup (password); - password_changed = TRUE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { - /* FIXME: potential race after verifying the private key above */ - /* FIXME: ensure blob doesn't start with file:// */ - priv->phase2_private_key = file_to_secure_bytes (value); - nm_assert (priv->phase2_private_key); - } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) - priv->phase2_private_key = path_to_scheme_value (value); - else { - nm_assert (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11); - priv->phase2_private_key = g_bytes_new (value, strlen (value) + 1); - } - - /* As required by NM and wpa_supplicant, set the client-cert - * property to the same PKCS#12 data. - */ - if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) { - if (priv->phase2_client_cert) - g_bytes_unref (priv->phase2_client_cert); - - priv->phase2_client_cert = g_bytes_ref (priv->phase2_private_key); - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT); - } - - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); - if (password_changed) - g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); - - NM_SET_OUT (out_format, (NMSetting8021xCKFormat) format); - return priv->phase2_private_key != NULL; + return _cert_impl_set (setting, PROP_PHASE2_PRIVATE_KEY, value, password, scheme, out_format, error); } /** @@ -2680,38 +2411,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting) { - NMSetting8021xPrivate *priv; - const char *path; - GError *error = NULL; - - g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); - priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - - if (!priv->phase2_private_key) - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - - switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) { - case NM_SETTING_802_1X_CK_SCHEME_BLOB: - if (crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL), - g_bytes_get_size (priv->phase2_private_key), - NULL)) - return NM_SETTING_802_1X_CK_FORMAT_PKCS12; - return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; - case NM_SETTING_802_1X_CK_SCHEME_PATH: - path = nm_setting_802_1x_get_phase2_private_key_path (setting); - if (crypto_is_pkcs12_file (path, &error)) - return NM_SETTING_802_1X_CK_FORMAT_PKCS12; - if (error && error->domain == G_FILE_ERROR) { - g_error_free (error); - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - } - g_error_free (error); - return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; - default: - break; - } - - return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + return _cert_impl_get_key_format (setting, phase2_private_key); } /** @@ -2725,7 +2425,7 @@ nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting) * * Since: 1.8 **/ -gint +int nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting) { g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0); @@ -2733,6 +2433,8 @@ nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting) return NM_SETTING_802_1X_GET_PRIVATE (setting)->auth_timeout; } +/*****************************************************************************/ + static void need_secrets_password (NMSetting8021x *self, GPtrArray *secrets, @@ -2777,11 +2479,11 @@ need_private_key_password (GBytes *blob, /* Private key password is required */ if (password) { if (path) - format = crypto_verify_private_key (path, password, NULL, NULL); + format = nm_crypto_verify_private_key (path, password, NULL, NULL); else if (blob) - format = crypto_verify_private_key_data (g_bytes_get_data (blob, NULL), - g_bytes_get_size (blob), - password, NULL, NULL); + format = nm_crypto_verify_private_key_data (g_bytes_get_data (blob, NULL), + g_bytes_get_size (blob), + password, NULL, NULL); else return FALSE; } @@ -2896,9 +2598,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error) } /* If the private key is PKCS#12, check that it matches the client cert */ - if (crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL), - g_bytes_get_size (priv->phase2_private_key), - NULL)) { + if (nm_crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL), + g_bytes_get_size (priv->phase2_private_key), + NULL)) { if (!g_bytes_equal (priv->phase2_private_key, priv->phase2_client_cert)) { g_set_error (error, NM_CONNECTION_ERROR, @@ -2944,9 +2646,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error) } /* If the private key is PKCS#12, check that it matches the client cert */ - if (crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL), - g_bytes_get_size (priv->private_key), - NULL)) { + if (nm_crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL), + g_bytes_get_size (priv->private_key), + NULL)) { if (!g_bytes_equal (priv->private_key, priv->client_cert)) { g_set_error (error, NM_CONNECTION_ERROR, @@ -3054,43 +2756,6 @@ verify_identity (NMSetting8021x *self, gboolean phase2, GError **error) return TRUE; } -/* Implemented below... */ -static void need_secrets_phase2 (NMSetting8021x *self, - GPtrArray *secrets, - gboolean phase2); - -typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self, - GPtrArray *secrets, - gboolean phase2); - -typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, - gboolean phase2, - GError **error); - -typedef struct { - const char *method; - EAPMethodNeedSecretsFunc ns_func; - EAPMethodValidateFunc v_func; -} EAPMethodsTable; - -static EAPMethodsTable eap_methods_table[] = { - { "leap", need_secrets_password, verify_identity }, - { "pwd", need_secrets_password, verify_identity }, - { "md5", need_secrets_password, verify_identity }, - { "pap", need_secrets_password, verify_identity }, - { "chap", need_secrets_password, verify_identity }, - { "mschap", need_secrets_password, verify_identity }, - { "mschapv2", need_secrets_password, verify_identity }, - { "fast", need_secrets_password, verify_identity }, - { "tls", need_secrets_tls, verify_tls }, - { "peap", need_secrets_phase2, verify_ttls }, - { "ttls", need_secrets_phase2, verify_ttls }, - { "sim", need_secrets_sim, NULL }, - { "gtc", need_secrets_password, verify_identity }, - { "otp", NULL, NULL }, // FIXME: implement - { NULL, NULL, NULL } -}; - static void need_secrets_phase2 (NMSetting8021x *self, GPtrArray *secrets, @@ -3124,91 +2789,31 @@ need_secrets_phase2 (NMSetting8021x *self, } } -static GPtrArray * -need_secrets (NMSetting *setting) -{ - NMSetting8021x *self = NM_SETTING_802_1X (setting); - NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); - GSList *iter; - GPtrArray *secrets; - gboolean eap_method_found = FALSE; - - secrets = g_ptr_array_sized_new (4); - - /* Ask each configured EAP method if it needs secrets */ - for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) { - const char *method = (const char *) iter->data; - int i; - - for (i = 0; eap_methods_table[i].method; i++) { - if (eap_methods_table[i].ns_func == NULL) - continue; - if (!strcmp (eap_methods_table[i].method, method)) { - (*eap_methods_table[i].ns_func) (self, secrets, FALSE); - - /* Only break out of the outer loop if this EAP method - * needed secrets. - */ - if (secrets->len > 0) - eap_method_found = TRUE; - break; - } - } - } - - if (secrets->len == 0) { - g_ptr_array_free (secrets, TRUE); - secrets = NULL; - } - - return secrets; -} - -static gboolean -verify_cert (GBytes *bytes, const char *prop_name, - const char *password, const char *password_prop_name, GError **error) -{ - GError *local = NULL; - NMSetting8021xCKScheme scheme; - - if (bytes) - scheme = get_cert_scheme (bytes, &local); - else - return TRUE; - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("certificate is invalid: %s"), local->message); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name); - g_error_free (local); - return FALSE; - } - - if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) { - g_set_error (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("password is not supported when certificate is not on a PKCS#11 token")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name); - return FALSE; - } - - return TRUE; -} +static EAPMethodsTable eap_methods_table[] = { + { "leap", need_secrets_password, verify_identity }, + { "pwd", need_secrets_password, verify_identity }, + { "md5", need_secrets_password, verify_identity }, + { "pap", need_secrets_password, verify_identity }, + { "chap", need_secrets_password, verify_identity }, + { "mschap", need_secrets_password, verify_identity }, + { "mschapv2", need_secrets_password, verify_identity }, + { "fast", need_secrets_password, verify_identity }, + { "tls", need_secrets_tls, verify_tls }, + { "peap", need_secrets_phase2, verify_ttls }, + { "ttls", need_secrets_phase2, verify_ttls }, + { "sim", need_secrets_sim, NULL }, + { "gtc", need_secrets_password, verify_identity }, + { "otp", NULL, NULL }, // FIXME: implement + { "external", NULL, NULL }, + { NULL, NULL, NULL } +}; static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSetting8021x *self = NM_SETTING_802_1X (setting); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); - const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", NULL }; - const char *valid_phase1_peapver[] = { "0", "1", NULL }; - const char *valid_phase1_peaplabel[] = { "0", "1", NULL }; - const char *valid_phase1_fast_pac[] = { "0", "1", "2", "3", NULL }; - const char *valid_phase2_auth[] = { "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls", NULL }; - const char *valid_phase2_autheap[] = { "md5", "mschapv2", "otp", "gtc", "tls", NULL }; + const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", "external", NULL }; GSList *iter; if (error) @@ -3248,7 +2853,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - if (priv->phase1_peapver && !g_strv_contains (valid_phase1_peapver, priv->phase1_peapver)) { + if (!NM_IN_STRSET (priv->phase1_peapver, NULL, + "0", + "1")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -3258,7 +2865,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->phase1_peaplabel && !g_strv_contains (valid_phase1_peaplabel, priv->phase1_peaplabel)) { + if (!NM_IN_STRSET (priv->phase1_peaplabel, NULL, + "0", + "1")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -3268,7 +2877,11 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->phase1_fast_provisioning && !g_strv_contains (valid_phase1_fast_pac, priv->phase1_fast_provisioning)) { + if (!NM_IN_STRSET (priv->phase1_fast_provisioning, NULL, + "0", + "1", + "2", + "3")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -3287,7 +2900,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->phase2_auth && !g_strv_contains (valid_phase2_auth, priv->phase2_auth)) { + if (!NM_IN_STRSET (priv->phase2_auth, NULL, + "pap", + "chap", + "mschap", + "mschapv2", + "gtc", + "otp", + "md5", + "tls")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -3297,7 +2918,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->phase2_autheap && !g_strv_contains (valid_phase2_autheap, priv->phase2_autheap)) { + if (!NM_IN_STRSET (priv->phase2_autheap, NULL, + "md5", + "mschapv2", + "otp", + "gtc", + "tls")) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -3307,307 +2933,231 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (!verify_cert (priv->ca_cert, NM_SETTING_802_1X_CA_CERT, - priv->ca_cert_password, NM_SETTING_802_1X_CA_CERT_PASSWORD, error)) + if (!_cert_verify_property (priv->ca_cert, + NM_SETTING_802_1X_CA_CERT, + priv->ca_cert_password, + NM_SETTING_802_1X_CA_CERT_PASSWORD, + error)) return FALSE; - if (!verify_cert (priv->phase2_ca_cert, NM_SETTING_802_1X_PHASE2_CA_CERT, - priv->phase2_ca_cert_password, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, error)) + if (!_cert_verify_property (priv->phase2_ca_cert, + NM_SETTING_802_1X_PHASE2_CA_CERT, + priv->phase2_ca_cert_password, + NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, + error)) return FALSE; - if (!verify_cert (priv->client_cert, NM_SETTING_802_1X_CLIENT_CERT, - priv->client_cert_password, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, error)) + if (!_cert_verify_property (priv->client_cert, + NM_SETTING_802_1X_CLIENT_CERT, + priv->client_cert_password, + NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, + error)) return FALSE; - if (!verify_cert (priv->phase2_client_cert, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - priv->phase2_client_cert_password, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, error)) + if (!_cert_verify_property (priv->phase2_client_cert, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + priv->phase2_client_cert_password, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, + error)) return FALSE; - if (!verify_cert (priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, NULL, NULL, error)) + if (!_cert_verify_property (priv->private_key, + NM_SETTING_802_1X_PRIVATE_KEY, + NULL, + NULL, + error)) return FALSE; - if (!verify_cert (priv->phase2_private_key, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, NULL, NULL, error)) + if (!_cert_verify_property (priv->phase2_private_key, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + NULL, + NULL, + error)) return FALSE; - /* FIXME: finish */ - return TRUE; } -static void -nm_setting_802_1x_init (NMSetting8021x *setting) -{ -} +/*****************************************************************************/ -static void -finalize (GObject *object) +static GPtrArray * +need_secrets (NMSetting *setting) { - NMSetting8021x *self = NM_SETTING_802_1X (object); + NMSetting8021x *self = NM_SETTING_802_1X (setting); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + GSList *iter; + GPtrArray *secrets; + gboolean eap_method_found = FALSE; - /* Strings first. g_free() already checks for NULLs so we don't have to */ - - g_free (priv->identity); - g_free (priv->anonymous_identity); - g_free (priv->ca_path); - g_free (priv->subject_match); - g_free (priv->domain_suffix_match); - g_free (priv->phase1_peapver); - g_free (priv->phase1_peaplabel); - g_free (priv->phase1_fast_provisioning); - g_free (priv->phase2_auth); - g_free (priv->phase2_autheap); - g_free (priv->phase2_ca_path); - g_free (priv->phase2_subject_match); - g_free (priv->phase2_domain_suffix_match); - g_free (priv->password); - if (priv->password_raw) - g_bytes_unref (priv->password_raw); - g_free (priv->pin); + secrets = g_ptr_array_sized_new (4); - g_slist_free_full (priv->eap, g_free); - g_slist_free_full (priv->altsubject_matches, g_free); - g_slist_free_full (priv->phase2_altsubject_matches, g_free); + /* Ask each configured EAP method if it needs secrets */ + for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) { + const char *method = (const char *) iter->data; + int i; - if (priv->ca_cert) - g_bytes_unref (priv->ca_cert); - g_free (priv->ca_cert_password); - if (priv->client_cert) - g_bytes_unref (priv->client_cert); - g_free (priv->client_cert_password); - if (priv->private_key) - g_bytes_unref (priv->private_key); - g_free (priv->private_key_password); - if (priv->phase2_ca_cert) - g_bytes_unref (priv->phase2_ca_cert); - g_free (priv->phase2_ca_cert_password); - if (priv->phase2_client_cert) - g_bytes_unref (priv->phase2_client_cert); - g_free (priv->phase2_client_cert_password); - if (priv->phase2_private_key) - g_bytes_unref (priv->phase2_private_key); - g_free (priv->phase2_private_key_password); + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].ns_func == NULL) + continue; + if (!strcmp (eap_methods_table[i].method, method)) { + (*eap_methods_table[i].ns_func) (self, secrets, FALSE); - G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object); -} + /* Only break out of the outer loop if this EAP method + * needed secrets. + */ + if (secrets->len > 0) + eap_method_found = TRUE; + break; + } + } + } -static GBytes * -set_cert_prop_helper (const GValue *value, const char *prop_name, GError **error) -{ - gboolean valid; - GBytes *bytes = NULL; - - bytes = g_value_dup_boxed (value); - /* Verify the new data */ - if (bytes) { - valid = verify_cert (bytes, prop_name, NULL, NULL, error); - if (!valid) - g_clear_pointer (&bytes, g_bytes_unref); + if (secrets->len == 0) { + g_ptr_array_free (secrets, TRUE); + return NULL; } - return bytes; + + return secrets; } +/*****************************************************************************/ + static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) { NMSetting8021x *setting = NM_SETTING_802_1X (object); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting); - GError *error = NULL; switch (prop_id) { case PROP_EAP: - g_slist_free_full (priv->eap, g_free); - priv->eap = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); + g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->eap, TRUE)); break; case PROP_IDENTITY: - g_free (priv->identity); - priv->identity = g_value_dup_string (value); + g_value_set_string (value, priv->identity); break; case PROP_ANONYMOUS_IDENTITY: - g_free (priv->anonymous_identity); - priv->anonymous_identity = g_value_dup_string (value); + g_value_set_string (value, priv->anonymous_identity); break; case PROP_PAC_FILE: - g_free (priv->pac_file); - priv->pac_file = g_value_dup_string (value); + g_value_set_string (value, priv->pac_file); break; case PROP_CA_CERT: - if (priv->ca_cert) - g_bytes_unref (priv->ca_cert); - priv->ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CA_CERT, &error); - if (error) { - g_warning ("Error setting certificate (invalid data): %s", error->message); - g_error_free (error); - } + g_value_set_boxed (value, priv->ca_cert); break; case PROP_CA_CERT_PASSWORD: - g_free (priv->ca_cert_password); - priv->ca_cert_password = g_value_dup_string (value); + g_value_set_string (value, priv->ca_cert_password); break; case PROP_CA_CERT_PASSWORD_FLAGS: - priv->ca_cert_password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->ca_cert_password_flags); break; case PROP_CA_PATH: - g_free (priv->ca_path); - priv->ca_path = g_value_dup_string (value); + g_value_set_string (value, priv->ca_path); break; case PROP_SUBJECT_MATCH: - g_free (priv->subject_match); - priv->subject_match = nm_strdup_not_empty (g_value_get_string (value)); + g_value_set_string (value, priv->subject_match); break; case PROP_ALTSUBJECT_MATCHES: - g_slist_free_full (priv->altsubject_matches, g_free); - priv->altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); + g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->altsubject_matches, TRUE)); break; case PROP_DOMAIN_SUFFIX_MATCH: - g_free (priv->domain_suffix_match); - priv->domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value)); + g_value_set_string (value, priv->domain_suffix_match); break; case PROP_CLIENT_CERT: - if (priv->client_cert) - g_bytes_unref (priv->client_cert); - priv->client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CLIENT_CERT, &error); - if (error) { - g_warning ("Error setting certificate (invalid data): %s", error->message); - g_error_free (error); - } + g_value_set_boxed (value, priv->client_cert); break; case PROP_CLIENT_CERT_PASSWORD: - g_free (priv->client_cert_password); - priv->client_cert_password = g_value_dup_string (value); + g_value_set_string (value, priv->client_cert_password); break; case PROP_CLIENT_CERT_PASSWORD_FLAGS: - priv->client_cert_password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->client_cert_password_flags); break; case PROP_PHASE1_PEAPVER: - g_free (priv->phase1_peapver); - priv->phase1_peapver = g_value_dup_string (value); + g_value_set_string (value, priv->phase1_peapver); break; case PROP_PHASE1_PEAPLABEL: - g_free (priv->phase1_peaplabel); - priv->phase1_peaplabel = g_value_dup_string (value); + g_value_set_string (value, priv->phase1_peaplabel); break; case PROP_PHASE1_FAST_PROVISIONING: - g_free (priv->phase1_fast_provisioning); - priv->phase1_fast_provisioning = g_value_dup_string (value); + g_value_set_string (value, priv->phase1_fast_provisioning); break; case PROP_PHASE1_AUTH_FLAGS: - priv->phase1_auth_flags = g_value_get_uint (value); + g_value_set_uint (value, priv->phase1_auth_flags); break; case PROP_PHASE2_AUTH: - g_free (priv->phase2_auth); - priv->phase2_auth = g_value_dup_string (value); + g_value_set_string (value, priv->phase2_auth); break; case PROP_PHASE2_AUTHEAP: - g_free (priv->phase2_autheap); - priv->phase2_autheap = g_value_dup_string (value); + g_value_set_string (value, priv->phase2_autheap); break; case PROP_PHASE2_CA_CERT: - if (priv->phase2_ca_cert) - g_bytes_unref (priv->phase2_ca_cert); - priv->phase2_ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CA_CERT, &error); - if (error) { - g_warning ("Error setting certificate (invalid data): %s", error->message); - g_error_free (error); - } + g_value_set_boxed (value, priv->phase2_ca_cert); break; case PROP_PHASE2_CA_CERT_PASSWORD: - g_free (priv->phase2_ca_cert_password); - priv->phase2_ca_cert_password = g_value_dup_string (value); + g_value_set_string (value, priv->phase2_ca_cert_password); break; case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS: - priv->phase2_ca_cert_password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->phase2_ca_cert_password_flags); break; case PROP_PHASE2_CA_PATH: - g_free (priv->phase2_ca_path); - priv->phase2_ca_path = g_value_dup_string (value); + g_value_set_string (value, priv->phase2_ca_path); break; case PROP_PHASE2_SUBJECT_MATCH: - g_free (priv->phase2_subject_match); - priv->phase2_subject_match = nm_strdup_not_empty (g_value_get_string (value)); + g_value_set_string (value, priv->phase2_subject_match); break; case PROP_PHASE2_ALTSUBJECT_MATCHES: - g_slist_free_full (priv->phase2_altsubject_matches, g_free); - priv->phase2_altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); + g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->phase2_altsubject_matches, TRUE)); break; case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: - g_free (priv->phase2_domain_suffix_match); - priv->phase2_domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value)); + g_value_set_string (value, priv->phase2_domain_suffix_match); break; case PROP_PHASE2_CLIENT_CERT: - - if (priv->phase2_client_cert) - g_bytes_unref (priv->phase2_client_cert); - priv->phase2_client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &error); - if (error) { - g_warning ("Error setting certificate (invalid data): %s", error->message); - g_error_free (error); - } + g_value_set_boxed (value, priv->phase2_client_cert); break; case PROP_PHASE2_CLIENT_CERT_PASSWORD: - g_free (priv->phase2_client_cert_password); - priv->phase2_client_cert_password = g_value_dup_string (value); + g_value_set_string (value, priv->phase2_client_cert_password); break; case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS: - priv->phase2_client_cert_password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->phase2_client_cert_password_flags); break; case PROP_PASSWORD: - g_free (priv->password); - priv->password = g_value_dup_string (value); + g_value_set_string (value, priv->password); break; case PROP_PASSWORD_FLAGS: - priv->password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->password_flags); break; case PROP_PASSWORD_RAW: - if (priv->password_raw) - g_bytes_unref (priv->password_raw); - priv->password_raw = g_value_dup_boxed (value); + g_value_set_boxed (value, priv->password_raw); break; case PROP_PASSWORD_RAW_FLAGS: - priv->password_raw_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->password_raw_flags); break; case PROP_PRIVATE_KEY: - if (priv->private_key) - g_bytes_unref (priv->private_key); - priv->private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PRIVATE_KEY, &error); - if (error) { - g_warning ("Error setting private key (invalid data): %s", error->message); - g_error_free (error); - } + g_value_set_boxed (value, priv->private_key); break; case PROP_PRIVATE_KEY_PASSWORD: - g_free (priv->private_key_password); - priv->private_key_password = g_value_dup_string (value); + g_value_set_string (value, priv->private_key_password); break; case PROP_PRIVATE_KEY_PASSWORD_FLAGS: - priv->private_key_password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->private_key_password_flags); break; case PROP_PHASE2_PRIVATE_KEY: - if (priv->phase2_private_key) - g_bytes_unref (priv->phase2_private_key); - priv->phase2_private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &error); - if (error) { - g_warning ("Error setting private key (invalid data): %s", error->message); - g_error_free (error); - } + g_value_set_boxed (value, priv->phase2_private_key); break; case PROP_PHASE2_PRIVATE_KEY_PASSWORD: - g_free (priv->phase2_private_key_password); - priv->phase2_private_key_password = g_value_dup_string (value); + g_value_set_string (value, priv->phase2_private_key_password); break; case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS: - priv->phase2_private_key_password_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->phase2_private_key_password_flags); break; case PROP_PIN: - g_free (priv->pin); - priv->pin = g_value_dup_string (value); + g_value_set_string (value, priv->pin); break; case PROP_PIN_FLAGS: - priv->pin_flags = g_value_get_flags (value); + g_value_set_flags (value, priv->pin_flags); break; case PROP_SYSTEM_CA_CERTS: - priv->system_ca_certs = g_value_get_boolean (value); + g_value_set_boolean (value, priv->system_ca_certs); break; case PROP_AUTH_TIMEOUT: - priv->auth_timeout = g_value_get_int (value); + g_value_set_int (value, priv->auth_timeout); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -3616,144 +3166,176 @@ set_property (GObject *object, guint prop_id, } static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) { NMSetting8021x *setting = NM_SETTING_802_1X (object); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting); switch (prop_id) { case PROP_EAP: - g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->eap, TRUE)); + g_slist_free_full (priv->eap, g_free); + priv->eap = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); break; case PROP_IDENTITY: - g_value_set_string (value, priv->identity); + g_free (priv->identity); + priv->identity = g_value_dup_string (value); break; case PROP_ANONYMOUS_IDENTITY: - g_value_set_string (value, priv->anonymous_identity); + g_free (priv->anonymous_identity); + priv->anonymous_identity = g_value_dup_string (value); break; case PROP_PAC_FILE: - g_value_set_string (value, priv->pac_file); + g_free (priv->pac_file); + priv->pac_file = g_value_dup_string (value); break; case PROP_CA_CERT: - g_value_set_boxed (value, priv->ca_cert); + g_bytes_unref (priv->ca_cert); + priv->ca_cert = g_value_dup_boxed (value); break; case PROP_CA_CERT_PASSWORD: - g_value_set_string (value, priv->ca_cert_password); + g_free (priv->ca_cert_password); + priv->ca_cert_password = g_value_dup_string (value); break; case PROP_CA_CERT_PASSWORD_FLAGS: - g_value_set_flags (value, priv->ca_cert_password_flags); + priv->ca_cert_password_flags = g_value_get_flags (value); break; case PROP_CA_PATH: - g_value_set_string (value, priv->ca_path); + g_free (priv->ca_path); + priv->ca_path = g_value_dup_string (value); break; case PROP_SUBJECT_MATCH: - g_value_set_string (value, priv->subject_match); + g_free (priv->subject_match); + priv->subject_match = nm_strdup_not_empty (g_value_get_string (value)); break; case PROP_ALTSUBJECT_MATCHES: - g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->altsubject_matches, TRUE)); + g_slist_free_full (priv->altsubject_matches, g_free); + priv->altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); break; case PROP_DOMAIN_SUFFIX_MATCH: - g_value_set_string (value, priv->domain_suffix_match); + g_free (priv->domain_suffix_match); + priv->domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value)); break; case PROP_CLIENT_CERT: - g_value_set_boxed (value, priv->client_cert); + g_bytes_unref (priv->client_cert); + priv->client_cert = g_value_dup_boxed (value); break; case PROP_CLIENT_CERT_PASSWORD: - g_value_set_string (value, priv->client_cert_password); + g_free (priv->client_cert_password); + priv->client_cert_password = g_value_dup_string (value); break; case PROP_CLIENT_CERT_PASSWORD_FLAGS: - g_value_set_flags (value, priv->client_cert_password_flags); + priv->client_cert_password_flags = g_value_get_flags (value); break; case PROP_PHASE1_PEAPVER: - g_value_set_string (value, priv->phase1_peapver); + g_free (priv->phase1_peapver); + priv->phase1_peapver = g_value_dup_string (value); break; case PROP_PHASE1_PEAPLABEL: - g_value_set_string (value, priv->phase1_peaplabel); + g_free (priv->phase1_peaplabel); + priv->phase1_peaplabel = g_value_dup_string (value); break; case PROP_PHASE1_FAST_PROVISIONING: - g_value_set_string (value, priv->phase1_fast_provisioning); + g_free (priv->phase1_fast_provisioning); + priv->phase1_fast_provisioning = g_value_dup_string (value); break; case PROP_PHASE1_AUTH_FLAGS: - g_value_set_uint (value, priv->phase1_auth_flags); + priv->phase1_auth_flags = g_value_get_uint (value); break; case PROP_PHASE2_AUTH: - g_value_set_string (value, priv->phase2_auth); + g_free (priv->phase2_auth); + priv->phase2_auth = g_value_dup_string (value); break; case PROP_PHASE2_AUTHEAP: - g_value_set_string (value, priv->phase2_autheap); + g_free (priv->phase2_autheap); + priv->phase2_autheap = g_value_dup_string (value); break; case PROP_PHASE2_CA_CERT: - g_value_set_boxed (value, priv->phase2_ca_cert); + g_bytes_unref (priv->phase2_ca_cert); + priv->phase2_ca_cert = g_value_dup_boxed (value); break; case PROP_PHASE2_CA_CERT_PASSWORD: - g_value_set_string (value, priv->phase2_ca_cert_password); + g_free (priv->phase2_ca_cert_password); + priv->phase2_ca_cert_password = g_value_dup_string (value); break; case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS: - g_value_set_flags (value, priv->phase2_ca_cert_password_flags); + priv->phase2_ca_cert_password_flags = g_value_get_flags (value); break; case PROP_PHASE2_CA_PATH: - g_value_set_string (value, priv->phase2_ca_path); + g_free (priv->phase2_ca_path); + priv->phase2_ca_path = g_value_dup_string (value); break; case PROP_PHASE2_SUBJECT_MATCH: - g_value_set_string (value, priv->phase2_subject_match); + g_free (priv->phase2_subject_match); + priv->phase2_subject_match = nm_strdup_not_empty (g_value_get_string (value)); break; case PROP_PHASE2_ALTSUBJECT_MATCHES: - g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->phase2_altsubject_matches, TRUE)); + g_slist_free_full (priv->phase2_altsubject_matches, g_free); + priv->phase2_altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); break; case PROP_PHASE2_DOMAIN_SUFFIX_MATCH: - g_value_set_string (value, priv->phase2_domain_suffix_match); + g_free (priv->phase2_domain_suffix_match); + priv->phase2_domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value)); break; case PROP_PHASE2_CLIENT_CERT: - g_value_set_boxed (value, priv->phase2_client_cert); + g_bytes_unref (priv->phase2_client_cert); + priv->phase2_client_cert = g_value_dup_boxed (value); break; case PROP_PHASE2_CLIENT_CERT_PASSWORD: - g_value_set_string (value, priv->phase2_client_cert_password); + g_free (priv->phase2_client_cert_password); + priv->phase2_client_cert_password = g_value_dup_string (value); break; case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS: - g_value_set_flags (value, priv->phase2_client_cert_password_flags); + priv->phase2_client_cert_password_flags = g_value_get_flags (value); break; case PROP_PASSWORD: - g_value_set_string (value, priv->password); + g_free (priv->password); + priv->password = g_value_dup_string (value); break; case PROP_PASSWORD_FLAGS: - g_value_set_flags (value, priv->password_flags); + priv->password_flags = g_value_get_flags (value); break; case PROP_PASSWORD_RAW: - g_value_set_boxed (value, priv->password_raw); + g_bytes_unref (priv->password_raw); + priv->password_raw = g_value_dup_boxed (value); break; case PROP_PASSWORD_RAW_FLAGS: - g_value_set_flags (value, priv->password_raw_flags); + priv->password_raw_flags = g_value_get_flags (value); break; case PROP_PRIVATE_KEY: - g_value_set_boxed (value, priv->private_key); + g_bytes_unref (priv->private_key); + priv->private_key = g_value_dup_boxed (value); break; case PROP_PRIVATE_KEY_PASSWORD: - g_value_set_string (value, priv->private_key_password); + nm_free_secret (priv->private_key_password); + priv->private_key_password = g_value_dup_string (value); break; case PROP_PRIVATE_KEY_PASSWORD_FLAGS: - g_value_set_flags (value, priv->private_key_password_flags); + priv->private_key_password_flags = g_value_get_flags (value); break; case PROP_PHASE2_PRIVATE_KEY: - g_value_set_boxed (value, priv->phase2_private_key); + g_bytes_unref (priv->phase2_private_key); + priv->phase2_private_key = g_value_dup_boxed (value); break; case PROP_PHASE2_PRIVATE_KEY_PASSWORD: - g_value_set_string (value, priv->phase2_private_key_password); + nm_free_secret (priv->phase2_private_key_password); + priv->phase2_private_key_password = g_value_dup_string (value); break; case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS: - g_value_set_flags (value, priv->phase2_private_key_password_flags); + priv->phase2_private_key_password_flags = g_value_get_flags (value); break; case PROP_PIN: - g_value_set_string (value, priv->pin); + g_free (priv->pin); + priv->pin = g_value_dup_string (value); break; case PROP_PIN_FLAGS: - g_value_set_flags (value, priv->pin_flags); + priv->pin_flags = g_value_get_flags (value); break; case PROP_SYSTEM_CA_CERTS: - g_value_set_boolean (value, priv->system_ca_certs); + priv->system_ca_certs = g_value_get_boolean (value); break; case PROP_AUTH_TIMEOUT: - g_value_set_int (value, priv->auth_timeout); + priv->auth_timeout = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -3761,23 +3343,85 @@ get_property (GObject *object, guint prop_id, } } +/*****************************************************************************/ + +static void +nm_setting_802_1x_init (NMSetting8021x *setting) +{ +} + +/** + * nm_setting_802_1x_new: + * + * Creates a new #NMSetting8021x object with default values. + * + * Returns: the new empty #NMSetting8021x object + **/ +NMSetting * +nm_setting_802_1x_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL); +} + static void -nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) +finalize (GObject *object) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + NMSetting8021x *self = NM_SETTING_802_1X (object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Strings first. g_free() already checks for NULLs so we don't have to */ - g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate)); + g_free (priv->identity); + g_free (priv->anonymous_identity); + g_free (priv->ca_path); + g_free (priv->subject_match); + g_free (priv->domain_suffix_match); + g_free (priv->phase1_peapver); + g_free (priv->phase1_peaplabel); + g_free (priv->phase1_fast_provisioning); + g_free (priv->phase2_auth); + g_free (priv->phase2_autheap); + g_free (priv->phase2_ca_path); + g_free (priv->phase2_subject_match); + g_free (priv->phase2_domain_suffix_match); + g_free (priv->password); + g_bytes_unref (priv->password_raw); + g_free (priv->pin); + + g_slist_free_full (priv->eap, g_free); + g_slist_free_full (priv->altsubject_matches, g_free); + g_slist_free_full (priv->phase2_altsubject_matches, g_free); + + g_bytes_unref (priv->ca_cert); + g_free (priv->ca_cert_password); + g_bytes_unref (priv->client_cert); + g_free (priv->client_cert_password); + g_bytes_unref (priv->private_key); + nm_free_secret (priv->private_key_password); + g_bytes_unref (priv->phase2_ca_cert); + g_free (priv->phase2_ca_cert_password); + g_bytes_unref (priv->phase2_client_cert); + g_free (priv->phase2_client_cert_password); + g_bytes_unref (priv->phase2_private_key); + nm_free_secret (priv->phase2_private_key_password); + + G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object); +} + +static void +nm_setting_802_1x_class_init (NMSetting8021xClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMSetting8021xPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->need_secrets = need_secrets; - - /* Properties */ + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; /** * NMSetting8021x:eap: @@ -3796,12 +3440,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_EAP_METHODS=PEAP * ---end--- */ - g_object_class_install_property - (object_class, PROP_EAP, - g_param_spec_boxed (NM_SETTING_802_1X_EAP, "", "", - G_TYPE_STRV, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_EAP] = + g_param_spec_boxed (NM_SETTING_802_1X_EAP, "", "", + G_TYPE_STRV, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:identity: @@ -3816,12 +3459,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_IDENTITY=itsme * ---end--- */ - g_object_class_install_property - (object_class, PROP_IDENTITY, - g_param_spec_string (NM_SETTING_802_1X_IDENTITY, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_IDENTITY] = + g_param_spec_string (NM_SETTING_802_1X_IDENTITY, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:anonymous-identity: @@ -3836,12 +3478,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Anonymous identity for EAP authentication methods. * ---end--- */ - g_object_class_install_property - (object_class, PROP_ANONYMOUS_IDENTITY, - g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_ANONYMOUS_IDENTITY] = + g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:pac-file: @@ -3855,12 +3496,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_PAC_FILE=/home/joe/my-fast.pac * ---end--- */ - g_object_class_install_property - (object_class, PROP_PAC_FILE, - g_param_spec_string (NM_SETTING_802_1X_PAC_FILE, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PAC_FILE] = + g_param_spec_string (NM_SETTING_802_1X_PAC_FILE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:ca-cert: @@ -3887,12 +3527,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_CA_CERT=/home/joe/cacert.crt * ---end--- */ - g_object_class_install_property - (object_class, PROP_CA_CERT, - g_param_spec_boxed (NM_SETTING_802_1X_CA_CERT, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CA_CERT] = + g_param_spec_boxed (NM_SETTING_802_1X_CA_CERT, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:ca-cert-password: @@ -3906,13 +3545,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_CA_CERT_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_CA_CERT_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CA_CERT_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_CA_CERT_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:ca-cert-password-flags: @@ -3924,13 +3562,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_CA_CERT_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CA_CERT_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:ca-path: @@ -3945,12 +3582,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: The property is not handled by ifcfg-rh plugin. * ---end--- */ - g_object_class_install_property - (object_class, PROP_CA_PATH, - g_param_spec_string (NM_SETTING_802_1X_CA_PATH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CA_PATH] = + g_param_spec_string (NM_SETTING_802_1X_CA_PATH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:subject-match: @@ -3968,12 +3604,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_SUBJECT_MATCH="Red Hat" * ---end--- */ - g_object_class_install_property - (object_class, PROP_SUBJECT_MATCH, - g_param_spec_string (NM_SETTING_802_1X_SUBJECT_MATCH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_SUBJECT_MATCH] = + g_param_spec_string (NM_SETTING_802_1X_SUBJECT_MATCH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:altsubject-matches: @@ -3989,12 +3624,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc" * ---end--- */ - g_object_class_install_property - (object_class, PROP_ALTSUBJECT_MATCHES, - g_param_spec_boxed (NM_SETTING_802_1X_ALTSUBJECT_MATCHES, "", "", - G_TYPE_STRV, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_ALTSUBJECT_MATCHES] = + g_param_spec_boxed (NM_SETTING_802_1X_ALTSUBJECT_MATCHES, "", "", + G_TYPE_STRV, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:domain-suffix-match: @@ -4013,12 +3647,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * variable: IEEE_8021X_DOMAIN_SUFFIX_MATCH(+) * ---end--- */ - g_object_class_install_property - (object_class, PROP_DOMAIN_SUFFIX_MATCH, - g_param_spec_string (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_DOMAIN_SUFFIX_MATCH] = + g_param_spec_string (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:client-cert: @@ -4043,12 +3676,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt * ---end--- */ - g_object_class_install_property - (object_class, PROP_CLIENT_CERT, - g_param_spec_boxed (NM_SETTING_802_1X_CLIENT_CERT, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CLIENT_CERT] = + g_param_spec_boxed (NM_SETTING_802_1X_CLIENT_CERT, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:client-cert-password: @@ -4062,13 +3694,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_CLIENT_CERT_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CLIENT_CERT_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:client-cert-password-flags: @@ -4080,13 +3711,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_CLIENT_CERT_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_CLIENT_CERT_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase1-peapver: @@ -4105,12 +3735,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Use to force a specific PEAP version. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE1_PEAPVER, - g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE1_PEAPVER] = + g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase1-peaplabel: @@ -4128,12 +3757,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Use to force the new PEAP label during key derivation. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE1_PEAPLABEL, - g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE1_PEAPLABEL] = + g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase1-fast-provisioning: @@ -4153,12 +3781,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_FAST_PROVISIONING="allow-auth allow-unauth" * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE1_FAST_PROVISIONING, - g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE1_FAST_PROVISIONING] = + g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase1-auth-flags: @@ -4180,13 +3807,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_PHASE1_AUTH_FLAGS="tls-1-0-disable tls-1-1-disable" * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE1_AUTH_FLAGS, - g_param_spec_uint (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, "", "", - 0, G_MAXUINT32, NM_SETTING_802_1X_AUTH_FLAGS_NONE, - G_PARAM_CONSTRUCT | - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE1_AUTH_FLAGS] = + g_param_spec_uint (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, "", "", + 0, G_MAXUINT32, NM_SETTING_802_1X_AUTH_FLAGS_NONE, + G_PARAM_CONSTRUCT | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-auth: @@ -4207,12 +3833,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_INNER_AUTH_METHODS=PAP * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_AUTH, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_AUTH] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-autheap: @@ -4233,12 +3858,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_INNER_AUTH_METHODS="MSCHAPV2 EAP-TLS" * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_AUTHEAP, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_AUTHEAP] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-ca-cert: @@ -4259,12 +3883,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * Setting this property directly is discouraged; use the * nm_setting_802_1x_set_phase2_ca_cert() function instead. **/ - g_object_class_install_property - (object_class, PROP_PHASE2_CA_CERT, - g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CA_CERT, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CA_CERT] = + g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CA_CERT, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-ca-cert-password: @@ -4278,13 +3901,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_CA_CERT_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CA_CERT_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-ca-cert-password-flags: @@ -4296,13 +3918,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_CA_CERT_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CA_CERT_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-ca-path: @@ -4311,12 +3932,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * certificates to be added to the verification chain in addition to the * certificate specified in the #NMSetting8021x:phase2-ca-cert property. **/ - g_object_class_install_property - (object_class, PROP_PHASE2_CA_PATH, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CA_PATH] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-subject-match: @@ -4335,12 +3955,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat" * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_SUBJECT_MATCH, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_SUBJECT_MATCH] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-altsubject-matches: @@ -4355,12 +3974,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * variable: IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+) * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_ALTSUBJECT_MATCHES, - g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, "", "", - G_TYPE_STRV, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_ALTSUBJECT_MATCHES] = + g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, "", "", + G_TYPE_STRV, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-domain-suffix-match: @@ -4380,12 +3998,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * variable: IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH(+) * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_DOMAIN_SUFFIX_MATCH, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_DOMAIN_SUFFIX_MATCH] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-client-cert: @@ -4413,12 +4030,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_CLIENT_CERT, - g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CLIENT_CERT] = + g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-client-cert-password: @@ -4432,13 +4048,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_CLIENT_CERT_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-client-cert-password-flags: @@ -4450,13 +4065,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) /* ---ifcfg-rh--- * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:password: @@ -4472,13 +4086,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * lookaside file, or it can be owned by a secret agent. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:password-flags: @@ -4492,13 +4105,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Password flags for IEEE_8021X_PASSWORD password. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:password-raw: @@ -4516,13 +4128,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_PASSWORD_RAW=041c8320083aa4bf * ---end--- */ - g_object_class_install_property - (object_class, PROP_PASSWORD_RAW, - g_param_spec_boxed (NM_SETTING_802_1X_PASSWORD_RAW, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PASSWORD_RAW] = + g_param_spec_boxed (NM_SETTING_802_1X_PASSWORD_RAW, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:password-raw-flags: @@ -4535,13 +4146,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: The property is not handled by ifcfg-rh plugin. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PASSWORD_RAW_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PASSWORD_RAW_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:private-key: @@ -4581,12 +4191,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * example: IEEE_8021X_PRIVATE_KEY=/home/joe/mykey.p12 * ---end--- */ - g_object_class_install_property - (object_class, PROP_PRIVATE_KEY, - g_param_spec_boxed (NM_SETTING_802_1X_PRIVATE_KEY, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PRIVATE_KEY] = + g_param_spec_boxed (NM_SETTING_802_1X_PRIVATE_KEY, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:private-key-password: @@ -4605,13 +4214,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * lookaside file, or it can be owned by a secret agent. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PRIVATE_KEY_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PRIVATE_KEY_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:private-key-password-flags: @@ -4626,13 +4234,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Password flags for IEEE_8021X_PRIVATE_KEY_PASSWORD password. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PRIVATE_KEY_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PRIVATE_KEY_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-private-key: @@ -4666,12 +4273,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Private key for inner authentication method for EAP-TLS. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_PRIVATE_KEY, - g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, "", "", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_PRIVATE_KEY] = + g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, "", "", + G_TYPE_BYTES, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-private-key-password: @@ -4691,13 +4297,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * lookaside file, or it can be owned by a secret agent. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD, - g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD] = + g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:phase2-private-key-password-flags: @@ -4712,13 +4317,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Password flags for IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD password. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:pin: @@ -4731,13 +4335,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: The property is not handled by ifcfg-rh plugin. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PIN, - g_param_spec_string (NM_SETTING_802_1X_PIN, "", "", - NULL, - G_PARAM_READWRITE | - NM_SETTING_PARAM_SECRET | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PIN] = + g_param_spec_string (NM_SETTING_802_1X_PIN, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_SECRET | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:pin-flags: @@ -4750,13 +4353,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: The property is not handled by ifcfg-rh plugin. * ---end--- */ - g_object_class_install_property - (object_class, PROP_PIN_FLAGS, - g_param_spec_flags (NM_SETTING_802_1X_PIN_FLAGS, "", "", - NM_TYPE_SETTING_SECRET_FLAGS, - NM_SETTING_SECRET_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_PIN_FLAGS] = + g_param_spec_flags (NM_SETTING_802_1X_PIN_FLAGS, "", "", + NM_TYPE_SETTING_SECRET_FLAGS, + NM_SETTING_SECRET_FLAG_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:system-ca-certs: @@ -4777,13 +4379,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: The property is not handled by ifcfg-rh plugin. * ---end--- */ - g_object_class_install_property - (object_class, PROP_SYSTEM_CA_CERTS, - g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_SYSTEM_CA_CERTS] = + g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); /** * NMSetting8021x:auth-timeout: @@ -4800,11 +4401,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * description: Timeout in seconds for the 802.1X authentication. Zero means the global default or 25. * ---end--- */ - g_object_class_install_property - (object_class, PROP_AUTH_TIMEOUT, - g_param_spec_int (NM_SETTING_802_1X_AUTH_TIMEOUT, "", "", - 0, G_MAXINT32, 0, - G_PARAM_READWRITE | - NM_SETTING_PARAM_FUZZY_IGNORE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_AUTH_TIMEOUT] = + g_param_spec_int (NM_SETTING_802_1X_AUTH_TIMEOUT, "", "", + 0, G_MAXINT32, 0, + G_PARAM_READWRITE | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_802_1X); } diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h index 986d0488..82ef5eba 100644 --- a/libnm-core/nm-setting-8021x.h +++ b/libnm-core/nm-setting-8021x.h @@ -359,7 +359,7 @@ NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format (NMSett NM_AVAILABLE_IN_1_8 NMSetting8021xAuthFlags nm_setting_802_1x_get_phase1_auth_flags (NMSetting8021x *setting); NM_AVAILABLE_IN_1_8 -gint nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting); +int nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c index c2eb5db4..9ffff927 100644 --- a/libnm-core/nm-setting-adsl.c +++ b/libnm-core/nm-setting-adsl.c @@ -37,9 +37,7 @@ * properties of ADSL connections. */ -G_DEFINE_TYPE_WITH_CODE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING, - _nm_register_setting (ADSL, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_ADSL) +G_DEFINE_TYPE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING) #define NM_SETTING_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate)) @@ -346,22 +344,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_adsl_class_init (NMSettingAdslClass *setting_class) +nm_setting_adsl_class_init (NMSettingAdslClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingAdslPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingAdslPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; /** * NMSettingAdsl:username: @@ -448,4 +444,6 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class) 0, 65536, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_ADSL); } diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c index 5b6ef3eb..bbc6a83d 100644 --- a/libnm-core/nm-setting-bluetooth.c +++ b/libnm-core/nm-setting-bluetooth.c @@ -43,9 +43,7 @@ * Point (NAP) profiles. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING, - _nm_register_setting (BLUETOOTH, NM_SETTING_PRIORITY_HW_NON_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BLUETOOTH) +G_DEFINE_TYPE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING) #define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate)) @@ -283,20 +281,19 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) +nm_setting_bluetooth_class_init (NMSettingBluetoothClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingBluetoothPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBluetoothPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingBluetooth:bdaddr: @@ -310,10 +307,13 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_BLUETOOTH_BDADDR, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_BLUETOOTH_BDADDR), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingBluetooth:type: @@ -328,4 +328,7 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BLUETOOTH, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index 9b4b3641..0c84b3a0 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -57,9 +57,7 @@ typedef struct { NMUtilsNamedValue *options_idx_cache; } NMSettingBondPrivate; -G_DEFINE_TYPE_WITH_CODE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING, - _nm_register_setting (BOND, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BOND) +G_DEFINE_TYPE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING) #define NM_SETTING_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate)) @@ -180,7 +178,7 @@ nm_setting_bond_get_option (NMSettingBond *setting, static gboolean validate_int (const char *name, const char *value, const BondDefault *def) { - glong num; + long num; guint i; for (i = 0; i < strlen (value); i++) { @@ -873,7 +871,7 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; if (nm_streq0 (prop_spec->name, NM_SETTING_BOND_OPTIONS)) { return options_equal (NM_SETTING_BOND (setting), @@ -882,9 +880,8 @@ compare_property (NMSetting *setting, flags); } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_bond_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_bond_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } /*****************************************************************************/ @@ -961,21 +958,21 @@ finalize (GObject *object) } static void -nm_setting_bond_class_init (NMSettingBondClass *setting_class) +nm_setting_bond_class_init (NMSettingBondClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingBondPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBondPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->compare_property = compare_property; - /* Properties */ + setting_class->verify = verify; + setting_class->compare_property = compare_property; + /** * NMSettingBond:options: (type GHashTable(utf8,utf8)): * @@ -997,10 +994,13 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_BOND_OPTIONS, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_BOND_OPTIONS), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /* ---dbus--- * property: interface-name @@ -1010,8 +1010,12 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class) * bond's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BOND, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c index 3fc0e873..4104f8c5 100644 --- a/libnm-core/nm-setting-bridge-port.c +++ b/libnm-core/nm-setting-bridge-port.c @@ -40,9 +40,7 @@ * optional properties that apply to bridge ports. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING, - _nm_register_setting (BRIDGE_PORT, NM_SETTING_PRIORITY_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE_PORT) +G_DEFINE_TYPE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING) #define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate)) @@ -212,19 +210,18 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class) +nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingBridgePortPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBridgePortPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingBridgePort:priority: * @@ -290,4 +287,6 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_BRIDGE_PORT); } diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 112b499f..71fe2ed2 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -38,9 +38,7 @@ * necessary for bridging connections. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING, - _nm_register_setting (BRIDGE, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE) +G_DEFINE_TYPE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) #define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate)) @@ -393,20 +391,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) +nm_setting_bridge_class_init (NMSettingBridgeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingBridgePrivate)); + g_type_class_add_private (klass, sizeof (NMSettingBridgePrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingBridge:mac-address: * @@ -444,10 +442,13 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_BRIDGE_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_BRIDGE_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingBridge:stp: @@ -638,8 +639,12 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) * bridge's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c index 63178951..a5d5428d 100644 --- a/libnm-core/nm-setting-cdma.c +++ b/libnm-core/nm-setting-cdma.c @@ -37,9 +37,7 @@ * networks, including those using CDMA2000/EVDO technology. */ -G_DEFINE_TYPE_WITH_CODE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING, - _nm_register_setting (CDMA, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CDMA) +G_DEFINE_TYPE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING) #define NM_SETTING_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate)) @@ -285,22 +283,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class) +nm_setting_cdma_class_init (NMSettingCdmaClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingCdmaPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingCdmaPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; /** * NMSettingCdma:number: @@ -375,4 +371,5 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class) NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_CDMA); } diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index 689ba794..50240bc9 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -45,9 +45,7 @@ * a #NMSettingConnection setting. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING, - _nm_register_setting (CONNECTION, NM_SETTING_PRIORITY_CONNECTION)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CONNECTION) +G_DEFINE_TYPE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING) #define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate)) @@ -71,8 +69,9 @@ typedef struct { NMSettingConnectionAutoconnectSlaves autoconnect_slaves; GSList *permissions; /* list of Permission structs */ gboolean autoconnect; - gint autoconnect_priority; - gint autoconnect_retries; + int autoconnect_priority; + int autoconnect_retries; + int multi_connect; guint64 timestamp; gboolean read_only; char *zone; @@ -80,8 +79,9 @@ typedef struct { guint gateway_ping_timeout; NMMetered metered; NMSettingConnectionLldp lldp; - gint auth_retries; + int auth_retries; int mdns; + int llmnr; } NMSettingConnectionPrivate; enum { @@ -94,6 +94,7 @@ enum { PROP_AUTOCONNECT, PROP_AUTOCONNECT_PRIORITY, PROP_AUTOCONNECT_RETRIES, + PROP_MULTI_CONNECT, PROP_TIMESTAMP, PROP_READ_ONLY, PROP_ZONE, @@ -105,6 +106,7 @@ enum { PROP_METERED, PROP_LLDP, PROP_MDNS, + PROP_LLMNR, PROP_STABLE_ID, PROP_AUTH_RETRIES, @@ -528,7 +530,7 @@ nm_setting_connection_get_autoconnect (NMSettingConnection *setting) * * Returns: the connection's autoconnect priority **/ -gint +int nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting) { g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0); @@ -547,7 +549,7 @@ nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting) * * Since: 1.6 **/ -gint +int nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting) { g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1); @@ -556,6 +558,22 @@ nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting) } /** + * nm_setting_connection_get_multi_connect: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:multi-connect property of the connection. + * + * Since: 1.14 + **/ +NMConnectionMultiConnect +nm_setting_connection_get_multi_connect (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1); + + return (NMConnectionMultiConnect) NM_SETTING_CONNECTION_GET_PRIVATE (setting)->multi_connect; +} + +/** * nm_setting_connection_get_auth_retries: * @setting: the #NMSettingConnection * @@ -566,7 +584,7 @@ nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting) * * Since: 1.10 **/ -gint +int nm_setting_connection_get_auth_retries (NMSettingConnection *setting) { g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1); @@ -880,6 +898,23 @@ nm_setting_connection_get_mdns (NMSettingConnection *setting) return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->mdns; } +/** + * nm_setting_connection_get_llmnr: + * @setting: the #NMSettingConnection + * + * Returns: the #NMSettingConnection:llmnr property of the setting. + * + * Since: 1.14 + **/ +NMSettingConnectionLlmnr +nm_setting_connection_get_llmnr (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), + NM_SETTING_CONNECTION_LLMNR_DEFAULT); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->llmnr; +} + static void _set_error_missing_base_setting (GError **error, const char *type) { @@ -1077,17 +1112,41 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if ( priv->mdns < NM_SETTING_CONNECTION_MDNS_DEFAULT - || priv->mdns > NM_SETTING_CONNECTION_MDNS_YES) { + if ( priv->mdns < (int) NM_SETTING_CONNECTION_MDNS_DEFAULT + || priv->mdns > (int) NM_SETTING_CONNECTION_MDNS_YES) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("mdns value %d is not valid"), priv->mdns); + _("value %d is not valid"), priv->mdns); g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MDNS); return FALSE; } + if ( priv->llmnr < (int) NM_SETTING_CONNECTION_LLMNR_DEFAULT + || priv->llmnr > (int) NM_SETTING_CONNECTION_LLMNR_YES) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value %d is not valid"), priv->llmnr); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_LLMNR); + return FALSE; + } + + if (!NM_IN_SET (priv->multi_connect, (int) NM_CONNECTION_MULTI_CONNECT_DEFAULT, + (int) NM_CONNECTION_MULTI_CONNECT_SINGLE, + (int) NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE, + (int) NM_CONNECTION_MULTI_CONNECT_MULTIPLE)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value %d is not valid"), priv->multi_connect); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_MULTI_CONNECT); + return FALSE; + } + /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ if (!priv->uuid) { @@ -1238,7 +1297,6 @@ compare_property (NMSetting *setting, && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_TIMESTAMP) == 0) return TRUE; - /* Otherwise chain up to parent to handle generic compare */ return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (setting, other, prop_spec, flags); } @@ -1248,6 +1306,7 @@ nm_setting_connection_init (NMSettingConnection *setting) NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting); priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; } static void @@ -1329,6 +1388,9 @@ set_property (GObject *object, guint prop_id, case PROP_AUTOCONNECT_RETRIES: priv->autoconnect_retries = g_value_get_int (value); break; + case PROP_MULTI_CONNECT: + priv->multi_connect = g_value_get_int (value); + break; case PROP_TIMESTAMP: priv->timestamp = g_value_get_uint64 (value); break; @@ -1369,6 +1431,9 @@ set_property (GObject *object, guint prop_id, case PROP_MDNS: priv->mdns = g_value_get_int (value); break; + case PROP_LLMNR: + priv->llmnr = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1424,6 +1489,9 @@ get_property (GObject *object, guint prop_id, case PROP_AUTOCONNECT_RETRIES: g_value_set_int (value, nm_setting_connection_get_autoconnect_retries (setting)); break; + case PROP_MULTI_CONNECT: + g_value_set_int (value, priv->multi_connect); + break; case PROP_TIMESTAMP: g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting)); break; @@ -1460,6 +1528,9 @@ get_property (GObject *object, guint prop_id, case PROP_MDNS: g_value_set_int (value, priv->mdns); break; + case PROP_LLMNR: + g_value_set_int (value, priv->llmnr); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1467,21 +1538,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) +nm_setting_connection_class_init (NMSettingConnectionClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingConnectionPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingConnectionPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->compare_property = compare_property; - /* Properties */ + setting_class->verify = verify; + setting_class->compare_property = compare_property; /** * NMSettingConnection:id: @@ -1618,11 +1688,14 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, NM_SETTING_CONNECTION_INTERFACE_NAME, - G_VARIANT_TYPE_STRING, - NULL, - nm_setting_connection_set_interface_name, - nm_setting_connection_no_interface_name); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_CONNECTION_INTERFACE_NAME), + G_VARIANT_TYPE_STRING, + NULL, + nm_setting_connection_set_interface_name, + nm_setting_connection_no_interface_name); /** * NMSettingConnection:type: @@ -1766,6 +1839,30 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) G_PARAM_STATIC_STRINGS)); /** + * NMSettingConnection:multi-connect: + * + * Specifies whether the profile can be active multiple times at a particular + * moment. The value is of type #NMConnectionMultiConnect. + * + * Since: 1.14 + */ + /* ---ifcfg-rh--- + * property: multi-connect + * variable: MULTI_CONNECT(+) + * description: whether the profile can be active on multiple devices at a given + * moment. The values are numbers corresponding to #NMConnectionMultiConnect enum. + * example: ZONE=3 + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_MULTI_CONNECT, + g_param_spec_int (NM_SETTING_CONNECTION_MULTI_CONNECT, "", "", + G_MININT32, G_MAXINT32, NM_CONNECTION_MULTI_CONNECT_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); + + /** * NMSettingConnection:timestamp: * * The time, in seconds since the Unix Epoch, that the connection was last @@ -2044,8 +2141,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) * The permitted values are: yes: register hostname and resolving * for the connection, no: disable mDNS for the interface, resolve: * do not register hostname but allow resolving of mDNS host names. - * When updating this property on a currently activated connection, - * the change takes effect immediately. * * This feature requires a plugin which supports mDNS. One such * plugin is dns-systemd-resolved. @@ -2054,11 +2149,11 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) **/ /* ---ifcfg-rh--- * property: mdns - * variable: CONNECTION_MDNS(+) + * variable: MDNS(+) * values: yes,no,resolve * default: missing variable means global default * description: Whether or not mDNS is enabled for the connection - * example: CONNECTION_MDNS=yes + * example: MDNS=yes * ---end--- */ g_object_class_install_property @@ -2068,4 +2163,41 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) NM_SETTING_CONNECTION_MDNS_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingConnection:llmnr: + * + * Whether Link-Local Multicast Name Resolution (LLMNR) is enabled + * for the connection. LLMNR is a protocol based on the Domain Name + * System (DNS) packet format that allows both IPv4 and IPv6 hosts + * to perform name resolution for hosts on the same local link. + * + * The permitted values are: yes: register hostname and resolving + * for the connection, no: disable LLMNR for the interface, resolve: + * do not register hostname but allow resolving of LLMNR host names. + * + * This feature requires a plugin which supports LLMNR. One such + * plugin is dns-systemd-resolved. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: llmnr + * variable: LLMNR(+) + * values: yes,no,resolve + * default: missing variable means global default + * description: Whether or not LLMNR is enabled for the connection + * example: LLMNR=yes + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_LLMNR, + g_param_spec_int (NM_SETTING_CONNECTION_LLMNR, "", "", + G_MININT32, G_MAXINT32, + NM_SETTING_CONNECTION_LLMNR_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_CONNECTION, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h index cf083a48..b65fb67b 100644 --- a/libnm-core/nm-setting-connection.h +++ b/libnm-core/nm-setting-connection.h @@ -52,6 +52,7 @@ G_BEGIN_DECLS #define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect" #define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY "autoconnect-priority" #define NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES "autoconnect-retries" +#define NM_SETTING_CONNECTION_MULTI_CONNECT "multi-connect" #define NM_SETTING_CONNECTION_TIMESTAMP "timestamp" #define NM_SETTING_CONNECTION_READ_ONLY "read-only" #define NM_SETTING_CONNECTION_PERMISSIONS "permissions" @@ -65,6 +66,7 @@ G_BEGIN_DECLS #define NM_SETTING_CONNECTION_LLDP "lldp" #define NM_SETTING_CONNECTION_AUTH_RETRIES "auth-retries" #define NM_SETTING_CONNECTION_MDNS "mdns" +#define NM_SETTING_CONNECTION_LLMNR "llmnr" /* Types for property values */ /** @@ -117,6 +119,24 @@ typedef enum { } NMSettingConnectionMdns; /** + * NMSettingConnectionLlmnr: + * @NM_SETTING_CONNECTION_LLMNR_DEFAULT: default value + * @NM_SETTING_CONNECTION_LLMNR_NO: disable LLMNR + * @NM_SETTING_CONNECTION_LLMNR_RESOLVE: support only resolving, do not register hostname + * @NM_SETTING_CONNECTION_LLMNR_YES: enable LLMNR + * + * #NMSettingConnectionLlmnr values indicate whether LLMNR should be enabled. + * + * Since: 1.14 + */ +typedef enum { + NM_SETTING_CONNECTION_LLMNR_DEFAULT = -1, + NM_SETTING_CONNECTION_LLMNR_NO = 0, + NM_SETTING_CONNECTION_LLMNR_RESOLVE = 1, + NM_SETTING_CONNECTION_LLMNR_YES = 2, +} NMSettingConnectionLlmnr; + +/** * NMSettingConnection: * * General Connection Profile Settings @@ -142,9 +162,11 @@ const char *nm_setting_connection_get_stable_id (NMSettingConnection *set const char *nm_setting_connection_get_interface_name (NMSettingConnection *setting); const char *nm_setting_connection_get_connection_type (NMSettingConnection *setting); gboolean nm_setting_connection_get_autoconnect (NMSettingConnection *setting); -gint nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting); +int nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting); NM_AVAILABLE_IN_1_6 -gint nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting); +int nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting); +NM_AVAILABLE_IN_1_14 +NMConnectionMultiConnect nm_setting_connection_get_multi_connect (NMSettingConnection *setting); guint64 nm_setting_connection_get_timestamp (NMSettingConnection *setting); gboolean nm_setting_connection_get_read_only (NMSettingConnection *setting); @@ -187,10 +209,13 @@ NM_AVAILABLE_IN_1_2 NMSettingConnectionLldp nm_setting_connection_get_lldp (NMSettingConnection *setting); NM_AVAILABLE_IN_1_10 -gint nm_setting_connection_get_auth_retries (NMSettingConnection *setting); +int nm_setting_connection_get_auth_retries (NMSettingConnection *setting); NM_AVAILABLE_IN_1_12 NMSettingConnectionMdns nm_setting_connection_get_mdns (NMSettingConnection *setting); +NM_AVAILABLE_IN_1_14 +NMSettingConnectionLlmnr nm_setting_connection_get_llmnr (NMSettingConnection *setting); + G_END_DECLS #endif /* __NM_SETTING_CONNECTION_H__ */ diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c index 491d9151..dabcbbaf 100644 --- a/libnm-core/nm-setting-dcb.c +++ b/libnm-core/nm-setting-dcb.c @@ -40,22 +40,20 @@ * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING, - _nm_register_setting (DCB, NM_SETTING_PRIORITY_HW_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DCB) +G_DEFINE_TYPE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING) #define NM_SETTING_DCB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate)) typedef struct { NMSettingDcbFlags app_fcoe_flags; - gint app_fcoe_priority; + int app_fcoe_priority; char * app_fcoe_mode; NMSettingDcbFlags app_iscsi_flags; - gint app_iscsi_priority; + int app_iscsi_priority; NMSettingDcbFlags app_fip_flags; - gint app_fip_priority; + int app_fip_priority; /* Priority Flow Control */ NMSettingDcbFlags pfc_flags; @@ -128,7 +126,7 @@ nm_setting_dcb_get_app_fcoe_flags (NMSettingDcb *setting) * * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting **/ -gint +int nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting) { g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0); @@ -170,7 +168,7 @@ nm_setting_dcb_get_app_iscsi_flags (NMSettingDcb *setting) * * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting **/ -gint +int nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting) { g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0); @@ -198,7 +196,7 @@ nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting) * * Returns: the #NMSettingDcb:app-fip-priority property of the setting **/ -gint +int nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting) { g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0); @@ -594,7 +592,7 @@ check_uint_array (const guint *array, } static gboolean -check_priority (gint val, +check_priority (int val, NMSettingDcbFlags flags, const char *prop_name, GError **error) @@ -907,20 +905,20 @@ finalize (GObject *object) } static void -nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) +nm_setting_dcb_class_init (NMSettingDcbClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingDcbPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingDcbPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingDcb:app-fcoe-flags: * @@ -1119,10 +1117,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_FLOW_CONTROL), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-group-flags: @@ -1167,10 +1168,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_GROUP_ID, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_GROUP_ID), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-group-bandwidth: (type GArray(guint)) @@ -1193,10 +1197,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-bandwidth: (type GArray(guint)) @@ -1221,10 +1228,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_BANDWIDTH, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_BANDWIDTH), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-strict-bandwidth: (type GArray(gboolean)) @@ -1247,10 +1257,13 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); /** * NMSettingDcb:priority-traffic-class: (type GArray(guint)) @@ -1272,8 +1285,14 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, - G_VARIANT_TYPE ("au"), - _nm_setting_dcb_uint_array_to_dbus, - _nm_setting_dcb_uint_array_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS), + G_VARIANT_TYPE ("au"), + _nm_setting_dcb_uint_array_to_dbus, + _nm_setting_dcb_uint_array_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_DCB, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-dcb.h b/libnm-core/nm-setting-dcb.h index 51a883fb..92ca2682 100644 --- a/libnm-core/nm-setting-dcb.h +++ b/libnm-core/nm-setting-dcb.h @@ -112,14 +112,14 @@ GType nm_setting_dcb_get_type (void); NMSetting * nm_setting_dcb_new (void); NMSettingDcbFlags nm_setting_dcb_get_app_fcoe_flags (NMSettingDcb *setting); -gint nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting); +int nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting); const char * nm_setting_dcb_get_app_fcoe_mode (NMSettingDcb *setting); NMSettingDcbFlags nm_setting_dcb_get_app_iscsi_flags (NMSettingDcb *setting); -gint nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting); +int nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting); NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting); -gint nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting); +int nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting); /* Priority Flow Control */ NMSettingDcbFlags nm_setting_dcb_get_priority_flow_control_flags (NMSettingDcb *setting); diff --git a/libnm-core/nm-setting-dummy.c b/libnm-core/nm-setting-dummy.c index 4b3c41f0..9ae05ec4 100644 --- a/libnm-core/nm-setting-dummy.c +++ b/libnm-core/nm-setting-dummy.c @@ -34,9 +34,7 @@ * necessary for connection to dummy devices **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING, - _nm_register_setting (DUMMY, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DUMMY) +G_DEFINE_TYPE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING) /** * nm_setting_dummy_new: @@ -68,9 +66,11 @@ nm_setting_dummy_init (NMSettingDummy *setting) } static void -nm_setting_dummy_class_init (NMSettingDummyClass *setting_class) +nm_setting_dummy_class_init (NMSettingDummyClass *klass) { - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - parent_class->verify = verify; + setting_class->verify = verify; + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_DUMMY); } diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c new file mode 100644 index 00000000..7bdbcb1a --- /dev/null +++ b/libnm-core/nm-setting-ethtool.c @@ -0,0 +1,342 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 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. + * + * Copyright 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-ethtool.h" + +#include "nm-setting-private.h" +#include "nm-ethtool-utils.h" + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-ethtool + * @short_description: Describes connection properties for ethtool related options + * + * The #NMSettingEthtool object is a #NMSetting subclass that describes properties + * to control network driver and hardware settings. + **/ + +/*****************************************************************************/ + +/** + * nm_ethtool_optname_is_feature: + * @optname: the option name to check + * + * Checks whether @optname is a valid option name for an offload feature. + * + * %Returns: %TRUE, if @optname is valid + * + * Since: 1.14 + */ +gboolean +nm_ethtool_optname_is_feature (const char *optname) +{ + return optname && nm_ethtool_id_is_feature (nm_ethtool_id_get_by_name (optname)); +} + +/*****************************************************************************/ + +/** + * NMSettingEthtool: + * + * Ethtool Ethernet Settings + * + * Since: 1.14 + */ +struct _NMSettingEthtool { + NMSetting parent; +}; + +struct _NMSettingEthtoolClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE (NMSettingEthtool, nm_setting_ethtool, NM_TYPE_SETTING) + +#define NM_SETTING_ETHTOOL_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettingEthtool, NM_IS_SETTING_ETHTOOL, NMSetting) + +/*****************************************************************************/ + +static void +_notify_attributes (NMSettingEthtool *self) +{ + _nm_setting_gendata_notify (NM_SETTING (self), TRUE); +} + +/*****************************************************************************/ + +/** + * nm_setting_ethtool_get_feature: + * @setting: the #NMSettingEthtool + * @optname: option name of the offload feature to get + * + * Gets and offload feature setting. Returns %NM_TERNARY_DEFAULT if the + * feature is not set. + * + * Returns: a #NMTernary value indicating whether the offload feature + * is enabled, disabled, or left untouched. + * + * Since: 1.14 + */ +NMTernary +nm_setting_ethtool_get_feature (NMSettingEthtool *setting, + const char *optname) +{ + GVariant *v; + + g_return_val_if_fail (NM_IS_SETTING_ETHTOOL (setting), NM_TERNARY_DEFAULT); + g_return_val_if_fail (optname && nm_ethtool_optname_is_feature (optname), NM_TERNARY_DEFAULT); + + v = nm_setting_gendata_get (NM_SETTING (setting), optname); + if ( v + && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + return g_variant_get_boolean (v) + ? NM_TERNARY_TRUE + : NM_TERNARY_FALSE; + } + return NM_TERNARY_DEFAULT; +} + +/** + * nm_setting_ethtool_set_feature: + * @setting: the #NMSettingEthtool + * @optname: option name of the offload feature to get + * @value: the new value to set. The special value %NM_TERNARY_DEFAULT + * means to clear the offload feature setting. + * + * Sets and offload feature setting. + * + * Since: 1.14 + */ +void +nm_setting_ethtool_set_feature (NMSettingEthtool *setting, + const char *optname, + NMTernary value) +{ + GHashTable *hash; + GVariant *v; + + g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); + g_return_if_fail (optname && nm_ethtool_optname_is_feature (optname)); + g_return_if_fail (NM_IN_SET (value, NM_TERNARY_DEFAULT, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE)); + + hash = _nm_setting_gendata_hash (NM_SETTING (setting), + value != NM_TERNARY_DEFAULT); + + if (value == NM_TERNARY_DEFAULT) { + if (hash) { + if (g_hash_table_remove (hash, optname)) + _notify_attributes (setting); + } + return; + } + + v = g_hash_table_lookup (hash, optname); + if ( v + && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + if (g_variant_get_boolean (v)) { + if (value == NM_TERNARY_TRUE) + return; + } else { + if (value == NM_TERNARY_FALSE) + return; + } + } + + v = g_variant_ref_sink (g_variant_new_boolean (value != NM_TERNARY_FALSE)); + g_hash_table_insert (hash, + g_strdup (optname), + v); + _notify_attributes (setting); +} + +/** + * nm_setting_ethtool_clear_features: + * @setting: the #NMSettingEthtool + * + * Clears all offload features settings + * + * Since: 1.14 + */ +void +nm_setting_ethtool_clear_features (NMSettingEthtool *setting) +{ + GHashTable *hash; + GHashTableIter iter; + const char *name; + gboolean changed = FALSE; + + g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); + + hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE); + if (!hash) + return; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) { + if (nm_ethtool_optname_is_feature (name)) { + g_hash_table_iter_remove (&iter); + changed = TRUE; + } + } + + if (changed) + _notify_attributes (setting); +} + +guint +nm_setting_ethtool_init_features (NMSettingEthtool *setting, + NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */) +{ + GHashTable *hash; + GHashTableIter iter; + guint i; + guint n_req = 0; + const char *name; + GVariant *variant; + + nm_assert (NM_IS_SETTING_ETHTOOL (setting)); + nm_assert (requested); + + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + requested[i] = NM_TERNARY_DEFAULT; + + hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE); + if (!hash) + return 0; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) { + NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name (name); + + if (!nm_ethtool_id_is_feature (ethtool_id)) + continue; + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) + continue; + + requested[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST] = g_variant_get_boolean (variant) + ? NM_TERNARY_TRUE + : NM_TERNARY_FALSE; + n_req++; + } + + return n_req; +} + +/*****************************************************************************/ + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + GHashTable *hash; + GHashTableIter iter; + const char *optname; + GVariant *variant; + + hash = _nm_setting_gendata_hash (setting, FALSE); + + if (!hash) + goto out; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &optname, (gpointer *) &variant)) { + if (!nm_ethtool_optname_is_feature (optname)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unsupported offload feature")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("offload feature has invalid variant type")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); + return FALSE; + } + } + +out: + return TRUE; +} + +/*****************************************************************************/ + +static const GVariantType * +get_variant_type (const NMSettInfoSetting *sett_info, + const char *name, + GError **error) +{ + if (nm_ethtool_optname_is_feature (name)) + return G_VARIANT_TYPE_BOOLEAN; + + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown ethtool option '%s'"), + name); + return NULL; +} + +/*****************************************************************************/ + +static void +nm_setting_ethtool_init (NMSettingEthtool *setting) +{ +} + +/** + * nm_setting_ethtool_new: + * + * Creates a new #NMSettingEthtool object with default values. + * + * Returns: (transfer full): the new empty #NMSettingEthtool object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_ethtool_new (void) +{ + return g_object_new (NM_TYPE_SETTING_ETHTOOL, NULL); +} + +static void +nm_setting_ethtool_class_init (NMSettingEthtoolClass *klass) +{ + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + setting_class->verify = verify; + + _nm_setting_class_commit_full (setting_class, + NM_META_SETTING_TYPE_ETHTOOL, + NM_SETT_INFO_SETT_DETAIL ( + .gendata_info = NM_SETT_INFO_SETT_GENDATA ( + .get_variant_type = get_variant_type, + ), + ), + NULL); +} diff --git a/libnm-core/nm-setting-ethtool.h b/libnm-core/nm-setting-ethtool.h new file mode 100644 index 00000000..6a0458a5 --- /dev/null +++ b/libnm-core/nm-setting-ethtool.h @@ -0,0 +1,124 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 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. + * + * Copyright 2018 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_ETHTOOL_H__ +#define __NM_SETTING_ETHTOOL_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +/*****************************************************************************/ + +#define NM_ETHTOOL_OPTNAME_FEATURE_ESP_HW_OFFLOAD "feature-esp-hw-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_ESP_TX_CSUM_HW_OFFLOAD "feature-esp-tx-csum-hw-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_FCOE_MTU "feature-fcoe-mtu" +#define NM_ETHTOOL_OPTNAME_FEATURE_GRO "feature-gro" +#define NM_ETHTOOL_OPTNAME_FEATURE_GSO "feature-gso" +#define NM_ETHTOOL_OPTNAME_FEATURE_HIGHDMA "feature-highdma" +#define NM_ETHTOOL_OPTNAME_FEATURE_HW_TC_OFFLOAD "feature-hw-tc-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_L2_FWD_OFFLOAD "feature-l2-fwd-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_LOOPBACK "feature-loopback" +#define NM_ETHTOOL_OPTNAME_FEATURE_LRO "feature-lro" +#define NM_ETHTOOL_OPTNAME_FEATURE_NTUPLE "feature-ntuple" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX "feature-rx" +#define NM_ETHTOOL_OPTNAME_FEATURE_RXHASH "feature-rxhash" +#define NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN "feature-rxvlan" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_ALL "feature-rx-all" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_FCS "feature-rx-fcs" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_GRO_HW "feature-rx-gro-hw" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD "feature-rx-udp_tunnel-port-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_FILTER "feature-rx-vlan-filter" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_STAG_FILTER "feature-rx-vlan-stag-filter" +#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_STAG_HW_PARSE "feature-rx-vlan-stag-hw-parse" +#define NM_ETHTOOL_OPTNAME_FEATURE_SG "feature-sg" +#define NM_ETHTOOL_OPTNAME_FEATURE_TLS_HW_RECORD "feature-tls-hw-record" +#define NM_ETHTOOL_OPTNAME_FEATURE_TLS_HW_TX_OFFLOAD "feature-tls-hw-tx-offload" +#define NM_ETHTOOL_OPTNAME_FEATURE_TSO "feature-tso" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX "feature-tx" +#define NM_ETHTOOL_OPTNAME_FEATURE_TXVLAN "feature-txvlan" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_FCOE_CRC "feature-tx-checksum-fcoe-crc" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IPV4 "feature-tx-checksum-ipv4" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IPV6 "feature-tx-checksum-ipv6" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IP_GENERIC "feature-tx-checksum-ip-generic" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_SCTP "feature-tx-checksum-sctp" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_ESP_SEGMENTATION "feature-tx-esp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_FCOE_SEGMENTATION "feature-tx-fcoe-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GRE_CSUM_SEGMENTATION "feature-tx-gre-csum-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GRE_SEGMENTATION "feature-tx-gre-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GSO_PARTIAL "feature-tx-gso-partial" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GSO_ROBUST "feature-tx-gso-robust" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_IPXIP4_SEGMENTATION "feature-tx-ipxip4-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_IPXIP6_SEGMENTATION "feature-tx-ipxip6-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_NOCACHE_COPY "feature-tx-nocache-copy" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCATTER_GATHER "feature-tx-scatter-gather" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCATTER_GATHER_FRAGLIST "feature-tx-scatter-gather-fraglist" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCTP_SEGMENTATION "feature-tx-sctp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP6_SEGMENTATION "feature-tx-tcp6-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_ECN_SEGMENTATION "feature-tx-tcp-ecn-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_MANGLEID_SEGMENTATION "feature-tx-tcp-mangleid-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_SEGMENTATION "feature-tx-tcp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_SEGMENTATION "feature-tx-udp-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION "feature-tx-udp_tnl-csum-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_SEGMENTATION "feature-tx-udp_tnl-segmentation" +#define NM_ETHTOOL_OPTNAME_FEATURE_TX_VLAN_STAG_HW_INSERT "feature-tx-vlan-stag-hw-insert" + +gboolean nm_ethtool_optname_is_feature (const char *optname); + +/*****************************************************************************/ + +#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type ()) +#define NM_SETTING_ETHTOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtool)) +#define NM_SETTING_ETHTOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) +#define NM_IS_SETTING_ETHTOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_ETHTOOL)) +#define NM_IS_SETTING_ETHTOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_ETHTOOL)) +#define NM_SETTING_ETHTOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass)) + +#define NM_SETTING_ETHTOOL_SETTING_NAME "ethtool" + +/*****************************************************************************/ + +typedef struct _NMSettingEthtoolClass NMSettingEthtoolClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_ethtool_get_type (void); + +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_ethtool_new (void); + +/*****************************************************************************/ + +NM_AVAILABLE_IN_1_14 +NMTernary nm_setting_ethtool_get_feature (NMSettingEthtool *setting, + const char *optname); +NM_AVAILABLE_IN_1_14 +void nm_setting_ethtool_set_feature (NMSettingEthtool *setting, + const char *optname, + NMTernary value); +NM_AVAILABLE_IN_1_14 +void nm_setting_ethtool_clear_features (NMSettingEthtool *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_ETHTOOL_H__ */ diff --git a/libnm-core/nm-setting-generic.c b/libnm-core/nm-setting-generic.c index 96f26ac2..44402e39 100644 --- a/libnm-core/nm-setting-generic.c +++ b/libnm-core/nm-setting-generic.c @@ -36,9 +36,7 @@ * the "connection type" setting on #NMConnections for generic devices. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING, - _nm_register_setting (GENERIC, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GENERIC) +G_DEFINE_TYPE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING) #define NM_SETTING_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate)) @@ -67,7 +65,11 @@ nm_setting_generic_init (NMSettingGeneric *setting) } static void -nm_setting_generic_class_init (NMSettingGenericClass *setting_class) +nm_setting_generic_class_init (NMSettingGenericClass *klass) { - g_type_class_add_private (setting_class, sizeof (NMSettingGenericPrivate)); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMSettingGenericPrivate)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_GENERIC); } diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c index 3011d917..b31da689 100644 --- a/libnm-core/nm-setting-gsm.c +++ b/libnm-core/nm-setting-gsm.c @@ -38,9 +38,7 @@ * networks, including those using GPRS/EDGE and UMTS/HSPA technology. */ -G_DEFINE_TYPE_WITH_CODE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING, - _nm_register_setting (GSM, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GSM) +G_DEFINE_TYPE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING) #define NM_SETTING_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate)) @@ -604,22 +602,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_gsm_class_init (NMSettingGsmClass *setting_class) +nm_setting_gsm_class_init (NMSettingGsmClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingGsmPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingGsmPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; /** * NMSettingGsm:number: @@ -822,10 +819,18 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class) G_PARAM_STATIC_STRINGS)); /* Ignore incoming deprecated properties */ - _nm_setting_class_add_dbus_only_property (parent_class, "allowed-bands", - G_VARIANT_TYPE_UINT32, - NULL, NULL); - _nm_setting_class_add_dbus_only_property (parent_class, "network-type", - G_VARIANT_TYPE_INT32, - NULL, NULL); + _properties_override_add_dbus_only (properties_override, + "allowed-bands", + G_VARIANT_TYPE_UINT32, + NULL, + NULL); + + _properties_override_add_dbus_only (properties_override, + "network-type", + G_VARIANT_TYPE_INT32, + NULL, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_GSM, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c index 8c49849a..d5ae7085 100644 --- a/libnm-core/nm-setting-infiniband.c +++ b/libnm-core/nm-setting-infiniband.c @@ -37,9 +37,7 @@ * necessary for connection to IP-over-InfiniBand networks. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING, - _nm_register_setting (INFINIBAND, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_INFINIBAND) +G_DEFINE_TYPE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING) #define NM_SETTING_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate)) @@ -378,21 +376,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class) +nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingInfinibandPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingInfinibandPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; + setting_class->verify = verify; - /* Properties */ /** * NMSettingInfiniband:mac-address: * @@ -425,10 +422,13 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_INFINIBAND_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_INFINIBAND_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingInfiniband:mtu: @@ -526,4 +526,6 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_INFINIBAND, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index c7f8c555..fa2535b8 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -1391,7 +1391,7 @@ typedef struct { GPtrArray *dns; /* array of IP address strings */ GPtrArray *dns_search; /* array of domain name strings */ GPtrArray *dns_options;/* array of DNS options */ - gint dns_priority; + int dns_priority; GPtrArray *addresses; /* array of NMIPAddress */ GPtrArray *routes; /* array of NMIPRoute */ gint64 route_metric; @@ -1403,8 +1403,8 @@ typedef struct { gboolean dhcp_send_hostname; gboolean never_default; gboolean may_fail; - gint dad_timeout; - gint dhcp_timeout; + int dad_timeout; + int dhcp_timeout; } NMSettingIPConfigPrivate; enum { @@ -1589,8 +1589,11 @@ nm_setting_ip_config_clear_dns (NMSettingIPConfig *setting) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_ptr_array_set_size (priv->dns, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS); + + if (priv->dns->len != 0) { + g_ptr_array_set_size (priv->dns, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS); + } } /** @@ -1688,8 +1691,6 @@ nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting, int idx) * Removes the DNS search domain @dns_search. * * Returns: %TRUE if the DNS search domain was found and removed; %FALSE if it was not. - * - * Since 0.9.10 **/ gboolean nm_setting_ip_config_remove_dns_search_by_value (NMSettingIPConfig *setting, @@ -1727,8 +1728,11 @@ nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_ptr_array_set_size (priv->dns_search, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH); + + if (priv->dns_search->len != 0) { + g_ptr_array_set_size (priv->dns_search, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH); + } } /** @@ -1804,7 +1808,7 @@ nm_setting_ip_config_get_dns_option (NMSettingIPConfig *setting, guint idx) * * Since: 1.2 **/ -gint +int nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, guint idx) { NMSettingIPConfigPrivate *priv; @@ -1966,7 +1970,7 @@ nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_ * * Since: 1.4 **/ -gint +int nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting) { g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); @@ -2107,8 +2111,10 @@ nm_setting_ip_config_clear_addresses (NMSettingIPConfig *setting) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); - g_ptr_array_set_size (priv->addresses, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES); + if (priv->addresses->len != 0) { + g_ptr_array_set_size (priv->addresses, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES); + } } /** @@ -2264,8 +2270,10 @@ nm_setting_ip_config_clear_routes (NMSettingIPConfig *setting) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); - g_ptr_array_set_size (priv->routes, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES); + if (priv->routes->len != 0) { + g_ptr_array_set_size (priv->routes, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES); + } } /** @@ -2421,7 +2429,7 @@ nm_setting_ip_config_get_may_fail (NMSettingIPConfig *setting) * * Since: 1.2 **/ -gint +int nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig *setting) { g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); @@ -2441,7 +2449,7 @@ nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig *setting) * * Since: 1.2 **/ -gint +int nm_setting_ip_config_get_dhcp_timeout (NMSettingIPConfig *setting) { g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); @@ -2611,7 +2619,7 @@ compare_property (NMSetting *setting, NMSettingCompareFlags flags) { NMSettingIPConfigPrivate *a_priv, *b_priv; - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i; if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ADDRESSES)) { @@ -2640,9 +2648,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } /*****************************************************************************/ @@ -2869,22 +2876,37 @@ ip_gateway_set (NMSetting *setting, return TRUE; } +GArray * +_nm_sett_info_property_override_create_array_ip_config (void) +{ + nm_auto_unref_gtypeclass NMSettingClass *setting_class = g_type_class_ref (NM_TYPE_SETTING_IP_CONFIG); + GArray *properties_override = _nm_sett_info_property_override_create_array (); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_GATEWAY), + G_VARIANT_TYPE_STRING, + NULL, + ip_gateway_set, + NULL); + + return properties_override; +} + static void -nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) +nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingIPConfigPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingIPConfigPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->compare_property = compare_property; - /* Properties */ + setting_class->verify = verify; + setting_class->compare_property = compare_property; /** * NMSettingIPConfig:method: @@ -2905,7 +2927,9 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) * "link-local", these properties must be empty. * * For IPv4 method "shared", the IP subnet can be configured by adding one - * manual IPv4 address or otherwise 10.42.x.0/24 is chosen. + * manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the + * shared method must be configured on the interface which shares the internet + * to a subnet, not on the uplink which is shared. **/ g_object_class_install_property (object_class, PROP_METHOD, @@ -3034,13 +3058,6 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_IP_CONFIG_GATEWAY, - G_VARIANT_TYPE_STRING, - NULL, - ip_gateway_set, - NULL); - /** * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute)) * diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 8b3c85de..882a88b6 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -247,7 +247,7 @@ guint nm_setting_ip_config_get_num_dns_options (NMSettingIPConfig gboolean nm_setting_ip_config_has_dns_options (NMSettingIPConfig *setting); const char *nm_setting_ip_config_get_dns_option (NMSettingIPConfig *setting, guint idx); -gint nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, +int nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, guint idx); gboolean nm_setting_ip_config_add_dns_option (NMSettingIPConfig *setting, const char *dns_option); @@ -258,7 +258,7 @@ gboolean nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig void nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_set); NM_AVAILABLE_IN_1_4 -gint nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting); +int nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting); guint nm_setting_ip_config_get_num_addresses (NMSettingIPConfig *setting); NMIPAddress *nm_setting_ip_config_get_address (NMSettingIPConfig *setting, @@ -298,9 +298,9 @@ gboolean nm_setting_ip_config_get_dhcp_send_hostname (NMSettingIPConfig gboolean nm_setting_ip_config_get_never_default (NMSettingIPConfig *setting); gboolean nm_setting_ip_config_get_may_fail (NMSettingIPConfig *setting); NM_AVAILABLE_IN_1_2 -gint nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig *setting); +int nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig *setting); NM_AVAILABLE_IN_1_2 -gint nm_setting_ip_config_get_dhcp_timeout (NMSettingIPConfig *setting); +int nm_setting_ip_config_get_dhcp_timeout (NMSettingIPConfig *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index c9cb97df..41314f58 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -30,9 +30,7 @@ * @short_description: Describes connection properties for IP tunnel devices **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING, - _nm_register_setting (IP_TUNNEL, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP_TUNNEL) +G_DEFINE_TYPE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING) #define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate)) @@ -320,12 +318,14 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) case NM_IP_TUNNEL_MODE_ISATAP: case NM_IP_TUNNEL_MODE_GRE: case NM_IP_TUNNEL_MODE_VTI: + case NM_IP_TUNNEL_MODE_GRETAP: family = AF_INET; break; case NM_IP_TUNNEL_MODE_IP6IP6: case NM_IP_TUNNEL_MODE_IPIP6: case NM_IP_TUNNEL_MODE_IP6GRE: case NM_IP_TUNNEL_MODE_VTI6: + case NM_IP_TUNNEL_MODE_IP6GRETAP: family = AF_INET6; break; case NM_IP_TUNNEL_MODE_UNKNOWN: @@ -388,8 +388,11 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if ( (priv->input_key && priv->input_key[0]) || (priv->output_key && priv->output_key[0])) { - if ( priv->mode != NM_IP_TUNNEL_MODE_GRE - && priv->mode != NM_IP_TUNNEL_MODE_IP6GRE) { + if (!NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_GRE, + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -410,7 +413,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) priv->input_key); g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_INPUT_KEY); - return FALSE; + return FALSE; } } @@ -426,7 +429,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) priv->output_key); g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_OUTPUT_KEY); - return FALSE; + return FALSE; } } @@ -454,6 +457,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if ( nm_connection_get_setting_wired (connection) + && !NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("wired setting not allowed for mode %s"), + nm_utils_enum_to_str (nm_ip_tunnel_mode_get_type (), priv->mode)); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_MODE); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + return TRUE; } @@ -604,18 +621,18 @@ finalize (GObject *object) } static void -nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) +nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingIPTunnelPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingIPTunnelPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; + + setting_class->verify = verify; /** * NMSettingIPTunnel:parent: @@ -833,4 +850,6 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_IP_TUNNEL); } diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index 0c668d8c..19f1cc8d 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -50,9 +50,7 @@ * connection. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG, - _nm_register_setting (IP4_CONFIG, NM_SETTING_PRIORITY_IP)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP4_CONFIG) +G_DEFINE_TYPE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG) #define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate)) @@ -525,20 +523,19 @@ ip4_route_data_set (NMSetting *setting, } static void -nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) +nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass) { - NMSettingClass *setting_class = NM_SETTING_CLASS (ip4_class); - GObjectClass *object_class = G_OBJECT_CLASS (ip4_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config (); g_type_class_add_private (setting_class, sizeof (NMSettingIP4ConfigPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - setting_class->verify = verify; - /* properties */ + setting_class->verify = verify; /* ---ifcfg-rh--- * property: method @@ -721,7 +718,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * * The special values "mac" and "perm-mac" are supported, which use the * current or permanent MAC address of the device to generate a client identifier - * with type ethernet type (01). Currently, these options only work for ethernet + * with type ethernet (01). Currently, these options only work for ethernet * type of links. * * The special value "stable" is supported to generate a type 0 client identifier based @@ -747,7 +744,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) /* ---ifcfg-rh--- * property: dad-timeout - * variable: ACD_TIMEOUT, ARPING_WAIT + * variable: ACD_TIMEOUT(+), ARPING_WAIT * default: missing variable means global default (config override or zero) * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds * for ARPING_WAIT) for address conflict detection before configuring @@ -798,11 +795,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * integers) * ---end--- */ - _nm_setting_class_transform_property (setting_class, - NM_SETTING_IP_CONFIG_DNS, - G_VARIANT_TYPE ("au"), - ip4_dns_to_dbus, - ip4_dns_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_DNS), + G_VARIANT_TYPE ("au"), + ip4_dns_to_dbus, + ip4_dns_from_dbus); /* ---dbus--- * property: addresses @@ -819,18 +817,19 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * for that subnet. * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ADDRESSES, - G_VARIANT_TYPE ("aau"), - ip4_addresses_get, - ip4_addresses_set, - NULL); - - _nm_setting_class_add_dbus_only_property (setting_class, - "address-labels", - G_VARIANT_TYPE_STRING_ARRAY, - ip4_address_labels_get, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ADDRESSES), + G_VARIANT_TYPE ("aau"), + ip4_addresses_get, + ip4_addresses_set, + NULL); + + _properties_override_add_dbus_only (properties_override, + "address-labels", + G_VARIANT_TYPE_STRING_ARRAY, + ip4_address_labels_get, + NULL); /* ---dbus--- * property: address-data @@ -841,11 +840,11 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * also exist on some addresses. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "address-data", - G_VARIANT_TYPE ("aa{sv}"), - ip4_address_data_get, - ip4_address_data_set); + _properties_override_add_dbus_only (properties_override, + "address-data", + G_VARIANT_TYPE ("aa{sv}"), + ip4_address_data_get, + ip4_address_data_set); /* ---dbus--- * property: routes @@ -864,12 +863,13 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * property.) * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ROUTES, - G_VARIANT_TYPE ("aau"), - ip4_routes_get, - ip4_routes_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ROUTES), + G_VARIANT_TYPE ("aau"), + ip4_routes_get, + ip4_routes_set, + NULL); /* ---dbus--- * property: route-data @@ -884,10 +884,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * also exist on some routes. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "route-data", - G_VARIANT_TYPE ("aa{sv}"), - ip4_route_data_get, - ip4_route_data_set); - + _properties_override_add_dbus_only (properties_override, + "route-data", + G_VARIANT_TYPE ("aa{sv}"), + ip4_route_data_get, + ip4_route_data_set); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP4_CONFIG, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index 808c88a7..a55fd801 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -52,9 +52,7 @@ * supported. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG, - _nm_register_setting (IP6_CONFIG, NM_SETTING_PRIORITY_IP)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG) +G_DEFINE_TYPE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG) #define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate)) @@ -549,20 +547,19 @@ finalize (GObject *object) } static void -nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) +nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (ip6_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (ip6_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config (); - g_type_class_add_private (ip6_class, sizeof (NMSettingIP6ConfigPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingIP6ConfigPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - setting_class->verify = verify; + object_class->finalize = finalize; - /* Properties */ + setting_class->verify = verify; /* ---ifcfg-rh--- * property: method @@ -590,7 +587,7 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) /* ---ifcfg-rh--- * property: dns-search - * variable: IPV6_DOMAIN + * variable: IPV6_DOMAIN(+) * format: string (space-separated domains) * description: List of DNS search domains. * ---end--- @@ -891,11 +888,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * description: Array of IP addresses of DNS servers (in network byte order) * ---end--- */ - _nm_setting_class_transform_property (setting_class, - NM_SETTING_IP_CONFIG_DNS, - G_VARIANT_TYPE ("aay"), - ip6_dns_to_dbus, - ip6_dns_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_DNS), + G_VARIANT_TYPE ("aay"), + ip6_dns_to_dbus, + ip6_dns_from_dbus); /* ---dbus--- * property: addresses @@ -911,12 +909,13 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * that subnet. * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ADDRESSES, - G_VARIANT_TYPE ("a(ayuay)"), - ip6_addresses_get, - ip6_addresses_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ADDRESSES), + G_VARIANT_TYPE ("a(ayuay)"), + ip6_addresses_get, + ip6_addresses_set, + NULL); /* ---dbus--- * property: address-data @@ -927,11 +926,11 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * also exist on some addresses. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "address-data", - G_VARIANT_TYPE ("aa{sv}"), - ip6_address_data_get, - ip6_address_data_set); + _properties_override_add_dbus_only (properties_override, + "address-data", + G_VARIANT_TYPE ("aa{sv}"), + ip6_address_data_get, + ip6_address_data_set); /* ---dbus--- * property: routes @@ -947,12 +946,13 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * default metric for the device. * ---end--- */ - _nm_setting_class_override_property (setting_class, - NM_SETTING_IP_CONFIG_ROUTES, - G_VARIANT_TYPE ("a(ayuayu)"), - ip6_routes_get, - ip6_routes_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_IP_CONFIG_ROUTES), + G_VARIANT_TYPE ("a(ayuayu)"), + ip6_routes_get, + ip6_routes_set, + NULL); /* ---dbus--- * property: route-data @@ -967,9 +967,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * also exist on some routes. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "route-data", - G_VARIANT_TYPE ("aa{sv}"), - ip6_route_data_get, - ip6_route_data_set); + _properties_override_add_dbus_only (properties_override, + "route-data", + G_VARIANT_TYPE ("aa{sv}"), + ip6_route_data_get, + ip6_route_data_set); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP6_CONFIG, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c index 92ebafa6..2c7cff23 100644 --- a/libnm-core/nm-setting-macsec.c +++ b/libnm-core/nm-setting-macsec.c @@ -40,9 +40,7 @@ * necessary for connection to MACsec (IEEE 802.1AE) interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING, - _nm_register_setting (MACSEC, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACSEC) +G_DEFINE_TYPE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING) #define NM_SETTING_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate)) @@ -474,18 +472,19 @@ finalize (GObject *object) } static void -nm_setting_macsec_class_init (NMSettingMacsecClass *setting_class) +nm_setting_macsec_class_init (NMSettingMacsecClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingMacsecPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingMacsecPrivate)); object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->need_secrets = need_secrets; + + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; /** * NMSettingMacsec:parent: @@ -627,4 +626,6 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *setting_class) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MACSEC); } diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c index 6fea8b0d..1fc16116 100644 --- a/libnm-core/nm-setting-macvlan.c +++ b/libnm-core/nm-setting-macvlan.c @@ -39,9 +39,7 @@ * necessary for connection to macvlan interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING, - _nm_register_setting (MACVLAN, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACVLAN) +G_DEFINE_TYPE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING) #define NM_SETTING_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate)) @@ -260,20 +258,18 @@ finalize (GObject *object) } static void -nm_setting_macvlan_class_init (NMSettingMacvlanClass *setting_class) +nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingMacvlanPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingMacvlanPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingMacvlan:parent: @@ -342,4 +338,6 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MACVLAN); } diff --git a/libnm-core/nm-setting-match.c b/libnm-core/nm-setting-match.c new file mode 100644 index 00000000..0964c644 --- /dev/null +++ b/libnm-core/nm-setting-match.c @@ -0,0 +1,295 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-match.h" +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-match + * @short_description: Properties to match a connection with a device. + * @include: nm-setting-match.h + **/ + +/** + * NMSettingMatch: + * + * Match settings. + * + * Since: 1.14 + */ +struct _NMSettingMatch { + NMSetting parent; + GPtrArray *interface_name; +}; + +struct _NMSettingMatchClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE (NMSettingMatch, nm_setting_match, NM_TYPE_SETTING) + +NM_GOBJECT_PROPERTIES_DEFINE (NMSettingMatch, + PROP_INTERFACE_NAME, +); + +/*****************************************************************************/ + +/** + * nm_setting_match_get_num_interface_names: + * @setting: the #NMSettingMatch + * + * Returns: the number of configured interface names + * + * Since: 1.14 + **/ +guint +nm_setting_match_get_num_interface_names (NMSettingMatch *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), 0); + + return setting->interface_name->len; +} + +/** + * nm_setting_match_get_interface_name: + * @setting: the #NMSettingMatch + * @idx: index number of the DNS search domain to return + * + * Returns: the interface name at index @idx + * + * Since: 1.14 + **/ +const char * +nm_setting_match_get_interface_name (NMSettingMatch *setting, int idx) +{ + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL); + + g_return_val_if_fail (idx >= 0 && idx < setting->interface_name->len, NULL); + + return setting->interface_name->pdata[idx]; +} + +/** + * nm_setting_match_add_interface_name: + * @setting: the #NMSettingMatch + * @interface_name: the interface name to add + * + * Adds a new interface name to the setting. + * + * Since: 1.14 + **/ +void +nm_setting_match_add_interface_name (NMSettingMatch *setting, + const char *interface_name) +{ + g_return_if_fail (NM_IS_SETTING_MATCH (setting)); + g_return_if_fail (interface_name != NULL); + g_return_if_fail (interface_name[0] != '\0'); + + g_ptr_array_add (setting->interface_name, g_strdup (interface_name)); + _notify (setting, PROP_INTERFACE_NAME); +} + +/** + * nm_setting_match_remove_interface_name: + * @setting: the #NMSettingMatch + * @idx: index number of the interface name + * + * Removes the interface name at index @idx. + * + * Since: 1.14 + **/ +void +nm_setting_match_remove_interface_name (NMSettingMatch *setting, int idx) +{ + g_return_if_fail (NM_IS_SETTING_MATCH (setting)); + + g_return_if_fail (idx >= 0 && idx < setting->interface_name->len); + + g_ptr_array_remove_index (setting->interface_name, idx); + _notify (setting, PROP_INTERFACE_NAME); +} + +/** + * nm_setting_match_remove_interface_name_by_value: + * @setting: the #NMSettingMatch + * @interface_name: the interface name to remove + * + * Removes @interface_name. + * + * Returns: %TRUE if the interface name was found and removed; %FALSE if it was not. + * + * Since: 1.14 + **/ +gboolean +nm_setting_match_remove_interface_name_by_value (NMSettingMatch *setting, + const char *interface_name) +{ + guint i; + + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), FALSE); + g_return_val_if_fail (interface_name != NULL, FALSE); + g_return_val_if_fail (interface_name[0] != '\0', FALSE); + + for (i = 0; i < setting->interface_name->len; i++) { + if (nm_streq (interface_name, setting->interface_name->pdata[i])) { + g_ptr_array_remove_index (setting->interface_name, i); + _notify (setting, PROP_INTERFACE_NAME); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_match_clear_interface_names: + * @setting: the #NMSettingMatch + * + * Removes all configured interface names. + * + * Since: 1.14 + **/ +void +nm_setting_match_clear_interface_names (NMSettingMatch *setting) +{ + g_return_if_fail (NM_IS_SETTING_MATCH (setting)); + + if (setting->interface_name->len != 0) { + g_ptr_array_set_size (setting->interface_name, 0); + _notify (setting, PROP_INTERFACE_NAME); + } +} + +/** + * nm_setting_match_get_interface_names: + * @setting: the #NMSettingMatch + * + * Returns all the interface names. + * + * Returns: (transfer none): the configured interface names. + * + * Since: 1.14 + **/ +const char *const * +nm_setting_match_get_interface_names (NMSettingMatch *setting, guint *length) +{ + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL); + g_return_val_if_fail (length, NULL); + + NM_SET_OUT (length, setting->interface_name->len); + return (const char *const *) setting->interface_name->pdata; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingMatch *self = NM_SETTING_MATCH (object); + + switch (prop_id) { + case PROP_INTERFACE_NAME: + g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (self->interface_name)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingMatch *self = NM_SETTING_MATCH (object); + + switch (prop_id) { + case PROP_INTERFACE_NAME: + g_ptr_array_unref (self->interface_name); + self->interface_name = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_match_init (NMSettingMatch *setting) +{ + setting->interface_name = g_ptr_array_new_with_free_func (g_free); +} + +/** + * nm_setting_match_new: + * + * Creates a new #NMSettingMatch object with default values. + * + * Returns: (transfer full): the new empty #NMSettingMatch object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_match_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_MATCH, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingMatch *self = NM_SETTING_MATCH (object); + + g_ptr_array_unref (self->interface_name); + + G_OBJECT_CLASS (nm_setting_match_parent_class)->finalize (object); +} + +static void +nm_setting_match_class_init (NMSettingMatchClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + object_class->finalize = finalize; + object_class->get_property = get_property; + object_class->set_property = set_property; + + /** + * NMSettingMatch:interface-name + * + * A list of interface names to match. Each element is a shell wildcard + * pattern. When an element is prefixed with exclamation mark (!) the + * condition is inverted. + * + * A candidate interface name is considered matching when both these + * conditions are satisfied: (a) any of the elements not prefixed with '!' + * matches or there aren't such elements; (b) none of the elements + * prefixed with '!' match. + * + * Since: 1.14 + **/ + obj_properties[PROP_INTERFACE_NAME] = + g_param_spec_boxed (NM_SETTING_MATCH_INTERFACE_NAME, "", "", + G_TYPE_STRV, + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MATCH); +} diff --git a/libnm-core/nm-setting-match.h b/libnm-core/nm-setting-match.h new file mode 100644 index 00000000..a39feca2 --- /dev/null +++ b/libnm-core/nm-setting-match.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright 2018 Red Hat, Inc. + */ + +#ifndef NM_SETTING_MATCH_H +#define NM_SETTING_MATCH_H + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_MATCH (nm_setting_match_get_type ()) +#define NM_SETTING_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_MATCH, NMSettingMatch)) +#define NM_SETTING_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_MATCH, NMSettingMatchClass)) +#define NM_IS_SETTING_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_MATCH)) +#define NM_IS_SETTING_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_MATCH)) +#define NM_SETTING_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_MATCH, NMSettingMatchClass)) + +#define NM_SETTING_MATCH_SETTING_NAME "match" + +#define NM_SETTING_MATCH_INTERFACE_NAME "interface-name" + +typedef struct _NMSettingMatchClass NMSettingMatchClass; + + +NM_AVAILABLE_IN_1_14 +GType nm_setting_match_get_type (void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_match_new (void); + +NM_AVAILABLE_IN_1_14 +guint nm_setting_match_get_num_interface_names (NMSettingMatch *setting); +NM_AVAILABLE_IN_1_14 +const char *nm_setting_match_get_interface_name (NMSettingMatch *setting, int idx); +NM_AVAILABLE_IN_1_14 +void nm_setting_match_remove_interface_name (NMSettingMatch *setting, int idx); +NM_AVAILABLE_IN_1_14 +gboolean nm_setting_match_remove_interface_name_by_value (NMSettingMatch *setting, + const char *interface_name); +NM_AVAILABLE_IN_1_14 +void nm_setting_match_add_interface_name (NMSettingMatch *setting, + const char *interface_name); +NM_AVAILABLE_IN_1_14 +void nm_setting_match_clear_interface_names (NMSettingMatch *setting); +NM_AVAILABLE_IN_1_14 +const char *const *nm_setting_match_get_interface_names (NMSettingMatch *setting, guint *length); +G_END_DECLS + +#endif /* NM_SETTING_MATCH_H */ diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c index 783d143f..7f4a1bbf 100644 --- a/libnm-core/nm-setting-olpc-mesh.c +++ b/libnm-core/nm-setting-olpc-mesh.c @@ -39,9 +39,7 @@ static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting); -G_DEFINE_TYPE_WITH_CODE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING, - _nm_register_setting (OLPC_MESH, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OLPC_MESH) +G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) #define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) @@ -214,20 +212,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class) +nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingOlpcMeshPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingOlpcMesh:ssid: * @@ -268,8 +266,14 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_OLPC_MESH, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-ovs-bridge.c b/libnm-core/nm-setting-ovs-bridge.c index 4993d13f..9ca5566f 100644 --- a/libnm-core/nm-setting-ovs-bridge.c +++ b/libnm-core/nm-setting-ovs-bridge.c @@ -61,9 +61,7 @@ struct _NMSettingOvsBridgeClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING, - _nm_register_setting (OVS_BRIDGE, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_BRIDGE) +G_DEFINE_TYPE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING) /*****************************************************************************/ @@ -264,15 +262,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *setting_class) +nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsBridge:fail-mode: @@ -334,4 +333,6 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_BRIDGE); } diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c index ff9e4c1d..a177098d 100644 --- a/libnm-core/nm-setting-ovs-interface.c +++ b/libnm-core/nm-setting-ovs-interface.c @@ -54,9 +54,7 @@ struct _NMSettingOvsInterfaceClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING, - _nm_register_setting (OVS_INTERFACE, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_INTERFACE) +G_DEFINE_TYPE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING) /*****************************************************************************/ @@ -363,15 +361,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *setting_class) +nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsInterface:type: @@ -388,4 +387,6 @@ nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_INTERFACE); } diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c index 980015f2..15005eea 100644 --- a/libnm-core/nm-setting-ovs-patch.c +++ b/libnm-core/nm-setting-ovs-patch.c @@ -55,9 +55,7 @@ struct _NMSettingOvsPatchClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING, - _nm_register_setting (OVS_PATCH, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_PATCH) +G_DEFINE_TYPE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING) /*****************************************************************************/ @@ -182,15 +180,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *setting_class) +nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsPatch:peer: @@ -208,4 +207,6 @@ nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_PATCH); } diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c index b61df0ce..10e542e7 100644 --- a/libnm-core/nm-setting-ovs-port.c +++ b/libnm-core/nm-setting-ovs-port.c @@ -65,9 +65,7 @@ struct _NMSettingOvsPortClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING, - _nm_register_setting (OVS_PORT, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_PORT) +G_DEFINE_TYPE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING) /*****************************************************************************/ @@ -361,15 +359,16 @@ finalize (GObject *object) } static void -nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class) +nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingOvsPort:vlan-mode: @@ -467,4 +466,6 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_PORT); } diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c index 32900c84..7425da19 100644 --- a/libnm-core/nm-setting-ppp.c +++ b/libnm-core/nm-setting-ppp.c @@ -35,9 +35,7 @@ * cable and DSL modems and some mobile broadband devices. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING, - _nm_register_setting (PPP, NM_SETTING_PRIORITY_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPP) +G_DEFINE_TYPE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING) #define NM_SETTING_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate)) @@ -525,19 +523,18 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_ppp_class_init (NMSettingPppClass *setting_class) +nm_setting_ppp_class_init (NMSettingPppClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingPppPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingPppPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingPpp:noauth: * @@ -798,4 +795,6 @@ nm_setting_ppp_class_init (NMSettingPppClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PPP); } diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c index d7a1a0db..793d93ce 100644 --- a/libnm-core/nm-setting-pppoe.c +++ b/libnm-core/nm-setting-pppoe.c @@ -38,9 +38,7 @@ * to provide IP transport, for example cable or DSL modems. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING, - _nm_register_setting (PPPOE, NM_SETTING_PRIORITY_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPPOE) +G_DEFINE_TYPE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING) #define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate)) @@ -288,21 +286,20 @@ finalize (GObject *object) } static void -nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class) +nm_setting_pppoe_class_init (NMSettingPppoeClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingPppoePrivate)); + g_type_class_add_private (klass, sizeof (NMSettingPppoePrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->need_secrets = need_secrets; - /* Properties */ + setting_class->verify = verify; + setting_class->need_secrets = need_secrets; + /** * NMSettingPppoe:parent: * @@ -374,4 +371,6 @@ nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class) NM_SETTING_SECRET_FLAG_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PPPOE); } diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index 863ea9f3..1e25226e 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -31,18 +31,13 @@ #include "nm-core-internal.h" -void _nm_register_setting_impl (const char *name, - GType type, - NMSettingPriority priority); - -#define _nm_register_setting(name, priority) \ - G_STMT_START { \ - _nm_register_setting_impl ("" NM_SETTING_ ## name ## _SETTING_NAME "", g_define_type_id, priority); \ - } G_STMT_END +/*****************************************************************************/ NMSettingPriority _nm_setting_get_base_type_priority (NMSetting *setting); NMSettingPriority _nm_setting_type_get_base_type_priority (GType type); -gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b); +int _nm_setting_compare_priority (gconstpointer a, gconstpointer b); + +/*****************************************************************************/ typedef enum NMSettingUpdateSecretResult { NM_SETTING_UPDATE_SECRET_ERROR = FALSE, @@ -85,10 +80,7 @@ gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting, */ #define NM_SETTING_PARAM_REAPPLY_IMMEDIATELY (1 << (6 + G_PARAM_USER_SHIFT)) -/* Ensure the setting's GType is registered at library load time */ -#define NM_SETTING_REGISTER_TYPE(x) \ -static void __attribute__((constructor)) register_setting (void) \ -{ g_type_ensure (x); } +#define NM_SETTING_PARAM_GENDATA_BACKED (1 << (7 + G_PARAM_USER_SHIFT)) GVariant *_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting, NMConnection *connection, @@ -115,44 +107,78 @@ NMSetting *_nm_setting_new_from_dbus (GType setting_type, NMSettingParseFlags parse_flags, GError **error); -typedef GVariant * (*NMSettingPropertyGetFunc) (NMSetting *setting, - const char *property); -typedef GVariant * (*NMSettingPropertySynthFunc) (NMSetting *setting, - NMConnection *connection, - const char *property); -typedef gboolean (*NMSettingPropertySetFunc) (NMSetting *setting, - GVariant *connection_dict, - const char *property, - GVariant *value, - NMSettingParseFlags parse_flags, - GError **error); -typedef gboolean (*NMSettingPropertyNotSetFunc) (NMSetting *setting, - GVariant *connection_dict, - const char *property, - NMSettingParseFlags parse_flags, - GError **error); - -void _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertySynthFunc synth_func, - NMSettingPropertySetFunc set_func); - -void _nm_setting_class_override_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertyGetFunc get_func, - NMSettingPropertySetFunc set_func, - NMSettingPropertyNotSetFunc not_set_func); - -typedef GVariant * (*NMSettingPropertyTransformToFunc) (const GValue *from); -typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from, GValue *to); - -void _nm_setting_class_transform_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertyTransformToFunc to_dbus, - NMSettingPropertyTransformFromFunc from_dbus); +/*****************************************************************************/ + +static inline GArray * +_nm_sett_info_property_override_create_array (void) +{ + return g_array_new (FALSE, FALSE, sizeof (NMSettInfoProperty)); +} + +GArray *_nm_sett_info_property_override_create_array_ip_config (void); + +void _nm_setting_class_commit_full (NMSettingClass *setting_class, + NMMetaSettingType meta_type, + const NMSettInfoSettDetail *detail, + GArray *properties_override); + +static inline void +_nm_setting_class_commit (NMSettingClass *setting_class, + NMMetaSettingType meta_type) +{ + _nm_setting_class_commit_full (setting_class, meta_type, NULL, NULL); +} + +#define NM_SETT_INFO_SETT_GENDATA(...) \ + ({ \ + static const NMSettInfoSettGendata _g = { \ + __VA_ARGS__ \ + }; \ + \ + &_g; \ + }) + +#define NM_SETT_INFO_SETT_DETAIL(...) \ + (&((const NMSettInfoSettDetail) { \ + __VA_ARGS__ \ + })) + +#define NM_SETT_INFO_PROPERTY(...) \ + (&((const NMSettInfoProperty) { \ + __VA_ARGS__ \ + })) + +void _properties_override_add_struct (GArray *properties_override, + const NMSettInfoProperty *prop_info); + +void _properties_override_add__helper (GArray *properties_override, + NMSettInfoProperty *prop_info); + +#define _properties_override_add(properties_override, \ + ...) \ + (_properties_override_add_struct (properties_override, \ + NM_SETT_INFO_PROPERTY (__VA_ARGS__))) + +void _properties_override_add_dbus_only (GArray *properties_override, + const char *property_name, + const GVariantType *dbus_type, + NMSettingPropertySynthFunc synth_func, + NMSettingPropertySetFunc set_func); + +void _properties_override_add_override (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyGetFunc get_func, + NMSettingPropertySetFunc set_func, + NMSettingPropertyNotSetFunc not_set_func); + +void _properties_override_add_transform (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyTransformToFunc to_dbus, + NMSettingPropertyTransformFromFunc from_dbus); + +/*****************************************************************************/ gboolean _nm_setting_use_legacy_property (NMSetting *setting, GVariant *connection_dict, @@ -161,4 +187,6 @@ gboolean _nm_setting_use_legacy_property (NMSetting *setting, GPtrArray *_nm_setting_need_secrets (NMSetting *setting); +/*****************************************************************************/ + #endif /* NM_SETTING_PRIVATE_H */ diff --git a/libnm-core/nm-setting-proxy.c b/libnm-core/nm-setting-proxy.c index 58a22080..d544c7fa 100644 --- a/libnm-core/nm-setting-proxy.c +++ b/libnm-core/nm-setting-proxy.c @@ -39,9 +39,7 @@ * to fulfill client queries. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING, - _nm_register_setting (PROXY, NM_SETTING_PRIORITY_IP)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PROXY) +G_DEFINE_TYPE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING) #define NM_SETTING_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate)) @@ -285,18 +283,18 @@ set_property (GObject *object, guint prop_id, } static void -nm_setting_proxy_class_init (NMSettingProxyClass *setting_class) +nm_setting_proxy_class_init (NMSettingProxyClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingProxyPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingProxyPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->finalize = finalize; + + setting_class->verify = verify; /** * NMSettingProxy:method: @@ -384,4 +382,6 @@ nm_setting_proxy_class_init (NMSettingProxyClass *setting_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PROXY); } diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c index e86988b5..b173197d 100644 --- a/libnm-core/nm-setting-serial.c +++ b/libnm-core/nm-setting-serial.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2011 Red Hat, Inc. + * Copyright 2007 - 2018 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -37,9 +37,7 @@ * such as mobile broadband or analog telephone connections. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING, - _nm_register_setting (SERIAL, NM_SETTING_PRIORITY_HW_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_SERIAL) +G_DEFINE_TYPE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING) #define NM_SETTING_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate)) @@ -145,12 +143,6 @@ nm_setting_serial_get_send_delay (NMSettingSerial *setting) return NM_SETTING_SERIAL_GET_PRIVATE (setting)->send_delay; } -static gboolean -verify (NMSetting *setting, NMConnection *connection, GError **error) -{ - return TRUE; -} - static void nm_setting_serial_init (NMSettingSerial *setting) { @@ -244,19 +236,16 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_serial_class_init (NMSettingSerialClass *setting_class) +nm_setting_serial_class_init (NMSettingSerialClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingSerialPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingSerialPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - parent_class->verify = verify; - - /* Properties */ /** * NMSettingSerial:baud: @@ -314,11 +303,13 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_SERIAL_PARITY, - G_VARIANT_TYPE_BYTE, - parity_to_dbus, - parity_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_SERIAL_PARITY), + G_VARIANT_TYPE_BYTE, + parity_to_dbus, + parity_from_dbus); /** * NMSettingSerial:stopbits: @@ -346,4 +337,7 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_SERIAL, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c new file mode 100644 index 00000000..45b3a1d2 --- /dev/null +++ b/libnm-core/nm-setting-sriov.c @@ -0,0 +1,1357 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-sriov.h" +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-sriov + * @short_description: Describes SR-IOV connection properties + * @include: nm-setting-sriov.h + **/ + +/** + * NMSettingSriov: + * + * SR-IOV settings. + * + * Since: 1.14 + */ +struct _NMSettingSriov { + NMSetting parent; + GPtrArray *vfs; + guint total_vfs; + NMTernary autoprobe_drivers; +}; + +struct _NMSettingSriovClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE (NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING) + +enum { + PROP_0, + PROP_TOTAL_VFS, + PROP_VFS, + PROP_AUTOPROBE_DRIVERS, + + LAST_PROP +}; + +/*****************************************************************************/ + +G_DEFINE_BOXED_TYPE (NMSriovVF, nm_sriov_vf, nm_sriov_vf_dup, nm_sriov_vf_unref) + +struct _NMSriovVF { + guint refcount; + guint index; + GHashTable *attributes; + GHashTable *vlans; + guint *vlan_ids; +}; + +typedef struct { + guint id; + guint qos; + NMSriovVFVlanProtocol protocol; +} VFVlan; + +static guint +_vf_vlan_hash (gconstpointer ptr) +{ + return nm_hash_val (1348254767u, *((guint *) ptr)); +} + +static gboolean +_vf_vlan_equal (gconstpointer a, gconstpointer b) +{ + return *((guint *) a) == *((guint *) b); +} + +static GHashTable * +_vf_vlan_create_hash (void) +{ + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (VFVlan, id) == 0); + return g_hash_table_new_full (_vf_vlan_hash, + _vf_vlan_equal, + NULL, + nm_g_slice_free_fcn (VFVlan)); +} + +/** + * nm_srio_vf_new: + * @index: the VF index + * + * Creates a new #NMSriovVF object. + * + * Returns: (transfer full): the new #NMSriovVF object. + * + * Since: 1.14 + **/ +NMSriovVF * +nm_sriov_vf_new (guint index) +{ + NMSriovVF *vf; + + vf = g_slice_new0 (NMSriovVF); + vf->refcount = 1; + vf->index = index; + vf->attributes = g_hash_table_new_full (nm_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_variant_unref); + return vf; +} + +/** + * nm_sriov_vf_ref: + * @vf: the #NMSriovVF + * + * Increases the reference count of the object. + * + * Since: 1.14 + **/ +void +nm_sriov_vf_ref (NMSriovVF *vf) +{ + g_return_if_fail (vf); + g_return_if_fail (vf->refcount > 0); + + vf->refcount++; +} + +/** + * nm_sriov_vf_unref: + * @vf: the #NMSriovVF + * + * Decreases the reference count of the object. If the reference count + * reaches zero, the object will be destroyed. + * + * Since: 1.14 + **/ +void +nm_sriov_vf_unref (NMSriovVF *vf) +{ + g_return_if_fail (vf); + g_return_if_fail (vf->refcount > 0); + + vf->refcount--; + if (vf->refcount == 0) { + g_hash_table_unref (vf->attributes); + if (vf->vlans) + g_hash_table_unref (vf->vlans); + g_free (vf->vlan_ids); + g_slice_free (NMSriovVF, vf); + } +} + +/** + * nm_sriov_vf_equal: + * @vf: the #NMSriovVF + * @other: the #NMSriovVF to compare @vf to. + * + * Determines if two #NMSriovVF objects have the same index, + * attributes and VLANs. + * + * Returns: %TRUE if the objects contain the same values, %FALSE + * if they do not. + * + * Since: 1.14 + **/ +gboolean +nm_sriov_vf_equal (const NMSriovVF *vf, const NMSriovVF *other) +{ + GHashTableIter iter; + const char *key; + GVariant *value, *value2; + VFVlan *vlan, *vlan2; + guint n_vlans; + + g_return_val_if_fail (vf, FALSE); + g_return_val_if_fail (vf->refcount > 0, FALSE); + g_return_val_if_fail (other, FALSE); + g_return_val_if_fail (other->refcount > 0, FALSE); + + if (vf == other) + return TRUE; + + if (vf->index != other->index) + return FALSE; + + if (g_hash_table_size (vf->attributes) != g_hash_table_size (other->attributes)) + return FALSE; + g_hash_table_iter_init (&iter, vf->attributes); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { + value2 = g_hash_table_lookup (other->attributes, key); + if (!value2) + return FALSE; + if (!g_variant_equal (value, value2)) + return FALSE; + } + + n_vlans = vf->vlans ? g_hash_table_size (vf->vlans) : 0u; + if (n_vlans != (other->vlans ? g_hash_table_size (other->vlans) : 0u)) + return FALSE; + if (n_vlans > 0) { + g_hash_table_iter_init (&iter, vf->vlans); + while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) { + vlan2 = g_hash_table_lookup (other->vlans, vlan); + if (!vlan2) + return FALSE; + if ( vlan->qos != vlan2->qos + || vlan->protocol != vlan2->protocol) + return FALSE; + } + } + + return TRUE; +} + +static void +vf_add_vlan (NMSriovVF *vf, + guint vlan_id, + guint qos, + NMSriovVFVlanProtocol protocol) +{ + VFVlan *vlan; + + vlan = g_slice_new0 (VFVlan); + vlan->id = vlan_id; + vlan->qos = qos; + vlan->protocol = protocol; + + if (!vf->vlans) + vf->vlans = _vf_vlan_create_hash (); + + g_hash_table_add (vf->vlans, vlan); + g_clear_pointer (&vf->vlan_ids, g_free); +} + +/** + * nm_sriov_vf_dup: + * @vf: the #NMSriovVF + * + * Creates a copy of @vf. + * + * Returns: (transfer full): a copy of @vf + * + * Since: 1.14 + **/ +NMSriovVF * +nm_sriov_vf_dup (const NMSriovVF *vf) +{ + NMSriovVF *copy; + GHashTableIter iter; + const char *name; + GVariant *variant; + VFVlan *vlan; + + g_return_val_if_fail (vf, NULL); + g_return_val_if_fail (vf->refcount > 0, NULL); + + copy = nm_sriov_vf_new (vf->index); + + g_hash_table_iter_init (&iter, vf->attributes); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) + nm_sriov_vf_set_attribute (copy, name, variant); + + if (vf->vlans) { + g_hash_table_iter_init (&iter, vf->vlans); + while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) + vf_add_vlan (copy, vlan->id, vlan->qos, vlan->protocol); + } + + return copy; +} + +/** + * nm_sriov_vf_get_index: + * @vf: the #NMSriovVF + * + * Gets the index property of this VF object. + * + * Returns: the VF index + * + * Since: 1.14 + **/ +guint +nm_sriov_vf_get_index (const NMSriovVF *vf) +{ + g_return_val_if_fail (vf, 0); + g_return_val_if_fail (vf->refcount > 0, 0); + + return vf->index; +} + +/** + * nm_sriov_vf_set_attribute: + * @vf: the #NMSriovVF + * @name: the name of a route attribute + * @value: (transfer none) (allow-none): the value + * + * Sets the named attribute on @vf to the given value. + * + * Since: 1.14 + **/ +void +nm_sriov_vf_set_attribute (NMSriovVF *vf, const char *name, GVariant *value) +{ + g_return_if_fail (vf); + g_return_if_fail (vf->refcount > 0); + g_return_if_fail (name && *name != '\0'); + g_return_if_fail (!nm_streq (name, "index")); + + if (value) { + g_hash_table_insert (vf->attributes, + g_strdup (name), + g_variant_ref_sink (value)); + } else + g_hash_table_remove (vf->attributes, name); +} + +/** + * nm_sriov_vf_get_attribute_names: + * @vf: the #NMSriovVF + * + * Gets an array of attribute names defined on @vf. + * + * Returns: (transfer container): a %NULL-terminated array of attribute names + * + * Since: 1.14 + **/ +const char ** +nm_sriov_vf_get_attribute_names (const NMSriovVF *vf) +{ + g_return_val_if_fail (vf, NULL); + g_return_val_if_fail (vf->refcount > 0, NULL); + + return nm_utils_strdict_get_keys (vf->attributes, TRUE, NULL); +} + +/** + * nm_sriov_vf_get_attribute: + * @vf: the #NMSriovVF + * @name: the name of a VF attribute + * + * Gets the value of the attribute with name @name on @vf + * + * Returns: (transfer none): the value of the attribute with name @name on + * @vf, or %NULL if @vf has no such attribute. + * + * Since: 1.14 + **/ +GVariant * +nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name) +{ + g_return_val_if_fail (vf, NULL); + g_return_val_if_fail (vf->refcount > 0, NULL); + g_return_val_if_fail (name && *name != '\0', NULL); + + return g_hash_table_lookup (vf->attributes, name); +} + +#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \ + &(NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type } + +const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = { + SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'), + SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, 0), + SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, 0), + SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, 0), + SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, 0), + /* D-Bus only, synthetic attributes */ + SRIOV_ATTR_SPEC_PTR ("vlans", G_VARIANT_TYPE_STRING, 'd'), + NULL, +}; + +/** + * nm_sriov_vf_attribute_validate: + * @name: the attribute name + * @value: the attribute value + * @known: (out): on return, whether the attribute name is a known one + * @error: (allow-none): return location for a #GError, or %NULL + * + * Validates a VF attribute, i.e. checks that the attribute is a known one, + * the value is of the correct type and well-formed. + * + * Returns: %TRUE if the attribute is valid, %FALSE otherwise + * + * Since: 1.14 + */ +gboolean +nm_sriov_vf_attribute_validate (const char *name, + GVariant *value, + gboolean *known, + GError **error) +{ + const NMVariantAttributeSpec *const *iter; + const NMVariantAttributeSpec *spec = NULL; + + g_return_val_if_fail (name, FALSE); + g_return_val_if_fail (value, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + + for (iter = _nm_sriov_vf_attribute_spec; *iter; iter++) { + if (nm_streq (name, (*iter)->name)) { + spec = *iter; + break; + } + } + + if (!spec || spec->str_type == 'd') { + NM_SET_OUT (known, FALSE); + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("unknown attribute")); + return FALSE; + } + + NM_SET_OUT (known, TRUE); + + if (!g_variant_is_of_type (value, spec->type)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid attribute type '%s'"), + g_variant_get_type_string (value)); + return FALSE; + } + + if (spec->type == G_VARIANT_TYPE_STRING) { + const char *string; + + switch (spec->str_type) { + case 'm': /* MAC address */ + string = g_variant_get_string (value, NULL); + if (!nm_utils_hwaddr_valid (string, -1)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("'%s' is not a valid MAC address"), + string); + return FALSE; + } + break; + default: + break; + } + } + + return TRUE; +} + +gboolean +_nm_sriov_vf_attribute_validate_all (const NMSriovVF *vf, GError **error) +{ + GHashTableIter iter; + const char *name; + GVariant *variant; + GVariant *min, *max; + + g_return_val_if_fail (vf, FALSE); + g_return_val_if_fail (vf->refcount > 0, FALSE); + + g_hash_table_iter_init (&iter, vf->attributes); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) { + if (!nm_sriov_vf_attribute_validate (name, variant, NULL, error)) { + g_prefix_error (error, "attribute '%s':", name); + return FALSE; + } + } + + min = g_hash_table_lookup (vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE); + max = g_hash_table_lookup (vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE); + if ( min + && max + && g_variant_get_uint32 (min) > g_variant_get_uint32 (max)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "min_tx_rate is greater than max_tx_rate"); + return FALSE; + } + + return TRUE; +} + +/** + * nm_sriov_vf_add_vlan: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Adds a VLAN to the VF. + * + * Returns: %TRUE if the VLAN was added; %FALSE if it already existed + * + * Since: 1.14 + **/ +gboolean +nm_sriov_vf_add_vlan (NMSriovVF *vf, guint vlan_id) +{ + g_return_val_if_fail (vf, FALSE); + g_return_val_if_fail (vf->refcount > 0, FALSE); + + if ( vf->vlans + && g_hash_table_contains (vf->vlans, &vlan_id)) + return FALSE; + + vf_add_vlan (vf, vlan_id, 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + + return TRUE; +} + +/** + * nm_sriov_vf_remove_vlan: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Removes a VLAN from a VF. + * + * Returns: %TRUE if the VLAN was removed, %FALSE if the VLAN @vlan_id + * did not belong to the VF. + * + * Since: 1.14 + */ +gboolean +nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id) +{ + g_return_val_if_fail (vf, FALSE); + g_return_val_if_fail (vf->refcount > 0, FALSE); + + if ( !vf->vlans + || !g_hash_table_remove (vf->vlans, &vlan_id)) + return FALSE; + + g_clear_pointer (&vf->vlan_ids, g_free); + return TRUE; +} + +static int +vlan_id_compare (gconstpointer a, gconstpointer b, gpointer user_data) +{ + guint id_a = *(guint *) a; + guint id_b = *(guint *) b; + + if (id_a < id_b) + return -1; + else if (id_a > id_b) + return 1; + else return 0; +} + +/** + * nm_sriov_vf_get_vlan_ids: + * @vf: the #NMSriovVF + * @length: (out) (allow-none): on return, the number of VLANs configured + * + * Returns the VLANs currently configured on the VF. + * + * Returns: (transfer none): a list of VLAN ids configured on the VF. + * + * Since: 1.14 + */ +const guint * +nm_sriov_vf_get_vlan_ids (const NMSriovVF *vf, guint *length) +{ + GHashTableIter iter; + VFVlan *vlan; + guint num, i; + + g_return_val_if_fail (vf, NULL); + g_return_val_if_fail (vf->refcount > 0, NULL); + + num = vf->vlans ? g_hash_table_size (vf->vlans) : 0u; + NM_SET_OUT (length, num); + + if (vf->vlan_ids) + return vf->vlan_ids; + if (num == 0) + return NULL; + + /* vf is const, however, vlan_ids is a mutable field caching the + * result ("mutable" in C++ terminology) */ + ((NMSriovVF *) vf)->vlan_ids = g_new0 (guint, num); + + i = 0; + g_hash_table_iter_init (&iter, vf->vlans); + while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) + vf->vlan_ids[i++] = vlan->id; + + nm_assert (num == i); + + g_qsort_with_data (vf->vlan_ids, num, sizeof (guint), vlan_id_compare, NULL); + + return vf->vlan_ids; +} + +/** + * nm_sriov_vf_set_vlan_qos: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * @qos: a QoS (priority) value + * + * Sets a QoS value for the given VLAN. + * + * Since: 1.14 + */ +void +nm_sriov_vf_set_vlan_qos (NMSriovVF *vf, guint vlan_id, guint32 qos) +{ + VFVlan *vlan; + + g_return_if_fail (vf); + g_return_if_fail (vf->refcount > 0); + + if ( !vf->vlans + || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) + g_return_if_reached (); + + vlan->qos = qos; +} + +/** + * nm_sriov_vf_set_vlan_protocol: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * @protocol: the VLAN protocol + * + * Sets the protocol for the given VLAN. + * + * Since: 1.14 + */ +void +nm_sriov_vf_set_vlan_protocol (NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol) +{ + VFVlan *vlan; + + g_return_if_fail (vf); + g_return_if_fail (vf->refcount > 0); + + if ( !vf->vlans + || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) + g_return_if_reached (); + + vlan->protocol = protocol; +} + +/** + * nm_sriov_vf_get_vlan_qos: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Returns the QoS value for the given VLAN. + * + * Returns: the QoS value + * + * Since: 1.14 + */ +guint32 +nm_sriov_vf_get_vlan_qos (const NMSriovVF *vf, guint vlan_id) +{ + VFVlan *vlan; + + g_return_val_if_fail (vf, 0); + g_return_val_if_fail (vf->refcount > 0, 0); + + if ( !vf->vlans + || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) + g_return_val_if_reached (0); + + return vlan->qos; +} + +/* + * nm_sriov_vf_get_vlan_protocol: + * @vf: the #NMSriovVF + * @vlan_id: the VLAN id + * + * Returns the configured protocol for the given VLAN. + * + * Returns: the configured protocol + * + * Since: 1.14 + */ +NMSriovVFVlanProtocol +nm_sriov_vf_get_vlan_protocol (const NMSriovVF *vf, guint vlan_id) +{ + VFVlan *vlan; + + g_return_val_if_fail (vf, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_return_val_if_fail (vf->refcount > 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + + if ( !vf->vlans + || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id))) + g_return_val_if_reached (NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + + return vlan->protocol; +} + +/*****************************************************************************/ + +/** + * nm_setting_sriov_new: + * + * Creates a new #NMSettingSriov object with default values. + * + * Returns: (transfer full): the new empty #NMSettingSriov object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_sriov_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_SRIOV, NULL); +} + +/** + * nm_setting_sriov_get_total_vfs: + * @setting: the #NMSettingSriov + * + * Returns the value contained in the #NMSettingSriov:total-vfs + * property. + * + * Returns: the total number of SR-IOV virtual functions to create + * + * Since: 1.14 + **/ +guint +nm_setting_sriov_get_total_vfs (NMSettingSriov *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), 0); + + return setting->total_vfs; +} + +/** + * nm_setting_sriov_get_num_vfs: + * @setting: the #NMSettingSriov + * + * Returns: the number of configured VFs + * + * Since: 1.14 + **/ +guint +nm_setting_sriov_get_num_vfs (NMSettingSriov *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), 0); + + return setting->vfs->len; +} + +/** + * nm_setting_sriov_get_vf: + * @setting: the #NMSettingSriov + * @idx: index number of the VF to return + * + * Returns: (transfer none): the VF at index @idx + * + * Since: 1.14 + **/ +NMSriovVF * +nm_setting_sriov_get_vf (NMSettingSriov *setting, guint idx) +{ + g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), NULL); + g_return_val_if_fail (idx < setting->vfs->len, NULL); + + return setting->vfs->pdata[idx]; +} + +/** + * nm_setting_sriov_add_vf: + * @setting: the #NMSettingSriov + * @vf: the VF to add + * + * Appends a new VF and associated information to the setting. The + * given VF is duplicated internally and is not changed by this function. + * + * Since: 1.14 + **/ +void +nm_setting_sriov_add_vf (NMSettingSriov *setting, NMSriovVF *vf) +{ + g_return_if_fail (NM_IS_SETTING_SRIOV (setting)); + g_return_if_fail (vf); + g_return_if_fail (vf->refcount > 0); + + g_ptr_array_add (setting->vfs, nm_sriov_vf_dup (vf)); + g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); +} + +/** + * nm_setting_sriov_remove_vf: + * @setting: the #NMSettingSriov + * @idx: index number of the VF + * + * Removes the VF at index @idx. + * + * Since: 1.14 + **/ +void +nm_setting_sriov_remove_vf (NMSettingSriov *setting, guint idx) +{ + g_return_if_fail (NM_IS_SETTING_SRIOV (setting)); + g_return_if_fail (idx < setting->vfs->len); + + g_ptr_array_remove_index (setting->vfs, idx); + g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); +} + +/** + * nm_setting_sriov_remove_vf_by_index: + * @setting: the #NMSettingSriov + * @index: the VF index of the VF to remove + * + * Removes the VF with VF index @index. + * + * Returns: %TRUE if the VF was found and removed; %FALSE if it was not + * + * Since: 1.14 + **/ +gboolean +nm_setting_sriov_remove_vf_by_index (NMSettingSriov *setting, + guint index) +{ + guint i; + + g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), FALSE); + + for (i = 0; i < setting->vfs->len; i++) { + if (nm_sriov_vf_get_index (setting->vfs->pdata[i]) == index) { + g_ptr_array_remove_index (setting->vfs, i); + g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_sriov_clear_vfs: + * @setting: the #NMSettingSriov + * + * Removes all configured VFs. + * + * Since: 1.14 + **/ +void +nm_setting_sriov_clear_vfs (NMSettingSriov *setting) +{ + g_return_if_fail (NM_IS_SETTING_SRIOV (setting)); + + if (setting->vfs->len != 0) { + g_ptr_array_set_size (setting->vfs, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS); + } +} + +/** + * nm_setting_sriov_get_autoprobe_drivers: + * @setting: the #NMSettingSriov + * + * Returns the value contained in the #NMSettingSriov:autoprobe-drivers + * property. + * + * Returns: the autoprobe-drivers property value + * + * Since: 1.14 + **/ +NMTernary +nm_setting_sriov_get_autoprobe_drivers (NMSettingSriov *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), NM_TERNARY_DEFAULT); + + return setting->autoprobe_drivers; +} + +static gint +vf_index_compare (gconstpointer a, gconstpointer b) +{ + NMSriovVF *vf_a = *(NMSriovVF **) a; + NMSriovVF *vf_b = *(NMSriovVF **) b; + + if (vf_a->index < vf_b->index) + return -1; + else if (vf_a->index > vf_b->index) + return 1; + else + return 0; +} + +gboolean +_nm_setting_sriov_sort_vfs (NMSettingSriov *setting) +{ + gboolean need_sort = FALSE; + guint i; + + for (i = 1; i < setting->vfs->len; i++) { + NMSriovVF *vf_prev = setting->vfs->pdata[i - 1]; + NMSriovVF *vf = setting->vfs->pdata[i]; + + if (vf->index <= vf_prev->index) { + need_sort = TRUE; + break; + } + } + + if (need_sort) + g_ptr_array_sort (setting->vfs, vf_index_compare); + + return need_sort; +} + +/*****************************************************************************/ + +static GVariant * +vfs_to_dbus (NMSetting *setting, const char *property) +{ + gs_unref_ptrarray GPtrArray *vfs = NULL; + GVariantBuilder builder; + guint i; + + g_object_get (setting, NM_SETTING_SRIOV_VFS, &vfs, NULL); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); + + if (vfs) { + for (i = 0; i < vfs->len; i++) { + gs_free const char **attr_names = NULL; + NMSriovVF *vf = vfs->pdata[i]; + GVariantBuilder vf_builder; + const guint *vlan_ids; + const char **name; + guint num_vlans; + + g_variant_builder_init (&vf_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add (&vf_builder, "{sv}", "index", + g_variant_new_uint32 (nm_sriov_vf_get_index (vf))); + + attr_names = nm_utils_strdict_get_keys (vf->attributes, TRUE, NULL); + if (attr_names) { + for (name = attr_names; *name; name++) { + g_variant_builder_add (&vf_builder, + "{sv}", + *name, + nm_sriov_vf_get_attribute (vf, *name)); + } + } + + /* VLANs are translated into an array of maps, where each map has + * keys 'id', 'qos' and 'proto'. This guarantees enough flexibility + * to accomodate any future new option. */ + vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans); + if (num_vlans) { + GVariantBuilder vlans_builder; + guint j; + + g_variant_builder_init (&vlans_builder, G_VARIANT_TYPE ("aa{sv}")); + for (j = 0; j < num_vlans; j++) { + GVariantBuilder vlan_builder; + + g_variant_builder_init (&vlan_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&vlan_builder, + "{sv}", "id", + g_variant_new_uint32 (vlan_ids[j])); + g_variant_builder_add (&vlan_builder, + "{sv}", "qos", + g_variant_new_uint32 (nm_sriov_vf_get_vlan_qos (vf, + vlan_ids[j]))); + g_variant_builder_add (&vlan_builder, + "{sv}", "protocol", + g_variant_new_uint32 (nm_sriov_vf_get_vlan_protocol (vf, + vlan_ids[j]))); + g_variant_builder_add (&vlans_builder, + "a{sv}", + &vlan_builder); + } + g_variant_builder_add (&vf_builder , "{sv}", "vlans", g_variant_builder_end (&vlans_builder)); + } + g_variant_builder_add (&builder, "a{sv}", &vf_builder); + } + } + + return g_variant_builder_end (&builder); +} + +static gboolean +vfs_from_dbus (NMSetting *setting, + GVariant *connection_dict, + const char *property, + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) +{ + GPtrArray *vfs; + GVariantIter vf_iter; + GVariant *vf_var; + + g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE); + + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + g_variant_iter_init (&vf_iter, value); + while (g_variant_iter_next (&vf_iter, "@a{sv}", &vf_var)) { + NMSriovVF *vf; + guint32 index; + GVariantIter attr_iter; + const char *attr_name; + GVariant *attr_var, *vlans_var; + + if (!g_variant_lookup (vf_var, "index", "u", &index)) + goto next; + + vf = nm_sriov_vf_new (index); + + g_variant_iter_init (&attr_iter, vf_var); + while (g_variant_iter_next (&attr_iter, "{&sv}", &attr_name, &attr_var)) { + if (!NM_IN_STRSET (attr_name, "index", "vlans")) + nm_sriov_vf_set_attribute (vf, attr_name, attr_var); + g_variant_unref (attr_var); + } + + if (g_variant_lookup (vf_var, "vlans", "@aa{sv}", &vlans_var)) { + GVariantIter vlan_iter; + GVariant *vlan_var; + + g_variant_iter_init (&vlan_iter, vlans_var); + while (g_variant_iter_next (&vlan_iter, "@a{sv}", &vlan_var)) { + NMSriovVFVlanProtocol proto = NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q; + gint64 vlan_id = -1; + guint qos = 0; + + g_variant_iter_init (&attr_iter, vlan_var); + while (g_variant_iter_next (&attr_iter, "{&sv}", &attr_name, &attr_var)) { + if ( nm_streq (attr_name, "id") + && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32)) + vlan_id = g_variant_get_uint32 (attr_var); + else if ( nm_streq (attr_name, "qos") + && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32)) + qos = g_variant_get_uint32 (attr_var); + else if ( nm_streq (attr_name, "protocol") + && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32)) + proto = g_variant_get_uint32 (attr_var); + g_variant_unref (attr_var); + } + if (vlan_id != -1) + vf_add_vlan (vf, vlan_id, qos, proto); + g_variant_unref (vlan_var); + } + g_variant_unref (vlans_var); + } + + g_ptr_array_add (vfs, vf); +next: + g_variant_unref (vf_var); + } + + g_object_set (setting, NM_SETTING_SRIOV_VFS, vfs, NULL); + g_ptr_array_unref (vfs); + + return TRUE; +} + +/*****************************************************************************/ + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingSriov *self = NM_SETTING_SRIOV (setting); + guint i; + + if (self->vfs->len) { + gs_unref_hashtable GHashTable *h = NULL; + + h = g_hash_table_new (nm_direct_hash, NULL); + for (i = 0; i < self->vfs->len; i++) { + NMSriovVF *vf = self->vfs->pdata[i]; + gs_free_error GError *local = NULL; + + if (vf->index >= self->total_vfs) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("VF with index %u, but the total number of VFs is %u"), + vf->index, self->total_vfs); + g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return FALSE; + } + + if (!_nm_sriov_vf_attribute_validate_all (vf, &local)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid VF %u: %s"), + vf->index, + local->message); + g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return FALSE; + } + + if (g_hash_table_contains (h, GUINT_TO_POINTER (vf->index))) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("duplicate VF index %u"), vf->index); + g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return FALSE; + } + + g_hash_table_add (h, GUINT_TO_POINTER (vf->index)); + } + } + + /* Failures from here on are NORMALIZABLE... */ + + if (self->vfs->len) { + for (i = 1; i < self->vfs->len; i++) { + NMSriovVF *vf_prev = self->vfs->pdata[i - 1]; + NMSriovVF *vf = self->vfs->pdata[i]; + + if (vf->index <= vf_prev->index) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("VFs %d and %d are not sorted by ascending index"), + vf_prev->index, vf->index); + g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME, + NM_SETTING_SRIOV_VFS); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + } + } + + return TRUE; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingSriov *self = NM_SETTING_SRIOV (object); + + switch (prop_id) { + case PROP_TOTAL_VFS: + self->total_vfs = g_value_get_uint (value); + break; + case PROP_VFS: + g_ptr_array_unref (self->vfs); + self->vfs = _nm_utils_copy_array (g_value_get_boxed (value), + (NMUtilsCopyFunc) nm_sriov_vf_dup, + (GDestroyNotify) nm_sriov_vf_unref); + break; + case PROP_AUTOPROBE_DRIVERS: + self->autoprobe_drivers = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingSriov *self = NM_SETTING_SRIOV (object); + + switch (prop_id) { + case PROP_TOTAL_VFS: + g_value_set_uint (value, self->total_vfs); + break; + case PROP_VFS: + g_value_take_boxed (value, _nm_utils_copy_array (self->vfs, + (NMUtilsCopyFunc) nm_sriov_vf_dup, + (GDestroyNotify) nm_sriov_vf_unref)); + break; + case PROP_AUTOPROBE_DRIVERS: + g_value_set_enum (value, self->autoprobe_drivers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +compare_property (NMSetting *setting, + NMSetting *other, + const GParamSpec *prop_spec, + NMSettingCompareFlags flags) +{ + NMSettingSriov *a = NM_SETTING_SRIOV (setting); + NMSettingSriov *b = NM_SETTING_SRIOV (other); + NMSettingClass *setting_class; + guint i; + + if (nm_streq (prop_spec->name, NM_SETTING_SRIOV_VFS)) { + if (a->vfs->len != b->vfs->len) + return FALSE; + for (i = 0; i < a->vfs->len; i++) { + if (!nm_sriov_vf_equal (a->vfs->pdata[i], b->vfs->pdata[i])) + return FALSE; + } + return TRUE; + } + + setting_class = NM_SETTING_CLASS (nm_setting_sriov_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); +} + +static void +nm_setting_sriov_init (NMSettingSriov *setting) +{ + setting->vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); +} + +static void +finalize (GObject *object) +{ + NMSettingSriov *self = NM_SETTING_SRIOV (object); + + g_ptr_array_unref (self->vfs); + + G_OBJECT_CLASS (nm_setting_sriov_parent_class)->finalize (object); +} + +static void +nm_setting_sriov_class_init (NMSettingSriovClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->compare_property = compare_property; + setting_class->verify = verify; + + /** + * NMSettingSriov:total-vfs + * + * The total number of virtual functions to create. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: total-vfs + * variable: SRIOV_TOTAL_VFS(+) + * description: The total number of virtual functions to create + * example: SRIOV_TOTAL_VFS=16 + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_TOTAL_VFS, + g_param_spec_uint (NM_SETTING_SRIOV_TOTAL_VFS, "", "", + 0, G_MAXUINT32, 0, + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingSriov:vfs: (type GPtrArray(NMSriovVF)) + * + * Array of virtual function descriptors. + * + * Each VF descriptor is a dictionary mapping attribute names + * to GVariant values. The 'index' entry is mandatory for + * each VF. + * + * When represented as string a VF is in the form: + * + * "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". + * + * for example: + * + * "2 mac=00:11:22:33:44:55 spoof-check=true". + * + * The "vlans" attribute is represented as a semicolor-separated + * list of VLAN descriptors, where each descriptor has the form + * + * "ID[.PRIORITY[.PROTO]]". + * + * PROTO can be either 'q' for 802.1Q (the default) or 'ad' for + * 802.1ad. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: vfs + * variable: SRIOV_VF1(+), SRIOV_VF2(+), ... + * description: SR-IOV virtual function descriptors + * example: SRIOV_VF10="mac=00:11:22:33:44:55", ... + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_VFS, + g_param_spec_boxed (NM_SETTING_SRIOV_VFS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_SRIOV_VFS), + G_VARIANT_TYPE ("aa{sv}"), + vfs_to_dbus, + vfs_from_dbus, + NULL); + + /** + * NMSettingSriov:autoprobe-drivers + * + * Whether to autoprobe virtual functions by a compatible driver. + * + * If set to %NM_TERNARY_TRUE, the kernel will try to bind VFs to + * a compatible driver and if this succeeds a new network + * interface will be instantiated for each VF. + * + * If set to %NM_TERNARY_FALSE, VFs will not be claimed and no + * network interfaces will be created for them. + * + * When set to %NM_TERNARY_DEFAULT, the global default is used; in + * case the global default is unspecified it is assumed to be + * %NM_TERNARY_TRUE. + * + * Since: 1.14 + **/ + /* ---ifcfg-rh--- + * property: autoprobe-drivers + * variable: SRIOV_AUTOPROBE_DRIVERS(+) + * default: missing variable means global default + * description: Whether to autoprobe virtual functions by a compatible driver + * example: SRIOV_AUTOPROBE_DRIVERS=0,1 + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_AUTOPROBE_DRIVERS, + g_param_spec_enum (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, "", "", + nm_ternary_get_type (), + NM_TERNARY_DEFAULT, + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_SRIOV, + NULL, properties_override); +} diff --git a/libnm-core/nm-setting-sriov.h b/libnm-core/nm-setting-sriov.h new file mode 100644 index 00000000..2e209964 --- /dev/null +++ b/libnm-core/nm-setting-sriov.h @@ -0,0 +1,123 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 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. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright 2018 Red Hat, Inc. + */ + +#ifndef NM_SETTING_SRIOV_H +#define NM_SETTING_SRIOV_H + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_SRIOV (nm_setting_sriov_get_type ()) +#define NM_SETTING_SRIOV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriov)) +#define NM_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass)) +#define NM_IS_SETTING_SRIOV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_SRIOV)) +#define NM_IS_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_SRIOV)) +#define NM_SETTING_SRIOV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass)) + +#define NM_SETTING_SRIOV_SETTING_NAME "sriov" + +#define NM_SETTING_SRIOV_TOTAL_VFS "total-vfs" +#define NM_SETTING_SRIOV_VFS "vfs" +#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS "autoprobe-drivers" + +#define NM_SRIOV_VF_ATTRIBUTE_MAC "mac" +#define NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK "spoof-check" +#define NM_SRIOV_VF_ATTRIBUTE_TRUST "trust" +#define NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE "min-tx-rate" +#define NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE "max-tx-rate" + +typedef struct _NMSettingSriovClass NMSettingSriovClass; +typedef struct _NMSriovVF NMSriovVF; + +/** + * NMSriovVFVlanProtocol: + * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q: use 802.1Q + * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: use 802.1ad + * + * #NMSriovVFVlanProtocol indicates the VLAN protocol to use. + * + * Since: 1.14 + */ +typedef enum { + NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q = 0, + NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD = 1, +} NMSriovVFVlanProtocol; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_sriov_get_type (void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_sriov_new (void); +NM_AVAILABLE_IN_1_14 +guint nm_setting_sriov_get_total_vfs (NMSettingSriov *setting); +NM_AVAILABLE_IN_1_14 +guint nm_setting_sriov_get_num_vfs (NMSettingSriov *setting); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_setting_sriov_get_vf (NMSettingSriov *setting, guint idx); +NM_AVAILABLE_IN_1_14 +void nm_setting_sriov_add_vf (NMSettingSriov *setting, NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +void nm_setting_sriov_remove_vf (NMSettingSriov *setting, guint idx); +NM_AVAILABLE_IN_1_14 +gboolean nm_setting_sriov_remove_vf_by_index (NMSettingSriov *setting, guint index); +NM_AVAILABLE_IN_1_14 +void nm_setting_sriov_clear_vfs (NMSettingSriov *setting); +NM_AVAILABLE_IN_1_14 +NMTernary nm_setting_sriov_get_autoprobe_drivers (NMSettingSriov *setting); + +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_add_vlan (NMSriovVF *vf, guint vlan_id); +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id); +NM_AVAILABLE_IN_1_14 +const guint *nm_sriov_vf_get_vlan_ids (const NMSriovVF *vf, guint *length); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_set_vlan_qos (NMSriovVF *vf, guint vlan_id, guint32 qos); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_set_vlan_protocol (NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol); +NM_AVAILABLE_IN_1_14 +guint32 nm_sriov_vf_get_vlan_qos (const NMSriovVF *vf, guint vlan_id); +NM_AVAILABLE_IN_1_14 +NMSriovVFVlanProtocol nm_sriov_vf_get_vlan_protocol (const NMSriovVF *vf, guint vlan_id); + +NM_AVAILABLE_IN_1_14 +GType nm_sriov_vf_get_type (void); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_sriov_vf_new (guint index); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_ref (NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_unref (NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_equal (const NMSriovVF *vf, const NMSriovVF *other); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_sriov_vf_dup (const NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +guint nm_sriov_vf_get_index (const NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +void nm_sriov_vf_set_attribute (NMSriovVF *vf, const char *name, GVariant *value); +NM_AVAILABLE_IN_1_14 +const char **nm_sriov_vf_get_attribute_names (const NMSriovVF *vf); +NM_AVAILABLE_IN_1_14 +GVariant *nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name); +NM_AVAILABLE_IN_1_14 +gboolean nm_sriov_vf_attribute_validate (const char *name, GVariant *value, gboolean *known, GError **error); + +G_END_DECLS + +#endif /* NM_SETTING_SRIOV_H */ diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c index f50969fb..43015d37 100644 --- a/libnm-core/nm-setting-tc-config.c +++ b/libnm-core/nm-setting-tc-config.c @@ -820,23 +820,21 @@ enum { /** * NMSettingTCConfig: * - * Linux Traffic Contril Settings. + * Linux Traffic Control Settings. * * Since: 1.12 */ struct _NMSettingTCConfig { - NMSetting parent; + NMSetting parent; GPtrArray *qdiscs; GPtrArray *tfilters; }; struct _NMSettingTCConfigClass { - NMSettingClass parent; + NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING, - _nm_register_setting (TC_CONFIG, NM_SETTING_PRIORITY_IP)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TC_CONFIG) +G_DEFINE_TYPE (NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING) /** * nm_setting_tc_config_new: @@ -983,8 +981,10 @@ nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *self) { g_return_if_fail (NM_IS_SETTING_TC_CONFIG (self)); - g_ptr_array_set_size (self->qdiscs, 0); - g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_QDISCS); + if (self->qdiscs->len != 0) { + g_ptr_array_set_size (self->qdiscs, 0); + g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_QDISCS); + } } /*****************************************************************************/ @@ -1117,8 +1117,10 @@ nm_setting_tc_config_clear_tfilters (NMSettingTCConfig *self) { g_return_if_fail (NM_IS_SETTING_TC_CONFIG (self)); - g_ptr_array_set_size (self->tfilters, 0); - g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_TFILTERS); + if (self->tfilters->len != 0) { + g_ptr_array_set_size (self->tfilters, 0); + g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_TFILTERS); + } } /*****************************************************************************/ @@ -1239,7 +1241,7 @@ compare_property (NMSetting *setting, { NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG (setting); NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG (other); - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i; if (nm_streq (prop_spec->name, NM_SETTING_TC_CONFIG_QDISCS)) { @@ -1262,9 +1264,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -1586,28 +1587,27 @@ tc_tfilters_set (NMSetting *setting, } static void -nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) +nm_setting_tc_config_class_init (NMSettingTCConfigClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->compare_property = compare_property; - parent_class->verify = verify; - /* Properties */ + setting_class->compare_property = compare_property; + setting_class->verify = verify; /** * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc)) * - * Array of TC queuening disciplines. + * Array of TC queueing disciplines. **/ /* ---ifcfg-rh--- * property: qdiscs - * variable: QDISC1, QDISC2, ... + * variable: QDISC1(+), QDISC2(+), ... * description: Queueing disciplines * example: QDISC1=ingress, QDISC2="root handle 1234: fq_codel" * ---end--- @@ -1620,12 +1620,13 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_TC_CONFIG_QDISCS, - G_VARIANT_TYPE ("aa{sv}"), - tc_qdiscs_get, - tc_qdiscs_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TC_CONFIG_QDISCS), + G_VARIANT_TYPE ("aa{sv}"), + tc_qdiscs_get, + tc_qdiscs_set, + NULL); /** * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) @@ -1634,7 +1635,7 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) **/ /* ---ifcfg-rh--- * property: qdiscs - * variable: FILTER1, FILTER2, ... + * variable: FILTER1(+), FILTER2(+), ... * description: Traffic filters * example: FILTER1="parent ffff: matchall action simple sdata Input", ... * ---end--- @@ -1647,10 +1648,14 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, - NM_SETTING_TC_CONFIG_TFILTERS, - G_VARIANT_TYPE ("aa{sv}"), - tc_tfilters_get, - tc_tfilters_set, - NULL); + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TC_CONFIG_TFILTERS), + G_VARIANT_TYPE ("aa{sv}"), + tc_tfilters_get, + tc_tfilters_set, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TC_CONFIG, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index b902b822..ee84aaf7 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -39,9 +39,7 @@ * optional properties that apply to team ports. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING, - _nm_register_setting (TEAM_PORT, NM_SETTING_PRIORITY_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM_PORT) +G_DEFINE_TYPE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING) #define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate)) @@ -115,7 +113,7 @@ nm_setting_team_port_get_config (NMSettingTeamPort *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), -1); @@ -131,7 +129,7 @@ nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_port_get_prio (NMSettingTeamPort *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0); @@ -163,7 +161,7 @@ nm_setting_team_port_get_sticky (NMSettingTeamPort *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0); @@ -179,7 +177,7 @@ nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0); @@ -323,8 +321,10 @@ nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting) g_return_if_fail (NM_IS_SETTING_TEAM_PORT (setting)); - g_ptr_array_set_size (priv->link_watchers, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS); + if (priv->link_watchers->len != 0) { + g_ptr_array_set_size (priv->link_watchers, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS); + } } static GVariant * @@ -407,7 +407,7 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; NMSettingTeamPortPrivate *a_priv, *b_priv; guint i, j; @@ -441,9 +441,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -586,21 +585,21 @@ finalize (GObject *object) } static void -nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) +nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingTeamPortPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingTeamPortPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->compare_property = compare_property; - parent_class->verify = verify; - /* Properties */ + setting_class->compare_property = compare_property; + setting_class->verify = verify; + /** * NMSettingTeamPort:config: * @@ -714,10 +713,14 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_TEAM_PORT_LINK_WATCHERS, - G_VARIANT_TYPE ("aa{sv}"), - team_link_watchers_to_dbus, - team_link_watchers_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TEAM_PORT_LINK_WATCHERS), + G_VARIANT_TYPE ("aa{sv}"), + team_link_watchers_to_dbus, + team_link_watchers_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM_PORT, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-team-port.h b/libnm-core/nm-setting-team-port.h index 4ecb1838..57611750 100644 --- a/libnm-core/nm-setting-team-port.h +++ b/libnm-core/nm-setting-team-port.h @@ -72,15 +72,15 @@ NMSetting * nm_setting_team_port_new (void); const char * nm_setting_team_port_get_config (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting); +int nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_port_get_prio (NMSettingTeamPort *setting); +int nm_setting_team_port_get_prio (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_port_get_sticky (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting); +int nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting); +int nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 guint nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting); NM_AVAILABLE_IN_1_12 diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index 195e509c..e6737e48 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -118,8 +118,8 @@ struct NMTeamLinkWatcher { * Since: 1.12 **/ NMTeamLinkWatcher * -nm_team_link_watcher_new_ethtool (gint delay_up, - gint delay_down, +nm_team_link_watcher_new_ethtool (int delay_up, + int delay_down, GError **error) { NMTeamLinkWatcher *watcher; @@ -161,9 +161,9 @@ nm_team_link_watcher_new_ethtool (gint delay_up, * Since: 1.12 **/ NMTeamLinkWatcher * -nm_team_link_watcher_new_nsna_ping (gint init_wait, - gint interval, - gint missed_max, +nm_team_link_watcher_new_nsna_ping (int init_wait, + int interval, + int missed_max, const char *target_host, GError **error) { @@ -225,9 +225,9 @@ nm_team_link_watcher_new_nsna_ping (gint init_wait, * Since: 1.12 **/ NMTeamLinkWatcher * -nm_team_link_watcher_new_arp_ping (gint init_wait, - gint interval, - gint missed_max, +nm_team_link_watcher_new_arp_ping (int init_wait, + int interval, + int missed_max, const char *target_host, const char *source_host, NMTeamLinkWatcherArpPingFlags flags, @@ -557,27 +557,25 @@ nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher) /*****************************************************************************/ -G_DEFINE_TYPE_WITH_CODE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING, - _nm_register_setting (TEAM, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM) +G_DEFINE_TYPE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING) #define NM_SETTING_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate)) typedef struct { char *config; - gint notify_peers_count; - gint notify_peers_interval; - gint mcast_rejoin_count; - gint mcast_rejoin_interval; + int notify_peers_count; + int notify_peers_interval; + int mcast_rejoin_count; + int mcast_rejoin_interval; char *runner; char *runner_hwaddr_policy; GPtrArray *runner_tx_hash; char *runner_tx_balancer; - gint runner_tx_balancer_interval; + int runner_tx_balancer_interval; gboolean runner_active; gboolean runner_fast_rate; - gint runner_sys_prio; - gint runner_min_ports; + int runner_sys_prio; + int runner_min_ports; char *runner_agg_select_policy; GPtrArray *link_watchers; /* Array of NMTeamLinkWatcher */ } NMSettingTeamPrivate; @@ -661,7 +659,7 @@ nm_setting_team_get_config (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_notify_peers_count (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -677,7 +675,7 @@ nm_setting_team_get_notify_peers_count (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -693,7 +691,7 @@ nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -709,7 +707,7 @@ nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -773,7 +771,7 @@ nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -821,7 +819,7 @@ nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -837,7 +835,7 @@ nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting) * * Since: 1.12 **/ -gint +int nm_setting_team_get_runner_min_ports (NMSettingTeam *setting) { g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0); @@ -1121,8 +1119,10 @@ nm_setting_team_clear_link_watchers (NMSettingTeam *setting) { g_return_if_fail (NM_IS_SETTING_TEAM (setting)); - g_ptr_array_set_size (priv->link_watchers, 0); - g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_LINK_WATCHERS); + if (priv->link_watchers->len != 0) { + g_ptr_array_set_size (priv->link_watchers, 0); + g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_LINK_WATCHERS); + } } static GVariant * @@ -1237,7 +1237,7 @@ compare_property (NMSetting *setting, NMSettingCompareFlags flags) { NMSettingTeamPrivate *a_priv, *b_priv; - NMSettingClass *parent_class; + NMSettingClass *setting_class; guint i, j; /* If we are trying to match a connection in order to assume it (and thus @@ -1270,9 +1270,8 @@ compare_property (NMSetting *setting, return TRUE; } - /* Otherwise chain up to parent to handle generic compare */ - parent_class = NM_SETTING_CLASS (nm_setting_team_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_team_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static void @@ -1557,21 +1556,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_team_class_init (NMSettingTeamClass *setting_class) +nm_setting_team_class_init (NMSettingTeamClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingTeamPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingTeamPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->compare_property = compare_property; - parent_class->verify = verify; - /* Properties */ + setting_class->compare_property = compare_property; + setting_class->verify = verify; + /** * NMSettingTeam:config: * @@ -1817,11 +1816,13 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_TEAM_LINK_WATCHERS, - G_VARIANT_TYPE ("aa{sv}"), - team_link_watchers_to_dbus, - team_link_watchers_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_TEAM_LINK_WATCHERS), + G_VARIANT_TYPE ("aa{sv}"), + team_link_watchers_to_dbus, + team_link_watchers_from_dbus); /* ---dbus--- * property: interface-name @@ -1831,8 +1832,12 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) * team's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h index cd766d8e..a600053a 100644 --- a/libnm-core/nm-setting-team.h +++ b/libnm-core/nm-setting-team.h @@ -57,19 +57,19 @@ typedef struct NMTeamLinkWatcher NMTeamLinkWatcher; GType nm_team_link_watcher_get_type (void); NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool (gint delay_up, - gint delay_down, +NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool (int delay_up, + int delay_down, GError **error); NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping (gint init_wait, - gint interval, - gint missed_max, +NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping (int init_wait, + int interval, + int missed_max, const char *target_host, GError **error); NM_AVAILABLE_IN_1_12 -NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (gint init_wait, - gint interval, - gint missed_max, +NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (int init_wait, + int interval, + int missed_max, const char *target_host, const char *source_host, NMTeamLinkWatcherArpPingFlags flags, @@ -174,13 +174,13 @@ NMSetting * nm_setting_team_new (void); const char * nm_setting_team_get_config (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_notify_peers_count (NMSettingTeam *setting); +int nm_setting_team_get_notify_peers_count (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting); +int nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting); +int nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting); +int nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 @@ -188,15 +188,15 @@ const char * nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting); +int nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_get_runner_active (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 gboolean nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting); +int nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 -gint nm_setting_team_get_runner_min_ports (NMSettingTeam *setting); +int nm_setting_team_get_runner_min_ports (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 const char * nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting); NM_AVAILABLE_IN_1_12 diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c index edcb3ffd..3e033e25 100644 --- a/libnm-core/nm-setting-tun.c +++ b/libnm-core/nm-setting-tun.c @@ -38,9 +38,7 @@ * necessary for connection to TUN/TAP interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING, - _nm_register_setting (TUN, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TUN) +G_DEFINE_TYPE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING) #define NM_SETTING_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate)) @@ -292,20 +290,19 @@ finalize (GObject *object) } static void -nm_setting_tun_class_init (NMSettingTunClass *setting_class) +nm_setting_tun_class_init (NMSettingTunClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingTunPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingTunPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingTun:mode: * @@ -406,4 +403,6 @@ nm_setting_tun_class_init (NMSettingTunClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_TUN); } diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c index ccc030aa..d72c9094 100644 --- a/libnm-core/nm-setting-user.c +++ b/libnm-core/nm-setting-user.c @@ -63,9 +63,7 @@ struct _NMSettingUserClass { NMSettingClass parent; }; -G_DEFINE_TYPE_WITH_CODE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING, - _nm_register_setting (USER, NM_SETTING_PRIORITY_USER)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_USER) +G_DEFINE_TYPE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING) #define NM_SETTING_USER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMSettingUser, NM_IS_SETTING_USER) @@ -398,29 +396,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } static gboolean -hash_table_equal (GHashTable *a, GHashTable *b) -{ - guint n; - GHashTableIter iter; - const char *key, *value, *valu2; - - n = a ? g_hash_table_size (a) : 0; - if (n != (b ? g_hash_table_size (b) : 0)) - return FALSE; - if (n > 0) { - g_hash_table_iter_init (&iter, a); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { - if (!g_hash_table_lookup_extended (b, key, NULL, (gpointer *) &valu2)) - return FALSE; - if (!nm_streq (value, valu2)) - return FALSE; - } - } - return TRUE; - -} - -static gboolean compare_property (NMSetting *setting, NMSetting *other, const GParamSpec *prop_spec, @@ -437,10 +412,10 @@ compare_property (NMSetting *setting, priv = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (setting)); pri2 = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (other)); - if (!hash_table_equal (priv->data, pri2->data)) + if (!nm_utils_hash_table_equal (priv->data, pri2->data, TRUE, g_str_equal)) return FALSE; - if (!hash_table_equal (priv->data_invalid, pri2->data_invalid)) + if (!nm_utils_hash_table_equal (priv->data_invalid, pri2->data_invalid, TRUE, g_str_equal)) return FALSE; return TRUE; @@ -572,12 +547,14 @@ nm_setting_user_class_init (NMSettingUserClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; + setting_class->compare_property = compare_property; - setting_class->verify = verify; + setting_class->verify = verify; /** * NMSettingUser:data: (type GHashTable(utf8,utf8)) @@ -608,8 +585,13 @@ nm_setting_user_class_init (NMSettingUserClass *klass) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - _nm_setting_class_transform_property (setting_class, NM_SETTING_USER_DATA, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_USER_DATA), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_USER, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index f9c6e02d..1b61da55 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -41,9 +41,7 @@ * necessary for connection to VLAN interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING, - _nm_register_setting (VLAN, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VLAN) +G_DEFINE_TYPE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING) #define NM_SETTING_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate)) @@ -134,7 +132,7 @@ static NMVlanQosMapping * priority_map_new_from_str (NMVlanPriorityMap map, const char *str) { NMVlanQosMapping *p = NULL; - gchar **t = NULL; + char **t = NULL; guint32 len; guint64 from, to; @@ -176,7 +174,7 @@ get_map (NMSettingVlan *self, NMVlanPriorityMap map) return NULL; } -static gint +static int prio_map_compare (gconstpointer p_a, gconstpointer p_b) { const NMVlanQosMapping *a = p_a; @@ -831,20 +829,19 @@ finalize (GObject *object) } static void -nm_setting_vlan_class_init (NMSettingVlanClass *setting_class) +nm_setting_vlan_class_init (NMSettingVlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingVlanPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingVlanPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingVlan:parent: @@ -921,11 +918,14 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (parent_class, NM_SETTING_VLAN_FLAGS, - NULL, - _override_flags_get, - NULL, - _override_flags_not_set); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_VLAN_FLAGS), + NULL, + _override_flags_get, + NULL, + _override_flags_not_set); /** * NMSettingVlan:ingress-priority-map: @@ -987,8 +987,12 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class) * vlan's interface name. * ---end--- */ - _nm_setting_class_add_dbus_only_property (parent_class, "interface-name", - G_VARIANT_TYPE_STRING, - _nm_setting_get_deprecated_virtual_interface_name, - NULL); + _properties_override_add_dbus_only (properties_override, + "interface-name", + G_VARIANT_TYPE_STRING, + _nm_setting_get_deprecated_virtual_interface_name, + NULL); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_VLAN, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index a921f51f..fcbeec68 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -25,6 +25,8 @@ #include <errno.h> #include <stdlib.h> +#include "nm-utils/nm-secret-utils.h" + #include "nm-setting-vpn.h" #include "nm-utils.h" #include "nm-utils-private.h" @@ -43,9 +45,7 @@ * properties. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING, - _nm_register_setting (VPN, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VPN) +G_DEFINE_TYPE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING) #define NM_SETTING_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate)) @@ -481,6 +481,7 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); + NMSettingConnection *s_con; if (!priv->service_type) { g_set_error_literal (error, @@ -510,6 +511,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if ( connection + && (s_con = nm_connection_get_setting_connection (connection)) + && nm_setting_connection_get_multi_connect (s_con) != NM_CONNECTION_MULTI_CONNECT_DEFAULT) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("cannot set connection.multi-connect for VPN setting")); + return FALSE; + } + return TRUE; } @@ -878,27 +889,26 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) +nm_setting_vpn_class_init (NMSettingVpnClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingVpnPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingVpnPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->update_one_secret = update_one_secret; - parent_class->get_secret_flags = get_secret_flags; - parent_class->set_secret_flags = set_secret_flags; - parent_class->need_secrets = need_secrets; - parent_class->compare_property = compare_property; - parent_class->clear_secrets_with_flags = clear_secrets_with_flags; + setting_class->verify = verify; + setting_class->update_one_secret = update_one_secret; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; + setting_class->need_secrets = need_secrets; + setting_class->compare_property = compare_property; + setting_class->clear_secrets_with_flags = clear_secrets_with_flags; - /* Properties */ /** * NMSettingVpn:service-type: * @@ -964,10 +974,13 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_VPN_DATA, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_VPN_DATA), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /** * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)): @@ -990,10 +1003,13 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_VPN_SECRETS, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_VPN_SECRETS), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /** * NMSettingVpn:timeout: @@ -1012,4 +1028,7 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_VPN, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c index 4be6a236..d00c5a7a 100644 --- a/libnm-core/nm-setting-vxlan.c +++ b/libnm-core/nm-setting-vxlan.c @@ -36,9 +36,7 @@ * necessary for connection to VXLAN interfaces. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING, - _nm_register_setting (VXLAN, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VXLAN) +G_DEFINE_TYPE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING) #define NM_SETTING_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate)) @@ -565,20 +563,18 @@ finalize (GObject *object) } static void -nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class) +nm_setting_vxlan_class_init (NMSettingVxlanClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); - g_type_class_add_private (setting_class, sizeof (NMSettingVxlanPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingVxlanPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; /** * NMSettingVxlan:parent: @@ -840,4 +836,6 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_VXLAN); } diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c index dbfb46e4..4c1a572e 100644 --- a/libnm-core/nm-setting-wimax.c +++ b/libnm-core/nm-setting-wimax.c @@ -42,9 +42,7 @@ * connections cannot be activated. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING, - _nm_register_setting (WIMAX, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIMAX) +G_DEFINE_TYPE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING) #define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) @@ -207,20 +205,20 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class) +nm_setting_wimax_class_init (NMSettingWimaxClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingWimaxPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWimaxPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - /* Properties */ + setting_class->verify = verify; + /** * NMSettingWimax:network-name: * @@ -251,8 +249,14 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, NM_SETTING_WIMAX_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIMAX_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIMAX, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c index 5da9ce7d..baa40cc4 100644 --- a/libnm-core/nm-setting-wired.c +++ b/libnm-core/nm-setting-wired.c @@ -40,9 +40,7 @@ * necessary for connection to Ethernet networks. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING, - _nm_register_setting (WIRED, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRED) +G_DEFINE_TYPE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING) #define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate)) @@ -766,8 +764,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) || ((!priv->speed) && (priv->duplex))) { g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, priv->auto_negotiate ? _("both speed and duplex should have a valid value or both should be unset") : _("both speed and duplex are required for static link configuration")); @@ -783,15 +781,15 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; if (nm_streq (prop_spec->name, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) { return nm_streq0 (NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address, NM_SETTING_WIRED_GET_PRIVATE (other)->cloned_mac_address); } - parent_class = NM_SETTING_CLASS (nm_setting_wired_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_wired_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } static GVariant * @@ -978,21 +976,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) +nm_setting_wired_class_init (NMSettingWiredClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_wired_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wired_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_wired_class, sizeof (NMSettingWiredPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWiredPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - setting_class->verify = verify; + + setting_class->verify = verify; setting_class->compare_property = compare_property; - /* Properties */ /** * NMSettingWired:port: * @@ -1103,12 +1101,14 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (setting_class, - NM_SETTING_WIRED_AUTO_NEGOTIATE, - G_VARIANT_TYPE_BOOLEAN, - _override_autoneg_get, - NULL, - NULL); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_AUTO_NEGOTIATE), + G_VARIANT_TYPE_BOOLEAN, + _override_autoneg_get, + NULL, + NULL); /** * NMSettingWired:mac-address: @@ -1141,10 +1141,13 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingWired:cloned-mac-address: @@ -1196,8 +1199,10 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (setting_class, - NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_CLONED_MAC_ADDRESS), G_VARIANT_TYPE_BYTESTRING, _nm_utils_hwaddr_cloned_get, _nm_utils_hwaddr_cloned_set, @@ -1215,11 +1220,11 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) * "cloned-mac-address". * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "assigned-mac-address", - G_VARIANT_TYPE_STRING, - _nm_utils_hwaddr_cloned_data_synth, - _nm_utils_hwaddr_cloned_data_set); + _properties_override_add_dbus_only (properties_override, + "assigned-mac-address", + G_VARIANT_TYPE_STRING, + _nm_utils_hwaddr_cloned_data_synth, + _nm_utils_hwaddr_cloned_data_set); /** * NMSettingWired:generate-mac-address-mask: @@ -1389,10 +1394,13 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_S390_OPTIONS, - G_VARIANT_TYPE ("a{ss}"), - _nm_utils_strdict_to_dbus, - _nm_utils_strdict_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRED_S390_OPTIONS), + G_VARIANT_TYPE ("a{ss}"), + _nm_utils_strdict_to_dbus, + _nm_utils_strdict_from_dbus); /** * NMSettingWired:wake-on-lan: @@ -1431,4 +1439,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRED, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index 31e386f3..d1527821 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -53,9 +53,7 @@ * ISBN: 978-1587051548 **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING, - _nm_register_setting (WIRELESS_SECURITY, NM_SETTING_PRIORITY_HW_AUX)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS_SECURITY) +G_DEFINE_TYPE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING) #define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityPrivate)) @@ -1431,25 +1429,24 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting_class) +nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_class); - NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_class, sizeof (NMSettingWirelessSecurityPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWirelessSecurityPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - parent_class->verify = verify; - parent_class->verify_secrets = verify_secrets; - parent_class->need_secrets = need_secrets; - parent_class->get_secret_flags = get_secret_flags; - parent_class->set_secret_flags = set_secret_flags; + setting_class->verify = verify; + setting_class->verify_secrets = verify_secrets; + setting_class->need_secrets = need_secrets; + setting_class->get_secret_flags = get_secret_flags; + setting_class->set_secret_flags = set_secret_flags; - /* Properties */ /** * NMSettingWirelessSecurity:key-mgmt: * @@ -1856,11 +1853,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (parent_class, - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - G_VARIANT_TYPE_UINT32, - wep_key_type_to_dbus, - NULL); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE), + G_VARIANT_TYPE_UINT32, + wep_key_type_to_dbus, + NULL); /** * NMSettingWirelessSecurity:wps-method: * @@ -1922,4 +1921,7 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRELESS_SECURITY, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index 89a2df8e..a9cae6c0 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -40,9 +40,7 @@ * necessary for connection to 802.11 Wi-Fi networks. **/ -G_DEFINE_TYPE_WITH_CODE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING, - _nm_register_setting (WIRELESS, NM_SETTING_PRIORITY_HW_BASE)) -NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS) +G_DEFINE_TYPE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING) #define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate)) @@ -937,15 +935,15 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - NMSettingClass *parent_class; + NMSettingClass *setting_class; if (nm_streq (prop_spec->name, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) { return nm_streq0 (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address, NM_SETTING_WIRELESS_GET_PRIVATE (other)->cloned_mac_address); } - parent_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class); - return parent_class->compare_property (setting, other, prop_spec, flags); + setting_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class); + return setting_class->compare_property (setting, other, prop_spec, flags); } /*****************************************************************************/ @@ -1176,21 +1174,21 @@ get_property (GObject *object, guint prop_id, } static void -nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) +nm_setting_wireless_class_init (NMSettingWirelessClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (setting_wireless_class); - NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wireless_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (setting_wireless_class, sizeof (NMSettingWirelessPrivate)); + g_type_class_add_private (klass, sizeof (NMSettingWirelessPrivate)); - /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; object_class->finalize = finalize; - setting_class->verify = verify; + + setting_class->verify = verify; setting_class->compare_property = compare_property; - /* Properties */ /** * NMSettingWireless:ssid: * @@ -1308,10 +1306,13 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_BSSID, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_BSSID), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingWireless:rate: @@ -1388,10 +1389,13 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_to_dbus, - _nm_utils_hwaddr_from_dbus); + + _properties_override_add_transform (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_to_dbus, + _nm_utils_hwaddr_from_dbus); /** * NMSettingWireless:cloned-mac-address: @@ -1441,12 +1445,14 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - _nm_setting_class_override_property (setting_class, - NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, - G_VARIANT_TYPE_BYTESTRING, - _nm_utils_hwaddr_cloned_get, - _nm_utils_hwaddr_cloned_set, - _nm_utils_hwaddr_cloned_not_set); + + _properties_override_add_override (properties_override, + g_object_class_find_property (G_OBJECT_CLASS (setting_class), + NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS), + G_VARIANT_TYPE_BYTESTRING, + _nm_utils_hwaddr_cloned_get, + _nm_utils_hwaddr_cloned_set, + _nm_utils_hwaddr_cloned_not_set); /* ---dbus--- * property: assigned-mac-address @@ -1460,11 +1466,11 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * "cloned-mac-address". * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, - "assigned-mac-address", - G_VARIANT_TYPE_STRING, - _nm_utils_hwaddr_cloned_data_synth, - _nm_utils_hwaddr_cloned_data_set); + _properties_override_add_dbus_only (properties_override, + "assigned-mac-address", + G_VARIANT_TYPE_STRING, + _nm_utils_hwaddr_cloned_data_synth, + _nm_utils_hwaddr_cloned_data_set); /** * NMSettingWireless:generate-mac-address-mask: @@ -1679,9 +1685,11 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * NetworkManager daemons. * ---end--- */ - _nm_setting_class_add_dbus_only_property (setting_class, "security", - G_VARIANT_TYPE_STRING, - nm_setting_wireless_get_security, NULL); + _properties_override_add_dbus_only (properties_override, + "security", + G_VARIANT_TYPE_STRING, + nm_setting_wireless_get_security, + NULL); /** * NMSettingWireless:wake-on-wlan: @@ -1708,4 +1716,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRELESS, + NULL, properties_override); } diff --git a/libnm-core/nm-setting-wpan.c b/libnm-core/nm-setting-wpan.c new file mode 100644 index 00000000..6e1aaadc --- /dev/null +++ b/libnm-core/nm-setting-wpan.c @@ -0,0 +1,274 @@ +/* + * 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 Lubomir Rintel <lkundrak@v3.sk> + */ + +#include "nm-default.h" + +#include "nm-setting-wpan.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" +#include "nm-utils-private.h" + +/* Ideally we'll be able to get this from a public header. */ +#ifndef IEEE802154_ADDR_LEN +#define IEEE802154_ADDR_LEN 8 +#endif + +enum { + PROP_0, + PROP_MAC_ADDRESS, + PROP_PAN_ID, + PROP_SHORT_ADDRESS, +}; + +typedef struct { + char *mac_address; + guint16 pan_id; + guint16 short_address; +} NMSettingWpanPrivate; + +/** + * NMSettingWpan: + * + * IEEE 802.15.4 (WPAN) MAC Settings + */ +struct _NMSettingWpan { + NMSetting parent; +}; + +struct _NMSettingWpanClass { + NMSettingClass parent; +}; + +/** + * SECTION:nm-setting-wpan + * @short_description: Describes connection properties for IEEE 802.15.4 (WPAN) MAC + * + * The #NMSettingWpan object is a #NMSetting subclass that describes properties + * necessary for configuring IEEE 802.15.4 (WPAN) MAC layer devices. + **/ + +G_DEFINE_TYPE (NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING) + +#define NM_SETTING_WPAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WPAN, NMSettingWpanPrivate)) + +/** + * nm_setting_wpan_get_mac_address: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:mac-address property of the setting + * + * Since: 1.14 + **/ +const char * +nm_setting_wpan_get_mac_address (NMSettingWpan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WPAN (setting), NULL); + + return NM_SETTING_WPAN_GET_PRIVATE (setting)->mac_address; +} + +/** + * nm_setting_wpan_get_pan_id: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:pan-id property of the setting + * + * Since: 1.14 + **/ +guint16 +nm_setting_wpan_get_pan_id (NMSettingWpan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WPAN (setting), G_MAXUINT16); + + return NM_SETTING_WPAN_GET_PRIVATE (setting)->pan_id; +} + +/** + * nm_setting_wpan_get_short_address: + * @setting: the #NMSettingWpan + * + * Returns: the #NMSettingWpan:short-address property of the setting + * + * Since: 1.14 + **/ +guint16 +nm_setting_wpan_get_short_address (NMSettingWpan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WPAN (setting), G_MAXUINT16); + + return NM_SETTING_WPAN_GET_PRIVATE (setting)->short_address; +} + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (setting); + + if (priv->mac_address && !nm_utils_hwaddr_valid (priv->mac_address, IEEE802154_ADDR_LEN)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_MAC_ADDRESS); + return FALSE; + } + + return TRUE; +} + +static void +get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingWpan *setting = NM_SETTING_WPAN (object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_value_set_string (value, nm_setting_wpan_get_mac_address (setting)); + break; + case PROP_PAN_ID: + g_value_set_uint (value, nm_setting_wpan_get_pan_id (setting)); + break; + case PROP_SHORT_ADDRESS: + g_value_set_uint (value, nm_setting_wpan_get_short_address (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_MAC_ADDRESS: + g_free (priv->mac_address); + priv->mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value), + IEEE802154_ADDR_LEN); + break; + case PROP_PAN_ID: + priv->pan_id = g_value_get_uint (value); + break; + case PROP_SHORT_ADDRESS: + priv->short_address = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_wpan_init (NMSettingWpan *setting) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (setting); + + priv->short_address = G_MAXUINT16; + priv->pan_id = G_MAXUINT16; +} + +/** + * nm_setting_wpan_new: + * + * Creates a new #NMSettingWpan object with default values. + * + * Returns: (transfer full): the new empty #NMSettingWpan object + * + * Since: 1.14 + **/ +NMSetting * +nm_setting_wpan_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_WPAN, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (object); + + g_free (priv->mac_address); + + G_OBJECT_CLASS (nm_setting_wpan_parent_class)->finalize (object); +} + +static void +nm_setting_wpan_class_init (NMSettingWpanClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingClass *setting_class = NM_SETTING_CLASS (klass); + + g_type_class_add_private (setting_class, sizeof (NMSettingWpanPrivate)); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingWpan:mac-address: + * + * If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) + * MAC layer device whose permanent MAC address matches. + **/ + /* ---keyfile--- + * property: mac-address + * format: usual hex-digits-and-colons notation + * description: MAC address in hex-digits-and-colons notation + * (e.g. 76:d8:9b:87:66:60:84:ee). + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_MAC_ADDRESS, + g_param_spec_string (NM_SETTING_WPAN_MAC_ADDRESS, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingWpan:pan-id: + * + * IEEE 802.15.4 Personal Area Network (PAN) identifier. + **/ + g_object_class_install_property + (object_class, PROP_PAN_ID, + g_param_spec_uint (NM_SETTING_WPAN_PAN_ID, "", "", + 0, G_MAXUINT16, G_MAXUINT16, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingWpan:short-address: + * + * Short IEEE 802.15.4 address to be used within a restricted environment. + **/ + g_object_class_install_property + (object_class, PROP_SHORT_ADDRESS, + g_param_spec_uint (NM_SETTING_WPAN_SHORT_ADDRESS, "", "", + 0, G_MAXUINT16, G_MAXUINT16, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_WPAN); +} diff --git a/libnm-core/nm-setting-wpan.h b/libnm-core/nm-setting-wpan.h new file mode 100644 index 00000000..a39e377e --- /dev/null +++ b/libnm-core/nm-setting-wpan.h @@ -0,0 +1,59 @@ +/* + * 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 Lubomir Rintel <lkundrak@v3.sk> + */ + +#ifndef __NM_SETTING_WPAN_H__ +#define __NM_SETTING_WPAN_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WPAN (nm_setting_wpan_get_type ()) +#define NM_SETTING_WPAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WPAN, NMSettingWpan)) +#define NM_SETTING_WPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WPANCONFIG, NMSettingWpanClass)) +#define NM_IS_SETTING_WPAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WPAN)) +#define NM_IS_SETTING_WPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WPAN)) +#define NM_SETTING_WPAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WPAN, NMSettingWpanClass)) + +#define NM_SETTING_WPAN_SETTING_NAME "wpan" +#define NM_SETTING_WPAN_MAC_ADDRESS "mac-address" +#define NM_SETTING_WPAN_PAN_ID "pan-id" +#define NM_SETTING_WPAN_SHORT_ADDRESS "short-address" + +typedef struct _NMSettingWpanClass NMSettingWpanClass; + +NM_AVAILABLE_IN_1_14 +GType nm_setting_wpan_get_type (void); +NM_AVAILABLE_IN_1_14 +NMSetting *nm_setting_wpan_new (void); + +NM_AVAILABLE_IN_1_14 +const char *nm_setting_wpan_get_mac_address (NMSettingWpan *setting); +NM_AVAILABLE_IN_1_14 +guint16 nm_setting_wpan_get_pan_id (NMSettingWpan *setting); +NM_AVAILABLE_IN_1_14 +guint16 nm_setting_wpan_get_short_address (NMSettingWpan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_WPAN_H__ */ diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 218f0dad..0cec5165 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -53,9 +53,13 @@ * of properties and allowed values. */ -G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) +/*****************************************************************************/ -#define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate)) +typedef struct { + GHashTable *hash; + const char **names; + GVariant **values; +} GenData; typedef struct { const char *name; @@ -63,10 +67,6 @@ typedef struct { NMSettingPriority priority; } SettingInfo; -typedef struct { - const SettingInfo *info; -} NMSettingPrivate; - enum { PROP_0, PROP_NAME, @@ -74,136 +74,66 @@ enum { PROP_LAST }; -/*****************************************************************************/ - -static GHashTable *registered_settings = NULL; -static GHashTable *registered_settings_by_type = NULL; - -static gboolean -_nm_gtype_equal (gconstpointer v1, gconstpointer v2) -{ - return *((const GType *) v1) == *((const GType *) v2); -} -static guint -_nm_gtype_hash (gconstpointer v) -{ - return *((const GType *) v); -} - -static void -_ensure_registered (void) -{ - if (G_UNLIKELY (registered_settings == NULL)) { - registered_settings = g_hash_table_new (nm_str_hash, g_str_equal); - registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal); - } -} +typedef struct { + GenData *gendata; +} NMSettingPrivate; -static void __attribute__((constructor)) -_ensure_registered_constructor (void) -{ - _ensure_registered (); -} +G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) -#define _ensure_setting_info(self, priv) \ - G_STMT_START { \ - NMSettingPrivate *_priv_esi = (priv); \ - if (G_UNLIKELY (!_priv_esi->info)) { \ - _priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \ - g_assert (_priv_esi->info); \ - } \ - } G_STMT_END +#define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate)) /*****************************************************************************/ -/* - * _nm_register_setting_impl: - * @name: the name of the #NMSetting object to register - * @type: the #GType of the #NMSetting - * @priority: the sort priority of the setting, see #NMSettingPriority - * - * INTERNAL ONLY: registers a setting's internal properties with libnm. - */ -void -_nm_register_setting_impl (const char *name, - GType type, - NMSettingPriority priority) -{ - SettingInfo *info; - - nm_assert (name && *name); - nm_assert (!NM_IN_SET (type, G_TYPE_INVALID, G_TYPE_NONE)); - nm_assert (priority != NM_SETTING_PRIORITY_INVALID); - - _ensure_registered (); - - nm_assert (!g_hash_table_lookup (registered_settings, name)); - nm_assert (!g_hash_table_lookup (registered_settings_by_type, &type)); - - nm_assert ( priority != NM_SETTING_PRIORITY_CONNECTION - || nm_streq (name, NM_SETTING_CONNECTION_SETTING_NAME)); +static GenData *_gendata_hash (NMSetting *setting, gboolean create_if_necessary); - info = g_slice_new0 (SettingInfo); - info->type = type; - info->priority = priority; - info->name = name; - g_hash_table_insert (registered_settings, (void *) info->name, info); - g_hash_table_insert (registered_settings_by_type, &info->type, info); -} - -static const SettingInfo * -_nm_setting_lookup_setting_by_type (GType type) -{ - _ensure_registered (); - return g_hash_table_lookup (registered_settings_by_type, &type); -} +/*****************************************************************************/ static NMSettingPriority -_get_setting_type_priority (GType type) +_get_base_type_priority (const NMMetaSettingInfo *setting_info, + GType gtype) { - const SettingInfo *info; + /* Historical oddity: PPPoE is a base-type even though it's not + * priority 1. It needs to be sorted *after* lower-level stuff like + * Wi-Fi security or 802.1x for secrets, but it's still allowed as a + * base type. + */ - g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32); + if (setting_info) { + if ( NM_IN_SET (setting_info->setting_priority, + NM_SETTING_PRIORITY_HW_BASE, + NM_SETTING_PRIORITY_HW_NON_BASE) + || gtype == NM_TYPE_SETTING_PPPOE) + return setting_info->setting_priority; + } - info = _nm_setting_lookup_setting_by_type (type); - return info->priority; + return NM_SETTING_PRIORITY_INVALID; } NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting) { - NMSettingPrivate *priv; + const NMMetaSettingInfo *setting_info; - g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32); - priv = NM_SETTING_GET_PRIVATE (setting); - _ensure_setting_info (setting, priv); - return priv->info->priority; + g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_PRIORITY_INVALID); + + setting_info = NM_SETTING_GET_CLASS (setting)->setting_info; + return setting_info ? setting_info->setting_priority : NM_SETTING_PRIORITY_INVALID; } NMSettingPriority _nm_setting_type_get_base_type_priority (GType type) { - NMSettingPriority priority; - - /* Historical oddity: PPPoE is a base-type even though it's not - * priority 1. It needs to be sorted *after* lower-level stuff like - * Wi-Fi security or 802.1x for secrets, but it's still allowed as a - * base type. - */ - priority = _get_setting_type_priority (type); - if ( NM_IN_SET (priority, - NM_SETTING_PRIORITY_HW_BASE, - NM_SETTING_PRIORITY_HW_NON_BASE) - || type == NM_TYPE_SETTING_PPPOE) - return priority; - else - return NM_SETTING_PRIORITY_INVALID; + return _get_base_type_priority (nm_meta_setting_infos_by_gtype (type), + type); } NMSettingPriority _nm_setting_get_base_type_priority (NMSetting *setting) { - return _nm_setting_type_get_base_type_priority (G_OBJECT_TYPE (setting)); + g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_PRIORITY_INVALID); + + return _get_base_type_priority (NM_SETTING_GET_CLASS (setting)->setting_info, + G_OBJECT_TYPE (setting)); } /** @@ -218,17 +148,15 @@ _nm_setting_get_base_type_priority (NMSetting *setting) GType nm_setting_lookup_type (const char *name) { - const SettingInfo *info; + const NMMetaSettingInfo *setting_info; g_return_val_if_fail (name, G_TYPE_INVALID); - _ensure_registered (); - - info = g_hash_table_lookup (registered_settings, name); - return info ? info->type : G_TYPE_INVALID; + setting_info = nm_meta_setting_infos_by_name (name); + return setting_info ? setting_info->get_setting_gtype () : G_TYPE_INVALID; } -gint +int _nm_setting_compare_priority (gconstpointer a, gconstpointer b) { NMSettingPriority prio_a, prio_b; @@ -273,90 +201,53 @@ _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_t /*****************************************************************************/ -typedef struct { - const char *name; - GParamSpec *param_spec; - const GVariantType *dbus_type; - - NMSettingPropertyGetFunc get_func; - NMSettingPropertySynthFunc synth_func; - NMSettingPropertySetFunc set_func; - NMSettingPropertyNotSetFunc not_set_func; - - NMSettingPropertyTransformToFunc to_dbus; - NMSettingPropertyTransformFromFunc from_dbus; -} NMSettingProperty; - -static NM_CACHED_QUARK_FCN ("nm-setting-property-overrides", setting_property_overrides_quark) -static NM_CACHED_QUARK_FCN ("nm-setting-properties", setting_properties_quark) - -static NMSettingProperty * -find_property (GArray *properties, const char *name) +static const NMSettInfoProperty * +_nm_sett_info_property_find_in_array (const NMSettInfoProperty *properties, guint len, const char *name) { - NMSettingProperty *property; - int i; - - if (!properties) - return NULL; + guint i; - for (i = 0; i < properties->len; i++) { - property = &g_array_index (properties, NMSettingProperty, i); - if (strcmp (name, property->name) == 0) - return property; + for (i = 0; i < len; i++) { + if (nm_streq (name, properties[i].name)) + return &properties[i]; } - return NULL; } -static void -add_property_override (NMSettingClass *setting_class, - const char *property_name, - GParamSpec *param_spec, - const GVariantType *dbus_type, - NMSettingPropertyGetFunc get_func, - NMSettingPropertySynthFunc synth_func, - NMSettingPropertySetFunc set_func, - NMSettingPropertyNotSetFunc not_set_func, - NMSettingPropertyTransformToFunc to_dbus, - NMSettingPropertyTransformFromFunc from_dbus) +void +_properties_override_add_struct (GArray *properties_override, + const NMSettInfoProperty *prop_info) { - GType setting_type = G_TYPE_FROM_CLASS (setting_class); - GArray *overrides; - NMSettingProperty override; - - g_return_if_fail (g_type_get_qdata (setting_type, setting_properties_quark ()) == NULL); - - memset (&override, 0, sizeof (override)); - override.name = property_name; - override.param_spec = param_spec; - override.dbus_type = dbus_type; - override.get_func = get_func; - override.synth_func = synth_func; - override.set_func = set_func; - override.not_set_func = not_set_func; - override.to_dbus = to_dbus; - override.from_dbus = from_dbus; - - overrides = g_type_get_qdata (setting_type, setting_property_overrides_quark ()); - if (!overrides) { - overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty)); - g_type_set_qdata (setting_type, setting_property_overrides_quark (), overrides); + nm_assert (properties_override); + nm_assert (prop_info); + nm_assert (prop_info->name || prop_info->param_spec); + nm_assert (!prop_info->param_spec || !prop_info->name || nm_streq0 (prop_info->name, prop_info->param_spec->name)); + nm_assert (!_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data, + properties_override->len, + prop_info->name ?: prop_info->param_spec->name)); + + nm_assert (!prop_info->from_dbus || prop_info->dbus_type); + nm_assert (!prop_info->set_func || prop_info->dbus_type); + + g_array_append_vals (properties_override, prop_info, 1); + + if (!prop_info->name) { + /* for convenience, allow omitting "name" if "param_spec" is given. */ + g_array_index (properties_override, + NMSettInfoProperty, + properties_override->len - 1).name = prop_info->param_spec->name; } - g_return_if_fail (find_property (overrides, property_name) == NULL); - - g_array_append_val (overrides, override); } /** - * _nm_setting_class_add_dbus_only_property: - * @setting_class: the setting class + * _properties_override_add_dbus_only: + * @properties_override: an array collecting the overrides * @property_name: the name of the property to override * @dbus_type: the type of the property (in its D-Bus representation) * @synth_func: (allow-none): function to call to synthesize a value for the property * @set_func: (allow-none): function to call to set the value of the property * * Registers a property named @property_name, which will be used in the D-Bus - * serialization of objects of @setting_class, but which does not correspond to + * serialization of objects of this setting type, but which does not correspond to * a #GObject property. * * When serializing a setting to D-Bus, @synth_func will be called to synthesize @@ -369,35 +260,30 @@ add_property_override (NMSettingClass *setting_class, * then the property will be ignored when deserializing.) */ void -_nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertySynthFunc synth_func, - NMSettingPropertySetFunc set_func) +_properties_override_add_dbus_only (GArray *properties_override, + const char *property_name, + const GVariantType *dbus_type, + NMSettingPropertySynthFunc synth_func, + NMSettingPropertySetFunc set_func) { - g_return_if_fail (NM_IS_SETTING_CLASS (setting_class)); - g_return_if_fail (property_name != NULL); - - /* Must not match any GObject property. */ - g_return_if_fail (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name)); - - add_property_override (setting_class, - property_name, NULL, dbus_type, - NULL, synth_func, set_func, NULL, - NULL, NULL); + _properties_override_add (properties_override, + .name = property_name, + .dbus_type = dbus_type, + .synth_func = synth_func, + .set_func = set_func); } /** - * _nm_setting_class_override_property: - * @setting_class: the setting class - * @property_name: the name of the property to override + * _properties_override_add_override: + * @properties_override: an array collecting the overrides + * @param_spec: the name of the property to override * @dbus_type: the type of the property (in its D-Bus representation) * @get_func: (allow-none): function to call to get the value of the property * @set_func: (allow-none): function to call to set the value of the property * @not_set_func: (allow-none): function to call to indicate the property was not set * - * Overrides the D-Bus representation of the #GObject property named - * @property_name on @setting_class. + * Overrides the D-Bus representation of the #GObject property that shares the + * same name as @param_spec. * * When serializing a setting to D-Bus, if @get_func is non-%NULL, then it will * be called to get the property's value. If it returns a #GVariant, the @@ -406,38 +292,38 @@ _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, * with g_object_get_property(), and added to the hash if it is not the default * value.) * - * When deserializing a D-Bus representation into a setting, if @property_name - * is present, then @set_func will be called to set it. (If @set_func is %NULL - * then the property will be set normally with g_object_set_property().) + * When deserializing a D-Bus representation into a setting, if a value with + * the name of @param_spec is present, then @set_func will be called to set it. + * (If @set_func is %NULL then the property will be set normally with + * g_object_set_property().) * * If @not_set_func is non-%NULL, then it will be called when deserializing a - * representation that does NOT contain @property_name. This can be used, eg, if - * a new property needs to be initialized from some older deprecated property + * representation that does NOT contain a value for the property. This can be used, + * eg, if a new property needs to be initialized from some older deprecated property * when it is not present. */ void -_nm_setting_class_override_property (NMSettingClass *setting_class, - const char *property_name, - const GVariantType *dbus_type, - NMSettingPropertyGetFunc get_func, - NMSettingPropertySetFunc set_func, - NMSettingPropertyNotSetFunc not_set_func) +_properties_override_add_override (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyGetFunc get_func, + NMSettingPropertySetFunc set_func, + NMSettingPropertyNotSetFunc not_set_func) { - GParamSpec *param_spec; - - param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name); - g_return_if_fail (param_spec != NULL); - - add_property_override (setting_class, - property_name, param_spec, dbus_type, - get_func, NULL, set_func, not_set_func, - NULL, NULL); + nm_assert (param_spec); + + _properties_override_add (properties_override, + .param_spec = param_spec, + .dbus_type = dbus_type, + .get_func = get_func, + .set_func = set_func, + .not_set_func = not_set_func); } /** - * _nm_setting_class_transform_property: - * @setting_class: the setting class - * @property: the name of the property to transform + * _properties_override_add_transform: + * @properties_override: an array collecting the overrides + * @param_spec: the param spec of the property to transform. * @dbus_type: the type of the property (in its D-Bus representation) * @to_dbus: function to convert from object to D-Bus format * @from_dbus: function to convert from D-Bus to object format @@ -451,23 +337,143 @@ _nm_setting_class_override_property (NMSettingClass *setting_class, * nm_property_compare() recognizes, as long as it recognizes @dbus_type. */ void -_nm_setting_class_transform_property (NMSettingClass *setting_class, - const char *property, - const GVariantType *dbus_type, - NMSettingPropertyTransformToFunc to_dbus, - NMSettingPropertyTransformFromFunc from_dbus) +_properties_override_add_transform (GArray *properties_override, + GParamSpec *param_spec, + const GVariantType *dbus_type, + NMSettingPropertyTransformToFunc to_dbus, + NMSettingPropertyTransformFromFunc from_dbus) +{ + nm_assert (param_spec); + + _properties_override_add (properties_override, + .param_spec = param_spec, + .dbus_type = dbus_type, + .to_dbus = to_dbus, + .from_dbus = from_dbus); +} + +static NMSettInfoSetting _sett_info_settings[_NM_META_SETTING_TYPE_NUM]; + +void +_nm_setting_class_commit_full (NMSettingClass *setting_class, + NMMetaSettingType meta_type, + const NMSettInfoSettDetail *detail, + GArray *properties_override) +{ + NMSettInfoSetting *sett_info; + gs_free GParamSpec **property_specs = NULL; + guint i, n_property_specs, override_len; + + nm_assert (NM_IS_SETTING_CLASS (setting_class)); + nm_assert (!setting_class->setting_info); + + nm_assert (meta_type < G_N_ELEMENTS (_sett_info_settings)); + + sett_info = &_sett_info_settings[meta_type]; + + nm_assert (!sett_info->setting_class); + nm_assert (!sett_info->property_infos_len); + nm_assert (!sett_info->property_infos); + + if (!properties_override) { + override_len = 0; + properties_override = _nm_sett_info_property_override_create_array (); + } else + override_len = properties_override->len; + + property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class), + &n_property_specs); + +#if NM_MORE_ASSERTS > 10 + /* assert that properties_override is constructed consistently. */ + for (i = 0; i < override_len; i++) { + guint j; + const NMSettInfoProperty *p = &g_array_index (properties_override, NMSettInfoProperty, i); + + nm_assert (!_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data, + i, + p->name)); + for (j = 0; j < n_property_specs; j++) { + if (nm_streq (property_specs[j]->name, p->name)) { + nm_assert (p->param_spec == property_specs[j]); + break; + } + } + nm_assert ((j == n_property_specs) == (p->param_spec == NULL)); + } +#endif + + for (i = 0; i < n_property_specs; i++) { + const char *name = property_specs[i]->name; + NMSettInfoProperty *p; + + if (_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data, + override_len, + name)) + continue; + + g_array_set_size (properties_override, properties_override->len + 1); + p = &g_array_index (properties_override, NMSettInfoProperty, properties_override->len - 1); + memset (p, 0, sizeof (*p)); + p->name = name; + p->param_spec = property_specs[i]; + } + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMSettInfoProperty, name) == 0); + g_array_sort (properties_override, nm_strcmp_p); + + setting_class->setting_info = &nm_meta_setting_infos[meta_type]; + sett_info->setting_class = setting_class; + if (detail) + sett_info->detail = *detail; + sett_info->property_infos_len = properties_override->len; + sett_info->property_infos = (const NMSettInfoProperty *) g_array_free (properties_override, + properties_override->len == 0); +} + +const NMSettInfoSetting * +_nm_sett_info_setting_get (NMSettingClass *setting_class) { - GParamSpec *param_spec; + if ( NM_IS_SETTING_CLASS (setting_class) + && setting_class->setting_info) { + nm_assert (setting_class->setting_info->meta_type < G_N_ELEMENTS (_sett_info_settings)); + return &_sett_info_settings[setting_class->setting_info->meta_type]; + } + return NULL; +} + +const NMSettInfoProperty * +_nm_sett_info_property_get (NMSettingClass *setting_class, + const char *property_name) +{ + const NMSettInfoSetting *sett_info = _nm_sett_info_setting_get (setting_class); + const NMSettInfoProperty *property; + gssize idx; + + if (!sett_info) + return NULL; + + G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMSettInfoProperty, name) == 0); + idx = nm_utils_array_find_binary_search (sett_info->property_infos, + sizeof (NMSettInfoProperty), + sett_info->property_infos_len, + &property_name, + nm_strcmp_p_with_data, + NULL); + + if (idx < 0) + return NULL; + + property = &sett_info->property_infos[idx]; - param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property); - g_return_if_fail (param_spec != NULL); + nm_assert (idx == 0 || strcmp (property[-1].name, property[0].name) < 0); + nm_assert (idx == sett_info->property_infos_len - 1 || strcmp (property[0].name, property[1].name) < 0); - add_property_override (setting_class, - property, param_spec, dbus_type, - NULL, NULL, NULL, NULL, - to_dbus, from_dbus); + return property; } +/*****************************************************************************/ + gboolean _nm_setting_use_legacy_property (NMSetting *setting, GVariant *connection_dict, @@ -504,77 +510,6 @@ _nm_setting_use_legacy_property (NMSetting *setting, return FALSE; } -static GArray * -nm_setting_class_ensure_properties (NMSettingClass *setting_class) -{ - GType type = G_TYPE_FROM_CLASS (setting_class), otype; - NMSettingProperty property, *override; - GArray *overrides, *type_overrides, *properties; - GParamSpec **property_specs; - guint n_property_specs, i; - - properties = g_type_get_qdata (type, setting_properties_quark ()); - if (properties) - return properties; - - /* Build overrides array from @setting_class and its superclasses */ - overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty)); - for (otype = type; otype != G_TYPE_OBJECT; otype = g_type_parent (otype)) { - type_overrides = g_type_get_qdata (otype, setting_property_overrides_quark ()); - if (type_overrides) - g_array_append_vals (overrides, (NMSettingProperty *)type_overrides->data, type_overrides->len); - } - - /* Build the properties array from the GParamSpecs, obeying overrides */ - properties = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty)); - - property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class), - &n_property_specs); - for (i = 0; i < n_property_specs; i++) { - override = find_property (overrides, property_specs[i]->name); - if (override) - property = *override; - else { - memset (&property, 0, sizeof (property)); - property.name = property_specs[i]->name; - property.param_spec = property_specs[i]; - } - g_array_append_val (properties, property); - } - g_free (property_specs); - - /* Add any remaining overrides not corresponding to GObject properties */ - for (i = 0; i < overrides->len; i++) { - override = &g_array_index (overrides, NMSettingProperty, i); - if (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), override->name)) - g_array_append_val (properties, *override); - } - g_array_unref (overrides); - - g_type_set_qdata (type, setting_properties_quark (), properties); - return properties; -} - -static const NMSettingProperty * -nm_setting_class_get_properties (NMSettingClass *setting_class, guint *n_properties) -{ - GArray *properties; - - properties = nm_setting_class_ensure_properties (setting_class); - - *n_properties = properties->len; - return (NMSettingProperty *) properties->data; -} - -static const NMSettingProperty * -nm_setting_class_find_property (NMSettingClass *setting_class, const char *property_name) -{ - GArray *properties; - - properties = nm_setting_class_ensure_properties (setting_class); - return find_property (properties, property_name); -} - /*****************************************************************************/ static const GVariantType * @@ -610,7 +545,7 @@ variant_type_for_gtype (GType type) static GVariant * get_property_for_dbus (NMSetting *setting, - const NMSettingProperty *property, + const NMSettInfoProperty *property, gboolean ignore_default) { GValue prop_value = { 0, }; @@ -638,7 +573,7 @@ get_property_for_dbus (NMSetting *setting, else if (g_type_is_a (prop_value.g_type, G_TYPE_FLAGS)) dbus_value = g_variant_new_uint32 (g_value_get_flags (&prop_value)); else if (prop_value.g_type == G_TYPE_BYTES) - dbus_value = _nm_utils_bytes_to_dbus (&prop_value); + dbus_value = nm_utils_gbytes_to_variant_ay (g_value_get_boxed (&prop_value)); else dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type)); g_value_unset (&prop_value); @@ -647,7 +582,7 @@ get_property_for_dbus (NMSetting *setting, } static gboolean -set_property_from_dbus (const NMSettingProperty *property, +set_property_from_dbus (const NMSettInfoProperty *property, GVariant *src_value, GValue *dst_value) { @@ -698,40 +633,57 @@ set_property_from_dbus (const NMSettingProperty *property, GVariant * _nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags) { + NMSettingPrivate *priv; GVariantBuilder builder; GVariant *dbus_value; - const NMSettingProperty *properties; + const NMSettInfoSetting *sett_info; guint n_properties, i; + const char *const*gendata_keys; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties); + priv = NM_SETTING_GET_PRIVATE (setting); g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING); + n_properties = _nm_setting_gendata_get_all (setting, &gendata_keys, NULL); for (i = 0; i < n_properties; i++) { - const NMSettingProperty *property = &properties[i]; + g_variant_builder_add (&builder, + "{sv}", + gendata_keys[i], + g_hash_table_lookup (priv->gendata->hash, gendata_keys[i])); + } + + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty *property = &sett_info->property_infos[i]; GParamSpec *prop_spec = property->param_spec; - if (!prop_spec && !property->synth_func) { - /* D-Bus-only property with no synth_func, so we skip it. */ - continue; - } + if (!prop_spec) { + if (!property->synth_func) + continue; - if (prop_spec && !(prop_spec->flags & G_PARAM_WRITABLE)) - continue; + if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + continue; + } else { + if (!(prop_spec->flags & G_PARAM_WRITABLE)) + continue; - if ( prop_spec && (prop_spec->flags & NM_SETTING_PARAM_LEGACY) - && !_nm_utils_is_manager_process) - continue; + if (NM_FLAGS_ANY (prop_spec->flags, NM_SETTING_PARAM_GENDATA_BACKED)) + continue; - if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS) - && (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET))) - continue; + if ( (prop_spec->flags & NM_SETTING_PARAM_LEGACY) + && !_nm_utils_is_manager_process) + continue; - if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) - && !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET))) - continue; + if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS) + && (prop_spec->flags & NM_SETTING_PARAM_SECRET)) + continue; + + if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS) + && !(prop_spec->flags & NM_SETTING_PARAM_SECRET)) + continue; + } if (property->synth_func) dbus_value = property->synth_func (setting, connection, property->name); @@ -778,8 +730,8 @@ _nm_setting_new_from_dbus (GType setting_type, { gs_unref_object NMSetting *setting = NULL; gs_unref_hashtable GHashTable *keys = NULL; - const NMSettingProperty *properties; - guint i, n_properties; + const NMSettInfoSetting *sett_info; + guint i; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL); @@ -823,9 +775,29 @@ _nm_setting_new_from_dbus (GType setting_type, } } - properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties); - for (i = 0; i < n_properties; i++) { - const NMSettingProperty *property = &properties[i]; + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + GHashTable *hash; + GVariantIter iter; + char *key; + GVariant *val; + + hash = _gendata_hash (setting, TRUE)->hash; + + g_variant_iter_init (&iter, setting_dict); + while (g_variant_iter_next (&iter, "{sv}", &key, &val)) { + g_hash_table_insert (hash, + key, + val); + } + + _nm_setting_gendata_notify (setting, TRUE); + return g_steal_pointer (&setting); + } + + for (i = 0; i < sett_info->property_infos_len; i++) { + const NMSettInfoProperty *property = &sett_info->property_infos[i]; gs_unref_variant GVariant *value = NULL; gs_free_error GError *local = NULL; @@ -944,12 +916,12 @@ const GVariantType * nm_setting_get_dbus_property_type (NMSetting *setting, const char *property_name) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); g_return_val_if_fail (property_name != NULL, NULL); - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), property_name); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), property_name); g_return_val_if_fail (property != NULL, NULL); if (property->dbus_type) @@ -961,14 +933,32 @@ nm_setting_get_dbus_property_type (NMSetting *setting, gboolean _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value) { + const NMSettInfoSetting *sett_info; GParamSpec *prop_spec; g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); g_return_val_if_fail (property_name, FALSE); g_return_val_if_fail (value, FALSE); - prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + GVariant *variant; + GenData *gendata = _gendata_hash (setting, FALSE); + + variant = gendata ? g_hash_table_lookup (gendata->hash, property_name) : NULL; + + if (!variant) { + g_value_unset (value); + return FALSE; + } + + g_value_init (value, G_TYPE_VARIANT); + g_value_set_variant (value, variant); + return TRUE; + } + prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); if (!prop_spec) { g_value_unset (value); return FALSE; @@ -1002,16 +992,37 @@ duplicate_setting (NMSetting *setting, NMSetting * nm_setting_duplicate (NMSetting *setting) { + const NMSettInfoSetting *sett_info; GObject *dup; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); dup = g_object_new (G_OBJECT_TYPE (setting), NULL); - g_object_freeze_notify (dup); - nm_setting_enumerate_values (setting, duplicate_setting, dup); - g_object_thaw_notify (dup); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + GenData *gendata = _gendata_hash (setting, FALSE); + + if ( gendata + && g_hash_table_size (gendata->hash) > 0) { + GHashTableIter iter; + GHashTable *h = _gendata_hash (NM_SETTING (dup), TRUE)->hash; + const char *key; + GVariant *val; + g_hash_table_iter_init (&iter, gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + g_hash_table_insert (h, + g_strdup (key), + g_variant_ref (val)); + } + } + } else { + g_object_freeze_notify (dup); + nm_setting_enumerate_values (setting, duplicate_setting, dup); + g_object_thaw_notify (dup); + } return NM_SETTING (dup); } @@ -1027,12 +1038,12 @@ nm_setting_duplicate (NMSetting *setting) const char * nm_setting_get_name (NMSetting *setting) { - NMSettingPrivate *priv; + const NMMetaSettingInfo *setting_info; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - priv = NM_SETTING_GET_PRIVATE (setting); - _ensure_setting_info (setting, priv); - return priv->info->name; + + setting_info = NM_SETTING_GET_CLASS (setting)->setting_info; + return setting_info ? setting_info->setting_name : NULL; } /** @@ -1126,7 +1137,7 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; GVariant *value1, *value2; int cmp; @@ -1158,7 +1169,7 @@ compare_property (NMSetting *setting, return TRUE; } - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), prop_spec->name); g_return_val_if_fail (property != NULL, FALSE); value1 = get_property_for_dbus (setting, property, TRUE); @@ -1191,9 +1202,10 @@ nm_setting_compare (NMSetting *a, NMSetting *b, NMSettingCompareFlags flags) { + const NMSettInfoSetting *sett_info; GParamSpec **property_specs; guint n_property_specs; - gint same = TRUE; + int same = TRUE; guint i; g_return_val_if_fail (NM_IS_SETTING (a), FALSE); @@ -1203,6 +1215,18 @@ nm_setting_compare (NMSetting *a, if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b)) return FALSE; + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (a)); + + if (sett_info->detail.gendata_info) { + GenData *a_gendata = _gendata_hash (a, FALSE); + GenData *b_gendata = _gendata_hash (b, FALSE); + + return nm_utils_hash_table_equal (a_gendata ? a_gendata->hash : NULL, + b_gendata ? b_gendata->hash : NULL, + TRUE, + g_variant_equal); + } + /* And now all properties */ property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); for (i = 0; i < n_property_specs && same; i++) { @@ -1288,6 +1312,21 @@ should_compare_prop (NMSetting *setting, return TRUE; } +static void +_setting_diff_add_result (GHashTable *results, const char *prop_name, NMSettingDiffResult r) +{ + void *p; + + if (r == NM_SETTING_DIFF_RESULT_UNKNOWN) + return; + + if (g_hash_table_lookup_extended (results, prop_name, NULL, &p)) { + if (!NM_FLAGS_ALL ((guint) r, GPOINTER_TO_UINT (p))) + g_hash_table_insert (results, g_strdup (prop_name), GUINT_TO_POINTER (((guint) r) | GPOINTER_TO_UINT (p))); + } else + g_hash_table_insert (results, g_strdup (prop_name), GUINT_TO_POINTER (r)); +} + /** * nm_setting_diff: * @a: a #NMSetting @@ -1316,8 +1355,7 @@ nm_setting_diff (NMSetting *a, gboolean invert_results, GHashTable **results) { - GParamSpec **property_specs; - guint n_property_specs; + const NMSettInfoSetting *sett_info; guint i; NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; @@ -1361,78 +1399,117 @@ nm_setting_diff (NMSetting *a, results_created = TRUE; } - /* And now all properties */ - property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (a)); - for (i = 0; i < n_property_specs; i++) { - GParamSpec *prop_spec = property_specs[i]; - NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; - - /* Handle compare flags */ - if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) - continue; - if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) - continue; - - compared_any = TRUE; - - if (b) { - gboolean different; - - different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); - if (different) { - gboolean a_is_default, b_is_default; + if (sett_info->detail.gendata_info) { + const char *key; + GVariant *val, *val2; + GHashTableIter iter; + GenData *a_gendata = _gendata_hash (a, FALSE); + GenData *b_gendata = b ? _gendata_hash (b, FALSE) : NULL; + + if (!a_gendata || !b_gendata) { + if (a_gendata || b_gendata) { + NMSettingDiffResult one_sided_result; + + one_sided_result = a_gendata ? a_result : b_result; + g_hash_table_iter_init (&iter, a_gendata ? a_gendata->hash : b_gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + diff_found = TRUE; + _setting_diff_add_result (*results, key, one_sided_result); + } + } + } else { + g_hash_table_iter_init (&iter, a_gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + val2 = b_gendata ? g_hash_table_lookup (b_gendata->hash, key) : NULL; + compared_any = TRUE; + if ( !val2 + || !g_variant_equal (val, val2)) { + diff_found = TRUE; + _setting_diff_add_result (*results, key, a_result); + } + } + g_hash_table_iter_init (&iter, b_gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + val2 = a_gendata ? g_hash_table_lookup (a_gendata->hash, key) : NULL; + compared_any = TRUE; + if ( !val2 + || !g_variant_equal (val, val2)) { + diff_found = TRUE; + _setting_diff_add_result (*results, key, b_result); + } + } + } + } else { + gs_free GParamSpec **property_specs = NULL; + guint n_property_specs; + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; + + /* Handle compare flags */ + if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) + continue; + if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) + continue; + + compared_any = TRUE; + + if (b) { + gboolean different; + + different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); + if (different) { + gboolean a_is_default, b_is_default; + GValue value = G_VALUE_INIT; + + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value); + a_is_default = g_param_value_defaults (prop_spec, &value); + + g_value_reset (&value); + g_object_get_property (G_OBJECT (b), prop_spec->name, &value); + b_is_default = g_param_value_defaults (prop_spec, &value); + + g_value_unset (&value); + if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { + if (!a_is_default) + r |= a_result; + if (!b_is_default) + r |= b_result; + } else { + r |= a_result | b_result; + if (a_is_default) + r |= a_result_default; + if (b_is_default) + r |= b_result_default; + } + } + } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) + r = a_result; /* only in A */ + else { GValue value = G_VALUE_INIT; g_value_init (&value, prop_spec->value_type); g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - a_is_default = g_param_value_defaults (prop_spec, &value); - - g_value_reset (&value); - g_object_get_property (G_OBJECT (b), prop_spec->name, &value); - b_is_default = g_param_value_defaults (prop_spec, &value); + if (!g_param_value_defaults (prop_spec, &value)) + r |= a_result; + else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) + r |= a_result | a_result_default; g_value_unset (&value); - if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { - if (!a_is_default) - r |= a_result; - if (!b_is_default) - r |= b_result; - } else { - r |= a_result | b_result; - if (a_is_default) - r |= a_result_default; - if (b_is_default) - r |= b_result_default; - } } - } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) - r = a_result; /* only in A */ - else { - GValue value = G_VALUE_INIT; - g_value_init (&value, prop_spec->value_type); - g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= a_result; - else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) - r |= a_result | a_result_default; - - g_value_unset (&value); - } - - if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { - void *p; - - diff_found = TRUE; - if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) { - if ((r & GPOINTER_TO_UINT (p)) != r) - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p))); - } else - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r)); + if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { + diff_found = TRUE; + _setting_diff_add_result (*results, prop_spec->name, r); + } } } - g_free (property_specs); if (!compared_any && !b) { /* special case: the setting has no properties, and the opposite @@ -1443,7 +1520,7 @@ nm_setting_diff (NMSetting *a, if (diff_found) { /* if there is a difference, we always return FALSE. It also means, we might - * have allocated a new @results hash, and return if to the caller. */ + * have allocated a new @results hash, and return it to the caller. */ return FALSE; } else { if (results_created) { @@ -1499,23 +1576,57 @@ nm_setting_enumerate_values (NMSetting *setting, NMSettingValueIterFn func, gpointer user_data) { + const NMSettInfoSetting *sett_info; GParamSpec **property_specs; - guint n_property_specs; - int i; + guint n_properties; + guint i; GType type; g_return_if_fail (NM_IS_SETTING (setting)); g_return_if_fail (func != NULL); - property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting)); + + if (sett_info->detail.gendata_info) { + const char *const*names; + + /* the properties of this setting are not real GObject properties. + * Hence, this API makes little sense (or does it?). Still, call + * @func with each value. */ + n_properties = _nm_setting_gendata_get_all (setting, &names, NULL); + if (n_properties > 0) { + gs_strfreev char **keys = g_strdupv ((char **) names); + GHashTable *h = _gendata_hash (setting, FALSE)->hash; + + for (i = 0; i < n_properties; i++) { + GValue value = G_VALUE_INIT; + GVariant *val = g_hash_table_lookup (h, keys[i]); + + if (!val) { + /* was deleted in the meantime? Skip */ + continue; + } + + g_value_init (&value, G_TYPE_VARIANT); + g_value_set_variant (&value, val); + /* call it will GParamFlags 0. It shall indicate that this + * is not a "real" GObject property. */ + func (setting, keys[i], &value, 0, user_data); + g_value_unset (&value); + } + } + return; + } + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_properties); /* sort the properties. This has an effect on the order in which keyfile * prints them. */ type = G_OBJECT_TYPE (setting); - g_qsort_with_data (property_specs, n_property_specs, sizeof (gpointer), + g_qsort_with_data (property_specs, n_properties, sizeof (gpointer), (GCompareDataFunc) _enumerate_values_sort, &type); - for (i = 0; i < n_property_specs; i++) { + for (i = 0; i < n_properties; i++) { GParamSpec *prop_spec = property_specs[i]; GValue value = G_VALUE_INIT; @@ -1541,7 +1652,7 @@ nm_setting_enumerate_values (NMSetting *setting, gboolean _nm_setting_clear_secrets (NMSetting *setting) { - GParamSpec **property_specs; + gs_free GParamSpec **property_specs = NULL; guint n_property_specs; guint i; gboolean changed = FALSE; @@ -1549,7 +1660,6 @@ _nm_setting_clear_secrets (NMSetting *setting) g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); - for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; @@ -1566,9 +1676,6 @@ _nm_setting_clear_secrets (NMSetting *setting) g_value_unset (&value); } } - - g_free (property_specs); - return changed; } @@ -1619,7 +1726,7 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting, NMSettingClearSecretsWithFlagsFn func, gpointer user_data) { - GParamSpec **property_specs; + gs_free GParamSpec **property_specs = NULL; guint n_property_specs; guint i; gboolean changed = FALSE; @@ -1637,8 +1744,6 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting, user_data); } } - - g_free (property_specs); return changed; } @@ -1672,11 +1777,11 @@ _nm_setting_need_secrets (NMSetting *setting) static int update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; GParamSpec *prop_spec; GValue prop_value = { 0, }; - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), key); if (!property) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -1765,10 +1870,10 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro static gboolean is_secret_prop (NMSetting *setting, const char *secret_name, GError **error) { - const NMSettingProperty *property; + const NMSettInfoProperty *property; GParamSpec *pspec; - property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name); + property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), secret_name); if (!property) { g_set_error_literal (error, NM_CONNECTION_ERROR, @@ -1888,59 +1993,40 @@ nm_setting_set_secret_flags (NMSetting *setting, * nm_setting_to_string: * @setting: the #NMSetting * - * Convert the setting into a string. For debugging purposes ONLY, should NOT - * be used for serialization of the setting, or machine-parsed in any way. The - * output format is not guaranteed to be stable and may change at any time. + * Convert the setting (including secrets!) into a string. For debugging + * purposes ONLY, should NOT be used for serialization of the setting, + * or machine-parsed in any way. The output format is not guaranteed to + * be stable and may change at any time. * * Returns: an allocated string containing a textual representation of the - * setting's properties and values (including secrets!), which the caller should + * setting's properties and values, which the caller should * free with g_free() **/ char * nm_setting_to_string (NMSetting *setting) { GString *string; - GParamSpec **property_specs; - guint n_property_specs; - guint i; - - g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - - property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + gs_unref_variant GVariant *variant = NULL; + GVariant *child; + GVariantIter iter; string = g_string_new (nm_setting_get_name (setting)); g_string_append_c (string, '\n'); - for (i = 0; i < n_property_specs; i++) { - GParamSpec *prop_spec = property_specs[i]; - GValue value = G_VALUE_INIT; - char *value_str; - gboolean is_default; - - if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) - continue; - - g_value_init (&value, prop_spec->value_type); - g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); + variant = _nm_setting_to_dbus (setting, NULL, NM_CONNECTION_SERIALIZE_ALL); - value_str = g_strdup_value_contents (&value); - g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str); - g_free (value_str); + g_variant_iter_init (&iter, variant); + while ((child = g_variant_iter_next_value (&iter))) { + gs_free char *name = NULL; + gs_free char *value_str = NULL; + gs_unref_variant GVariant *value = NULL; - is_default = g_param_value_defaults (prop_spec, &value); - g_value_unset (&value); + g_variant_get (child, "{sv}", &name, &value); + value_str = g_variant_print (value, FALSE); - g_string_append (string, " ("); - g_string_append_c (string, 's'); - if (is_default) - g_string_append_c (string, 'd'); - g_string_append_c (string, ')'); - g_string_append_c (string, '\n'); + g_string_append_printf (string, "\t%s : %s\n", name, value_str); } - g_free (property_specs); - g_string_append_c (string, '\n'); - return g_string_free (string, FALSE); } @@ -1962,17 +2048,257 @@ _nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting, /*****************************************************************************/ -static void -nm_setting_init (NMSetting *setting) +static GenData * +_gendata_hash (NMSetting *setting, gboolean create_if_necessary) { + NMSettingPrivate *priv; + + nm_assert (NM_IS_SETTING (setting)); + + priv = NM_SETTING_GET_PRIVATE (setting); + + if (G_UNLIKELY (!priv->gendata)) { + if (!create_if_necessary) + return NULL; + priv->gendata = g_slice_new (GenData); + priv->gendata->hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + priv->gendata->names = NULL; + priv->gendata->values = NULL; + } + + return priv->gendata; } -static void -constructed (GObject *object) +GHashTable * +_nm_setting_gendata_hash (NMSetting *setting, gboolean create_if_necessary) { - _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object)); + GenData *gendata; - G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object); + gendata = _gendata_hash (setting, create_if_necessary); + return gendata ? gendata->hash : NULL; +} + +void +_nm_setting_gendata_notify (NMSetting *setting, + gboolean names_changed) +{ + GenData *gendata; + + gendata = _gendata_hash (setting, FALSE); + if (!gendata) + return; + + nm_clear_g_free (&gendata->values); + + if (names_changed) { + /* if only the values changed, it's sufficient to invalidate the + * values cache. Otherwise, the names cache must be invalidated too. */ + nm_clear_g_free (&gendata->names); + } + + /* Note, that currently there is now way to notify the subclass when gendata changed. + * gendata is only changed in two situations: + * 1) from within NMSetting itself, for example when creating a NMSetting instance + * from keyfile or a D-Bus GVariant. + * 2) actively from the subclass itself + * For 2), we don't need the notification, because the subclass knows that something + * changed. + * For 1), we currently don't need the notification either, because all that the subclass + * currently would do, is emit a g_object_notify() signal. However, 1) only happens when + * the setting instance is newly created, at that point, nobody listens to the signal. + * + * If we ever need it, then we would need to call a virtual function to notify the subclass + * that gendata changed. */ +} + +GVariant * +nm_setting_gendata_get (NMSetting *setting, + const char *name) +{ + GenData *gendata; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + g_return_val_if_fail (name, NULL); + + gendata = _gendata_hash (setting, FALSE); + return gendata ? g_hash_table_lookup (gendata->hash, name) : NULL; +} + +guint +_nm_setting_gendata_get_all (NMSetting *setting, + const char *const**out_names, + GVariant *const**out_values) +{ + GenData *gendata; + GHashTable *hash; + guint i, len; + + nm_assert (NM_IS_SETTING (setting)); + + gendata = _gendata_hash (setting, FALSE); + if (!gendata) + goto out_zero; + + hash = gendata->hash; + len = g_hash_table_size (hash); + if (len == 0) + goto out_zero; + + if (!out_names && !out_values) + return len; + + if (G_UNLIKELY (!gendata->names)) { + gendata->names = nm_utils_strdict_get_keys (hash, + TRUE, + NULL); + } + + if (out_values) { + if (G_UNLIKELY (!gendata->values)) { + gendata->values = g_new (GVariant *, len + 1); + for (i = 0; i < len; i++) + gendata->values[i] = g_hash_table_lookup (hash, gendata->names[i]); + gendata->values[i] = NULL; + } + *out_values = gendata->values; + } + + NM_SET_OUT (out_names, (const char *const*) gendata->names); + return len; + +out_zero: + NM_SET_OUT (out_names, NULL); + NM_SET_OUT (out_values, NULL); + return 0; +} + +/** + * nm_setting_gendata_get_all_names: + * @setting: the #NMSetting + * @out_len: (allow-none): (out): + * + * Gives the number of generic data elements and optionally returns all their + * key names and values. This API is low level access and unless you know what you + * are doing, it might not be what you want. + * + * Returns: (array length=out_len zero-terminated=1) (transfer none): + * A %NULL terminated array of key names. If no names are present, this returns + * %NULL. The returned array and the names are owned by %NMSetting and might be invalidated + * soon. + * + * Since: 1.14 + **/ +const char *const* +nm_setting_gendata_get_all_names (NMSetting *setting, + guint *out_len) +{ + const char *const*names; + guint len; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + len = _nm_setting_gendata_get_all (setting, &names, NULL); + NM_SET_OUT (out_len, len); + return names; +} + +/** + * nm_setting_gendata_get_all_values: + * @setting: the #NMSetting + * + * Gives the number of generic data elements and optionally returns all their + * key names and values. This API is low level access and unless you know what you + * are doing, it might not be what you want. + * + * Returns: (array zero-terminated=1) (transfer none): + * A %NULL terminated array of #GVariant. If no data is present, this returns + * %NULL. The returned array and the variants are owned by %NMSetting and might be invalidated + * soon. The sort order of nm_setting_gendata_get_all_names() and nm_setting_gendata_get_all_values() + * is consistent. That means, the nth value has the nth name returned by nm_setting_gendata_get_all_names(). + * + * Since: 1.14 + **/ +GVariant *const* +nm_setting_gendata_get_all_values (NMSetting *setting) +{ + GVariant *const*values; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + _nm_setting_gendata_get_all (setting, NULL, &values); + return values; +} + +void +_nm_setting_gendata_to_gvalue (NMSetting *setting, + GValue *value) +{ + GenData *gendata; + GHashTable *new; + const char *key; + GVariant *val; + GHashTableIter iter; + + nm_assert (NM_IS_SETTING (setting)); + nm_assert (value); + nm_assert (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_HASH_TABLE)); + + new = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + + gendata = _gendata_hash (setting, FALSE); + if (gendata) { + g_hash_table_iter_init (&iter, gendata->hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert (new, g_strdup (key), g_variant_ref (val)); + } + + g_value_take_boxed (value, new); +} + +gboolean +_nm_setting_gendata_reset_from_hash (NMSetting *setting, + GHashTable *new) +{ + GenData *gendata; + GHashTableIter iter; + const char *key; + GVariant *val; + guint num; + + nm_assert (NM_IS_SETTING (setting)); + nm_assert (new); + + num = new ? g_hash_table_size (new) : 0; + + gendata = _gendata_hash (setting, num > 0); + + if (num == 0) { + if ( !gendata + || g_hash_table_size (gendata->hash) == 0) + return FALSE; + + g_hash_table_remove_all (gendata->hash); + _nm_setting_gendata_notify (setting, TRUE); + return TRUE; + } + + /* let's not bother to find out whether the new hash has any different + * content the the current gendata. Just replace it. */ + g_hash_table_remove_all (gendata->hash); + if (num > 0) { + g_hash_table_iter_init (&iter, new); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert (gendata->hash, g_strdup (key), g_variant_ref (val)); + } + _nm_setting_gendata_notify (setting, TRUE); + return TRUE; +} + +/*****************************************************************************/ + +static void +nm_setting_init (NMSetting *setting) +{ } static void @@ -1992,15 +2318,44 @@ get_property (GObject *object, guint prop_id, } static void +finalize (GObject *object) +{ + NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object); + + if (priv->gendata) { + g_free (priv->gendata->names); + g_free (priv->gendata->values); + g_hash_table_unref (priv->gendata->hash); + g_slice_free (GenData, priv->gendata); + } + + G_OBJECT_CLASS (nm_setting_parent_class)->finalize (object); +} + +static void nm_setting_class_init (NMSettingClass *setting_class) { GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + GModule *self_module; + gpointer func; + + /* loading libnm and legacy libraries libnm-util/libnm-glib at the same + * time is not supported. The reason is, that both libraries use the same + * glib type names ("NMSetting"), and glib does not support namespacing + * to allow for that. + * + * Arbitrarily, add a check here, see whether a known symbol from libnm-util + * is present. If it is, it indicates that the process is borked and we + * abort. */ + self_module = g_module_open (NULL, 0); + if (g_module_symbol (self_module, "nm_util_get_private", &func)) + g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported"); + g_module_close (self_module); g_type_class_add_private (setting_class, sizeof (NMSettingPrivate)); - /* virtual methods */ - object_class->constructed = constructed; object_class->get_property = get_property; + object_class->finalize = finalize; setting_class->update_one_secret = update_one_secret; setting_class->get_secret_flags = get_secret_flags; @@ -2008,14 +2363,12 @@ nm_setting_class_init (NMSettingClass *setting_class) setting_class->compare_property = compare_property; setting_class->clear_secrets_with_flags = clear_secrets_with_flags; - /* Properties */ - /** * NMSetting:name: * * The setting's name, which uniquely identifies the setting within the * connection. Each setting type has a name unique to that type, for - * example "ppp" or "wireless" or "wired". + * example "ppp" or "802-11-wireless" or "802-3-ethernet". **/ g_object_class_install_property (object_class, PROP_NAME, diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 47a2fdc1..a7a0f81f 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -168,11 +168,13 @@ typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting, NMSettingSecretFlags flags, gpointer user_data); +struct _NMMetaSettingInfo; + typedef struct { GObjectClass parent; /* Virtual functions */ - gint (*verify) (NMSetting *setting, + int (*verify) (NMSetting *setting, NMConnection *connection, GError **error); @@ -211,7 +213,10 @@ typedef struct { NMSettingCompareFlags flags); /*< private >*/ - gpointer padding[7]; + const struct _NMMetaSettingInfo *setting_info; + + /*< private >*/ + gpointer padding[6]; } NMSettingClass; /** @@ -282,7 +287,8 @@ void nm_setting_enumerate_values (NMSetting *setting, char *nm_setting_to_string (NMSetting *setting); -/* Secrets */ +/*****************************************************************************/ + gboolean nm_setting_get_secret_flags (NMSetting *setting, const char *secret_name, NMSettingSecretFlags *out_flags, @@ -293,10 +299,13 @@ gboolean nm_setting_set_secret_flags (NMSetting *setting, NMSettingSecretFlags flags, GError **error); -/* Properties */ +/*****************************************************************************/ + const GVariantType *nm_setting_get_dbus_property_type (NMSetting *setting, const char *property_name); +/*****************************************************************************/ + G_END_DECLS #endif /* __NM_SETTING_H__ */ diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h index 5d0f8386..b886730a 100644 --- a/libnm-core/nm-utils-private.h +++ b/libnm-core/nm-utils-private.h @@ -74,7 +74,6 @@ GVariant * _nm_utils_strdict_to_dbus (const GValue *prop_value); void _nm_utils_strdict_from_dbus (GVariant *dbus_value, GValue *prop_value); -GVariant * _nm_utils_bytes_to_dbus (const GValue *prop_value); void _nm_utils_bytes_from_dbus (GVariant *dbus_value, GValue *prop_value); @@ -83,6 +82,13 @@ char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize lengt GPtrArray * _nm_utils_team_link_watchers_from_variant (GVariant *value); GVariant * _nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers); +void _nm_utils_format_variant_attributes_full (GString *str, + const NMUtilsNamedValue *values, + guint num_values, + char attr_separator, + char key_value_separator); +gboolean _nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error); + /* JSON to GValue conversion macros */ typedef struct { diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index b700c7f5..47ec7a4e 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -43,7 +43,7 @@ #include "nm-common-macros.h" #include "nm-utils-private.h" #include "nm-setting-private.h" -#include "crypto.h" +#include "nm-crypto.h" #include "nm-setting-bond.h" #include "nm-setting-bridge.h" #include "nm-setting-infiniband.h" @@ -230,31 +230,33 @@ get_system_encodings (void) return cached_encodings; } -/* init libnm */ - -static gboolean initialized = FALSE; +/*****************************************************************************/ static void __attribute__((constructor)) _nm_utils_init (void) { - GModule *self; - gpointer func; + static int initialized = 0; - if (initialized) + if (g_atomic_int_get (&initialized) != 0) return; - initialized = TRUE; - self = g_module_open (NULL, 0); - if (g_module_symbol (self, "nm_util_get_private", &func)) - g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported"); - g_module_close (self); + /* we don't expect this code to run multiple times, nor on multiple threads. + * + * In practice, it would not be a problem if two threads concurrently try to + * run the initialization code below, all code below itself is thread-safe, + * Hence, a poor-man guard "initialized" above is more than sufficient, + * although it does not guarantee that the code is not run concurrently. */ bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); _nm_dbus_errors_init (); + + g_atomic_int_set (&initialized, 1); } +/*****************************************************************************/ + gboolean _nm_utils_is_manager_process; /* ssid helpers */ @@ -300,19 +302,19 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) g_return_val_if_fail (ssid != NULL, NULL); - if (g_utf8_validate ((const gchar *) ssid, len, NULL)) - return g_strndup ((const gchar *) ssid, len); + if (g_utf8_validate ((const char *) ssid, len, NULL)) + return g_strndup ((const char *) ssid, len); encodings = get_system_encodings (); for (e = encodings; *e; e++) { - converted = g_convert ((const gchar *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); + converted = g_convert ((const char *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); if (converted) break; } if (!converted) { - converted = g_convert_with_fallback ((const gchar *) ssid, len, + converted = g_convert_with_fallback ((const char *) ssid, len, "UTF-8", encodings[0], "?", NULL, NULL, NULL); } @@ -323,7 +325,7 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) */ /* Use the printable range of 0x20-0x7E */ - gchar *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@" + char *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@" "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" "abcdefghijklmnopqrstuvwxyz{|}~"; @@ -334,6 +336,18 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) return converted; } +char * +_nm_utils_ssid_to_utf8 (GBytes *ssid) +{ + const guint8 *p; + gsize l; + + g_return_val_if_fail (ssid, NULL); + + p = g_bytes_get_data (ssid, &l); + return nm_utils_ssid_to_utf8 (p, l); +} + /* Shamelessly ripped from the Linux kernel ieee80211 stack */ /** * nm_utils_is_empty_ssid: @@ -361,6 +375,18 @@ nm_utils_is_empty_ssid (const guint8 *ssid, gsize len) return TRUE; } +gboolean +_nm_utils_is_empty_ssid (GBytes *ssid) +{ + const guint8 *p; + gsize l; + + g_return_val_if_fail (ssid, FALSE); + + p = g_bytes_get_data (ssid, &l); + return nm_utils_is_empty_ssid (p, l); +} + #define ESSID_MAX_SIZE 32 /** @@ -402,6 +428,37 @@ nm_utils_escape_ssid (const guint8 *ssid, gsize len) return escaped; } +char * +_nm_utils_ssid_to_string_arr (const guint8 *ssid, gsize len) +{ + char *s_copy; + const char *s_cnst; + + if (len == 0) + return g_strdup ("(empty)"); + + s_cnst = nm_utils_buf_utf8safe_escape (ssid, len, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, &s_copy); + nm_assert (s_cnst); + + if (nm_utils_is_empty_ssid (ssid, len)) + return g_strdup_printf ("\"%s\" (hidden)", s_cnst); + + return g_strdup_printf ("\"%s\"", s_cnst); +} + +char * +_nm_utils_ssid_to_string (GBytes *ssid) +{ + gconstpointer p; + gsize l; + + if (!ssid) + return g_strdup ("(none)"); + + p = g_bytes_get_data (ssid, &l); + return _nm_utils_ssid_to_string_arr (p, l); +} + /** * nm_utils_same_ssid: * @ssid1: (array length=len1): the first SSID to compare @@ -566,39 +623,6 @@ _nm_utils_copy_strdict (GHashTable *strdict) } GPtrArray * -_nm_utils_copy_slist_to_array (const GSList *list, - NMUtilsCopyFunc copy_func, - GDestroyNotify unref_func) -{ - const GSList *iter; - GPtrArray *array; - - array = g_ptr_array_new_with_free_func (unref_func); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (array, copy_func ? copy_func (iter->data) : iter->data); - return array; -} - -GSList * -_nm_utils_copy_array_to_slist (const GPtrArray *array, - NMUtilsCopyFunc copy_func) -{ - GSList *slist = NULL; - gpointer item; - int i; - - if (!array) - return NULL; - - for (i = 0; i < array->len; i++) { - item = array->pdata[i]; - slist = g_slist_prepend (slist, copy_func (item)); - } - - return g_slist_reverse (slist); -} - -GPtrArray * _nm_utils_copy_array (const GPtrArray *array, NMUtilsCopyFunc copy_func, GDestroyNotify free_func) @@ -645,136 +669,6 @@ _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer ne return -1; } -gssize -_nm_utils_ptrarray_find_binary_search (gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data, - gssize *out_idx_first, - gssize *out_idx_last) -{ - gssize imin, imax, imid, i2min, i2max, i2mid; - int cmp; - - g_return_val_if_fail (list || !len, ~((gssize) 0)); - g_return_val_if_fail (cmpfcn, ~((gssize) 0)); - - imin = 0; - if (len > 0) { - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (list[imid], needle, user_data); - if (cmp == 0) { - /* we found a matching entry at index imid. - * - * Does the caller request the first/last index as well (in case that - * there are multiple entries which compare equal). */ - - if (out_idx_first) { - i2min = imin; - i2max = imid + 1; - while (i2min <= i2max) { - i2mid = i2min + (i2max - i2min) / 2; - - cmp = cmpfcn (list[i2mid], needle, user_data); - if (cmp == 0) - i2max = i2mid -1; - else { - nm_assert (cmp < 0); - i2min = i2mid + 1; - } - } - *out_idx_first = i2min; - } - if (out_idx_last) { - i2min = imid + 1; - i2max = imax; - while (i2min <= i2max) { - i2mid = i2min + (i2max - i2min) / 2; - - cmp = cmpfcn (list[i2mid], needle, user_data); - if (cmp == 0) - i2min = i2mid + 1; - else { - nm_assert (cmp > 0); - i2max = i2mid - 1; - } - } - *out_idx_last = i2min - 1; - } - return imid; - } - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - imin = ~imin; - NM_SET_OUT (out_idx_first, imin); - NM_SET_OUT (out_idx_last, imin); - return imin; -} - -gssize -_nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data) -{ - gssize imin, imax, imid; - int cmp; - - g_return_val_if_fail (list || !len, ~((gssize) 0)); - g_return_val_if_fail (cmpfcn, ~((gssize) 0)); - g_return_val_if_fail (elem_size > 0, ~((gssize) 0)); - - imin = 0; - if (len == 0) - return ~imin; - - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn (&((const char *) list)[elem_size * imid], needle, user_data); - if (cmp == 0) - return imid; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - return ~imin; -} - -GVariant * -_nm_utils_bytes_to_dbus (const GValue *prop_value) -{ - GBytes *bytes = g_value_get_boxed (prop_value); - - if (bytes) { - return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - g_bytes_get_data (bytes, NULL), - g_bytes_get_size (bytes), - 1); - } else { - return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - NULL, 0, - 1); - } -} - void _nm_utils_bytes_from_dbus (GVariant *dbus_value, GValue *prop_value) @@ -2648,6 +2542,249 @@ nm_utils_tc_tfilter_from_str (const char *str, GError **error) /*****************************************************************************/ +extern const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[]; + +/** + * nm_utils_sriov_vf_to_str: + * @vf: the %NMSriovVF + * @omit_index: if %TRUE, the VF index will be omitted from output string + * @error: (out) (allow-none): location to store the error on failure + * + * Converts a SR-IOV virtual function object to its string representation. + * + * Returns: a newly allocated string or %NULL on error + * + * Since: 1.14 + */ +char * +nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error) +{ + gs_free NMUtilsNamedValue *values = NULL; + gs_free const char **names = NULL; + const guint *vlan_ids; + guint num_vlans, num_attrs; + guint i; + GString *str; + + str = g_string_new (""); + if (!omit_index) + g_string_append_printf (str, "%u", nm_sriov_vf_get_index (vf)); + + names = nm_sriov_vf_get_attribute_names (vf); + num_attrs = names ? g_strv_length ((char **) names) : 0; + values = g_new0 (NMUtilsNamedValue, num_attrs); + + for (i = 0; i < num_attrs; i++) { + values[i].name = names[i]; + values[i].value_ptr = nm_sriov_vf_get_attribute (vf, names[i]); + } + + if (num_attrs > 0) { + if (!omit_index) + g_string_append_c (str, ' '); + _nm_utils_format_variant_attributes_full (str, values, num_attrs, ' ', '='); + } + + vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans); + if (num_vlans != 0) { + g_string_append (str, " vlans"); + for (i = 0; i < num_vlans; i++) { + guint32 qos; + NMSriovVFVlanProtocol protocol; + + qos = nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]); + protocol = nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]); + + g_string_append_c (str, i == 0 ? '=' : ';'); + + g_string_append_printf (str, "%u", vlan_ids[i]); + + if ( qos != 0 + || protocol != NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q) { + g_string_append_printf (str, + ".%u%s", + (unsigned) qos, + protocol == NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q ? "" : ".ad"); + } + } + } + + return g_string_free (str, FALSE); +} + +gboolean +_nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error) +{ + gs_free const char **vlans = NULL; + guint i; + + vlans = nm_utils_strsplit_set (str, ";", FALSE); + if (!vlans) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "empty VF VLAN"); + return FALSE; + } + + for (i = 0; vlans[i]; i++) { + gs_strfreev char **params = NULL; + guint id = G_MAXUINT; + gint64 qos = -1; + + /* we accept leading/trailing whitespace around vlans[1]. Hence + * the nm_str_skip_leading_spaces() and g_strchomp() below. + * + * However, we don't accept any whitespace inside the specifier. + * Hence the NM_STRCHAR_ALL() checks. */ + + params = g_strsplit (nm_str_skip_leading_spaces (vlans[i]), ".", 3); + if (!params || !params[0] || *params[0] == '\0') { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "empty VF VLAN"); + return FALSE; + } + + if (!params[1]) + g_strchomp (params[0]); + if (NM_STRCHAR_ALL (params[0], ch, ch == 'x' || g_ascii_isdigit (ch))) + id = _nm_utils_ascii_str_to_int64 (params[0], 0, 0, 4095, G_MAXUINT); + if (id == G_MAXUINT) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN id '%s'", + params[0]); + return FALSE; + } + if (!nm_sriov_vf_add_vlan (vf, id)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "duplicate VLAN id %u", + id); + return FALSE; + } + + if (!params[1]) + continue; + + if (!params[2]) + g_strchomp (params[1]); + if (NM_STRCHAR_ALL (params[1], ch, ch == 'x' || g_ascii_isdigit (ch))) + qos = _nm_utils_ascii_str_to_int64 (params[1], 0, 0, G_MAXUINT32, -1); + if (qos == -1) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN QoS '%s'", + params[1]); + return FALSE; + } + nm_sriov_vf_set_vlan_qos (vf, id, qos); + + if (!params[2]) + continue; + + g_strchomp (params[2]); + + if (nm_streq (params[2], "ad")) + nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + else if (nm_streq (params[2], "q")) + nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + else { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid VF VLAN protocol '%s'", + params[2]); + return FALSE; + } + } + + return TRUE; +} + +/** + * nm_utils_sriov_vf_from_str: + * @str: the input string + * @error: (out) (allow-none): location to store the error on failure + * + * Converts a string to a SR-IOV virtual function object. + * + * Returns: (transfer full): the virtual function object + * + * Since: 1.14 + */ +NMSriovVF * +nm_utils_sriov_vf_from_str (const char *str, GError **error) +{ + gs_free char *index_free = NULL; + const char *detail; + + g_return_val_if_fail (str, NULL); + g_return_val_if_fail (!error || !*error, NULL); + + while (*str == ' ') + str++; + + detail = strchr (str, ' '); + if (detail) { + index_free = g_strndup (str, detail - str); + str = index_free; + detail++; + } + + return _nm_utils_sriov_vf_from_strparts (str, detail, error); +} + +NMSriovVF * +_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error) +{ + NMSriovVF *vf; + guint32 n_index; + GHashTableIter iter; + char *key; + GVariant *variant; + gs_unref_hashtable GHashTable *ht = NULL; + + n_index = _nm_utils_ascii_str_to_int64 (index, 10, 0, G_MAXUINT32, 0); + if (errno) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid index"); + return NULL; + } + + vf = nm_sriov_vf_new (n_index); + if (detail) { + ht = nm_utils_parse_variant_attributes (detail, ' ', '=', TRUE, _nm_sriov_vf_attribute_spec, error); + if (!ht) { + nm_sriov_vf_unref (vf); + return NULL; + } + + if ((variant = g_hash_table_lookup (ht, "vlans"))) { + if (!_nm_sriov_vf_parse_vlans (vf, g_variant_get_string (variant, NULL), error)) { + nm_sriov_vf_unref (vf); + return NULL; + } + g_hash_table_remove (ht, "vlans"); + } + + g_hash_table_iter_init (&iter, ht); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &variant)) + nm_sriov_vf_set_attribute (vf, key, g_variant_ref_sink (variant)); + } + + return vf; +} + +/*****************************************************************************/ + /** * nm_utils_uuid_generate_buf_: * @buf: input buffer, must contain at least 37 bytes @@ -2701,9 +2838,17 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g g_return_val_if_fail (uuid_type == NM_UTILS_UUID_TYPE_LEGACY || uuid_type == NM_UTILS_UUID_TYPE_VARIANT3, NULL); g_return_val_if_fail (!type_args || uuid_type == NM_UTILS_UUID_TYPE_VARIANT3, NULL); + if (slen < 0) + slen = s ? strlen (s) : 0; + switch (uuid_type) { case NM_UTILS_UUID_TYPE_LEGACY: - crypto_md5_hash (NULL, 0, s, slen, (char *) uuid, sizeof (uuid)); + nm_crypto_md5_hash (NULL, + 0, + (guint8 *) s, + slen, + (guint8 *) uuid, + sizeof (uuid)); break; case NM_UTILS_UUID_TYPE_VARIANT3: { uuid_t ns_uuid = { 0 }; @@ -2714,7 +2859,12 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g g_return_val_if_reached (NULL); } - crypto_md5_hash (s, slen, (char *) ns_uuid, sizeof (ns_uuid), (char *) uuid, sizeof (uuid)); + nm_crypto_md5_hash ((guint8 *) s, + slen, + (guint8 *) ns_uuid, + sizeof (ns_uuid), + (guint8 *) uuid, + sizeof (uuid)); uuid[6] = (uuid[6] & 0x0F) | 0x30; uuid[8] = (uuid[8] & 0x3F) | 0x80; @@ -2774,110 +2924,6 @@ _nm_utils_uuid_generate_from_strings (const char *string1, ...) /*****************************************************************************/ -/** - * nm_utils_rsa_key_encrypt: - * @data: (array length=len): RSA private key data to be encrypted - * @len: length of @data - * @in_password: (allow-none): existing password to use, if any - * @out_password: (out) (allow-none): if @in_password was %NULL, a random - * password will be generated and returned in this argument - * @error: detailed error information on return, if an error occurred - * - * Encrypts the given RSA private key data with the given password (or generates - * a password if no password was given) and converts the data to PEM format - * suitable for writing to a file. It uses Triple DES cipher for the encryption. - * - * Returns: (transfer full): on success, PEM-formatted data suitable for writing - * to a PEM-formatted certificate/private key file. - **/ -GByteArray * -nm_utils_rsa_key_encrypt (const guint8 *data, - gsize len, - const char *in_password, - char **out_password, - GError **error) -{ - char salt[16]; - int salt_len; - char *key = NULL, *enc = NULL, *pw_buf[32]; - gsize key_len = 0, enc_len = 0; - GString *pem = NULL; - char *tmp, *tmp_password = NULL; - int left; - const char *p; - GByteArray *ret = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - if (out_password) - g_return_val_if_fail (*out_password == NULL, NULL); - - /* Make the password if needed */ - if (!in_password) { - if (!crypto_randomize (pw_buf, sizeof (pw_buf), error)) - return NULL; - in_password = tmp_password = nm_utils_bin2hexstr (pw_buf, sizeof (pw_buf), -1); - } - - salt_len = 8; - if (!crypto_randomize (salt, salt_len, error)) - goto out; - - key = crypto_make_des_aes_key (CIPHER_DES_EDE3_CBC, &salt[0], salt_len, in_password, &key_len, NULL); - if (!key) - g_return_val_if_reached (NULL); - - enc = crypto_encrypt (CIPHER_DES_EDE3_CBC, data, len, salt, salt_len, key, key_len, &enc_len, error); - if (!enc) - goto out; - - pem = g_string_sized_new (enc_len * 2 + 100); - g_string_append (pem, "-----BEGIN RSA PRIVATE KEY-----\n"); - g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n"); - - /* Convert the salt to a hex string */ - tmp = nm_utils_bin2hexstr (salt, salt_len, salt_len * 2); - g_string_append_printf (pem, "DEK-Info: %s,%s\n\n", CIPHER_DES_EDE3_CBC, tmp); - g_free (tmp); - - /* Convert the encrypted key to a base64 string */ - p = tmp = g_base64_encode ((const guchar *) enc, enc_len); - left = strlen (tmp); - while (left > 0) { - g_string_append_len (pem, p, (left < 64) ? left : 64); - g_string_append_c (pem, '\n'); - left -= 64; - p += 64; - } - g_free (tmp); - - g_string_append (pem, "-----END RSA PRIVATE KEY-----\n"); - - ret = g_byte_array_sized_new (pem->len); - g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len); - if (tmp_password && out_password) - *out_password = g_strdup (tmp_password); - -out: - if (key) { - memset (key, 0, key_len); - g_free (key); - } - if (enc) { - memset (enc, 0, enc_len); - g_free (enc); - } - if (pem) - g_string_free (pem, TRUE); - - if (tmp_password) { - memset (tmp_password, 0, strlen (tmp_password)); - g_free (tmp_password); - } - - return ret; -} - static gboolean file_has_extension (const char *filename, const char *extensions[]) { @@ -2910,18 +2956,15 @@ gboolean nm_utils_file_is_certificate (const char *filename) { const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL }; - NMCryptoFileFormat file_format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; - GByteArray *cert; + NMCryptoFileFormat file_format; g_return_val_if_fail (filename != NULL, FALSE); if (!file_has_extension (filename, extensions)) return FALSE; - cert = crypto_load_and_verify_certificate (filename, &file_format, NULL); - if (cert) - g_byte_array_unref (cert); - + if (!nm_crypto_load_and_verify_certificate (filename, &file_format, NULL, NULL)) + return FALSE; return file_format = NM_CRYPTO_FILE_FORMAT_X509; } @@ -2947,7 +2990,7 @@ nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted) if (!file_has_extension (filename, extensions)) return FALSE; - return crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN; + return nm_crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN; } /** @@ -2963,7 +3006,7 @@ nm_utils_file_is_pkcs12 (const char *filename) { g_return_val_if_fail (filename != NULL, FALSE); - return crypto_is_pkcs12_file (filename, NULL); + return nm_crypto_is_pkcs12_file (filename, NULL); } /*****************************************************************************/ @@ -3483,13 +3526,13 @@ nm_utils_hwaddr_len (int type) g_return_val_if_reached (0); } -static guint8 * -_str2bin (const char *asc, - gboolean delimiter_required, - const char *delimiter_candidates, - guint8 *buffer, - gsize buffer_length, - gsize *out_len) +guint8 * +_nm_utils_str2bin_full (const char *asc, + gboolean delimiter_required, + const char *delimiter_candidates, + guint8 *buffer, + gsize buffer_length, + gsize *out_len) { const char *in = asc; guint8 *out = buffer; @@ -3559,7 +3602,7 @@ _str2bin (const char *asc, return buffer; } -#define hwaddr_aton(asc, buffer, buffer_length, out_len) _str2bin ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len)) +#define hwaddr_aton(asc, buffer, buffer_length, out_len) _nm_utils_str2bin_full ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len)) /** * nm_utils_hexstr2bin: @@ -3585,7 +3628,7 @@ nm_utils_hexstr2bin (const char *hex) buffer_length = strlen (hex) / 2 + 3; buffer = g_malloc (buffer_length); - if (!_str2bin (hex, FALSE, ":", buffer, buffer_length, &len)) { + if (!_nm_utils_str2bin_full (hex, FALSE, ":", buffer, buffer_length, &len)) { g_free (buffer); return NULL; } @@ -4290,6 +4333,8 @@ nm_utils_is_uuid (const char *str) const char *p = str; int num_dashes = 0; + g_return_val_if_fail (str, FALSE); + while (*p) { if (*p == '-') num_dashes++; @@ -4465,7 +4510,7 @@ _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin) return TRUE; } - if (_str2bin (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) { + if (_nm_utils_str2bin_full (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) { /* MAX DUID length is 128 octects + the type code (2 octects). */ if ( duid_len > 2 && duid_len <= (128 + 2)) { @@ -4886,7 +4931,7 @@ nm_utils_enum_from_str (GType type, const char *str, * * Since: 1.2 */ -const char **nm_utils_enum_get_values (GType type, gint from, gint to) +const char **nm_utils_enum_get_values (GType type, int from, int to) { return _nm_utils_enum_get_values (type, from, to); } @@ -5539,7 +5584,7 @@ _nm_utils_team_config_get (const char *conf, g_ptr_array_free (data, TRUE); } else if (json_is_array (json_element)) { - GPtrArray *data = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + GPtrArray *data = g_ptr_array_new_with_free_func (g_free); json_t *str_element; int index; @@ -6147,44 +6192,21 @@ next: return g_steal_pointer (&ht); } -/* - * nm_utils_format_variant_attributes: - * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values - * @attr_separator: the attribute separator character - * @key_value_separator: character separating key and values - * - * Format attributes to a string. - * - * Returns: (transfer full): the string representing attributes, or %NULL - * in case there are no attributes - * - * Since: 1.8 - */ -char * -nm_utils_format_variant_attributes (GHashTable *attributes, - char attr_separator, - char key_value_separator) +void +_nm_utils_format_variant_attributes_full (GString *str, + const NMUtilsNamedValue *values, + guint num_values, + char attr_separator, + char key_value_separator) { - GString *str = NULL; - GVariant *variant; - char sep = 0; const char *name, *value; + GVariant *variant; char *escaped; char buf[64]; - gs_free NMUtilsNamedValue *values = NULL; - guint i, len; - - g_return_val_if_fail (attr_separator, NULL); - g_return_val_if_fail (key_value_separator, NULL); - - if (!attributes || !g_hash_table_size (attributes)) - return NULL; - - values = nm_utils_named_values_from_str_dict (attributes, &len); - - str = g_string_new (""); + char sep = 0; + guint i; - for (i = 0; i < len; i++) { + for (i = 0; i < num_values; i++) { name = values[i].name; variant = (GVariant *) values[i].value_ptr; value = NULL; @@ -6217,7 +6239,44 @@ nm_utils_format_variant_attributes (GHashTable *attributes, sep = attr_separator; } +} + +/* + * nm_utils_format_variant_attributes: + * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values + * @attr_separator: the attribute separator character + * @key_value_separator: character separating key and values + * + * Format attributes to a string. + * + * Returns: (transfer full): the string representing attributes, or %NULL + * in case there are no attributes + * + * Since: 1.8 + */ +char * +nm_utils_format_variant_attributes (GHashTable *attributes, + char attr_separator, + char key_value_separator) +{ + GString *str = NULL; + gs_free NMUtilsNamedValue *values = NULL; + guint len; + g_return_val_if_fail (attr_separator, NULL); + g_return_val_if_fail (key_value_separator, NULL); + + if (!attributes || !g_hash_table_size (attributes)) + return NULL; + + values = nm_utils_named_values_from_str_dict (attributes, &len); + + str = g_string_new (""); + _nm_utils_format_variant_attributes_full (str, + values, + len, + attr_separator, + key_value_separator); return g_string_free (str, FALSE); } diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index 70245869..cf9572b9 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -34,8 +34,9 @@ #include <linux/if_infiniband.h> #include "nm-core-enum-types.h" -#include "nm-setting-wireless-security.h" +#include "nm-setting-sriov.h" #include "nm-setting-tc-config.h" +#include "nm-setting-wireless-security.h" G_BEGIN_DECLS @@ -213,7 +214,7 @@ NM_AVAILABLE_IN_1_2 gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token); NM_AVAILABLE_IN_1_2 -const char **nm_utils_enum_get_values (GType type, gint from, gint to); +const char **nm_utils_enum_get_values (GType type, int from, int to); NM_AVAILABLE_IN_1_6 guint nm_utils_version (void); @@ -250,9 +251,17 @@ char *nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error /*****************************************************************************/ +NM_AVAILABLE_IN_1_14 +char *nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error); +NM_AVAILABLE_IN_1_14 +NMSriovVF *nm_utils_sriov_vf_from_str (const char *str, GError **error); + +/*****************************************************************************/ + NM_AVAILABLE_IN_1_12 gint64 nm_utils_get_timestamp_msec (void); + G_END_DECLS #endif /* __NM_UTILS_H__ */ diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h index ee6dbc0b..59482d4e 100644 --- a/libnm-core/nm-version.h +++ b/libnm-core/nm-version.h @@ -160,10 +160,18 @@ # define NM_AVAILABLE_IN_1_12 #endif -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_12_2 -# define NM_AVAILABLE_IN_1_12_2 G_UNAVAILABLE(1,12,2) +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_14 +# define NM_DEPRECATED_IN_1_14 G_DEPRECATED +# define NM_DEPRECATED_IN_1_14_FOR(f) G_DEPRECATED_FOR(f) #else -# define NM_AVAILABLE_IN_1_12_2 +# define NM_DEPRECATED_IN_1_14 +# define NM_DEPRECATED_IN_1_14_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_14 +# define NM_AVAILABLE_IN_1_14 G_UNAVAILABLE(1,14) +#else +# define NM_AVAILABLE_IN_1_14 #endif #endif /* NM_VERSION_H */ diff --git a/libnm-core/tests/certs/test-aes-key.pem b/libnm-core/tests/certs/test-aes-128-key.pem index aab8f463..aab8f463 100644 --- a/libnm-core/tests/certs/test-aes-key.pem +++ b/libnm-core/tests/certs/test-aes-128-key.pem diff --git a/libnm-core/tests/certs/test-aes-256-key.pem b/libnm-core/tests/certs/test-aes-256-key.pem new file mode 100644 index 00000000..e51bafd3 --- /dev/null +++ b/libnm-core/tests/certs/test-aes-256-key.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,5FF6BD2D4E57E8933D4A6814DEF5305A + +9Br+xw6XOg7qUqfeE5PJ4g/PAm7eTcPMb4FzSKkaEosLo6oj4f37TwXuojJZeAmi +1EytpqM1vdYHCLdjg+qYaTIq6mzMZIyoaREokcOhcNrq5S0J39gJLVV9LjiXhCAH +GQgDBnbRT6HGz70AyTRLcW9aj6uBzTv/m92sLUw2txFeBXK8n2AA1oHJTgsFNYjf +/ZvTCE1VMQHDPx31Vn5WXSUHNc0hx4MTIwpHqWI17ohr8IiWCs5HXVfVaqrNeNEw +haD7fg8oNxjLs46/4dDWmfWXhDsMFSweZv03gZdyVjwn1IOqeVGmTdLpllfgOW7E ++XE8Y/d55s5nkOxu6eXNMtWgjclKBGr2iMxxnODmEsUt2WcV98cPS+25o3hOfy3s +NIcfxtWVRFUtjqf3ragyGLuXFqATkj1slj4LVMeewRJ1g+Z6ti0mwBN+ZrYtKdec +FRNb4zr5FW+3SqkIIJVfxJEYJDB4zODhMg8tySEHLKuT0uz42YQ4aoOHTzO5WDBY +2BI7TjRppXcExPnkAk5jqbKA6BjT9KcAVyypfxDKvCeXKdjDcL6ISOBSm6cQBh8D +HxsFzMy9PF6kKNeiNiEsVPnKYvhvs1hTBtp+IAgJ6KZnCDKplZFxo/mBAlV2KyCT +x+Mhmme3fXdLJkvxlVJAoAhwgXvomVCVTGI3JhcQIqVgxPIKYpqlHVFC7JjG+yQX +tvzCPtr9G9+Ofrm6zXjlDD7zNyl/KfFtEWhO2ePHkQlCEuKJnsnRIf/wQ0viG0yY +MH31Z/84o2pKLBKY5fq8+eYuYoP9Rk4W2LpjGMvdkKhEHL26kZofeFyqD+JcaxHc +kQh7/SbWAsREGb9Jp7I2q1mo749mse1oSFIQa5gN3jB0mgHZd6edRYeW2Up+rqEK +k6Xd6uqs7bZd5W9sP7Cf6yJOFEjqFVLQEVEXWSchgeta/JNrjGr3UzLFN2S+vhvX +XgDa41y2UdXHRqj2s864u0ZDPyGXYZnVbvQn/8xHQ7rvxHowpTn+XXUEf0AQnk3j +9h++3McwP8GuVxkwc6o9TfOL+ell5jup7F3SekwEiE3hqY8x87g6X2zD5VSnfCy3 +0t0LmPGI1b3LABeYjA1WEdhoTlHrNLkwOR4gsudrJ5nxIzfGy+IHaloXLJy4YKfX +pJ+qyGRUR42YD9IhiEmmmO1VoJgVEYfBiz50Jg8emddku6eKdmv9IKjiSb2pTbDS +4oUYKg109OOn+krk67dNXofAXrBa8v7QusC0yz9N25H05Xyou1iqpGk+uBrTqEO6 +lW9lWQo57BQU9og40xMKH/xQgIxfQRktUKsPizj8mKil4izo5KgjPSqBeEbj+Q3c +0FKlrpTXQlXfX5Z5esqMuCSiwQEzoJR+V+SUaSVcg1av0k/CJMin4Cr8roai+OjK +lhaQIvx35Bzd02yERYsfpDjmQCXmIeiDm8JtB6znbQPUJ4d8kzWR+5ACOZW/dUss +YhWJRkZpkIwTY+/sDU4mnP2R37MNo+OH4CwZyUDHjlkRPGW+6JBEpnnlI9a/1Vb1 +pjAGpi/8u/luvZGTzCzxQG2dZc5YQR869U+wFsFbLRiD0aP2SpdOH0QxxPOcdR8+ +HWyL01BJBKyK/wZWJhe+63zlk1L5CA0XYpoNkYpMlPNZkcqR7QzUOATfuBgI2aPM +AXaweaAWhpPCDsc2RypIs9DhTiCCkt8tq8Au15hVUKAoshLeewPtv0t75MEC0hVB +z6FVnNlqq0cqqcSVqvUG6JUGtFOGgG3ifEMXggq5k12+wGzY63DLR8dFPNpOL6/1 +nocOayHJIU9M8PP817PzhAUAePRRUKRg8kkbKKeZnCJxoF7O15AFVEJnl9Vyokkz +bULYhzYVx3xh8THMi+5jsnKWPJyMeYHbHH3C658SIw6Ff9fgEWscv5ZkGYdKMg+l +8hBn+++SoqIO+F3lOGco+s8qlYox106lUwJEtORXcBxmkaHSo/X2AVO8Owt4vYli +mjWnY6V9vooBgOuCMcY780pcoj2lSf9JPHDYK0j8t5VumDUSLyLt+tCj0yv/vl5L +9L++vbu2akZRC9ChijYpfhTvXoG36ePhoT7AGGnhpFjjw1VqG80GY4XSODKzH86w +kUcZoErb8swUPYOtsybtuPb+6c/YofQ8GfpVosPZgSRD4+U7v+zA3/z8xF2B0xt6 +uV8hXbropuni8KmbFuKrPZK3p2v2aZ8F0+GITwS75/hbT6D7ruUSr5q4V0VKeE8G +k3QSI0s6+74stPv3S/ByCxu8q51ffYqVw00wzPpEc4SmHEa0R7IczJKXupmDdZZM +1rASSBNzS5TZDBXP6S7npYQ8nHhgXTdCFO7eM3bp24B/i2o0s7+gkKrz0DkEbv9I +UrCJjTL8OIIP4qSLMILzZ8pB28c+zyM482ZqFY/2b7j6WlTiqa9P1adrD1gLxTQ0 +Sw9xY+sY3PAJqcnPA5NjDZL/h5plgHhCqDa9pEtdBVG2Mxcl9bXbphwD1MIzj4gr +xtlW1HUJ/iOhFcXldOJ1MCt++Bm5av4mL5adQ/oUnL5Q0oZZFwqT09k7xe7lZ98N +uj2Lfl8NN7N3ama9KatgbX5g6IALuk/rJN/4KEiiu24m+lR7c5L0pg/cG6LIFjmk +HlTsc0ANCgeZBhDJ8kvjcXDhFOqoYE/+D2VO6ZEHRsDibQ+kjpaH+DiD01/gh0N0 +HM6GGtm3GbOyZUhw5OFz04xzcyFYo2xaqzgaZieAOcrt2s6XyPVf1gww08/HtTMR +gLg14MUQvRXV6kPJfdu4OLZ//b6J0KnzVyLDRdOrWIj2raLWmKwQN9qv05/yskcD +Y6x7wq3v6iZpFjDc53sslhwp2XRsoWT9X5alVspz8WvP/kqgkTdzpPFdp1vIovOQ +kRXdzzKICDGDJUIcTL8cJ3Dv4XqNR/sVyuB4dfndzQQApbdYTDNpwX0VJDBjMkQy +Up6aiUknxa6Cbp7b1ZfUQY8yNBAIZL+R8dmobT3nAHW61DaASHSxn+elCD2Ja/6b +EiWikskyN6crMAv35ILr5ySsZK97ttNNmRoGFbt8bTjRd83Ie+UfH445kCKsY83x +aDCvWm+bbV6M9rSgjhJ3bWOudiw+EBMGvSamSnS7CYnRmwq4t+4bM2sh2nYKY0qw +-----END RSA PRIVATE KEY----- diff --git a/libnm-core/tests/meson.build b/libnm-core/tests/meson.build index 2eeadd88..627e6b53 100644 --- a/libnm-core/tests/meson.build +++ b/libnm-core/tests/meson.build @@ -37,8 +37,7 @@ foreach test_unit: test_units c_args: [ '-DNETWORKMANAGER_COMPILATION_TEST', '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE', - ] + - nm_build_cflags, + ], link_with: libnm_core ) test( diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index fb99ffea..6b63e6fd 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -28,7 +28,7 @@ #include <stdio.h> #include <string.h> -#include "crypto.h" +#include "nm-crypto-impl.h" #include "nm-utils.h" #include "nm-errors.h" #include "nm-core-internal.h" @@ -99,37 +99,20 @@ static void test_cert (gconstpointer test_data) { gs_free char *path = NULL; - GByteArray *array; + gs_unref_bytes GBytes *cert = NULL; NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; GError *error = NULL; + gboolean success; path = g_build_filename (TEST_CERT_DIR, (const char *) test_data, NULL); - array = crypto_load_and_verify_certificate (path, &format, &error); - g_assert_no_error (error); + success = nm_crypto_load_and_verify_certificate (path, &format, &cert, &error); + nmtst_assert_success (success, error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_X509); - g_byte_array_free (array, TRUE); - g_assert (nm_utils_file_is_certificate (path)); } -static GByteArray * -file_to_byte_array (const char *filename) -{ - char *contents; - GByteArray *array = NULL; - gsize length = 0; - - if (g_file_get_contents (filename, &contents, &length, NULL)) { - array = g_byte_array_sized_new (length); - g_byte_array_append (array, (guint8 *) contents, length); - g_assert (array->len == length); - g_free (contents); - } - return array; -} - static void test_load_private_key (const char *path, const char *password, @@ -138,13 +121,13 @@ test_load_private_key (const char *path, { NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; gboolean is_encrypted = FALSE; - GByteArray *array, *decrypted; + gs_unref_bytes GBytes *array = NULL; GError *error = NULL; g_assert (nm_utils_file_is_private_key (path, &is_encrypted)); g_assert (is_encrypted); - array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error); + array = nmtst_crypto_decrypt_openssl_private_key (path, password, &key_type, &error); /* Even if the password is wrong, we should determine the key type */ g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); @@ -164,16 +147,14 @@ test_load_private_key (const char *path, g_assert (array != NULL); if (decrypted_path) { - /* Compare the crypto decrypted key against a known-good decryption */ - decrypted = file_to_byte_array (decrypted_path); - g_assert (decrypted != NULL); - g_assert (decrypted->len == array->len); - g_assert (memcmp (decrypted->data, array->data, array->len) == 0); + gs_free char *contents = NULL; + gsize length; - g_byte_array_free (decrypted, TRUE); + /* Compare the crypto decrypted key against a known-good decryption */ + if (!g_file_get_contents (decrypted_path, &contents, &length, NULL)) + g_assert_not_reached (); + g_assert (nm_utils_gbytes_equal_mem (array, contents, length)); } - - g_byte_array_free (array, TRUE); } static void @@ -187,7 +168,7 @@ test_load_pkcs12 (const char *path, g_assert (nm_utils_file_is_private_key (path, NULL)); - format = crypto_verify_private_key (path, password, &is_encrypted, &error); + format = nm_crypto_verify_private_key (path, password, &is_encrypted, &error); if (expected_error != -1) { g_assert_error (error, NM_CRYPTO_ERROR, expected_error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); @@ -209,7 +190,7 @@ test_load_pkcs12_no_password (const char *path) g_assert (nm_utils_file_is_private_key (path, NULL)); /* We should still get a valid returned crypto file format */ - format = crypto_verify_private_key (path, NULL, &is_encrypted, &error); + format = nm_crypto_verify_private_key (path, NULL, &is_encrypted, &error); g_assert_no_error (error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12); g_assert (is_encrypted); @@ -221,7 +202,7 @@ test_is_pkcs12 (const char *path, gboolean expect_fail) gboolean is_pkcs12; GError *error = NULL; - is_pkcs12 = crypto_is_pkcs12_file (path, &error); + is_pkcs12 = nm_crypto_is_pkcs12_file (path, &error); if (expect_fail) { g_assert_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA); @@ -244,7 +225,7 @@ test_load_pkcs8 (const char *path, g_assert (nm_utils_file_is_private_key (path, NULL)); - format = crypto_verify_private_key (path, password, &is_encrypted, &error); + format = nm_crypto_verify_private_key (path, password, &is_encrypted, &error); if (expected_error != -1) { g_assert_error (error, NM_CRYPTO_ERROR, expected_error); g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN); @@ -261,34 +242,35 @@ test_encrypt_private_key (const char *path, const char *password) { NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - GByteArray *array, *encrypted, *re_decrypted; + gs_unref_bytes GBytes *array = NULL; + gs_unref_bytes GBytes *encrypted = NULL; + gs_unref_bytes GBytes *re_decrypted = NULL; GError *error = NULL; - array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error); - g_assert_no_error (error); - g_assert (array != NULL); + array = nmtst_crypto_decrypt_openssl_private_key (path, password, &key_type, &error); + nmtst_assert_success (array, error); g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); /* Now re-encrypt the private key */ - encrypted = nm_utils_rsa_key_encrypt (array->data, array->len, password, NULL, &error); - g_assert_no_error (error); - g_assert (encrypted != NULL); + encrypted = nmtst_crypto_rsa_key_encrypt (g_bytes_get_data (array, NULL), + g_bytes_get_size (array), + password, + NULL, + &error); + nmtst_assert_success (encrypted, error); /* Then re-decrypt the private key */ key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; - re_decrypted = crypto_decrypt_openssl_private_key_data (encrypted->data, encrypted->len, - password, &key_type, &error); - g_assert_no_error (error); - g_assert (re_decrypted != NULL); + re_decrypted = nmtst_crypto_decrypt_openssl_private_key_data (g_bytes_get_data (encrypted, NULL), + g_bytes_get_size (encrypted), + password, + &key_type, + &error); + nmtst_assert_success (re_decrypted, error); g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA); /* Compare the original decrypted key with the re-decrypted key */ - g_assert_cmpint (array->len, ==, re_decrypted->len); - g_assert (!memcmp (array->data, re_decrypted->data, array->len)); - - g_byte_array_free (re_decrypted, TRUE); - g_byte_array_free (encrypted, TRUE); - g_byte_array_free (array, TRUE); + g_assert (g_bytes_equal (array, re_decrypted)); } static void @@ -417,15 +399,16 @@ test_md5 (void) for (i = 0; i < G_N_ELEMENTS (md5_tests); i++) { memset (digest, 0, sizeof (digest)); - crypto_md5_hash (md5_tests[i].salt, - /* crypto_md5_hash() used to clamp salt_len to 8. It - * doesn't any more, so we need to do it here now to - * get output that matches md5_tests[i].result. - */ - md5_tests[i].salt ? 8 : 0, - md5_tests[i].password, - strlen (md5_tests[i].password), - digest, md5_tests[i].digest_size); + nm_crypto_md5_hash ((const guint8 *) md5_tests[i].salt, + /* nm_crypto_md5_hash() used to clamp salt_len to 8. It + * doesn't any more, so we need to do it here now to + * get output that matches md5_tests[i].result. + */ + md5_tests[i].salt ? 8 : 0, + (const guint8 *) md5_tests[i].password, + strlen (md5_tests[i].password), + (guint8 *) digest, + md5_tests[i].digest_size); hex = nm_utils_bin2hexstr (digest, md5_tests[i].digest_size, -1); g_assert_cmpstr (hex, ==, md5_tests[i].result); @@ -444,7 +427,7 @@ main (int argc, char **argv) nmtst_init (&argc, &argv, TRUE); - success = crypto_init (&error); + success = _nm_crypto_init (&error); g_assert_no_error (error); g_assert (success); @@ -476,8 +459,11 @@ main (int argc, char **argv) g_test_add_data_func ("/libnm/crypto/key/padding-8", "test2_key_and_cert.pem, 12345testing", test_key); - g_test_add_data_func ("/libnm/crypto/key/aes", - "test-aes-key.pem, test-aes-password", + g_test_add_data_func ("/libnm/crypto/key/aes-128", + "test-aes-128-key.pem, test-aes-password", + test_key); + g_test_add_data_func ("/libnm/crypto/key/aes-256", + "test-aes-256-key.pem, test-aes-password", test_key); g_test_add_data_func ("/libnm/crypto/key/decrypted", "test-key-only-decrypted.pem", diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 3b9debd9..38531248 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2008 - 2011 Red Hat, Inc. + * Copyright 2008 - 2018 Red Hat, Inc. * */ @@ -43,6 +43,7 @@ #include "nm-setting-bridge-port.h" #include "nm-setting-cdma.h" #include "nm-setting-connection.h" +#include "nm-setting-ethtool.h" #include "nm-setting-generic.h" #include "nm-setting-gsm.h" #include "nm-setting-infiniband.h" @@ -61,9 +62,11 @@ #include "nm-setting-wired.h" #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" +#include "nm-setting-wpan.h" #include "nm-simple-connection.h" #include "nm-keyfile-internal.h" #include "nm-utils/nm-dedup-multi.h" +#include "nm-ethtool-utils.h" #include "test-general-enums.h" @@ -222,8 +225,8 @@ test_nm_g_slice_free_fcn (void) p = g_slice_new (gint32); (nm_g_slice_free_fcn (gint32)) (p); - p = g_slice_new (gint); - (nm_g_slice_free_fcn (gint)) (p); + p = g_slice_new (int); + (nm_g_slice_free_fcn (int)) (p); p = g_slice_new (gint64); nm_g_slice_free_fcn_gint64 (p); @@ -235,7 +238,7 @@ test_nm_g_slice_free_fcn (void) /*****************************************************************************/ static void -_do_test_nm_utils_strsplit_set (const char *str, ...) +_do_test_nm_utils_strsplit_set (gboolean escape, const char *str, ...) { gs_unref_ptrarray GPtrArray *args_array = g_ptr_array_new (); const char *const*args; @@ -252,7 +255,7 @@ _do_test_nm_utils_strsplit_set (const char *str, ...) args = (const char *const*) args_array->pdata; - words = nm_utils_strsplit_set (str, " \t\n"); + words = nm_utils_strsplit_set (str, " \t\n", escape); if (!args[0]) { g_assert (!words); @@ -265,7 +268,7 @@ _do_test_nm_utils_strsplit_set (const char *str, ...) g_assert (args[i]); g_assert (words[i]); g_assert (args[i][0]); - g_assert (NM_STRCHAR_ALL (args[i], ch, !NM_IN_SET (ch, ' ', '\t', '\n'))); + g_assert (escape || NM_STRCHAR_ALL (args[i], ch, !NM_IN_SET (ch, ' ', '\t', '\n'))); g_assert_cmpstr (args[i], ==, words[i]); } } @@ -276,21 +279,29 @@ _do_test_nm_utils_strsplit_set (const char *str, ...) static void test_nm_utils_strsplit_set (void) { - do_test_nm_utils_strsplit_set (NULL); - do_test_nm_utils_strsplit_set (""); - do_test_nm_utils_strsplit_set ("\t"); - do_test_nm_utils_strsplit_set (" \t\n"); - do_test_nm_utils_strsplit_set ("a", "a"); - do_test_nm_utils_strsplit_set ("a b", "a", "b"); - do_test_nm_utils_strsplit_set ("a\rb", "a\rb"); - do_test_nm_utils_strsplit_set (" a\rb ", "a\rb"); - do_test_nm_utils_strsplit_set (" a bbbd afds ere", "a", "bbbd", "afds", "ere"); - do_test_nm_utils_strsplit_set ("1 2 3 4 5 6 7 8 9 0 " + do_test_nm_utils_strsplit_set (FALSE, NULL); + do_test_nm_utils_strsplit_set (FALSE, ""); + do_test_nm_utils_strsplit_set (FALSE, "\t"); + do_test_nm_utils_strsplit_set (FALSE, " \t\n"); + do_test_nm_utils_strsplit_set (FALSE, "a", "a"); + do_test_nm_utils_strsplit_set (FALSE, "a b", "a", "b"); + do_test_nm_utils_strsplit_set (FALSE, "a\rb", "a\rb"); + do_test_nm_utils_strsplit_set (FALSE, " a\rb ", "a\rb"); + do_test_nm_utils_strsplit_set (FALSE, " a bbbd afds ere", "a", "bbbd", "afds", "ere"); + do_test_nm_utils_strsplit_set (FALSE, + "1 2 3 4 5 6 7 8 9 0 " "1 2 3 4 5 6 7 8 9 0 " "1 2 3 4 5 6 7 8 9 0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"); + do_test_nm_utils_strsplit_set (TRUE, "\\", "\\"); + do_test_nm_utils_strsplit_set (TRUE, "\\ ", "\\ "); + do_test_nm_utils_strsplit_set (TRUE, "\\\\", "\\\\"); + do_test_nm_utils_strsplit_set (TRUE, "\\\t", "\\\t"); + do_test_nm_utils_strsplit_set (TRUE, "foo\\", "foo\\"); + do_test_nm_utils_strsplit_set (TRUE, "bar foo\\", "bar", "foo\\"); + do_test_nm_utils_strsplit_set (TRUE, "\\ a b\\ \\ c", "\\ a", "b\\ \\ ", "c"); } /*****************************************************************************/ @@ -2594,6 +2605,7 @@ test_connection_diff_a_only (void) { NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_CONNECTION_MULTI_CONNECT, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_READ_ONLY, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_ZONE, NM_SETTING_DIFF_RESULT_IN_A }, @@ -2606,6 +2618,7 @@ test_connection_diff_a_only (void) { NM_SETTING_CONNECTION_LLDP, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_MDNS, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_CONNECTION_LLMNR, NM_SETTING_DIFF_RESULT_IN_A }, { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN } } }, { NM_SETTING_WIRED_SETTING_NAME, { @@ -5328,18 +5341,17 @@ test_hexstr2bin (void) { "aab:ccc:ddd" }, { "aab::ccc:ddd" }, }; - GBytes *b; guint i; for (i = 0; i < G_N_ELEMENTS (items); i++) { + gs_unref_bytes GBytes *b = NULL; + b = nm_utils_hexstr2bin (items[i].str); - if (items[i].expected_len) { + if (items[i].expected_len) g_assert (b); - g_assert_cmpint (g_bytes_get_size (b), ==, items[i].expected_len); - g_assert (memcmp (g_bytes_get_data (b, NULL), items[i].expected, g_bytes_get_size (b)) == 0); - g_bytes_unref (b); - } else - g_assert (b == NULL); + else + g_assert (!b); + g_assert (nm_utils_gbytes_equal_mem (b, items[i].expected, items[i].expected_len)); } } @@ -6033,7 +6045,7 @@ static void test_nm_utils_is_power_of_two (void) { guint64 xyes, xno; - gint i, j; + int i, j; GRand *rand = nmtst_get_rand (); int numbits; @@ -6124,7 +6136,7 @@ _test_find_binary_search_do (const int *array, gsize len) expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle); - idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last); + idx = nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last); if (expected_result >= 0) { g_assert_cmpint (expected_result, ==, idx); } else { @@ -6186,12 +6198,12 @@ _test_find_binary_search_do_uint32 (const int *int_array, gsize len) expected_result = idx; } - idx = _nm_utils_array_find_binary_search (array, - sizeof (guint32), - len, - &NEEDLE, - nm_cmp_uint32_p_with_data, - NULL); + idx = nm_utils_array_find_binary_search (array, + sizeof (guint32), + len, + &NEEDLE, + nm_cmp_uint32_p_with_data, + NULL); if (expected_result >= 0) g_assert_cmpint (expected_result, ==, idx); else { @@ -6291,11 +6303,11 @@ test_nm_utils_ptrarray_find_binary_search_with_duplicates (void) for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) { gconstpointer p = GINT_TO_POINTER (i); - idx = _nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last); + idx = nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last); idx_first2 = _nm_utils_ptrarray_find_first (arr, i_len, p); - idx2 = _nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL); + idx2 = nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL); g_assert_cmpint (idx, ==, idx2); if (idx_first2 < 0) { @@ -6547,74 +6559,161 @@ test_nm_utils_enum (void) /*****************************************************************************/ static void -do_test_utils_str_utf8safe (const char *str, const char *expected, NMUtilsStrUtf8SafeFlags flags) +_do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsize expected_len) { - const char *str_safe, *s; - gs_free char *str2 = NULL; - gs_free char *str3 = NULL; + gsize l; + const char *s; + gs_free gpointer buf_free_1 = NULL; + gs_free char *str_free_1 = NULL; - str_safe = nm_utils_str_utf8safe_escape (str, flags, &str2); + s = nm_utils_buf_utf8safe_unescape (str, &l, &buf_free_1); + g_assert_cmpint (expected_len, ==, l); + g_assert_cmpstr (s, ==, expected); - str3 = nm_utils_str_utf8safe_escape_cp (str, flags); - g_assert_cmpstr (str3, ==, str_safe); - g_assert ((!str && !str3) || (str != str3)); - g_clear_pointer (&str3, g_free); + if (str == NULL) { + g_assert (!s); + g_assert (!buf_free_1); + g_assert_cmpint (l, ==, 0); + } else { + g_assert (s); + if (!strchr (str, '\\')) { + g_assert (!buf_free_1); + g_assert (s == str); + g_assert_cmpint (l, ==, strlen (str)); + } else { + g_assert (buf_free_1); + g_assert (s == buf_free_1); + g_assert (memcmp (s, expected, expected_len) == 0); + } + } + + if ( expected + && l == strlen (expected)) { + /* there are no embeeded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */ + s = nm_utils_str_utf8safe_unescape (str, &str_free_1); + g_assert_cmpstr (s, ==, expected); + if (strchr (str, '\\')) { + g_assert (str_free_1 != str); + g_assert (s == str_free_1); + } else + g_assert (s == str); + } +} + +#define do_test_utils_str_utf8safe_unescape(str, expected) \ + _do_test_utils_str_utf8safe_unescape (""str"", expected, NM_STRLEN (expected)) + +static void +_do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expected, NMUtilsStrUtf8SafeFlags flags) +{ + const char *str_safe; + const char *buf_safe; + const char *s; + gs_free gpointer buf_free_1 = NULL; + gs_free char *str_free_1 = NULL; + gs_free char *str_free_2 = NULL; + gs_free char *str_free_3 = NULL; + gs_free char *str_free_4 = NULL; + gs_free char *str_free_5 = NULL; + gs_free char *str_free_6 = NULL; + gs_free char *str_free_7 = NULL; + gs_free char *str_free_8 = NULL; + gboolean str_has_nul = FALSE; + + buf_safe = nm_utils_buf_utf8safe_escape (str, str_len, flags, &str_free_1); + + str_safe = nm_utils_str_utf8safe_escape (str, flags, &str_free_2); + + if (str_len == 0) { + g_assert (buf_safe == NULL); + g_assert (str_free_1 == NULL); + g_assert (str_safe == str); + g_assert (str == NULL || str[0] == '\0'); + g_assert (str_free_2 == NULL); + } else if (str_len == strlen (str)) { + g_assert (buf_safe); + g_assert_cmpstr (buf_safe, ==, str_safe); + + /* nm_utils_buf_utf8safe_escape() can only return a pointer equal to the input string, + * if and only if str_len is negative. Otherwise, the input str won't be NUL terminated + * and cannot be returned. */ + g_assert (buf_safe != str); + g_assert (buf_safe == str_free_1); + } else + str_has_nul = TRUE; + + str_free_3 = nm_utils_str_utf8safe_escape_cp (str, flags); + g_assert_cmpstr (str_free_3, ==, str_safe); + g_assert ((!str && !str_free_3) || (str != str_free_3)); + + if (str_len > 0) + _do_test_utils_str_utf8safe_unescape (buf_safe, str, str_len); if (expected == NULL) { + g_assert (!str_has_nul); + g_assert (str_safe == str); - g_assert (!str2); + g_assert (!str_free_2); if (str) { g_assert (!strchr (str, '\\')); g_assert (g_utf8_validate (str, -1, NULL)); } - g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str3)); - g_assert (!str3); + g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str_free_4)); + g_assert (!str_free_4); - str3 = nm_utils_str_utf8safe_unescape_cp (str_safe); + str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe); if (str) { - g_assert (str3 != str); - g_assert_cmpstr (str3, ==, str); + g_assert (str_free_5 != str); + g_assert_cmpstr (str_free_5, ==, str); } else - g_assert (!str3); - g_clear_pointer (&str3, g_free); + g_assert (!str_free_5); return; } - g_assert (str); - g_assert (str_safe != str); - g_assert (str_safe == str2); - g_assert ( strchr (str, '\\') - || !g_utf8_validate (str, -1, NULL) - || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) - && NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127)) - || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) - && NM_STRCHAR_ANY (str, ch, (guchar) ch < ' '))); - g_assert (g_utf8_validate (str_safe, -1, NULL)); + if (!str_has_nul) { + g_assert (str); + g_assert (str_safe != str); + g_assert (str_safe == str_free_2); + g_assert ( strchr (str, '\\') + || !g_utf8_validate (str, -1, NULL) + || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) + && NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127)) + || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) + && NM_STRCHAR_ANY (str, ch, (guchar) ch < ' '))); + g_assert (g_utf8_validate (str_safe, -1, NULL)); - str3 = g_strcompress (str_safe); - g_assert_cmpstr (str, ==, str3); - g_clear_pointer (&str3, g_free); + str_free_6 = g_strcompress (str_safe); + g_assert_cmpstr (str, ==, str_free_6); - str3 = nm_utils_str_utf8safe_unescape_cp (str_safe); - g_assert (str3 != str); - g_assert_cmpstr (str3, ==, str); - g_clear_pointer (&str3, g_free); + str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe); + g_assert (str_free_7 != str); + g_assert_cmpstr (str_free_7, ==, str); - s = nm_utils_str_utf8safe_unescape (str_safe, &str3); - g_assert (str3 != str); - g_assert (s == str3); - g_assert_cmpstr (str3, ==, str); - g_clear_pointer (&str3, g_free); + s = nm_utils_str_utf8safe_unescape (str_safe, &str_free_8); + g_assert (str_free_8 != str); + g_assert (s == str_free_8); + g_assert_cmpstr (str_free_8, ==, str); + + g_assert_cmpstr (str_safe, ==, expected); + + return; + } + + g_assert_cmpstr (buf_safe, ==, expected); - g_assert_cmpstr (str_safe, ==, expected); } +#define do_test_utils_str_utf8safe(str, expected, flags) \ + _do_test_utils_str_utf8safe (""str"", NM_STRLEN (str), expected, flags) static void test_utils_str_utf8safe (void) { - do_test_utils_str_utf8safe (NULL, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + _do_test_utils_str_utf8safe (NULL, 0, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("\\", "\\\\", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("\\a", "\\\\a", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); do_test_utils_str_utf8safe ("\314", "\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); do_test_utils_str_utf8safe ("\314\315x\315\315x", "\\314\\315x\\315\\315x", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); do_test_utils_str_utf8safe ("\314\315xx", "\\314\\315xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); @@ -6636,6 +6735,18 @@ test_utils_str_utf8safe (void) do_test_utils_str_utf8safe ("㈞abä㈞b", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); do_test_utils_str_utf8safe ("abäb", "ab\\303\\244b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII); do_test_utils_str_utf8safe ("ab\ab", "ab\\007b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL); + + do_test_utils_str_utf8safe ("\0", "\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("\0a\0", "\\000a\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("\\\0", "\\\\\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("\n\0", "\n\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); + do_test_utils_str_utf8safe ("\n\0", "\\012\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL); + + do_test_utils_str_utf8safe_unescape ("\n\\0", "\n\0"); + do_test_utils_str_utf8safe_unescape ("\n\\01", "\n\01"); + do_test_utils_str_utf8safe_unescape ("\n\\012", "\n\012"); + do_test_utils_str_utf8safe_unescape ("\n\\.", "\n."); + do_test_utils_str_utf8safe_unescape ("\\n\\.3\\r", "\n.3\r"); } /*****************************************************************************/ @@ -6951,7 +7062,7 @@ test_route_attributes_format (void) /*****************************************************************************/ static gboolean -do_test_nm_set_out_called (gint *call_count) +do_test_nm_set_out_called (int *call_count) { (*call_count)++; return TRUE; @@ -7005,6 +7116,120 @@ test_get_start_time_for_pid (void) /*****************************************************************************/ +static void +test_nm_va_args_macros (void) +{ +#define GET_NARG_1(...) \ + NM_NARG (__VA_ARGS__) + + g_assert_cmpint ( 0, ==, GET_NARG_1 ()); + g_assert_cmpint ( 1, ==, GET_NARG_1 (x)); + g_assert_cmpint ( 2, ==, GET_NARG_1 ( , )); + g_assert_cmpint ( 2, ==, GET_NARG_1 ( , x)); + g_assert_cmpint ( 2, ==, GET_NARG_1 (x, )); + g_assert_cmpint ( 2, ==, GET_NARG_1 (x, x)); + g_assert_cmpint ( 3, ==, GET_NARG_1 ( , , )); + g_assert_cmpint ( 3, ==, GET_NARG_1 ( , , x)); + g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, )); + g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, x)); + g_assert_cmpint ( 3, ==, GET_NARG_1 (x, , )); + g_assert_cmpint ( 3, ==, GET_NARG_1 (x, , x)); + g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, )); + g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , , )); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , , x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , x, )); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , x, x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, , )); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, , x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, )); + g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , , )); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , , x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , x, )); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , x, x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, , )); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, , x)); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, )); + g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, x)); + + g_assert_cmpint ( 5, ==, GET_NARG_1 (x, x, x, x, x)); + g_assert_cmpint ( 6, ==, GET_NARG_1 (x, x, x, x, x, x)); + g_assert_cmpint ( 7, ==, GET_NARG_1 (x, x, x, x, x, x, x)); + g_assert_cmpint ( 8, ==, GET_NARG_1 (x, x, x, x, x, x, x, x)); + g_assert_cmpint ( 9, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x)); + g_assert_cmpint (10, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x, x)); + + G_STATIC_ASSERT_EXPR (0 == GET_NARG_1 ()); + G_STATIC_ASSERT_EXPR (1 == GET_NARG_1 (x)); + G_STATIC_ASSERT_EXPR (2 == GET_NARG_1 (x, x)); +} + +/*****************************************************************************/ + +static void +test_ethtool_offload (void) +{ + const NMEthtoolData *d; + + g_assert_cmpint (nm_ethtool_id_get_by_name ("invalid"), ==, NM_ETHTOOL_ID_UNKNOWN); + g_assert_cmpint (nm_ethtool_id_get_by_name ("feature-rx"), ==, NM_ETHTOOL_ID_FEATURE_RX); + + d = nm_ethtool_data_get_by_optname (NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); + g_assert (d); + g_assert_cmpint (d->id, ==, NM_ETHTOOL_ID_FEATURE_RXHASH); + g_assert_cmpstr (d->optname, ==, NM_ETHTOOL_OPTNAME_FEATURE_RXHASH); +} + +static void +test_nm_utils_escape_spaces (void) +{ + char *to_free; + + g_assert_cmpstr (_nm_utils_escape_spaces (NULL, &to_free), ==, NULL); + g_free (to_free); + + g_assert_cmpstr (_nm_utils_escape_spaces ("", &to_free), ==, ""); + g_free (to_free); + + g_assert_cmpstr (_nm_utils_escape_spaces (" ", &to_free), ==, "\\ "); + g_free (to_free); + + g_assert_cmpstr (_nm_utils_escape_spaces ("\t ", &to_free), ==, "\\\t\\ "); + g_free (to_free); + + g_assert_cmpstr (_nm_utils_escape_spaces ("abc", &to_free), ==, "abc"); + g_free (to_free); + + g_assert_cmpstr (_nm_utils_escape_spaces ("abc def", &to_free), ==, "abc\\ def"); + g_free (to_free); + + g_assert_cmpstr (_nm_utils_escape_spaces ("abc\tdef", &to_free), ==, "abc\\\tdef"); + g_free (to_free); +} + +static void +test_nm_utils_unescape_spaces (void) +{ +#define CHECK_STR(in, out) \ + G_STMT_START { \ + gs_free char *str = g_strdup (in); \ + \ + g_assert_cmpstr (_nm_utils_unescape_spaces (str), ==, out); \ + } G_STMT_END + + CHECK_STR ("\\a", "\\a"); + CHECK_STR ("foobar", "foobar"); + CHECK_STR ("foo bar", "foo bar"); + CHECK_STR ("foo\\ bar", "foo bar"); + CHECK_STR ("foo\\", "foo\\"); + CHECK_STR ("\\\\\t", "\\\t"); + +#undef CHECK_STR +} + +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) @@ -7144,8 +7369,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two); - g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); - g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); + g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); + g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len); @@ -7153,12 +7378,16 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx); g_test_add_func ("/core/general/_nm_utils_validate_json", test_nm_utils_check_valid_json); g_test_add_func ("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal); + g_test_add_func ("/core/general/_nm_utils_escape_spaces", test_nm_utils_escape_spaces); + g_test_add_func ("/core/general/_nm_utils_unescape_spaces", test_nm_utils_unescape_spaces); g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum); g_test_add_func ("/core/general/nm-set-out", test_nm_set_out); g_test_add_func ("/core/general/route_attributes/parse", test_route_attributes_parse); g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format); g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid); + g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros); + g_test_add_func ("/core/general/test_ethtool_offload", test_ethtool_offload); return g_test_run (); } diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c index 672c72b6..d941fa22 100644 --- a/libnm-core/tests/test-keyfile.c +++ b/libnm-core/tests/test-keyfile.c @@ -127,10 +127,8 @@ _assert_gbytes (GBytes *bytes, gconstpointer data, gssize len) if (!len) g_assert (!bytes); - else { - g_assert_cmpint (g_bytes_get_size (bytes), ==, len); - g_assert (memcmp (g_bytes_get_data (bytes, NULL), data, len) == 0); - } + + g_assert (nm_utils_gbytes_equal_mem (bytes, data, len)); } static GKeyFile * @@ -277,8 +275,9 @@ _keyfile_convert (NMConnection **con, b1 = nm_setting_802_1x_get_ca_cert_blob (s1); b2 = nm_setting_802_1x_get_ca_cert_blob (s2); - g_assert_cmpint (g_bytes_get_size (b1), ==, g_bytes_get_size (b2)); - g_assert (memcmp (g_bytes_get_data (b1, NULL), g_bytes_get_data (b2, NULL), g_bytes_get_size (b1)) == 0); + g_assert (b1); + g_assert (b2); + g_assert (g_bytes_equal (b1, b2)); break; } default: @@ -344,8 +343,7 @@ _test_8021x_cert_check (NMConnection *con, } g_assert (blob); - g_assert_cmpint (g_bytes_get_size (blob), ==, val_len); - g_assert (!memcmp (g_bytes_get_data (blob, NULL), value, val_len)); + g_assert (nm_utils_gbytes_equal_mem (blob, value, val_len)); kval = g_key_file_get_string (keyfile, "802-1x", "ca-cert", NULL); g_assert (kval); diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index e71d6b7c..c8eda381 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -23,9 +23,12 @@ #include <string.h> #include "nm-utils.h" +#include "nm-utils-private.h" +#include "nm-core-internal.h" #include "nm-setting-8021x.h" #include "nm-setting-bond.h" #include "nm-setting-dcb.h" +#include "nm-setting-ethtool.h" #include "nm-setting-team.h" #include "nm-setting-team-port.h" #include "nm-setting-tc-config.h" @@ -34,6 +37,7 @@ #include "nm-simple-connection.h" #include "nm-setting-connection.h" #include "nm-errors.h" +#include "nm-keyfile-internal.h" #include "nm-utils/nm-test-utils.h" @@ -46,7 +50,7 @@ compare_blob_data (const char *test, const char *key_path, GBytes *key) { - char *contents = NULL; + gs_free char *contents = NULL; gsize len = 0; GError *error = NULL; gboolean success; @@ -57,18 +61,18 @@ compare_blob_data (const char *test, nmtst_assert_success (success, error); g_assert_cmpmem (contents, len, g_bytes_get_data (key, NULL), g_bytes_get_size (key)); - - g_free (contents); } static void check_scheme_path (GBytes *value, const char *path) { const guint8 *p; + gsize l; g_assert (value); - p = g_bytes_get_data (value, NULL); + p = g_bytes_get_data (value, &l); + g_assert_cmpint (l, ==, strlen (path) + NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1); g_assert (memcmp (p, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0); p += strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); g_assert (memcmp (p, path, strlen (path)) == 0); @@ -998,7 +1002,7 @@ test_runner_loadbalance_sync_from_config (void) { gs_unref_ptrarray GPtrArray *tx_hash = NULL; - tx_hash = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + tx_hash = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (tx_hash, g_strdup ("eth")); g_ptr_array_add (tx_hash, g_strdup ("ipv4")); g_ptr_array_add (tx_hash, g_strdup ("ipv6")); @@ -1035,7 +1039,7 @@ test_runner_lacp_sync_from_config (void) { gs_unref_ptrarray GPtrArray *tx_hash = NULL; - tx_hash = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + tx_hash = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (tx_hash, g_strdup ("eth")); g_ptr_array_add (tx_hash, g_strdup ("ipv4")); g_ptr_array_add (tx_hash, g_strdup ("ipv6")); @@ -1263,6 +1267,307 @@ test_team_port_full_config (void) /*****************************************************************************/ static void +test_ethtool_1 (void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *con3 = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + gs_unref_keyfile GKeyFile *keyfile = NULL; + NMSettingConnection *s_con; + NMSettingEthtool *s_ethtool; + NMSettingEthtool *s_ethtool2; + NMSettingEthtool *s_ethtool3; + + con = nmtst_create_minimal_connection ("ethtool-1", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + &s_con); + s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ethtool)); + + nm_setting_ethtool_set_feature (s_ethtool, + NM_ETHTOOL_OPTNAME_FEATURE_RX, + NM_TERNARY_TRUE); + nm_setting_ethtool_set_feature (s_ethtool, + NM_ETHTOOL_OPTNAME_FEATURE_LRO, + NM_TERNARY_FALSE); + + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT); + + nmtst_connection_normalize (con); + + variant = nm_connection_to_dbus (con, NM_CONNECTION_SERIALIZE_ALL); + + con2 = nm_simple_connection_new_from_dbus (variant, &error); + nmtst_assert_success (con2, error); + + s_ethtool2 = NM_SETTING_ETHTOOL (nm_connection_get_setting (con2, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT); + + nmtst_assert_connection_verifies_without_normalization (con2); + + nmtst_assert_connection_equals (con, FALSE, con2, FALSE); + + keyfile = nm_keyfile_write (con, NULL, NULL, &error); + nmtst_assert_success (keyfile, error); + + con3 = nm_keyfile_read (keyfile, + "ethtool-keyfile-name", + NULL, + NULL, + NULL, + &error); + nmtst_assert_success (con3, error); + + nmtst_connection_normalize (con3); + + nmtst_assert_connection_equals (con, FALSE, con3, FALSE); + + s_ethtool3 = NM_SETTING_ETHTOOL (nm_connection_get_setting (con3, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT); +} + +/*****************************************************************************/ + +static void +test_sriov_vf (void) +{ + NMSriovVF *vf1, *vf2; + GError *error = NULL; + char *str; + + vf1 = nm_sriov_vf_new (1); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("00:11:22:33:44:55")); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (TRUE)); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE)); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32 (100)); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32 (500)); + + str = nm_utils_sriov_vf_to_str (vf1, FALSE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, "1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100 spoof-check=true trust=false"); + g_free (str); + + vf2 = nm_utils_sriov_vf_from_str (" 1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100", &error); + nmtst_assert_success (vf2, error); + nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (FALSE)); + nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (TRUE)); + nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (TRUE)); + nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, NULL); + nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE)); + + g_assert (nm_sriov_vf_equal (vf1, vf2)); + + nm_sriov_vf_unref (vf1); + nm_sriov_vf_unref (vf2); +} + +static void +test_sriov_vf_dup (void) +{ + NMSriovVF *vf1, *vf2; + + vf1 = nm_sriov_vf_new (1); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("foobar")); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE)); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32 (10)); + nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32 (1000)); + nm_sriov_vf_add_vlan (vf1, 80); + nm_sriov_vf_set_vlan_qos (vf1, 80, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + vf2 = nm_sriov_vf_dup (vf1); + g_assert (nm_sriov_vf_equal (vf1, vf2)); + + nm_sriov_vf_unref (vf1); + nm_sriov_vf_unref (vf2); +} + +static void +test_sriov_vf_vlan (void) +{ + NMSriovVF *vf; + const guint *vlan_ids; + guint num; + GError *error = NULL; + gs_free char *str = NULL; + + vf = nm_sriov_vf_new (19); + nm_sriov_vf_set_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("00:11:22")); + g_assert (nm_sriov_vf_add_vlan (vf, 80)); + g_assert (!nm_sriov_vf_add_vlan (vf, 80)); + g_assert (nm_sriov_vf_add_vlan (vf, 82)); + g_assert (nm_sriov_vf_add_vlan (vf, 83)); + g_assert (nm_sriov_vf_add_vlan (vf, 81)); + g_assert (!nm_sriov_vf_remove_vlan (vf, 100)); + g_assert (nm_sriov_vf_remove_vlan (vf, 82)); + nm_sriov_vf_set_vlan_qos (vf, 81, 0xabba); + nm_sriov_vf_set_vlan_protocol (vf, 81, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num); + g_assert (vlan_ids); + g_assert_cmpint (num, ==, 3); + g_assert_cmpint (vlan_ids[0], ==, 80); + g_assert_cmpint (vlan_ids[1], ==, 81); + g_assert_cmpint (vlan_ids[2], ==, 83); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 80), ==, 0x0); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 80), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 81), ==, 0xabba); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + nm_sriov_vf_unref (vf); + + vf = nm_utils_sriov_vf_from_str ("20 spoof-check=false vlans=85.0.q;4000.0x20.ad;81.10;83", &error); + nmtst_assert_success (vf, error); + vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num); + g_assert (vlan_ids); + g_assert_cmpint (num, ==, 4); + g_assert_cmpint (vlan_ids[0], ==, 81); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 81), ==, 10); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint (vlan_ids[1], ==, 83); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 83), ==, 0); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 83), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint (vlan_ids[2], ==, 85); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 85), ==, 0); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 85), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + g_assert_cmpint (vlan_ids[3], ==, 4000); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 4000), ==, 0x20); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 4000), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD); + + str = nm_utils_sriov_vf_to_str (vf, FALSE, &error); + nmtst_assert_success (str, error); + g_assert_cmpstr (str, ==, "20 spoof-check=false vlans=81.10;83;85;4000.32.ad"); + + nm_sriov_vf_unref (vf); +} + +static void +test_sriov_setting (void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingConnection *s_con; + NMSettingSriov *s_sriov = NULL; + NMSriovVF *vf1, *vf2, *vf3; + GError *error = NULL; + gboolean success; + + con = nm_simple_connection_new (); + + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (con, NM_SETTING (s_con)); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test SR-IOV connection", + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (), + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0", + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + + nm_connection_add_setting (con, nm_setting_wired_new ()); + + s_sriov = (NMSettingSriov *) nm_setting_sriov_new (); + nm_connection_add_setting (con, NM_SETTING (s_sriov)); + + g_object_set (s_sriov, NM_SETTING_SRIOV_TOTAL_VFS, 16, NULL); + nm_setting_sriov_add_vf (s_sriov, (vf1 = nm_sriov_vf_new (0))); + nm_setting_sriov_add_vf (s_sriov, (vf2 = nm_sriov_vf_new (4))); + nm_setting_sriov_add_vf (s_sriov, (vf3 = nm_sriov_vf_new (10))); + g_assert (nm_setting_sriov_remove_vf_by_index (s_sriov, 4)); + nm_sriov_vf_unref (vf2); + nm_setting_sriov_add_vf (s_sriov, (vf2 = nm_sriov_vf_new (2))); + + nmtst_assert_connection_verifies_and_normalizable (con); + nmtst_connection_normalize (con); + success = nm_setting_verify ((NMSetting *) s_sriov, con, &error); + nmtst_assert_success (success, error); + + g_assert_cmpint (nm_setting_sriov_get_num_vfs (s_sriov), ==, 3); + g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 0)), ==, 0); + g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 1)), ==, 2); + g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 2)), ==, 10); + + nm_sriov_vf_unref (vf1); + nm_sriov_vf_unref (vf2); + nm_sriov_vf_unref (vf3); +} + +typedef struct { + guint id; + guint qos; + bool proto_ad; +} VlanData; + +static void +_test_sriov_parse_vlan_one (const char *string, gboolean exp_res, VlanData *data, guint data_length) +{ + NMSriovVF *vf; + gboolean res; + guint i, num_vlans; + const guint *vlan_ids; + + vf = nm_sriov_vf_new (1); + g_assert (vf); + + res = _nm_sriov_vf_parse_vlans (vf, string, NULL); + g_assert_cmpint (res, ==, exp_res); + + if (exp_res) { + vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans); + g_assert_cmpint (num_vlans, ==, data_length); + for (i = 0; i < num_vlans; i++) { + g_assert_cmpint (vlan_ids[i], ==, data[i].id); + g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]), ==, data[i].qos); + g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]), + ==, + data[i].proto_ad ? NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q); + } + } + + nm_sriov_vf_unref (vf); +} + +#define test_sriov_parse_vlan_one(string, result, ...) \ + { \ + VlanData _data[] = { __VA_ARGS__ }; \ + guint _length = G_N_ELEMENTS (_data); \ + \ + _test_sriov_parse_vlan_one (string, result, _data, _length); \ + } + +static void +test_sriov_parse_vlans (void) +{ + test_sriov_parse_vlan_one ("", FALSE, {}); + test_sriov_parse_vlan_one ("1", TRUE, {1, 0, 0}); + test_sriov_parse_vlan_one ("1;2", TRUE, {1, 0, 0}, {2, 0, 0}); + test_sriov_parse_vlan_one ("4095;;2", TRUE, {2, 0, 0}, {4095, 0, 0}); + test_sriov_parse_vlan_one ("1 2", FALSE, {}); + test_sriov_parse_vlan_one ("4096", FALSE, {}); + test_sriov_parse_vlan_one ("1.10", TRUE, {1, 10, 0}); + test_sriov_parse_vlan_one ("1.20.ad", TRUE, {1, 20, 1}); + test_sriov_parse_vlan_one ("1.21.q", TRUE, {1, 21, 0}); + test_sriov_parse_vlan_one ("9.20.foo", FALSE, {}); + test_sriov_parse_vlan_one ("1.20.ad.12", FALSE, {}); + test_sriov_parse_vlan_one ("1;1.10", FALSE, {}); + test_sriov_parse_vlan_one ("1..1;2", FALSE, {}); + test_sriov_parse_vlan_one ("1..ad;2", FALSE, {}); + test_sriov_parse_vlan_one ("1.2.ad;2.0.q;5;3", TRUE, {1, 2, 1}, {2, 0, 0}, {3, 0, 0}, {5, 0, 0}); +} + +/*****************************************************************************/ + +static void test_tc_config_qdisc (void) { NMTCQdisc *qdisc1, *qdisc2; @@ -1669,6 +1974,14 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/dcb/priorities", test_dcb_priorities_valid); g_test_add_func ("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums); + g_test_add_func ("/libnm/settings/ethtool/1", test_ethtool_1); + + g_test_add_func ("/libnm/settings/sriov/vf", test_sriov_vf); + g_test_add_func ("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup); + g_test_add_func ("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan); + g_test_add_func ("/libnm/settings/sriov/setting", test_sriov_setting); + g_test_add_func ("/libnm/settings/sriov/vlans", test_sriov_parse_vlans); + g_test_add_func ("/libnm/settings/tc_config/qdisc", test_tc_config_qdisc); g_test_add_func ("/libnm/settings/tc_config/action", test_tc_config_action); g_test_add_func ("/libnm/settings/tc_config/tfilter", test_tc_config_tfilter); |